diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index baa2c8c0bcfb2..64cc43957e01f 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -176,6 +176,35 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, Features.push_back("+unaligned-vector-mem"); } + if (const Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) { + const StringRef CFProtection{A->getValue()}; + const bool CFProtectionBranch = + CFProtection == "full" || CFProtection == "branch"; + if (CFProtectionBranch) { + bool FuncSig; + if (const Arg *SA = + Args.getLastArg(options::OPT_mcf_branch_label_scheme_EQ)) { + const StringRef Scheme{SA->getValue()}; + if (Scheme == "unlabeled") { + FuncSig = false; + } else { + assert(Scheme == "func-sig" && + "-mcf-branch-label-scheme should be either `unlabeled` or " + "`func-sig`"); + FuncSig = true; + } + } else { + // `func-sig` is assumed if `-mcf-branch-label-scheme` is not given. + FuncSig = true; + } + + if (FuncSig) + Features.push_back("+zicfilp-func-sig"); + else + Features.push_back("+zicfilp-unlabeled"); + } + } + // Now add any that the user explicitly requested on the command line, // which may override the defaults. handleTargetFeaturesGroup(D, Triple, Args, Features, diff --git a/clang/test/Driver/riscv-features.c b/clang/test/Driver/riscv-features.c index 80dec2c71f985..8d02bb82abc30 100644 --- a/clang/test/Driver/riscv-features.c +++ b/clang/test/Driver/riscv-features.c @@ -85,3 +85,21 @@ // FUCHSIA-SAME: "-target-feature" "+zbb" // FUCHSIA-SAME: "-target-feature" "+zbs" +// RUN: %clang --target=riscv32 -fcf-protection=full -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG +// RUN: %clang --target=riscv32 -fcf-protection=full -mcf-branch-label-scheme=func-sig -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG +// RUN: %clang --target=riscv32 -fcf-protection=full -mcf-branch-label-scheme=unlabeled -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-UNLABELED +// RUN: %clang --target=riscv32 -fcf-protection=branch -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG +// RUN: %clang --target=riscv32 -fcf-protection=branch -mcf-branch-label-scheme=func-sig -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG +// RUN: %clang --target=riscv32 -fcf-protection=branch -mcf-branch-label-scheme=unlabeled -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-UNLABELED +// RUN: %clang --target=riscv64 -fcf-protection=full -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG +// RUN: %clang --target=riscv64 -fcf-protection=full -mcf-branch-label-scheme=func-sig -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG +// RUN: %clang --target=riscv64 -fcf-protection=full -mcf-branch-label-scheme=unlabeled -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-UNLABELED +// RUN: %clang --target=riscv64 -fcf-protection=branch -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG +// RUN: %clang --target=riscv64 -fcf-protection=branch -mcf-branch-label-scheme=func-sig -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-FUNC-SIG +// RUN: %clang --target=riscv64 -fcf-protection=branch -mcf-branch-label-scheme=unlabeled -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ZICFILP-UNLABELED +// ZICFILP-FUNC-SIG-NOT: "-target-feature" "-zicfilp-unlabeled" +// ZICFILP-FUNC-SIG: "-target-feature" "+zicfilp-func-sig" +// ZICFILP-FUNC-SIG-NOT: "-target-feature" "-zicfilp-unlabeled" +// ZICFILP-UNLABELED-NOT: "-target-feature" "-zicfilp-func-sig" +// ZICFILP-UNLABELED: "-target-feature" "+zicfilp-unlabeled" +// ZICFILP-UNLABELED-NOT: "-target-feature" "-zicfilp-func-sig" diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp index 5abb5461f74b3..065ff48a38ab4 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp @@ -134,6 +134,10 @@ void validate(const Triple &TT, const FeatureBitset &FeatureBits) { if (FeatureBits[RISCV::Feature32Bit] && FeatureBits[RISCV::Feature64Bit]) reportFatalUsageError("RV32 and RV64 can't be combined"); + if (FeatureBits[RISCV::FeatureZicfilpFuncSig] && + FeatureBits[RISCV::FeatureZicfilpUnlabeled]) + reportFatalUsageError( + "+zicfilp-func-sig and +zicfilp-unlabeled can't be combined"); } llvm::Expected> diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp index cb6117eb0917b..908b976d6e4bb 100644 --- a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp +++ b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp @@ -337,9 +337,7 @@ bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT, // Static chain parameter must not be passed in normal argument registers, // so we assign t2/t3 for it as done in GCC's // __builtin_call_with_static_chain - bool HasCFBranch = - Subtarget.hasStdExtZicfilp() && - MF.getFunction().getParent()->getModuleFlag("cf-protection-branch"); + bool HasCFBranch = Subtarget.hasZicfilpCFI(); // Normal: t2, Branch control flow protection: t3 const auto StaticChainReg = HasCFBranch ? RISCV::X28 : RISCV::X7; diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 171940e149815..2211cbf03a7db 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -170,8 +170,6 @@ def FeatureStdExtZicfilp def HasStdExtZicfilp : Predicate<"Subtarget->hasStdExtZicfilp()">, AssemblerPredicate<(all_of FeatureStdExtZicfilp), "'Zicfilp' (Landing pad)">; -def NoStdExtZicfilp : Predicate<"!Subtarget->hasStdExtZicfilp()">, - AssemblerPredicate<(all_of (not FeatureStdExtZicfilp))>; def FeatureStdExtZicfiss : RISCVExperimentalExtension<1, 0, "Shadow stack", @@ -1802,3 +1800,15 @@ def FeatureTaggedGlobals : SubtargetFeature<"tagged-globals", "AllowTaggedGlobals", "true", "Use an instruction sequence for taking the address of a global " "that allows a memory tag in the upper address bits">; + +// Zicfilp-based CFI +def FeatureZicfilpUnlabeled + : SubtargetFeature< + "zicfilp-unlabeled", "HasZicfilpUnlabeled", "true", + "Enforce forward-edge control-flow integrity with ZICFILP-unlabeled">; +def FeatureZicfilpFuncSig + : SubtargetFeature< + "zicfilp-func-sig", "HasZicfilpFuncSig", "true", + "Enforce forward-edge control-flow integrity with ZICFILP-func-sig">; +def HasZicfilpCFI : Predicate<"Subtarget->hasZicfilpCFI()">; +def HasNoZicfilpCFI : Predicate<"!Subtarget->hasZicfilpCFI()">; diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index e09e6fb5b26ee..d7d602b102de5 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -8528,10 +8528,7 @@ SDValue RISCVTargetLowering::lowerINIT_TRAMPOLINE(SDValue Op, // 28: // 36: - const bool HasCFBranch = - Subtarget.hasStdExtZicfilp() && - DAG.getMachineFunction().getFunction().getParent()->getModuleFlag( - "cf-protection-branch"); + const bool HasCFBranch = Subtarget.hasZicfilpCFI(); const unsigned StaticChainIdx = HasCFBranch ? 5 : 4; const unsigned StaticChainOffset = StaticChainIdx * 4; const unsigned FunctionAddressOffset = StaticChainOffset + 8; @@ -22953,11 +22950,10 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI, // Use software guarded branch for large code model non-indirect calls // Tail call to external symbol will have a null CLI.CB and we need another // way to determine the callsite type - bool NeedSWGuarded = false; - if (getTargetMachine().getCodeModel() == CodeModel::Large && - Subtarget.hasStdExtZicfilp() && - ((CLI.CB && !CLI.CB->isIndirectCall()) || CalleeIsLargeExternalSymbol)) - NeedSWGuarded = true; + const bool NeedSWGuarded = + getTargetMachine().getCodeModel() == CodeModel::Large && + Subtarget.hasZicfilpCFI() && + ((CLI.CB && !CLI.CB->isIndirectCall()) || CalleeIsLargeExternalSymbol); if (IsTailCall) { MF.getFrameInfo().setHasTailCall(); @@ -24546,8 +24542,8 @@ SDValue RISCVTargetLowering::expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const { - if (Subtarget.hasStdExtZicfilp()) { - // When Zicfilp enabled, we need to use software guarded branch for jump + if (Subtarget.hasZicfilpCFI()) { + // When Zicfilp CFI is used, we need to use software guarded branch for jump // table branch. SDValue Chain = Value; // Jump table debug info is only needed if CodeView is enabled. diff --git a/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp b/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp index 43621b8f0f33d..fdf4e43f94f3a 100644 --- a/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp +++ b/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp @@ -19,6 +19,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/Support/Error.h" #define DEBUG_TYPE "riscv-indrect-branch-tracking" #define PASS_NAME "RISC-V Indirect Branch Tracking" @@ -63,10 +64,16 @@ static void emitLpad(MachineBasicBlock &MBB, const RISCVInstrInfo *TII, bool RISCVIndirectBranchTracking::runOnMachineFunction(MachineFunction &MF) { const auto &Subtarget = MF.getSubtarget(); - const RISCVInstrInfo *TII = Subtarget.getInstrInfo(); - if (!Subtarget.hasStdExtZicfilp()) + if (!Subtarget.hasZicfilpCFI()) return false; + const RISCVInstrInfo *TII = Subtarget.getInstrInfo(); + + if (Subtarget.getZicfilpLabelScheme() != + RISCVSubtarget::ZicfilpLabelSchemeEnum::Unlabeled) + reportFatalUsageError( + "only cf-branch-label-scheme=unlabeled is supported for now"); + uint32_t FixedLabel = 0; if (PreferredLandingPadLabel.getNumOccurrences() > 0) { if (!isUInt<20>(PreferredLandingPadLabel)) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 8bd383033f11c..610edf126f0c5 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1746,12 +1746,12 @@ let isBarrier = 1, isBranch = 1, isTerminator = 1 in def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>, PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>; -let Predicates = [NoStdExtZicfilp], +let Predicates = [HasNoZicfilpCFI], isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in def PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>, PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; -let Predicates = [HasStdExtZicfilp], +let Predicates = [HasZicfilpCFI], isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in { def PseudoBRINDNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1, simm12:$imm12), []>, PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; @@ -1761,7 +1761,7 @@ def PseudoBRINDX7 : Pseudo<(outs), (ins GPRX7:$rs1, simm12:$imm12), []>, // For Zicfilp, need to avoid using X7/T2 for indirect branches which need // landing pad. -let Predicates = [HasStdExtZicfilp] in { +let Predicates = [HasZicfilpCFI] in { def : Pat<(brind GPRJALRNonX7:$rs1), (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, 0)>; def : Pat<(brind (add GPRJALRNonX7:$rs1, simm12:$imm12)), (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, simm12:$imm12)>; @@ -1771,7 +1771,7 @@ def : Pat<(riscv_sw_guarded_brind (add GPRX7:$rs1, simm12:$imm12)), (PseudoBRINDX7 GPRX7:$rs1, simm12:$imm12)>; } -let Predicates = [NoStdExtZicfilp] in { +let Predicates = [HasNoZicfilpCFI] in { def : Pat<(brind GPRJALR:$rs1), (PseudoBRIND GPRJALR:$rs1, 0)>; def : Pat<(brind (add GPRJALR:$rs1, simm12:$imm12)), (PseudoBRIND GPRJALR:$rs1, simm12:$imm12)>; @@ -1808,11 +1808,11 @@ let Predicates = [HasStdExtSmrnmi] in def : Pat<(riscv_mnret_glue), (MNRET)>; let isCall = 1, Defs = [X1] in { -let Predicates = [NoStdExtZicfilp] in +let Predicates = [HasNoZicfilpCFI] in def PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1), [(riscv_call GPRJALR:$rs1)]>, PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; -let Predicates = [HasStdExtZicfilp] in { +let Predicates = [HasZicfilpCFI] in { def PseudoCALLIndirectNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1), [(riscv_call GPRJALRNonX7:$rs1)]>, PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; @@ -1837,11 +1837,11 @@ def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), [], Sched<[WriteIALU, WriteJalr, ReadJalr]>; let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in { -let Predicates = [NoStdExtZicfilp] in +let Predicates = [HasNoZicfilpCFI] in def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1), [(riscv_tail GPRTC:$rs1)]>, PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; -let Predicates = [HasStdExtZicfilp] in { +let Predicates = [HasZicfilpCFI] in { def PseudoTAILIndirectNonX7 : Pseudo<(outs), (ins GPRTCNonX7:$rs1), [(riscv_tail GPRTCNonX7:$rs1)]>, PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; diff --git a/llvm/lib/Target/RISCV/RISCVLandingPadSetup.cpp b/llvm/lib/Target/RISCV/RISCVLandingPadSetup.cpp index 072694e123084..9b5cd1f5d0b80 100644 --- a/llvm/lib/Target/RISCV/RISCVLandingPadSetup.cpp +++ b/llvm/lib/Target/RISCV/RISCVLandingPadSetup.cpp @@ -48,7 +48,7 @@ bool RISCVLandingPadSetup::runOnMachineFunction(MachineFunction &MF) { const auto &STI = MF.getSubtarget(); const RISCVInstrInfo &TII = *STI.getInstrInfo(); - if (!STI.hasStdExtZicfilp()) + if (!STI.hasZicfilpCFI()) return false; uint32_t Label = 0; diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h index fd57e02c25d05..1ae5e93737527 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -91,6 +91,13 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { NLog2N, }; // clang-format on + + enum class ZicfilpLabelSchemeEnum { + Disabled, + Unlabeled, + FuncSig, + }; + private: virtual void anchor(); @@ -186,6 +193,17 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { return HasStdExtZfhmin || HasStdExtZfbfmin; } + ZicfilpLabelSchemeEnum getZicfilpLabelScheme() const { + if (hasZicfilpFuncSig()) + return ZicfilpLabelSchemeEnum::FuncSig; + if (hasZicfilpUnlabeled()) + return ZicfilpLabelSchemeEnum::Unlabeled; + return ZicfilpLabelSchemeEnum::Disabled; + } + bool hasZicfilpCFI() const { + return getZicfilpLabelScheme() != ZicfilpLabelSchemeEnum::Disabled; + } + bool hasConditionalMoveFusion() const { // Do we support fusing a branch+mv or branch+c.mv as a conditional move. return (hasConditionalCompressedMoveFusion() && hasStdExtZca()) || diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp index 3f2a83f8ce98c..aeea19b5f85b6 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -17,6 +17,7 @@ #include "RISCVTargetObjectFile.h" #include "RISCVTargetTransformInfo.h" #include "TargetInfo/RISCVTargetInfo.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/GlobalISel/CSEInfo.h" #include "llvm/CodeGen/GlobalISel/IRTranslator.h" @@ -31,6 +32,9 @@ #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Passes/PassBuilder.h" @@ -268,6 +272,35 @@ RISCVTargetMachine::getSubtargetImpl(const Function &F) const { I = std::make_unique( TargetTriple, CPU, TuneCPU, FS, ABIName, RVVBitsMin, RVVBitsMax, *this); } + + if (const Module *const M = F.getParent()) { + if (const Metadata *const CF = M->getModuleFlag("cf-protection-branch"); + CF && !mdconst::extract(CF)->isZero()) { + StringRef LabelScheme; + if (const Metadata *const MD = + M->getModuleFlag("cf-branch-label-scheme")) { + LabelScheme = cast(MD)->getString(); + if (LabelScheme != "func-sig" && LabelScheme != "unlabeled") + reportFatalUsageError("cf-branch-label-scheme=" + LabelScheme + + " module flag is unsupported"); + } else { + reportFatalUsageError("missing cf-branch-label-scheme module flag"); + } + + using ZicfilpLabelSchemeEnum = RISCVSubtarget::ZicfilpLabelSchemeEnum; + const ZicfilpLabelSchemeEnum SupportedScheme = I->getZicfilpLabelScheme(); + if ((SupportedScheme != ZicfilpLabelSchemeEnum::FuncSig && + LabelScheme == "func-sig") || + (SupportedScheme != ZicfilpLabelSchemeEnum::Unlabeled && + LabelScheme == "unlabeled")) + reportFatalUsageError( + "require target feature (+zicfilp-" + LabelScheme + + ") to handle cf-branch-label-scheme=" + LabelScheme + + " module flag"); + } else if (I->hasZicfilpCFI()) { + reportFatalUsageError("require cf-protection-branch != 0 module flag"); + } + } return I.get(); } diff --git a/llvm/test/CodeGen/RISCV/calls.ll b/llvm/test/CodeGen/RISCV/calls.ll index f30c453d7f6bc..1a3e77b8b8ea1 100644 --- a/llvm/test/CodeGen/RISCV/calls.ll +++ b/llvm/test/CodeGen/RISCV/calls.ll @@ -11,8 +11,6 @@ ; RUN: | FileCheck -check-prefix=RV64I-MEDIUM %s ; RUN: llc -code-model=large -mtriple=riscv64 -verify-machineinstrs < %s \ ; RUN: | FileCheck -check-prefix=RV64I-LARGE %s -; RUN: llc -code-model=large -mtriple=riscv64 -mattr=experimental-zicfilp -verify-machineinstrs < %s \ -; RUN: | FileCheck -check-prefix=RV64I-LARGE-ZICFILP %s declare i32 @external_function(i32) @@ -64,19 +62,6 @@ define i32 @test_call_external(i32 %a) nounwind { ; RV64I-LARGE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64I-LARGE-NEXT: addi sp, sp, 16 ; RV64I-LARGE-NEXT: ret -; -; RV64I-LARGE-ZICFILP-LABEL: test_call_external: -; RV64I-LARGE-ZICFILP: # %bb.0: -; RV64I-LARGE-ZICFILP-NEXT: lpad 0 -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, -16 -; RV64I-LARGE-ZICFILP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-LARGE-ZICFILP-NEXT: .Lpcrel_hi0: -; RV64I-LARGE-ZICFILP-NEXT: auipc a1, %pcrel_hi(.LCPI0_0) -; RV64I-LARGE-ZICFILP-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi0)(a1) -; RV64I-LARGE-ZICFILP-NEXT: jalr t2 -; RV64I-LARGE-ZICFILP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, 16 -; RV64I-LARGE-ZICFILP-NEXT: ret %1 = call i32 @external_function(i32 %a) ret i32 %1 } @@ -131,19 +116,6 @@ define i32 @test_call_dso_local(i32 %a) nounwind { ; RV64I-LARGE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64I-LARGE-NEXT: addi sp, sp, 16 ; RV64I-LARGE-NEXT: ret -; -; RV64I-LARGE-ZICFILP-LABEL: test_call_dso_local: -; RV64I-LARGE-ZICFILP: # %bb.0: -; RV64I-LARGE-ZICFILP-NEXT: lpad 0 -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, -16 -; RV64I-LARGE-ZICFILP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-LARGE-ZICFILP-NEXT: .Lpcrel_hi1: -; RV64I-LARGE-ZICFILP-NEXT: auipc a1, %pcrel_hi(.LCPI1_0) -; RV64I-LARGE-ZICFILP-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi1)(a1) -; RV64I-LARGE-ZICFILP-NEXT: jalr t2 -; RV64I-LARGE-ZICFILP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, 16 -; RV64I-LARGE-ZICFILP-NEXT: ret %1 = call i32 @dso_local_function(i32 %a) ret i32 %1 } @@ -173,12 +145,6 @@ define i32 @defined_function(i32 %a) nounwind { ; RV64I-LARGE: # %bb.0: ; RV64I-LARGE-NEXT: addiw a0, a0, 1 ; RV64I-LARGE-NEXT: ret -; -; RV64I-LARGE-ZICFILP-LABEL: defined_function: -; RV64I-LARGE-ZICFILP: # %bb.0: -; RV64I-LARGE-ZICFILP-NEXT: lpad 0 -; RV64I-LARGE-ZICFILP-NEXT: addiw a0, a0, 1 -; RV64I-LARGE-ZICFILP-NEXT: ret %1 = add i32 %a, 1 ret i32 %1 } @@ -231,19 +197,6 @@ define i32 @test_call_defined(i32 %a) nounwind { ; RV64I-LARGE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64I-LARGE-NEXT: addi sp, sp, 16 ; RV64I-LARGE-NEXT: ret -; -; RV64I-LARGE-ZICFILP-LABEL: test_call_defined: -; RV64I-LARGE-ZICFILP: # %bb.0: -; RV64I-LARGE-ZICFILP-NEXT: lpad 0 -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, -16 -; RV64I-LARGE-ZICFILP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-LARGE-ZICFILP-NEXT: .Lpcrel_hi2: -; RV64I-LARGE-ZICFILP-NEXT: auipc a1, %pcrel_hi(.LCPI3_0) -; RV64I-LARGE-ZICFILP-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi2)(a1) -; RV64I-LARGE-ZICFILP-NEXT: jalr t2 -; RV64I-LARGE-ZICFILP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, 16 -; RV64I-LARGE-ZICFILP-NEXT: ret %1 = call i32 @defined_function(i32 %a) ret i32 %1 } @@ -303,18 +256,6 @@ define i32 @test_call_indirect(ptr %a, i32 %b) nounwind { ; RV64I-LARGE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64I-LARGE-NEXT: addi sp, sp, 16 ; RV64I-LARGE-NEXT: ret -; -; RV64I-LARGE-ZICFILP-LABEL: test_call_indirect: -; RV64I-LARGE-ZICFILP: # %bb.0: -; RV64I-LARGE-ZICFILP-NEXT: lpad 0 -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, -16 -; RV64I-LARGE-ZICFILP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-LARGE-ZICFILP-NEXT: mv a2, a0 -; RV64I-LARGE-ZICFILP-NEXT: mv a0, a1 -; RV64I-LARGE-ZICFILP-NEXT: jalr a2 -; RV64I-LARGE-ZICFILP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, 16 -; RV64I-LARGE-ZICFILP-NEXT: ret %1 = call i32 %a(i32 %b) ret i32 %1 } @@ -406,24 +347,6 @@ define i32 @test_call_indirect_no_t0(ptr %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 ; RV64I-LARGE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64I-LARGE-NEXT: addi sp, sp, 16 ; RV64I-LARGE-NEXT: ret -; -; RV64I-LARGE-ZICFILP-LABEL: test_call_indirect_no_t0: -; RV64I-LARGE-ZICFILP: # %bb.0: -; RV64I-LARGE-ZICFILP-NEXT: lpad 0 -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, -16 -; RV64I-LARGE-ZICFILP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-LARGE-ZICFILP-NEXT: mv t1, a0 -; RV64I-LARGE-ZICFILP-NEXT: mv a0, a1 -; RV64I-LARGE-ZICFILP-NEXT: mv a1, a2 -; RV64I-LARGE-ZICFILP-NEXT: mv a2, a3 -; RV64I-LARGE-ZICFILP-NEXT: mv a3, a4 -; RV64I-LARGE-ZICFILP-NEXT: mv a4, a5 -; RV64I-LARGE-ZICFILP-NEXT: mv a5, a6 -; RV64I-LARGE-ZICFILP-NEXT: mv a6, a7 -; RV64I-LARGE-ZICFILP-NEXT: jalr t1 -; RV64I-LARGE-ZICFILP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, 16 -; RV64I-LARGE-ZICFILP-NEXT: ret %1 = call i32 %a(i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) ret i32 %1 } @@ -456,12 +379,6 @@ define fastcc i32 @fastcc_function(i32 %a, i32 %b) nounwind { ; RV64I-LARGE: # %bb.0: ; RV64I-LARGE-NEXT: addw a0, a0, a1 ; RV64I-LARGE-NEXT: ret -; -; RV64I-LARGE-ZICFILP-LABEL: fastcc_function: -; RV64I-LARGE-ZICFILP: # %bb.0: -; RV64I-LARGE-ZICFILP-NEXT: lpad 0 -; RV64I-LARGE-ZICFILP-NEXT: addw a0, a0, a1 -; RV64I-LARGE-ZICFILP-NEXT: ret %1 = add i32 %a, %b ret i32 %1 } @@ -535,24 +452,6 @@ define i32 @test_call_fastcc(i32 %a, i32 %b) nounwind { ; RV64I-LARGE-NEXT: ld s0, 0(sp) # 8-byte Folded Reload ; RV64I-LARGE-NEXT: addi sp, sp, 16 ; RV64I-LARGE-NEXT: ret -; -; RV64I-LARGE-ZICFILP-LABEL: test_call_fastcc: -; RV64I-LARGE-ZICFILP: # %bb.0: -; RV64I-LARGE-ZICFILP-NEXT: lpad 0 -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, -16 -; RV64I-LARGE-ZICFILP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-LARGE-ZICFILP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill -; RV64I-LARGE-ZICFILP-NEXT: mv s0, a0 -; RV64I-LARGE-ZICFILP-NEXT: .Lpcrel_hi3: -; RV64I-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI7_0) -; RV64I-LARGE-ZICFILP-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi3)(a0) -; RV64I-LARGE-ZICFILP-NEXT: mv a0, s0 -; RV64I-LARGE-ZICFILP-NEXT: jalr t2 -; RV64I-LARGE-ZICFILP-NEXT: mv a0, s0 -; RV64I-LARGE-ZICFILP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-LARGE-ZICFILP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, 16 -; RV64I-LARGE-ZICFILP-NEXT: ret %1 = call fastcc i32 @fastcc_function(i32 %a, i32 %b) ret i32 %a } @@ -673,33 +572,6 @@ define i32 @test_call_external_many_args(i32 %a) nounwind { ; RV64I-LARGE-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; RV64I-LARGE-NEXT: addi sp, sp, 32 ; RV64I-LARGE-NEXT: ret -; -; RV64I-LARGE-ZICFILP-LABEL: test_call_external_many_args: -; RV64I-LARGE-ZICFILP: # %bb.0: -; RV64I-LARGE-ZICFILP-NEXT: lpad 0 -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, -32 -; RV64I-LARGE-ZICFILP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill -; RV64I-LARGE-ZICFILP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill -; RV64I-LARGE-ZICFILP-NEXT: mv s0, a0 -; RV64I-LARGE-ZICFILP-NEXT: .Lpcrel_hi4: -; RV64I-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI8_0) -; RV64I-LARGE-ZICFILP-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi4)(a0) -; RV64I-LARGE-ZICFILP-NEXT: sd s0, 0(sp) -; RV64I-LARGE-ZICFILP-NEXT: sd s0, 8(sp) -; RV64I-LARGE-ZICFILP-NEXT: mv a0, s0 -; RV64I-LARGE-ZICFILP-NEXT: mv a1, s0 -; RV64I-LARGE-ZICFILP-NEXT: mv a2, s0 -; RV64I-LARGE-ZICFILP-NEXT: mv a3, s0 -; RV64I-LARGE-ZICFILP-NEXT: mv a4, s0 -; RV64I-LARGE-ZICFILP-NEXT: mv a5, s0 -; RV64I-LARGE-ZICFILP-NEXT: mv a6, s0 -; RV64I-LARGE-ZICFILP-NEXT: mv a7, s0 -; RV64I-LARGE-ZICFILP-NEXT: jalr t2 -; RV64I-LARGE-ZICFILP-NEXT: mv a0, s0 -; RV64I-LARGE-ZICFILP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload -; RV64I-LARGE-ZICFILP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, 32 -; RV64I-LARGE-ZICFILP-NEXT: ret %1 = call i32 @external_many_args(i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, i32 %a) ret i32 %a @@ -735,13 +607,6 @@ define i32 @defined_many_args(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 % ; RV64I-LARGE-NEXT: lw a0, 8(sp) ; RV64I-LARGE-NEXT: addiw a0, a0, 1 ; RV64I-LARGE-NEXT: ret -; -; RV64I-LARGE-ZICFILP-LABEL: defined_many_args: -; RV64I-LARGE-ZICFILP: # %bb.0: -; RV64I-LARGE-ZICFILP-NEXT: lpad 0 -; RV64I-LARGE-ZICFILP-NEXT: lw a0, 8(sp) -; RV64I-LARGE-ZICFILP-NEXT: addiw a0, a0, 1 -; RV64I-LARGE-ZICFILP-NEXT: ret %added = add i32 %j, 1 ret i32 %added } @@ -839,28 +704,6 @@ define i32 @test_call_defined_many_args(i32 %a) nounwind { ; RV64I-LARGE-NEXT: ld ra, 24(sp) # 8-byte Folded Reload ; RV64I-LARGE-NEXT: addi sp, sp, 32 ; RV64I-LARGE-NEXT: ret -; -; RV64I-LARGE-ZICFILP-LABEL: test_call_defined_many_args: -; RV64I-LARGE-ZICFILP: # %bb.0: -; RV64I-LARGE-ZICFILP-NEXT: lpad 0 -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, -32 -; RV64I-LARGE-ZICFILP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill -; RV64I-LARGE-ZICFILP-NEXT: .Lpcrel_hi5: -; RV64I-LARGE-ZICFILP-NEXT: auipc a1, %pcrel_hi(.LCPI10_0) -; RV64I-LARGE-ZICFILP-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi5)(a1) -; RV64I-LARGE-ZICFILP-NEXT: sd a0, 0(sp) -; RV64I-LARGE-ZICFILP-NEXT: sd a0, 8(sp) -; RV64I-LARGE-ZICFILP-NEXT: mv a1, a0 -; RV64I-LARGE-ZICFILP-NEXT: mv a2, a0 -; RV64I-LARGE-ZICFILP-NEXT: mv a3, a0 -; RV64I-LARGE-ZICFILP-NEXT: mv a4, a0 -; RV64I-LARGE-ZICFILP-NEXT: mv a5, a0 -; RV64I-LARGE-ZICFILP-NEXT: mv a6, a0 -; RV64I-LARGE-ZICFILP-NEXT: mv a7, a0 -; RV64I-LARGE-ZICFILP-NEXT: jalr t2 -; RV64I-LARGE-ZICFILP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, 32 -; RV64I-LARGE-ZICFILP-NEXT: ret %1 = call i32 @defined_many_args(i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, i32 %a) ret i32 %1 @@ -994,35 +837,6 @@ define fastcc void @fastcc_call_nonfastcc(){ ; RV64I-LARGE-NEXT: addi sp, sp, 32 ; RV64I-LARGE-NEXT: .cfi_def_cfa_offset 0 ; RV64I-LARGE-NEXT: ret -; -; RV64I-LARGE-ZICFILP-LABEL: fastcc_call_nonfastcc: -; RV64I-LARGE-ZICFILP: # %bb.0: -; RV64I-LARGE-ZICFILP-NEXT: lpad 0 -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, -32 -; RV64I-LARGE-ZICFILP-NEXT: .cfi_def_cfa_offset 32 -; RV64I-LARGE-ZICFILP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill -; RV64I-LARGE-ZICFILP-NEXT: .cfi_offset ra, -8 -; RV64I-LARGE-ZICFILP-NEXT: li t0, 10 -; RV64I-LARGE-ZICFILP-NEXT: li t1, 9 -; RV64I-LARGE-ZICFILP-NEXT: .Lpcrel_hi6: -; RV64I-LARGE-ZICFILP-NEXT: auipc a5, %pcrel_hi(.LCPI11_0) -; RV64I-LARGE-ZICFILP-NEXT: li a0, 1 -; RV64I-LARGE-ZICFILP-NEXT: li a1, 2 -; RV64I-LARGE-ZICFILP-NEXT: li a2, 3 -; RV64I-LARGE-ZICFILP-NEXT: li a3, 4 -; RV64I-LARGE-ZICFILP-NEXT: li a4, 5 -; RV64I-LARGE-ZICFILP-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi6)(a5) -; RV64I-LARGE-ZICFILP-NEXT: li a5, 6 -; RV64I-LARGE-ZICFILP-NEXT: li a6, 7 -; RV64I-LARGE-ZICFILP-NEXT: li a7, 8 -; RV64I-LARGE-ZICFILP-NEXT: sd t1, 0(sp) -; RV64I-LARGE-ZICFILP-NEXT: sd t0, 8(sp) -; RV64I-LARGE-ZICFILP-NEXT: jalr t2 -; RV64I-LARGE-ZICFILP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload -; RV64I-LARGE-ZICFILP-NEXT: .cfi_restore ra -; RV64I-LARGE-ZICFILP-NEXT: addi sp, sp, 32 -; RV64I-LARGE-ZICFILP-NEXT: .cfi_def_cfa_offset 0 -; RV64I-LARGE-ZICFILP-NEXT: ret call void @external_many_args(i32 1, i32 2,i32 3,i32 4,i32 5,i32 6,i32 7,i32 8,i32 9,i32 10) ret void } diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll index b94665b718ae7..0d2887e506d44 100644 --- a/llvm/test/CodeGen/RISCV/features-info.ll +++ b/llvm/test/CodeGen/RISCV/features-info.ll @@ -263,6 +263,8 @@ ; CHECK-NEXT: ziccif - 'Ziccif' (Main Memory Supports Instruction Fetch with Atomicity Requirement). ; CHECK-NEXT: zicclsm - 'Zicclsm' (Main Memory Supports Misaligned Loads/Stores). ; CHECK-NEXT: ziccrse - 'Ziccrse' (Main Memory Supports Forward Progress on LR/SC Sequences). +; CHECK-NEXT: zicfilp-func-sig - Enforce forward-edge control-flow integrity with ZICFILP-func-sig. +; CHECK-NEXT: zicfilp-unlabeled - Enforce forward-edge control-flow integrity with ZICFILP-unlabeled. ; CHECK-NEXT: zicntr - 'Zicntr' (Base Counters and Timers). ; CHECK-NEXT: zicond - 'Zicond' (Integer Conditional Operations). ; CHECK-NEXT: zicsr - 'Zicsr' (CSRs). diff --git a/llvm/test/CodeGen/RISCV/jumptable-swguarded.ll b/llvm/test/CodeGen/RISCV/jumptable-swguarded.ll index b4ab0585c0cc9..bd340c617423a 100644 --- a/llvm/test/CodeGen/RISCV/jumptable-swguarded.ll +++ b/llvm/test/CodeGen/RISCV/jumptable-swguarded.ll @@ -1,14 +1,11 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp < %s | FileCheck %s -; RUN: llc -mtriple riscv64 -mattr=+experimental-zicfilp < %s | FileCheck %s -; RUN: llc -mtriple riscv32 < %s | FileCheck %s --check-prefix=NO-ZICFILP -; RUN: llc -mtriple riscv64 < %s | FileCheck %s --check-prefix=NO-ZICFILP +; RUN: llc -mtriple riscv32 -mattr=+zicfilp-unlabeled < %s | FileCheck %s +; RUN: llc -mtriple riscv64 -mattr=+zicfilp-unlabeled < %s | FileCheck %s ; Test using t2 to jump table branch. define void @above_threshold(i32 signext %in, ptr %out) nounwind { ; CHECK-LABEL: above_threshold: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: lpad 0 +; CHECK-NEXT: auipc zero, 0 ; CHECK-NEXT: addi a0, a0, -1 ; CHECK-NEXT: li a2, 5 ; CHECK-NEXT: bltu a2, a0, .LBB0_9 @@ -40,40 +37,6 @@ define void @above_threshold(i32 signext %in, ptr %out) nounwind { ; CHECK-NEXT: sw a0, 0(a1) ; CHECK-NEXT: .LBB0_9: # %exit ; CHECK-NEXT: ret -; -; NO-ZICFILP-LABEL: above_threshold: -; NO-ZICFILP: # %bb.0: # %entry -; NO-ZICFILP-NEXT: addi a0, a0, -1 -; NO-ZICFILP-NEXT: li a2, 5 -; NO-ZICFILP-NEXT: bltu a2, a0, .LBB0_9 -; NO-ZICFILP-NEXT: # %bb.1: # %entry -; NO-ZICFILP-NEXT: slli a0, a0, 2 -; NO-ZICFILP-NEXT: lui a2, %hi(.LJTI0_0) -; NO-ZICFILP-NEXT: addi a2, a2, %lo(.LJTI0_0) -; NO-ZICFILP-NEXT: add a0, a2, a0 -; NO-ZICFILP-NEXT: lw a0, 0(a0) -; NO-ZICFILP-NEXT: jr a0 -; NO-ZICFILP-NEXT: .LBB0_2: # %bb1 -; NO-ZICFILP-NEXT: li a0, 4 -; NO-ZICFILP-NEXT: j .LBB0_8 -; NO-ZICFILP-NEXT: .LBB0_3: # %bb5 -; NO-ZICFILP-NEXT: li a0, 100 -; NO-ZICFILP-NEXT: j .LBB0_8 -; NO-ZICFILP-NEXT: .LBB0_4: # %bb3 -; NO-ZICFILP-NEXT: li a0, 2 -; NO-ZICFILP-NEXT: j .LBB0_8 -; NO-ZICFILP-NEXT: .LBB0_5: # %bb4 -; NO-ZICFILP-NEXT: li a0, 1 -; NO-ZICFILP-NEXT: j .LBB0_8 -; NO-ZICFILP-NEXT: .LBB0_6: # %bb2 -; NO-ZICFILP-NEXT: li a0, 3 -; NO-ZICFILP-NEXT: j .LBB0_8 -; NO-ZICFILP-NEXT: .LBB0_7: # %bb6 -; NO-ZICFILP-NEXT: li a0, 200 -; NO-ZICFILP-NEXT: .LBB0_8: # %exit -; NO-ZICFILP-NEXT: sw a0, 0(a1) -; NO-ZICFILP-NEXT: .LBB0_9: # %exit -; NO-ZICFILP-NEXT: ret entry: switch i32 %in, label %exit [ i32 1, label %bb1 @@ -104,3 +67,8 @@ bb6: exit: ret void } + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 8, !"cf-protection-branch", i32 1} +!1 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} diff --git a/llvm/test/CodeGen/RISCV/lpad.ll b/llvm/test/CodeGen/RISCV/lpad.ll index 93eda6f10eedb..de9ddf5deb450 100644 --- a/llvm/test/CodeGen/RISCV/lpad.ll +++ b/llvm/test/CodeGen/RISCV/lpad.ll @@ -1,17 +1,15 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp < %s | FileCheck %s --check-prefixes=CHECK,RV32 -; RUN: llc -mtriple riscv64 -mattr=+experimental-zicfilp < %s | FileCheck %s --check-prefixes=CHECK,RV64 -; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp \ -; RUN: -riscv-landing-pad-label=1 < %s | FileCheck %s --check-prefixes=FIXED-ONE,FIXED-ONE-RV32 -; RUN: llc -mtriple riscv64 -mattr=+experimental-zicfilp \ -; RUN: -riscv-landing-pad-label=1 < %s | FileCheck %s --check-prefixes=FIXED-ONE,FIXED-ONE-RV64 +; RUN: llc -mtriple riscv32 -mattr=+zicfilp-unlabeled < %s | FileCheck %s --check-prefixes=CHECK,RV32 +; RUN: llc -mtriple riscv64 -mattr=+zicfilp-unlabeled < %s | FileCheck %s --check-prefixes=CHECK,RV64 +; RUN: llc -mtriple riscv32 -mattr=+zicfilp-unlabeled -riscv-landing-pad-label=1 < %s | FileCheck %s --check-prefixes=FIXED-ONE,FIXED-ONE-RV32 +; RUN: llc -mtriple riscv64 -mattr=+zicfilp-unlabeled -riscv-landing-pad-label=1 < %s | FileCheck %s --check-prefixes=FIXED-ONE,FIXED-ONE-RV64 ; Check indirectbr. @__const.indirctbr.addr = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@indirctbr, %labelA), ptr blockaddress(@indirctbr, %labelB)], align 8 define void @indirctbr(i32 %i, ptr %p) { ; RV32-LABEL: indirctbr: ; RV32: # %bb.0: # %entry -; RV32-NEXT: lpad 0 +; RV32-NEXT: auipc zero, 0 ; RV32-NEXT: slli a0, a0, 2 ; RV32-NEXT: lui a2, %hi(.L__const.indirctbr.addr) ; RV32-NEXT: addi a2, a2, %lo(.L__const.indirctbr.addr) @@ -21,20 +19,20 @@ define void @indirctbr(i32 %i, ptr %p) { ; RV32-NEXT: .p2align 2 ; RV32-NEXT: .Ltmp3: # Block address taken ; RV32-NEXT: .LBB0_1: # %labelA -; RV32-NEXT: lpad 0 +; RV32-NEXT: auipc zero, 0 ; RV32-NEXT: li a0, 1 ; RV32-NEXT: sw a0, 0(a1) ; RV32-NEXT: .p2align 2 ; RV32-NEXT: .Ltmp4: # Block address taken ; RV32-NEXT: .LBB0_2: # %labelB -; RV32-NEXT: lpad 0 +; RV32-NEXT: auipc zero, 0 ; RV32-NEXT: li a0, 2 ; RV32-NEXT: sw a0, 0(a1) ; RV32-NEXT: ret ; ; RV64-LABEL: indirctbr: ; RV64: # %bb.0: # %entry -; RV64-NEXT: lpad 0 +; RV64-NEXT: auipc zero, 0 ; RV64-NEXT: sext.w a0, a0 ; RV64-NEXT: slli a0, a0, 3 ; RV64-NEXT: lui a2, %hi(.L__const.indirctbr.addr) @@ -45,20 +43,20 @@ define void @indirctbr(i32 %i, ptr %p) { ; RV64-NEXT: .p2align 2 ; RV64-NEXT: .Ltmp3: # Block address taken ; RV64-NEXT: .LBB0_1: # %labelA -; RV64-NEXT: lpad 0 +; RV64-NEXT: auipc zero, 0 ; RV64-NEXT: li a0, 1 ; RV64-NEXT: sw a0, 0(a1) ; RV64-NEXT: .p2align 2 ; RV64-NEXT: .Ltmp4: # Block address taken ; RV64-NEXT: .LBB0_2: # %labelB -; RV64-NEXT: lpad 0 +; RV64-NEXT: auipc zero, 0 ; RV64-NEXT: li a0, 2 ; RV64-NEXT: sw a0, 0(a1) ; RV64-NEXT: ret ; ; FIXED-ONE-RV32-LABEL: indirctbr: ; FIXED-ONE-RV32: # %bb.0: # %entry -; FIXED-ONE-RV32-NEXT: lpad 1 +; FIXED-ONE-RV32-NEXT: auipc zero, 1 ; FIXED-ONE-RV32-NEXT: slli a0, a0, 2 ; FIXED-ONE-RV32-NEXT: lui a2, %hi(.L__const.indirctbr.addr) ; FIXED-ONE-RV32-NEXT: addi a2, a2, %lo(.L__const.indirctbr.addr) @@ -69,20 +67,20 @@ define void @indirctbr(i32 %i, ptr %p) { ; FIXED-ONE-RV32-NEXT: .p2align 2 ; FIXED-ONE-RV32-NEXT: .Ltmp3: # Block address taken ; FIXED-ONE-RV32-NEXT: .LBB0_1: # %labelA -; FIXED-ONE-RV32-NEXT: lpad 1 +; FIXED-ONE-RV32-NEXT: auipc zero, 1 ; FIXED-ONE-RV32-NEXT: li a0, 1 ; FIXED-ONE-RV32-NEXT: sw a0, 0(a1) ; FIXED-ONE-RV32-NEXT: .p2align 2 ; FIXED-ONE-RV32-NEXT: .Ltmp4: # Block address taken ; FIXED-ONE-RV32-NEXT: .LBB0_2: # %labelB -; FIXED-ONE-RV32-NEXT: lpad 1 +; FIXED-ONE-RV32-NEXT: auipc zero, 1 ; FIXED-ONE-RV32-NEXT: li a0, 2 ; FIXED-ONE-RV32-NEXT: sw a0, 0(a1) ; FIXED-ONE-RV32-NEXT: ret ; ; FIXED-ONE-RV64-LABEL: indirctbr: ; FIXED-ONE-RV64: # %bb.0: # %entry -; FIXED-ONE-RV64-NEXT: lpad 1 +; FIXED-ONE-RV64-NEXT: auipc zero, 1 ; FIXED-ONE-RV64-NEXT: sext.w a0, a0 ; FIXED-ONE-RV64-NEXT: slli a0, a0, 3 ; FIXED-ONE-RV64-NEXT: lui a2, %hi(.L__const.indirctbr.addr) @@ -94,13 +92,13 @@ define void @indirctbr(i32 %i, ptr %p) { ; FIXED-ONE-RV64-NEXT: .p2align 2 ; FIXED-ONE-RV64-NEXT: .Ltmp3: # Block address taken ; FIXED-ONE-RV64-NEXT: .LBB0_1: # %labelA -; FIXED-ONE-RV64-NEXT: lpad 1 +; FIXED-ONE-RV64-NEXT: auipc zero, 1 ; FIXED-ONE-RV64-NEXT: li a0, 1 ; FIXED-ONE-RV64-NEXT: sw a0, 0(a1) ; FIXED-ONE-RV64-NEXT: .p2align 2 ; FIXED-ONE-RV64-NEXT: .Ltmp4: # Block address taken ; FIXED-ONE-RV64-NEXT: .LBB0_2: # %labelB -; FIXED-ONE-RV64-NEXT: lpad 1 +; FIXED-ONE-RV64-NEXT: auipc zero, 1 ; FIXED-ONE-RV64-NEXT: li a0, 2 ; FIXED-ONE-RV64-NEXT: sw a0, 0(a1) ; FIXED-ONE-RV64-NEXT: ret @@ -122,12 +120,12 @@ labelB: ; preds = %labelA, %entry define void @call(ptr %0) { ; CHECK-LABEL: call: ; CHECK: # %bb.0: -; CHECK-NEXT: lpad 0 +; CHECK-NEXT: auipc zero, 0 ; CHECK-NEXT: jr a0 ; ; FIXED-ONE-LABEL: call: ; FIXED-ONE: # %bb.0: -; FIXED-ONE-NEXT: lpad 1 +; FIXED-ONE-NEXT: auipc zero, 1 ; FIXED-ONE-NEXT: lui t2, 1 ; FIXED-ONE-NEXT: jr a0 tail call void %0() @@ -139,7 +137,7 @@ declare dso_local i32 @__gxx_personality_v0(...) define void @invoke(ptr %f) personality ptr @__gxx_personality_v0 { ; RV32-LABEL: invoke: ; RV32: # %bb.0: # %entry -; RV32-NEXT: lpad 0 +; RV32-NEXT: auipc zero, 0 ; RV32-NEXT: addi sp, sp, -16 ; RV32-NEXT: .cfi_def_cfa_offset 16 ; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill @@ -161,7 +159,7 @@ define void @invoke(ptr %f) personality ptr @__gxx_personality_v0 { ; ; RV64-LABEL: invoke: ; RV64: # %bb.0: # %entry -; RV64-NEXT: lpad 0 +; RV64-NEXT: auipc zero, 0 ; RV64-NEXT: addi sp, sp, -16 ; RV64-NEXT: .cfi_def_cfa_offset 16 ; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill @@ -183,7 +181,7 @@ define void @invoke(ptr %f) personality ptr @__gxx_personality_v0 { ; ; FIXED-ONE-RV32-LABEL: invoke: ; FIXED-ONE-RV32: # %bb.0: # %entry -; FIXED-ONE-RV32-NEXT: lpad 1 +; FIXED-ONE-RV32-NEXT: auipc zero, 1 ; FIXED-ONE-RV32-NEXT: addi sp, sp, -16 ; FIXED-ONE-RV32-NEXT: .cfi_def_cfa_offset 16 ; FIXED-ONE-RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill @@ -206,7 +204,7 @@ define void @invoke(ptr %f) personality ptr @__gxx_personality_v0 { ; ; FIXED-ONE-RV64-LABEL: invoke: ; FIXED-ONE-RV64: # %bb.0: # %entry -; FIXED-ONE-RV64-NEXT: lpad 1 +; FIXED-ONE-RV64-NEXT: auipc zero, 1 ; FIXED-ONE-RV64-NEXT: addi sp, sp, -16 ; FIXED-ONE-RV64-NEXT: .cfi_def_cfa_offset 16 ; FIXED-ONE-RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill @@ -241,12 +239,12 @@ try.cont: define void @external() { ; CHECK-LABEL: external: ; CHECK: # %bb.0: -; CHECK-NEXT: lpad 0 +; CHECK-NEXT: auipc zero, 0 ; CHECK-NEXT: ret ; ; FIXED-ONE-LABEL: external: ; FIXED-ONE: # %bb.0: -; FIXED-ONE-NEXT: lpad 1 +; FIXED-ONE-NEXT: auipc zero, 1 ; FIXED-ONE-NEXT: ret ret void } @@ -268,12 +266,12 @@ define internal void @internal() { define internal void @internal2() { ; CHECK-LABEL: internal2: ; CHECK: # %bb.0: -; CHECK-NEXT: lpad 0 +; CHECK-NEXT: auipc zero, 0 ; CHECK-NEXT: ret ; ; FIXED-ONE-LABEL: internal2: ; FIXED-ONE: # %bb.0: -; FIXED-ONE-NEXT: lpad 1 +; FIXED-ONE-NEXT: auipc zero, 1 ; FIXED-ONE-NEXT: ret ret void } @@ -289,3 +287,8 @@ define void @interrupt() "interrupt"="machine" { ; FIXED-ONE-NEXT: mret ret void } + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 8, !"cf-protection-branch", i32 1} +!1 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} diff --git a/llvm/test/CodeGen/RISCV/nest-register.ll b/llvm/test/CodeGen/RISCV/nest-register.ll index 6e892e05c4297..e222beee45783 100644 --- a/llvm/test/CodeGen/RISCV/nest-register.ll +++ b/llvm/test/CodeGen/RISCV/nest-register.ll @@ -3,10 +3,6 @@ ; RUN: | FileCheck -check-prefix=RV32I %s ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ ; RUN: | FileCheck -check-prefix=RV64I %s -; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfilp -verify-machineinstrs < %s \ -; RUN: | FileCheck -check-prefix=RV64I-ZICFILP %s -; RUN: not llc -mtriple=riscv64 -target-abi=lp64e -mattr=+experimental-zicfilp \ -; RUN: -verify-machineinstrs < %s 2>&1 | FileCheck -check-prefix=LP64E-ZICFILP %s ; Tests that the 'nest' parameter attribute causes the relevant parameter to be ; passed in the right register. @@ -21,12 +17,6 @@ define ptr @nest_receiver(ptr nest %arg) nounwind { ; RV64I: # %bb.0: ; RV64I-NEXT: mv a0, t2 ; RV64I-NEXT: ret -; -; RV64I-ZICFILP-LABEL: nest_receiver: -; RV64I-ZICFILP: # %bb.0: -; RV64I-ZICFILP-NEXT: lpad 0 -; RV64I-ZICFILP-NEXT: mv a0, t3 -; RV64I-ZICFILP-NEXT: ret ret ptr %arg } @@ -50,22 +40,6 @@ define ptr @nest_caller(ptr %arg) nounwind { ; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret -; -; RV64I-ZICFILP-LABEL: nest_caller: -; RV64I-ZICFILP: # %bb.0: -; RV64I-ZICFILP-NEXT: lpad 0 -; RV64I-ZICFILP-NEXT: addi sp, sp, -16 -; RV64I-ZICFILP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-ZICFILP-NEXT: mv t3, a0 -; RV64I-ZICFILP-NEXT: call nest_receiver -; RV64I-ZICFILP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-ZICFILP-NEXT: addi sp, sp, 16 -; RV64I-ZICFILP-NEXT: ret %result = call ptr @nest_receiver(ptr nest %arg) ret ptr %result } - -; LP64E-ZICFILP: LLVM ERROR: Nested functions with control flow protection are not usable with ILP32E or LP64E ABI. -!llvm.module.flags = !{!0} - -!0 = !{i32 8, !"cf-protection-branch", i32 1} diff --git a/llvm/test/CodeGen/RISCV/rv64-trampoline-cfi.ll b/llvm/test/CodeGen/RISCV/rv64-trampoline-cfi.ll index 8a338a855c863..b63b9765c6f81 100644 --- a/llvm/test/CodeGen/RISCV/rv64-trampoline-cfi.ll +++ b/llvm/test/CodeGen/RISCV/rv64-trampoline-cfi.ll @@ -1,8 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 -; RUN: llc -O0 -mtriple=riscv64 -mattr=+experimental-zicfilp -verify-machineinstrs < %s \ -; RUN: | FileCheck -check-prefix=RV64 %s -; RUN: llc -O0 -mtriple=riscv64-unknown-linux-gnu -mattr=+experimental-zicfilp -verify-machineinstrs < %s \ -; RUN: | FileCheck -check-prefix=RV64-LINUX %s +; RUN: llc -O0 -mtriple=riscv64 -mattr=+zicfilp-unlabeled -verify-machineinstrs < %s | FileCheck -check-prefix=RV64 %s +; RUN: llc -O0 -mtriple=riscv64-unknown-linux-gnu -mattr=+zicfilp-unlabeled -verify-machineinstrs < %s | FileCheck -check-prefix=RV64-LINUX %s declare void @llvm.init.trampoline(ptr, ptr, ptr) declare ptr @llvm.adjust.trampoline(ptr) @@ -11,7 +9,7 @@ declare i64 @f(ptr nest, i64) define i64 @test0(i64 %n, ptr %p) nounwind { ; RV64-LABEL: test0: ; RV64: # %bb.0: -; RV64-NEXT: lpad 0 +; RV64-NEXT: auipc zero, 0 ; RV64-NEXT: addi sp, sp, -64 ; RV64-NEXT: sd ra, 56(sp) # 8-byte Folded Spill ; RV64-NEXT: sd a0, 0(sp) # 8-byte Folded Spill @@ -50,7 +48,7 @@ define i64 @test0(i64 %n, ptr %p) nounwind { ; ; RV64-LINUX-LABEL: test0: ; RV64-LINUX: # %bb.0: -; RV64-LINUX-NEXT: lpad 0 +; RV64-LINUX-NEXT: auipc zero, 0 ; RV64-LINUX-NEXT: addi sp, sp, -64 ; RV64-LINUX-NEXT: sd ra, 56(sp) # 8-byte Folded Spill ; RV64-LINUX-NEXT: sd a0, 0(sp) # 8-byte Folded Spill @@ -94,6 +92,7 @@ define i64 @test0(i64 %n, ptr %p) nounwind { ret i64 %ret } -!llvm.module.flags = !{!0} +!llvm.module.flags = !{!0, !1} !0 = !{i32 8, !"cf-protection-branch", i32 1} +!1 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} diff --git a/llvm/test/CodeGen/RISCV/tail-calls.ll b/llvm/test/CodeGen/RISCV/tail-calls.ll index 366b37ac5d472..4d164c84e9d3f 100644 --- a/llvm/test/CodeGen/RISCV/tail-calls.ll +++ b/llvm/test/CodeGen/RISCV/tail-calls.ll @@ -1,8 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple riscv32-unknown-linux-gnu -o - %s | FileCheck %s -; RUN: llc -mtriple riscv32-unknown-linux-gnu -mattr=experimental-zicfilp \ -; RUN: -code-model=large -o - %s \ -; RUN: | FileCheck %s -check-prefix=CHECK-LARGE-ZICFILP ; RUN: llc -mtriple riscv32-unknown-elf -o - %s | FileCheck %s ; Perform tail call optimization for global address. @@ -11,14 +8,6 @@ define i32 @caller_tail(i32 %i) nounwind { ; CHECK-LABEL: caller_tail: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: tail callee_tail -; -; CHECK-LARGE-ZICFILP-LABEL: caller_tail: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi0: -; CHECK-LARGE-ZICFILP-NEXT: auipc a1, %pcrel_hi(.LCPI0_0) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi0)(a1) -; CHECK-LARGE-ZICFILP-NEXT: jr t2 entry: %r = tail call i32 @callee_tail(i32 %i) ret i32 %r @@ -37,21 +26,6 @@ define void @caller_extern(ptr %src) optsize { ; CHECK-NEXT: mv a0, a1 ; CHECK-NEXT: mv a1, a3 ; CHECK-NEXT: tail memcpy -; -; CHECK-LARGE-ZICFILP-LABEL: caller_extern: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi1: -; CHECK-LARGE-ZICFILP-NEXT: auipc a1, %pcrel_hi(.LCPI1_0) -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi2: -; CHECK-LARGE-ZICFILP-NEXT: auipc a2, %pcrel_hi(.LCPI1_1) -; CHECK-LARGE-ZICFILP-NEXT: lw a1, %pcrel_lo(.Lpcrel_hi1)(a1) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi2)(a2) -; CHECK-LARGE-ZICFILP-NEXT: li a2, 7 -; CHECK-LARGE-ZICFILP-NEXT: mv a3, a0 -; CHECK-LARGE-ZICFILP-NEXT: mv a0, a1 -; CHECK-LARGE-ZICFILP-NEXT: mv a1, a3 -; CHECK-LARGE-ZICFILP-NEXT: jr t2 entry: tail call void @llvm.memcpy.p0.p0.i32(ptr @dest, ptr %src, i32 7, i1 false) ret void @@ -69,21 +43,6 @@ define void @caller_extern_pgso(ptr %src) !prof !14 { ; CHECK-NEXT: mv a0, a1 ; CHECK-NEXT: mv a1, a3 ; CHECK-NEXT: tail memcpy -; -; CHECK-LARGE-ZICFILP-LABEL: caller_extern_pgso: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi3: -; CHECK-LARGE-ZICFILP-NEXT: auipc a1, %pcrel_hi(.LCPI2_0) -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi4: -; CHECK-LARGE-ZICFILP-NEXT: auipc a2, %pcrel_hi(.LCPI2_1) -; CHECK-LARGE-ZICFILP-NEXT: lw a1, %pcrel_lo(.Lpcrel_hi3)(a1) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi4)(a2) -; CHECK-LARGE-ZICFILP-NEXT: li a2, 7 -; CHECK-LARGE-ZICFILP-NEXT: mv a3, a0 -; CHECK-LARGE-ZICFILP-NEXT: mv a0, a1 -; CHECK-LARGE-ZICFILP-NEXT: mv a1, a3 -; CHECK-LARGE-ZICFILP-NEXT: jr t2 entry: tail call void @llvm.memcpy.p0.p0.i32(ptr @dest_pgso, ptr %src, i32 7, i1 false) ret void @@ -104,21 +63,6 @@ define void @caller_indirect_tail(i32 %a) nounwind { ; CHECK-NEXT: lui t1, %hi(callee_indirect1) ; CHECK-NEXT: addi t1, t1, %lo(callee_indirect1) ; CHECK-NEXT: jr t1 -; -; CHECK-LARGE-ZICFILP-LABEL: caller_indirect_tail: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: beqz a0, .LBB3_2 -; CHECK-LARGE-ZICFILP-NEXT: # %bb.1: # %entry -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi6: -; CHECK-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI3_0) -; CHECK-LARGE-ZICFILP-NEXT: lw t1, %pcrel_lo(.Lpcrel_hi6)(a0) -; CHECK-LARGE-ZICFILP-NEXT: jr t1 -; CHECK-LARGE-ZICFILP-NEXT: .LBB3_2: -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi5: -; CHECK-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI3_1) -; CHECK-LARGE-ZICFILP-NEXT: lw t1, %pcrel_lo(.Lpcrel_hi5)(a0) -; CHECK-LARGE-ZICFILP-NEXT: jr t1 entry: %tobool = icmp eq i32 %a, 0 %callee = select i1 %tobool, ptr @callee_indirect1, ptr @callee_indirect2 @@ -140,19 +84,6 @@ define i32 @caller_indirect_no_t0(ptr %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5 ; CHECK-NEXT: mv a5, a6 ; CHECK-NEXT: mv a6, a7 ; CHECK-NEXT: jr t1 -; -; CHECK-LARGE-ZICFILP-LABEL: caller_indirect_no_t0: -; CHECK-LARGE-ZICFILP: # %bb.0: -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: mv t1, a0 -; CHECK-LARGE-ZICFILP-NEXT: mv a0, a1 -; CHECK-LARGE-ZICFILP-NEXT: mv a1, a2 -; CHECK-LARGE-ZICFILP-NEXT: mv a2, a3 -; CHECK-LARGE-ZICFILP-NEXT: mv a3, a4 -; CHECK-LARGE-ZICFILP-NEXT: mv a4, a5 -; CHECK-LARGE-ZICFILP-NEXT: mv a5, a6 -; CHECK-LARGE-ZICFILP-NEXT: mv a6, a7 -; CHECK-LARGE-ZICFILP-NEXT: jr t1 %9 = tail call i32 %0(i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7) ret i32 %9 } @@ -175,26 +106,6 @@ define void @caller_varargs(i32 %a, i32 %b) nounwind { ; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret -; -; CHECK-LARGE-ZICFILP-LABEL: caller_varargs: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, -16 -; CHECK-LARGE-ZICFILP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi7: -; CHECK-LARGE-ZICFILP-NEXT: auipc a2, %pcrel_hi(.LCPI5_0) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi7)(a2) -; CHECK-LARGE-ZICFILP-NEXT: sw a0, 0(sp) -; CHECK-LARGE-ZICFILP-NEXT: mv a2, a1 -; CHECK-LARGE-ZICFILP-NEXT: mv a3, a0 -; CHECK-LARGE-ZICFILP-NEXT: mv a4, a0 -; CHECK-LARGE-ZICFILP-NEXT: mv a5, a1 -; CHECK-LARGE-ZICFILP-NEXT: mv a6, a1 -; CHECK-LARGE-ZICFILP-NEXT: mv a7, a0 -; CHECK-LARGE-ZICFILP-NEXT: jalr t2 -; CHECK-LARGE-ZICFILP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, 16 -; CHECK-LARGE-ZICFILP-NEXT: ret entry: %call = tail call i32 (i32, ...) @callee_varargs(i32 %a, i32 %b, i32 %b, i32 %a, i32 %a, i32 %b, i32 %b, i32 %a, i32 %a) ret void @@ -223,31 +134,6 @@ define i32 @caller_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g ; CHECK-NEXT: lw ra, 28(sp) # 4-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 32 ; CHECK-NEXT: ret -; -; CHECK-LARGE-ZICFILP-LABEL: caller_args: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, -32 -; CHECK-LARGE-ZICFILP-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: lw t0, 32(sp) -; CHECK-LARGE-ZICFILP-NEXT: lw t1, 36(sp) -; CHECK-LARGE-ZICFILP-NEXT: lw t3, 40(sp) -; CHECK-LARGE-ZICFILP-NEXT: lw t4, 44(sp) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, 48(sp) -; CHECK-LARGE-ZICFILP-NEXT: lw t5, 52(sp) -; CHECK-LARGE-ZICFILP-NEXT: sw t2, 16(sp) -; CHECK-LARGE-ZICFILP-NEXT: sw t5, 20(sp) -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi8: -; CHECK-LARGE-ZICFILP-NEXT: auipc t2, %pcrel_hi(.LCPI6_0) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi8)(t2) -; CHECK-LARGE-ZICFILP-NEXT: sw t0, 0(sp) -; CHECK-LARGE-ZICFILP-NEXT: sw t1, 4(sp) -; CHECK-LARGE-ZICFILP-NEXT: sw t3, 8(sp) -; CHECK-LARGE-ZICFILP-NEXT: sw t4, 12(sp) -; CHECK-LARGE-ZICFILP-NEXT: jalr t2 -; CHECK-LARGE-ZICFILP-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, 32 -; CHECK-LARGE-ZICFILP-NEXT: ret entry: %r = tail call i32 @callee_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) ret i32 %r @@ -270,25 +156,6 @@ define void @caller_indirect_args() nounwind { ; CHECK-NEXT: lw ra, 28(sp) # 4-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 32 ; CHECK-NEXT: ret -; -; CHECK-LARGE-ZICFILP-LABEL: caller_indirect_args: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, -32 -; CHECK-LARGE-ZICFILP-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: lui a1, 262128 -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi9: -; CHECK-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI7_0) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi9)(a0) -; CHECK-LARGE-ZICFILP-NEXT: mv a0, sp -; CHECK-LARGE-ZICFILP-NEXT: sw zero, 0(sp) -; CHECK-LARGE-ZICFILP-NEXT: sw zero, 4(sp) -; CHECK-LARGE-ZICFILP-NEXT: sw zero, 8(sp) -; CHECK-LARGE-ZICFILP-NEXT: sw a1, 12(sp) -; CHECK-LARGE-ZICFILP-NEXT: jalr t2 -; CHECK-LARGE-ZICFILP-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, 32 -; CHECK-LARGE-ZICFILP-NEXT: ret entry: %call = tail call i32 @callee_indirect_args(fp128 0xL00000000000000003FFF000000000000) ret void @@ -300,14 +167,6 @@ define void @caller_weak() nounwind { ; CHECK-LABEL: caller_weak: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: tail callee_weak -; -; CHECK-LARGE-ZICFILP-LABEL: caller_weak: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi10: -; CHECK-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI8_0) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi10)(a0) -; CHECK-LARGE-ZICFILP-NEXT: jr t2 entry: tail call void @callee_weak() ret void @@ -356,48 +215,6 @@ define void @caller_irq() nounwind "interrupt"="machine" { ; CHECK-NEXT: lw t6, 0(sp) # 4-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 64 ; CHECK-NEXT: mret -; -; CHECK-LARGE-ZICFILP-LABEL: caller_irq: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, -64 -; CHECK-LARGE-ZICFILP-NEXT: sw ra, 60(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw t0, 56(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw t1, 52(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw t2, 48(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw a0, 44(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw a1, 40(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw a2, 36(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw a3, 32(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw a4, 28(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw a5, 24(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw a6, 20(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw a7, 16(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw t3, 12(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw t4, 8(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw t5, 4(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: sw t6, 0(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi11: -; CHECK-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI9_0) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi11)(a0) -; CHECK-LARGE-ZICFILP-NEXT: jalr t2 -; CHECK-LARGE-ZICFILP-NEXT: lw ra, 60(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw t0, 56(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw t1, 52(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw t2, 48(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw a0, 44(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw a1, 40(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw a2, 36(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw a3, 32(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw a4, 28(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw a5, 24(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw a6, 20(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw a7, 16(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw t3, 12(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw t4, 8(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw t5, 4(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: lw t6, 0(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, 64 -; CHECK-LARGE-ZICFILP-NEXT: mret entry: tail call void @callee_irq() ret void @@ -419,22 +236,6 @@ define i32 @caller_byval() nounwind { ; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret -; -; CHECK-LARGE-ZICFILP-LABEL: caller_byval: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, -16 -; CHECK-LARGE-ZICFILP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: lw a0, 8(sp) -; CHECK-LARGE-ZICFILP-NEXT: sw a0, 4(sp) -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi12: -; CHECK-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI10_0) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi12)(a0) -; CHECK-LARGE-ZICFILP-NEXT: addi a0, sp, 4 -; CHECK-LARGE-ZICFILP-NEXT: jalr t2 -; CHECK-LARGE-ZICFILP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, 16 -; CHECK-LARGE-ZICFILP-NEXT: ret entry: %a = alloca ptr %r = tail call i32 @callee_byval(ptr byval(ptr) %a) @@ -457,22 +258,6 @@ define void @caller_nostruct() nounwind { ; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret -; -; CHECK-LARGE-ZICFILP-LABEL: caller_nostruct: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, -16 -; CHECK-LARGE-ZICFILP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi13: -; CHECK-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI11_0) -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi14: -; CHECK-LARGE-ZICFILP-NEXT: auipc a1, %pcrel_hi(.LCPI11_1) -; CHECK-LARGE-ZICFILP-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi13)(a0) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi14)(a1) -; CHECK-LARGE-ZICFILP-NEXT: jalr t2 -; CHECK-LARGE-ZICFILP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, 16 -; CHECK-LARGE-ZICFILP-NEXT: ret entry: tail call void @callee_struct(ptr sret(%struct.A) @a) ret void @@ -489,19 +274,6 @@ define void @caller_struct(ptr sret(%struct.A) %a) nounwind { ; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret -; -; CHECK-LARGE-ZICFILP-LABEL: caller_struct: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, -16 -; CHECK-LARGE-ZICFILP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi15: -; CHECK-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI12_0) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi15)(a0) -; CHECK-LARGE-ZICFILP-NEXT: jalr t2 -; CHECK-LARGE-ZICFILP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, 16 -; CHECK-LARGE-ZICFILP-NEXT: ret entry: tail call void @callee_nostruct() ret void @@ -517,19 +289,6 @@ define i32 @disable_tail_calls(i32 %i) nounwind "disable-tail-calls"="true" { ; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret -; -; CHECK-LARGE-ZICFILP-LABEL: disable_tail_calls: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, -16 -; CHECK-LARGE-ZICFILP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi16: -; CHECK-LARGE-ZICFILP-NEXT: auipc a1, %pcrel_hi(.LCPI13_0) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi16)(a1) -; CHECK-LARGE-ZICFILP-NEXT: jalr t2 -; CHECK-LARGE-ZICFILP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; CHECK-LARGE-ZICFILP-NEXT: addi sp, sp, 16 -; CHECK-LARGE-ZICFILP-NEXT: ret entry: %rv = tail call i32 @callee_tail(i32 %i) ret i32 %rv @@ -556,35 +315,6 @@ define i32 @duplicate_returns(i32 %a, i32 %b) nounwind { ; CHECK-NEXT: tail test1 ; CHECK-NEXT: .LBB14_6: # %if.else8 ; CHECK-NEXT: tail test3 -; -; CHECK-LARGE-ZICFILP-LABEL: duplicate_returns: -; CHECK-LARGE-ZICFILP: # %bb.0: # %entry -; CHECK-LARGE-ZICFILP-NEXT: lpad 0 -; CHECK-LARGE-ZICFILP-NEXT: beqz a0, .LBB14_4 -; CHECK-LARGE-ZICFILP-NEXT: # %bb.1: # %if.else -; CHECK-LARGE-ZICFILP-NEXT: beqz a1, .LBB14_5 -; CHECK-LARGE-ZICFILP-NEXT: # %bb.2: # %if.else4 -; CHECK-LARGE-ZICFILP-NEXT: bge a1, a0, .LBB14_6 -; CHECK-LARGE-ZICFILP-NEXT: # %bb.3: # %if.then6 -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi19: -; CHECK-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI14_1) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi19)(a0) -; CHECK-LARGE-ZICFILP-NEXT: jr t2 -; CHECK-LARGE-ZICFILP-NEXT: .LBB14_4: # %if.then -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi17: -; CHECK-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI14_3) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi17)(a0) -; CHECK-LARGE-ZICFILP-NEXT: jr t2 -; CHECK-LARGE-ZICFILP-NEXT: .LBB14_5: # %if.then2 -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi18: -; CHECK-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI14_2) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi18)(a0) -; CHECK-LARGE-ZICFILP-NEXT: jr t2 -; CHECK-LARGE-ZICFILP-NEXT: .LBB14_6: # %if.else8 -; CHECK-LARGE-ZICFILP-NEXT: .Lpcrel_hi20: -; CHECK-LARGE-ZICFILP-NEXT: auipc a0, %pcrel_hi(.LCPI14_0) -; CHECK-LARGE-ZICFILP-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi20)(a0) -; CHECK-LARGE-ZICFILP-NEXT: jr t2 entry: %cmp = icmp eq i32 %a, 0 br i1 %cmp, label %if.then, label %if.else diff --git a/llvm/test/CodeGen/RISCV/zicfilp-disabled-indirect-branch.ll b/llvm/test/CodeGen/RISCV/zicfilp-disabled-indirect-branch.ll new file mode 100644 index 0000000000000..897260908075c --- /dev/null +++ b/llvm/test/CodeGen/RISCV/zicfilp-disabled-indirect-branch.ll @@ -0,0 +1,41 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3 +; RUN: llc -mtriple=riscv64 -stop-after=finalize-isel < %s | FileCheck %s + +@brind.arr = internal unnamed_addr constant [2 x ptr] [ptr blockaddress(@brind, %5), ptr blockaddress(@brind, %8)], align 8 +@x = dso_local global i32 0, align 4 + +define void @brind(i32 noundef signext %0) { + ; CHECK-LABEL: name: brind + ; CHECK: PseudoBRIND killed [[VAR:%.*]], 0 + %2 = sext i32 %0 to i64 + %3 = getelementptr inbounds [2 x ptr], ptr @brind.arr, i64 0, i64 %2 + %4 = load ptr, ptr %3, align 8 + indirectbr ptr %4, [label %5, label %8] + +5: ; preds = %1 + %6 = load i32, ptr @x, align 4 + %7 = add nsw i32 %6, 2 + store i32 %7, ptr @x, align 4 + br label %8 + +8: ; preds = %5, %1 + %9 = load i32, ptr @x, align 4 + %10 = add nsw i32 %9, 1 + store i32 %10, ptr @x, align 4 + ret void +} + +define i32 @indirect_call(ptr %0) { + ; CHECK-LABEL: name: indirect_call + ; CHECK: PseudoCALLIndirect + call void %0() + ret i32 0 +} + + +define void @indirect_tail(ptr %0) { + ; CHECK-LABEL: name: indirect_tail + ; CHECK: PseudoTAILIndirect + tail call void %0() + ret void +} diff --git a/llvm/test/CodeGen/RISCV/zicfilp-indirect-branch.ll b/llvm/test/CodeGen/RISCV/zicfilp-indirect-branch.ll index bccd28ee7e2b3..c3a9a8b07687c 100644 --- a/llvm/test/CodeGen/RISCV/zicfilp-indirect-branch.ll +++ b/llvm/test/CodeGen/RISCV/zicfilp-indirect-branch.ll @@ -1,15 +1,12 @@ ; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3 -; RUN: llc -mtriple=riscv64 -stop-after=finalize-isel < %s | FileCheck %s -; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfilp -stop-after=finalize-isel < %s | FileCheck -check-prefixes=ZICFILP %s +; RUN: llc -mtriple=riscv64 -mattr=+zicfilp-unlabeled -stop-after=finalize-isel < %s | FileCheck %s @brind.arr = internal unnamed_addr constant [2 x ptr] [ptr blockaddress(@brind, %5), ptr blockaddress(@brind, %8)], align 8 @x = dso_local global i32 0, align 4 define void @brind(i32 noundef signext %0) { ; CHECK-LABEL: name: brind - ; CHECK: PseudoBRIND killed [[VAR:%.*]], 0 - ; ZICFILP-LABEL: name: brind - ; ZICFILP: PseudoBRINDNonX7 killed [[VAR:%.*]], 0 + ; CHECK: PseudoBRINDNonX7 killed [[VAR:%.*]], 0 %2 = sext i32 %0 to i64 %3 = getelementptr inbounds [2 x ptr], ptr @brind.arr, i64 0, i64 %2 %4 = load ptr, ptr %3, align 8 @@ -30,9 +27,7 @@ define void @brind(i32 noundef signext %0) { define i32 @indirect_call(ptr %0) { ; CHECK-LABEL: name: indirect_call - ; CHECK: PseudoCALLIndirect - ; ZICFILP-LABEL: name: indirect_call - ; ZICFILP: PseudoCALLIndirectNonX7 + ; CHECK: PseudoCALLIndirectNonX7 call void %0() ret i32 0 } @@ -40,9 +35,12 @@ define i32 @indirect_call(ptr %0) { define void @indirect_tail(ptr %0) { ; CHECK-LABEL: name: indirect_tail - ; CHECK: PseudoTAILIndirect - ; ZICFILP-LABEL: name: indirect_tail - ; ZICFILP: PseudoTAILIndirectNonX7 + ; CHECK: PseudoTAILIndirectNonX7 tail call void %0() ret void } + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 8, !"cf-protection-branch", i32 1} +!1 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} diff --git a/llvm/test/CodeGen/RISCV/zicfilp-unlabeled-calls.ll b/llvm/test/CodeGen/RISCV/zicfilp-unlabeled-calls.ll new file mode 100644 index 0000000000000..9e34f28792c0f --- /dev/null +++ b/llvm/test/CodeGen/RISCV/zicfilp-unlabeled-calls.ll @@ -0,0 +1,253 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -code-model=large -mtriple=riscv64 -mattr=+zicfilp-unlabeled -verify-machineinstrs < %s \ +; RUN: | FileCheck %s + +declare i32 @external_function(i32) + +define i32 @test_call_external(i32 %a) nounwind { +; CHECK-LABEL: test_call_external: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: .Lpcrel_hi0: +; CHECK-NEXT: auipc a1, %pcrel_hi(.LCPI0_0) +; CHECK-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi0)(a1) +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %1 = call i32 @external_function(i32 %a) + ret i32 %1 +} + +declare dso_local i32 @dso_local_function(i32) + +define i32 @test_call_dso_local(i32 %a) nounwind { +; CHECK-LABEL: test_call_dso_local: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: .Lpcrel_hi1: +; CHECK-NEXT: auipc a1, %pcrel_hi(.LCPI1_0) +; CHECK-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi1)(a1) +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %1 = call i32 @dso_local_function(i32 %a) + ret i32 %1 +} + +define i32 @defined_function(i32 %a) nounwind { +; CHECK-LABEL: defined_function: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addiw a0, a0, 1 +; CHECK-NEXT: ret + %1 = add i32 %a, 1 + ret i32 %1 +} + +define i32 @test_call_defined(i32 %a) nounwind { +; CHECK-LABEL: test_call_defined: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: .Lpcrel_hi2: +; CHECK-NEXT: auipc a1, %pcrel_hi(.LCPI3_0) +; CHECK-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi2)(a1) +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %1 = call i32 @defined_function(i32 %a) + ret i32 %1 +} + +define i32 @test_call_indirect(ptr %a, i32 %b) nounwind { +; CHECK-LABEL: test_call_indirect: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: mv a2, a0 +; CHECK-NEXT: mv a0, a1 +; CHECK-NEXT: jalr a2 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %1 = call i32 %a(i32 %b) + ret i32 %1 +} + +; Make sure we don't use t0 as the source for jalr as that is a hint to pop the +; return address stack on some microarchitectures. +define i32 @test_call_indirect_no_t0(ptr %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) nounwind { +; CHECK-LABEL: test_call_indirect_no_t0: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: mv t1, a0 +; CHECK-NEXT: mv a0, a1 +; CHECK-NEXT: mv a1, a2 +; CHECK-NEXT: mv a2, a3 +; CHECK-NEXT: mv a3, a4 +; CHECK-NEXT: mv a4, a5 +; CHECK-NEXT: mv a5, a6 +; CHECK-NEXT: mv a6, a7 +; CHECK-NEXT: jalr t1 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %1 = call i32 %a(i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) + ret i32 %1 +} + +; Ensure that calls to fastcc functions aren't rejected. Such calls may be +; introduced when compiling with optimisation. + +define fastcc i32 @fastcc_function(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: fastcc_function: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addw a0, a0, a1 +; CHECK-NEXT: ret + %1 = add i32 %a, %b + ret i32 %1 +} + +define i32 @test_call_fastcc(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: test_call_fastcc: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: sd s0, 0(sp) # 8-byte Folded Spill +; CHECK-NEXT: mv s0, a0 +; CHECK-NEXT: .Lpcrel_hi3: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI7_0) +; CHECK-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi3)(a0) +; CHECK-NEXT: mv a0, s0 +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: mv a0, s0 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: ld s0, 0(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %1 = call fastcc i32 @fastcc_function(i32 %a, i32 %b) + ret i32 %a +} + +declare i32 @external_many_args(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) nounwind + +define i32 @test_call_external_many_args(i32 %a) nounwind { +; CHECK-LABEL: test_call_external_many_args: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -32 +; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; CHECK-NEXT: mv s0, a0 +; CHECK-NEXT: .Lpcrel_hi4: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI8_0) +; CHECK-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi4)(a0) +; CHECK-NEXT: sd s0, 0(sp) +; CHECK-NEXT: sd s0, 8(sp) +; CHECK-NEXT: mv a0, s0 +; CHECK-NEXT: mv a1, s0 +; CHECK-NEXT: mv a2, s0 +; CHECK-NEXT: mv a3, s0 +; CHECK-NEXT: mv a4, s0 +; CHECK-NEXT: mv a5, s0 +; CHECK-NEXT: mv a6, s0 +; CHECK-NEXT: mv a7, s0 +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: mv a0, s0 +; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; CHECK-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 32 +; CHECK-NEXT: ret + %1 = call i32 @external_many_args(i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, + i32 %a, i32 %a, i32 %a, i32 %a, i32 %a) + ret i32 %a +} + +define i32 @defined_many_args(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 %j) nounwind { +; CHECK-LABEL: defined_many_args: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: lw a0, 8(sp) +; CHECK-NEXT: addiw a0, a0, 1 +; CHECK-NEXT: ret + %added = add i32 %j, 1 + ret i32 %added +} + +define i32 @test_call_defined_many_args(i32 %a) nounwind { +; CHECK-LABEL: test_call_defined_many_args: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -32 +; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; CHECK-NEXT: .Lpcrel_hi5: +; CHECK-NEXT: auipc a1, %pcrel_hi(.LCPI10_0) +; CHECK-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi5)(a1) +; CHECK-NEXT: sd a0, 0(sp) +; CHECK-NEXT: sd a0, 8(sp) +; CHECK-NEXT: mv a1, a0 +; CHECK-NEXT: mv a2, a0 +; CHECK-NEXT: mv a3, a0 +; CHECK-NEXT: mv a4, a0 +; CHECK-NEXT: mv a5, a0 +; CHECK-NEXT: mv a6, a0 +; CHECK-NEXT: mv a7, a0 +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 32 +; CHECK-NEXT: ret + %1 = call i32 @defined_many_args(i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, + i32 %a, i32 %a, i32 %a, i32 %a, i32 %a) + ret i32 %1 +} + +define fastcc void @fastcc_call_nonfastcc(){ +; CHECK-LABEL: fastcc_call_nonfastcc: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -32 +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; CHECK-NEXT: .cfi_offset ra, -8 +; CHECK-NEXT: li t0, 10 +; CHECK-NEXT: li t1, 9 +; CHECK-NEXT: .Lpcrel_hi6: +; CHECK-NEXT: auipc a5, %pcrel_hi(.LCPI11_0) +; CHECK-NEXT: li a0, 1 +; CHECK-NEXT: li a1, 2 +; CHECK-NEXT: li a2, 3 +; CHECK-NEXT: li a3, 4 +; CHECK-NEXT: li a4, 5 +; CHECK-NEXT: ld t2, %pcrel_lo(.Lpcrel_hi6)(a5) +; CHECK-NEXT: li a5, 6 +; CHECK-NEXT: li a6, 7 +; CHECK-NEXT: li a7, 8 +; CHECK-NEXT: sd t1, 0(sp) +; CHECK-NEXT: sd t0, 8(sp) +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; CHECK-NEXT: .cfi_restore ra +; CHECK-NEXT: addi sp, sp, 32 +; CHECK-NEXT: .cfi_def_cfa_offset 0 +; CHECK-NEXT: ret + call void @external_many_args(i32 1, i32 2,i32 3,i32 4,i32 5,i32 6,i32 7,i32 8,i32 9,i32 10) + ret void +} + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 8, !"cf-protection-branch", i32 1} +!1 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} diff --git a/llvm/test/CodeGen/RISCV/zicfilp-unlabeled-nest-register.ll b/llvm/test/CodeGen/RISCV/zicfilp-unlabeled-nest-register.ll new file mode 100644 index 0000000000000..a90c470ff23a4 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/zicfilp-unlabeled-nest-register.ll @@ -0,0 +1,38 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 -mattr=+zicfilp-unlabeled -verify-machineinstrs < %s | \ +; RUN: FileCheck -check-prefix=RV64I %s +; RUN: not llc -mtriple=riscv64 -mattr=+zicfilp-unlabeled -target-abi=lp64e -verify-machineinstrs < %s \ +; RUN: 2>&1 | FileCheck -check-prefix=LP64E %s + +; Tests that the 'nest' parameter attribute causes the relevant parameter to be +; passed in the right register. + +define ptr @nest_receiver(ptr nest %arg) nounwind { +; RV64I-LABEL: nest_receiver: +; RV64I: # %bb.0: +; RV64I-NEXT: auipc zero, 0 +; RV64I-NEXT: mv a0, t3 +; RV64I-NEXT: ret + ret ptr %arg +} + +define ptr @nest_caller(ptr %arg) nounwind { +; RV64I-LABEL: nest_caller: +; RV64I: # %bb.0: +; RV64I-NEXT: auipc zero, 0 +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: mv t3, a0 +; RV64I-NEXT: call nest_receiver +; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %result = call ptr @nest_receiver(ptr nest %arg) + ret ptr %result +} + +; LP64E: LLVM ERROR: Nested functions with control flow protection are not usable with ILP32E or LP64E ABI. +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 8, !"cf-protection-branch", i32 1} +!1 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} diff --git a/llvm/test/CodeGen/RISCV/zicfilp-unlabeled-tail-calls.ll b/llvm/test/CodeGen/RISCV/zicfilp-unlabeled-tail-calls.ll new file mode 100644 index 0000000000000..d444ef7951d2b --- /dev/null +++ b/llvm/test/CodeGen/RISCV/zicfilp-unlabeled-tail-calls.ll @@ -0,0 +1,434 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple riscv32-unknown-linux-gnu -mattr=+zicfilp-unlabeled -code-model=large -o - %s | FileCheck %s + +; Perform tail call optimization for global address. +declare i32 @callee_tail(i32 %i) +define i32 @caller_tail(i32 %i) nounwind { +; CHECK-LABEL: caller_tail: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: .Lpcrel_hi0: +; CHECK-NEXT: auipc a1, %pcrel_hi(.LCPI0_0) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi0)(a1) +; CHECK-NEXT: jr t2 +entry: + %r = tail call i32 @callee_tail(i32 %i) + ret i32 %r +} + +; Perform tail call optimization for external symbol. +@dest = global [2 x i8] zeroinitializer +declare void @llvm.memcpy.p0.p0.i32(ptr, ptr, i32, i1) +define void @caller_extern(ptr %src) optsize { +; CHECK-LABEL: caller_extern: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: .Lpcrel_hi1: +; CHECK-NEXT: auipc a1, %pcrel_hi(.LCPI1_0) +; CHECK-NEXT: .Lpcrel_hi2: +; CHECK-NEXT: auipc a2, %pcrel_hi(.LCPI1_1) +; CHECK-NEXT: lw a1, %pcrel_lo(.Lpcrel_hi1)(a1) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi2)(a2) +; CHECK-NEXT: li a2, 7 +; CHECK-NEXT: mv a3, a0 +; CHECK-NEXT: mv a0, a1 +; CHECK-NEXT: mv a1, a3 +; CHECK-NEXT: jr t2 +entry: + tail call void @llvm.memcpy.p0.p0.i32(ptr @dest, ptr %src, i32 7, i1 false) + ret void +} + +; Perform tail call optimization for external symbol. +@dest_pgso = global [2 x i8] zeroinitializer +define void @caller_extern_pgso(ptr %src) !prof !14 { +; CHECK-LABEL: caller_extern_pgso: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: .Lpcrel_hi3: +; CHECK-NEXT: auipc a1, %pcrel_hi(.LCPI2_0) +; CHECK-NEXT: .Lpcrel_hi4: +; CHECK-NEXT: auipc a2, %pcrel_hi(.LCPI2_1) +; CHECK-NEXT: lw a1, %pcrel_lo(.Lpcrel_hi3)(a1) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi4)(a2) +; CHECK-NEXT: li a2, 7 +; CHECK-NEXT: mv a3, a0 +; CHECK-NEXT: mv a0, a1 +; CHECK-NEXT: mv a1, a3 +; CHECK-NEXT: jr t2 +entry: + tail call void @llvm.memcpy.p0.p0.i32(ptr @dest_pgso, ptr %src, i32 7, i1 false) + ret void +} + +; Perform indirect tail call optimization (for function pointer call). +declare void @callee_indirect1() +declare void @callee_indirect2() +define void @caller_indirect_tail(i32 %a) nounwind { +; CHECK-LABEL: caller_indirect_tail: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: beqz a0, .LBB3_2 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: .Lpcrel_hi6: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI3_0) +; CHECK-NEXT: lw t1, %pcrel_lo(.Lpcrel_hi6)(a0) +; CHECK-NEXT: jr t1 +; CHECK-NEXT: .LBB3_2: +; CHECK-NEXT: .Lpcrel_hi5: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI3_1) +; CHECK-NEXT: lw t1, %pcrel_lo(.Lpcrel_hi5)(a0) +; CHECK-NEXT: jr t1 +entry: + %tobool = icmp eq i32 %a, 0 + %callee = select i1 %tobool, ptr @callee_indirect1, ptr @callee_indirect2 + tail call void %callee() + ret void +} + +; Make sure we don't use t0 as the source for jr as that is a hint to pop the +; return address stack on some microarchitectures. +define i32 @caller_indirect_no_t0(ptr %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7) { +; CHECK-LABEL: caller_indirect_no_t0: +; CHECK: # %bb.0: +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: mv t1, a0 +; CHECK-NEXT: mv a0, a1 +; CHECK-NEXT: mv a1, a2 +; CHECK-NEXT: mv a2, a3 +; CHECK-NEXT: mv a3, a4 +; CHECK-NEXT: mv a4, a5 +; CHECK-NEXT: mv a5, a6 +; CHECK-NEXT: mv a6, a7 +; CHECK-NEXT: jr t1 + %9 = tail call i32 %0(i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7) + ret i32 %9 +} + +; Do not tail call optimize functions with varargs passed by stack. +declare i32 @callee_varargs(i32, ...) +define void @caller_varargs(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: caller_varargs: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; CHECK-NEXT: .Lpcrel_hi7: +; CHECK-NEXT: auipc a2, %pcrel_hi(.LCPI5_0) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi7)(a2) +; CHECK-NEXT: sw a0, 0(sp) +; CHECK-NEXT: mv a2, a1 +; CHECK-NEXT: mv a3, a0 +; CHECK-NEXT: mv a4, a0 +; CHECK-NEXT: mv a5, a1 +; CHECK-NEXT: mv a6, a1 +; CHECK-NEXT: mv a7, a0 +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret +entry: + %call = tail call i32 (i32, ...) @callee_varargs(i32 %a, i32 %b, i32 %b, i32 %a, i32 %a, i32 %b, i32 %b, i32 %a, i32 %a) + ret void +} + +; Do not tail call optimize if stack is used to pass parameters. +declare i32 @callee_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) +define i32 @caller_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) nounwind { +; CHECK-LABEL: caller_args: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -32 +; CHECK-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; CHECK-NEXT: lw t0, 32(sp) +; CHECK-NEXT: lw t1, 36(sp) +; CHECK-NEXT: lw t3, 40(sp) +; CHECK-NEXT: lw t4, 44(sp) +; CHECK-NEXT: lw t2, 48(sp) +; CHECK-NEXT: lw t5, 52(sp) +; CHECK-NEXT: sw t2, 16(sp) +; CHECK-NEXT: sw t5, 20(sp) +; CHECK-NEXT: .Lpcrel_hi8: +; CHECK-NEXT: auipc t2, %pcrel_hi(.LCPI6_0) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi8)(t2) +; CHECK-NEXT: sw t0, 0(sp) +; CHECK-NEXT: sw t1, 4(sp) +; CHECK-NEXT: sw t3, 8(sp) +; CHECK-NEXT: sw t4, 12(sp) +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: lw ra, 28(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 32 +; CHECK-NEXT: ret +entry: + %r = tail call i32 @callee_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) + ret i32 %r +} + +; Do not tail call optimize if parameters need to be passed indirectly. +declare i32 @callee_indirect_args(fp128 %a) +define void @caller_indirect_args() nounwind { +; CHECK-LABEL: caller_indirect_args: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -32 +; CHECK-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; CHECK-NEXT: lui a1, 262128 +; CHECK-NEXT: .Lpcrel_hi9: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI7_0) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi9)(a0) +; CHECK-NEXT: mv a0, sp +; CHECK-NEXT: sw zero, 0(sp) +; CHECK-NEXT: sw zero, 4(sp) +; CHECK-NEXT: sw zero, 8(sp) +; CHECK-NEXT: sw a1, 12(sp) +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: lw ra, 28(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 32 +; CHECK-NEXT: ret +entry: + %call = tail call i32 @callee_indirect_args(fp128 0xL00000000000000003FFF000000000000) + ret void +} + +; Perform tail call optimization for external weak symbol. +declare extern_weak void @callee_weak() +define void @caller_weak() nounwind { +; CHECK-LABEL: caller_weak: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: .Lpcrel_hi10: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI8_0) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi10)(a0) +; CHECK-NEXT: jr t2 +entry: + tail call void @callee_weak() + ret void +} + +; Exception-handling functions need a special set of instructions to indicate a +; return to the hardware. Tail-calling another function would probably break +; this. +declare void @callee_irq() +define void @caller_irq() nounwind "interrupt"="machine" { +; CHECK-LABEL: caller_irq: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: addi sp, sp, -64 +; CHECK-NEXT: sw ra, 60(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw t0, 56(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw t1, 52(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw t2, 48(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw a0, 44(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw a1, 40(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw a2, 36(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw a3, 32(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw a4, 28(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw a5, 24(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw a6, 20(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw a7, 16(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw t3, 12(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw t4, 8(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw t5, 4(sp) # 4-byte Folded Spill +; CHECK-NEXT: sw t6, 0(sp) # 4-byte Folded Spill +; CHECK-NEXT: .Lpcrel_hi11: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI9_0) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi11)(a0) +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: lw ra, 60(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw t0, 56(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw t1, 52(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw t2, 48(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw a0, 44(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw a1, 40(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw a2, 36(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw a3, 32(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw a4, 28(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw a5, 24(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw a6, 20(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw a7, 16(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw t3, 12(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw t4, 8(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw t5, 4(sp) # 4-byte Folded Reload +; CHECK-NEXT: lw t6, 0(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 64 +; CHECK-NEXT: mret +entry: + tail call void @callee_irq() + ret void +} + +; Byval parameters hand the function a pointer directly into the stack area +; we want to reuse during a tail call. Do not tail call optimize functions with +; byval parameters. +declare i32 @callee_byval(ptr byval(ptr) %a) +define i32 @caller_byval() nounwind { +; CHECK-LABEL: caller_byval: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; CHECK-NEXT: lw a0, 8(sp) +; CHECK-NEXT: sw a0, 4(sp) +; CHECK-NEXT: .Lpcrel_hi12: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI10_0) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi12)(a0) +; CHECK-NEXT: addi a0, sp, 4 +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret +entry: + %a = alloca ptr + %r = tail call i32 @callee_byval(ptr byval(ptr) %a) + ret i32 %r +} + +; Do not tail call optimize if callee uses structret semantics. +%struct.A = type { i32 } +@a = global %struct.A zeroinitializer + +declare void @callee_struct(ptr sret(%struct.A) %a) +define void @caller_nostruct() nounwind { +; CHECK-LABEL: caller_nostruct: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; CHECK-NEXT: .Lpcrel_hi13: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI11_0) +; CHECK-NEXT: .Lpcrel_hi14: +; CHECK-NEXT: auipc a1, %pcrel_hi(.LCPI11_1) +; CHECK-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi13)(a0) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi14)(a1) +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret +entry: + tail call void @callee_struct(ptr sret(%struct.A) @a) + ret void +} + +; Do not tail call optimize if caller uses structret semantics. +declare void @callee_nostruct() +define void @caller_struct(ptr sret(%struct.A) %a) nounwind { +; CHECK-LABEL: caller_struct: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; CHECK-NEXT: .Lpcrel_hi15: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI12_0) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi15)(a0) +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret +entry: + tail call void @callee_nostruct() + ret void +} + +; Do not tail call optimize if disabled. +define i32 @disable_tail_calls(i32 %i) nounwind "disable-tail-calls"="true" { +; CHECK-LABEL: disable_tail_calls: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; CHECK-NEXT: .Lpcrel_hi16: +; CHECK-NEXT: auipc a1, %pcrel_hi(.LCPI13_0) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi16)(a1) +; CHECK-NEXT: jalr t2 +; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret +entry: + %rv = tail call i32 @callee_tail(i32 %i) + ret i32 %rv +} + +; Duplicate returns to enable tail call optimizations. +declare i32 @test() +declare i32 @test1() +declare i32 @test2() +declare i32 @test3() +define i32 @duplicate_returns(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: duplicate_returns: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: auipc zero, 0 +; CHECK-NEXT: beqz a0, .LBB14_4 +; CHECK-NEXT: # %bb.1: # %if.else +; CHECK-NEXT: beqz a1, .LBB14_5 +; CHECK-NEXT: # %bb.2: # %if.else4 +; CHECK-NEXT: bge a1, a0, .LBB14_6 +; CHECK-NEXT: # %bb.3: # %if.then6 +; CHECK-NEXT: .Lpcrel_hi19: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI14_1) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi19)(a0) +; CHECK-NEXT: jr t2 +; CHECK-NEXT: .LBB14_4: # %if.then +; CHECK-NEXT: .Lpcrel_hi17: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI14_3) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi17)(a0) +; CHECK-NEXT: jr t2 +; CHECK-NEXT: .LBB14_5: # %if.then2 +; CHECK-NEXT: .Lpcrel_hi18: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI14_2) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi18)(a0) +; CHECK-NEXT: jr t2 +; CHECK-NEXT: .LBB14_6: # %if.else8 +; CHECK-NEXT: .Lpcrel_hi20: +; CHECK-NEXT: auipc a0, %pcrel_hi(.LCPI14_0) +; CHECK-NEXT: lw t2, %pcrel_lo(.Lpcrel_hi20)(a0) +; CHECK-NEXT: jr t2 +entry: + %cmp = icmp eq i32 %a, 0 + br i1 %cmp, label %if.then, label %if.else + +if.then: ; preds = %entry + %call = tail call i32 @test() + br label %return + +if.else: ; preds = %entry + %cmp1 = icmp eq i32 %b, 0 + br i1 %cmp1, label %if.then2, label %if.else4 + +if.then2: ; preds = %if.else + %call3 = tail call i32 @test1() + br label %return + +if.else4: ; preds = %if.else + %cmp5 = icmp sgt i32 %a, %b + br i1 %cmp5, label %if.then6, label %if.else8 + +if.then6: ; preds = %if.else4 + %call7 = tail call i32 @test2() + br label %return + +if.else8: ; preds = %if.else4 + %call9 = tail call i32 @test3() + br label %return + +return: ; preds = %if.else8, %if.then6, %if.then2, %if.then + %retval = phi i32 [ %call, %if.then ], [ %call3, %if.then2 ], [ %call7, %if.then6 ], [ %call9, %if.else8 ] + ret i32 %retval +} + +!llvm.module.flags = !{!0, !15, !16} +!0 = !{i32 1, !"ProfileSummary", !1} +!1 = !{!2, !3, !4, !5, !6, !7, !8, !9} +!2 = !{!"ProfileFormat", !"InstrProf"} +!3 = !{!"TotalCount", i64 10000} +!4 = !{!"MaxCount", i64 10} +!5 = !{!"MaxInternalCount", i64 1} +!6 = !{!"MaxFunctionCount", i64 1000} +!7 = !{!"NumCounts", i64 3} +!8 = !{!"NumFunctions", i64 3} +!9 = !{!"DetailedSummary", !10} +!10 = !{!11, !12, !13} +!11 = !{i32 10000, i64 100, i32 1} +!12 = !{i32 999000, i64 100, i32 1} +!13 = !{i32 999999, i64 1, i32 2} +!14 = !{!"function_entry_count", i64 0} +!15 = !{i32 8, !"cf-protection-branch", i32 1} +!16 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} diff --git a/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv32-foo-disabled.ll b/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv32-foo-disabled.ll new file mode 100644 index 0000000000000..45090922eafd0 --- /dev/null +++ b/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv32-foo-disabled.ll @@ -0,0 +1,18 @@ +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-linux-gnu" + +; Function Attrs: noinline nounwind optnone +define dso_local i32 @foo() #0 { +entry: + ret i32 0 +} + +attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv32" "target-features"="+32bit" } + +!llvm.module.flags = !{!0, !1, !2, !4} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"target-abi", !"ilp32"} +!2 = !{i32 6, !"riscv-isa", !3} +!3 = !{!"rv32i2p1"} +!4 = !{i32 8, !"SmallDataLimit", i32 0} diff --git a/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv32-foo-unknown-scheme.ll b/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv32-foo-unknown-scheme.ll new file mode 100644 index 0000000000000..c390edddb0c0a --- /dev/null +++ b/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv32-foo-unknown-scheme.ll @@ -0,0 +1,20 @@ +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-linux-gnu" + +; Function Attrs: noinline nounwind optnone +define dso_local i32 @foo() #0 { +entry: + ret i32 0 +} + +attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv32" "target-features"="+32bit" } + +!llvm.module.flags = !{!0, !1, !2, !4, !5, !6} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"target-abi", !"ilp32"} +!2 = !{i32 6, !"riscv-isa", !3} +!3 = !{!"rv32i2p1"} +!4 = !{i32 8, !"cf-protection-branch", i32 1} +!5 = !{i32 1, !"cf-branch-label-scheme", !"unknown-scheme"} +!6 = !{i32 8, !"SmallDataLimit", i32 0} diff --git a/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv32-foo-unlabeled.ll b/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv32-foo-unlabeled.ll new file mode 100644 index 0000000000000..7c6f56422683e --- /dev/null +++ b/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv32-foo-unlabeled.ll @@ -0,0 +1,20 @@ +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-linux-gnu" + +; Function Attrs: noinline nounwind optnone +define dso_local i32 @foo() #0 { +entry: + ret i32 0 +} + +attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv32" "target-features"="+32bit" } + +!llvm.module.flags = !{!0, !1, !2, !4, !5, !6} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"target-abi", !"ilp32"} +!2 = !{i32 6, !"riscv-isa", !3} +!3 = !{!"rv32i2p1"} +!4 = !{i32 8, !"cf-protection-branch", i32 1} +!5 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} +!6 = !{i32 8, !"SmallDataLimit", i32 0} diff --git a/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv64-foo-disabled.ll b/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv64-foo-disabled.ll new file mode 100644 index 0000000000000..e59f8ec41c1a6 --- /dev/null +++ b/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv64-foo-disabled.ll @@ -0,0 +1,18 @@ +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" +target triple = "riscv64-unknown-linux-gnu" + +; Function Attrs: noinline nounwind optnone +define dso_local signext i32 @foo() #0 { +entry: + ret i32 0 +} + +attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv64" "target-features"="+64bit" } + +!llvm.module.flags = !{!0, !1, !2, !4} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"target-abi", !"lp64"} +!2 = !{i32 6, !"riscv-isa", !3} +!3 = !{!"rv64i2p1"} +!4 = !{i32 8, !"SmallDataLimit", i32 0} diff --git a/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv64-foo-unknown-scheme.ll b/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv64-foo-unknown-scheme.ll new file mode 100644 index 0000000000000..f308f10dd718d --- /dev/null +++ b/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv64-foo-unknown-scheme.ll @@ -0,0 +1,20 @@ +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" +target triple = "riscv64-unknown-linux-gnu" + +; Function Attrs: noinline nounwind optnone +define dso_local signext i32 @foo() #0 { +entry: + ret i32 0 +} + +attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv64" "target-features"="+64bit" } + +!llvm.module.flags = !{!0, !1, !2, !4, !5, !6} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"target-abi", !"lp64"} +!2 = !{i32 6, !"riscv-isa", !3} +!3 = !{!"rv64i2p1"} +!4 = !{i32 8, !"cf-protection-branch", i32 1} +!5 = !{i32 1, !"cf-branch-label-scheme", !"unknown-scheme"} +!6 = !{i32 8, !"SmallDataLimit", i32 0} diff --git a/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv64-foo-unlabeled.ll b/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv64-foo-unlabeled.ll new file mode 100644 index 0000000000000..0aa7f112ba942 --- /dev/null +++ b/llvm/test/LTO/RISCV/branch-cfi/Inputs/rv64-foo-unlabeled.ll @@ -0,0 +1,20 @@ +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" +target triple = "riscv64-unknown-linux-gnu" + +; Function Attrs: noinline nounwind optnone +define dso_local signext i32 @foo() #0 { +entry: + ret i32 0 +} + +attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv64" "target-features"="+64bit" } + +!llvm.module.flags = !{!0, !1, !2, !4, !5, !6} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"target-abi", !"lp64"} +!2 = !{i32 6, !"riscv-isa", !3} +!3 = !{!"rv64i2p1"} +!4 = !{i32 8, !"cf-protection-branch", i32 1} +!5 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} +!6 = !{i32 8, !"SmallDataLimit", i32 0} diff --git a/llvm/test/LTO/RISCV/branch-cfi/rv32-unlabeled.ll b/llvm/test/LTO/RISCV/branch-cfi/rv32-unlabeled.ll new file mode 100644 index 0000000000000..cb29af67b777e --- /dev/null +++ b/llvm/test/LTO/RISCV/branch-cfi/rv32-unlabeled.ll @@ -0,0 +1,43 @@ +; RUN: llvm-as %s -o %t.main.bc +; RUN: llvm-as %p/Inputs/rv32-foo-unlabeled.ll -o %t.foo.unlabeled.bc +; RUN: llvm-link %t.main.bc %t.foo.unlabeled.bc -S | FileCheck --check-prefix=UNLABELED %s + +; RUN: llvm-as %p/Inputs/rv32-foo-disabled.ll -o %t.foo.disabled.bc +; RUN: llvm-link %t.main.bc %t.foo.disabled.bc -S | FileCheck --check-prefix=DISABLED %s + +; RUN: llvm-as %p/Inputs/rv32-foo-unknown-scheme.ll -o %t.foo.unknown.scheme.bc +; RUN: not llvm-link %t.main.bc %t.foo.unknown.scheme.bc 2>&1 | FileCheck --check-prefix=SCHEME-CONFLICT %s + +target datalayout = "e-m:e-p:32:32-i64:64-n32-S128" +target triple = "riscv32-unknown-linux-gnu" + +; Function Attrs: noinline nounwind optnone +define dso_local i32 @main() #0 { +entry: + %retval = alloca i32, align 4 + store i32 0, ptr %retval, align 4 + %call = call i32 @foo() + ret i32 %call +} + +declare dso_local i32 @foo() #1 + +attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv32" "target-features"="+32bit" } +attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv32" "target-features"="+32bit" } + +!llvm.module.flags = !{!0, !1, !2, !4, !5, !6} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"target-abi", !"ilp32"} +!2 = !{i32 6, !"riscv-isa", !3} +!3 = !{!"rv32i2p1"} +; UNLABELED-DAG: [[P_FLAG:![0-9]+]] = !{i32 8, !"cf-protection-branch", i32 1} +; DISABLED-DAG: [[P_FLAG:![0-9]+]] = !{i32 8, !"cf-protection-branch", i32 0} +!4 = !{i32 8, !"cf-protection-branch", i32 1} +; UNLABELED-DAG: [[S_FLAG:![0-9]+]] = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} +!5 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} +!6 = !{i32 8, !"SmallDataLimit", i32 0} +; UNLABELED-DAG: !llvm.module.flags = !{{[{].*}}[[P_FLAG]]{{, .*}}[[S_FLAG]]{{[,}]}} +; DISABLED-DAG: !llvm.module.flags = !{{[{].*}}[[P_FLAG]]{{[,}]}} + +; SCHEME-CONFLICT: error: linking module flags 'cf-branch-label-scheme': IDs have conflicting values: '!"unknown-scheme"' from {{.*}}, and '!"unlabeled"' from llvm-link diff --git a/llvm/test/LTO/RISCV/branch-cfi/rv64-unlabeled.ll b/llvm/test/LTO/RISCV/branch-cfi/rv64-unlabeled.ll new file mode 100644 index 0000000000000..b0897a8462319 --- /dev/null +++ b/llvm/test/LTO/RISCV/branch-cfi/rv64-unlabeled.ll @@ -0,0 +1,43 @@ +; RUN: llvm-as %s -o %t.main.bc +; RUN: llvm-as %p/Inputs/rv64-foo-unlabeled.ll -o %t.foo.unlabeled.bc +; RUN: llvm-link %t.main.bc %t.foo.unlabeled.bc -S | FileCheck --check-prefix=UNLABELED %s + +; RUN: llvm-as %p/Inputs/rv64-foo-disabled.ll -o %t.foo.disabled.bc +; RUN: llvm-link %t.main.bc %t.foo.disabled.bc -S | FileCheck --check-prefix=DISABLED %s + +; RUN: llvm-as %p/Inputs/rv64-foo-unknown-scheme.ll -o %t.foo.unknown.scheme.bc +; RUN: not llvm-link %t.main.bc %t.foo.unknown.scheme.bc 2>&1 | FileCheck --check-prefix=SCHEME-CONFLICT %s + +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" +target triple = "riscv64-unknown-linux-gnu" + +; Function Attrs: noinline nounwind optnone +define dso_local signext i32 @main() #0 { +entry: + %retval = alloca i32, align 4 + store i32 0, ptr %retval, align 4 + %call = call signext i32 @foo() + ret i32 %call +} + +declare dso_local signext i32 @foo() #1 + +attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv64" "target-features"="+64bit" } +attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv64" "target-features"="+64bit" } + +!llvm.module.flags = !{!0, !1, !2, !4, !5, !6} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, !"target-abi", !"lp64"} +!2 = !{i32 6, !"riscv-isa", !3} +!3 = !{!"rv64i2p1"} +; UNLABELED-DAG: [[P_FLAG:![0-9]+]] = !{i32 8, !"cf-protection-branch", i32 1} +; DISABLED-DAG: [[P_FLAG:![0-9]+]] = !{i32 8, !"cf-protection-branch", i32 0} +!4 = !{i32 8, !"cf-protection-branch", i32 1} +; UNLABELED-DAG: [[S_FLAG:![0-9]+]] = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} +!5 = !{i32 1, !"cf-branch-label-scheme", !"unlabeled"} +!6 = !{i32 8, !"SmallDataLimit", i32 0} +; UNLABELED-DAG: !llvm.module.flags = !{{[{].*}}[[P_FLAG]]{{, .*}}[[S_FLAG]]{{[,}]}} +; DISABLED-DAG: !llvm.module.flags = !{{[{].*}}[[P_FLAG]]{{[,}]}} + +; SCHEME-CONFLICT: error: linking module flags 'cf-branch-label-scheme': IDs have conflicting values: '!"unknown-scheme"' from {{.*}}, and '!"unlabeled"' from llvm-link