re PR tree-optimization/91178 (Infinite recursion in split_constant_offset in slp...
authorRichard Biener <rguenther@suse.de>
Wed, 17 Jul 2019 11:21:49 +0000 (11:21 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 17 Jul 2019 11:21:49 +0000 (11:21 +0000)
2019-07-17  Richard Biener  <rguenther@suse.de>

PR tree-optimization/91178
* tree-ssa.c (release_defs_bitset): Iterate from higher to
lower SSA names to avoid quadratic behavior in the common case.
* tree-data-ref.c (split_constant_offset): Add limit argument
and pass it down.  Initialize it from PARAM_SSA_NAME_DEF_CHAIN_LIMIT.
(split_constant_offset_1): Add limit argument and use it to
limit SSA def walking.  Optimize the common plus/minus case.

From-SVN: r273550

gcc/ChangeLog
gcc/tree-data-ref.c
gcc/tree-ssa.c

index b15db2d089e83a89dcb1d2f3fdb2366a1305fdd3..f13d8a6a9a4016a27a46f90cf843e9265f6c2ac9 100644 (file)
@@ -1,3 +1,13 @@
+2019-07-17  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/91178
+       * tree-ssa.c (release_defs_bitset): Iterate from higher to
+       lower SSA names to avoid quadratic behavior in the common case.
+       * tree-data-ref.c (split_constant_offset): Add limit argument
+       and pass it down.  Initialize it from PARAM_SSA_NAME_DEF_CHAIN_LIMIT.
+       (split_constant_offset_1): Add limit argument and use it to
+       limit SSA def walking.  Optimize the common plus/minus case.
+
 2019-07-17  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/91178
index df1a7b8016ea1d8888d785ff202dda33ead9e657..7f75b7e3afeebd33fda493d942ff7f7160102d39 100644 (file)
@@ -583,7 +583,8 @@ debug_ddrs (vec<ddr_p> ddrs)
 
 static void
 split_constant_offset (tree exp, tree *var, tree *off,
-                      hash_map<tree, std::pair<tree, tree> > &cache);
+                      hash_map<tree, std::pair<tree, tree> > &cache,
+                      unsigned *limit);
 
 /* Helper function for split_constant_offset.  Expresses OP0 CODE OP1
    (the type of the result is TYPE) as VAR + OFF, where OFF is a nonzero
@@ -594,7 +595,8 @@ split_constant_offset (tree exp, tree *var, tree *off,
 static bool
 split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
                         tree *var, tree *off,
-                        hash_map<tree, std::pair<tree, tree> > &cache)
+                        hash_map<tree, std::pair<tree, tree> > &cache,
+                        unsigned *limit)
 {
   tree var0, var1;
   tree off0, off1;
@@ -615,8 +617,15 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
       /* FALLTHROUGH */
     case PLUS_EXPR:
     case MINUS_EXPR:
-      split_constant_offset (op0, &var0, &off0, cache);
-      split_constant_offset (op1, &var1, &off1, cache);
+      if (TREE_CODE (op1) == INTEGER_CST)
+       {
+         split_constant_offset (op0, &var0, &off0, cache, limit);
+         *var = var0;
+         *off = size_binop (ocode, off0, fold_convert (ssizetype, op1));
+         return true;
+       }
+      split_constant_offset (op0, &var0, &off0, cache, limit);
+      split_constant_offset (op1, &var1, &off1, cache, limit);
       *var = fold_build2 (code, type, var0, var1);
       *off = size_binop (ocode, off0, off1);
       return true;
@@ -625,7 +634,7 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
       if (TREE_CODE (op1) != INTEGER_CST)
        return false;
 
-      split_constant_offset (op0, &var0, &off0, cache);
+      split_constant_offset (op0, &var0, &off0, cache, limit);
       *var = fold_build2 (MULT_EXPR, type, var0, op1);
       *off = size_binop (MULT_EXPR, off0, fold_convert (ssizetype, op1));
       return true;
@@ -649,7 +658,7 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
 
        if (poffset)
          {
-           split_constant_offset (poffset, &poffset, &off1, cache);
+           split_constant_offset (poffset, &poffset, &off1, cache, limit);
            off0 = size_binop (PLUS_EXPR, off0, off1);
            if (POINTER_TYPE_P (TREE_TYPE (base)))
              base = fold_build_pointer_plus (base, poffset);
@@ -719,11 +728,15 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
            e = std::make_pair (op0, ssize_int (0));
          }
 
+       if (*limit == 0)
+         return false;
+       --*limit;
+
        var0 = gimple_assign_rhs1 (def_stmt);
        var1 = gimple_assign_rhs2 (def_stmt);
 
        bool res = split_constant_offset_1 (type, var0, subcode, var1,
-                                           var, off, cache);
+                                           var, off, cache, limit);
        if (res && use_cache)
          *cache.get (op0) = std::make_pair (*var, *off);
        return res;
