reload.c (can_reload_into): New function.

* reload.c (can_reload_into): New function.
	(push_reload): Use it.

From-SVN: r68542
This commit is contained in:
J"orn Rennecke 2003-06-26 20:07:23 +00:00 committed by Joern Rennecke
parent 6f8507b13f
commit 35d6034bcb
4 changed files with 243 additions and 1 deletions

View File

@ -1,3 +1,8 @@
2003-06-26 J"orn Rennecke <joern.rennecke@superh.com>
* reload.c (can_reload_into): New function.
(push_reload): Use it.
2003-06-26 Kazu Hirata <kazu@cs.umass.edu>
* config/h8300/h8300.c (compute_a_rotate_length): Fix the

View File

@ -840,6 +840,56 @@ reload_inner_reg_of_subreg (x, mode, output)
!= (int) HARD_REGNO_NREGS (REGNO (inner), GET_MODE (inner))));
}
/* Return nonzero if IN can be reloaded into REGNO with mode MODE without
requiring an extra reload register. The caller has already found that
IN contains some reference to REGNO, so check that we can produce the
new value in a single step. E.g. if we have
(set (reg r13) (plus (reg r13) (const int 1))), and there is an
instruction that adds one to a register, this should succeed.
However, if we have something like
(set (reg r13) (plus (reg r13) (const int 999))), and the constant 999
needs to be loaded into a register first, we need a separate reload
register.
Such PLUS reloads are generated by find_reload_address_part.
The out-of-range PLUS expressions are usually introduced in the instruction
patterns by register elimination and substituting pseudos without a home
by their function-invariant equivalences. */
static int
can_reload_into (rtx in, int regno, enum machine_mode mode)
{
rtx dst, test_insn;
int r = 0;
struct recog_data save_recog_data;
/* For matching constraints, we often get notional input reloads where
we want to use the original register as the reload register. I.e.
technically this is a non-optional input-output reload, but IN is
already a valid register, and has been chosen as the reload register.
Speed this up, since it trivially works. */
if (GET_CODE (in) == REG)
return 1;
/* To test MEMs properly, we'd have to take into account all the reloads
that are already scheduled, which can become quite complicated.
And since we've already handled address reloads for this MEM, it
should always succeed anyway. */
if (GET_CODE (in) == MEM)
return 1;
/* If we can make a simple SET insn that does the job, everything should
be fine. */
dst = gen_rtx_REG (mode, regno);
test_insn = make_insn_raw (gen_rtx_SET (VOIDmode, dst, in));
save_recog_data = recog_data;
if (recog_memoized (test_insn) >= 0)
{
extract_insn (test_insn);
r = constrain_operands (1);
}
recog_data = save_recog_data;
return r;
}
/* Record one reload that needs to be performed.
IN is an rtx saying where the data are to be found before this instruction.
OUT says where they must be stored after the instruction.
@ -1532,7 +1582,11 @@ push_reload (in, out, inloc, outloc, class,
regno + offs))
break;
if (offs == nregs)
if (offs == nregs
&& (! (refers_to_regno_for_reload_p
(regno, (regno + HARD_REGNO_NREGS (regno, inmode)),
in, (rtx *)0))
|| can_reload_into (in, regno, inmode)))
{
rld[i].reg_rtx = gen_rtx_REG (rel_mode, regno);
break;

View File

@ -1,5 +1,7 @@
2003-06-26 J"orn Rennecke <joern.rennecke@superh.com>
* gcc.c-torture/execute/multi-ix.c: New test.
* gcc.c-torture/execute/simd-4.c (main):
Added missing semicolon at end of union.

View File

@ -0,0 +1,181 @@
/* Test for a reload bug:
if you have a memory reference using the indexed addressing
mode, and the base address is a pseudo containing an address in the frame
and this pseudo fails to get a hard register, we end up with a double PLUS,
so the frame address gets reloaded. Now, when the index got a hard register,
and it dies in this insn, push_reload will consider that hard register as
a reload register, and disregrad overlaps with rld[n_reloads].in . That is
fine as long as the add can be done with a single insn, but when the
constant is so large that it has to be reloaded into a register first,
that clobbers the index. */
#include <stdarg.h>
#ifdef STACK_SIZE
#define CHUNK ((STACK_SIZE-100)/40/sizeof(int))
#else
#define CHUNK 500
#endif
void s(int, ...);
void z(int, ...);
void c(int, ...);
typedef int l[CHUNK];
void
f (int n)
{
int i;
l a0, a1, a2, a3, a4, a5, a6, a7, a8, a9;
l a10, a11, a12, a13, a14, a15, a16, a17, a18, a19;
l a20, a21, a22, a23, a24, a25, a26, a27, a28, a29;
l a30, a31, a32, a33, a34, a35, a36, a37, a38, a39;
int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
int i10, i11, i12, i13, i14, i15, i16, i17, i18, i19;
int i20, i21, i22, i23, i24, i25, i26, i27, i28, i29;
int i30, i31, i32, i33, i34, i35, i36, i37, i38, i39;
for (i = 0; i < n; i++)
{
s (40, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
a30, a31, a32, a33, a34, a35, a36, a37, a38, a39);
i0 = a0[0];
i1 = a1[0];
i2 = a2[0];
i3 = a3[0];
i4 = a4[0];
i5 = a5[0];
i6 = a6[0];
i7 = a7[0];
i8 = a8[0];
i9 = a9[0];
i10 = a10[0];
i11 = a11[0];
i12 = a12[0];
i13 = a13[0];
i14 = a14[0];
i15 = a15[0];
i16 = a16[0];
i17 = a17[0];
i18 = a18[0];
i19 = a19[0];
i20 = a20[0];
i21 = a21[0];
i22 = a22[0];
i23 = a23[0];
i24 = a24[0];
i25 = a25[0];
i26 = a26[0];
i27 = a27[0];
i28 = a28[0];
i29 = a29[0];
i30 = a30[0];
i31 = a31[0];
i32 = a32[0];
i33 = a33[0];
i34 = a34[0];
i35 = a35[0];
i36 = a36[0];
i37 = a37[0];
i38 = a38[0];
i39 = a39[0];
z (40, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
a30, a31, a32, a33, a34, a35, a36, a37, a38, a39);
a0[i0] = i0;
a1[i1] = i1;
a2[i2] = i2;
a3[i3] = i3;
a4[i4] = i4;
a5[i5] = i5;
a6[i6] = i6;
a7[i7] = i7;
a8[i8] = i8;
a9[i9] = i9;
a10[i10] = i10;
a11[i11] = i11;
a12[i12] = i12;
a13[i13] = i13;
a14[i14] = i14;
a15[i15] = i15;
a16[i16] = i16;
a17[i17] = i17;
a18[i18] = i18;
a19[i19] = i19;
a20[i20] = i20;
a21[i21] = i21;
a22[i22] = i22;
a23[i23] = i23;
a24[i24] = i24;
a25[i25] = i25;
a26[i26] = i26;
a27[i27] = i27;
a28[i28] = i28;
a29[i29] = i29;
a30[i30] = i30;
a31[i31] = i31;
a32[i32] = i32;
a33[i33] = i33;
a34[i34] = i34;
a35[i35] = i35;
a36[i36] = i36;
a37[i37] = i37;
a38[i38] = i38;
a39[i39] = i39;
c (40, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
a20, a21, a22, a23, a24, a25, a26, a27, a28, a29,
a30, a31, a32, a33, a34, a35, a36, a37, a38, a39);
}
}
int
main ()
{
f (1);
exit (0);
}
void s(int n, ...)
{
va_list list;
va_start (list, n);
while (--n)
{
int *a = va_arg (list, int *);
a[0] = n;
}
va_end (list);
}
void z(int n, ...)
{
va_list list;
va_start (list, n);
while (--n)
{
int *a = va_arg (list, int *);
bzero (a, sizeof (l));
}
va_end (list);
}
void c(int n, ...)
{
va_list list;
va_start (list, n);
while (--n)
{
int *a = va_arg (list, int *);
if (a[n] != n)
abort ();
}
va_end (list);
}