http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57915
Andrey Belevantsev <abel at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |abel at gcc dot gnu.org --- Comment #6 from Andrey Belevantsev <abel at gcc dot gnu.org> --- The cprop pass doesn't care much in this case, it only passes the resulting set to simplify_rtx which does nothing. Fwprop does the right thing with the similar insn (insn 9) but doesn't work for insn in question (insn 58) because it is inside the loop: 1466 Do not forward propagate addresses into loops until after unrolling. 1467 CSE did so because it was able to fix its own mess, but we are not. */ But come on, in this case the def/use are in the same basic block(!) so this stuff not fixed by fwprop is later fixed (wrongly) by _local_ cprop. Fwprop2 is supposed to fix this but it surely runs after the 1st cprop so it doesn't have a chance. So either we: 1) drop the loop check altogether -- forward_propagate_into already has code not to propagate into the inner loop; this might be too risky as I don't know all reasons of why the first fwprop does not propagate inside loops; 2) allow at least propagating into the same blocks to offset the local cprop code as in the below patch; 3) teach cprop to leave it for the second fwprop_addr -- but there's a lot of stuff happening in between; 4) teach cprop to simplify rtxes in line with the fwprop's propagate rtx code, i.e. diving inside and when looking at a mem, pass its address to simplify_gen_binary and other address-related things. The below patch is the simplest option 2) and fixes the test case. diff --git a/gcc/fwprop.c b/gcc/fwprop.c index 4317f51..c62a501 100644 --- a/gcc/fwprop.c +++ b/gcc/fwprop.c @@ -1469,11 +1469,14 @@ fwprop (void) for (i = 0; i < DF_USES_TABLE_SIZE (); i++) { df_ref use = DF_USES_GET (i); + df_ref def; if (use) if (DF_REF_TYPE (use) == DF_REF_REG_USE || DF_REF_BB (use)->loop_father == NULL /* The outer most loop is not really a loop. */ - || loop_outer (DF_REF_BB (use)->loop_father) == NULL) + || loop_outer (DF_REF_BB (use)->loop_father) == NULL + || ((def = get_def_for_use (use)) + && DF_REF_BB (use) == DF_REF_BB (def))) need_cleanup |= forward_propagate_into (use); }