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);
     }

Reply via email to