[RTL, ColdFire 24/63] Add support for a MODE_INDEX_REG_CLASS macro
Jeffrey Law
law@redhat.com
Tue Feb 27 20:44:00 GMT 2007
On Tue, 2007-02-27 at 16:50 +0000, Richard Sandiford wrote:
> Jeffrey Law <law@redhat.com> writes:
> > On Thu, 2007-02-22 at 19:08 -0800, Mark Mitchell wrote:
> >> I'm not quite sure if I know exactly whose court the ball is in at this
> >> point. If I understand correctly, Jeff is still unhappy with the patch,
> >> and Richard still thinks it's the right thing.
> > It's in my court. Current todo is to look at what Bernd did and why
> > and ponder how it plays with what Richard wants to do.
> >
> > I'd also like to see (and this is a new request) some code which
> > triggers these problems. I have a couple theories that I'd like to
> > poke at, but without triggering code that's going to be tough to do.
>
> OK. I can't remember off-hand which testcases failed without this,
> so here's a testcase specifically for it:
>
> --------------------------------------------------------------------
> void foo (float *x);
> float bar (void)
> {
> float x[0x5000];
> foo (x);
> return x[0x4000] + x[0];
> }
> --------------------------------------------------------------------
>
> Compile with -O2 -fomit-frame-pointer -mcpu=5485.
So after poking at this for a few minutes with the debugger, I'm really
interested in why you think fixing double_reg_address_ok to be indexed
by the mode of the memory reference is insufficient to fix this problem.
Basically we have this after lreg:
(insn 24 19 30 2 (set (reg/i:SF 0 %d0 [ <result> ])
(plus:SF (mem/s:SF (plus:SI (reg/f:SI 14 %a6)
(const_int -16384 [0xffffc000])) [3 x+65536 S4 A16])
(mem/s:SF (reg/f:SI 31) [3 x+0 S4 A16]))) 157 {addsf3_cf}
(nil)
(expr_list:REG_DEAD (reg/f:SI 31)
(nil)))
Which is a valid insn. Register elimination changes the memory
reference to something like:
(mem:SF (plus:SI (%sp) (const_int 65540))
Which is invalid because the offset is too big.
find_reloads_address comes along and realizes the address is
invalid and reloads the invalid displacement into an index register
creating the (invalid) reg+reg addressing mode via this code:
if (double_reg_address_ok)
{
/* Unshare the sum as well. */
*loc = ad = copy_rtx (ad);
/* Reload the displacement into an index reg.
We assume the frame pointer or arg pointer is a base reg.
*/
find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
INDEX_REG_CLASS, GET_MODE (ad),
opnum,
type, ind_levels);
return 0;
}
The problem, ISTM, is that reload assumes that if reg+reg addressing
is valid for QImode (per the double_reg_address_ok computation) then
reg+reg addressing must be valid for all modes which is clearly
incorrect for coldfire (as well as the PA). If we twiddle reload
to made double_reg_address_ok be mode dependent, then instead of
reloading the displacement into a register and creating a bogus
addressing mode, we'll instead reload the entire sum into a register
and use register indirect which is clearly valid. Note you'll still
get full use of indexed addressing in cases where your G_I_L_A
allows it.
I haven't really tested the attached patch except to verify that
the provided testcase no longer aborts and that the reloads we
generate for the problem insn look correct. However, I feel its a
much more correct solution than what you're trying to do.
Thoughts/Comments?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: DIFFS
Type: text/x-patch
Size: 4494 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20070227/3e80f119/attachment.bin>
More information about the Gcc-patches
mailing list