In this PR we hit the issue that when CCP faces a conditional which is (still) undefined it will consider all outgoing edges executable. Eventually we'll reverse that decision (but without reflecting that in the lattice), but it's too late then if a PHI node merging the edges has been evaluated to a copy defined in the not executable path.
Thus the following patch makes sure we never even start with such a case (SSA propagator iteration order hopefully makes sure this doesn't pessimize things in non-loop regions - I have a patch to fix some iteration order oddities of it). Bootstrap and regtest running on x86_64-unknown-linux-gnu. Richard. 2015-07-06 Richard Biener <rguent...@suse.de> PR tree-optimization/66772 * tree-ssa-ccp.c (ccp_visit_phi_node): Make sure that copy values are available in the PHI node BB when there are still unexecutable edges. * gcc.dg/torture/pr66772-1.c: New testcase. * gcc.dg/torture/pr66772-2.c: Likewise. Index: gcc/tree-ssa-ccp.c =================================================================== *** gcc/tree-ssa-ccp.c (revision 225449) --- gcc/tree-ssa-ccp.c (working copy) *************** ccp_visit_phi_node (gphi *phi) *** 1081,1086 **** --- 1094,1100 ---- new_val.mask = 0; bool first = true; + bool non_exec_edge = false; for (i = 0; i < gimple_phi_num_args (phi); i++) { /* Compute the meet operator over all the PHI arguments flowing *************** ccp_visit_phi_node (gphi *phi) *** 1121,1126 **** --- 1135,1156 ---- if (new_val.lattice_val == VARYING) break; } + else + non_exec_edge = true; + } + + /* In case there were non-executable edges and the value is a copy + make sure its definition dominates the PHI node. */ + if (non_exec_edge + && new_val.lattice_val == CONSTANT + && TREE_CODE (new_val.value) == SSA_NAME + && ! SSA_NAME_IS_DEFAULT_DEF (new_val.value) + && ! dominated_by_p (CDI_DOMINATORS, gimple_bb (phi), + gimple_bb (SSA_NAME_DEF_STMT (new_val.value)))) + { + new_val.lattice_val = VARYING; + new_val.value = NULL_TREE; + new_val.mask = -1; } if (dump_file && (dump_flags & TDF_DETAILS)) Index: gcc/testsuite/gcc.dg/torture/pr66733-1.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr66733-1.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr66733-1.c (working copy) *************** *** 0 **** --- 1,28 ---- + /* { dg-do compile } */ + + int a; + + int + fn1 () + { + return 1; + } + + void + fn2 () + { + int b, j; + for (;;) + { + int c = 1; + if (j) + { + if (c) + break; + } + else + b = a; + fn1 () && b; + j = fn1 (); + } + } Index: gcc/testsuite/gcc.dg/torture/pr66733-2.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr66733-2.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr66733-2.c (working copy) *************** *** 0 **** --- 1,46 ---- + /* { dg-do compile } */ + + int a, b, c, e, f; + + void fn1 (int p) { } + + int + fn2 (int p) + { + return a ? p % a : 0; + } + + short + fn3 (int p) + { + return (1 >> p) < 1 ? 1 : p; + } + + int + fn4 () + { + int g = 0, h = 1; + if (b) + goto lbl; + fn2 (0); + if (fn3 (1)) + fn1 (e && c); + if (h) + { + int i = 1; + lbl: + if (i) + return 0; + for (; g < 1; g++) + ; + } + for (;;) + f || g > 0; + } + + int + main () + { + fn4 (); + return 0; + }