This fixes PR56661 - we were value-numbering two call results
the same even though function attributes tell us that they are
required to return a distinct value (and this property is exploited
by alias analysis).  Simply don't do that (as opposed to trying to
fix things up).

Bootstrap and regtest pending on x86_64-unknown-linux-gnu.

Richard.

2013-03-20  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/56661
        * tree-ssa-sccvn.c (visit_use): Only value-number calls if
        the result does not have to be distinct.

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

Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c        (revision 196808)
--- gcc/tree-ssa-sccvn.c        (working copy)
*************** visit_use (tree use)
*** 3506,3513 ****
                     We can value number 2 calls to the same function with the
                     same vuse and the same operands which are not subsequent
                     the same, because there is no code in the program that can
!                    compare the 2 values.  */
!                 || gimple_vdef (stmt)))
            changed = visit_reference_op_call (lhs, stmt);
          else
            changed = defs_to_varying (stmt);
--- 3506,3518 ----
                     We can value number 2 calls to the same function with the
                     same vuse and the same operands which are not subsequent
                     the same, because there is no code in the program that can
!                    compare the 2 values...  */
!                 || (gimple_vdef (stmt)
!                     /* ... unless the call returns a pointer which does
!                        not alias with anything else.  In which case the
!                        information that the values are distinct are encoded
!                        in the IL.  */
!                     && !(gimple_call_return_flags (stmt) & ERF_NOALIAS))))
            changed = visit_reference_op_call (lhs, stmt);
          else
            changed = defs_to_varying (stmt);
Index: gcc/testsuite/gcc.dg/torture/pr56661.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr56661.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr56661.c      (working copy)
***************
*** 0 ****
--- 1,46 ----
+ /* { dg-do run } */
+ 
+ __attribute__((noinline, noclone)) void
+ bar (int *b)
+ {
+   b[0] = b[1] = b[2] = 1;
+ }
+ 
+ __attribute__((noinline, noclone)) int
+ baz (int x)
+ {
+   if (x != 1)
+     __builtin_abort ();
+ }
+ 
+ void
+ foo (int x)
+ {
+   if (x == 0)
+     {
+       int *b = __builtin_malloc (3 * sizeof (int));
+       while (b[0])
+       ;
+     }
+   else if (x == 1)
+     {
+       int i, j;
+       int *b = __builtin_malloc (3 * sizeof (int));
+       for (i = 0; i < 2; i++)
+       {
+         bar (b);
+         for (j = 0; j < 3; ++j)
+           baz (b[j]);
+         baz (b[0]);
+       }
+     }
+ }
+ 
+ int
+ main ()
+ {
+   int x = 1;
+   asm volatile ("" : "+r" (x));
+   foo (x);
+   return 0;
+ }

Reply via email to