> On 10/29/2013 09:43 AM, Matthew Fortune wrote:
> > 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?
> Sorry, I can not reproduce this using a test from PR58461 and patch enabling
> LRA for mips.

I'm afraid the patch in the bug report includes some incorrect workarounds 
which were my early attempt at resolving this issue.

> It is hard for me to say what is going on.  Elimination is done when we match
> hard reg against constraints.  May be elimination to hfp is rejected on some
> sub-pass and LRA don't try all alternatives after this.
> 
> Could you send me the test from which you got this dumps and what
> options did you use.  I can say more.   As I understand there should be
> no such problem.  If reload can do right think, LRA should do the same.

Attached is a reduced patch to enable LRA for mips16 with my workarounds 
omitted.

Also attached is frametest.c which should be compiled with -O2 -mips16. Add 
-mreload to compare with reload and you will see the extra instruction that LRA 
produces. When not omitting the frame pointer, LRA and reload behave the same.

Regards,
Matthew
> >

Attachment: mips16lra.patch
Description: mips16lra.patch

int g(int*);
int foo()
{
  int b = 1;
  g(&b);
  return b;
}

Reply via email to