[llvm-dev] ARM: Predicated returns considered analyzable?

Krzysztof Parzyszek via llvm-dev llvm-dev at lists.llvm.org
Wed Aug 12 07:43:07 PDT 2015


Doh. I missed the list in my first reply...  Here's the replay of the 
conversation:



----- Renato:

On 10 August 2015 at 14:05, Krzysztof Parzyszek via llvm-dev
<llvm-dev at lists.llvm.org> wrote:
 > -->     %SP<def,tied1> = t2LDMIA_RET %SP<tied0>, pred:8, pred:%CPSR,
 > %R7<def>, %PC<def>, %SP<imp-use,undef>, %R7<imp-use,undef>,
 > %PC<imp-use,undef>
 >
 > Here the instruction t2LDMIA_RET is a terminator and yet it's 
followed by a
 > non-terminator tBLXi.  This looks wrong.  Does anyone have any 
comments on
 > this?

Isn't it because one of the predicates is CPSR, which means it's a
conditional instruction, so not really a terminator?

This lowers to the expected:

     str lr, [sp, #-4]!
     cmp r1, #0
     it ne
     cmpne r0, #3
     bhi .LBB0_2 <-- Turned into a conditional jump

     bl bar

.LBB0_2:
     ldr lr, [sp], #4
     bx lr

cheers,
--renato



----- Me:

On 8/11/2015 8:32 AM, Renato Golin wrote:
 > On 10 August 2015 at 14:05, Krzysztof Parzyszek via llvm-dev
 > <llvm-dev at lists.llvm.org> wrote:
 >> -->     %SP<def,tied1> = t2LDMIA_RET %SP<tied0>, pred:8, pred:%CPSR,
 >> %R7<def>, %PC<def>, %SP<imp-use,undef>, %R7<imp-use,undef>,
 >> %PC<imp-use,undef>
 >>
 >> Here the instruction t2LDMIA_RET is a terminator and yet it's 
followed by a
 >> non-terminator tBLXi.  This looks wrong.  Does anyone have any 
comments on
 >> this?
 >
 > Isn't it because one of the predicates is CPSR, which means it's a
 > conditional instruction, so not really a terminator?

It is marked as a terminator in the table-gen output (ARMGenInstrInfo.inc):

   { 2399,       5,      1,      4,      355, 
0|(1ULL<<MCID::Pseudo)|(1ULL<<MCID::Return)|(1ULL<<MCID::Barrier)|(1ULL<<MCID::MayLoad)|(1ULL<<MCID::Predicable)|(1ULL<<MCID::Terminator)|(1ULL<<MCID::Variadic)|(1ULL<<MCID::UnmodeledSideEffects)|(1ULL<<MCID::ExtraDefRegAllocReq), 
0x0ULL, nullptr, nullptr, OperandInfo52, -1 ,nullptr },  // Inst #2399 = 
t2LDMIA_RET


The test isTerminator only checks the MCInstrDesc:

   /// Various passes use this to insert code into the bottom of a basic 
block,
   /// but before control flow occurs.
   bool isTerminator() const { return Flags & (1 << MCID::Terminator); }


-Krzysztof



----- Renato:

On 11 August 2015 at 14:54, Krzysztof Parzyszek 
<kparzysz at codeaurora.org> wrote:
 > The test isTerminator only checks the MCInstrDesc:
 >
 >   /// Various passes use this to insert code into the bottom of a basic
 > block,
 >   /// but before control flow occurs.
 >   bool isTerminator() const { return Flags & (1 << MCID::Terminator); }

I'm guessing this only means "can be terminator". With conditional
terminators there really isn't a way to be certain, and with so many
instructions being conditional in Thumb, it's probably not a good idea
to try and model it perfectly.

Are you relying on isTerminator() for something and getting it wrong?

--renato



----- Me:

On 8/11/2015 9:10 AM, Renato Golin wrote:
 > On 11 August 2015 at 14:54, Krzysztof Parzyszek 
<kparzysz at codeaurora.org> wrote:
 >> The test isTerminator only checks the MCInstrDesc:
 >>
 >>    /// Various passes use this to insert code into the bottom of a basic
 >> block,
 >>    /// but before control flow occurs.
 >>    bool isTerminator() const { return Flags & (1 << MCID::Terminator); }
 >
 > I'm guessing this only means "can be terminator". With conditional
 > terminators there really isn't a way to be certain, and with so many
 > instructions being conditional in Thumb, it's probably not a good idea
 > to try and model it perfectly.
 >
 > Are you relying on isTerminator() for something and getting it wrong?

This came up in our local build that has some extra code in 
if-conversion to predicate a "diamond", but with both sides returning. 
There was an unrelated problem there, and while I was working on it I 
found out that we can still generate a basic block with a conditional 
return in the middle of it.  This is the late if-conversion, so it may 
be that some rules are relaxed at this point.
Still, MBB::getFirstTerminator would return the conditional return even 
though it may be followed by other instruction, and if it was to happen 
earlier in the optimization sequence, a lot of things could go wrong. It 
seems like this is not causing more trouble simply because there is no 
earlier optimization that could "exploit" this.

To answer your question---no, at this point nothing is catastrophically 
wrong, but it looks like a problem waiting to happen.

-Krzysztof



----- Renato:

On 11 August 2015 at 15:28, Krzysztof Parzyszek 
<kparzysz at codeaurora.org> wrote:
 > It seems like this is not causing more trouble simply because there is no
 > earlier optimization that could "exploit" this.

I see. This is worrying, but without actual hard data, it's hard to
know how to fix it.


 > To answer your question---no, at this point nothing is catastrophically
 > wrong, but it looks like a problem waiting to happen.

I'd add a comment to isTerminator() to make sure that people using it
know that it can back-fire if used with predicated code.

--renato



----- Me:

On 8/11/2015 9:36 AM, Renato Golin wrote:
 >
 > I'd add a comment to isTerminator() to make sure that people using it
 > know that it can back-fire if used with predicated code.

Hmm.  I'm not sure if this is a proper description.  A conditional 
branch is "predicated".  If we allow a conditional return to be in the 
middle of a basic block at a certain point, should we also allow (at 
least formally) conditional branches as well?  That would imply that 
there is a point in the optimization sequence after which having 
"exiting" instructions is allowed in the middle of the block.  Since 
having a conditional branch in the middle is not allowed during early 
optimizations, a predicated return should also be disallowed there.
Can such a point be formally defined (as in "after pass XYX, is it 
allowed to have predicated terminators in the middle of a block")?

-Krzysztof




-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
hosted by The Linux Foundation


More information about the llvm-dev mailing list