diff options
27 files changed, 150 insertions, 26 deletions
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index e4539ab080e..32038dc7334 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2009,6 +2009,10 @@ def mno_stackrealign : Flag<["-"], "mno-stackrealign">, Group<m_Group>; def mretpoline : Flag<["-"], "mretpoline">, Group<m_Group>, Flags<[CoreOption,DriverOption]>; def mno_retpoline : Flag<["-"], "mno-retpoline">, Group<m_Group>, Flags<[CoreOption,DriverOption]>; +def mspeculative_load_hardening : Flag<["-"], "mspeculative-load-hardening">, + Group<m_Group>, Flags<[CoreOption,CC1Option]>; +def mno_speculative_load_hardening : Flag<["-"], "mno-speculative-load-hardening">, + Group<m_Group>, Flags<[CoreOption]>; def mrelax : Flag<["-"], "mrelax">, Group<m_riscv_Features_Group>, HelpText<"Enable linker relaxation">; diff --git a/clang/include/clang/Frontend/CodeGenOptions.def b/clang/include/clang/Frontend/CodeGenOptions.def index 4968e7b2bf3..f94979c3e61 100644 --- a/clang/include/clang/Frontend/CodeGenOptions.def +++ b/clang/include/clang/Frontend/CodeGenOptions.def @@ -211,6 +211,7 @@ CODEGENOPT(SanitizeCoverageStackDepth, 1, 0) ///< Enable max stack depth tracing CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers. CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. +CODEGENOPT(SpeculativeLoadHardening, 1, 0) ///< Enable speculative load hardening. CODEGENOPT(FineGrainedBitfieldAccesses, 1, 0) ///< Enable fine-grained bitfield accesses. CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index c2b4c95ae9e..8857ffdde49 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1784,6 +1784,9 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone, FuncAttrs.addAttribute("stackrealign"); if (CodeGenOpts.Backchain) FuncAttrs.addAttribute("backchain"); + + if (CodeGenOpts.SpeculativeLoadHardening) + FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening); } if (getLangOpts().assumeFunctionsAreConvergent()) { diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp index ff2023c2cbe..bc707857d8f 100644 --- a/clang/lib/Driver/ToolChains/Arch/X86.cpp +++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp @@ -146,15 +146,23 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, // Translate the high level `-mretpoline` flag to the specific target feature // flags. We also detect if the user asked for retpoline external thunks but - // failed to ask for retpolines themselves. This is a bit hacky but keeps - // existing usages working. We should consider deprecated this and instead - // warning if the user requests external retpoline thunks and *doesn't* - // request some form of retpolines. - if (Args.hasArgNoClaim(options::OPT_mretpoline, options::OPT_mno_retpoline)) { + // failed to ask for retpolines themselves (through any of the different + // flags). This is a bit hacky but keeps existing usages working. We should + // consider deprecating this and instead warn if the user requests external + // retpoline thunks and *doesn't* request some form of retpolines. + if (Args.hasArgNoClaim(options::OPT_mretpoline, options::OPT_mno_retpoline, + options::OPT_mspeculative_load_hardening, + options::OPT_mno_speculative_load_hardening)) { if (Args.hasFlag(options::OPT_mretpoline, options::OPT_mno_retpoline, false)) { Features.push_back("+retpoline-indirect-calls"); Features.push_back("+retpoline-indirect-branches"); + } else if (Args.hasFlag(options::OPT_mspeculative_load_hardening, + options::OPT_mno_speculative_load_hardening, + false)) { + // On x86, speculative load hardening relies on at least using retpolines + // for indirect calls. + Features.push_back("+retpoline-indirect-calls"); } } else if (Args.hasFlag(options::OPT_mretpoline_external_thunk, options::OPT_mno_retpoline_external_thunk, false)) { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index ff083c79f10..79129a7a7c6 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4132,6 +4132,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_pthread); + Args.AddLastArg(CmdArgs, options::OPT_mspeculative_load_hardening, + options::OPT_mno_speculative_load_hardening); + RenderSSPOptions(getToolChain(), Args, CmdArgs, KernelOrKext); // Translate -mstackrealign diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 4ac79293282..5210314493d 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1147,6 +1147,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.KeepStaticConsts = Args.hasArg(OPT_fkeep_static_consts); + Opts.SpeculativeLoadHardening = Args.hasArg(OPT_mspeculative_load_hardening); + return Success; } diff --git a/clang/test/CodeGen/attr-speculative-load-hardening.c b/clang/test/CodeGen/attr-speculative-load-hardening.c new file mode 100644 index 00000000000..ccbded44bb4 --- /dev/null +++ b/clang/test/CodeGen/attr-speculative-load-hardening.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -mspeculative-load-hardening -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s -check-prefix=SLH +// +// Check that we set the attribute on each function. + +int test1() { + return 42; +} +// SLH: @{{.*}}test1{{.*}}[[SLH:#[0-9]+]] + +// SLH: attributes [[SLH]] = { {{.*}}speculative_load_hardening{{.*}} } diff --git a/clang/test/Driver/x86-target-features.c b/clang/test/Driver/x86-target-features.c index 527a9a2cfff..ee2e6afd615 100644 --- a/clang/test/Driver/x86-target-features.c +++ b/clang/test/Driver/x86-target-features.c @@ -140,6 +140,15 @@ // RETPOLINE-EXTERNAL-THUNK: "-target-feature" "+retpoline-external-thunk" // NO-RETPOLINE-EXTERNAL-THUNK: "-target-feature" "-retpoline-external-thunk" +// RUN: %clang -target i386-linux-gnu -mspeculative-load-hardening %s -### -o %t.o 2>&1 | FileCheck -check-prefix=SLH %s +// RUN: %clang -target i386-linux-gnu -mretpoline -mspeculative-load-hardening %s -### -o %t.o 2>&1 | FileCheck -check-prefix=RETPOLINE %s +// RUN: %clang -target i386-linux-gnu -mno-speculative-load-hardening %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-SLH %s +// SLH-NOT: retpoline +// SLH: "-target-feature" "+retpoline-indirect-calls" +// SLH-NOT: retpoline +// SLH: "-mspeculative-load-hardening" +// NO-SLH-NOT: retpoline + // RUN: %clang -target i386-linux-gnu -mwaitpkg %s -### -o %t.o 2>&1 | FileCheck -check-prefix=WAITPKG %s // RUN: %clang -target i386-linux-gnu -mno-waitpkg %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-WAITPKG %s // WAITPKG: "-target-feature" "+waitpkg" diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 167a33e7c3d..2aba2077653 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -1636,6 +1636,28 @@ example: This attribute indicates that HWAddressSanitizer checks (dynamic address safety analysis based on tagged pointers) are enabled for this function. +``speculative_load_hardening`` + This attribute indicates that + `Speculative Load Hardening <https://llvm.org/docs/SpeculativeLoadHardening.html>`_ + should be enabled for the function body. This is a best-effort attempt to + mitigate all known speculative execution information leak vulnerabilities + that are based on the fundamental principles of modern processors' + speculative execution. These vulnerabilities are classified as "Spectre + variant #1" vulnerabilities typically. Notably, this does not attempt to + mitigate any vulnerabilities where the speculative execution and/or + prediction devices of specific processors can be *completely* undermined + (such as "Branch Target Injection", a.k.a, "Spectre variant #2"). Instead, + this is a target-independent request to harden against the completely + generic risk posed by speculative execution to incorrectly load secret data, + making it available to some micro-architectural side-channel for information + leak. For a processor without any speculative execution or predictors, this + is expected to be a no-op. + + When inlining, the attribute is sticky. Inlining a function that carries + this attribute will cause the caller to gain the attribute. This is intended + to provide a maximally conservative model where the code in a function + annotated with this attribute will always (even after inlining) end up + hardened. ``speculatable`` This function attribute indicates that the function does not have any effects besides calculating its result and does not have undefined behavior. diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 6723cf42dd2..5467ecc2626 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -591,6 +591,7 @@ enum AttributeKindCodes { ATTR_KIND_NOCF_CHECK = 56, ATTR_KIND_OPT_FOR_FUZZING = 57, ATTR_KIND_SHADOWCALLSTACK = 58, + ATTR_KIND_SPECULATIVE_LOAD_HARDENING = 59, }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td index 39978c41ac7..e786d85d05a 100644 --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -176,6 +176,14 @@ def SanitizeMemory : EnumAttr<"sanitize_memory">; /// HWAddressSanitizer is on. def SanitizeHWAddress : EnumAttr<"sanitize_hwaddress">; +/// Speculative Load Hardening is enabled. +/// +/// Note that this uses the default compatibility (always compatible during +/// inlining) and a conservative merge strategy where inlining an attributed +/// body will add the attribute to the caller. This ensures that code carrying +/// this attribute will always be lowered with hardening enabled. +def SpeculativeLoadHardening : EnumAttr<"speculative_load_hardening">; + /// Argument is swift error. def SwiftError : EnumAttr<"swifterror">; @@ -232,6 +240,7 @@ def : MergeRule<"setAND<UnsafeFPMathAttr>">; def : MergeRule<"setOR<NoImplicitFloatAttr>">; def : MergeRule<"setOR<NoJumpTablesAttr>">; def : MergeRule<"setOR<ProfileSampleAccurateAttr>">; +def : MergeRule<"setOR<SpeculativeLoadHardeningAttr>">; def : MergeRule<"adjustCallerSSPLevel">; def : MergeRule<"adjustCallerStackProbes">; def : MergeRule<"adjustCallerStackProbeSize">; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index d868ec286aa..f4e340b4113 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -678,6 +678,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(sanitize_hwaddress); KEYWORD(sanitize_thread); KEYWORD(sanitize_memory); + KEYWORD(speculative_load_hardening); KEYWORD(swifterror); KEYWORD(swiftself); KEYWORD(uwtable); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index a63228ddc03..e2ee8d6c167 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -1276,6 +1276,9 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, B.addAttribute(Attribute::SanitizeThread); break; case lltok::kw_sanitize_memory: B.addAttribute(Attribute::SanitizeMemory); break; + case lltok::kw_speculative_load_hardening: + B.addAttribute(Attribute::SpeculativeLoadHardening); + break; case lltok::kw_strictfp: B.addAttribute(Attribute::StrictFP); break; case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break; case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break; @@ -1619,6 +1622,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) { case lltok::kw_sanitize_hwaddress: case lltok::kw_sanitize_memory: case lltok::kw_sanitize_thread: + case lltok::kw_speculative_load_hardening: case lltok::kw_ssp: case lltok::kw_sspreq: case lltok::kw_sspstrong: @@ -1715,6 +1719,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { case lltok::kw_sanitize_hwaddress: case lltok::kw_sanitize_memory: case lltok::kw_sanitize_thread: + case lltok::kw_speculative_load_hardening: case lltok::kw_ssp: case lltok::kw_sspreq: case lltok::kw_sspstrong: diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index 2da14da4a43..4a3975955fa 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -219,6 +219,7 @@ enum Kind { kw_sret, kw_sanitize_thread, kw_sanitize_memory, + kw_speculative_load_hardening, kw_strictfp, kw_swifterror, kw_swiftself, diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 11bc6db8ba1..7ef52acd464 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1165,6 +1165,8 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) { case Attribute::NoCfCheck: return 1ULL << 57; case Attribute::OptForFuzzing: return 1ULL << 58; case Attribute::ShadowCallStack: return 1ULL << 59; + case Attribute::SpeculativeLoadHardening: + return 1ULL << 60; case Attribute::Dereferenceable: llvm_unreachable("dereferenceable attribute not supported in raw format"); break; @@ -1389,6 +1391,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::SanitizeThread; case bitc::ATTR_KIND_SANITIZE_MEMORY: return Attribute::SanitizeMemory; + case bitc::ATTR_KIND_SPECULATIVE_LOAD_HARDENING: + return Attribute::SpeculativeLoadHardening; case bitc::ATTR_KIND_SWIFT_ERROR: return Attribute::SwiftError; case bitc::ATTR_KIND_SWIFT_SELF: diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index c768021a0a4..1262401266e 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -690,6 +690,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_SANITIZE_THREAD; case Attribute::SanitizeMemory: return bitc::ATTR_KIND_SANITIZE_MEMORY; + case Attribute::SpeculativeLoadHardening: + return bitc::ATTR_KIND_SPECULATIVE_LOAD_HARDENING; case Attribute::SwiftError: return bitc::ATTR_KIND_SWIFT_ERROR; case Attribute::SwiftSelf: diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index d87187481be..d1330e93e21 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -323,6 +323,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "returns_twice"; if (hasAttribute(Attribute::SExt)) return "signext"; + if (hasAttribute(Attribute::SpeculativeLoadHardening)) + return "speculative_load_hardening"; if (hasAttribute(Attribute::Speculatable)) return "speculatable"; if (hasAttribute(Attribute::StackProtect)) diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 2dcb9c4adf8..fc6bc4ff9d1 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1478,6 +1478,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) { case Attribute::InaccessibleMemOnly: case Attribute::InaccessibleMemOrArgMemOnly: case Attribute::AllocSize: + case Attribute::SpeculativeLoadHardening: case Attribute::Speculatable: case Attribute::StrictFP: return true; diff --git a/llvm/lib/Target/X86/X86SpeculativeLoadHardening.cpp b/llvm/lib/Target/X86/X86SpeculativeLoadHardening.cpp index e9b4032a199..7979315a2ae 100644 --- a/llvm/lib/Target/X86/X86SpeculativeLoadHardening.cpp +++ b/llvm/lib/Target/X86/X86SpeculativeLoadHardening.cpp @@ -75,6 +75,11 @@ STATISTIC(NumCallsOrJumpsHardened, STATISTIC(NumInstsInserted, "Number of instructions inserted"); STATISTIC(NumLFENCEsInserted, "Number of lfence instructions inserted"); +static cl::opt<bool> EnableSpeculativeLoadHardening( + "x86-speculative-load-hardening", + cl::desc("Force enable speculative load hardening"), cl::init(false), + cl::Hidden); + static cl::opt<bool> HardenEdgesWithLFENCE( PASS_KEY "-lfence", cl::desc( @@ -404,6 +409,12 @@ bool X86SpeculativeLoadHardeningPass::runOnMachineFunction( LLVM_DEBUG(dbgs() << "********** " << getPassName() << " : " << MF.getName() << " **********\n"); + // Only run if this pass is forced enabled or we detect the relevant function + // attribute requesting SLH. + if (!EnableSpeculativeLoadHardening && + !MF.getFunction().hasFnAttribute(Attribute::SpeculativeLoadHardening)) + return false; + Subtarget = &MF.getSubtarget<X86Subtarget>(); MRI = &MF.getRegInfo(); TII = Subtarget->getInstrInfo(); diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp index 969cd0ab7e7..dd1bbc761b2 100644 --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -54,10 +54,6 @@ static cl::opt<bool> EnableMachineCombinerPass("x86-machine-combiner", cl::desc("Enable the machine combiner pass"), cl::init(true), cl::Hidden); -static cl::opt<bool> EnableSpeculativeLoadHardening( - "x86-speculative-load-hardening", - cl::desc("Enable speculative load hardening"), cl::init(false), cl::Hidden); - namespace llvm { void initializeWinEHStatePassPass(PassRegistry &); @@ -475,9 +471,7 @@ void X86PassConfig::addPreRegAlloc() { addPass(createX86AvoidStoreForwardingBlocks()); } - if (EnableSpeculativeLoadHardening) - addPass(createX86SpeculativeLoadHardeningPass()); - + addPass(createX86SpeculativeLoadHardeningPass()); addPass(createX86FlagsCopyLoweringPass()); addPass(createX86WinAllocaExpander()); } diff --git a/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp b/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp index 37273f97541..4dc1529ddbf 100644 --- a/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp @@ -58,6 +58,7 @@ static Attribute::AttrKind parseAttrKind(StringRef Kind) { .Case("sanitize_hwaddress", Attribute::SanitizeHWAddress) .Case("sanitize_memory", Attribute::SanitizeMemory) .Case("sanitize_thread", Attribute::SanitizeThread) + .Case("speculative_load_hardening", Attribute::SpeculativeLoadHardening) .Case("ssp", Attribute::StackProtect) .Case("sspreq", Attribute::StackProtectReq) .Case("sspstrong", Attribute::StackProtectStrong) diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index d9f39bd1749..7f26c53ecf3 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -753,6 +753,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs, case Attribute::SanitizeMemory: case Attribute::SanitizeThread: case Attribute::SanitizeHWAddress: + case Attribute::SpeculativeLoadHardening: case Attribute::StackProtect: case Attribute::StackProtectReq: case Attribute::StackProtectStrong: diff --git a/llvm/test/CodeGen/X86/O0-pipeline.ll b/llvm/test/CodeGen/X86/O0-pipeline.ll index 569f6a76234..05c0f358e7b 100644 --- a/llvm/test/CodeGen/X86/O0-pipeline.ll +++ b/llvm/test/CodeGen/X86/O0-pipeline.ll @@ -37,6 +37,7 @@ ; CHECK-NEXT: X86 PIC Global Base Reg Initialization ; CHECK-NEXT: Expand ISel Pseudo-instructions ; CHECK-NEXT: Local Stack Slot Allocation +; CHECK-NEXT: X86 speculative load hardening ; CHECK-NEXT: MachineDominator Tree Construction ; CHECK-NEXT: X86 EFLAGS copy lowering ; CHECK-NEXT: X86 WinAlloca Expander diff --git a/llvm/test/CodeGen/X86/O3-pipeline.ll b/llvm/test/CodeGen/X86/O3-pipeline.ll index cf1e5036bd5..44fda3c9e7a 100644 --- a/llvm/test/CodeGen/X86/O3-pipeline.ll +++ b/llvm/test/CodeGen/X86/O3-pipeline.ll @@ -90,6 +90,7 @@ ; CHECK-NEXT: X86 LEA Optimize ; CHECK-NEXT: X86 Optimize Call Frame ; CHECK-NEXT: X86 Avoid Store Forwarding Block +; CHECK-NEXT: X86 speculative load hardening ; CHECK-NEXT: MachineDominator Tree Construction ; CHECK-NEXT: X86 EFLAGS copy lowering ; CHECK-NEXT: X86 WinAlloca Expander diff --git a/llvm/test/CodeGen/X86/speculative-load-hardening-gather.ll b/llvm/test/CodeGen/X86/speculative-load-hardening-gather.ll index 8f4a47eac11..96cfac3b752 100644 --- a/llvm/test/CodeGen/X86/speculative-load-hardening-gather.ll +++ b/llvm/test/CodeGen/X86/speculative-load-hardening-gather.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -x86-speculative-load-hardening | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s declare <4 x float> @llvm.x86.avx2.gather.d.ps(<4 x float>, i8*, <4 x i32>, <4 x float>, i8) @@ -950,6 +950,6 @@ entry: ret <4 x i64> %v } -attributes #0 = { nounwind "target-features"="+avx2" } -attributes #1 = { nounwind "target-features"="+avx512f" } -attributes #2 = { nounwind "target-features"="+avx512vl" } +attributes #0 = { nounwind speculative_load_hardening "target-features"="+avx2" } +attributes #1 = { nounwind speculative_load_hardening "target-features"="+avx512f" } +attributes #2 = { nounwind speculative_load_hardening "target-features"="+avx512vl" } diff --git a/llvm/test/CodeGen/X86/speculative-load-hardening.ll b/llvm/test/CodeGen/X86/speculative-load-hardening.ll index 152fc411cff..f5949dbf467 100644 --- a/llvm/test/CodeGen/X86/speculative-load-hardening.ll +++ b/llvm/test/CodeGen/X86/speculative-load-hardening.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -x86-speculative-load-hardening | FileCheck %s --check-prefix=X64 -; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -x86-speculative-load-hardening -x86-slh-lfence | FileCheck %s --check-prefix=X64-LFENCE +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=X64 +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -x86-slh-lfence | FileCheck %s --check-prefix=X64-LFENCE ; ; FIXME: Add support for 32-bit and other EH ABIs. @@ -8,7 +8,7 @@ declare void @leak(i32 %v1, i32 %v2) declare void @sink(i32) -define i32 @test_trivial_entry_load(i32* %ptr) { +define i32 @test_trivial_entry_load(i32* %ptr) speculative_load_hardening { ; X64-LABEL: test_trivial_entry_load: ; X64: # %bb.0: # %entry ; X64-NEXT: movq %rsp, %rcx @@ -29,7 +29,7 @@ entry: ret i32 %v } -define void @test_basic_conditions(i32 %a, i32 %b, i32 %c, i32* %ptr1, i32* %ptr2, i32** %ptr3) { +define void @test_basic_conditions(i32 %a, i32 %b, i32 %c, i32* %ptr1, i32* %ptr2, i32** %ptr3) speculative_load_hardening { ; X64-LABEL: test_basic_conditions: ; X64: # %bb.0: # %entry ; X64-NEXT: pushq %r15 @@ -193,7 +193,7 @@ exit: ret void } -define void @test_basic_loop(i32 %a, i32 %b, i32* %ptr1, i32* %ptr2) nounwind { +define void @test_basic_loop(i32 %a, i32 %b, i32* %ptr1, i32* %ptr2) nounwind speculative_load_hardening { ; X64-LABEL: test_basic_loop: ; X64: # %bb.0: # %entry ; X64-NEXT: pushq %rbp @@ -301,7 +301,7 @@ exit: ret void } -define void @test_basic_nested_loop(i32 %a, i32 %b, i32 %c, i32* %ptr1, i32* %ptr2) nounwind { +define void @test_basic_nested_loop(i32 %a, i32 %b, i32 %c, i32* %ptr1, i32* %ptr2) nounwind speculative_load_hardening { ; X64-LABEL: test_basic_nested_loop: ; X64: # %bb.0: # %entry ; X64-NEXT: pushq %rbp @@ -497,7 +497,7 @@ declare i8* @__cxa_allocate_exception(i64) local_unnamed_addr declare void @__cxa_throw(i8*, i8*, i8*) local_unnamed_addr -define void @test_basic_eh(i32 %a, i32* %ptr1, i32* %ptr2) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +define void @test_basic_eh(i32 %a, i32* %ptr1, i32* %ptr2) speculative_load_hardening personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { ; X64-LABEL: test_basic_eh: ; X64: # %bb.0: # %entry ; X64-NEXT: pushq %rbp @@ -668,7 +668,7 @@ declare void @sink_float(float) declare void @sink_double(double) ; Test direct and converting loads of floating point values. -define void @test_fp_loads(float* %fptr, double* %dptr, i32* %i32ptr, i64* %i64ptr) nounwind { +define void @test_fp_loads(float* %fptr, double* %dptr, i32* %i32ptr, i64* %i64ptr) nounwind speculative_load_hardening { ; X64-LABEL: test_fp_loads: ; X64: # %bb.0: # %entry ; X64-NEXT: pushq %r15 @@ -855,7 +855,7 @@ declare void @sink_v4i32(<4 x i32>) declare void @sink_v2i64(<2 x i64>) ; Test loads of vectors. -define void @test_vec_loads(<4 x float>* %v4f32ptr, <2 x double>* %v2f64ptr, <16 x i8>* %v16i8ptr, <8 x i16>* %v8i16ptr, <4 x i32>* %v4i32ptr, <2 x i64>* %v2i64ptr) nounwind { +define void @test_vec_loads(<4 x float>* %v4f32ptr, <2 x double>* %v2f64ptr, <16 x i8>* %v16i8ptr, <8 x i16>* %v8i16ptr, <4 x i32>* %v4i32ptr, <2 x i64>* %v2i64ptr) nounwind speculative_load_hardening { ; X64-LABEL: test_vec_loads: ; X64: # %bb.0: # %entry ; X64-NEXT: pushq %rbp @@ -996,7 +996,7 @@ entry: ret void } -define void @test_deferred_hardening(i32* %ptr1, i32* %ptr2, i32 %x) nounwind { +define void @test_deferred_hardening(i32* %ptr1, i32* %ptr2, i32 %x) nounwind speculative_load_hardening { ; X64-LABEL: test_deferred_hardening: ; X64: # %bb.0: # %entry ; X64-NEXT: pushq %r15 diff --git a/llvm/test/Transforms/Inline/attributes.ll b/llvm/test/Transforms/Inline/attributes.ll index 66a831bf817..028f3b0f197 100644 --- a/llvm/test/Transforms/Inline/attributes.ll +++ b/llvm/test/Transforms/Inline/attributes.ll @@ -26,6 +26,10 @@ define i32 @safestack_callee(i32 %i) safestack { ret i32 %i } +define i32 @slh_callee(i32 %i) speculative_load_hardening { + ret i32 %i +} + define i32 @alwaysinline_callee(i32 %i) alwaysinline { ret i32 %i } @@ -161,6 +165,28 @@ define i32 @test_safestack(i32 %arg) safestack { ; CHECK-NEXT: ret i32 } +; Can inline a normal function into an SLH'ed function. +define i32 @test_caller_slh(i32 %i) speculative_load_hardening { +; CHECK-LABEL: @test_caller_slh( +; CHECK-SAME: ) [[SLH:.*]] { +; CHECK-NOT: call +; CHECK: ret i32 +entry: + %callee = call i32 @noattr_callee(i32 %i) + ret i32 %callee +} + +; Can inline a SLH'ed function into a normal one, propagating SLH. +define i32 @test_callee_slh(i32 %i) { +; CHECK-LABEL: @test_callee_slh( +; CHECK-SAME: ) [[SLH:.*]] { +; CHECK-NOT: call +; CHECK: ret i32 +entry: + %callee = call i32 @slh_callee(i32 %i) + ret i32 %callee +} + ; Check that a function doesn't get inlined if target-cpu strings don't match ; exactly. define i32 @test_target_cpu_callee0(i32 %i) "target-cpu"="corei7" { @@ -384,6 +410,7 @@ define i32 @test_null-pointer-is-valid2(i32 %i) "null-pointer-is-valid"="true" { ; CHECK-NEXT: ret i32 } +; CHECK: attributes [[SLH]] = { speculative_load_hardening } ; CHECK: attributes [[FPMAD_FALSE]] = { "less-precise-fpmad"="false" } ; CHECK: attributes [[FPMAD_TRUE]] = { "less-precise-fpmad"="true" } ; CHECK: attributes [[NOIMPLICITFLOAT]] = { noimplicitfloat } |