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; + }