summaryrefslogtreecommitdiff
path: root/gcc/lra-eliminations.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2017-12-20 12:53:35 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2017-12-20 12:53:35 +0000
commit73ca989cb823c3857336ada13446bc5c04cec3eb (patch)
treefc42b0612019e3b1e83163506a633ce5c28f801e /gcc/lra-eliminations.c
parentd05d755107df11e675a57ac4371fd0031c7d68a4 (diff)
poly_int: lra frame offsets
This patch makes LRA use poly_int64s rather than HOST_WIDE_INTs to store a frame offset (including in things like eliminations). 2017-12-20 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> gcc/ * lra-int.h (lra_reg): Change offset from int to poly_int64. (lra_insn_recog_data): Change sp_offset from HOST_WIDE_INT to poly_int64. (lra_eliminate_regs_1, eliminate_regs_in_insn): Change update_sp_offset from a HOST_WIDE_INT to a poly_int64. (lra_update_reg_val_offset, lra_reg_val_equal_p): Take the offset as a poly_int64 rather than an int. * lra-assigns.c (find_hard_regno_for_1): Handle poly_int64 offsets. (setup_live_pseudos_and_spill_after_risky_transforms): Likewise. * lra-constraints.c (equiv_address_substitution): Track offsets as poly_int64s. (emit_inc): Check poly_int_rtx_p instead of CONST_INT_P. (curr_insn_transform): Handle the new form of sp_offset. * lra-eliminations.c (lra_elim_table): Change previous_offset and offset from HOST_WIDE_INT to poly_int64. (print_elim_table, update_reg_eliminate): Update accordingly. (self_elim_offsets): Change from HOST_WIDE_INT to poly_int64_pod. (get_elimination): Update accordingly. (form_sum): Check poly_int_rtx_p instead of CONST_INT_P. (lra_eliminate_regs_1, eliminate_regs_in_insn): Change update_sp_offset from a HOST_WIDE_INT to a poly_int64. Handle poly_int64 offsets generally. (curr_sp_change): Change from HOST_WIDE_INT to poly_int64. (mark_not_eliminable, init_elimination): Update accordingly. (remove_reg_equal_offset_note): Return a bool and pass the new offset back by pointer as a poly_int64. * lra-remat.c (change_sp_offset): Take sp_offset as a poly_int64 rather than a HOST_WIDE_INT. (do_remat): Track offsets poly_int64s. * lra.c (lra_update_insn_recog_data, setup_sp_offset): Likewise. Co-Authored-By: Alan Hayward <alan.hayward@arm.com> Co-Authored-By: David Sherwood <david.sherwood@arm.com> From-SVN: r255876
Diffstat (limited to 'gcc/lra-eliminations.c')
-rw-r--r--gcc/lra-eliminations.c114
1 files changed, 57 insertions, 57 deletions
diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c
index 24a02ef1208..4f130a68e79 100644
--- a/gcc/lra-eliminations.c
+++ b/gcc/lra-eliminations.c
@@ -79,9 +79,9 @@ struct lra_elim_table
int to;
/* Difference between values of the two hard registers above on
previous iteration. */
- HOST_WIDE_INT previous_offset;
+ poly_int64 previous_offset;
/* Difference between the values on the current iteration. */
- HOST_WIDE_INT offset;
+ poly_int64 offset;
/* Nonzero if this elimination can be done. */
bool can_eliminate;
/* CAN_ELIMINATE since the last check. */
@@ -120,10 +120,14 @@ print_elim_table (FILE *f)
struct lra_elim_table *ep;
for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
- fprintf (f, "%s eliminate %d to %d (offset=" HOST_WIDE_INT_PRINT_DEC
- ", prev_offset=" HOST_WIDE_INT_PRINT_DEC ")\n",
- ep->can_eliminate ? "Can" : "Can't",
- ep->from, ep->to, ep->offset, ep->previous_offset);
+ {
+ fprintf (f, "%s eliminate %d to %d (offset=",
+ ep->can_eliminate ? "Can" : "Can't", ep->from, ep->to);
+ print_dec (ep->offset, f);
+ fprintf (f, ", prev_offset=");
+ print_dec (ep->previous_offset, f);
+ fprintf (f, ")\n");
+ }
}
/* Print info about elimination table to stderr. */
@@ -161,7 +165,7 @@ static struct lra_elim_table self_elim_table;
/* Offsets should be used to restore original offsets for eliminable
hard register which just became not eliminable. Zero,
otherwise. */
-static HOST_WIDE_INT self_elim_offsets[FIRST_PSEUDO_REGISTER];
+static poly_int64_pod self_elim_offsets[FIRST_PSEUDO_REGISTER];
/* Map: hard regno -> RTL presentation. RTL presentations of all
potentially eliminable hard registers are stored in the map. */
@@ -193,6 +197,7 @@ static rtx
form_sum (rtx x, rtx y)
{
machine_mode mode = GET_MODE (x);
+ poly_int64 offset;
if (mode == VOIDmode)
mode = GET_MODE (y);
@@ -200,10 +205,10 @@ form_sum (rtx x, rtx y)
if (mode == VOIDmode)
mode = Pmode;
- if (CONST_INT_P (x))
- return plus_constant (mode, y, INTVAL (x));
- else if (CONST_INT_P (y))
- return plus_constant (mode, x, INTVAL (y));
+ if (poly_int_rtx_p (x, &offset))
+ return plus_constant (mode, y, offset);
+ else if (poly_int_rtx_p (y, &offset))
+ return plus_constant (mode, x, offset);
else if (CONSTANT_P (x))
std::swap (x, y);
@@ -252,14 +257,14 @@ get_elimination (rtx reg)
{
int hard_regno;
struct lra_elim_table *ep;
- HOST_WIDE_INT offset;
lra_assert (REG_P (reg));
if ((hard_regno = REGNO (reg)) < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
return NULL;
if ((ep = elimination_map[hard_regno]) != NULL)
return ep->from_rtx != reg ? NULL : ep;
- if ((offset = self_elim_offsets[hard_regno]) == 0)
+ poly_int64 offset = self_elim_offsets[hard_regno];
+ if (known_eq (offset, 0))
return NULL;
/* This is an iteration to restore offsets just after HARD_REGNO
stopped to be eliminable. */
@@ -325,7 +330,7 @@ move_plus_up (rtx x)
rtx
lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
bool subst_p, bool update_p,
- HOST_WIDE_INT update_sp_offset, bool full_p)
+ poly_int64 update_sp_offset, bool full_p)
{
enum rtx_code code = GET_CODE (x);
struct lra_elim_table *ep;
@@ -335,7 +340,8 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
int copied = 0;
lra_assert (!update_p || !full_p);
- lra_assert (update_sp_offset == 0 || (!subst_p && update_p && !full_p));
+ lra_assert (known_eq (update_sp_offset, 0)
+ || (!subst_p && update_p && !full_p));
if (! current_function_decl)
return x;
@@ -360,7 +366,7 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
{
rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
- if (update_sp_offset != 0)
+ if (maybe_ne (update_sp_offset, 0))
{
if (ep->to_rtx == stack_pointer_rtx)
return plus_constant (Pmode, to, update_sp_offset);
@@ -387,20 +393,21 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
{
if ((ep = get_elimination (XEXP (x, 0))) != NULL)
{
- HOST_WIDE_INT offset;
+ poly_int64 offset, curr_offset;
rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
if (! update_p && ! full_p)
return gen_rtx_PLUS (Pmode, to, XEXP (x, 1));
- if (update_sp_offset != 0)
+ if (maybe_ne (update_sp_offset, 0))
offset = ep->to_rtx == stack_pointer_rtx ? update_sp_offset : 0;
else
offset = (update_p
? ep->offset - ep->previous_offset : ep->offset);
if (full_p && insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
offset -= lra_get_insn_recog_data (insn)->sp_offset;
- if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == -offset)
+ if (poly_int_rtx_p (XEXP (x, 1), &curr_offset)
+ && known_eq (curr_offset, -offset))
return to;
else
return gen_rtx_PLUS (Pmode, to,
@@ -449,7 +456,7 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
{
rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
- if (update_sp_offset != 0)
+ if (maybe_ne (update_sp_offset, 0))
{
if (ep->to_rtx == stack_pointer_rtx)
return plus_constant (Pmode,
@@ -464,7 +471,7 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
* INTVAL (XEXP (x, 1)));
else if (full_p)
{
- HOST_WIDE_INT offset = ep->offset;
+ poly_int64 offset = ep->offset;
if (insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
offset -= lra_get_insn_recog_data (insn)->sp_offset;
@@ -711,7 +718,7 @@ lra_eliminate_regs (rtx x, machine_mode mem_mode,
/* Stack pointer offset before the current insn relative to one at the
func start. RTL insns can change SP explicitly. We keep the
changes from one insn to another through this variable. */
-static HOST_WIDE_INT curr_sp_change;
+static poly_int64 curr_sp_change;
/* Scan rtx X for references to elimination source or target registers
in contexts that would prevent the elimination from happening.
@@ -725,6 +732,7 @@ mark_not_eliminable (rtx x, machine_mode mem_mode)
struct lra_elim_table *ep;
int i, j;
const char *fmt;
+ poly_int64 offset = 0;
switch (code)
{
@@ -738,7 +746,7 @@ mark_not_eliminable (rtx x, machine_mode mem_mode)
&& ((code != PRE_MODIFY && code != POST_MODIFY)
|| (GET_CODE (XEXP (x, 1)) == PLUS
&& XEXP (x, 0) == XEXP (XEXP (x, 1), 0)
- && CONST_INT_P (XEXP (XEXP (x, 1), 1)))))
+ && poly_int_rtx_p (XEXP (XEXP (x, 1), 1), &offset))))
{
int size = GET_MODE_SIZE (mem_mode);
@@ -752,7 +760,7 @@ mark_not_eliminable (rtx x, machine_mode mem_mode)
else if (code == PRE_INC || code == POST_INC)
curr_sp_change += size;
else if (code == PRE_MODIFY || code == POST_MODIFY)
- curr_sp_change += INTVAL (XEXP (XEXP (x, 1), 1));
+ curr_sp_change += offset;
}
else if (REG_P (XEXP (x, 0))
&& REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER)
@@ -802,9 +810,9 @@ mark_not_eliminable (rtx x, machine_mode mem_mode)
if (SET_DEST (x) == stack_pointer_rtx
&& GET_CODE (SET_SRC (x)) == PLUS
&& XEXP (SET_SRC (x), 0) == SET_DEST (x)
- && CONST_INT_P (XEXP (SET_SRC (x), 1)))
+ && poly_int_rtx_p (XEXP (SET_SRC (x), 1), &offset))
{
- curr_sp_change += INTVAL (XEXP (SET_SRC (x), 1));
+ curr_sp_change += offset;
return;
}
if (! REG_P (SET_DEST (x))
@@ -859,11 +867,11 @@ mark_not_eliminable (rtx x, machine_mode mem_mode)
#ifdef HARD_FRAME_POINTER_REGNUM
-/* Find offset equivalence note for reg WHAT in INSN and return the
- found elmination offset. If the note is not found, return NULL.
- Remove the found note. */
-static rtx
-remove_reg_equal_offset_note (rtx_insn *insn, rtx what)
+/* Search INSN's reg notes to see whether the destination is equal to
+ WHAT + C for some constant C. Return true if so, storing C in
+ *OFFSET_OUT and removing the reg note. */
+static bool
+remove_reg_equal_offset_note (rtx_insn *insn, rtx what, poly_int64 *offset_out)
{
rtx link, *link_loc;
@@ -873,12 +881,12 @@ remove_reg_equal_offset_note (rtx_insn *insn, rtx what)
if (REG_NOTE_KIND (link) == REG_EQUAL
&& GET_CODE (XEXP (link, 0)) == PLUS
&& XEXP (XEXP (link, 0), 0) == what
- && CONST_INT_P (XEXP (XEXP (link, 0), 1)))
+ && poly_int_rtx_p (XEXP (XEXP (link, 0), 1), offset_out))
{
*link_loc = XEXP (link, 1);
- return XEXP (XEXP (link, 0), 1);
+ return true;
}
- return NULL_RTX;
+ return false;
}
#endif
@@ -899,7 +907,7 @@ remove_reg_equal_offset_note (rtx_insn *insn, rtx what)
void
eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
- HOST_WIDE_INT update_sp_offset)
+ poly_int64 update_sp_offset)
{
int icode = recog_memoized (insn);
rtx old_set = single_set (insn);
@@ -940,28 +948,21 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
nonlocal goto. */
{
rtx src = SET_SRC (old_set);
- rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx);
-
+ poly_int64 offset = 0;
+
/* We should never process such insn with non-zero
UPDATE_SP_OFFSET. */
- lra_assert (update_sp_offset == 0);
+ lra_assert (known_eq (update_sp_offset, 0));
- if (off != NULL_RTX
- || src == ep->to_rtx
- || (GET_CODE (src) == PLUS
- && XEXP (src, 0) == ep->to_rtx
- && CONST_INT_P (XEXP (src, 1))))
+ if (remove_reg_equal_offset_note (insn, ep->to_rtx, &offset)
+ || strip_offset (src, &offset) == ep->to_rtx)
{
- HOST_WIDE_INT offset;
-
if (replace_p)
{
SET_DEST (old_set) = ep->to_rtx;
lra_update_insn_recog_data (insn);
return;
}
- offset = (off != NULL_RTX ? INTVAL (off)
- : src == ep->to_rtx ? 0 : INTVAL (XEXP (src, 1)));
offset -= (ep->offset - ep->previous_offset);
src = plus_constant (Pmode, ep->to_rtx, offset);
@@ -997,13 +998,13 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
currently support: a single set with the source or a REG_EQUAL
note being a PLUS of an eliminable register and a constant. */
plus_src = plus_cst_src = 0;
+ poly_int64 offset = 0;
if (old_set && REG_P (SET_DEST (old_set)))
{
if (GET_CODE (SET_SRC (old_set)) == PLUS)
plus_src = SET_SRC (old_set);
/* First see if the source is of the form (plus (...) CST). */
- if (plus_src
- && CONST_INT_P (XEXP (plus_src, 1)))
+ if (plus_src && poly_int_rtx_p (XEXP (plus_src, 1), &offset))
plus_cst_src = plus_src;
/* Check that the first operand of the PLUS is a hard reg or
the lowpart subreg of one. */
@@ -1021,7 +1022,6 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
if (plus_cst_src)
{
rtx reg = XEXP (plus_cst_src, 0);
- HOST_WIDE_INT offset = INTVAL (XEXP (plus_cst_src, 1));
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
@@ -1032,7 +1032,7 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
if (! replace_p)
{
- if (update_sp_offset == 0)
+ if (known_eq (update_sp_offset, 0))
offset += (ep->offset - ep->previous_offset);
if (ep->to_rtx == stack_pointer_rtx)
{
@@ -1051,7 +1051,7 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
the cost of the insn by replacing a simple REG with (plus
(reg sp) CST). So try only when we already had a PLUS
before. */
- if (offset == 0 || plus_src)
+ if (known_eq (offset, 0) || plus_src)
{
rtx new_src = plus_constant (GET_MODE (to_rtx), to_rtx, offset);
@@ -1239,7 +1239,7 @@ update_reg_eliminate (bitmap insns_with_changed_offsets)
if (lra_dump_file != NULL)
fprintf (lra_dump_file, " Using elimination %d to %d now\n",
ep1->from, ep1->to);
- lra_assert (ep1->previous_offset == 0);
+ lra_assert (known_eq (ep1->previous_offset, 0));
ep1->previous_offset = ep->offset;
}
else
@@ -1251,7 +1251,7 @@ update_reg_eliminate (bitmap insns_with_changed_offsets)
fprintf (lra_dump_file, " %d is not eliminable at all\n",
ep->from);
self_elim_offsets[ep->from] = -ep->offset;
- if (ep->offset != 0)
+ if (maybe_ne (ep->offset, 0))
bitmap_ior_into (insns_with_changed_offsets,
&lra_reg_info[ep->from].insn_bitmap);
}
@@ -1271,7 +1271,7 @@ update_reg_eliminate (bitmap insns_with_changed_offsets)
the usage for pseudos. */
if (ep->from != ep->to)
SET_HARD_REG_BIT (temp_hard_reg_set, ep->to);
- if (ep->previous_offset != ep->offset)
+ if (maybe_ne (ep->previous_offset, ep->offset))
{
bitmap_ior_into (insns_with_changed_offsets,
&lra_reg_info[ep->from].insn_bitmap);
@@ -1357,13 +1357,13 @@ init_elimination (void)
if (NONDEBUG_INSN_P (insn))
{
mark_not_eliminable (PATTERN (insn), VOIDmode);
- if (curr_sp_change != 0
+ if (maybe_ne (curr_sp_change, 0)
&& find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX))
stop_to_sp_elimination_p = true;
}
}
if (! frame_pointer_needed
- && (curr_sp_change != 0 || stop_to_sp_elimination_p)
+ && (maybe_ne (curr_sp_change, 0) || stop_to_sp_elimination_p)
&& bb->succs && bb->succs->length () != 0)
for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
if (ep->to == STACK_POINTER_REGNUM)