On Wed, Jan 24, 2018 at 4:42 AM, Alexandre Oliva <aol...@redhat.com> wrote: > These two patches fix PR81611. > > The first one improves forwprop so that we avoid adding SSA conflicting > by forwpropping the iv increment, which may cause both the incremented > and the original value to be live, even when the iv is copied between > the PHI node and the increment. We already handled the case in which > there aren't any such copies. > > Alas, this is not enough to address the problem on avr, even though it > fixes it on e.g. ppc. The reason is that avr rejects var+offset > addresses, and this prevents the memory access in a post-inc code > sequence from being adjusted to an address that auto-inc-dec can > recognize. > > The second patch adjusts auto-inc-dec to recognize a code sequence in > which the original, unincremented pseudo is used in an address after > it's incremented into another pseudo, and turn that into a post-inc > address, leaving the copying for subsequent passes to eliminate. > > Regstrapped on x86_64-linux-gnu, i686-linux-gnu, ppc64-linux-gnu and > aarch64-linux-gnu. Ok to install? > > > I'd appreciate suggestions on how to turn the submitted testcase into a > regression test; I suppose an avr-specific test that requires the > auto-inc transformation is a possibility, but that feels a bit too > limited, doesn't it? Thoughts? Thanks in advance, > > > [PR81611] accept copies in simple_iv_increment_p > > If there are copies between the GIMPLE_PHI at the loop body and the > increment that reaches it (presumably through a back edge), still > regard it as a simple_iv_increment, so that we won't consider the > value in the back edge eligible for forwprop. Doing so would risk > making the phi node and the incremented conflicting value live > within the loop, and the phi node to be preserved for propagated > uses after the loop. > > for gcc/ChangeLog > > PR tree-optimization/81611 > * tree-ssa-dom.c (simple_iv_increment_p): Skip intervening > copies. > --- > gcc/tree-ssa-dom.c | 21 +++++++++++++++++---- > 1 file changed, 17 insertions(+), 4 deletions(-) > > diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c > index 2b371667253a..3c0ff9458342 100644 > --- a/gcc/tree-ssa-dom.c > +++ b/gcc/tree-ssa-dom.c > @@ -1276,8 +1276,11 @@ record_equality (tree x, tree y, class > const_and_copies *const_and_copies) > /* Returns true when STMT is a simple iv increment. It detects the > following situation: > > - i_1 = phi (..., i_2) > - i_2 = i_1 +/- ... */ > + i_1 = phi (..., i_k) > + [...] > + i_j = i_{j-1} for each j : 2 <= j <= k-1 > + [...] > + i_k = i_{k-1} +/- ... */ > > bool > simple_iv_increment_p (gimple *stmt) > @@ -1305,8 +1308,18 @@ simple_iv_increment_p (gimple *stmt) > return false; > > phi = SSA_NAME_DEF_STMT (preinc); > - if (gimple_code (phi) != GIMPLE_PHI) > - return false; > + while (gimple_code (phi) != GIMPLE_PHI) > + { > + /* Follow trivial copies, but not the DEF used in a back edge, > + so that we don't prevent coalescing. */ > + if (gimple_code (phi) != GIMPLE_ASSIGN > + || gimple_assign_lhs (phi) != preinc > + || !gimple_assign_ssa_name_copy_p (phi))
given gimple_assign_ssa_name_copy checks it is an assign just do if (!gimple_assign_ssa-anme_Copy_p (phi)) the lhs != preinc check is always false given you got to phi via SSA_NAME_DEF_STMT of preinc. The simple_iv_increment_p change is ok with that change. The other change is RTL which I defer to somebody else. Richard. > + return false; > + > + preinc = gimple_assign_rhs1 (phi); > + phi = SSA_NAME_DEF_STMT (preinc); > + } > > for (i = 0; i < gimple_phi_num_args (phi); i++) > if (gimple_phi_arg_def (phi, i) == lhs) > > > [PR81611] turn inc-and-use-of-dead-orig into auto-inc > > When the addressing modes available on the machine don't allow offsets > in addresses, odds are that post-increments will be represented in > trees and RTL as: > > y <= x + 1 > ... *(x) ... > x <= y > > so deal with this form so as to create auto-inc addresses that we'd > otherwise miss. > > > for gcc/ChangeLog > > PR rtl-optimization/81611 > * auto-inc-dec.c (attempt_change): Move dead note from > mem_insn if it's the next use of regno > (find_address): Take address use of reg holding > non-incremented value. > (merge_in_block): Attempt to use a mem insn that is the next > use of the original regno. > --- > gcc/auto-inc-dec.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 44 insertions(+), 2 deletions(-) > > diff --git a/gcc/auto-inc-dec.c b/gcc/auto-inc-dec.c > index d02fa9d081c7..4ffbcf56a456 100644 > --- a/gcc/auto-inc-dec.c > +++ b/gcc/auto-inc-dec.c > @@ -508,7 +508,11 @@ attempt_change (rtx new_addr, rtx inc_reg) > before the memory reference. */ > gcc_assert (mov_insn); > emit_insn_before (mov_insn, inc_insn.insn); > - move_dead_notes (mov_insn, inc_insn.insn, inc_insn.reg0); > + regno = REGNO (inc_insn.reg0); > + if (reg_next_use[regno] == mem_insn.insn) > + move_dead_notes (mov_insn, mem_insn.insn, inc_insn.reg0); > + else > + move_dead_notes (mov_insn, inc_insn.insn, inc_insn.reg0); > > regno = REGNO (inc_insn.reg_res); > reg_next_def[regno] = mov_insn; > @@ -842,7 +846,7 @@ find_address (rtx *address_of_x) > > if (code == MEM && rtx_equal_p (XEXP (x, 0), inc_insn.reg_res)) > { > - /* Match with *reg0. */ > + /* Match with *reg_res. */ > mem_insn.mem_loc = address_of_x; > mem_insn.reg0 = inc_insn.reg_res; > mem_insn.reg1_is_const = true; > @@ -850,6 +854,17 @@ find_address (rtx *address_of_x) > mem_insn.reg1 = GEN_INT (0); > return -1; > } > + if (code == MEM && inc_insn.reg1_is_const && inc_insn.reg0 > + && rtx_equal_p (XEXP (x, 0), inc_insn.reg0)) > + { > + /* Match with *reg0 AKA *(reg_res - reg1_val). */ > + mem_insn.mem_loc = address_of_x; > + mem_insn.reg0 = inc_insn.reg_res; > + mem_insn.reg1_is_const = true; > + mem_insn.reg1_val = -inc_insn.reg1_val; > + mem_insn.reg1 = GEN_INT (mem_insn.reg1_val); > + return -1; > + } > if (code == MEM && GET_CODE (XEXP (x, 0)) == PLUS > && rtx_equal_p (XEXP (XEXP (x, 0), 0), inc_insn.reg_res)) > { > @@ -1370,6 +1385,33 @@ merge_in_block (int max_reg, basic_block bb) > insn_is_add_or_inc = false; > } > } > + > + if (ok && insn_is_add_or_inc > + && inc_insn.reg0 != inc_insn.reg_res) > + { > + regno = REGNO (inc_insn.reg0); > + int luid = DF_INSN_LUID (mem_insn.insn); > + mem_insn.insn = get_next_ref (regno, bb, reg_next_use); > + > + /* Try a mem use of reg0 before that of reg_res > + too. If there's no further use of reg_res, > + there's no point in trying an auto-inc, and > + if the use of reg0 is after that of reg_res, > + it will be too late for the auto-inc to > + compute reg_res's correct value. */ > + if (mem_insn.insn > + && luid > DF_INSN_LUID (mem_insn.insn) > + && find_address (&PATTERN (mem_insn.insn)) == -1) > + { > + if (dump_file) > + dump_mem_insn (dump_file); > + if (try_merge ()) > + { > + success_in_block++; > + insn_is_add_or_inc = false; > + } > + } > + } > } > } > } > > > -- > Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/ > You must be the change you wish to see in the world. -- Gandhi > Be Free! -- http://FSFLA.org/ FSF Latin America board member > Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer