Krzysztof Parzyszek via llvm-dev
2015-Aug-12 14:43 UTC
[llvm-dev] ARM: Predicated returns considered analyzable?
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
James Molloy via llvm-dev
2015-Aug-13 07:46 UTC
[llvm-dev] ARM: Predicated returns considered analyzable?
Hi Krzystof, I'm not sure what the problem is here. For me, the function name "MBB::getFirstTerminator" you quoted implies that there may be more than one terminator. So it not returning the last terminator doesn't seem surprising at all. In fact, at this stage a conditional branch (not to a fallthrough block) is represented as a sequence of "B.COND; B", where both are terminators and one is predicated. I don't see how conditional returns are any different. Cheers, James On Wed, 12 Aug 2015 at 15:43 Krzysztof Parzyszek via llvm-dev < llvm-dev at lists.llvm.org> wrote:> 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 > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org http://llvm.cs.uiuc.edu > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150813/1c3a21a7/attachment.html>
Krzysztof Parzyszek via llvm-dev
2015-Aug-13 12:44 UTC
[llvm-dev] ARM: Predicated returns considered analyzable?
On 8/13/2015 2:46 AM, James Molloy wrote:> > I'm not sure what the problem is here. For me, the function name > "MBB::getFirstTerminator" you quoted implies that there may be more than > one terminator. So it not returning the last terminator doesn't seem > surprising at all.The problem is that the first terminator is followed by a non-terminator. The code snippet from the first email: t2CMPri %R1<kill>, 0, pred:14, pred:%noreg, %CPSR<imp-def> t2CMPri %R0<kill>, 3, pred:1, pred:%CPSR, %CPSR<imp-def>, %CPSR<imp-use,undef> (1) %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> (2) tBLXi pred:14, pred:%noreg, <ga:@bar>, <regmask>, %LR<imp-def,dead>, %SP<imp-use>, %SP<imp-def>, %R0<imp-def,dead> (3) %SP<def,tied1> = t2LDMIA_RET %SP<tied0>, pred:14, pred:%noreg, %R7<def>, %PC<def> (1) is a terminator (predicated), (2) is a non-terminator, (3) is a terminator again. -Krzysztof -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation