This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Taking register width into account
- To: gcc-patches at gcc dot gnu dot org
- Subject: Taking register width into account
- From: Alexandre Oliva <aoliva at redhat dot com>
- Date: 20 Nov 2000 02:22:19 -0200
- Organization: GCC Team, Red Hat
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