]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: [multiple changes]
authorRichard Biener <rguenther@suse.de>
Fri, 2 Aug 2019 08:40:34 +0000 (08:40 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 2 Aug 2019 08:40:34 +0000 (08:40 +0000)
2019-08-02  Richard Biener  <rguenther@suse.de>

Backport from mainline
2019-07-31  Richard Biener  <rguenther@suse.de>

PR tree-optimization/91178
* tree-ssa-sccvn.c (vn_reference_maybe_forwprop_address):
Use tail-recursion.

* gcc.dg/torture/pr91178-2.c: New testcase.

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.

* gcc.dg/torture/pr91178.c: New testcase.

2019-07-12  Martin Sebor  <msebor@redhat.com>

* doc/invoke.texi (ssa-name-def-chain-limit): Document new --param.
* params.def (PARAM_SSA_NAME_DEF_CHAIN_LIMIT): Add new --param.
* tree-vrp.c (vrp_prop::check_mem_ref): Use
PARAM_SSA_NAME_DEF_CHAIN_LIMIT.

* gcc.dg/Warray-bounds-43.c: New test.

From-SVN: r274000

gcc/ChangeLog
gcc/doc/invoke.texi
gcc/params.def
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Warray-bounds-43.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr91178-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr91178.c [new file with mode: 0644]
gcc/tree-data-ref.c
gcc/tree-ssa-sccvn.c
gcc/tree-ssa.c
gcc/tree-vrp.c

index 9934b26f7aa6bcdda12dd5e4a3252e83cfe7ce0a..57c1025f6e34cb6fe74f97874e3a74a5b97bdac0 100644 (file)
@@ -1,3 +1,29 @@
+2019-08-02  Richard Biener  <rguenther@suse.de>
+
+       Backport from mainline
+       2019-07-31  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/91178
+       * tree-ssa-sccvn.c (vn_reference_maybe_forwprop_address):
+       Use tail-recursion.
+
+       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-12  Martin Sebor  <msebor@redhat.com>
+
+       * doc/invoke.texi (ssa-name-def-chain-limit): Document new --param.
+       * params.def (PARAM_SSA_NAME_DEF_CHAIN_LIMIT): Add new --param.
+       * tree-vrp.c (vrp_prop::check_mem_ref): Use
+       PARAM_SSA_NAME_DEF_CHAIN_LIMIT.
+
 2019-08-01  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
index 29585cf15aacbec0ccded93c59cb76e20483bbab..6ef36ce02aaa2a78ec02cd4826bd44c053b42f02 100644 (file)
@@ -12157,6 +12157,13 @@ before the loop versioning pass considers it too big to copy,
 discounting any instructions in inner loops that directly benefit
 from versioning.
 
+@item ssa-name-def-chain-limit
+The maximum number of SSA_NAME assignments to follow in determining
+a property of a variable such as its value.  This limits the number
+of iterations or recursive calls GCC performs when optimizing certain
+statements or when determining their validity prior to issuing
+diagnostics.
+
 @end table
 @end table
 
index 3c9c5fc0f13d4f22b188e3ff801e817aaf1cba97..813dc55d94c61a788d244bb12290f7309964fbc7 100644 (file)
@@ -1414,6 +1414,12 @@ DEFPARAM(PARAM_LOOP_VERSIONING_MAX_OUTER_INSNS,
         " loops.",
         100, 0, 0)
 
+DEFPARAM(PARAM_SSA_NAME_DEF_CHAIN_LIMIT,
+        "ssa-name-def-chain-limit",
+        "The maximum number of SSA_NAME assignments to follow in determining "
+        "a value.",
+        512, 0, 0)
+
 /*
 
 Local variables:
index b7d14cd03deced66cd118180295c343c670238a7..337b50e194c0ede7bcb4ef4c0c9849467c2d6f1a 100644 (file)
@@ -1,3 +1,20 @@
+2019-08-02  Richard Biener  <rguenther@suse.de>
+
+       Backport from mainline
+       2019-07-31  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/91178
+       * gcc.dg/torture/pr91178-2.c: New testcase.
+
+       2019-07-17  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/91178
+       * gcc.dg/torture/pr91178.c: New testcase.
+
+       2019-07-12  Martin Sebor  <msebor@redhat.com>
+
+       * gcc.dg/Warray-bounds-43.c: New test.
+
 2019-08-01  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-43.c b/gcc/testsuite/gcc.dg/Warray-bounds-43.c
new file mode 100644 (file)
index 0000000..8892921
--- /dev/null
@@ -0,0 +1,133 @@
+/* Test to verify that --param ssa_name_def_chain_limit can be used to
+   limit the maximum number of SSA_NAME assignments the warning follows.
+   { dg-do compile }
+   { dg-options "-O2 -Wall --param ssa-name-def-chain-limit=4" }  */
+
+#define NOIPA __attribute__ ((noipa))
+
+const char a0[] = "";
+const char a1[] = "1";
+const char a2[] = "12";
+const char a3[] = "123";
+const char a4[] = "1234";
+const char a5[] = "12345";
+const char a6[] = "123456";
+const char a7[] = "1234567";
+const char a8[] = "12345678";
+const char a9[] = "123456789";
+
+void f (const char*, ...);
+
+int i0, i1, i2, i3, i4, i5, i6, i7, i8;
+
+NOIPA int g2 (int i)
+{
+  if (i < 1) i = 1;
+
+  const char *p0 = a9;
+  const char *p1 = p0 + i;
+  const char *p2 = p1 + i;
+
+  f (p0, p1, p2);
+
+  return p2[8];     // { dg-warning "\\\[-Warray-bounds]" }
+}
+
+NOIPA int g3 (int i)
+{
+  if (i < 1) i = 1;
+
+  const char *p0 = a9;
+  const char *p1 = p0 + i;
+  const char *p2 = p1 + i;
+  const char *p3 = p2 + i;
+
+  f (p0, p1, p2, p3);
+
+  return p3[7];     // { dg-warning "\\\[-Warray-bounds]" }
+}
+
+NOIPA int g4 (int i)
+{
+  if (i < 1) i = 1;
+
+  const char *p0 = a9;
+  const char *p1 = p0 + i;
+  const char *p2 = p1 + i;
+  const char *p3 = p2 + i;
+  const char *p4 = p3 + i;
+
+  f (p0, p1, p2, p3, p4);
+
+  return p4[6];     // { dg-warning "\\\[-Warray-bounds]" }
+}
+
+NOIPA int g5 (int i)
+{
+  if (i < 1) i = 1;
+
+  const char *p0 = a9;
+  const char *p1 = p0 + i;
+  const char *p2 = p1 + i;
+  const char *p3 = p2 + i;
+  const char *p4 = p3 + i;
+  const char *p5 = p4 + i;
+
+  f (p0, p1, p2, p3, p4, p5);
+
+  return p5[5];
+}
+
+NOIPA int g6 (int i)
+{
+  if (i < 1) i = 1;
+
+  const char *p0 = a9;
+  const char *p1 = p0 + i;
+  const char *p2 = p1 + i;
+  const char *p3 = p2 + i;
+  const char *p4 = p3 + i;
+  const char *p5 = p4 + i;
+  const char *p6 = p5 + i;
+
+  f (p0, p1, p2, p3, p4, p5, p6);
+
+  return p6[4];
+}
+
+NOIPA int g7 (int i)
+{
+  if (i < 1) i = 1;
+
+  const char *p0 = a9;
+  const char *p1 = p0 + i;
+  const char *p2 = p1 + i;
+  const char *p3 = p2 + i;
+  const char *p4 = p3 + i;
+  const char *p5 = p4 + i;
+  const char *p6 = p5 + i;
+  const char *p7 = p6 + i;
+
+  f (p0, p1, p2, p3, p4, p5, p6, p7);
+
+  return p7[3];
+}
+
+NOIPA int g8 (int i)
+{
+  if (i < 1) i = 1;
+
+  const char *p0 = a9;
+  const char *p1 = p0 + i;
+  const char *p2 = p1 + i;
+  const char *p3 = p2 + i;
+  const char *p4 = p3 + i;
+  const char *p5 = p4 + i;
+  const char *p6 = p5 + i;
+  const char *p7 = p6 + i;
+  const char *p8 = p7 + i;
+
+  f (p0, p1, p2, p3, p4, p5, p6, p7, p8);
+
+  return p8[2];
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr91178-2.c b/gcc/testsuite/gcc.dg/torture/pr91178-2.c
new file mode 100644 (file)
index 0000000..0ebb470
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+int a[100][70304];
+int b[100];
+void c()
+{
+  for (int d = 2; d < 4; d++)
+    for (int e = 2; e <= 50; e++)
+      for (int f = 32; f <= 38; f++)
+       b[d + f] -= a[e][5];
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr91178.c b/gcc/testsuite/gcc.dg/torture/pr91178.c
new file mode 100644 (file)
index 0000000..b7a2dbe
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+int a;
+extern int f[10][91125];
+int b[50];
+void c()
+{
+  for (int d = 6; d <= a; d++)
+    for (int e = 16; e <= 24; e++)
+      b[e] -= f[d][d];
+}
index ad0a00720d1d0f93c8a56ce1c15503db05026f43..d00c1bd31e64ed72fde8bf4fa4cdf7663809dd11 100644 (file)
@@ -584,7 +584,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
@@ -595,7 +596,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;
@@ -616,8 +618,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;
@@ -626,7 +635,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;
@@ -650,7 +659,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);
@@ -720,11 +729,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;
@@ -747,7 +760,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].  */
@@ -782,7 +795,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;
          }
