This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
addsi3_mips16 and frame pointer with LRA
- From: Matthew Fortune <Matthew dot Fortune at imgtec dot com>
- To: Richard Sandiford <rdsandiford at googlemail dot com>, Vladimir Makarov <vmakarov at redhat dot com>
- Cc: "gcc at gcc dot gnu dot org" <gcc at gcc dot gnu dot org>
- Date: Tue, 29 Oct 2013 13:43:03 +0000
- Subject: addsi3_mips16 and frame pointer with LRA
- Authentication-results: sourceware.org; auth=none
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. If the frame pointer is needed then this works well because $17 is used and fits the "d" constraint however when the frame pointer is omitted $sp has to be reloaded into a "d" register even though there is another alternative which it would directly match.
The fragment of the reload dump:
1 Matching alt: reject+=2
1 Non-pseudo reload: reject+=2
alt=4,overall=10,losers=1,rld_nregs=1
1 Matching alt: reject+=2
1 Non-pseudo reload: reject+=2
alt=5,overall=10,losers=1,rld_nregs=1
1 Non-pseudo reload: reject+=2
1 Non-pseudo reload: reject+=2
alt=7,overall=8,losers=1,rld_nregs=1
1 Non-pseudo reload: reject+=2
2 Non-pseudo reload: reject+=2
2 Non input pseudo reload: reject++
alt=8,overall=17,losers=2 -- refuse
Choosing alt 7 in insn 5: (0) d (1) d (2) O {*addsi3_mips16}
Creating newreg=198 from oldreg=78, assigning class M16_REGS to r198
And the end result is:
(insn 20 18 5 2 (set (reg/f:SI 2 $2 [198])
(reg/f:SI 29 $sp)) test.c:6 290 {*movsi_mips16}
(nil))
(insn 5 20 6 2 (set (reg:SI 4 $4)
(plus:SI (reg/f:SI 2 $2 [198])
(const_int 16 [0x10]))) test.c:6 13 {*addsi3_mips16}
(nil))
The only way I can currently see to get any direct usage of $sp in an add instruction would be to artificially reduce the permitted immediate range by 1 bit so that there is a single alternative that allows either "ks" or "d" with a 15bit immediate. I don't really want to do that though. I initially allowed $frame to be treated as per $sp but that led to an ICE when $frame was eliminated to $17 and the immediate was out of range.
Have I missed anything that would allow me to support the full immediate range in all cases?
Regards,
Matthew
Matthew Fortune
Leading Software Design Engineer, MIPS processor IP
Imagination Technologies Limited
t: +44 (0)113 242 9814
www.imgtec.com