This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
HARD_REGNO_MODE_OK_FOR_CLASS Might Be Nice (tm)
- From: Bernd Jendrissek <berndj at prism dot co dot za>
- To: gcc at gcc dot gnu dot org
- Date: Wed, 21 Dec 2005 20:23:17 +0200
- Subject: HARD_REGNO_MODE_OK_FOR_CLASS Might Be Nice (tm)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
I think so, at least.
The problem I seem to be having is related to this bit of code in
reload1.c:find_reg():
for (j = 1; j < this_nregs; j++)
{
this_cost += spill_add_cost[regno + j];
if ((TEST_HARD_REG_BIT (not_usable, regno + j))
|| TEST_HARD_REG_BIT (used_by_other_reload, regno + j))
ok = 0;
even though the dominating if() already tests for
HARD_REGNO_MODE_OK (regno, rl->mode).
I've been playing with my 16-bit ix86 port again, and after a LONG while
I finally figured out that this was the cause of "can't find a register
in class BASE_REGS". It was because I had decided to expose the
registers as %al, %ah, ... %bl, %bh, ... instead of the customary %[e]ax
and friends. I had defined %bl as being in BASE_REGS, but %bh was not
(originally I had the regs as their 16-bit views), so the loop above was
rejecting 16-bit %bx in addresses because *all* of %bx (%bh in
particular) was not in BASE_REGS according to REG_CLASS_CONTENTS.
The simple solution was just to add %bh to BASE_REGS in
REG_CLASS_CONTENTS; that seemed to take care of the BASE_REGS problem
for me. On to the next cluster of problems. I finally got around %cl
vs %cx (for shift counts) by expanding the shift patterns first into,
for example,
(define_expand "ashlhi3"
[(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
(ashift:HI (match_operand:HI 1 "general_operand" "")
(match_operand:QI 2 "general_operand" "")))
(clobber (reg:CC FLAGS_REG))])]
...
first before recognizing them with define_insn'ed patterns; that seemed
to do the trick of forcing GCC to "know" that the ix86 shift counts have
no more than 8 bits of significance (less even, in fact).
Now I'm on the multiplication patterns, which are widening, for which I
have:
(define_insn "mulhisi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=a")
(mult:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0"))
(sign_extend:SI (match_operand:HI 2 "general_operand" "rm"))))
(clobber (reg:CC FLAGS_REG))]
...
Unfortunately now I'm having trouble getting GCC to allocate the SImode
result to the "a" register ('a' maps to AXREGS, consisting of %al and
%ah). The "a" register in SImode would in fact be the %dx:%ax pair. I
suppose I could introduce *yet another* constraint letter and yet
another class that would contain all of %ax and %dx, but would be used
only for forcing (reg:SI 0 [ al ]).
Which leads me to the subject. Would it be a win to have a macro
HARD_REGNO_MODE_OK_FOR_CLASS (REGNO, MODE, CLASS) which would be the
authoritative test for this loop in find_reg()? On my port, and I
imagine on many others too, I think a default
#ifndef HARD_REGNO_MODE_OK_FOR_CLASS
#define HARD_REGNO_MODE_OK_FOR_CLASS(REGNO, MODE, CLASS) \
HARD_REGNO_MODE_OK ((REGNO), (MODE))
#endif
would be okay.
Although... that loop in find_reg() probably exists for a reason.
>revision 1.185
>date: 1999/12/13 13:21:34; author: crux; state: Exp; lines: +356 -1045
>Simplify reload register allocation
Not very illuminating... so I rip the bits I don't like out of
not_usable (*) and see what happens. It turns out constrain_operands()
also wants the whole register set in which an operand lies to be in the
class specified by the constraint. So I change that (**), and now I'm a
little happier again, despite probably breaking other ports I'm not not
using.
(*) Like so:
diff -u -b -p -r1.483 reload1.c
- --- reload1.c 30 Sep 2005 18:09:56 -0000 1.483
+++ reload1.c 21 Dec 2005 18:01:50 -0000
@@ -1674,13 +1674,17 @@ find_reg (struct insn_chain *chain, int
int best_reg = -1;
unsigned int i, j;
int k;
+ HARD_REG_SET regclass;
HARD_REG_SET not_usable;
HARD_REG_SET used_by_other_reload;
reg_set_iterator rsi;
+ COPY_HARD_REG_SET (regclass, reg_class_contents[rl->class]);
COPY_HARD_REG_SET (not_usable, bad_spill_regs);
IOR_HARD_REG_SET (not_usable, bad_spill_regs_global);
+#if 0
IOR_COMPL_HARD_REG_SET (not_usable, reg_class_contents[rl->class]);
+#endif
CLEAR_HARD_REG_SET (used_by_other_reload);
for (k = 0; k < order; k++)
@@ -1697,6 +1701,7 @@ find_reg (struct insn_chain *chain, int
unsigned int regno = i;
if (! TEST_HARD_REG_BIT (not_usable, regno)
+ && TEST_HARD_REG_BIT (regclass, regno)
&& ! TEST_HARD_REG_BIT (used_by_other_reload, regno)
&& HARD_REGNO_MODE_OK (regno, rl->mode))
{
(**) And like so:
diff -u -b -p -r1.228 recog.c
- --- recog.c 23 Oct 2005 21:15:18 -0000 1.228
+++ recog.c 21 Dec 2005 18:15:45 -0000
@@ -2673,6 +2673,8 @@ reg_fits_class_p (rtx operand, enum reg_
{
int sr;
regno += offset;
+ if (TEST_HARD_REG_BIT (reg_class_contents[(int) cl], regno))
+ return 1;
for (sr = hard_regno_nregs[regno][mode] - 1;
sr > 0; sr--)
if (! TEST_HARD_REG_BIT (reg_class_contents[(int) cl],
Of course these patches almost certainly only appear to fix my
*immediate* problem. "The problem" being that I want to be able to tell
GCC two different things: "I want %dx to be part of an SImode group in
class AXDXREGS" and "but only %al is useable as an operand". Any ideas?
TIA & HAND
- --
There is a lot of food in a supermarket, too, but a supermarket isn't
the best place to hold a dinner party. -- Christopher Faylor
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
Comment: Please fetch my new key 804177F8 from hkp://wwwkeys.eu.pgp.net/
iD8DBQFDqZ11wyMv24BBd/gRArbEAJwOBD6KnO1c0PzqKzH4bqBfHBTJ+QCdHPKM
2d9aF7uTIFcYnGQPrEQeTTM=
=pbfi
-----END PGP SIGNATURE-----