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]

Taking register width into account


Playing with vector types on a port whose FP registers are half as
wide as a word, I've noticed that reload wouldn't skip odd FP register
when loading/storing pairs of FP registers that correspond to the
words of such vector types.

I.e., reload would issue:

        (set (subreg:DF (reg:V... fpreg0) 0)
             (mem:DF (...)))
        (set (subreg:DF (reg:V... fpreg0) 1)
             (mem:DF (plus (...) (const_int 8)))
        (set (subreg:DF (reg:V... fpreg0) 2)
             (mem:DF (plus (...) (const_int 16))))

But alter_subreg() would transform this in:

        (set (reg:DF fpreg0) (mem:DF (...))
        (set (reg:DF fpreg1) (mem:DF (plus (...) (const_int 8))))
        (set (reg:DF fpreg2) (mem:DF (plus (...) (const_int 16))))
        ...

instead of:

        (set (reg:DF fpreg0) (mem:DF (...))
        (set (reg:DF fpreg2) (mem:DF (plus (...) (const_int 8))))
        (set (reg:DF fpreg4) (mem:DF (plus (...) (const_int 16))))
        ...

The reason is that alter_subreg didn't take into account the fact that
FP registers are half as wide as a word.  Unfortunately, this
information is not promptly available in GCC.  Here's a patch that
computes it based on HARD_REGNO_NREGS, the mode size and the word
size.  Bootstrapped on i686-pc-linux-gnu.  Ok to install?

BTW, I understand I could have used ALTER_HARD_SUBREG to work around
this problem, but why not fix it for all ports? :-)

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* final.c (alter_subreg): Multiply SUBREG_WORD by the number of
	registers per word.
	* flow.c (mark_set_1): Likewise.

Index: gcc/final.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/final.c,v
retrieving revision 1.148
diff -u -p -r1.148 final.c
--- gcc/final.c 2000/11/10 16:01:13 1.148
+++ gcc/final.c 2000/11/20 03:41:27
@@ -3165,7 +3165,9 @@ alter_subreg (x)
       regno = ALTER_HARD_SUBREG (GET_MODE (x), SUBREG_WORD (x),
 				 GET_MODE (y), REGNO (y));
 #else
-      regno = REGNO (y) + SUBREG_WORD (x);
+      regno = REGNO (y) + (SUBREG_WORD (x) * HARD_REGNO_NREGS (REGNO (y),
+							       GET_MODE (y))
+			   * UNITS_PER_WORD / GET_MODE_SIZE (GET_MODE (y)));
 #endif
       PUT_CODE (x, REG);
       REGNO (x) = regno;
Index: gcc/flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.350
diff -u -p -r1.350 flow.c
--- gcc/flow.c 2000/11/14 09:58:40 1.350
+++ gcc/flow.c 2000/11/20 03:41:28
@@ -4527,7 +4527,9 @@ mark_set_1 (pbi, code, reg, cond, insn, 
 	      regno_first = ALTER_HARD_SUBREG (outer_mode, SUBREG_WORD (reg),
 					       inner_mode, regno_first);
 #else
-	      regno_first += SUBREG_WORD (reg);
+	      regno_first += (SUBREG_WORD (reg)
+			      * HARD_REGNO_NREGS (REGNO (reg), inner_mode)
+			      * UNITS_PER_WORD / GET_MODE_SIZE (inner_mode));
 #endif
 	      regno_last = (regno_first
 			    + HARD_REGNO_NREGS (regno_first, outer_mode) - 1);

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

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