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