diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -7558,6 +7558,7 @@ if (IsCFICall) Ret.getNode()->setCFIType(CLI.CFIType->getZExtValue()); + DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge); DAG.addCallSiteInfo(Ret.getNode(), std::move(CSInfo)); return Ret; } diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp --- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -2171,6 +2171,9 @@ // Update call site info and delete the pseudo instruction TCRETURN. if (MI.isCandidateForCallSiteEntry()) MI.getMF()->moveCallSiteInfo(&MI, &*NewMI); + // Copy nomerge flag over to new instruction. + if (MI.getFlag(MachineInstr::NoMerge)) + NewMI->setFlag(MachineInstr::NoMerge); MBB.erase(MBBI); MBBI = NewMI; diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -2845,6 +2845,7 @@ if (isTailCall) { MF.getFrameInfo().setHasTailCall(); SDValue Ret = DAG.getNode(ARMISD::TC_RETURN, dl, NodeTys, Ops); + DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge); DAG.addCallSiteInfo(Ret.getNode(), std::move(CSInfo)); return Ret; } diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -2615,7 +2615,9 @@ if (IsTailCall) { MF.getFrameInfo().setHasTailCall(); - return DAG.getNode(LoongArchISD::TAIL, DL, NodeTys, Ops); + SDValue Ret = DAG.getNode(LoongArchISD::TAIL, DL, NodeTys, Ops); + DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge); + return Ret; } Chain = DAG.getNode(LoongArchISD::CALL, DL, NodeTys, Ops); diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -5622,7 +5622,9 @@ assert(CallOpc == PPCISD::TC_RETURN && "Unexpected call opcode for a tail call."); DAG.getMachineFunction().getFrameInfo().setHasTailCall(); - return DAG.getNode(CallOpc, dl, MVT::Other, Ops); + SDValue Ret = DAG.getNode(CallOpc, dl, MVT::Other, Ops); + DAG.addNoMergeSiteInfo(Ret.getNode(), CFlags.NoMerge); + return Ret; } std::array ReturnTypes = {{MVT::Other, MVT::Glue}}; diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -13677,7 +13677,9 @@ if (IsTailCall) { MF.getFrameInfo().setHasTailCall(); - return DAG.getNode(RISCVISD::TAIL, DL, NodeTys, Ops); + SDValue Ret = DAG.getNode(RISCVISD::TAIL, DL, NodeTys, Ops); + DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge); + return Ret; } Chain = DAG.getNode(RISCVISD::CALL, DL, NodeTys, Ops); diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1848,8 +1848,11 @@ // Emit the call. SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); - if (IsTailCall) - return DAG.getNode(SystemZISD::SIBCALL, DL, NodeTys, Ops); + if (IsTailCall) { + SDValue Ret = DAG.getNode(SystemZISD::SIBCALL, DL, NodeTys, Ops); + DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge); + return Ret; + } Chain = DAG.getNode(SystemZISD::CALL, DL, NodeTys, Ops); DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge); Glue = Chain.getValue(1); diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -4972,6 +4972,7 @@ if (IsCFICall) Ret.getNode()->setCFIType(CLI.CFIType->getZExtValue()); + DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge); DAG.addCallSiteInfo(Ret.getNode(), std::move(CSInfo)); return Ret; } diff --git a/llvm/test/CodeGen/AArch64/nomerge.ll b/llvm/test/CodeGen/AArch64/nomerge.ll --- a/llvm/test/CodeGen/AArch64/nomerge.ll +++ b/llvm/test/CodeGen/AArch64/nomerge.ll @@ -1,13 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=aarch64 -o - | FileCheck %s -define void @foo(i32 %i) uwtable { +define void @foo(i32 %i) nounwind { ; CHECK-LABEL: foo: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill -; CHECK-NEXT: .cfi_def_cfa_offset 16 -; CHECK-NEXT: .cfi_offset w30, -16 -; CHECK-NEXT: .cfi_remember_state ; CHECK-NEXT: cmp w0, #7 ; CHECK-NEXT: b.eq .LBB0_3 ; CHECK-NEXT: // %bb.1: // %entry @@ -16,16 +13,11 @@ ; CHECK-NEXT: // %bb.2: // %if.then ; CHECK-NEXT: bl bar ; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload -; CHECK-NEXT: .cfi_def_cfa_offset 0 -; CHECK-NEXT: .cfi_restore w30 ; CHECK-NEXT: b bar ; CHECK-NEXT: .LBB0_3: // %if.then2 -; CHECK-NEXT: .cfi_restore_state ; CHECK-NEXT: bl bar ; CHECK-NEXT: .LBB0_4: // %if.end3 ; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload -; CHECK-NEXT: .cfi_def_cfa_offset 0 -; CHECK-NEXT: .cfi_restore w30 ; CHECK-NEXT: b bar entry: switch i32 %i, label %if.end3 [ @@ -46,6 +38,29 @@ ret void } +define void @foo_tail(i1 %i) nounwind { +; CHECK-LABEL: foo_tail: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: tbz w0, #0, .LBB1_2 +; CHECK-NEXT: // %bb.1: // %if.then +; CHECK-NEXT: b bar +; CHECK-NEXT: .LBB1_2: // %if.else +; CHECK-NEXT: b bar +entry: + br i1 %i, label %if.then, label %if.else + +if.then: + tail call void @bar() #0 + br label %if.end + +if.else: + tail call void @bar() #0 + br label %if.end + +if.end: + ret void +} + declare void @bar() attributes #0 = { nomerge } diff --git a/llvm/test/CodeGen/ARM/nomerge.ll b/llvm/test/CodeGen/ARM/nomerge.ll --- a/llvm/test/CodeGen/ARM/nomerge.ll +++ b/llvm/test/CodeGen/ARM/nomerge.ll @@ -1,6 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 ; RUN: llc < %s -mtriple=arm -o - | FileCheck %s define void @foo(i32 %i) { +; CHECK-LABEL: foo: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: push {r11, lr} +; CHECK-NEXT: cmp r0, #7 +; CHECK-NEXT: beq .LBB0_3 +; CHECK-NEXT: @ %bb.1: @ %entry +; CHECK-NEXT: cmp r0, #5 +; CHECK-NEXT: bne .LBB0_4 +; CHECK-NEXT: @ %bb.2: @ %if.then +; CHECK-NEXT: bl bar +; CHECK-NEXT: pop {r11, lr} +; CHECK-NEXT: b bar +; CHECK-NEXT: .LBB0_3: @ %if.then2 +; CHECK-NEXT: bl bar +; CHECK-NEXT: .LBB0_4: @ %if.end3 +; CHECK-NEXT: pop {r11, lr} +; CHECK-NEXT: b bar entry: switch i32 %i, label %if.end3 [ i32 5, label %if.then @@ -20,17 +38,30 @@ ret void } +define void @foo_tail(i1 %i) { +; CHECK-LABEL: foo_tail: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: tst r0, #1 +; CHECK-NEXT: beq .LBB1_2 +; CHECK-NEXT: @ %bb.1: @ %if.then +; CHECK-NEXT: b bar +; CHECK-NEXT: .LBB1_2: @ %if.else +; CHECK-NEXT: b bar +entry: + br i1 %i, label %if.then, label %if.else + +if.then: + tail call void @bar() #0 + br label %if.end + +if.else: + tail call void @bar() #0 + br label %if.end + +if.end: + ret void +} + declare void @bar() attributes #0 = { nomerge } - -; CHECK-LABEL: foo: -; CHECK: @ %bb.0: @ %entry -; CHECK: @ %bb.1: @ %entry -; CHECK: @ %bb.2: @ %if.then -; CHECK-NEXT: bl bar -; CHECK: b bar -; CHECK: .LBB0_3: @ %if.then2 -; CHECK-NEXT: bl bar -; CHECK: .LBB0_4: @ %if.end3 -; CHECK: b bar diff --git a/llvm/test/CodeGen/LoongArch/nomerge.ll b/llvm/test/CodeGen/LoongArch/nomerge.ll --- a/llvm/test/CodeGen/LoongArch/nomerge.ll +++ b/llvm/test/CodeGen/LoongArch/nomerge.ll @@ -1,6 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 ; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s -define void @foo(i32 %i) { +define void @foo(i32 %i) nounwind { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: addi.d $sp, $sp, -16 +; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; CHECK-NEXT: bstrpick.d $a0, $a0, 31, 0 +; CHECK-NEXT: ori $a1, $zero, 7 +; CHECK-NEXT: beq $a0, $a1, .LBB0_3 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: ori $a1, $zero, 5 +; CHECK-NEXT: bne $a0, $a1, .LBB0_4 +; CHECK-NEXT: # %bb.2: # %if.then +; CHECK-NEXT: bl %plt(bar) +; CHECK-NEXT: b .LBB0_4 +; CHECK-NEXT: .LBB0_3: # %if.then2 +; CHECK-NEXT: bl %plt(bar) +; CHECK-NEXT: .LBB0_4: # %if.end3 +; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 16 +; CHECK-NEXT: b %plt(bar) entry: switch i32 %i, label %if.end3 [ i32 5, label %if.then @@ -20,16 +40,30 @@ ret void } +define void @foo_tail(i1 %i) nounwind { +; CHECK-LABEL: foo_tail: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: andi $a0, $a0, 1 +; CHECK-NEXT: beqz $a0, .LBB1_2 +; CHECK-NEXT: # %bb.1: # %if.then +; CHECK-NEXT: b %plt(bar) +; CHECK-NEXT: .LBB1_2: # %if.else +; CHECK-NEXT: b %plt(bar) +entry: + br i1 %i, label %if.then, label %if.else + +if.then: + tail call void @bar() #0 + br label %if.end + +if.else: + tail call void @bar() #0 + br label %if.end + +if.end: + ret void +} + declare void @bar() attributes #0 = { nomerge } - -; CHECK-LABEL: foo: -; CHECK: # %bb.0: # %entry -; CHECK: # %bb.1: # %entry -; CHECK: # %bb.2: # %if.then -; CHECK-NEXT: bl %plt(bar) -; CHECK: .LBB0_3: # %if.then2 -; CHECK-NEXT: bl %plt(bar) -; CHECK: .LBB0_4: # %if.end3 -; CHECK: b %plt(bar) diff --git a/llvm/test/CodeGen/PowerPC/nomerge.ll b/llvm/test/CodeGen/PowerPC/nomerge.ll --- a/llvm/test/CodeGen/PowerPC/nomerge.ll +++ b/llvm/test/CodeGen/PowerPC/nomerge.ll @@ -1,6 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 ; RUN: llc < %s -mtriple=powerpc -o - | FileCheck %s -define void @foo(i32 %i) { +define void @foo(i32 %i) nounwind { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mflr 0 +; CHECK-NEXT: stwu 1, -16(1) +; CHECK-NEXT: cmplwi 3, 7 +; CHECK-NEXT: stw 0, 20(1) +; CHECK-NEXT: beq 0, .LBB0_3 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: cmplwi 3, 5 +; CHECK-NEXT: bne 0, .LBB0_4 +; CHECK-NEXT: # %bb.2: # %if.then +; CHECK-NEXT: bl bar +; CHECK-NEXT: b .LBB0_4 +; CHECK-NEXT: .LBB0_3: # %if.then2 +; CHECK-NEXT: bl bar +; CHECK-NEXT: .LBB0_4: # %if.end3 +; CHECK-NEXT: bl bar +; CHECK-NEXT: lwz 0, 20(1) +; CHECK-NEXT: addi 1, 1, 16 +; CHECK-NEXT: mtlr 0 +; CHECK-NEXT: blr entry: switch i32 %i, label %if.end3 [ i32 5, label %if.then @@ -20,16 +42,39 @@ ret void } +define void @foo_tail(i1 %i) nounwind { +; CHECK-LABEL: foo_tail: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mflr 0 +; CHECK-NEXT: stwu 1, -16(1) +; CHECK-NEXT: andi. 3, 3, 1 +; CHECK-NEXT: stw 0, 20(1) +; CHECK-NEXT: bc 4, 1, .LBB1_2 +; CHECK-NEXT: # %bb.1: # %if.then +; CHECK-NEXT: bl bar +; CHECK-NEXT: b .LBB1_3 +; CHECK-NEXT: .LBB1_2: # %if.else +; CHECK-NEXT: bl bar +; CHECK-NEXT: .LBB1_3: # %if.end +; CHECK-NEXT: lwz 0, 20(1) +; CHECK-NEXT: addi 1, 1, 16 +; CHECK-NEXT: mtlr 0 +; CHECK-NEXT: blr +entry: + br i1 %i, label %if.then, label %if.else + +if.then: + tail call void @bar() #0 + br label %if.end + +if.else: + tail call void @bar() #0 + br label %if.end + +if.end: + ret void +} + declare void @bar() attributes #0 = { nomerge } - -; CHECK-LABEL: foo: -; CHECK: # %bb.0: # %entry -; CHECK: # %bb.1: # %entry -; CHECK: # %bb.2: # %if.then -; CHECK-NEXT: bl bar -; CHECK: .LBB0_3: # %if.then2 -; CHECK-NEXT: bl bar -; CHECK: .LBB0_4: # %if.end3 -; CHECK-NEXT: bl bar diff --git a/llvm/test/CodeGen/RISCV/nomerge.ll b/llvm/test/CodeGen/RISCV/nomerge.ll --- a/llvm/test/CodeGen/RISCV/nomerge.ll +++ b/llvm/test/CodeGen/RISCV/nomerge.ll @@ -1,6 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 ; RUN: llc < %s -mtriple=riscv64 -o - | FileCheck %s -define void @foo(i32 %i) { +define void @foo(i32 %i) nounwind { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: sext.w a0, a0 +; CHECK-NEXT: li a1, 7 +; CHECK-NEXT: beq a0, a1, .LBB0_3 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: li a1, 5 +; CHECK-NEXT: bne a0, a1, .LBB0_4 +; CHECK-NEXT: # %bb.2: # %if.then +; CHECK-NEXT: call bar@plt +; CHECK-NEXT: j .LBB0_4 +; CHECK-NEXT: .LBB0_3: # %if.then2 +; CHECK-NEXT: call bar@plt +; CHECK-NEXT: .LBB0_4: # %if.end3 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: tail bar@plt entry: switch i32 %i, label %if.end3 [ i32 5, label %if.then @@ -20,16 +40,30 @@ ret void } +define void @foo_tail(i1 %i) nounwind{ +; CHECK-LABEL: foo_tail: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: andi a0, a0, 1 +; CHECK-NEXT: beqz a0, .LBB1_2 +; CHECK-NEXT: # %bb.1: # %if.then +; CHECK-NEXT: tail bar@plt +; CHECK-NEXT: .LBB1_2: # %if.else +; CHECK-NEXT: tail bar@plt +entry: + br i1 %i, label %if.then, label %if.else + +if.then: + tail call void @bar() #0 + br label %if.end + +if.else: + tail call void @bar() #0 + br label %if.end + +if.end: + ret void +} + declare void @bar() attributes #0 = { nomerge } - -; CHECK-LABEL: foo: -; CHECK: # %bb.0: # %entry -; CHECK: # %bb.1: # %entry -; CHECK: # %bb.2: # %if.then -; CHECK-NEXT: call bar -; CHECK: .LBB0_3: # %if.then2 -; CHECK-NEXT: call bar -; CHECK: .LBB0_4: # %if.end3 -; CHECK: tail bar diff --git a/llvm/test/CodeGen/SystemZ/nomerge.ll b/llvm/test/CodeGen/SystemZ/nomerge.ll --- a/llvm/test/CodeGen/SystemZ/nomerge.ll +++ b/llvm/test/CodeGen/SystemZ/nomerge.ll @@ -1,6 +1,23 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 ; RUN: llc < %s -mtriple=s390x-linux-gnu -o - | FileCheck %s -define void @foo(i32 %i) { +define void @foo(i32 %i) nounwind { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stmg %r14, %r15, 112(%r15) +; CHECK-NEXT: aghi %r15, -160 +; CHECK-NEXT: cije %r2, 7, .LBB0_3 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: cijlh %r2, 5, .LBB0_4 +; CHECK-NEXT: # %bb.2: # %if.then +; CHECK-NEXT: brasl %r14, bar@PLT +; CHECK-NEXT: lmg %r14, %r15, 272(%r15) +; CHECK-NEXT: jg bar@PLT +; CHECK-NEXT: .LBB0_3: # %if.then2 +; CHECK-NEXT: brasl %r14, bar@PLT +; CHECK-NEXT: .LBB0_4: # %if.end3 +; CHECK-NEXT: lmg %r14, %r15, 272(%r15) +; CHECK-NEXT: jg bar@PLT entry: switch i32 %i, label %if.end3 [ i32 5, label %if.then @@ -20,17 +37,28 @@ ret void } +define void @foo_tail(i1 %i) nounwind { +; CHECK-LABEL: foo_tail: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: tmll %r2, 1 +; CHECK-NEXT: jge bar@PLT +; CHECK-NEXT: .LBB1_1: # %if.then +; CHECK-NEXT: jg bar@PLT +entry: + br i1 %i, label %if.then, label %if.else + +if.then: + tail call void @bar() #0 + br label %if.end + +if.else: + tail call void @bar() #0 + br label %if.end + +if.end: + ret void +} + declare void @bar() attributes #0 = { nomerge } - -; CHECK-LABEL: foo: -; CHECK: # %bb.0: # %entry -; CHECK: # %bb.1: # %entry -; CHECK: # %bb.2: # %if.then -; CHECK-NEXT: brasl %r14, bar@PLT -; CHECK: jg bar@PLT -; CHECK: .LBB0_3: # %if.then2 -; CHECK: brasl %r14, bar@PLT -; CHECK: .LBB0_4: # %if.end3 -; CHECK: jg bar@PLT diff --git a/llvm/test/CodeGen/X86/nomerge.ll b/llvm/test/CodeGen/X86/nomerge.ll --- a/llvm/test/CodeGen/X86/nomerge.ll +++ b/llvm/test/CodeGen/X86/nomerge.ll @@ -1,6 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 ; RUN: llc < %s -mtriple=x86_64 -o - | FileCheck %s -define void @foo(i32 %i) { +define void @foo(i32 %i) nounwind { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: cmpl $7, %edi +; CHECK-NEXT: je .LBB0_3 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: cmpl $5, %edi +; CHECK-NEXT: jne .LBB0_4 +; CHECK-NEXT: # %bb.2: # %if.then +; CHECK-NEXT: callq bar +; CHECK-NEXT: popq %rax +; CHECK-NEXT: jmp bar # TAILCALL +; CHECK-NEXT: .LBB0_3: # %if.then2 +; CHECK-NEXT: callq bar +; CHECK-NEXT: .LBB0_4: # %if.end3 +; CHECK-NEXT: popq %rax +; CHECK-NEXT: jmp bar # TAILCALL entry: switch i32 %i, label %if.end3 [ i32 5, label %if.then @@ -20,17 +38,28 @@ ret void } +define void @foo_tail(i1 %i) nounwind { +; CHECK-LABEL: foo_tail: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: je bar # TAILCALL +; CHECK-NEXT: # %bb.1: # %if.then +; CHECK-NEXT: jmp bar # TAILCALL +entry: + br i1 %i, label %if.then, label %if.else + +if.then: + tail call void @bar() #0 + br label %if.end + +if.else: + tail call void @bar() #0 + br label %if.end + +if.end: + ret void +} + declare dso_local void @bar() attributes #0 = { nomerge } - -; CHECK-LABEL: foo: -; CHECK: # %bb.0: # %entry -; CHECK: # %bb.1: # %entry -; CHECK: # %bb.2: # %if.then -; CHECK-NEXT: callq bar -; CHECK: jmp bar # TAILCALL -; CHECK: .LBB0_3: # %if.then2 -; CHECK: callq bar -; CHECK: .LBB0_4: # %if.end3 -; CHECK: jmp bar # TAILCALL