[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 it by turning such RTL as: (set y (plus x n)) ... (mem x) ... without intervening uses of y into (set y x) ... (mem (post_add y n)) ... 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. Add parm to limit search to the named reg only. (merge_in_block): Attempt to use a mem insn that is the next use of the original regno. From-SVN: r258053
This commit is contained in:
parent
8cda97ab52
commit
408e89356c
2 changed files with 141 additions and 10 deletions
|
@ -1,3 +1,14 @@
|
|||
2018-02-28 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
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. Add parm to limit search to the named
|
||||
reg only.
|
||||
(merge_in_block): Attempt to use a mem insn that is the next
|
||||
use of the original regno.
|
||||
|
||||
2018-02-27 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c++/83871
|
||||
|
|
|
@ -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;
|
||||
|
@ -825,13 +829,15 @@ parse_add_or_inc (rtx_insn *insn, bool before_mem)
|
|||
|
||||
/* A recursive function that checks all of the mem uses in
|
||||
ADDRESS_OF_X to see if any single one of them is compatible with
|
||||
what has been found in inc_insn.
|
||||
what has been found in inc_insn. To avoid accidental matches, we
|
||||
will only find MEMs with FINDREG, be it inc_insn.reg_res, be it
|
||||
inc_insn.reg0.
|
||||
|
||||
-1 is returned for success. 0 is returned if nothing was found and
|
||||
1 is returned for failure. */
|
||||
|
||||
static int
|
||||
find_address (rtx *address_of_x)
|
||||
find_address (rtx *address_of_x, rtx findreg)
|
||||
{
|
||||
rtx x = *address_of_x;
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
|
@ -840,9 +846,10 @@ find_address (rtx *address_of_x)
|
|||
int value = 0;
|
||||
int tem;
|
||||
|
||||
if (code == MEM && rtx_equal_p (XEXP (x, 0), inc_insn.reg_res))
|
||||
if (code == MEM && findreg == inc_insn.reg_res
|
||||
&& 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,7 +857,21 @@ find_address (rtx *address_of_x)
|
|||
mem_insn.reg1 = GEN_INT (0);
|
||||
return -1;
|
||||
}
|
||||
if (code == MEM && GET_CODE (XEXP (x, 0)) == PLUS
|
||||
if (code == MEM && inc_insn.reg1_is_const && inc_insn.reg0
|
||||
&& findreg == inc_insn.reg0
|
||||
&& rtx_equal_p (XEXP (x, 0), inc_insn.reg0))
|
||||
{
|
||||
/* Match with *reg0, assumed to be equivalent to
|
||||
*(reg_res - reg1_val); callers must check whether this is the case. */
|
||||
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 && findreg == inc_insn.reg_res
|
||||
&& GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& rtx_equal_p (XEXP (XEXP (x, 0), 0), inc_insn.reg_res))
|
||||
{
|
||||
rtx b = XEXP (XEXP (x, 0), 1);
|
||||
|
@ -879,7 +900,7 @@ find_address (rtx *address_of_x)
|
|||
{
|
||||
/* If REG occurs inside a MEM used in a bit-field reference,
|
||||
that is unacceptable. */
|
||||
if (find_address (&XEXP (x, 0)))
|
||||
if (find_address (&XEXP (x, 0), findreg))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -891,7 +912,7 @@ find_address (rtx *address_of_x)
|
|||
{
|
||||
if (fmt[i] == 'e')
|
||||
{
|
||||
tem = find_address (&XEXP (x, i));
|
||||
tem = find_address (&XEXP (x, i), findreg);
|
||||
/* If this is the first use, let it go so the rest of the
|
||||
insn can be checked. */
|
||||
if (value == 0)
|
||||
|
@ -905,7 +926,7 @@ find_address (rtx *address_of_x)
|
|||
int j;
|
||||
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
||||
{
|
||||
tem = find_address (&XVECEXP (x, i, j));
|
||||
tem = find_address (&XVECEXP (x, i, j), findreg);
|
||||
/* If this is the first use, let it go so the rest of
|
||||
the insn can be checked. */
|
||||
if (value == 0)
|
||||
|
@ -1360,7 +1381,106 @@ merge_in_block (int max_reg, basic_block bb)
|
|||
if (dump_file)
|
||||
dump_inc_insn (dump_file);
|
||||
|
||||
if (ok && find_address (&PATTERN (mem_insn.insn)) == -1)
|
||||
if (ok && find_address (&PATTERN (mem_insn.insn),
|
||||
inc_insn.reg_res) == -1)
|
||||
{
|
||||
if (dump_file)
|
||||
dump_mem_insn (dump_file);
|
||||
if (try_merge ())
|
||||
{
|
||||
success_in_block++;
|
||||
insn_is_add_or_inc = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (insn_is_add_or_inc
|
||||
/* find_address will only recognize an address
|
||||
with a reg0 that's not reg_res when
|
||||
reg1_is_const, so cut it off early if we
|
||||
already know it won't match. */
|
||||
&& inc_insn.reg1_is_const
|
||||
&& inc_insn.reg0
|
||||
&& inc_insn.reg0 != inc_insn.reg_res)
|
||||
{
|
||||
/* If we identified an inc_insn that uses two
|
||||
different pseudos, it's of the form
|
||||
|
||||
(set reg_res (plus reg0 reg1))
|
||||
|
||||
where reg1 is a constant (*).
|
||||
|
||||
The next use of reg_res was not idenfied by
|
||||
find_address as a mem_insn that we could turn
|
||||
into auto-inc, so see if we find a suitable
|
||||
MEM in the next use of reg0, as long as it's
|
||||
before any subsequent use of reg_res:
|
||||
|
||||
... (mem (... reg0 ...)) ...
|
||||
|
||||
... reg_res ...
|
||||
|
||||
In this case, we can turn the plus into a
|
||||
copy, and the reg0 in the MEM address into a
|
||||
post_inc of reg_res:
|
||||
|
||||
(set reg_res reg0)
|
||||
|
||||
... (mem (... (post_add reg_res reg1) ...)) ...
|
||||
|
||||
reg_res will then have the correct value at
|
||||
subsequent uses, and reg0 will remain
|
||||
unchanged.
|
||||
|
||||
(*) We could support non-const reg1, but then
|
||||
we'd have to check that reg1 remains
|
||||
unchanged all the way to the modified MEM,
|
||||
and we'd have to extend find_address to
|
||||
represent a non-const negated reg1. */
|
||||
regno = REGNO (inc_insn.reg0);
|
||||
rtx_insn *reg0_use = get_next_ref (regno, bb,
|
||||
reg_next_use);
|
||||
|
||||
/* Give up if the next use of reg0 is after the next
|
||||
use of reg_res (same insn is ok; we might have
|
||||
found a MEM with reg_res before, and that failed,
|
||||
but now we try reg0, which might work), or defs
|
||||
of reg_res (same insn is not ok, we'd introduce
|
||||
another def in the same insn) or reg0. */
|
||||
if (reg0_use)
|
||||
{
|
||||
int luid = DF_INSN_LUID (reg0_use);
|
||||
|
||||
/* It might seem pointless to introduce an
|
||||
auto-inc if there's no subsequent use of
|
||||
reg_res (i.e., mem_insn.insn == NULL), but
|
||||
the next use might be in the next iteration
|
||||
of a loop, and it won't hurt if we make the
|
||||
change even if it's not needed. */
|
||||
if (mem_insn.insn
|
||||
&& luid > DF_INSN_LUID (mem_insn.insn))
|
||||
reg0_use = NULL;
|
||||
|
||||
rtx_insn *other_insn
|
||||
= get_next_ref (REGNO (inc_insn.reg_res), bb,
|
||||
reg_next_def);
|
||||
|
||||
if (other_insn && luid >= DF_INSN_LUID (other_insn))
|
||||
reg0_use = NULL;
|
||||
|
||||
other_insn
|
||||
= get_next_ref (REGNO (inc_insn.reg0), bb,
|
||||
reg_next_def);
|
||||
|
||||
if (other_insn && luid > DF_INSN_LUID (other_insn))
|
||||
reg0_use = NULL;
|
||||
}
|
||||
|
||||
mem_insn.insn = reg0_use;
|
||||
|
||||
if (mem_insn.insn
|
||||
&& find_address (&PATTERN (mem_insn.insn),
|
||||
inc_insn.reg0) == -1)
|
||||
{
|
||||
if (dump_file)
|
||||
dump_mem_insn (dump_file);
|
||||
|
|
Loading…
Add table
Reference in a new issue