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}}; @@ -6296,7 +6298,7 @@ ArgOffset += PtrByteSize; continue; } - // Copy the object to parameter save area if it can not be entirely passed + // Copy the object to parameter save area if it can not be entirely passed // by registers. // FIXME: we only need to copy the parts which need to be passed in // parameter save area. For the parts passed by registers, we don't need @@ -6929,7 +6931,7 @@ // // Low Memory +--------------------------------------------+ // SP +---> | Back chain | ---+ -// | +--------------------------------------------+ | +// | +--------------------------------------------+ | // | | Saved Condition Register | | // | +--------------------------------------------+ | // | | Saved Linkage Register | | @@ -7892,7 +7894,7 @@ return SDValue(); SDValue N1 = Op.getOperand(0); - EVT SrcVT = N1.getValueType(); + EVT SrcVT = N1.getValueType(); unsigned SrcSize = SrcVT.getSizeInBits(); if (SrcSize > 256 || !isPowerOf2_32(SrcVT.getVectorNumElements()) || !llvm::has_single_bit( 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 @@ -27,6 +27,15 @@ ; CHECK-NEXT: .cfi_def_cfa_offset 0 ; CHECK-NEXT: .cfi_restore w30 ; CHECK-NEXT: b bar + +; CHECK-LABEL: foo_tail: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: // %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: switch i32 %i, label %if.end3 [ i32 5, label %if.then @@ -46,6 +55,22 @@ ret void } +define void @foo_tail(i1 %i) { +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 @@ -20,6 +20,22 @@ ret void } +define void @foo_tail(i1 %i) { +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 } @@ -34,3 +50,10 @@ ; CHECK-NEXT: bl bar ; CHECK: .LBB0_4: @ %if.end3 ; CHECK: b bar + +; CHECK-LABEL: foo_tail: +; CHECK: @ %bb.0: @ %entry +; CHECK: @ %bb.1: @ %if.then +; CHECK-NEXT: b bar +; CHECK-NEXT: .LBB1_2: @ %if.else +; CHECK-NEXT: 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 @@ -20,6 +20,22 @@ ret void } +define void @foo_tail(i1 %i) { +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 } @@ -33,3 +49,9 @@ ; CHECK-NEXT: bl %plt(bar) ; CHECK: .LBB0_4: # %if.end3 ; CHECK: b %plt(bar) + +; CHECK-LABEL: foo_tail: +; CHECK: # %bb.1: # %if.then +; CHECK-NEXT: b %plt(bar) +; CHECK-NEXT: .LBB1_2: # %if.else +; CHECK-NEXT: 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 @@ -20,6 +20,22 @@ ret void } +define void @foo_tail(i1 %i) { +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 } @@ -33,3 +49,9 @@ ; CHECK-NEXT: bl bar ; CHECK: .LBB0_4: # %if.end3 ; CHECK-NEXT: bl bar + +; CHECK-LABEL: foo_tail: +; CHECK: # %bb.1: # %if.then +; CHECK-NEXT: bl bar +; CHECK: .LBB1_2: # %if.else +; 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 @@ -20,6 +20,22 @@ ret void } +define void @foo_tail(i1 %i) { +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 } @@ -33,3 +49,9 @@ ; CHECK-NEXT: call bar ; CHECK: .LBB0_4: # %if.end3 ; CHECK: tail bar + +; CHECK-LABEL: foo_tail: +; CHECK: # %bb.1: # %if.then +; CHECK-NEXT: tail bar@plt +; CHECK-NEXT: .LBB1_2: # %if.else +; CHECK-NEXT: tail bar@plt 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 @@ -20,6 +20,22 @@ ret void } +define void @foo_tail(i1 %i) { +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 } @@ -34,3 +50,9 @@ ; CHECK: brasl %r14, bar@PLT ; CHECK: .LBB0_4: # %if.end3 ; CHECK: jg bar@PLT + +; CHECK-LABEL: foo_tail: +; CHECK: # %bb.0: # %entry +; CHECK: jge bar@PLT +; CHECK-NEXT: .LBB1_1: # %if.then +; CHECK-NEXT: 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 @@ -20,6 +20,22 @@ ret void } +define void @foo_tail(i1 %i) { +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 } @@ -34,3 +50,9 @@ ; CHECK: callq bar ; CHECK: .LBB0_4: # %if.end3 ; CHECK: jmp bar # TAILCALL + +; CHECK-LABEL: foo_tail: +; CHECK: # %bb.0: # %entry +; CHECK: je bar # TAILCALL +; CHECK-NEXT: # %bb.1: # %if.then +; CHECK: jmp bar # TAILCALL