This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFC [reload1] maybe share op_addr reloads
- From: DJ Delorie <dj at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 1 Dec 2005 21:36:29 -0500
- Subject: RFC [reload1] maybe share op_addr reloads
Another RFC - this one for reload. The m32c has two viable address
registers (there are three others, but they have limitations, only two
are general purpose). Sometimes, you need three address registers to
satisfy reload, mostly because the frame pointer has a limited
displacement. If you start with something like this:
a = *b;
*and* both a and b are on the stack, *and* they're too far away from
the frame pointer, you start with rtl like this:
(set (reg 101)
(mem (reg 101)))
but end up with rtl like this:
(set (mem (plus (reg fp) (const_int 160)))
(mem (mem (plus (reg fp) (const_int 170)))))
The three reloads are: (1) the first plus, (2) the second plus, and
(3) the nested mem.
(yes, I tried convincing reload to reload $fp to a separate register,
but it still reloaded the plus anyway.)
Anyway, my thought was if we can detect the case where one reload is
an address portion of another reload, we may be able to use the same
register for both reloads. The function "maybe_share_reloads_dj"
below is the start of detecting this case; it's probably naive at the
moment but it did point out that the rtx's aren't the same rtx in that
situation (hence the rtx_equal_p and not ==). It also doesn't check
to see if the register is only used for those two reloads, which I
assume needs to be added in the final version. Does this sound like a
reasonable approach?
Also, This patch dumps the failed reload information to the dump file,
which I can submit as an independent patch if this is an acceptable
change.
Index: reload1.c
===================================================================
--- reload1.c (revision 107742)
+++ reload1.c (working copy)
@@ -1674,6 +1674,28 @@ count_spilled_pseudo (int spilled, int s
spill_cost[r + nregs] -= REG_FREQ (reg);
}
+ /* The idea is, if we're reloading a MEM, and we've already reloaded
+ it's address, we can reuse that reload register if none of the
+ other reloads are also using it. */
+static int
+maybe_share_reloads_dj (int r1, int r2)
+{
+ rtx my_rtx = rld[r1].in;
+ rtx other_rtx = rld[r2].in;
+ if (GET_CODE (my_rtx) != MEM)
+ {
+ rtx tmp = my_rtx;
+ my_rtx = other_rtx;
+ other_rtx = tmp;
+ }
+ if (GET_CODE (my_rtx) == MEM
+ && rtx_equal_p(XEXP (my_rtx,0), other_rtx)
+ && rld[r1].opnum == rld[r2].opnum)
+ return 1;
+
+ return 0;
+}
+
/* Find reload register to use for reload number ORDER. */
static int
@@ -1830,6 +1852,8 @@ find_reload_regs (struct insn_chain *cha
&& rld[r].regno == -1)
if (! find_reg (chain, i))
{
+ if (dump_file)
+ fprintf(dump_file, "reload failure for reload %d\n", i);
spill_failure (chain->insn, rld[r].class);
failure = 1;
return;
@@ -1898,6 +1922,12 @@ spill_failure (rtx insn, enum reg_class
{
error ("unable to find a register to spill in class %qs",
reg_class_names[class]);
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "\nReloads for insn # %d\n", INSN_UID (insn));
+ debug_reload_to_stream (dump_file);
+ }
fatal_insn ("this is the insn:", insn);
}
}
@@ -4742,7 +4772,8 @@ reloads_conflict (int r1, int r2)
case RELOAD_FOR_OPERAND_ADDRESS:
return (r2_type == RELOAD_FOR_INPUT || r2_type == RELOAD_FOR_INSN
- || r2_type == RELOAD_FOR_OPERAND_ADDRESS);
+ || (r2_type == RELOAD_FOR_OPERAND_ADDRESS
+ && !maybe_share_reloads_dj (r1, r2)));
case RELOAD_FOR_OPADDR_ADDR:
return (r2_type == RELOAD_FOR_INPUT