This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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);
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]