This fixes one issue with copyrename, that it "leaks" names backward through a PHI node because it treats a PHI node
_1 = PHI <_2, _3, _4> as _1 = _2; _1 = _3; _1 = _4; at the point of the PHI node which is certainly not what it is (the assigns exist, one each, on the incoming edges only). The following fixes that. Bootstrapped and tested on x86_64-unknown-linux-gnu. The guality test fails for -Os on x86_64 and for -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects on i586, a single FAIL is much better than another 7 XPASSes, so I left it as FAIL. On x86_64 now also gcc.target/i386/pad-10.c FAILs, because appearantly whatever is responsible for not issueing padding nops is confused by the no longer occuring coalescing at out-of-SSA time. Thus clearly a pre-existing bug and simply a weak testcase. Applied. Richard. 2012-08-13 Richard Guenther <rguent...@suse.de> PR tree-optimization/54200 * tree-ssa-copyrename.c (rename_ssa_copies): Do not add PHI results to another partition if not all PHI arguments have the same partition. * gcc.dg/guality/pr54200.c: New testcase. * gcc.dg/tree-ssa/slsr-8.c: Adjust. Index: gcc/tree-ssa-copyrename.c =================================================================== *** gcc/tree-ssa-copyrename.c.orig 2012-08-10 15:51:19.000000000 +0200 --- gcc/tree-ssa-copyrename.c 2012-08-10 15:51:29.000638547 +0200 *************** rename_ssa_copies (void) *** 348,362 **** res = gimple_phi_result (phi); /* Do not process virtual SSA_NAMES. */ ! if (!is_gimple_reg (res)) continue; ! for (i = 0; i < gimple_phi_num_args (phi); i++) ! { ! tree arg = gimple_phi_arg (phi, i)->def; ! if (TREE_CODE (arg) == SSA_NAME) ! updated |= copy_rename_partition_coalesce (map, res, arg, debug); ! } } } --- 348,400 ---- res = gimple_phi_result (phi); /* Do not process virtual SSA_NAMES. */ ! if (virtual_operand_p (res)) continue; ! /* Make sure to only use the same partition for an argument ! as the result but never the other way around. */ ! if (SSA_NAME_VAR (res) ! && !DECL_IGNORED_P (SSA_NAME_VAR (res))) ! for (i = 0; i < gimple_phi_num_args (phi); i++) ! { ! tree arg = PHI_ARG_DEF (phi, i); ! if (TREE_CODE (arg) == SSA_NAME) ! updated |= copy_rename_partition_coalesce (map, res, arg, ! debug); ! } ! /* Else if all arguments are in the same partition try to merge ! it with the result. */ ! else ! { ! int all_p_same = -1; ! int p = -1; ! for (i = 0; i < gimple_phi_num_args (phi); i++) ! { ! tree arg = PHI_ARG_DEF (phi, i); ! if (TREE_CODE (arg) != SSA_NAME) ! { ! all_p_same = 0; ! break; ! } ! else if (all_p_same == -1) ! { ! p = partition_find (map->var_partition, ! SSA_NAME_VERSION (arg)); ! all_p_same = 1; ! } ! else if (all_p_same == 1 ! && p != partition_find (map->var_partition, ! SSA_NAME_VERSION (arg))) ! { ! all_p_same = 0; ! break; ! } ! } ! if (all_p_same == 1) ! updated |= copy_rename_partition_coalesce (map, res, ! PHI_ARG_DEF (phi, 0), ! debug); ! } } } Index: gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c.orig 2012-08-10 15:51:19.000000000 +0200 --- gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c 2012-08-10 15:51:29.000638547 +0200 *************** f (int s, int *c) *** 17,23 **** return x1 ? x2 : x3; } ! /* There are 2 ' * ' instances in the decls (since "int * x3;" is ! optimized out), 1 parm, 2 in the code. */ ! /* { dg-final { scan-tree-dump-times " \\* " 5 "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ --- 17,23 ---- return x1 ? x2 : x3; } ! /* There are 4 ' * ' instances in the decls (since "int * iftmp.0;" is ! added), 1 parm, 2 in the code. */ ! /* { dg-final { scan-tree-dump-times " \\* " 7 "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ Index: gcc/testsuite/gcc.dg/guality/pr54200.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gcc.dg/guality/pr54200.c 2012-08-10 16:12:48.006594252 +0200 *************** *** 0 **** --- 1,28 ---- + /* PR tree-optimization/54200 */ + /* { dg-do run } */ + /* { dg-options "-g -fno-var-tracking-assignments" } */ + + int o __attribute__((used)); + + void bar (void) { o = 2; } + + int __attribute__((noinline,noclone)) + foo (int z, int x, int b) + { + if (x == 1) + { + bar (); + return z; + } + else + { + int a = (x + z) + b; + return a; /* { dg-final { gdb-test 20 "z" "3" } } */ + } + } + + int main () + { + foo (3, 2, 1); + return 0; + }