This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: addsi3_mips16 and frame pointer with LRA
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: Matthew Fortune <Matthew dot Fortune at imgtec dot com>
- Cc: Vladimir Makarov <vmakarov at redhat dot com>, "gcc\ at gcc dot gnu dot org" <gcc at gcc dot gnu dot org>
- Date: Tue, 29 Oct 2013 19:08:17 +0000
- Subject: Re: addsi3_mips16 and frame pointer with LRA
- Authentication-results: sourceware.org; auth=none
- References: <6D39441BF12EF246A7ABCE6654B02353417256 at LEMAIL01 dot le dot imgtec dot org>
Thanks for looking at this.
Matthew Fortune <Matthew.Fortune@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 */ \