Thanks for looking at this. Matthew Fortune <matthew.fort...@imgtec.com> writes: > Hi Richard/Vladimir, > > I believe I finally understand one of the issues with LRA and mips16 but > I can't see how to solve it. Take the following instruction: > > (insn 5 18 6 2 (set (reg:SI 4 $4) > (plus:SI (reg/f:SI 78 $frame) > (const_int 16 [0x10]))) test.c:6 13 {*addsi3_mips16} > (nil)) > > $frame will be eliminated to either $sp or the hard frame pointer, which > for mips16 is $17. The problem here is that there is no single > alternative that accepts either $sp or $17 because the supported > immediate range is different for $sp(ks) and $17(d). The "ks" > alternative is disregarded (presumably because there is no way to reload > into $sp if that ended up being necessary) and instead the "d" > alternative is chosen.
Ah. That's probably because "ks" is defined as a normal constraint rather than a register constraint. Doing it that way worked best with reload, because reload did the eliminations first and then matched the result. The instruction above would already have been converted into the $sp or $fp form before matching, so "ks" could simply check for a (reg STACK_POINTER_REGNUM). LRA instead keeps the original form around but converts the register during in_class_p: if (regno < FIRST_PSEUDO_REGISTER) { rtx final_reg = reg; rtx *final_loc = &final_reg; lra_eliminate_reg_if_possible (final_loc); return TEST_HARD_REG_BIT (reg_class_contents[cl], REGNO (*final_loc)); } But this only gets called when matching against a register class, so we'd need a register constraint. Does the patch below help? Thanks, Richard Index: gcc/config/mips/constraints.md =================================================================== --- gcc/config/mips/constraints.md 2013-05-25 17:00:02.849405240 +0100 +++ gcc/config/mips/constraints.md 2013-10-29 18:57:24.708435641 +0000 @@ -102,12 +102,9 @@ (define_constraint "kf" "@internal" (match_operand 0 "force_to_mem_operand")) -;; This is a normal rather than a register constraint because we can -;; never use the stack pointer as a reload register. -(define_constraint "ks" - "@internal" - (and (match_code "reg") - (match_test "REGNO (op) == STACK_POINTER_REGNUM"))) +(define_register_constraint "ks" + "SP_REG" + "@internal") ;; Integer constraints Index: gcc/config/mips/mips.c =================================================================== --- gcc/config/mips/mips.c 2013-10-27 18:49:14.034309187 +0000 +++ gcc/config/mips/mips.c 2013-10-29 18:56:48.784108194 +0000 @@ -624,7 +624,7 @@ const enum reg_class mips_regno_to_class M16_REGS, M16_REGS, LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS, T_REG, PIC_FN_ADDR_REG, LEA_REGS, LEA_REGS, - LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS, + LEA_REGS, SP_REG, LEA_REGS, LEA_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, Index: gcc/config/mips/mips.h =================================================================== --- gcc/config/mips/mips.h 2013-10-20 08:17:38.784934317 +0100 +++ gcc/config/mips/mips.h 2013-10-29 18:56:18.861835434 +0000 @@ -1863,6 +1863,7 @@ enum reg_class M16_T_REGS, /* mips16 registers plus T register */ PIC_FN_ADDR_REG, /* SVR4 PIC function address register */ V1_REG, /* Register $v1 ($3) used for TLS access. */ + SP_REG, /* Register $sp ($29) */ LEA_REGS, /* Every GPR except $25 */ GR_REGS, /* integer registers */ FP_REGS, /* floating point registers */ @@ -1900,6 +1901,7 @@ #define REG_CLASS_NAMES \ "M16_T_REGS", \ "PIC_FN_ADDR_REG", \ "V1_REG", \ + "SP_REG", \ "LEA_REGS", \ "GR_REGS", \ "FP_REGS", \ @@ -1940,6 +1942,7 @@ #define REG_CLASS_CONTENTS { 0x010300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* M16_T_REGS */ \ { 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* PIC_FN_ADDR_REG */ \ { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* V1_REG */ \ + { 0x20000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* V1_REG */ \ { 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* LEA_REGS */ \ { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* GR_REGS */ \ { 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* FP_REGS */ \