@@ -799,7 +812,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;
@@ -813,7 +827,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;
@@ -823,10 +837,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 8bc2a9da6c820d4ccfa7cd44cdeb6fbe67c8d1a6..9529d1669c96059fa435941b84f55f833a1d6aa4 100644 (file)
@@ -1267,113 +1267,123 @@ static bool
 vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops,
                                     unsigned int *i_p)
 {
-  unsigned int i = *i_p;
-  vn_reference_op_t op = &(*ops)[i];
-  vn_reference_op_t mem_op = &(*ops)[i - 1];
-  gimple *def_stmt;
-  enum tree_code code;
-  poly_offset_int off;
-
-  def_stmt = SSA_NAME_DEF_STMT (op->op0);
-  if (!is_gimple_assign (def_stmt))
-    return false;
-
-  code = gimple_assign_rhs_code (def_stmt);
-  if (code != ADDR_EXPR
-      && code != POINTER_PLUS_EXPR)
-    return false;
-
-  off = poly_offset_int::from (wi::to_poly_wide (mem_op->op0), SIGNED);
+  bool changed = false;
+  vn_reference_op_t op;
 
-  /* The only thing we have to do is from &OBJ.foo.bar add the offset
-     from .foo.bar to the preceding MEM_REF offset and replace the
-     address with &OBJ.  */
-  if (code == ADDR_EXPR)
+  do
     {
-      tree addr, addr_base;
-      poly_int64 addr_offset;
-
-      addr = gimple_assign_rhs1 (def_stmt);
-      addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0),
-                                                &addr_offset);
-      /* If that didn't work because the address isn't invariant propagate
-         the reference tree from the address operation in case the current
-        dereference isn't offsetted.  */
-      if (!addr_base
-         && *i_p == ops->length () - 1
-         && known_eq (off, 0)
-         /* This makes us disable this transform for PRE where the
-            reference ops might be also used for code insertion which
-            is invalid.  */
-         && default_vn_walk_kind == VN_WALKREWRITE)
+      unsigned int i = *i_p;
+      op = &(*ops)[i];
+      vn_reference_op_t mem_op = &(*ops)[i - 1];
+      gimple *def_stmt;
+      enum tree_code code;
+      poly_offset_int off;
+
+      def_stmt = SSA_NAME_DEF_STMT (op->op0);
+      if (!is_gimple_assign (def_stmt))
+       return changed;
+
+      code = gimple_assign_rhs_code (def_stmt);
+      if (code != ADDR_EXPR
+         && code != POINTER_PLUS_EXPR)
+       return changed;
+
+      off = poly_offset_int::from (wi::to_poly_wide (mem_op->op0), SIGNED);
+
+      /* The only thing we have to do is from &OBJ.foo.bar add the offset
+        from .foo.bar to the preceding MEM_REF offset and replace the
+        address with &OBJ.  */
+      if (code == ADDR_EXPR)
        {
-         auto_vec<vn_reference_op_s, 32> tem;
-         copy_reference_ops_from_ref (TREE_OPERAND (addr, 0), &tem);
-         /* Make sure to preserve TBAA info.  The only objects not
-            wrapped in MEM_REFs that can have their address taken are
-            STRING_CSTs.  */
-         if (tem.length () >= 2
-             && tem[tem.length () - 2].opcode == MEM_REF)
+         tree addr, addr_base;
+         poly_int64 addr_offset;
+
+         addr = gimple_assign_rhs1 (def_stmt);
+         addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0),
+                                                    &addr_offset);
+         /* If that didn't work because the address isn't invariant propagate
+            the reference tree from the address operation in case the current
+            dereference isn't offsetted.  */
+         if (!addr_base
+             && *i_p == ops->length () - 1
+             && known_eq (off, 0)
+             /* This makes us disable this transform for PRE where the
+                reference ops might be also used for code insertion which
+                is invalid.  */
+             && default_vn_walk_kind == VN_WALKREWRITE)
            {
-             vn_reference_op_t new_mem_op = &tem[tem.length () - 2];
-             new_mem_op->op0
-               = wide_int_to_tree (TREE_TYPE (mem_op->op0),
-                                   wi::to_poly_wide (new_mem_op->op0));
+             auto_vec<vn_reference_op_s, 32> tem;
+             copy_reference_ops_from_ref (TREE_OPERAND (addr, 0), &tem);
+             /* Make sure to preserve TBAA info.  The only objects not
+                wrapped in MEM_REFs that can have their address taken are
+                STRING_CSTs.  */
+             if (tem.length () >= 2
+                 && tem[tem.length () - 2].opcode == MEM_REF)
+               {
+                 vn_reference_op_t new_mem_op = &tem[tem.length () - 2];
+                 new_mem_op->op0
+                     = wide_int_to_tree (TREE_TYPE (mem_op->op0),
+                                         wi::to_poly_wide (new_mem_op->op0));
+               }
+             else
+               gcc_assert (tem.last ().opcode == STRING_CST);
+             ops->pop ();
+             ops->pop ();
+             ops->safe_splice (tem);
+             --*i_p;
+             return true;
            }
-         else
-           gcc_assert (tem.last ().opcode == STRING_CST);
-         ops->pop ();
-         ops->pop ();
-         ops->safe_splice (tem);
-         --*i_p;
-         return true;
+         if (!addr_base
+             || TREE_CODE (addr_base) != MEM_REF
+             || (TREE_CODE (TREE_OPERAND (addr_base, 0)) == SSA_NAME
+                 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (addr_base,
+                                                                   0))))
+           return changed;
+
+         off += addr_offset;
+         off += mem_ref_offset (addr_base);
+         op->op0 = TREE_OPERAND (addr_base, 0);
+       }
+      else
+       {
+         tree ptr, ptroff;
+         ptr = gimple_assign_rhs1 (def_stmt);
+         ptroff = gimple_assign_rhs2 (def_stmt);
+         if (TREE_CODE (ptr) != SSA_NAME
+             || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr)
+             /* Make sure to not endlessly recurse.
+                See gcc.dg/tree-ssa/20040408-1.c for an example.  Can easily
+                happen when we value-number a PHI to its backedge value.  */
+             || SSA_VAL (ptr) == op->op0
+             || !poly_int_tree_p (ptroff))
+           return changed;
+
+         off += wi::to_poly_offset (ptroff);
+         op->op0 = ptr;
        }
