Working on LRA regression on ppc after the merge, I found that lo_sum
support improves code size significantly. Here the patch to support lo_sum.
The patch was successfully bootstrapped on x86/x86-64 and ppc.
Committed as rev. 189333.
2012-07-05 Vladimir Makarov <vmaka...@redhat.com>
* lra-constraints.c (extract_loc_address_regs): Process LO_SUM.
Remove assert.
(process_address): Try LO_SUM.
* config/rs6000/rs6000.c (legitimate_lo_sum_address_p): Permit
some toc references for LRA.
Index: lra-constraints.c
===================================================================
--- lra-constraints.c (revision 189273)
+++ lra-constraints.c (working copy)
@@ -371,6 +371,7 @@ extract_loc_address_regs (bool top_p, en
return;
case PLUS:
+ case LO_SUM:
/* When we have an address that is a sum, we must determine
whether registers are "base" or "index" regs. If there is a
sum of two registers, we must choose one to be the
@@ -399,11 +400,10 @@ extract_loc_address_regs (bool top_p, en
/* If this machine only allows one register per address, it
must be in the first operand. */
- if (MAX_REGS_PER_ADDRESS == 1)
+ if (MAX_REGS_PER_ADDRESS == 1 || code == LO_SUM)
{
- extract_loc_address_regs (false, mode, as, arg0_loc, false, PLUS,
+ extract_loc_address_regs (false, mode, as, arg0_loc, false, code,
code1, modify_p, ad);
- lra_assert (CONSTANT_P (arg1)); /* It should be a displacement. */
ad->disp_loc = arg1_loc;
}
/* If index and base registers are the same on this machine,
@@ -2600,12 +2600,41 @@ process_address (int nop, rtx *before, r
{
if (ad.index_reg_loc == NULL)
{
- /* disp => new_base */
+ int code = -1;
enum reg_class cl = base_reg_class (mode, as, SCRATCH, SCRATCH);
new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, "disp");
- lra_emit_move (new_reg, *ad.disp_loc);
- *ad.disp_loc = new_reg;
+#ifdef HAVE_lo_sum
+ {
+ rtx insn;
+ rtx last = get_last_insn ();
+
+ /* disp => lo_sum (new_base, disp) */
+ insn = emit_insn (gen_rtx_SET
+ (VOIDmode, new_reg,
+ gen_rtx_HIGH (Pmode, copy_rtx (*ad.disp_loc))));
+ code = recog_memoized (insn);
+ if (code >= 0)
+ {
+ rtx save = *ad.disp_loc;
+
+ *ad.disp_loc = gen_rtx_LO_SUM (Pmode, new_reg, *ad.disp_loc);
+ if (! valid_address_p (mode, *ad.disp_loc, as))
+ {
+ *ad.disp_loc = save;
+ code = -1;
+ }
+ }
+ if (code < 0)
+ delete_insns_since (last);
+ }
+#endif
+ if (code < 0)
+ {
+ /* disp => new_base */
+ lra_emit_move (new_reg, *ad.disp_loc);
+ *ad.disp_loc = new_reg;
+ }
}
else
{
Index: config/rs6000/rs6000.c
===================================================================
--- config/rs6000/rs6000.c (revision 189273)
+++ config/rs6000/rs6000.c (working copy)
@@ -5378,9 +5378,13 @@ legitimate_lo_sum_address_p (enum machin
if (TARGET_ELF || TARGET_MACHO)
{
+ bool toc_ok_p;
+
if (DEFAULT_ABI != ABI_AIX && DEFAULT_ABI != ABI_DARWIN && flag_pic)
return false;
- if (TARGET_TOC)
+ toc_ok_p = (lra_in_progress && TARGET_CMODEL != CMODEL_SMALL
+ && small_toc_ref (x, VOIDmode));
+ if (TARGET_TOC && ! toc_ok_p)
return false;
if (GET_MODE_NUNITS (mode) != 1)
return false;
@@ -5390,7 +5394,7 @@ legitimate_lo_sum_address_p (enum machin
&& (mode == DFmode || mode == DDmode))))
return false;
- return CONSTANT_P (x);
+ return CONSTANT_P (x) || toc_ok_p;
}
return false;