This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: LRA Stuck in a loop until aborting
- From: Richard Sandiford <rsandifo at linux dot vnet dot ibm dot com>
- To: pshortis at dataworx dot com dot au
- Cc: gcc at gcc dot gnu dot org
- Date: Thu, 17 Apr 2014 12:23:53 +0100
- Subject: Re: LRA Stuck in a loop until aborting
- Authentication-results: sourceware.org; auth=none
- References: <fc847518922f9baf6394b7982d05edce at dataworx dot com dot au> <534EFEB4 dot 40407 at dataworx dot com dot au> <534F01EB dot 30004 at redhat dot com> <534F43DA dot 8020700 at redhat dot com> <bbfcc64e17239e1fe902b76f3c9fb613 at dataworx dot com dot au>
pshortis@dataworx.com.au writes:
> On 17.04.2014 13:00, Jeff Law wrote:
>> On 04/16/14 16:19, Richard Henderson wrote:
>>>
>>> The register allocators only select an alternative for a move. They
>>> do not
>>> choose between N different patterns, separately describing loads,
>>> stores, and
>>> register-to-register movement.
>>>
>>> I'm fairly sure the documentation is quite clear on this, and GCC had
>>> required
>>> this since the beginning of time.
>> Correct on all counts; many an hour was spent reimplementing the PA
>> movXX patterns to satisfy that requirement.
>>
>> jeff
> I'm convinced :-) but...
>
> gcc internals info about movm is fairly comprehensive and I had taken
> care to ensure that I satisfied ...
>
> "The constraints on a âmovmâ must permit moving any hard register to
> any other hard register provided..."
>
> by providing a define_expand that assigns from a general_operand to a
> nonimmediate_operand and ...
>
> *ldsi instruction that can load from a general_operand to a
> nonimmediate_operand
> and a
> *storesi instruction that can store a register_operand to a
> memory_operand
Must admit I can't find where this is documented from a quick look.
Like Jeff and Richard, I could swear it was documented somewhere...
> In any case, out of curiosity and to convice myself I hadn't imagined
> the old reload pass handling this I reverted my recent fixes so that
> ldsi and storesi were once again as described above then repeated the
> exercise with full rtl dumping on and compared the rtl generated both
> with and without LRA enabled.
>
> In both cases the *.ira dmp produced the triggering ...
>
> (insn 57 61 58 5 (set (reg/v:SI 46 [orig:31 s ] [31])
> (reg/v:SI 31 [ s ])) 48 {*ldsi}
> (expr_list:REG_DEAD (reg/v:SI 31 [ s ])
> (nil)))
>
> The non-LRA reload rtl produced ..
>
> (insn 57 61 67 3 (set (reg:SI 1 r1)
> (mem/c:SI (plus:HI (reg/f:HI 3 r3)
> (const_int 4 [0x4])) [4 %sfp+4 S4 A16])) 48 {*ldsi}
> (nil))
> (insn 67 57 58 3 (set (mem/c:SI (plus:HI (reg/f:HI 3 r3)
> (const_int 4 [0x4])) [4 %sfp+4 S4 A16])
> (reg:SI 1 r1)) 47 {*storesi}
> (nil))
>
> While the LRA just got stuck in a loop unable to perform the reload of
> insn 57 that the old reload pass handled (or more correctly didn't choke
> over - it seems to be a redundant load/store).
>
> I'm really just highlighting this because I know the LRA is quite young
> and this might be a hint towards a deeper/other issues.
I think LRA just exploits the rule more than reload did. Reload would
look at the original instruction as a move between two MEMs, pick a hard
register for the destination of the *ldsi, then emit a store from the
hard register to the original MEM destination, on the assumption that
that move must be possible. (It would never actually match against
*storesi contraints, or even know that *storesi is the instruction
that would be used.) It was then down to pot luck whether that hard
register gets rused ("inherited") by later instructions that need
(reg/v:SI 46 [orig:31 s ] [31]).
LRA tries to take a more global view by introducing new pseudo registers
to represent as-yet unallocated reload registers. As you say, a consequence
of this is that you can see moves between two pseudo registers that match the
load pattern predicates but in which the destination is destined to be a MEM.
Thanks,
Richard