------- Comment #5 from hubicka at gcc dot gnu dot org 2006-08-07 09:09 ------- The IA-64 problem shall be fixed by my patch for PR target/26655. The x86 problem is trickier. Reload is decided to merge all classes mentioned in given alternative, so "ad" is equivalent to "A", while recog.c is working the oposite way. The best way to fix it I can think of is to make reload ignore the classes that are too small to fit the register themselves. It does not fix the problem quite in general but at least deals with the x86 cases.
(in general one can have multiple register mode, join together two multiple reg classes but reload might place the result just on the boundary still making recog unhappy.) Better ideas? Honza Index: reload.c =================================================================== -cp -L reload.c (revision 115987) -L reload.c (working copy) .svn/text-base/reload.c.svn-base reload.c *** reload.c (revision 115987) --- reload.c (working copy) *************** find_reloads (rtx insn, int replace, int *** 2913,2918 **** --- 2913,2919 ---- operand. */ int constmemok = 0; int earlyclobber = 0; + enum reg_class class = NO_REGS; /* If the predicate accepts a unary operator, it means that we need to reload the operand, but do not do this for *************** find_reloads (rtx insn, int replace, int *** 3309,3314 **** --- 3310,3316 ---- /* Drop through into 'r' case. */ case 'r': + class = GENERAL_REGS; this_alternative[i] = (int) reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS]; goto reg; *************** find_reloads (rtx insn, int replace, int *** 3368,3384 **** break; } this_alternative[i] = (int) (reg_class_subunion [this_alternative[i]] ! [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]); reg: if (GET_MODE (operand) == BLKmode) break; winreg = 1; if (REG_P (operand) ! && reg_fits_class_p (operand, this_alternative[i], ! offset, GET_MODE (recog_data.operand[i]))) win = 1; break; } --- 3370,3409 ---- break; } + class = REG_CLASS_FROM_CONSTRAINT (c, p); + /* When class is too tiny to hold the operand, ignore it. + See PR21299. First quickly test if things looks slopy + and if they does try to look if register is really + available. */ + if (CLASS_MAX_NREGS (class, GET_MODE (recog_data.operand[i])) + > (int)reg_class_size [class]) + { + int regno; + enum machine_mode mode; + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) + if (TEST_HARD_REG_BIT (reg_class_contents[class], regno) + && HARD_REGNO_MODE_OK (regno, mode) + && (regno + hard_regno_nregs[regno][mode] + < FIRST_PSEUDO_REGISTER) + && TEST_HARD_REG_BIT + (reg_class_contents[class], + regno + hard_regno_nregs[regno][mode])) + break; + if (regno == FIRST_PSEUDO_REGISTER) + break; + } this_alternative[i] = (int) (reg_class_subunion [this_alternative[i]] ! [(int) class]); reg: if (GET_MODE (operand) == BLKmode) break; winreg = 1; if (REG_P (operand) ! && reg_fits_class_p (operand, class, ! offset, ! GET_MODE (recog_data.operand[i]))) win = 1; break; } -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21299