]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Introduce a param-switch-limit for EVRP.
authorAndrew MacLeod <amacleod@redhat.com>
Wed, 29 Sep 2021 21:25:50 +0000 (17:25 -0400)
committerAndrew MacLeod <amacleod@redhat.com>
Wed, 6 Oct 2021 13:18:09 +0000 (09:18 -0400)
Very large switches cause a lot of range calculations with multiple subranges
to happen.  This can cause quadratic or even exponetial time increases in
large testcases.  This patch introduces a param variable to limit
the size of switches EVRP will process.

* gimple-range-edge.cc (gimple_outgoing_range::gimple_outgoing_range):
Add parameter to limit size when recognizing switches.
(gimple_outgoing_range::edge_range_p): Check size limit.
* gimple-range-edge.h (gimple_outgoing_range): Add size field.
* gimple-range-gori.cc (gori_map::calculate_gori): Ignore switches
that exceed the size limit.
(gori_compute::gori_compute): Add initializer.
* params.opt (evrp-switch-limit): New.
* doc/invoke.texi: Update docs.

gcc/doc/invoke.texi
gcc/gimple-range-edge.cc
gcc/gimple-range-edge.h
gcc/gimple-range-gori.cc
gcc/params.opt

index b4eaa7793b7f0411c803390670b7b23bd03051ca..80bc7fe41e053fa6229c15dbde65a7e053e4e136 100644 (file)
@@ -14505,6 +14505,9 @@ Maximum number of basic blocks before EVRP uses a sparse cache.
 @item evrp-mode
 Specifies the mode Early VRP should operate in.
 
+@item evrp-switch-limit
+Specifies the maximum number of switch cases before EVRP ignores a switch.
+
 @item unroll-jam-min-percent
 The minimum percentage of memory references that must be optimized
 away for the unroll-and-jam transformation to be considered profitable.
index d11153e677e74d088667e52a1830f62fbfd7daa3..afffc8dbcae1c494571dfb746b6884b24078cb67 100644 (file)
@@ -65,9 +65,10 @@ gcond_edge_range (irange &r, edge e)
 }
 
 
-gimple_outgoing_range::gimple_outgoing_range ()
+gimple_outgoing_range::gimple_outgoing_range (int max_sw_edges)
 {
   m_edge_table = NULL;
+  m_max_edges = max_sw_edges;
 }
 
 
@@ -192,6 +193,10 @@ gimple_outgoing_range::edge_range_p (irange &r, edge e)
       return s;
     }
 
+  // Only process switches if it within the size limit.
+  if (EDGE_COUNT (e->src->succs) > (unsigned)m_max_edges)
+    return NULL;
+
   gcc_checking_assert (is_a<gswitch *> (s));
   gswitch *sw = as_a<gswitch *> (s);
   tree type = TREE_TYPE (gimple_switch_index (sw));
index 87b4124d01de0f34b6f847942c44614ed89df840..03e8e82bd038d64f92ed088a08f3798e8adcf1d8 100644 (file)
@@ -38,13 +38,14 @@ along with GCC; see the file COPYING3.  If not see
 class gimple_outgoing_range
 {
 public:
-  gimple_outgoing_range ();
+  gimple_outgoing_range (int max_sw_edges = INT_MAX);
   ~gimple_outgoing_range ();
   gimple *edge_range_p (irange &r, edge e);
 private:
   void calc_switch_ranges (gswitch *sw);
   bool get_edge_range (irange &r, gimple *s, edge e);
 
+  int m_max_edges;
   hash_map<edge, irange *> *m_edge_table;
   irange_allocator m_range_allocator;
 };
index 4a1ade7f921b1039022e0b7625c2314f5040f0db..6946fa65dda4e19c7fb204fcaac878338048b289 100644 (file)
@@ -565,6 +565,9 @@ gori_map::calculate_gori (basic_block bb)
     }
   else
     {
+      // Do not process switches if they are too large.
+      if (EDGE_COUNT (bb->succs) > (unsigned)param_evrp_switch_limit)
+       return;
       gswitch *gs = as_a<gswitch *>(stmt);
       name = gimple_range_ssa_p (gimple_switch_index (gs));
       maybe_add_gori (name, gimple_bb (stmt));
@@ -634,7 +637,8 @@ debug (gori_map &g)
 
 // Construct a gori_compute object.
 
-gori_compute::gori_compute (int not_executable_flag) : tracer ("GORI ")
+gori_compute::gori_compute (int not_executable_flag)
+                     : outgoing (param_evrp_switch_limit), tracer ("GORI ")
 {
   m_not_executable_flag = not_executable_flag;
   // Create a boolean_type true and false range.
index 658ca0288519e5f8185da67535dc42517c24d21c..82ddbb8b1211608fde98d335cf0c660c37e0b6a3 100644 (file)
@@ -130,6 +130,10 @@ Maximal estimated growth of function body caused by early inlining of single cal
 Common Joined UInteger Var(param_evrp_sparse_threshold) Init(800) Optimization Param
 Maximum number of basic blocks before EVRP uses a sparse cache.
 
+-param=evrp-switch-limit=
+Common Joined UInteger Var(param_evrp_switch_limit) Init(50) Optimization Param
+Maximum number of outgoing edges in a switch before EVRP will not process it.
+
 -param=evrp-mode=
 Common Joined Var(param_evrp_mode) Enum(evrp_mode) Init(EVRP_MODE_RVRP_ONLY) Param Optimization
 --param=evrp-mode=[legacy|ranger|legacy-first|ranger-first|trace|gori|cache|tracegori|debug] Specifies the mode Early VRP should operate in.