[cfe-dev] Question about 'CodeGenFunction::EmitGotoStmt'
jingu kang via cfe-dev
cfe-dev at lists.llvm.org
Thu Jul 1 03:45:28 PDT 2021
As an update, I can see the JumpThreading pass detects the branches
with cleanup. However, it fails to thread the branches because it
could cause irreducible loops...
It looks like we can thread them using the
'-jump-threading-across-loop-headers' option which is for testing.
The source code has lots of goto statements and it causes llvm's
LooInfo to detect weird loops. It seems I need to look at the weird
loops, which block the jump threading, before tackle the JumpThreading
pass.
Thanks
JinGu Kang
On Wed, 30 Jun 2021 at 21:56, jingu kang <jaykang10 at gmail.com> wrote:
>
> I appreciate your kind comments. Paul, Eli, John.
>
> I was looking at gcc's output from the same c code as below.
>
> <test+2580> ldr x14, [x12, #16]
> <test+2584> ubfiz x3, x11, #4, #32
> <test+2588> ldrh w6, [x14, x3]
> <test+2592> cbz w6, 0x4fe920 <test+480> --> goto destination
>
> destination:
> <test+480> ldr w2, [sp, #120]
> <test+484> cbnz w2, 0x4fe9b0 <test+624>
> <test+488> cbz w23, 0x501e7c <test+14140>
> <test+492> adrp x12, 0x697000 <PL_sv_consts+32>
> <test+496> sub x19, x19, #0x78
>
> As you can see on the above output, there is direct branch
> instruction. I tried to figure out what causes branches through the
> cleanup from the goto statement in clang/llvm.
> As Eli and John mentioned, it could be handled on jump threading or
> something like that. Let me check it.
>
> Thanks for good comments again,
> JinGu Kang
>
> 2021년 6월 30일 (수) 오후 7:12, John McCall <rjmccall at apple.com>님이 작성:
> >
> > On 30 Jun 2021, at 9:54, paul.robinson at sony.com wrote:
> > >> -----Original Message-----
> > >> From: jingu kang <jaykang10 at gmail.com>
> > >> Sent: Wednesday, June 30, 2021 9:00 AM
> > >> To: Robinson, Paul <paul.robinson at sony.com>; rjmccall at apple.com
> > >> Cc: Jingu.Kang at arm.com; cfe-dev at lists.llvm.org
> > >> Subject: Re: [cfe-dev] Question about 'CodeGenFunction::EmitGotoStmt'
> > >>
> > >> Additionally, I am looking at this case from perlbench of spec2017.
> > >>
> > >> 2021년 6월 30일 (수) 오후 12:49, jingu kang
> > >> <jaykang10 at gmail.com>님이 작성:
> > >>>
> > >>> Hi Paul
> > >>>
> > >>> Thanks for your kind explanation.
> > >>>
> > >>> I have investigated the situation more.
> > >>>
> > >>> clang pushes cleanup for lifetime.marker of local variable. When the
> > >>> cleanup is popped, the fixup for the goto statement is updated with
> > >>> the cleanup.
> > >>>
> > >>> From a spec benchmark, it looks like it causes more instructions as
> > >> below.
> > >>> For AArch64
> > >>> <test+11400> ldr x8, [x19, #16]
> > >>> <test+11404> lsl x9, x24, #4
> > >>> <test+11408> ldrh w8, [x8, x9]
> > >>> <test+11412> cbz w8, 0x34ce94 <test+12868> --> goto cleanup1
> > >>>
> > >>> cleanup1:
> > >>> <test+12868> mov w8, #0x8
> > >>> <test+12872> b 0x34d034 <test+13284> --> goto cleanup2
> > >>>
> > >>> cleanup2:
> > >>> <test+13284> cmp w8, #0x6
> > >>> <test+13288> b.eq 0x34edc8 <test+20856>
> > >>> <test+13292> cmp w8, #0x8
> > >>> <test+13296> b.eq 0x34edc8 <test+20856> --> goto destination
> > >>>
> > >>> destination:
> > >>> <test+20856> ldr w8, [sp, #392]
> > >>> <test+20860> tbz w8, #0, 0x34ee28 <test+20952>
> > >>> <test+20864> ldr x9, [sp, #296]
> > >>> <test+20868> cbz x9, 0x34f4f8 <test+22696>
> > >>>
> > >>> We could disable the lifetime.marker with the cmd option "-Xclang
> > >>> -disable-lifetime-markers" but it looks bad for llvm passes...
> > >>>
> > >>> At this moment, I am looking at below comment and code...
> > >>>
> > >>> /// A branch fixup. These are required when emitting a goto to a
> > >>> /// label which hasn't been emitted yet. The goto is optimistically
> > >>> /// emitted as a branch to the basic block for the label, and (if it
> > >>> /// occurs in a scope with non-trivial cleanups) a fixup is added to
> > >>> /// the innermost cleanup. When a (normal) cleanup is popped, any
> > >>> /// unresolved fixups in that scope are threaded through the
> > >>> cleanup.
> > >>> struct BranchFixup {
> > >>>
> > >>> void CodeGenFunction::PopCleanupBlock(bool
> > >>> FallthroughIsBranchThrough)
> > >>> ...
> > >>> // IV. Pop the cleanup and emit it.
> > >>> ...
> > >>> // Optimistically hope that any fixups will continue falling
> > >> through.
> > >>> for (unsigned I = FixupDepth, E =
> > >>> EHStack.getNumBranchFixups();
> > >>> I < E; ++I) {
> > >>> BranchFixup &Fixup = EHStack.getBranchFixup(I);
> > >>> if (!Fixup.Destination) continue;
> > >>> if (!Fixup.OptimisticBranchBlock) {
> > >>>
> > >> createStoreInstBefore(Builder.getInt32(Fixup.DestinationIndex),
> > >>> getNormalCleanupDestSlot(),
> > >>> Fixup.InitialBranch);
> > >>> Fixup.InitialBranch->setSuccessor(0, NormalEntry);
> > >>> }
> > >>> Fixup.OptimisticBranchBlock = NormalExit;
> > >>> }
> > >>>
> > >>> Is it possible to avoid adding a fixup to the cleanup with
> > >>> lifetime.marker or something like that? If I missed something,
> > >>> please
> > >>> let me know.
> >
> > We could treat branches through lifetime scopes differently, but
> > then we’d emit worse lifetime annotations, which could interfere
> > with optimization in other ways. I don’t know what problem you’re
> > seeing, but generally all the branch-fixup stuff is pretty simple
> > to eliminate with jump-folding. I don’t think this is a problem we
> > can solve in the frontend without major rearchitecture.
> >
> > John.
> >
> > >
> > > Unfortunately I am unfamiliar with the lifetime marker mechanism,
> > > so I cannot help you there.
> > > --paulr
> > >
> > >>>
> > >>> Thanks
> > >>> JinGu Kang
> > >>>
> > >>> 2021년 6월 29일 (화) 오후 6:40, <paul.robinson at sony.com>님이
> > >>> 작성:
> > >>>>
> > >>>>> From a spec benchmark, I have seen that the ‘goto’ statement
> > >>>>> goes to
> > >>>>> its destination through the cleanup function as below.
> > >>>>>
> > >>>>> void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
> > >>>>> // If this code is reachable then emit a stop point (if
> > >>>>> generating
> > >>>>> // debug info). We have to do this ourselves because we are on
> > >>>>> the
> > >>>>> // "simple" statement path.
> > >>>>> if (HaveInsertPoint())
> > >>>>> EmitStopPoint(&S);
> > >>>>> EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel()));
> > >>>>> }
> > >>>>>
> > >>>>> I guess we could emit the branch for the target directly. If
> > >> possible,
> > >>>>> can someone let me know why the goto statement has to go through
> > >>>>> the
> > >>>>> cleanup function please? If I missed something, please let me
> > >>>>> know.
> > >>>>
> > >>>> I haven't looked, but one reason would be if the 'goto' transfers
> > >>>> out
> > >>>> of a block that has a local variable with a destructor; the
> > >>>> destructor
> > >>>> has to run before control transfers to the 'goto' label. If there
> > >>>> are
> > >>>> no such local variables, there is no cleanup to do, and the 'goto'
> > >>>> becomes a simple branch.
> > >>>> --paulr
> > >>>>
More information about the cfe-dev
mailing list