-      if (!addr_base
-         || TREE_CODE (addr_base) != MEM_REF
-         || (TREE_CODE (TREE_OPERAND (addr_base, 0)) == SSA_NAME
-             && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (addr_base, 0))))
-       return false;
-
-      off += addr_offset;
-      off += mem_ref_offset (addr_base);
-      op->op0 = TREE_OPERAND (addr_base, 0);
-    }
-  else
-    {
-      tree ptr, ptroff;
-      ptr = gimple_assign_rhs1 (def_stmt);
-      ptroff = gimple_assign_rhs2 (def_stmt);
-      if (TREE_CODE (ptr) != SSA_NAME
-         || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr)
-         /* Make sure to not endlessly recurse.
-            See gcc.dg/tree-ssa/20040408-1.c for an example.  Can easily
-            happen when we value-number a PHI to its backedge value.  */
-         || SSA_VAL (ptr) == op->op0
-         || !poly_int_tree_p (ptroff))
-       return false;
 
-      off += wi::to_poly_offset (ptroff);
-      op->op0 = ptr;
+      mem_op->op0 = wide_int_to_tree (TREE_TYPE (mem_op->op0), off);
+      if (tree_fits_shwi_p (mem_op->op0))
+       mem_op->off = tree_to_shwi (mem_op->op0);
+      else
+       mem_op->off = -1;
+      /* ???  Can end up with endless recursion here!?
+        gcc.c-torture/execute/strcmp-1.c  */
+      if (TREE_CODE (op->op0) == SSA_NAME)
+       op->op0 = SSA_VAL (op->op0);
+      if (TREE_CODE (op->op0) != SSA_NAME)
+       op->opcode = TREE_CODE (op->op0);
+
+      changed = true;
     }
