The following patch fixes building Ada on ppc64 with LRA (elimination
part changes which makes it behave as reload pass code). The patch also
fixes a failure on new test added for ppc recently. This change is in
very sensitive part of LRA and there is possibility that other targets
can be affected but I think the probability of this is very small.
The patch was successfully bootstrapped and tested on x86/x86-64 and ppc64.
Committed as rev. 203147.
2013-10-02 Vladimir Makarov <vmaka...@redhat.com>
* lra-constraints.c (process_alt_operand): Calculate scratch_p and
use it. Use smaller increase for scratch. Don't increase reject
for early clobber scratch.
* lra-eliminations.c (eliminate_regs_in_insn): Remove all insns
setting eliminated regs except setting fp from hfp.
(lra_eliminate): Check lra_insn_recog_data on NULL.
Index: ChangeLog
===================================================================
--- ChangeLog (revision 202721)
+++ ChangeLog (working copy)
@@ -1,3 +1,12 @@
+2013-10-02 Vladimir Makarov <vmaka...@redhat.com>
+
+ * lra-constraints.c (process_alt_operand): Calculate scratch_p and
+ use it. Use smaller increase for scratch. Don't increase reject
+ for early clobber scratch.
+ * lra-eliminations.c (eliminate_regs_in_insn): Remove all insns
+ setting eliminated regs except setting fp from hfp.
+ (lra_eliminate): Check lra_insn_recog_data on NULL.
+
2013-09-18 Vladimir Makarov <vmaka...@redhat.com>
* lra-constraints.c (need_for_all_save_p): Use macro
Index: config/aarch64/aarch64.c
===================================================================
--- config/aarch64/aarch64.c (revision 202626)
+++ config/aarch64/aarch64.c (working copy)
@@ -8151,6 +8151,16 @@ aarch64_vectorize_vec_perm_const_ok (enu
return ret;
}
+/* Return true if we use LRA instead of reload pass. */
+static bool
+aarch64_lra_p (void)
+{
+ return aarch64_lra_flag;
+}
+
+#undef TARGET_LRA_P
+#define TARGET_LRA_P aarch64_lra_p
+
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST aarch64_address_cost
Index: config/aarch64/aarch64.opt
===================================================================
--- config/aarch64/aarch64.opt (revision 202626)
+++ config/aarch64/aarch64.opt (working copy)
@@ -83,6 +83,10 @@ momit-leaf-frame-pointer
Target Report Save Var(flag_omit_leaf_frame_pointer) Init(1)
Omit the frame pointer in leaf functions
+mlra
+Target Report Save Var(aarch64_lra_flag) Init(0)
+Use LRA
+
mtls-dialect=
Target RejectNegative Joined Enum(tls_type) Var(aarch64_tls_dialect)
Init(TLS_DESCRIPTORS)
Specify TLS dialect
Index: lra-constraints.c
===================================================================
--- lra-constraints.c (revision 202721)
+++ lra-constraints.c (working copy)
@@ -1453,6 +1453,7 @@ process_alt_operands (int only_alternati
HARD_REG_SET this_alternative_set, this_costly_alternative_set;
bool this_alternative_match_win, this_alternative_win;
bool this_alternative_offmemok;
+ bool scratch_p;
enum machine_mode mode;
opalt_num = nalt * n_operands + nop;
@@ -1858,6 +1859,8 @@ process_alt_operands (int only_alternati
}
while ((p += len), c);
+ scratch_p = (operand_reg[nop] != NULL_RTX
+ && lra_former_scratch_p (REGNO (operand_reg[nop])));
/* Record which operands fit this alternative. */
if (win)
{
@@ -1878,14 +1881,17 @@ process_alt_operands (int only_alternati
}
else
{
- /* Prefer won reg to spilled pseudo under other equal
- conditions. */
- if (lra_dump_file != NULL)
- fprintf
- (lra_dump_file,
- " %d Non pseudo reload: reject++\n",
- nop);
- reject++;
+ /* Prefer won reg to spilled pseudo under other
+ equal conditions for possibe inheritance. */
+ if (! scratch_p)
+ {
+ if (lra_dump_file != NULL)
+ fprintf
+ (lra_dump_file,
+ " %d Non pseudo reload: reject++\n",
+ nop);
+ reject++;
+ }
if (in_class_p (operand_reg[nop],
this_costly_alternative, NULL))
{
@@ -1904,13 +1910,13 @@ process_alt_operands (int only_alternati
insns are generated for the scratches. So it
might cost something but probably less than old
reload pass believes. */
- if (lra_former_scratch_p (REGNO (operand_reg[nop])))
+ if (scratch_p)
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file,
- " %d Scratch win: reject+=3\n",
+ " %d Scratch win: reject+=2\n",
nop);
- reject += 3;
+ reject += 2;
}
}
}
@@ -2124,7 +2130,7 @@ process_alt_operands (int only_alternati
}
}
- if (early_clobber_p)
+ if (early_clobber_p && ! scratch_p)
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file,
Index: lra-eliminations.c
===================================================================
--- lra-eliminations.c (revision 202626)
+++ lra-eliminations.c (working copy)
@@ -808,69 +808,69 @@ eliminate_regs_in_insn (rtx insn, bool r
if (old_set != 0 && REG_P (SET_DEST (old_set))
&& (ep = get_elimination (SET_DEST (old_set))) != NULL)
{
- bool delete_p = replace_p;
-
+ for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate)
+ {
+ 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)
- {
- rtx src = SET_SRC (old_set);
- rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx);
-
- if (replace_p)
- {
- SET_DEST (old_set) = ep->to_rtx;
- lra_update_insn_recog_data (insn);
- return;
- }
- else if (off != NULL_RTX
- || src == ep->to_rtx
- || (GET_CODE (src) == PLUS
- && XEXP (src, 1) == ep->to_rtx
- && CONST_INT_P (XEXP (src, 1))))
- {
- HOST_WIDE_INT 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);
-
- /* First see if this insn remains valid when we make
- the change. If not, keep the INSN_CODE the same
- and let the constraint pass 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);
- /* Add offset note for future updates. */
- add_reg_note (insn, REG_EQUAL, src);
- return;
- }
-
-
- /* We can't delete this insn, but needn't process it
- since it won't be used unless something changes. */
- delete_p = false;
- }
+ 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. */
+ {
+ rtx src = SET_SRC (old_set);
+ rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx);
+
+ if (off != NULL_RTX
+ || src == ep->to_rtx
+ || (GET_CODE (src) == PLUS
+ && XEXP (src, 0) == ep->to_rtx
+ && CONST_INT_P (XEXP (src, 1))))
+ {
+ 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);
+
+ /* First see if this insn remains valid when we
+ make the change. If not, keep the INSN_CODE
+ the same and let the constraint pass 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);
+ /* Add offset note for future updates. */
+ add_reg_note (insn, REG_EQUAL, src);
+ return;
+ }
+ }
#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;
+
+ /* 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
@@ -1317,7 +1317,9 @@ lra_eliminate (bool final_p)
"Updating elimination of equiv for reg %d\n", i);
}
EXECUTE_IF_SET_IN_BITMAP (&insns_with_changed_offsets, 0, uid, bi)
- process_insn_for_elimination (lra_insn_recog_data[uid]->insn, final_p);
+ /* A dead insn can be deleted in process_insn_for_elimination. */
+ if (lra_insn_recog_data[uid] != NULL)
+ process_insn_for_elimination (lra_insn_recog_data[uid]->insn, final_p);
bitmap_clear (&insns_with_changed_offsets);
lra_eliminate_done:
Index: testsuite/gcc.target/i386/pr19398.c
===================================================================