The following patch fixes one testsuite regression on ppc64. LRA
removed two insns setting asm reg variable assigned to eliminable hard
regnos. It should be not done.
The patch was successfully bootstrapped on x86-64, ppc64, ia64.
Committed as rev. 189264.
2012-07-04 Vladimir Makarov <vmaka...@redhat.com>
* lra-eliminations.c (get_elimination): Change prototype.
(lra_eliminate_regs_1, eliminate_regs_in_insn): Transfer reg
instead of regno to get_elimination.
(lra_eliminate_reg_if_possible): Ditto.
Index: lra-eliminations.c
===================================================================
--- lra-eliminations.c (revision 189236)
+++ lra-eliminations.c (working copy)
@@ -225,18 +225,22 @@ lra_get_elimation_hard_regno (int hard_r
return ep->to;
}
-/* Return elimination which will be used for HARD_REGNO, NULL otherwise. */
+/* Return elimination which will be used for hard reg REG, NULL
+ otherwise. */
static struct elim_table *
-get_elimination (int hard_regno)
+get_elimination (rtx reg)
{
+ int hard_regno;
struct elim_table *ep;
HOST_WIDE_INT offset;
- if (hard_regno < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
+ 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)
return NULL;
- if ((ep = elimination_map[hard_regno]) != NULL
- || (offset = self_elim_offsets[hard_regno]) == 0)
- return ep;
/* This is an iteration to restore offsets just after HARD_REGNO
stopped to be eliminable. */
self_elim_table.from = self_elim_table.to = hard_regno;
@@ -268,7 +272,6 @@ lra_eliminate_regs_1 (rtx x, enum machin
{
enum rtx_code code = GET_CODE (x);
struct elim_table *ep;
- int regno;
rtx new_rtx;
int i, j;
const char *fmt;
@@ -295,24 +298,18 @@ lra_eliminate_regs_1 (rtx x, enum machin
return x;
case REG:
- regno = REGNO (x);
-
/* First handle the case where we encounter a bare register that
is eliminable. Replace it with a PLUS. */
- if (regno < FIRST_PSEUDO_REGISTER)
+ if ((ep = get_elimination (x)) != NULL)
{
- if ((ep = get_elimination (regno)) != NULL)
- {
- rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
-
- if (update_p)
- return plus_constant (Pmode, to,
- ep->offset - ep->previous_offset);
- else if (full_p)
- return plus_constant (Pmode, to, ep->offset);
- else
- return to;
- }
+ rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
+
+ if (update_p)
+ return plus_constant (Pmode, to, ep->offset - ep->previous_offset);
+ else if (full_p)
+ return plus_constant (Pmode, to, ep->offset);
+ else
+ return to;
}
return x;
@@ -333,11 +330,9 @@ lra_eliminate_regs_1 (rtx x, enum machin
case PLUS:
/* If this is the sum of an eliminable register and a constant, rework
the sum. */
- if (REG_P (XEXP (x, 0))
- && (regno = REGNO (XEXP (x, 0))) < FIRST_PSEUDO_REGISTER
- && CONSTANT_P (XEXP (x, 1)))
+ if (REG_P (XEXP (x, 0)) && CONSTANT_P (XEXP (x, 1)))
{
- if ((ep = get_elimination (regno)) != NULL)
+ if ((ep = get_elimination (XEXP (x, 0))) != NULL)
{
HOST_WIDE_INT offset;
rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
@@ -407,27 +402,25 @@ lra_eliminate_regs_1 (rtx x, enum machin
so that we have (plus (mult ..) ..). This is needed in order
to keep load-address insns valid. This case is pathological.
We ignore the possibility of overflow here. */
- if (REG_P (XEXP (x, 0))
- && (regno = REGNO (XEXP (x, 0))) < FIRST_PSEUDO_REGISTER
- && CONST_INT_P (XEXP (x, 1)))
- if ((ep = get_elimination (regno)) != NULL)
- {
- rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
-
- if (update_p)
- return
- plus_constant (Pmode,
- gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
- (ep->offset - ep->previous_offset)
- * INTVAL (XEXP (x, 1)));
- else if (full_p)
- return
- plus_constant (Pmode,
- gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
- ep->offset * INTVAL (XEXP (x, 1)));
- else
- return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
- }
+ if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))
+ && (ep = get_elimination (XEXP (x, 0))) != NULL)
+ {
+ rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
+
+ if (update_p)
+ return
+ plus_constant (Pmode,
+ gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
+ (ep->offset - ep->previous_offset)
+ * INTVAL (XEXP (x, 1)));
+ else if (full_p)
+ return
+ plus_constant (Pmode,
+ gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
+ ep->offset * INTVAL (XEXP (x, 1)));
+ else
+ return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
+ }
/* ... fall through ... */
@@ -769,7 +762,7 @@ eliminate_regs_in_insn (rtx insn, bool r
int icode = recog_memoized (insn);
rtx old_set = single_set (insn);
bool val;
- int i, regno;
+ int i;
rtx substed_operand[MAX_RECOG_OPERANDS];
rtx orig_operand[MAX_RECOG_OPERANDS];
struct elim_table *ep;
@@ -787,93 +780,88 @@ eliminate_regs_in_insn (rtx insn, bool r
return;
}
+ /* Check for setting an eliminable register. */
if (old_set != 0 && REG_P (SET_DEST (old_set))
- && (regno = REGNO (SET_DEST (old_set))) < FIRST_PSEUDO_REGISTER)
+ && (ep = get_elimination (SET_DEST (old_set))) != NULL)
{
- /* Check for setting an eliminable register. */
- if ((ep = get_elimination (regno)) != NULL)
- {
- bool delete_p = replace_p;
-
+ bool delete_p = replace_p;
+
#ifdef HARD_FRAME_POINTER_REGNUM
- /* If this is setting the frame pointer register to the
- hardware frame pointer register and this is an
- elimination that will be done (tested above), this insn
- is really adjusting the frame pointer downward to
- compensate for the adjustment done before a nonlocal
- goto. */
- if (ep->from == FRAME_POINTER_REGNUM
- && ep->to == HARD_FRAME_POINTER_REGNUM)
+ /* If this is setting the frame pointer register to the hardware
+ frame pointer register and this is an elimination that will
+ be done (tested above), this insn is really adjusting the
+ frame pointer downward to compensate for the adjustment done
+ before a nonlocal goto. */
+ if (ep->from == FRAME_POINTER_REGNUM
+ && ep->to == HARD_FRAME_POINTER_REGNUM)
+ {
+ if (replace_p)
{
- if (replace_p)
- {
- SET_DEST (old_set) = ep->to_rtx;
- lra_update_insn_recog_data (insn);
- return;
- }
- else
+ SET_DEST (old_set) = ep->to_rtx;
+ lra_update_insn_recog_data (insn);
+ return;
+ }
+ else
+ {
+ rtx base = SET_SRC (old_set);
+ HOST_WIDE_INT offset = 0;
+ rtx base_insn = insn;
+
+ while (base != ep->to_rtx)
{
- rtx base = SET_SRC (old_set);
- HOST_WIDE_INT offset = 0;
- rtx base_insn = insn;
-
- while (base != ep->to_rtx)
+ rtx prev_insn, prev_set;
+
+ if (GET_CODE (base) == PLUS && CONST_INT_P (XEXP (base, 1)))
{
- rtx prev_insn, prev_set;
-
- if (GET_CODE (base) == PLUS
- && CONST_INT_P (XEXP (base, 1)))
- {
- offset += INTVAL (XEXP (base, 1));
- base = XEXP (base, 0);
- }
- else if ((prev_insn = prev_nonnote_insn (base_insn)) != 0
- && (prev_set = single_set (prev_insn)) != 0
- && rtx_equal_p (SET_DEST (prev_set), base))
- {
- base = SET_SRC (prev_set);
- base_insn = prev_insn;
- }
- else
- break;
+ offset += INTVAL (XEXP (base, 1));
+ base = XEXP (base, 0);
}
-
- if (base == ep->to_rtx)
+ else if ((prev_insn = prev_nonnote_insn (base_insn)) != 0
+ && (prev_set = single_set (prev_insn)) != 0
+ && rtx_equal_p (SET_DEST (prev_set), base))
{
- rtx src;
-
- offset -= (ep->offset - ep->previous_offset);
- src = plus_constant (Pmode, ep->to_rtx, offset);
-
- /* First see if this insn remains valid when we
- make the change. If not, keep the INSN_CODE
- the same and let reload fit it up. */
- validate_change (insn, &SET_SRC (old_set), src, 1);
- validate_change (insn, &SET_DEST (old_set),
- ep->from_rtx, 1);
- if (! apply_change_group ())
- {
- SET_SRC (old_set) = src;
- SET_DEST (old_set) = ep->from_rtx;
- }
- lra_update_insn_recog_data (insn);
- return;
+ base = SET_SRC (prev_set);
+ base_insn = prev_insn;
}
+ else
+ break;
+ }
+
+ if (base == ep->to_rtx)
+ {
+ rtx src;
+
+ offset -= (ep->offset - ep->previous_offset);
+ src = plus_constant (Pmode, ep->to_rtx, offset);
+
+ /* First see if this insn remains valid when we
+ make the change. If not, keep the INSN_CODE
+ the same and let reload fit it up. */
+ validate_change (insn, &SET_SRC (old_set), src, 1);
+ validate_change (insn, &SET_DEST (old_set),
+ ep->from_rtx, 1);
+ if (! apply_change_group ())
+ {
+ SET_SRC (old_set) = src;
+ SET_DEST (old_set) = ep->from_rtx;
+ }
+ lra_update_insn_recog_data (insn);
+ return;
}
-
-
- /* We can't delete this insn, but needn't process it
- since it won't be used unless something changes. */
- delete_p = false;
}
-#endif
- /* This insn isn't serving a useful purpose. We delete it
- when REPLACE is set. */
- if (delete_p)
- lra_delete_dead_insn (insn);
- return;
+
+ /* We can't delete this insn, but needn't process it
+ since it won't be used unless something changes. */
+ delete_p = false;
}
+#endif
+
+ /* This insn isn't serving a useful purpose. We delete it
+ when REPLACE is set. */
+ if (delete_p)
+ lra_delete_dead_insn (insn);
+ return;
}
/* We allow one special case which happens to work on all machines we
@@ -909,8 +897,7 @@ eliminate_regs_in_insn (rtx insn, bool r
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
- if (REG_P (reg) && (regno = REGNO (reg)) < FIRST_PSEUDO_REGISTER
- && (ep = get_elimination (regno)) != NULL)
+ if (REG_P (reg) && (ep = get_elimination (reg)) != NULL)
{
rtx to_rtx = replace_p ? ep->to_rtx : ep->from_rtx;
@@ -1234,7 +1221,7 @@ lra_eliminate_reg_if_possible (rtx *loc)
/* Virtual registers are not allocatable. ??? */
|| ! TEST_HARD_REG_BIT (lra_no_alloc_regs, regno))
return;
- if ((ep = get_elimination (regno)) != NULL)
+ if ((ep = get_elimination (*loc)) != NULL)
*loc = ep->to_rtx;
}