This is the mail archive of the gcc@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]

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-----


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