| # RUN: llc -run-pass=branch-folder %s -o - | FileCheck %s |
| |
| # PR33980 |
| |
| # Don't form conditional tail calls when the original conditional branch has |
| # the same true and false destination. Otherwise, when we remove the tail call |
| # successor we will also remove the fallthrough successor from the CFG. |
| |
| # CHECK: body: | |
| # CHECK: bb.0.entry: |
| # CHECK: successors: %bb.1(0x40000000) |
| # CHECK: liveins: $edi |
| # CHECK: CMP32ri8 killed $edi, 2, implicit-def $eflags |
| # CHECK: TCRETURNdi64cc @mergeable_conditional_tailcall |
| |
| # This was the unconditional branch to a dead MBB that we left behind before |
| # this bug was fixed. |
| # CHECK-NOT: JMP_1 %bb.-1 |
| |
| --- | |
| ; ModuleID = 't.ll' |
| source_filename = "t.ll" |
| target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |
| target triple = "x86_64--linux" |
| |
| @static_local_guard = external global i64, align 8 |
| |
| ; Function Attrs: optsize |
| define void @f(i32 %arg) #0 { |
| entry: |
| switch i32 %arg, label %sw.epilog [ |
| i32 0, label %sw.bb |
| i32 1, label %sw.bb |
| i32 2, label %sw.bb2 |
| ] |
| |
| sw.bb: ; preds = %entry, %entry |
| %tmp = load atomic i8, i8* bitcast (i64* @static_local_guard to i8*) acquire, align 8 |
| %guard.uninitialized.i = icmp eq i8 %tmp, 0 |
| br i1 %guard.uninitialized.i, label %init.check.i, label %return, !prof !0 |
| |
| init.check.i: ; preds = %sw.bb |
| tail call void @initialize_static_local(i64* nonnull @static_local_guard) |
| ret void |
| |
| sw.bb2: ; preds = %entry |
| tail call void @mergeable_conditional_tailcall() |
| ret void |
| |
| sw.epilog: ; preds = %entry |
| tail call void @mergeable_conditional_tailcall() |
| ret void |
| |
| return: ; preds = %sw.bb |
| ret void |
| } |
| |
| declare void @mergeable_conditional_tailcall() |
| |
| declare void @initialize_static_local(i64*) |
| |
| ; Function Attrs: nounwind |
| declare void @llvm.stackprotector(i8*, i8**) #1 |
| |
| attributes #0 = { optsize } |
| attributes #1 = { nounwind } |
| |
| !0 = !{!"branch_weights", i32 1, i32 1048575} |
| |
| ... |
| --- |
| name: f |
| alignment: 0 |
| exposesReturnsTwice: false |
| legalized: false |
| regBankSelected: false |
| selected: false |
| tracksRegLiveness: true |
| registers: |
| liveins: |
| - { reg: '$edi', virtual-reg: '' } |
| frameInfo: |
| isFrameAddressTaken: false |
| isReturnAddressTaken: false |
| hasStackMap: false |
| hasPatchPoint: false |
| stackSize: 0 |
| offsetAdjustment: 0 |
| maxAlignment: 0 |
| adjustsStack: false |
| hasCalls: false |
| stackProtector: '' |
| maxCallFrameSize: 0 |
| hasOpaqueSPAdjustment: false |
| hasVAStart: false |
| hasMustTailInVarArgFunc: false |
| savePoint: '' |
| restorePoint: '' |
| fixedStack: |
| stack: |
| constants: |
| body: | |
| bb.0.entry: |
| successors: %bb.2(0x40000000), %bb.1(0x40000000) |
| liveins: $edi |
| |
| CMP32ri8 killed $edi, 2, implicit-def $eflags |
| JB_1 %bb.2, implicit $eflags |
| JMP_1 %bb.1 |
| |
| bb.1.entry: |
| successors: %bb.4(0x40000000), %bb.5(0x40000000) |
| liveins: $eflags |
| |
| JE_1 %bb.4, implicit killed $eflags |
| JMP_1 %bb.5 |
| |
| bb.2.sw.bb: |
| successors: %bb.3(0x00000800), %bb.6(0x7ffff800) |
| |
| $al = ACQUIRE_MOV8rm $rip, 1, $noreg, @static_local_guard, $noreg :: (volatile load acquire 1 from `i8* bitcast (i64* @static_local_guard to i8*)`, align 8) |
| TEST8rr killed $al, $al, implicit-def $eflags |
| JNE_1 %bb.6, implicit killed $eflags |
| JMP_1 %bb.3 |
| |
| bb.3.init.check.i: |
| dead $edi = MOV32ri64 @static_local_guard, implicit-def $rdi |
| TCRETURNdi64 @initialize_static_local, 0, csr_64, implicit $rsp, implicit $rdi |
| |
| bb.4.sw.bb2: |
| TCRETURNdi64 @mergeable_conditional_tailcall, 0, csr_64, implicit $rsp |
| |
| bb.5.sw.epilog: |
| TCRETURNdi64 @mergeable_conditional_tailcall, 0, csr_64, implicit $rsp |
| |
| bb.6.return: |
| RET 0 |
| |
| ... |