> -----Original Message----- > From: Richard Biener [mailto:richard.guent...@gmail.com] > Sent: Monday, March 30, 2020 4:39 PM > To: xiezhiheng <xiezhih...@huawei.com> > Cc: gcc@gcc.gnu.org > Subject: Re: [QUESTION] About RTL optimization at forward propagation > > On Sat, Mar 28, 2020 at 4:19 AM xiezhiheng <xiezhih...@huawei.com> > wrote: > > > > Hi, > > I find there exists some restricts in function fwprop preventing it to > > forward propagate addresses into loops. > > /* Go through all the uses. df_uses_create will create new ones at the > > end, and we'll go through them as well. > > > > Do not forward propagate addresses into loops until after unrolling. > > CSE did so because it was able to fix its own mess, but we are not. */ > > for (i = 0; i < DF_USES_TABLE_SIZE (); i++) > > { > > if (!propagations_left) > > break; > > > > df_ref use = DF_USES_GET (i); > > 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) > > forward_propagate_into (use, fwprop_addr_p); > > > > else if (fwprop_addr_p) > > forward_propagate_into (use, false); > > } > > } > > > > And I have two questions. > > 1) What are the reasons or background for not forward propagating > > addresses into loops ? > > 2) Can we still forward propagate addresses if the def and use are in the > > same loop ? > > I mean something like: > > The condiition indeed looks odd, the canonical way would be to check > > !flow_loop_nested_p (DF_REF_BB (def)->loop_father, DF_REF_BB > (use)->loop_father) > > which would allow propagating addresses defined in loops outside as well. > And loop_father should never be NULL I think.
Thanks for replying! I think your change will also propagate addresses from one loop to another. If def's loop is less frequent than use's, maybe it'll get worse performance. I suggest we can go with the following condition DF_REF_BB(def)->loop_father == DF_REF_BB(use)->loop_father || flow_loop_nested_p (DF_REF_BB(use)->loop_father, DF_REF_BB(def)->loop_father) Also I find that function should_replace_address returns true when it has a positive gain. /* OLD is a memory address. Return whether it is good to use NEW instead, for a memory access in the given MODE. */ static bool should_replace_address (rtx old_rtx, rtx new_rtx, machine_mode mode, addr_space_t as, bool speed) { int gain; if (rtx_equal_p (old_rtx, new_rtx) || !memory_address_addr_space_p (mode, new_rtx, as)) return false; /* Copy propagation is always ok. */ if (REG_P (old_rtx) && REG_P (new_rtx)) return true; /* Prefer the new address if it is less expensive. */ gain = (address_cost (old_rtx, mode, as, speed) - address_cost (new_rtx, mode, as, speed)); /* If the addresses have equivalent cost, prefer the new address if it has the highest `set_src_cost'. That has the potential of eliminating the most insns without additional costs, and it is the same that cse.c used to do. */ if (gain == 0) gain = (set_src_cost (new_rtx, VOIDmode, speed) - set_src_cost (old_rtx, VOIDmode, speed)); return (gain > 0); <<<<<<<< } Actually we can choose the new address if they have the same cost, because we may get some other benefits. Compare a) m = n + 10 MEM[m + 20] = 0 and b) m = n + 10 MEM[n + 30] = 0 Although we have no gain in memory operation (they have the same ` address_cost' and ` set_src_cost'), we may have a chance to eliminate the dead code ` m = n + 10' in (b). Best regards! > > > diff -Nurp a/gcc/fwprop.c b/gcc/fwprop.c > > --- a/gcc/fwprop.c 2020-03-27 03:17:50.704000000 -0400 > > +++ b/gcc/fwprop.c 2020-03-27 04:58:35.148000000 -0400 > > @@ -1573,10 +1573,12 @@ fwprop (bool fwprop_addr_p) > > df_ref use = DF_USES_GET (i); > > if (use) > > { > > + df_ref def = get_def_for_use (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 && DF_REF_BB (def)->loop_father == DF_REF_BB > > (use)->loop_father)) > > forward_propagate_into (use, fwprop_addr_p); > > > > else if (fwprop_addr_p) > > > > I would be grateful if anyone could help. > > > > Best regards