@@ -746,7 +759,7 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
                /* Split the unconverted operand and try to prove that
                   wrapping isn't a problem.  */
                tree tmp_var, tmp_off;
-               split_constant_offset (op0, &tmp_var, &tmp_off, cache);
+               split_constant_offset (op0, &tmp_var, &tmp_off, cache, limit);
 
                /* See whether we have an SSA_NAME whose range is known
                   to be [A, B].  */
@@ -781,7 +794,7 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
                *off = wide_int_to_tree (ssizetype, diff);
              }
            else
-             split_constant_offset (op0, &var0, off, cache);
+             split_constant_offset (op0, &var0, off, cache, limit);
            *var = fold_convert (type, var0);
            return true;
          }
@@ -798,7 +811,8 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
 
 static void
 split_constant_offset (tree exp, tree *var, tree *off,
-                      hash_map<tree, std::pair<tree, tree> > &cache)
+                      hash_map<tree, std::pair<tree, tree> > &cache,
+                      unsigned *limit)
 {
   tree type = TREE_TYPE (exp), op0, op1, e, o;
   enum tree_code code;
@@ -812,7 +826,7 @@ split_constant_offset (tree exp, tree *var, tree *off,
 
   code = TREE_CODE (exp);
   extract_ops_from_tree (exp, &code, &op0, &op1);
-  if (split_constant_offset_1 (type, op0, code, op1, &e, &o, cache))
+  if (split_constant_offset_1 (type, op0, code, op1, &e, &o, cache, limit))
     {
       *var = e;
       *off = o;
@@ -822,10 +836,11 @@ split_constant_offset (tree exp, tree *var, tree *off,
 void
 split_constant_offset (tree exp, tree *var, tree *off)
 {
+  unsigned limit = PARAM_VALUE (PARAM_SSA_NAME_DEF_CHAIN_LIMIT);
   static hash_map<tree, std::pair<tree, tree> > *cache;
   if (!cache)
     cache = new hash_map<tree, std::pair<tree, tree> > (37);
-  split_constant_offset (exp, var, off, *cache);
+  split_constant_offset (exp, var, off, *cache, &limit);
   cache->empty ();
 }
 
index 16eaa8e326c6d324ab76d82fb8af3936b1873da1..b4b5c903e13b1695daeff66a680c64fa7da0829d 100644 (file)
@@ -559,20 +559,25 @@ release_defs_bitset (bitmap toremove)
 
   /* Performing a topological sort is probably overkill, this will
      most likely run in slightly superlinear time, rather than the
-     pathological quadratic worst case.  */
+     pathological quadratic worst case.
+     But iterate from max SSA name version to min one because
+     that mimics allocation order during code generation behavior best.
+     Use an array for this which we compact on-the-fly with a NULL
+     marker moving towards the end of the vector.  */
+  auto_vec<tree, 16> names;
+  names.reserve (bitmap_count_bits (toremove) + 1);
+  names.quick_push (NULL_TREE);
+  EXECUTE_IF_SET_IN_BITMAP (toremove, 0, j, bi)
+    names.quick_push (ssa_name (j));
+
+  bitmap_tree_view (toremove);
   while (!bitmap_empty_p (toremove))
     {
-      unsigned to_remove_bit = -1U;
-      EXECUTE_IF_SET_IN_BITMAP (toremove, 0, j, bi)
+      j = names.length () - 1;
+      for (unsigned i = names.length () - 1; names[i];)
        {
-         if (to_remove_bit != -1U)
-           {
-             bitmap_clear_bit (toremove, to_remove_bit);
-             to_remove_bit = -1U;
-           }
-
          bool remove_now = true;
-         tree var = ssa_name (j);
+         tree var = names[i];
          gimple *stmt;
          imm_use_iterator uit;
 
@@ -617,14 +622,15 @@ release_defs_bitset (bitmap toremove)
                  gsi_remove (&gsi, true);
                  release_defs (def);
                }
-
-             to_remove_bit = j;
+             bitmap_clear_bit (toremove, SSA_NAME_VERSION (var));
            }
+         else
+           --i;
+         if (--j != i)
+           names[i] = names[j];
        }
-      if (to_remove_bit != -1U)
-       bitmap_clear_bit (toremove, to_remove_bit);
     }
-
+  bitmap_list_view (toremove);
 }
 
 /* Disable warnings about missing quoting in GCC diagnostics for