This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch to prevent find_dummy_reload returning an invalid reg
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 15 Feb 2002 10:58:25 +0000
- Subject: Patch to prevent find_dummy_reload returning an invalid reg
This problem cropped up on an uncontributed port. I think the test
case will only fail on ports that:
- have HI-mode registers
- pass DI-sized structures in registers
- allow SI-mode values only in even registers
I can't find another port like that, so I guess this patch is really
only fixing a potential bug. It's really simple, though, and seems to
be changing unintentional behaviour, so I'd like to submit it anyway.
In the test case...
struct s
{
short i1;
long i2;
short i3;
};
struct s foo (struct s s)
{
s.i2++;
return s;
}
...i2 is passed in registers 1 & 2, and has to be moved to an even pair
before being incremented. Before reload, the increment pattern was:
(set (subreg:SI (reg:DI 0) 2)
(plus:SI (subreg:SI (reg:DI 0) 2)
(reg:SI 4)))
Reload (correctly) generates an in-out reload for:
(subreg:SI (reg:DI 0) 2)
push_reload passes it to find_dummy_reload, which has a check that an
input register is valid for its mode, but no corresponding check that
an output register is valid. In this case it would return:
(reg:SI 1)
and so no reload would actually be done.
Bootstrapped & regression tested on i686-pc-linux-gnu. OK to install?
Richard
* reload.c (find_dummy_reload): Check that an output register
is valid for its mode.
* gcc.c-torture/execute/20020215-1.c: New test.
Index: reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.176
diff -c -p -d -r1.176 reload.c
*** reload.c 2002/01/23 01:56:22 1.176
--- reload.c 2002/02/15 09:28:50
*************** find_dummy_reload (real_in, real_out, in
*** 1879,1884 ****
--- 1879,1885 ----
*inloc = const0_rtx;
if (regno < FIRST_PSEUDO_REGISTER
+ && HARD_REGNO_MODE_OK (regno, outmode)
&& ! refers_to_regno_for_reload_p (regno, regno + nwords,
PATTERN (this_insn), outloc))
{
*** /dev/null Tue Nov 14 21:44:43 2000
--- testsuite/gcc.c-torture/execute/20020215-1.c Wed Feb 13 17:14:49 2002
***************
*** 0 ****
--- 1,33 ----
+ /* Test failed on an architecture that:
+
+ - had 16-bit registers,
+ - passed 64-bit structures in registers,
+ - only allowed SImode values in even numbered registers.
+
+ Before reload, s.i2 in foo() was represented as:
+
+ (subreg:SI (reg:DI 0) 2)
+
+ find_dummy_reload would return (reg:SI 1) for the subreg reload,
+ despite that not being a valid register. */
+
+ struct s
+ {
+ short i1;
+ long i2;
+ short i3;
+ };
+
+ struct s foo (struct s s)
+ {
+ s.i2++;
+ return s;
+ }
+
+ int main ()
+ {
+ struct s s = foo ((struct s) { 1000, 2000L, 3000 });
+ if (s.i1 != 1000 || s.i2 != 2001L || s.i3 != 3000)
+ abort ();
+ exit (0);
+ }