VRP was constant-propagating to a loop latch edge PHI arg from sth derived from an assert-expr. That's usually not a good idea because it prevents coalescing (or the fixup code has to insert a copy from a constant). If we derive the constant from an assert then we don't even save computation of the constant.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2015-02-20 Richard Biener <rguent...@suse.de> PR tree-optimization/65136 * tree-ssa-propagate.c: Include cfgloop.h. (replace_phi_args_in): Avoid replacing loop latch edge PHI arguments with constants. * gcc.dg/tree-ssa/pr65136.c: New testcase. Index: gcc/tree-ssa-propagate.c =================================================================== --- gcc/tree-ssa-propagate.c (revision 220809) +++ gcc/tree-ssa-propagate.c (working copy) @@ -66,6 +66,7 @@ #include "langhooks.h" #include "value-prof.h" #include "domwalk.h" +#include "cfgloop.h" /* This file implements a generic value propagation engine based on the same propagation used by the SSA-CCP algorithm [1]. @@ -992,6 +993,7 @@ replace_phi_args_in (gphi *phi, ssa_prop print_gimple_stmt (dump_file, phi, 0, TDF_SLIM); } + basic_block bb = gimple_bb (phi); for (i = 0; i < gimple_phi_num_args (phi); i++) { tree arg = gimple_phi_arg_def (phi, i); @@ -1002,6 +1004,21 @@ replace_phi_args_in (gphi *phi, ssa_prop if (val && val != arg && may_propagate_copy (arg, val)) { + edge e = gimple_phi_arg_edge (phi, i); + + /* Avoid propagating constants into loop latch edge + PHI arguments as this makes coalescing the copy + across this edge impossible. If the argument is + defined by an assert - otherwise the stmt will + get removed without replacing its uses. */ + if (TREE_CODE (val) != SSA_NAME + && bb->loop_father->header == bb + && dominated_by_p (CDI_DOMINATORS, e->src, bb) + && is_gimple_assign (SSA_NAME_DEF_STMT (arg)) + && (gimple_assign_rhs_code (SSA_NAME_DEF_STMT (arg)) + == ASSERT_EXPR)) + continue; + if (TREE_CODE (val) != SSA_NAME) prop_stats.num_const_prop++; else @@ -1014,8 +1031,15 @@ replace_phi_args_in (gphi *phi, ssa_prop through an abnormal edge, update the replacement accordingly. */ if (TREE_CODE (val) == SSA_NAME - && gimple_phi_arg_edge (phi, i)->flags & EDGE_ABNORMAL) - SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val) = 1; + && e->flags & EDGE_ABNORMAL + && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val)) + { + /* This can only occur for virtual operands, since + for the real ones SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val)) + would prevent replacement. */ + gcc_checking_assert (virtual_operand_p (val)); + SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val) = 1; + } } } } Index: gcc/testsuite/gcc.dg/tree-ssa/pr65136.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/pr65136.c (revision 0) +++ gcc/testsuite/gcc.dg/tree-ssa/pr65136.c (working copy) @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-rtl-expand-details" } */ + +int foo(unsigned int cc ) +{ + + while ( cc >> 16 ) + { + cc = (cc & 0xffff) + (cc >> 16); + } + + return ( (unsigned short)(cc) ) == ((unsigned short)(-1)); +} + +/* { dg-final { scan-rtl-dump-not "_\[0-9\]* = 1;" "expand" } } */ +/* { dg-final { cleanup-rtl-dump "expand" } } */