This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
reload patch to set address_reloaded
- To: gcc-patches at gcc dot gnu dot org
- Subject: reload patch to set address_reloaded
- From: Aldy Hernandez <aldyh at redhat dot com>
- Date: Sat, 22 Jul 2000 23:11:31 -0700
I've noticed that a constraint in the Arm backend was failing to match
an instruction because address_reloaded[i] was not being set
correctly, except when the given operand was of type MEM.
The following patch adds another parameter to find_reloads_toplev()
which will be the place to put the result of find_reloads_address() if
it gets called.
The patch has been approved by Jim Wilson, and here's his additional
explanation:
We have a pseudo reg with reg_equiv_memory_loc set. find_reloads
calls find_reloads_toplev, which creates a MEM and passes it to
find_reloads_address to reload it. When find_reloads_toplev returns,
the operand is now
(mem:DI (plus:SI (plus:SI (fp) (const_int -16))
(const_int -8)))
The funniness here was done by LEGITIMIZE_RELOAD_ADDRESS which rewrote
the address because the offset was too big. There was a reload
scheduled to put (fp - 16) in a register, so this address is
effectively (reg - 8) after reloading. We then examine constraints
for the movdi pattern, and see the 'o' constraint. The operand does
not pass the offsettable_memref_p test because it is in a
non-canonical form. The operand does not pass the address_reloaded
test because the return value of find_reloads_address was thrown away.
Thus the operand is not recognized as valid for 'o' and we get a
reload. We noticed it because we were trying to modify arm.md, and
ended up getting a reload abort when the wrong alternative was chosen,
but without any change we get inefficient code here. In order to
avoid the problem, we have to pass the return value of
find_reloads_address back through find_reloads_toplev to find_reloads.
This gives the same result as when find_reloads calls
find_reloads_address directly.
I'm committing the patch shortly.
Cheers.
Aldy
2000-07-22 Aldy Hernandez <aldyh@redhat.com>
* reload.c (find_reloads_toplev): Add new parameter
"address_reloaded".
(find_reloads): Add new parameter to find_reloads_toplev calls.
Index: reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.113
diff -u -p -r1.113 reload.c
--- reload.c 2000/07/12 17:20:17 1.113
+++ reload.c 2000/07/23 05:53:08
@@ -258,7 +258,7 @@ static struct decomposition decompose PA
static int immune_p PARAMS ((rtx, rtx, struct decomposition));
static int alternative_allows_memconst PARAMS ((const char *, int));
static rtx find_reloads_toplev PARAMS ((rtx, int, enum reload_type, int,
- int, rtx));
+ int, rtx, int *));
static rtx make_memloc PARAMS ((rtx, int));
static int find_reloads_address PARAMS ((enum machine_mode, rtx *, rtx, rtx *,
int, enum reload_type, int, rtx));
@@ -2592,7 +2592,8 @@ find_reloads (insn, replace, ind_levels,
ind_levels,
set != 0
&& &SET_DEST (set) == recog_data.operand_loc[i],
- insn);
+ insn,
+ &address_reloaded[i]);
/* If we made a MEM to load (a part of) the stackslot of a pseudo
that didn't get a hard register, emit a USE with a REG_EQUAL
@@ -2616,7 +2617,8 @@ find_reloads (insn, replace, ind_levels,
a unary operator by reloading the operand. */
substed_operand[i] = recog_data.operand[i]
= find_reloads_toplev (recog_data.operand[i], i, address_type[i],
- ind_levels, 0, insn);
+ ind_levels, 0, insn,
+ &address_reloaded[i]);
else if (code == REG)
{
/* This is equivalent to calling find_reloads_toplev.
@@ -2644,7 +2646,8 @@ find_reloads (insn, replace, ind_levels,
of a constant equivalence was checked above. */
substed_operand[i] = recog_data.operand[i]
= find_reloads_toplev (recog_data.operand[i], i, address_type[i],
- ind_levels, 0, insn);
+ ind_levels, 0, insn,
+ &address_reloaded[i]);
}
/* If the operand is still a register (we didn't replace it with an
equivalent), get the preferred class to reload it into. */
@@ -3540,7 +3543,8 @@ find_reloads (insn, replace, ind_levels,
substed_operand[i] = recog_data.operand[i]
= find_reloads_toplev (force_const_mem (operand_mode[i],
recog_data.operand[i]),
- i, address_type[i], ind_levels, 0, insn);
+ i, address_type[i], ind_levels, 0, insn,
+ NULL);
if (alternative_allows_memconst (recog_data.constraints[i],
goal_alternative_number))
goal_alternative_win[i] = 1;
@@ -4169,16 +4173,21 @@ alternative_allows_memconst (constraint,
INSN, if nonzero, is the insn in which we do the reload. It is used
to determine if we may generate output reloads, and where to put USEs
- for pseudos that we have to replace with stack slots. */
+ for pseudos that we have to replace with stack slots.
+ ADDRESS_RELOADED. If nonzero, is a pointer to where we put the
+ result of find_reloads_address. */
+
static rtx
-find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn)
+find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn,
+ address_reloaded)
rtx x;
int opnum;
enum reload_type type;
int ind_levels;
int is_set_dest;
rtx insn;
+ int *address_reloaded;
{
register RTX_CODE code = GET_CODE (x);
@@ -4211,8 +4220,10 @@ find_reloads_toplev (x, opnum, type, ind
if (replace_reloads && recog_data.operand[opnum] != x)
emit_insn_before (gen_rtx_USE (VOIDmode, x), insn);
x = mem;
- find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
- opnum, type, ind_levels, insn);
+ i = find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
+ opnum, type, ind_levels, insn);
+ if (address_reloaded)
+ *address_reloaded = i;
}
}
return x;
@@ -4220,8 +4231,12 @@ find_reloads_toplev (x, opnum, type, ind
if (code == MEM)
{
rtx tem = x;
- find_reloads_address (GET_MODE (x), &tem, XEXP (x, 0), &XEXP (x, 0),
- opnum, type, ind_levels, insn);
+
+ i = find_reloads_address (GET_MODE (x), &tem, XEXP (x, 0), &XEXP (x, 0),
+ opnum, type, ind_levels, insn);
+ if (address_reloaded)
+ *address_reloaded = i;
+
return tem;
}
@@ -4326,7 +4341,8 @@ find_reloads_toplev (x, opnum, type, ind
if (fmt[i] == 'e')
{
rtx new_part = find_reloads_toplev (XEXP (x, i), opnum, type,
- ind_levels, is_set_dest, insn);
+ ind_levels, is_set_dest, insn,
+ address_reloaded);
/* If we have replaced a reg with it's equivalent memory loc -
that can still be handled here e.g. if it's in a paradoxical
subreg - we must make the change in a copy, rather than using