mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-25 07:44:06 +08:00
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:
parent
6f8507b13f
commit
35d6034bcb
@ -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
|
||||
|
56
gcc/reload.c
56
gcc/reload.c
@ -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;
|
||||
|
@ -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.
|
||||
|
||||
|
181
gcc/testsuite/gcc.c-torture/execute/multi-ix.c
Normal file
181
gcc/testsuite/gcc.c-torture/execute/multi-ix.c
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user