On Wed, Jan 24, 2018 at 4:42 AM, Alexandre Oliva <[email protected]> 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