]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/47365 (wrong code with -O -ftree-pre)
authorRichard Guenther <rguenther@suse.de>
Fri, 21 Jan 2011 14:05:00 +0000 (14:05 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 21 Jan 2011 14:05:00 +0000 (14:05 +0000)
2011-01-21  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/47365
* tree-ssa-sccvn.h (vn_lookup_kind): Declare.
(vn_reference_lookup_pieces): Adjust.
(vn_reference_lookup): Likewise.
* tree-ssa-sccvn.c (vn_walk_kind): New static global.
(vn_reference_lookup_3): Only look through kills if in
VN_WALKREWRITE mode.
(vn_reference_lookup_pieces): Adjust.
(vn_reference_lookup): Likewise.
(visit_reference_op_load): Likewise.
(visit_reference_op_store): Likewise.
* tree-ssa-pre.c (phi_translate_1): Use VN_WALK mode.
(compute_avail): Likewise.
(eliminate): Likewise.

* gcc.dg/torture/pr47365.c: New testcase.
* gcc.dg/tree-ssa/pr47392.c: Likewise.

From-SVN: r169090

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr47365.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr47392.c [new file with mode: 0644]
gcc/tree-ssa-pre.c
gcc/tree-ssa-sccvn.c
gcc/tree-ssa-sccvn.h

index 00d949d7c7c89023aa262a4e105fe557287268e9..3ba8544c38908216640b752f338d5bcf92984f88 100644 (file)
@@ -1,3 +1,20 @@
+2011-01-21  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/47365
+       * tree-ssa-sccvn.h (vn_lookup_kind): Declare.
+       (vn_reference_lookup_pieces): Adjust.
+       (vn_reference_lookup): Likewise.
+       * tree-ssa-sccvn.c (vn_walk_kind): New static global.
+       (vn_reference_lookup_3): Only look through kills if in
+       VN_WALKREWRITE mode.
+       (vn_reference_lookup_pieces): Adjust.
+       (vn_reference_lookup): Likewise.
+       (visit_reference_op_load): Likewise.
+       (visit_reference_op_store): Likewise.
+       * tree-ssa-pre.c (phi_translate_1): Use VN_WALK mode.
+       (compute_avail): Likewise.
+       (eliminate): Likewise.
+
 2011-01-20  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/47167
index 77d642169a959569f3803421477b2a2c838dcbbe..42cd7a2206095b17f618e2c434f57512d7421e8a 100644 (file)
@@ -1,3 +1,9 @@
+2011-01-21  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/47365
+       * gcc.dg/torture/pr47365.c: New testcase.
+       * gcc.dg/tree-ssa/pr47392.c: Likewise.
+
 2011-01-21  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * g++.dg/other/anon5.C: Skip on mips-sgi-irix*.
diff --git a/gcc/testsuite/gcc.dg/torture/pr47365.c b/gcc/testsuite/gcc.dg/torture/pr47365.c
new file mode 100644 (file)
index 0000000..e3bc550
--- /dev/null
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+
+struct A
+{
+  int i;
+};
+
+struct B
+{
+  struct A a[2];
+};
+
+int i = 1;
+struct B b = { 0, 3 };
+
+static void
+test ()
+{
+  if (b.a[0].i != i)
+    {
+      int t = b.a[0].i;
+      b.a[0] = b.a[1];
+      b.a[1].i = t;
+    }
+
+  if (b.a[1].i == i)
+    __builtin_abort ();
+
+  if (b.a[0].i == 0)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  test ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr47392.c b/gcc/testsuite/gcc.dg/tree-ssa/pr47392.c
new file mode 100644 (file)
index 0000000..9092ddd
--- /dev/null
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+
+struct A
+{
+  int i;
+};
+
+struct B
+{
+  struct A a[2];
+};
+
+int i = 1;
+struct B b = { 0, 3 };
+
+static void
+test ()
+{
+  if (b.a[0].i != i)
+    {
+      int t = b.a[0].i;
+      b.a[0] = b.a[1];
+      b.a[1].i = t;
+    }
+
+  if (b.a[1].i == i)
+    __builtin_abort ();
+
+  if (b.a[0].i == 0)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  test ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "Eliminated: 1" "pre" } } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
index 1cf78c776ddee8bc018b4c952e2b25f6711b1a01..7b117a81f6fee8964662b97528608a6f437fb2dd 100644 (file)
@@ -1701,7 +1701,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
            tree result = vn_reference_lookup_pieces (newvuse, ref->set,
                                                      ref->type,
                                                      newoperands,
-                                                     &newref, true);
+                                                     &newref, VN_WALK);
            if (newref)
              VEC_free (vn_reference_op_s, heap, newoperands);
 
@@ -2558,6 +2558,10 @@ compute_antic (void)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "Starting iteration %d\n", num_iterations);
+      /* ???  We need to clear our PHI translation cache here as the
+         ANTIC sets shrink and we restrict valid translations to
+        those having operands with leaders in ANTIC.  Same below
+        for PA ANTIC computation.  */
       num_iterations++;
       changed = false;
       for (i = n_basic_blocks - NUM_FIXED_BLOCKS - 1; i >= 0; i--)
@@ -3965,7 +3969,7 @@ compute_avail (void)
                copy_reference_ops_from_call (stmt, &ops);
                vn_reference_lookup_pieces (gimple_vuse (stmt), 0,
                                            gimple_expr_type (stmt),
-                                           ops, &ref, false);
+                                           ops, &ref, VN_NOWALK);
                VEC_free (vn_reference_op_s, heap, ops);
                if (!ref)
                  continue;
@@ -4035,7 +4039,7 @@ compute_avail (void)
 
                      vn_reference_lookup (gimple_assign_rhs1 (stmt),
                                           gimple_vuse (stmt),
-                                          true, &ref);
+                                          VN_WALK, &ref);
                      if (!ref)
                        continue;
 
@@ -4265,7 +4269,7 @@ eliminate (void)
              tree rhs = gimple_assign_rhs1 (stmt);
              tree val;
              val = vn_reference_lookup (gimple_assign_lhs (stmt),
-                                        gimple_vuse (stmt), true, NULL);
+                                        gimple_vuse (stmt), VN_WALK, NULL);
              if (TREE_CODE (rhs) == SSA_NAME)
                rhs = VN_INFO (rhs)->valnum;
              if (val
index 9b2638f109049cfa98de76f057ca0db9a909d942..886f215bb1b88eddd48629fbe21fa9e299874aa2 100644 (file)
@@ -988,6 +988,7 @@ vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult)
 }
 
 static tree *last_vuse_ptr;
+static vn_lookup_kind vn_walk_kind;
 
 /* Callback for walk_non_aliased_vuses.  Adjusts the vn_reference_t VR_
    with the current VUSE and performs the expression lookup.  */
@@ -1103,7 +1104,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
 
   /* For aggregate copies translate the reference through them if
      the copy kills ref.  */
-  else if (gimple_assign_single_p (def_stmt)
+  else if (vn_walk_kind == VN_WALKREWRITE
+          && gimple_assign_single_p (def_stmt)
           && (DECL_P (gimple_assign_rhs1 (def_stmt))
               || INDIRECT_REF_P (gimple_assign_rhs1 (def_stmt))
               || handled_component_p (gimple_assign_rhs1 (def_stmt))))
@@ -1193,7 +1195,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
 tree
 vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
                            VEC (vn_reference_op_s, heap) *operands,
-                           vn_reference_t *vnresult, bool maywalk)
+                           vn_reference_t *vnresult, vn_lookup_kind kind)
 {
   struct vn_reference_s vr1;
   vn_reference_t tmp;
@@ -1218,10 +1220,11 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
   vn_reference_lookup_1 (&vr1, vnresult);
 
   if (!*vnresult
-      && maywalk
+      && kind != VN_NOWALK
       && vr1.vuse)
     {
       ao_ref r;
+      vn_walk_kind = kind;
       if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands))
        *vnresult =
          (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
@@ -1244,7 +1247,7 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
    stored in the hashtable if one exists.  */
 
 tree
-vn_reference_lookup (tree op, tree vuse, bool maywalk,
+vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
                     vn_reference_t *vnresult)
 {
   VEC (vn_reference_op_s, heap) *operands;
@@ -1259,12 +1262,13 @@ vn_reference_lookup (tree op, tree vuse, bool maywalk,
   vr1.set = get_alias_set (op);
   vr1.hashcode = vn_reference_compute_hash (&vr1);
 
-  if (maywalk
+  if (kind != VN_NOWALK
       && vr1.vuse)
     {
       vn_reference_t wvnresult;
       ao_ref r;
       ao_ref_init (&r, op);
+      vn_walk_kind = kind;
       wvnresult =
        (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
                                                vn_reference_lookup_2,
@@ -1983,14 +1987,14 @@ visit_reference_op_load (tree lhs, tree op, gimple stmt)
 
   last_vuse = gimple_vuse (stmt);
   last_vuse_ptr = &last_vuse;
-  result = vn_reference_lookup (op, gimple_vuse (stmt), true, NULL);
+  result = vn_reference_lookup (op, gimple_vuse (stmt), VN_WALKREWRITE, NULL);
   last_vuse_ptr = NULL;
 
   /* If we have a VCE, try looking up its operand as it might be stored in
      a different type.  */
   if (!result && TREE_CODE (op) == VIEW_CONVERT_EXPR)
     result = vn_reference_lookup (TREE_OPERAND (op, 0), gimple_vuse (stmt),
-                                 true, NULL);
+                                 VN_WALKREWRITE, NULL);
 
   /* We handle type-punning through unions by value-numbering based
      on offset and size of the access.  Be prepared to handle a
@@ -2101,7 +2105,7 @@ visit_reference_op_store (tree lhs, tree op, gimple stmt)
      Otherwise, the vdefs for the store are used when inserting into
      the table, since the store generates a new memory state.  */
 
-  result = vn_reference_lookup (lhs, gimple_vuse (stmt), false, NULL);
+  result = vn_reference_lookup (lhs, gimple_vuse (stmt), VN_NOWALK, NULL);
 
   if (result)
     {
index c60c28ac11a55b396b4eeb2c9579b7c3328a69df..dd237fc6cddad9e4f746e17076c29c3ca5493979 100644 (file)
@@ -185,10 +185,11 @@ void copy_reference_ops_from_ref (tree, VEC(vn_reference_op_s, heap) **);
 void copy_reference_ops_from_call (gimple, VEC(vn_reference_op_s, heap) **);
 bool ao_ref_init_from_vn_reference (ao_ref *, alias_set_type, tree,
                                    VEC (vn_reference_op_s, heap) *);
+typedef enum { VN_NOWALK, VN_WALK, VN_WALKREWRITE } vn_lookup_kind;
 tree vn_reference_lookup_pieces (tree, alias_set_type, tree,
                                 VEC (vn_reference_op_s, heap) *,
-                                vn_reference_t *, bool);
-tree vn_reference_lookup (tree, tree, bool, vn_reference_t *);
+                                vn_reference_t *, vn_lookup_kind);
+tree vn_reference_lookup (tree, tree, vn_lookup_kind, vn_reference_t *);
 vn_reference_t vn_reference_insert (tree, tree, tree);
 vn_reference_t vn_reference_insert_pieces (tree, alias_set_type, tree,
                                           VEC (vn_reference_op_s, heap) *,