This fixes copy-propagation (in DOM in this case) which breaks virtual SSA form by introducing overlapping life-ranges which in turn breaks CFG transforms that rely on that property.
The patch disables copy-propagation of virtuals in general (for all passes checking may_propagate_copy) because that predicate cannot decide if the propagation would be valid. Instead the patch special-cases propagation of virtual operands across PHI nodes (the only relevant case of virtual operand copy propagation) in phi_only_cprop. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2013-05-28 Richard Biener <rguent...@suse.de> PR tree-optimization/57411 * tree-ssa-copy.c (may_propagate_copy): Cannot propagate virtual operands. * tree-ssa-dom.c (eliminate_const_or_copy): Special-case virtual operand propagation. * g++.dg/opt/pr57411.C: New testcase. Index: gcc/tree-ssa-copy.c =================================================================== *** gcc/tree-ssa-copy.c (revision 199356) --- gcc/tree-ssa-copy.c (working copy) *************** may_propagate_copy (tree dest, tree orig *** 73,86 **** if (!useless_type_conversion_p (type_d, type_o)) return false; ! /* Propagating virtual operands is always ok. */ if (TREE_CODE (dest) == SSA_NAME && virtual_operand_p (dest)) ! { ! /* But only between virtual operands. */ ! gcc_assert (TREE_CODE (orig) == SSA_NAME && virtual_operand_p (orig)); ! ! return true; ! } /* Anything else is OK. */ return true; --- 73,82 ---- if (!useless_type_conversion_p (type_d, type_o)) return false; ! /* Generally propagating virtual operands is not ok as that may ! create overlapping life-ranges. */ if (TREE_CODE (dest) == SSA_NAME && virtual_operand_p (dest)) ! return false; /* Anything else is OK. */ return true; Index: gcc/testsuite/g++.dg/opt/pr57411.C =================================================================== *** gcc/testsuite/g++.dg/opt/pr57411.C (revision 0) --- gcc/testsuite/g++.dg/opt/pr57411.C (working copy) *************** *** 0 **** --- 1,23 ---- + // { dg-do compile } + // { dg-options "-O -fno-tree-dce -ftree-vectorize" } + + static inline void + iota (int *__first, int *__last, int __value) + { + for (; __first != __last; ++__first) + { + *__first = __value; + } + } + + void assert_fail (); + + int A[] = { 0, 0, 0 }; + + void + test01 (int equal) + { + iota (A, A + 3, 1); + if (equal) + assert_fail (); + } Index: gcc/tree-ssa-dom.c =================================================================== *** gcc/tree-ssa-dom.c (revision 199355) --- gcc/tree-ssa-dom.c (working copy) *************** eliminate_const_or_copy (gimple stmt, bi *** 2936,2942 **** return; } ! propagate_rhs_into_lhs (stmt, lhs, rhs, interesting_names); /* Note that STMT may well have been deleted by now, so do not access it, instead use the saved version # to clear --- 2936,2957 ---- return; } ! if (!virtual_operand_p (lhs)) ! propagate_rhs_into_lhs (stmt, lhs, rhs, interesting_names); ! else ! { ! gimple use_stmt; ! imm_use_iterator iter; ! use_operand_p use_p; ! /* For virtual operands we have to propagate into all uses as ! otherwise we will create overlapping life-ranges. */ ! FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs) ! FOR_EACH_IMM_USE_ON_STMT (use_p, iter) ! SET_USE (use_p, rhs); ! if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs) = 1; ! remove_stmt_or_phi (stmt); ! } /* Note that STMT may well have been deleted by now, so do not access it, instead use the saved version # to clear