+  /* Tail-recurse.  */
+  while (TREE_CODE (op->op0) == SSA_NAME);
 
-  mem_op->op0 = wide_int_to_tree (TREE_TYPE (mem_op->op0), off);
-  if (tree_fits_shwi_p (mem_op->op0))
-    mem_op->off = tree_to_shwi (mem_op->op0);
-  else
-    mem_op->off = -1;
-  /* ???  Can end up with endless recursion here!?
-     gcc.c-torture/execute/strcmp-1.c  */
-  if (TREE_CODE (op->op0) == SSA_NAME)
-    op->op0 = SSA_VAL (op->op0);
-  if (TREE_CODE (op->op0) != SSA_NAME)
-    op->opcode = TREE_CODE (op->op0);
-
-  /* And recurse.  */
-  if (TREE_CODE (op->op0) == SSA_NAME)
-    vn_reference_maybe_forwprop_address (ops, i_p);
-  else if (TREE_CODE (op->op0) == ADDR_EXPR)
+  /* Fold a remaining *&.  */
+  if (TREE_CODE (op->op0) == ADDR_EXPR)
     vn_reference_fold_indirect (ops, i_p);
-  return true;
+
+  return changed;
 }
 
 /* Optimize the reference REF to a constant if possible or return
index cf366982eef6dddec53f49ada76effd8a810fe63..bdb6d6b0a706b0f54d0ad9f55a1cbaaae8eec6e4 100644 (file)
@@ -554,20 +554,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;
 
@@ -612,14 +617,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);
 }
 
 /* Verify virtual SSA form.  */
index 0a172719e5dfbaf8e5e5bfda5a059b8e96b05e54..795d7184a65f9afb6782ce1ba7ab26be6ece732a 100644 (file)
@@ -4549,7 +4549,8 @@ vrp_prop::check_mem_ref (location_t location, tree ref,
      The loop computes the range of the final offset for expressions such
      as (A + i0 + ... + iN)[CSTOFF] where i0 through iN are SSA_NAMEs in
      some range.  */
-  while (TREE_CODE (arg) == SSA_NAME)
+  const unsigned limit = PARAM_VALUE (PARAM_SSA_NAME_DEF_CHAIN_LIMIT);
+  for (unsigned n = 0; TREE_CODE (arg) == SSA_NAME && n < limit; ++n)
     {
       gimple *def = SSA_NAME_DEF_STMT (arg);
       if (!is_gimple_assign (def))