[llvm] [X86] Declare command line options in TableGen (PR #228327)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 1 22:49:26 PDT 2026
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/228327
>From f2214c2258a297eada69821dd20dea6d7db16b54 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Thu, 1 Oct 2026 00:00:34 -0700
Subject: [PATCH] [X86] Declare command line options in TableGen
Move the cl::opts into X86Options.td, following Sparc (#227977):
X86Subtarget.h declares the struct, LLVMInitializeX86Target registers
it, and code reads Subtarget.getCLOpts().
Options that read cl::opt::getNumOccurrences() become std::optional
members defaulting to std::nullopt, which LibraryOptions.h now parses.
Aided by Opus 5.5
---
llvm/docs/CommandLine.md | 1 +
llvm/include/llvm/Option/LibraryOptions.h | 10 ++
llvm/lib/Target/X86/CMakeLists.txt | 4 +
.../X86/X86AvoidStoreForwardingBlocks.cpp | 19 +--
.../Target/X86/X86CallFrameOptimization.cpp | 8 +-
llvm/lib/Target/X86/X86CmovConversion.cpp | 54 +++----
llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp | 4 +-
llvm/lib/Target/X86/X86CompressEVEX.cpp | 4 +-
llvm/lib/Target/X86/X86DomainReassignment.cpp | 8 +-
llvm/lib/Target/X86/X86FixupBWInsts.cpp | 8 +-
llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 15 +-
llvm/lib/Target/X86/X86ISelLowering.cpp | 79 ++--------
.../Target/X86/X86IndirectBranchTracking.cpp | 7 +-
llvm/lib/Target/X86/X86InsertVZeroUpper.cpp | 10 +-
llvm/lib/Target/X86/X86InstrFragments.td | 4 +-
llvm/lib/Target/X86/X86InstrInfo.cpp | 62 +++-----
.../X86LoadValueInjectionLoadHardening.cpp | 41 +----
llvm/lib/Target/X86/X86LowerAMXIntrinsics.cpp | 12 +-
llvm/lib/Target/X86/X86MCInstLower.cpp | 14 +-
llvm/lib/Target/X86/X86OptimizeLEAs.cpp | 8 +-
llvm/lib/Target/X86/X86Options.td | 143 ++++++++++++++++++
llvm/lib/Target/X86/X86RegisterInfo.cpp | 30 +---
llvm/lib/Target/X86/X86SelectionDAGInfo.cpp | 6 +-
...culativeExecutionSideEffectSuppression.cpp | 34 +----
.../X86/X86SpeculativeLoadHardening.cpp | 81 +++-------
llvm/lib/Target/X86/X86Subtarget.cpp | 14 +-
llvm/lib/Target/X86/X86Subtarget.h | 9 ++
.../lib/Target/X86/X86SuppressAPXForReloc.cpp | 10 +-
llvm/lib/Target/X86/X86TargetMachine.cpp | 20 +--
llvm/lib/Target/X86/X86TargetMachine.h | 3 +
llvm/lib/Target/X86/X86WinEHUnwindV2.cpp | 30 +---
llvm/lib/Target/X86/X86WinEHUnwindV3.cpp | 11 +-
.../X86/apx/optimize-compare-multipred.mir | 6 +-
llvm/unittests/Option/LibraryOptionsTest.cpp | 15 +-
llvm/unittests/Option/LibraryOpts.td | 2 +
.../gn/secondary/llvm/lib/Target/X86/BUILD.gn | 8 +
.../llvm-project-overlay/llvm/BUILD.bazel | 12 ++
37 files changed, 341 insertions(+), 465 deletions(-)
create mode 100644 llvm/lib/Target/X86/X86Options.td
diff --git a/llvm/docs/CommandLine.md b/llvm/docs/CommandLine.md
index db311101cb8d0d8..385881c8df81f15 100644
--- a/llvm/docs/CommandLine.md
+++ b/llvm/docs/CommandLine.md
@@ -1590,6 +1590,7 @@ Both accept `--` for `-`.
Only `-help-hidden` lists the options, like `cl::Hidden`.
A default is the member's C++ initializer, so `"\"-\""` initializes `foo_path` to `"-"`.
+A `std::optional` member defaulting to `std::nullopt` tells whether the option was given, replacing `cl::opt::getNumOccurrences()`.
The header declares the struct after including what the member defaults need, and one source file defines it and registers it with `cl::`.
The library then lists `FooOptionsTableGen` under `DEPENDS` and `Option` under `LINK_COMPONENTS`.
diff --git a/llvm/include/llvm/Option/LibraryOptions.h b/llvm/include/llvm/Option/LibraryOptions.h
index 7d9bd4f823963d7..06209d5d56a402e 100644
--- a/llvm/include/llvm/Option/LibraryOptions.h
+++ b/llvm/include/llvm/Option/LibraryOptions.h
@@ -21,6 +21,7 @@
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
+#include <optional>
#include <type_traits>
namespace llvm {
@@ -51,6 +52,15 @@ parseArgValue(StringRef S, T &V) {
return to_integer(S, V);
}
+// A std::optional member is set only when its option is given.
+template <typename T> bool parseArgValue(StringRef S, std::optional<T> &V) {
+ T X{};
+ if (!parseArgValue(S, X))
+ return false;
+ V = X;
+ return true;
+}
+
/// An OptTable with a public constructor, shared by every options struct.
class LLVM_ABI LibraryOptTable : public OptTable {
public:
diff --git a/llvm/lib/Target/X86/CMakeLists.txt b/llvm/lib/Target/X86/CMakeLists.txt
index ee6f314d70fdd30..e7e0e9a5cbe3553 100644
--- a/llvm/lib/Target/X86/CMakeLists.txt
+++ b/llvm/lib/Target/X86/CMakeLists.txt
@@ -24,6 +24,9 @@ tablegen(LLVM X86GenPreLegalizeGICombiner.inc -gen-global-isel-combiner
-combiners="X86PreLegalizerCombiner")
tablegen(LLVM X86GenPostLegalizeGICombiner.inc -gen-global-isel-combiner
-combiners="X86PostLegalizerCombiner")
+
+set(LLVM_TARGET_DEFINITIONS X86Options.td)
+tablegen(LLVM X86Options.inc -gen-opt-parser-defs)
add_public_tablegen_target(X86CommonTableGen)
set(sources
@@ -112,6 +115,7 @@ add_llvm_target(X86CodeGen ${sources}
Instrumentation
MC
ObjCARC
+ Option
Passes
ProfileData
SelectionDAG
diff --git a/llvm/lib/Target/X86/X86AvoidStoreForwardingBlocks.cpp b/llvm/lib/Target/X86/X86AvoidStoreForwardingBlocks.cpp
index 2501dbeb6e6eeb6..ce89feebaca702f 100644
--- a/llvm/lib/Target/X86/X86AvoidStoreForwardingBlocks.cpp
+++ b/llvm/lib/Target/X86/X86AvoidStoreForwardingBlocks.cpp
@@ -54,16 +54,6 @@ using namespace llvm;
#define DEBUG_TYPE "x86-avoid-sfb"
-static cl::opt<bool> DisableX86AvoidStoreForwardBlocks(
- "x86-disable-avoid-SFB", cl::Hidden,
- cl::desc("X86: Disable Store Forwarding Blocks fixup."), cl::init(false));
-
-static cl::opt<unsigned> X86AvoidSFBInspectionLimit(
- "x86-sfb-inspection-limit",
- cl::desc("X86: Number of instructions backward to "
- "inspect for store forwarding blocks."),
- cl::init(20), cl::Hidden);
-
namespace {
using DisplacementSizeMap = std::map<int64_t, unsigned>;
@@ -339,10 +329,9 @@ static bool isRelevantAddressingMode(MachineInstr *MI) {
// and load instructions have enough instructions in between to
// keep the core busy.
static SmallVector<MachineInstr *, 2>
-findPotentialBlockers(MachineInstr *LoadInst) {
+findPotentialBlockers(MachineInstr *LoadInst, unsigned InspectionLimit) {
SmallVector<MachineInstr *, 2> PotentialBlockers;
unsigned BlockCount = 0;
- const unsigned InspectionLimit = X86AvoidSFBInspectionLimit;
for (auto PBInst = std::next(MachineBasicBlock::reverse_iterator(LoadInst)),
E = LoadInst->getParent()->rend();
PBInst != E; ++PBInst) {
@@ -655,8 +644,8 @@ removeRedundantBlockingStores(DisplacementSizeMap &BlockingStoresDispSizeMap) {
bool X86AvoidSFBImpl::runOnMachineFunction(MachineFunction &MF) {
bool Changed = false;
- if (DisableX86AvoidStoreForwardBlocks ||
- !MF.getSubtarget<X86Subtarget>().is64Bit())
+ const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();
+ if (ST.getCLOpts().disable_avoid_SFB || !ST.is64Bit())
return false;
MRI = &MF.getRegInfo();
@@ -673,7 +662,7 @@ bool X86AvoidSFBImpl::runOnMachineFunction(MachineFunction &MF) {
DisplacementSizeMap BlockingStoresDispSizeMap;
SmallVector<MachineInstr *, 2> PotentialBlockers =
- findPotentialBlockers(LoadInst);
+ findPotentialBlockers(LoadInst, ST.getCLOpts().sfb_inspection_limit);
for (auto *PBInst : PotentialBlockers) {
if (!isPotentialBlockingStoreInst(PBInst->getOpcode(),
LoadInst->getOpcode()) ||
diff --git a/llvm/lib/Target/X86/X86CallFrameOptimization.cpp b/llvm/lib/Target/X86/X86CallFrameOptimization.cpp
index 4966ec2fe8dc92f..b5738a563f5d1c4 100644
--- a/llvm/lib/Target/X86/X86CallFrameOptimization.cpp
+++ b/llvm/lib/Target/X86/X86CallFrameOptimization.cpp
@@ -40,7 +40,6 @@
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
#include "llvm/MC/MCDwarf.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
@@ -52,11 +51,6 @@ using namespace llvm;
#define DEBUG_TYPE "x86-cf-opt"
-static cl::opt<bool>
- NoX86CFOpt("no-x86-call-frame-opt",
- cl::desc("Avoid optimizing x86 call frames for size"),
- cl::init(false), cl::Hidden);
-
namespace {
class X86CallFrameOptimizationImpl {
@@ -145,7 +139,7 @@ INITIALIZE_PASS(X86CallFrameOptimizationLegacy, DEBUG_TYPE,
// Also returns false in cases where it's potentially legal, but
// we don't even want to try.
bool X86CallFrameOptimizationImpl::isLegal(MachineFunction &MF) {
- if (NoX86CFOpt.getValue())
+ if (MF.getSubtarget<X86Subtarget>().getCLOpts().no_x86_call_frame_opt)
return false;
// We can't encode multiple DW_CFA_GNU_args_size or DW_CFA_def_cfa_offset
diff --git a/llvm/lib/Target/X86/X86CmovConversion.cpp b/llvm/lib/Target/X86/X86CmovConversion.cpp
index 002b3b2beb55145..96927f53024a8d1 100644
--- a/llvm/lib/Target/X86/X86CmovConversion.cpp
+++ b/llvm/lib/Target/X86/X86CmovConversion.cpp
@@ -42,6 +42,7 @@
#include "X86.h"
#include "X86InstrInfo.h"
+#include "X86Subtarget.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
@@ -65,7 +66,6 @@
#include "llvm/InitializePasses.h"
#include "llvm/MC/MCSchedule.h"
#include "llvm/Pass.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/CGPassBuilderOption.h"
@@ -83,27 +83,6 @@ STATISTIC(NumOfCmovGroupCandidate, "Number of CMOV-group candidates");
STATISTIC(NumOfLoopCandidate, "Number of CMOV-conversion profitable loops");
STATISTIC(NumOfOptimizedCmovGroups, "Number of optimized CMOV-groups");
-// This internal switch can be used to turn off the cmov/branch optimization.
-static cl::opt<bool>
- EnableCmovConverter("x86-cmov-converter",
- cl::desc("Enable the X86 cmov-to-branch optimization."),
- cl::init(true), cl::Hidden);
-
-static cl::opt<unsigned>
- GainCycleThreshold("x86-cmov-converter-threshold",
- cl::desc("Minimum gain per loop (in cycles) threshold."),
- cl::init(4), cl::Hidden);
-
-static cl::opt<bool> ForceMemOperand(
- "x86-cmov-converter-force-mem-operand",
- cl::desc("Convert cmovs to branches whenever they have memory operands."),
- cl::init(true), cl::Hidden);
-
-static cl::opt<bool> ForceAll(
- "x86-cmov-converter-force-all",
- cl::desc("Convert all cmovs to branches."),
- cl::init(false), cl::Hidden);
-
namespace {
/// Converts X86 cmov instructions into branches when profitable.
@@ -117,7 +96,7 @@ class X86CmovConversionImpl {
MachineRegisterInfo *MRI = nullptr;
const TargetInstrInfo *TII = nullptr;
const TargetRegisterInfo *TRI = nullptr;
- const TargetSubtargetInfo *STI = nullptr;
+ const X86Subtarget *STI = nullptr;
MachineLoopInfo *MLI = nullptr;
TargetSchedModel TSchedModel;
@@ -173,7 +152,8 @@ void X86CmovConversionLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
}
bool X86CmovConversionImpl::runOnMachineFunction(MachineFunction &MF) {
- if (!EnableCmovConverter)
+ STI = &MF.getSubtarget<X86Subtarget>();
+ if (!STI->getCLOpts().cmov_converter)
return false;
// If the SelectOptimize pass is enabled, cmovs have already been optimized.
@@ -184,24 +164,27 @@ bool X86CmovConversionImpl::runOnMachineFunction(MachineFunction &MF) {
<< "**********\n");
bool Changed = false;
- STI = &MF.getSubtarget();
MRI = &MF.getRegInfo();
TII = STI->getInstrInfo();
TRI = STI->getRegisterInfo();
TSchedModel.init(STI);
// Before we handle the more subtle cases of register-register CMOVs inside
- // of potentially hot loops, we want to quickly remove all CMOVs (ForceAll) or
- // the ones with a memory operand (ForceMemOperand option). The latter CMOV
- // will risk a stall waiting for the load to complete that speculative
- // execution behind a branch is better suited to handle on modern x86 chips.
- if (ForceMemOperand || ForceAll) {
+ // of potentially hot loops, we want to quickly remove all CMOVs
+ // (cmov_converter_force_all) or the ones with a memory operand
+ // (cmov_converter_force_mem_operand). The latter CMOV will risk a stall
+ // waiting for the load to complete that speculative execution behind a branch
+ // is better suited to handle on modern x86 chips.
+ const X86Options &CLOpts = STI->getCLOpts();
+ if (CLOpts.cmov_converter_force_mem_operand ||
+ CLOpts.cmov_converter_force_all) {
CmovGroups AllCmovGroups;
SmallVector<MachineBasicBlock *, 4> Blocks(llvm::make_pointer_range(MF));
if (collectCmovCandidates(Blocks, AllCmovGroups, /*IncludeLoads*/ true)) {
for (auto &Group : AllCmovGroups) {
// Skip any group that doesn't do at least one memory operand cmov.
- if (ForceMemOperand && !ForceAll &&
+ if (CLOpts.cmov_converter_force_mem_operand &&
+ !CLOpts.cmov_converter_force_all &&
llvm::none_of(Group, [&](MachineInstr *I) { return I->mayLoad(); }))
continue;
@@ -212,8 +195,8 @@ bool X86CmovConversionImpl::runOnMachineFunction(MachineFunction &MF) {
convertCmovInstsToBranches(Group);
}
}
- // Early return as ForceAll converts all CmovGroups.
- if (ForceAll)
+ // Early return as cmov_converter_force_all converts all CmovGroups.
+ if (CLOpts.cmov_converter_force_all)
return Changed;
}
@@ -518,11 +501,12 @@ bool X86CmovConversionImpl::checkForProfitableCmovCandidates(
//
// In addition, In order not to optimize loops with very small gain, the
// gain (in cycles) after 2nd iteration should not be less than a given
- // threshold. Thus, the check (Diff[1] >= GainCycleThreshold) must apply.
+ // threshold. Thus, the check (Diff[1] >= cmov_converter_threshold) must
+ // apply.
//
// If loop is not worth optimizing, remove all CMOV-group-candidates.
//===--------------------------------------------------------------------===//
- if (Diff[1] < GainCycleThreshold)
+ if (Diff[1] < STI->getCLOpts().cmov_converter_threshold)
return false;
bool WorthOptLoop = false;
diff --git a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
index 40f8738bb389aaa..7a72f80c3845979 100644
--- a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
@@ -37,8 +37,6 @@
using namespace llvm;
-extern cl::opt<bool> X86EnableMachineCombinerPass;
-
namespace {
class X86CodeGenPassBuilder : public CodeGenPassBuilder {
@@ -171,7 +169,7 @@ Error X86CodeGenPassBuilder::addGlobalInstructionSelect(
void X86CodeGenPassBuilder::addILPOpts(PassManagerWrapper &PMW) {
addMachineFunctionPass(EarlyIfConverterPass(), PMW);
- if (X86EnableMachineCombinerPass)
+ if (getTM().getCLOpts().machine_combiner)
addMachineFunctionPass(MachineCombinerPass(), PMW);
addMachineFunctionPass(X86CmovConversionPass(), PMW);
}
diff --git a/llvm/lib/Target/X86/X86CompressEVEX.cpp b/llvm/lib/Target/X86/X86CompressEVEX.cpp
index 16645576514ae3f..034bfb0630c71d3 100644
--- a/llvm/lib/Target/X86/X86CompressEVEX.cpp
+++ b/llvm/lib/Target/X86/X86CompressEVEX.cpp
@@ -65,8 +65,6 @@ using namespace llvm;
#define DEBUG_TYPE COMP_EVEX_NAME
-extern cl::opt<bool> X86EnableAPXForRelocation;
-
namespace {
// Including the generated EVEX compression tables.
#define GET_X86_COMPRESS_EVEX_TABLE
@@ -667,7 +665,7 @@ static bool CompressEVEXImpl(MachineInstr &MI, MachineBasicBlock &MBB,
// ADDrm/mr instructions with NDD + relocation had been transformed to the
// instructions without NDD in X86SuppressAPXForRelocation pass. That is to
// keep backward compatibility with linkers without APX support.
- if (!X86EnableAPXForRelocation)
+ if (!ST.getCLOpts().enable_apx_for_relocation)
assert(!isAddMemInstrWithRelocation(MI) &&
"Unexpected NDD instruction with relocation!");
} else if (Opc == X86::ADD32ri_ND || Opc == X86::ADD64ri32_ND ||
diff --git a/llvm/lib/Target/X86/X86DomainReassignment.cpp b/llvm/lib/Target/X86/X86DomainReassignment.cpp
index 2e4e41dbf8e88da..3fc7027e3d1ccbb 100644
--- a/llvm/lib/Target/X86/X86DomainReassignment.cpp
+++ b/llvm/lib/Target/X86/X86DomainReassignment.cpp
@@ -35,10 +35,6 @@ using namespace llvm;
STATISTIC(NumClosuresConverted, "Number of closures converted by the pass");
STATISTIC(NumClosuresBuilt, "Number of closures built by the pass");
-static cl::opt<bool> DisableX86DomainReassignment(
- "disable-x86-domain-reassignment", cl::Hidden,
- cl::desc("X86: Disable Virtual Register Reassignment."), cl::init(false));
-
namespace {
enum RegDomain { NoDomain = -1, GPRDomain, MaskDomain, OtherDomain, NumDomains };
@@ -759,14 +755,14 @@ void X86DomainReassignmentImpl::initConverters() {
}
bool X86DomainReassignmentImpl::runOnMachineFunction(MachineFunction &MF) {
- if (DisableX86DomainReassignment)
+ STI = &MF.getSubtarget<X86Subtarget>();
+ if (STI->getCLOpts().disable_x86_domain_reassignment)
return false;
LLVM_DEBUG(
dbgs() << "***** Machine Function before Domain Reassignment *****\n");
LLVM_DEBUG(MF.print(dbgs()));
- STI = &MF.getSubtarget<X86Subtarget>();
// GPR->K is the only transformation currently supported, bail out early if no
// AVX512.
// TODO: We're also bailing of AVX512BW isn't supported since we use VK32 and
diff --git a/llvm/lib/Target/X86/X86FixupBWInsts.cpp b/llvm/lib/Target/X86/X86FixupBWInsts.cpp
index 18819efd35e27de..0c599bed8311df5 100644
--- a/llvm/lib/Target/X86/X86FixupBWInsts.cpp
+++ b/llvm/lib/Target/X86/X86FixupBWInsts.cpp
@@ -67,12 +67,6 @@ using namespace llvm;
#define DEBUG_TYPE FIXUPBW_NAME
-// Option to allow this optimization pass to have fine-grained control.
-static cl::opt<bool>
- FixupBWInsts("fixup-byte-word-insts",
- cl::desc("Change byte and word instructions to larger sizes"),
- cl::init(true), cl::Hidden);
-
namespace {
class X86FixupBWInstImpl {
public:
@@ -163,7 +157,7 @@ FunctionPass *llvm::createX86FixupBWInstsLegacyPass() {
}
bool X86FixupBWInstImpl::runOnMachineFunction(MachineFunction &MF) {
- if (!FixupBWInsts)
+ if (!MF.getSubtarget<X86Subtarget>().getCLOpts().fixup_byte_word_insts)
return false;
this->MF = &MF;
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index 5dd67f8829bc50a..a9eb13b7b013a04 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -41,16 +41,6 @@ using namespace llvm;
STATISTIC(NumLoadMoved, "Number of loads moved below TokenFactor");
-static cl::opt<bool> AndImmShrink("x86-and-imm-shrink", cl::init(true),
- cl::desc("Enable setting constant bits to reduce size of mask immediates"),
- cl::Hidden);
-
-static cl::opt<bool> EnablePromoteAnyextLoad(
- "x86-promote-anyext-load", cl::init(true),
- cl::desc("Enable promoting aligned anyext load to wider load"), cl::Hidden);
-
-extern cl::opt<bool> IndirectBranchTracking;
-
//===----------------------------------------------------------------------===//
// Pattern Matcher Implementation
//===----------------------------------------------------------------------===//
@@ -1018,7 +1008,8 @@ void X86DAGToDAGISel::PreprocessISelDAG() {
Metadata *CFProtectionBranch =
MF->getFunction().getParent()->getModuleFlag(
"cf-protection-branch");
- if (CFProtectionBranch || IndirectBranchTracking) {
+ if (CFProtectionBranch ||
+ Subtarget->getCLOpts().indirect_branch_tracking) {
SDLoc dl(N);
uint64_t ComplementImm =
(~Imm) & maskTrailingOnes<uint64_t>(VT.getSizeInBits());
@@ -5813,7 +5804,7 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
}
if (matchBitExtract(Node))
return;
- if (AndImmShrink && shrinkAndImmediate(Node))
+ if (Subtarget->getCLOpts().and_imm_shrink && shrinkAndImmediate(Node))
return;
[[fallthrough]];
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 7817c86155e5b05..bd8e51af8015579 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -55,7 +55,6 @@
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"
@@ -69,65 +68,6 @@ using namespace llvm;
#define DEBUG_TYPE "x86-isel"
-static cl::opt<int> ExperimentalPrefInnermostLoopAlignment(
- "x86-experimental-pref-innermost-loop-alignment", cl::init(4),
- cl::desc(
- "Sets the preferable loop alignment for experiments (as log2 bytes) "
- "for innermost loops only. If specified, this option overrides "
- "alignment set by x86-experimental-pref-loop-alignment."),
- cl::Hidden);
-
-static cl::opt<int> BrMergingBaseCostThresh(
- "x86-br-merging-base-cost", cl::init(2),
- cl::desc(
- "Sets the cost threshold for when multiple conditionals will be merged "
- "into one branch versus be split in multiple branches. Merging "
- "conditionals saves branches at the cost of additional instructions. "
- "This value sets the instruction cost limit, below which conditionals "
- "will be merged, and above which conditionals will be split. Set to -1 "
- "to never merge branches."),
- cl::Hidden);
-
-static cl::opt<int> BrMergingCcmpBias(
- "x86-br-merging-ccmp-bias", cl::init(6),
- cl::desc("Increases 'x86-br-merging-base-cost' in cases that the target "
- "supports conditional compare instructions."),
- cl::Hidden);
-
-static cl::opt<bool>
- WidenShift("x86-widen-shift", cl::init(true),
- cl::desc("Replace narrow shifts with wider shifts."),
- cl::Hidden);
-
-static cl::opt<int> BrMergingLikelyBias(
- "x86-br-merging-likely-bias", cl::init(0),
- cl::desc("Increases 'x86-br-merging-base-cost' in cases that it is likely "
- "that all conditionals will be executed. For example for merging "
- "the conditionals (a == b && c > d), if its known that a == b is "
- "likely, then it is likely that if the conditionals are split "
- "both sides will be executed, so it may be desirable to increase "
- "the instruction cost threshold. Set to -1 to never merge likely "
- "branches."),
- cl::Hidden);
-
-static cl::opt<int> BrMergingUnlikelyBias(
- "x86-br-merging-unlikely-bias", cl::init(-1),
- cl::desc(
- "Decreases 'x86-br-merging-base-cost' in cases that it is unlikely "
- "that all conditionals will be executed. For example for merging "
- "the conditionals (a == b && c > d), if its known that a == b is "
- "unlikely, then it is unlikely that if the conditionals are split "
- "both sides will be executed, so it may be desirable to decrease "
- "the instruction cost threshold. Set to -1 to never merge unlikely "
- "branches."),
- cl::Hidden);
-
-static cl::opt<bool> MulConstantOptimization(
- "mul-constant-optimization", cl::init(true),
- cl::desc("Replace 'mul x, Const' with more effective instructions like "
- "SHIFT, LEA, etc."),
- cl::Hidden);
-
X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
const X86Subtarget &STI)
: TargetLowering(TM, STI), Subtarget(STI) {
@@ -3946,10 +3886,10 @@ X86TargetLowering::getJumpConditionMergingParams(Instruction::BinaryOps Opc,
const Value *Rhs,
const Function *) const {
using namespace llvm::PatternMatch;
- int BaseCost = BrMergingBaseCostThresh.getValue();
+ int BaseCost = Subtarget.getCLOpts().br_merging_base_cost;
// With CCMP, branches can be merged in a more efficient way.
if (BaseCost >= 0 && Subtarget.hasCCMP())
- BaseCost += BrMergingCcmpBias;
+ BaseCost += Subtarget.getCLOpts().br_merging_ccmp_bias;
// a == b && a == c is a fast pattern on x86.
if (BaseCost >= 0 && Opc == Instruction::And &&
match(Lhs, m_SpecificICmp(ICmpInst::ICMP_EQ, m_Value(), m_Value())) &&
@@ -3965,8 +3905,8 @@ X86TargetLowering::getJumpConditionMergingParams(Instruction::BinaryOps Opc,
match(Rhs, m_SpecificICmp(ICmpInst::ICMP_EQ, m_Value(), m_Value())))
return {-1, -1, -1};
- return {BaseCost, BrMergingLikelyBias.getValue(),
- BrMergingUnlikelyBias.getValue()};
+ return {BaseCost, Subtarget.getCLOpts().br_merging_likely_bias,
+ Subtarget.getCLOpts().br_merging_unlikely_bias};
}
bool X86TargetLowering::preferScalarizeSplat(SDNode *N) const {
@@ -31628,7 +31568,7 @@ static SDValue LowerShift(SDValue Op, const X86Subtarget &Subtarget,
}
APInt APIntShiftAmt;
bool IsConstantSplat = X86::isConstantSplat(Amt, APIntShiftAmt);
- bool Profitable = WidenShift;
+ bool Profitable = Subtarget.getCLOpts().widen_shift;
// AVX512BW brings support for vpsllvw.
if (WideEltSizeInBits * AmtWideElts.size() >= 512 &&
WideEltSizeInBits < 32 && !Subtarget.hasBWI()) {
@@ -51292,7 +51232,7 @@ static SDValue combineMul(SDNode *N, SelectionDAG &DAG,
// Optimize a single multiply with constant into two operations in order to
// implement it with two cheaper instructions, e.g. LEA + SHL, LEA + LEA.
- if (!MulConstantOptimization)
+ if (!Subtarget.getCLOpts().mul_constant_optimization)
return SDValue();
// An imul is usually smaller than the alternative sequence.
@@ -65640,8 +65580,9 @@ X86TargetLowering::getStackProbeSize(const MachineFunction &MF) const {
Align X86TargetLowering::getPrefLoopAlignment(
MachineLoop *ML, const MachineBasicBlock *BlockToAlign) const {
- if (ML && ML->isInnermost() &&
- ExperimentalPrefInnermostLoopAlignment.getNumOccurrences())
- return Align(1ULL << ExperimentalPrefInnermostLoopAlignment);
+ std::optional<int> InnermostAlign =
+ Subtarget.getCLOpts().experimental_pref_innermost_loop_alignment;
+ if (ML && ML->isInnermost() && InnermostAlign)
+ return Align(1ULL << *InnermostAlign);
return TargetLowering::getPrefLoopAlignment();
}
diff --git a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
index 6ccad26a890dd6b..e2cb373a306509a 100644
--- a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
+++ b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
@@ -29,10 +29,6 @@ using namespace llvm;
#define DEBUG_TYPE "x86-indirect-branch-tracking"
-cl::opt<bool> IndirectBranchTracking(
- "x86-indirect-branch-tracking", cl::init(false), cl::Hidden,
- cl::desc("Enable X86 indirect branch tracking pass."));
-
STATISTIC(NumEndBranchAdded, "Number of ENDBR instructions added");
namespace {
@@ -125,7 +121,8 @@ static bool runIndirectBranchTracking(MachineFunction &MF) {
#else
bool isJITwithCET = false;
#endif
- if (!isCFProtectionSupported && !IndirectBranchTracking && !isJITwithCET)
+ if (!isCFProtectionSupported && !TM->getCLOpts().indirect_branch_tracking &&
+ !isJITwithCET)
return false;
// True if the current MF was changed and false otherwise.
diff --git a/llvm/lib/Target/X86/X86InsertVZeroUpper.cpp b/llvm/lib/Target/X86/X86InsertVZeroUpper.cpp
index 4cbb911a5880f75..9d11ae8ac321722 100644
--- a/llvm/lib/Target/X86/X86InsertVZeroUpper.cpp
+++ b/llvm/lib/Target/X86/X86InsertVZeroUpper.cpp
@@ -42,11 +42,6 @@ using namespace llvm;
#define DEBUG_TYPE "x86-insert-vzeroupper"
-static cl::opt<bool>
- UseVZeroUpper("x86-use-vzeroupper", cl::Hidden,
- cl::desc("Minimize AVX to SSE transition penalty"),
- cl::init(true));
-
STATISTIC(NumVZU, "Number of vzeroupper instructions inserted");
namespace {
@@ -277,11 +272,8 @@ static bool processBasicBlock(MachineBasicBlock &MBB,
/// Loop over all of the basic blocks, inserting vzeroupper instructions before
/// function calls.
static bool insertVZeroUpper(MachineFunction &MF) {
- if (!UseVZeroUpper)
- return false;
-
const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();
- if (!ST.hasAVX() || !ST.insertVZEROUPPER())
+ if (!ST.getCLOpts().use_vzeroupper || !ST.hasAVX() || !ST.insertVZEROUPPER())
return false;
MachineRegisterInfo &MRI = MF.getRegInfo();
diff --git a/llvm/lib/Target/X86/X86InstrFragments.td b/llvm/lib/Target/X86/X86InstrFragments.td
index 383e713f93810d3..6a43bbe149dbbf3 100644
--- a/llvm/lib/Target/X86/X86InstrFragments.td
+++ b/llvm/lib/Target/X86/X86InstrFragments.td
@@ -671,7 +671,7 @@ def loadi16 : PatFrag<(ops node:$ptr), (i16 (unindexedload node:$ptr)), [{
ISD::LoadExtType ExtType = LD->getExtensionType();
if (ExtType == ISD::NON_EXTLOAD)
return true;
- if (ExtType == ISD::EXTLOAD && EnablePromoteAnyextLoad)
+ if (ExtType == ISD::EXTLOAD && Subtarget->getCLOpts().promote_anyext_load)
return LD->getAlign() >= 2 && LD->isSimple();
return false;
}]> {
@@ -690,7 +690,7 @@ def loadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{
ISD::LoadExtType ExtType = LD->getExtensionType();
if (ExtType == ISD::NON_EXTLOAD)
return true;
- if (ExtType == ISD::EXTLOAD && EnablePromoteAnyextLoad)
+ if (ExtType == ISD::EXTLOAD && Subtarget->getCLOpts().promote_anyext_load)
return LD->getAlign() >= 4 && LD->isSimple();
return false;
}]> {
diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp
index db11719b86cbeb1..48ca98b7cd3f122 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -37,7 +37,6 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@@ -52,39 +51,6 @@ using namespace llvm;
#define GET_INSTRINFO_CTOR_DTOR
#include "X86GenInstrInfo.inc"
-extern cl::opt<bool> X86EnableAPXForRelocation;
-
-static cl::opt<bool>
- NoFusing("disable-spill-fusing",
- cl::desc("Disable fusing of spill code into instructions"),
- cl::Hidden);
-static cl::opt<bool>
- PrintFailedFusing("print-failed-fuse-candidates",
- cl::desc("Print instructions that the allocator wants to"
- " fuse, but the X86 backend currently can't"),
- cl::Hidden);
-static cl::opt<bool>
- ReMatPICStubLoad("remat-pic-stub-load",
- cl::desc("Re-materialize load from stub in PIC mode"),
- cl::init(false), cl::Hidden);
-static cl::opt<unsigned>
- PartialRegUpdateClearance("partial-reg-update-clearance",
- cl::desc("Clearance between two register writes "
- "for inserting XOR to avoid partial "
- "register update"),
- cl::init(64), cl::Hidden);
-static cl::opt<unsigned> UndefRegClearance(
- "undef-reg-clearance",
- cl::desc("How many idle instructions we would like before "
- "certain undef register reads"),
- cl::init(128), cl::Hidden);
-
-static cl::opt<unsigned> MaxNFConversions(
- "x86-max-nf-conversions-for-cmp-reuse",
- cl::desc("Maximum number of NF conversions allowed to reuse EFLAGS from a "
- "producer dominating a multi-predecessor block"),
- cl::init(6), cl::Hidden);
-
// Pin the vtable to this file.
void X86InstrInfo::anchor() {}
@@ -936,7 +902,8 @@ bool X86InstrInfo::isReMaterializableImpl(
if (BaseReg == 0 || BaseReg == X86::RIP)
return true;
// Allow re-materialization of PIC load.
- if (!(!ReMatPICStubLoad && MI.getOperand(1 + X86::AddrDisp).isGlobal())) {
+ if (!(!Subtarget.getCLOpts().remat_pic_stub_load &&
+ MI.getOperand(1 + X86::AddrDisp).isGlobal())) {
const MachineFunction &MF = *MI.getParent()->getParent();
const MachineRegisterInfo &MRI = MF.getRegInfo();
if (regIsPICBase(BaseReg, MRI))
@@ -3264,7 +3231,9 @@ unsigned X86::getNFVariantIfClobberRemovable(const MachineInstr &MI,
// optimization for replacing non-NF with NF. This is to keep backward
// compatiblity with old version of linkers without APX relocation type
// support on Linux OS.
- if (!X86EnableAPXForRelocation && isAddMemInstrWithRelocation(MI))
+ const X86Subtarget &ST = MI.getMF()->getSubtarget<X86Subtarget>();
+ if (!ST.getCLOpts().enable_apx_for_relocation &&
+ isAddMemInstrWithRelocation(MI))
return 0;
return X86::getNFVariant(MI.getOpcode());
}
@@ -5363,7 +5332,8 @@ MachineInstr *X86InstrInfo::findDominatingRedundantFlagInstr(
unsigned NewOpc = X86::getNFVariantIfClobberRemovable(Inst, TRI);
if (!NewOpc)
return nullptr;
- if (InstsToUpdate.size() + Pending.size() >= MaxNFConversions)
+ if (InstsToUpdate.size() + Pending.size() >=
+ Subtarget.getCLOpts().max_nf_conversions_for_cmp_reuse)
return nullptr;
Pending.push_back(std::make_pair(&Inst, NewOpc));
}
@@ -5403,7 +5373,8 @@ MachineInstr *X86InstrInfo::findDominatingRedundantFlagInstr(
unsigned NewOpc = X86::getNFVariantIfClobberRemovable(Inst, TRI);
if (!NewOpc)
return nullptr;
- if (InstsToUpdate.size() + Pending.size() >= MaxNFConversions)
+ if (InstsToUpdate.size() + Pending.size() >=
+ Subtarget.getCLOpts().max_nf_conversions_for_cmp_reuse)
return nullptr;
Pending.push_back(std::make_pair(&Inst, NewOpc));
}
@@ -7037,7 +7008,7 @@ unsigned X86InstrInfo::getPartialRegUpdateClearance(
// If any instructions in the clearance range are reading Reg, insert a
// dependency breaking instruction, which is inexpensive and is likely to
// be hidden in other instruction's cycles.
- return PartialRegUpdateClearance;
+ return Subtarget.getCLOpts().partial_reg_update_clearance;
}
// Return true for any instruction the copies the high bits of the first source
@@ -7391,7 +7362,7 @@ X86InstrInfo::getUndefRegClearance(const MachineInstr &MI, unsigned OpNum,
const TargetRegisterInfo *TRI) const {
const MachineOperand &MO = MI.getOperand(OpNum);
if (MO.getReg().isPhysical() && hasUndefRegUpdate(MI.getOpcode(), OpNum))
- return UndefRegClearance;
+ return Subtarget.getCLOpts().undef_reg_clearance;
return 0;
}
@@ -7712,7 +7683,8 @@ unsigned X86InstrInfo::commuteOperandsForFold(MachineInstr &MI,
}
static void printFailMsgforFold(const MachineInstr &MI, unsigned Idx) {
- if (PrintFailedFusing && !MI.isCopy())
+ const X86Subtarget &ST = MI.getMF()->getSubtarget<X86Subtarget>();
+ if (ST.getCLOpts().print_failed_fuse_candidates && !MI.isCopy())
dbgs() << "We failed to fuse operand " << Idx << " in " << MI;
}
@@ -7903,7 +7875,7 @@ X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
VirtRegMap *VRM) const {
MachineBasicBlock::iterator InsertPt = MI;
// Check switch flag
- if (NoFusing)
+ if (Subtarget.getCLOpts().disable_spill_fusing)
return nullptr;
// Avoid partial and undef register update stalls unless optimizing for size.
@@ -8474,7 +8446,7 @@ X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
}
// Check switch flag
- if (NoFusing)
+ if (Subtarget.getCLOpts().disable_spill_fusing)
return nullptr;
// Avoid partial and undef register update stalls unless optimizing for size.
@@ -8487,8 +8459,8 @@ X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
// avoid emit APX relocation when the flag is disabled for backward
// compatibility.
uint64_t TSFlags = MI.getDesc().TSFlags;
- if (!X86EnableAPXForRelocation && isMemInstrWithGOTPCREL(LoadMI) &&
- X86II::hasNewDataDest(TSFlags))
+ if (!Subtarget.getCLOpts().enable_apx_for_relocation &&
+ isMemInstrWithGOTPCREL(LoadMI) && X86II::hasNewDataDest(TSFlags))
return nullptr;
// Determine the alignment of the load.
diff --git a/llvm/lib/Target/X86/X86LoadValueInjectionLoadHardening.cpp b/llvm/lib/Target/X86/X86LoadValueInjectionLoadHardening.cpp
index 871081e3287247d..f55bf8202486aa4 100644
--- a/llvm/lib/Target/X86/X86LoadValueInjectionLoadHardening.cpp
+++ b/llvm/lib/Target/X86/X86LoadValueInjectionLoadHardening.cpp
@@ -56,7 +56,6 @@
#include "llvm/CodeGen/RDFGraph.h"
#include "llvm/CodeGen/RDFLiveness.h"
#include "llvm/InitializePasses.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DOTGraphTraits.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DynamicLibrary.h"
@@ -74,34 +73,6 @@ STATISTIC(NumFunctionsMitigated, "Number of functions for which mitigations "
"were deployed");
STATISTIC(NumGadgets, "Number of LVI gadgets detected during analysis");
-static cl::opt<std::string> OptimizePluginPath(
- PASS_KEY "-opt-plugin",
- cl::desc("Specify a plugin to optimize LFENCE insertion"), cl::Hidden);
-
-static cl::opt<bool> NoConditionalBranches(
- PASS_KEY "-no-cbranch",
- cl::desc("Don't treat conditional branches as disclosure gadgets. This "
- "may improve performance, at the cost of security."),
- cl::init(false), cl::Hidden);
-
-static cl::opt<bool> EmitDot(
- PASS_KEY "-dot",
- cl::desc(
- "For each function, emit a dot graph depicting potential LVI gadgets"),
- cl::init(false), cl::Hidden);
-
-static cl::opt<bool> EmitDotOnly(
- PASS_KEY "-dot-only",
- cl::desc("For each function, emit a dot graph depicting potential LVI "
- "gadgets, and do not insert any fences"),
- cl::init(false), cl::Hidden);
-
-static cl::opt<bool> EmitDotVerify(
- PASS_KEY "-dot-verify",
- cl::desc("For each function, emit a dot graph to stdout depicting "
- "potential LVI gadgets, used for testing purposes only"),
- cl::init(false), cl::Hidden);
-
static llvm::sys::DynamicLibrary OptimizeDL;
typedef int (*OptimizeCutT)(unsigned int *Nodes, unsigned int NodesSize,
unsigned int *Edges, int *EdgeValues,
@@ -274,12 +245,12 @@ bool X86LoadValueInjectionLoadHardeningImpl::run(
if (Graph == nullptr)
return false; // didn't find any gadgets
- if (EmitDotVerify) {
+ if (STI->getCLOpts().lvi_load_dot_verify) {
writeGadgetGraph(outs(), MF, Graph.get());
return false;
}
- if (EmitDot || EmitDotOnly) {
+ if (STI->getCLOpts().lvi_load_dot || STI->getCLOpts().lvi_load_dot_only) {
LLVM_DEBUG(dbgs() << "Emitting gadget graph...\n");
std::error_code FileError;
std::string FileName = "lvi.";
@@ -291,16 +262,16 @@ bool X86LoadValueInjectionLoadHardeningImpl::run(
writeGadgetGraph(FileOut, MF, Graph.get());
FileOut.close();
LLVM_DEBUG(dbgs() << "Emitting gadget graph... Done\n");
- if (EmitDotOnly)
+ if (STI->getCLOpts().lvi_load_dot_only)
return false;
}
int FencesInserted;
- if (!OptimizePluginPath.empty()) {
+ if (!STI->getCLOpts().lvi_load_opt_plugin.empty()) {
if (!OptimizeDL.isValid()) {
std::string ErrorMsg;
OptimizeDL = llvm::sys::DynamicLibrary::getPermanentLibrary(
- OptimizePluginPath.c_str(), &ErrorMsg);
+ STI->getCLOpts().lvi_load_opt_plugin.str().c_str(), &ErrorMsg);
if (!ErrorMsg.empty())
report_fatal_error(Twine("Failed to load opt plugin: \"") + ErrorMsg +
"\"");
@@ -401,7 +372,7 @@ X86LoadValueInjectionLoadHardeningImpl::getGadgetGraph(
// Check whether this use can transmit (leak) its value.
if (instrUsesRegToAccessMemory(UseMI, UseMO.getReg()) ||
- (!NoConditionalBranches &&
+ (!STI->getCLOpts().lvi_load_no_cbranch &&
instrUsesRegToBranch(UseMI, UseMO.getReg()))) {
Transmitters[Def.Id].push_back(Use.Addr->getOwner(DFG).Id);
if (UseMI.mayLoad())
diff --git a/llvm/lib/Target/X86/X86LowerAMXIntrinsics.cpp b/llvm/lib/Target/X86/X86LowerAMXIntrinsics.cpp
index 5e1a30a37f1a8a6..c1d6ea26c0292d2 100644
--- a/llvm/lib/Target/X86/X86LowerAMXIntrinsics.cpp
+++ b/llvm/lib/Target/X86/X86LowerAMXIntrinsics.cpp
@@ -17,6 +17,7 @@
//===----------------------------------------------------------------------===//
//
#include "X86.h"
+#include "X86TargetMachine.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
@@ -60,10 +61,6 @@ static bool isV256I32Ty(Type *Ty) {
}
#endif
-static cl::opt<bool>
- X86ScalarizeAMX("enable-x86-scalar-amx", cl::init(false), cl::Hidden,
- cl::desc("X86: enable AMX scalarizition."));
-
namespace {
class X86LowerAMXIntrinsics {
Function &Func;
@@ -649,8 +646,11 @@ bool X86LowerAMXIntrinsics::visit() {
namespace {
bool shouldRunLowerAMXIntrinsics(const Function &F, const TargetMachine *TM) {
- return X86ScalarizeAMX && (F.hasFnAttribute(Attribute::OptimizeNone) ||
- TM->getOptLevel() == CodeGenOptLevel::None);
+ const X86Options &CLOpts =
+ static_cast<const X86TargetMachine *>(TM)->getCLOpts();
+ return CLOpts.enable_x86_scalar_amx &&
+ (F.hasFnAttribute(Attribute::OptimizeNone) ||
+ TM->getOptLevel() == CodeGenOptLevel::None);
}
bool runLowerAMXIntrinsics(Function &F, DominatorTree *DT, LoopInfo *LI) {
diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp
index ad0946b4c3310fe..82e8329ead04e03 100644
--- a/llvm/lib/Target/X86/X86MCInstLower.cpp
+++ b/llvm/lib/Target/X86/X86MCInstLower.cpp
@@ -56,14 +56,6 @@
using namespace llvm;
-static cl::opt<bool> EnableBranchHint("enable-branch-hint",
- cl::desc("Enable branch hint."),
- cl::init(false), cl::Hidden);
-static cl::opt<unsigned> BranchHintProbabilityThreshold(
- "branch-hint-probability-threshold",
- cl::desc("The probability threshold of enabling branch hint."),
- cl::init(50), cl::Hidden);
-
namespace {
/// X86MCInstLower - This class is used to lower an MachineInstr into an MCInst.
@@ -2652,13 +2644,15 @@ void X86AsmPrinter::emitInstruction(const MachineInstr *MI) {
// Two instruction prefixes (2EH for branch not-taken and 3EH for branch
// taken) are used as branch hints. Here we add branch taken prefix for
// jump instruction with higher probability than threshold.
- if (getSubtarget().hasBranchHint() && EnableBranchHint) {
+ if (getSubtarget().hasBranchHint() &&
+ getSubtarget().getCLOpts().enable_branch_hint) {
const MachineBranchProbabilityInfo *MBPI =
&getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
MachineBasicBlock *DestBB = MI->getOperand(0).getMBB();
BranchProbability EdgeProb =
MBPI->getEdgeProbability(MI->getParent(), DestBB);
- BranchProbability Threshold(BranchHintProbabilityThreshold, 100);
+ BranchProbability Threshold(
+ getSubtarget().getCLOpts().branch_hint_probability_threshold, 100);
if (EdgeProb > Threshold)
EmitAndCountInstruction(MCInstBuilder(X86::DS_PREFIX));
}
diff --git a/llvm/lib/Target/X86/X86OptimizeLEAs.cpp b/llvm/lib/Target/X86/X86OptimizeLEAs.cpp
index 3ea9e942cbb82fc..b2321f40bff2bd2 100644
--- a/llvm/lib/Target/X86/X86OptimizeLEAs.cpp
+++ b/llvm/lib/Target/X86/X86OptimizeLEAs.cpp
@@ -42,7 +42,6 @@
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
#include "llvm/MC/MCInstrDesc.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@@ -55,11 +54,6 @@ using namespace llvm;
#define DEBUG_TYPE "x86-optimize-leas"
-static cl::opt<bool>
- DisableX86LEAOpt("disable-x86-lea-opt", cl::Hidden,
- cl::desc("X86: Disable LEA optimizations."),
- cl::init(false));
-
STATISTIC(NumSubstLEAs, "Number of LEA instruction substitutions");
STATISTIC(NumRedundantLEAs, "Number of redundant LEA instructions removed");
@@ -691,7 +685,7 @@ bool X86OptimizeLEAsImpl::runOnMachineFunction(
MachineBlockFrequencyInfo *MBFI) {
bool Changed = false;
- if (DisableX86LEAOpt)
+ if (MF.getSubtarget<X86Subtarget>().getCLOpts().disable_x86_lea_opt)
return false;
MRI = &MF.getRegInfo();
diff --git a/llvm/lib/Target/X86/X86Options.td b/llvm/lib/Target/X86/X86Options.td
new file mode 100644
index 000000000000000..ccfb0e8c1481492
--- /dev/null
+++ b/llvm/lib/Target/X86/X86Options.td
@@ -0,0 +1,143 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+include "llvm/Option/LibraryOptions.td"
+
+def X86Options : OptionsStruct<prefix = "x86-">;
+
+defm : ValueField<"branch-hint-probability-threshold", "unsigned", "50",
+ "The probability threshold of enabling branch hint">;
+defm : BoolField<"disable-spill-fusing", "false",
+ "Disable fusing of spill code into instructions">;
+defm : BoolField<"disable-x86-domain-reassignment", "false",
+ "X86: Disable Virtual Register Reassignment">;
+defm : BoolField<"disable-x86-lea-opt", "false",
+ "X86: Disable LEA optimizations">;
+defm : BoolField<"enable-branch-hint", "false",
+ "Enable branch hint">;
+defm : BoolField<"enable-x86-scalar-amx", "false",
+ "X86: enable AMX scalarizition">;
+defm : BoolField<"fixup-byte-word-insts", "true",
+ "Change byte and word instructions to larger sizes">;
+defm : BoolField<"mul-constant-optimization", "true",
+ "Replace 'mul x, Const' with more effective instructions like SHIFT, LEA, etc">;
+defm : BoolField<"no-x86-call-frame-opt", "false",
+ "Avoid optimizing x86 call frames for size">;
+defm : ValueField<"partial-reg-update-clearance", "unsigned", "64",
+ "Clearance between two register writes for inserting XOR to avoid partial register update">;
+defm : BoolField<"print-failed-fuse-candidates", "false",
+ "Print instructions that the allocator wants to fuse, but the X86 backend currently can't">;
+defm : BoolField<"remat-pic-stub-load", "false",
+ "Re-materialize load from stub in PIC mode">;
+defm : ValueField<"undef-reg-clearance", "unsigned", "128",
+ "How many idle instructions we would like before certain undef register reads">;
+defm : BoolField<"x86-and-imm-shrink", "true",
+ "Enable setting constant bits to reduce size of mask immediates">;
+defm : ValueField<"x86-br-merging-base-cost", "int", "2",
+ "Sets the cost threshold for when multiple conditionals will be merged into one branch versus be split in multiple branches. "
+ "Merging conditionals saves branches at the cost of additional instructions. This value sets the instruction cost limit, below which conditionals will be merged, and above which conditionals will be split. Set to -1 to never merge branches">;
+defm : ValueField<"x86-br-merging-ccmp-bias", "int", "6",
+ "Increases 'x86-br-merging-base-cost' in cases that the target supports conditional compare instructions">;
+defm : ValueField<"x86-br-merging-likely-bias", "int", "0",
+ "Increases 'x86-br-merging-base-cost' in cases that it is likely that all conditionals will be executed. "
+ "For example for merging the conditionals (a == b && c > d), if its known that a == b is likely, then it is likely that if the conditionals are split both sides will be executed, so it may be desirable to increase the instruction cost threshold. Set to -1 to never merge likely branches">;
+defm : ValueField<"x86-br-merging-unlikely-bias", "int", "-1",
+ "Decreases 'x86-br-merging-base-cost' in cases that it is unlikely that all conditionals will be executed. "
+ "For example for merging the conditionals (a == b && c > d), if its known that a == b is unlikely, then it is unlikely that if the conditionals are split both sides will be executed, so it may be desirable to decrease the instruction cost threshold. Set to -1 to never merge unlikely branches">;
+defm : BoolField<"x86-cmov-converter", "true",
+ "Enable the X86 cmov-to-branch optimization">;
+defm : BoolField<"x86-cmov-converter-force-all", "false",
+ "Convert all cmovs to branches">;
+defm : BoolField<"x86-cmov-converter-force-mem-operand", "true",
+ "Convert cmovs to branches whenever they have memory operands">;
+defm : ValueField<"x86-cmov-converter-threshold", "unsigned", "4",
+ "Minimum gain per loop (in cycles) threshold">;
+defm : BoolField<"x86-disable-avoid-SFB", "false",
+ "X86: Disable Store Forwarding Blocks fixup">;
+defm : BoolField<"x86-disable-regalloc-hints-for-ndd", "false",
+ "Disable two address hints for register allocation">;
+// Temporary option to control early if-conversion for x86 while adding machine
+// models.
+defm : BoolField<"x86-early-ifcvt", "false",
+ "Enable early if-conversion on X86">;
+defm : BoolField<"x86-enable-apx-for-relocation", "false",
+ "Enable APX features (EGPR, NDD and NF) for instructions with relocations on x86-64 ELF">;
+defm : ValueField<"x86-experimental-pref-innermost-loop-alignment", "std::optional<int>", "std::nullopt",
+ "Sets the preferable loop alignment for experiments (as log2 bytes) for innermost loops only. "
+ "If specified, this option overrides alignment set by x86-experimental-pref-loop-alignment">;
+defm : BoolField<"x86-indirect-branch-tracking", "false",
+ "Enable X86 indirect branch tracking pass">;
+defm : BoolField<"x86-lvi-load-dot", "false",
+ "For each function, emit a dot graph depicting potential LVI gadgets">;
+defm : BoolField<"x86-lvi-load-dot-only", "false",
+ "For each function, emit a dot graph depicting potential LVI gadgets, and do not insert any fences">;
+defm : BoolField<"x86-lvi-load-dot-verify", "false",
+ "For each function, emit a dot graph to stdout depicting potential LVI gadgets, used for testing purposes only">;
+defm : BoolField<"x86-lvi-load-no-cbranch", "false",
+ "Don't treat conditional branches as disclosure gadgets. "
+ "This may improve performance, at the cost of security">;
+defm : ValueField<"x86-lvi-load-opt-plugin", "StringRef", "",
+ "Specify a plugin to optimize LFENCE insertion">;
+defm : BoolField<"x86-machine-combiner", "true",
+ "Enable the machine combiner pass">;
+defm : ValueField<"x86-max-nf-conversions-for-cmp-reuse", "unsigned", "6",
+ "Maximum number of NF conversions allowed to reuse EFLAGS from a producer dominating a multi-predecessor block">;
+defm : BoolField<"x86-promote-anyext-load", "true",
+ "Enable promoting aligned anyext load to wider load">;
+defm : BoolField<"x86-seses-enable-without-lvi-cfi", "false",
+ "Force enable speculative execution side effect suppression. "
+ "(Note: User must pass -mlvi-cfi in order to mitigate indirect branches and returns.)">;
+defm : BoolField<"x86-seses-omit-branch-lfences", "false",
+ "Omit all lfences before branch instructions">;
+defm : BoolField<"x86-seses-one-lfence-per-bb", "false",
+ "Omit all lfences other than the first to be placed in a basic block">;
+defm : BoolField<"x86-seses-only-lfence-non-const", "false",
+ "Only lfence before groups of terminators where at least one branch instruction has an input to the addressing mode that is a register other than %rip">;
+defm : ValueField<"x86-setjmp-csr-warning-threshold", "unsigned", "50",
+ "Basic block count threshold for emitting a warning about callee-saved registers reserved due to setjmp">;
+defm : ValueField<"x86-sfb-inspection-limit", "unsigned", "20",
+ "X86: Number of instructions backward to inspect for store forwarding blocks">;
+defm : BoolField<"x86-slh-fence-call-and-ret", "false",
+ "Use a full speculation fence to harden both call and ret edges rather than a lighter weight mitigation">;
+defm : BoolField<"x86-slh-indirect", "true",
+ "Harden indirect calls and jumps against using speculatively stored attacker controlled addresses. "
+ "This is designed to mitigate Spectre v1.2 style attacks">;
+defm : BoolField<"x86-slh-ip", "true",
+ "Harden interprocedurally by passing our state in and out of functions in the high bits of the stack pointer">;
+defm : BoolField<"x86-slh-lfence", "false",
+ "Use LFENCE along each conditional edge to harden against speculative loads rather than conditional movs and poisoned pointers">;
+defm : BoolField<"x86-slh-loads", "true",
+ "Sanitize loads from memory. "
+ "When disable, no significant security is provided">;
+defm : BoolField<"x86-slh-post-load", "true",
+ "Harden the value loaded *after* it is loaded by flushing the loaded bits to 1. "
+ "This is hard to do in general but can be done easily for GPRs">;
+defm : BoolField<"x86-speculative-load-hardening", "false",
+ "Force enable speculative load hardening">;
+defm : BoolField<"x86-tile-ra", "true",
+ "Enable the tile register allocation pass">;
+defm : BoolField<"x86-use-base-pointer", "true",
+ "Enable use of a base pointer for complex stack frames">;
+defm : BoolField<"x86-use-fsrm-for-memcpy", "false",
+ "Use fast short rep mov in memcpy lowering">;
+defm : BoolField<"x86-use-vzeroupper", "true",
+ "Minimize AVX to SSE transition penalty">;
+defm : BoolField<"x86-widen-shift", "true",
+ "Replace narrow shifts with wider shifts">;
+defm : ValueField<"x86-wineh-unwindv2-force-mode", "std::optional<unsigned>", "std::nullopt",
+ "Overwrites the Unwind v2 mode for testing purposes">;
+// This threshold is for the *approximate* number of instructions, see the
+// comment in runAnalysisOnFuncOrFunclet in X86WinEHUnwindV2.cpp for more
+// details.
+defm : ValueField<"x86-wineh-unwindv2-instruction-count-threshold", "unsigned", "600",
+ "Maximum number of (approximate) instructions before splitting into a new unwind info">;
+defm : ValueField<"x86-wineh-unwindv2-unwind-codes-threshold", "unsigned", "UINT8_MAX",
+ "Maximum number of unwind codes before splitting into a new unwind info">;
+defm : ValueField<"x86-wineh-unwindv3-instr-avg-size", "unsigned", "7",
+ "Average size of an instruction. "
+ "This value is used in determining split points for chained unwinder info">;
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index 7e1003c9b470b3a..6ae03b5ca761d21 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -30,7 +30,6 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/MC/MCContext.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetMachine.h"
@@ -39,23 +38,6 @@ using namespace llvm;
#define GET_REGINFO_TARGET_DESC
#include "X86GenRegisterInfo.inc"
-static cl::opt<bool>
-EnableBasePointer("x86-use-base-pointer", cl::Hidden, cl::init(true),
- cl::desc("Enable use of a base pointer for complex stack frames"));
-
-static cl::opt<bool>
- DisableRegAllocNDDHints("x86-disable-regalloc-hints-for-ndd", cl::Hidden,
- cl::init(false),
- cl::desc("Disable two address hints for register "
- "allocation"));
-
-static cl::opt<unsigned> SetjmpCSRWarningThreshold(
- "x86-setjmp-csr-warning-threshold", cl::Hidden, cl::init(50),
- cl::desc("Basic block count threshold for emitting a warning about "
- "callee-saved registers reserved due to setjmp"));
-
-extern cl::opt<bool> X86EnableAPXForRelocation;
-
X86RegisterInfo::X86RegisterInfo(const Triple &TT)
: X86GenRegisterInfo((TT.isX86_64() ? X86::RIP : X86::EIP),
X86_MC::getDwarfRegFlavour(TT, false),
@@ -130,10 +112,9 @@ X86RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
// Keep using non-rex2 register class when APX feature (EGPR/NDD/NF) is not
// enabled for relocation.
- if (!X86EnableAPXForRelocation && isNonRex2RegClass(RC))
- return RC;
-
const X86Subtarget &Subtarget = MF.getSubtarget<X86Subtarget>();
+ if (!Subtarget.getCLOpts().enable_apx_for_relocation && isNonRex2RegClass(RC))
+ return RC;
const TargetRegisterClass *Super = RC;
auto I = RC->superclasses().begin();
@@ -649,7 +630,8 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
for (const MCPhysReg &SubReg : subregs_inclusive(Reg))
Reserved.set(SubReg);
}
- if (NumReservedCSRs && MF.size() > SetjmpCSRWarningThreshold &&
+ if (NumReservedCSRs &&
+ MF.size() > ST.getCLOpts().setjmp_csr_warning_threshold &&
!MF.getRegInfo().reservedRegsFrozen()) {
MF.getContext().reportWarning(
SMLoc(), Twine(NumReservedCSRs) +
@@ -808,7 +790,7 @@ bool X86RegisterInfo::hasBasePointer(const MachineFunction &MF) const {
const MachineFrameInfo &MFI = MF.getFrameInfo();
- if (!EnableBasePointer)
+ if (!MF.getSubtarget<X86Subtarget>().getCLOpts().use_base_pointer)
return false;
// When we need stack realignment, we can't address the stack from the frame
@@ -1182,7 +1164,7 @@ bool X86RegisterInfo::getRegAllocationHints(Register VirtReg,
return BaseImplRetVal;
if (ID != X86::TILERegClassID) {
- if (DisableRegAllocNDDHints || !ST.hasNDD() ||
+ if (ST.getCLOpts().disable_regalloc_hints_for_ndd || !ST.hasNDD() ||
!TRI.isGeneralPurposeRegisterClass(&RC))
return BaseImplRetVal;
diff --git a/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp b/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp
index 8b9782be0ea41ae..8d5dadf6ea9f666 100644
--- a/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp
+++ b/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp
@@ -25,10 +25,6 @@ using namespace llvm;
#define DEBUG_TYPE "x86-selectiondag-info"
-static cl::opt<bool>
- UseFSRMForMemcpy("x86-use-fsrm-for-memcpy", cl::Hidden, cl::init(false),
- cl::desc("Use fast short rep mov in memcpy lowering"));
-
X86SelectionDAGInfo::X86SelectionDAGInfo()
: SelectionDAGGenTargetInfo(X86GenSDNodeInfo) {}
@@ -405,7 +401,7 @@ SDValue X86SelectionDAGInfo::EmitTargetCodeForMemcpy(
return SDValue();
// If enabled and available, use fast short rep mov.
- if (UseFSRMForMemcpy && Subtarget.hasFSRM())
+ if (Subtarget.getCLOpts().use_fsrm_for_memcpy && Subtarget.hasFSRM())
return emitRepmovs(Subtarget, DAG, dl, Chain, Dst, Src, Size, MVT::i8);
// Handle constant sizes
diff --git a/llvm/lib/Target/X86/X86SpeculativeExecutionSideEffectSuppression.cpp b/llvm/lib/Target/X86/X86SpeculativeExecutionSideEffectSuppression.cpp
index 5558ffd7ab067cb..fd396fb3cbbcef9 100644
--- a/llvm/lib/Target/X86/X86SpeculativeExecutionSideEffectSuppression.cpp
+++ b/llvm/lib/Target/X86/X86SpeculativeExecutionSideEffectSuppression.cpp
@@ -29,31 +29,6 @@ using namespace llvm;
STATISTIC(NumLFENCEsInserted, "Number of lfence instructions inserted");
-static cl::opt<bool> EnableSpeculativeExecutionSideEffectSuppression(
- "x86-seses-enable-without-lvi-cfi",
- cl::desc("Force enable speculative execution side effect suppression. "
- "(Note: User must pass -mlvi-cfi in order to mitigate indirect "
- "branches and returns.)"),
- cl::init(false), cl::Hidden);
-
-static cl::opt<bool> OneLFENCEPerBasicBlock(
- "x86-seses-one-lfence-per-bb",
- cl::desc(
- "Omit all lfences other than the first to be placed in a basic block."),
- cl::init(false), cl::Hidden);
-
-static cl::opt<bool> OnlyLFENCENonConst(
- "x86-seses-only-lfence-non-const",
- cl::desc("Only lfence before groups of terminators where at least one "
- "branch instruction has an input to the addressing mode that is a "
- "register other than %rip."),
- cl::init(false), cl::Hidden);
-
-static cl::opt<bool>
- OmitBranchLFENCEs("x86-seses-omit-branch-lfences",
- cl::desc("Omit all lfences before branch instructions."),
- cl::init(false), cl::Hidden);
-
namespace {
constexpr StringRef X86SESESPassName =
@@ -96,7 +71,7 @@ runX86SpeculativeExecutionSideEffectSuppression(MachineFunction &MF) {
// Check whether SESES needs to run as the fallback for LVI at O0, whether the
// user explicitly passed an SESES flag, or whether the SESES target feature
// was set.
- if (!EnableSpeculativeExecutionSideEffectSuppression &&
+ if (!Subtarget.getCLOpts().seses_enable_without_lvi_cfi &&
!(Subtarget.useLVILoadHardening() && OptLevel == CodeGenOptLevel::None) &&
!Subtarget.useSpeculativeExecutionSideEffectSuppression())
return false;
@@ -127,7 +102,7 @@ runX86SpeculativeExecutionSideEffectSuppression(MachineFunction &MF) {
NumLFENCEsInserted++;
Modified = true;
}
- if (OneLFENCEPerBasicBlock)
+ if (Subtarget.getCLOpts().seses_one_lfence_per_bb)
break;
}
// The following section will be LFENCEing before groups of terminators
@@ -148,13 +123,14 @@ runX86SpeculativeExecutionSideEffectSuppression(MachineFunction &MF) {
// Look for branch instructions that will require an LFENCE to be put
// before this basic block's terminators.
- if (!MI.isBranch() || OmitBranchLFENCEs) {
+ if (!MI.isBranch() || Subtarget.getCLOpts().seses_omit_branch_lfences) {
// This isn't a branch or we're not putting LFENCEs before branches.
PrevInstIsLFENCE = false;
continue;
}
- if (OnlyLFENCENonConst && hasConstantAddressingMode(MI)) {
+ if (Subtarget.getCLOpts().seses_only_lfence_non_const &&
+ hasConstantAddressingMode(MI)) {
// This is a branch, but it only has constant addressing mode and we're
// not adding LFENCEs before such branches.
PrevInstIsLFENCE = false;
diff --git a/llvm/lib/Target/X86/X86SpeculativeLoadHardening.cpp b/llvm/lib/Target/X86/X86SpeculativeLoadHardening.cpp
index 89111b5b7899c7a..19ec1bfd448d50f 100644
--- a/llvm/lib/Target/X86/X86SpeculativeLoadHardening.cpp
+++ b/llvm/lib/Target/X86/X86SpeculativeLoadHardening.cpp
@@ -48,7 +48,6 @@
#include "llvm/IR/DebugLoc.h"
#include "llvm/MC/MCSchedule.h"
#include "llvm/Pass.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
@@ -72,50 +71,6 @@ 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(
- "Use LFENCE along each conditional edge to harden against speculative "
- "loads rather than conditional movs and poisoned pointers."),
- cl::init(false), cl::Hidden);
-
-static cl::opt<bool> EnablePostLoadHardening(
- PASS_KEY "-post-load",
- cl::desc("Harden the value loaded *after* it is loaded by "
- "flushing the loaded bits to 1. This is hard to do "
- "in general but can be done easily for GPRs."),
- cl::init(true), cl::Hidden);
-
-static cl::opt<bool> FenceCallAndRet(
- PASS_KEY "-fence-call-and-ret",
- cl::desc("Use a full speculation fence to harden both call and ret edges "
- "rather than a lighter weight mitigation."),
- cl::init(false), cl::Hidden);
-
-static cl::opt<bool> HardenInterprocedurally(
- PASS_KEY "-ip",
- cl::desc("Harden interprocedurally by passing our state in and out of "
- "functions in the high bits of the stack pointer."),
- cl::init(true), cl::Hidden);
-
-static cl::opt<bool>
- HardenLoads(PASS_KEY "-loads",
- cl::desc("Sanitize loads from memory. When disable, no "
- "significant security is provided."),
- cl::init(true), cl::Hidden);
-
-static cl::opt<bool> HardenIndirectCallsAndJumps(
- PASS_KEY "-indirect",
- cl::desc("Harden indirect calls and jumps against using speculatively "
- "stored attacker controlled addresses. This is designed to "
- "mitigate Spectre v1.2 style attacks."),
- cl::init(true), cl::Hidden);
-
namespace {
constexpr StringRef X86SLHPassName = "X86 speculative load hardening";
@@ -415,11 +370,11 @@ bool X86SpeculativeLoadHardeningImpl::run(MachineFunction &MF) {
// Only run if this pass is forced enabled or we detect the relevant function
// attribute requesting SLH.
- if (!EnableSpeculativeLoadHardening &&
+ Subtarget = &MF.getSubtarget<X86Subtarget>();
+ if (!Subtarget->getCLOpts().speculative_load_hardening &&
!MF.getFunction().hasFnAttribute(Attribute::SpeculativeLoadHardening))
return false;
- Subtarget = &MF.getSubtarget<X86Subtarget>();
MRI = &MF.getRegInfo();
TII = Subtarget->getInstrInfo();
TRI = Subtarget->getRegisterInfo();
@@ -432,7 +387,7 @@ bool X86SpeculativeLoadHardeningImpl::run(MachineFunction &MF) {
return false;
// We support an alternative hardening technique based on a debug flag.
- if (HardenEdgesWithLFENCE) {
+ if (Subtarget->getCLOpts().slh_lfence) {
hardenEdgesWithLFENCE(MF);
return true;
}
@@ -464,7 +419,7 @@ bool X86SpeculativeLoadHardeningImpl::run(MachineFunction &MF) {
// If we have loads being hardened and we've asked for call and ret edges to
// get a full fence-based mitigation, inject that fence.
- if (HasVulnerableLoad && FenceCallAndRet) {
+ if (HasVulnerableLoad && Subtarget->getCLOpts().slh_fence_call_and_ret) {
// We need to insert an LFENCE at the start of the function to suspend any
// incoming misspeculation from the caller. This helps two-fold: the caller
// may not have been protected as this code has been, and this code gets to
@@ -478,12 +433,13 @@ bool X86SpeculativeLoadHardeningImpl::run(MachineFunction &MF) {
// If we guarded the entry with an LFENCE and have no conditionals to protect
// in blocks, then we're done.
- if (FenceCallAndRet && Infos.empty())
+ if (Subtarget->getCLOpts().slh_fence_call_and_ret && Infos.empty())
// We may have changed the function's code at this point to insert fences.
return true;
// For every basic block in the function which can b
- if (HardenInterprocedurally && !FenceCallAndRet) {
+ if (Subtarget->getCLOpts().slh_ip &&
+ !Subtarget->getCLOpts().slh_fence_call_and_ret) {
// Set up the predicate state by extracting it from the incoming stack
// pointer so we pick up any misspeculation in our caller.
PS->InitialReg = extractPredStateFromSP(Entry, EntryInsertPt, Loc);
@@ -526,7 +482,7 @@ bool X86SpeculativeLoadHardeningImpl::run(MachineFunction &MF) {
// predicate state in the stack pointer, so extract fresh predicate state from
// the stack pointer and make it available in SSA.
// FIXME: Handle non-itanium ABI EH models.
- if (HardenInterprocedurally) {
+ if (Subtarget->getCLOpts().slh_ip) {
for (MachineBasicBlock &MBB : MF) {
assert(!MBB.isEHScopeEntry() && "Only Itanium ABI EH supported!");
assert(!MBB.isEHFuncletEntry() && "Only Itanium ABI EH supported!");
@@ -539,7 +495,7 @@ bool X86SpeculativeLoadHardeningImpl::run(MachineFunction &MF) {
}
}
- if (HardenIndirectCallsAndJumps) {
+ if (Subtarget->getCLOpts().slh_indirect) {
// If we are going to harden calls and jumps we need to unfold their memory
// operands.
unfoldCallAndJumpLoads(MF);
@@ -1301,7 +1257,7 @@ void X86SpeculativeLoadHardeningImpl::tracePredStateThroughBlocksAndHarden(
// be free (due to reuse).
//
// Note that we only need this pass if we are actually hardening loads.
- if (HardenLoads)
+ if (Subtarget->getCLOpts().slh_loads)
for (MachineInstr &MI : MBB) {
// We naively assume that all def'ed registers of an instruction have
// a data dependency on all of their operands.
@@ -1368,9 +1324,9 @@ void X86SpeculativeLoadHardeningImpl::tracePredStateThroughBlocksAndHarden(
// address registers, queue it up to be hardened post-load. Notably,
// even once hardened this won't introduce a useful dependency that
// could prune out subsequent loads.
- if (EnablePostLoadHardening && X86InstrInfo::isDataInvariantLoad(MI) &&
- !isEFLAGSDefLive(MI) && MI.getDesc().getNumDefs() == 1 &&
- MI.getOperand(0).isReg() &&
+ if (Subtarget->getCLOpts().slh_post_load &&
+ X86InstrInfo::isDataInvariantLoad(MI) && !isEFLAGSDefLive(MI) &&
+ MI.getDesc().getNumDefs() == 1 && MI.getOperand(0).isReg() &&
canHardenRegister(MI.getOperand(0).getReg()) &&
!HardenedAddrRegs.count(BaseReg) &&
!HardenedAddrRegs.count(IndexReg)) {
@@ -1398,7 +1354,7 @@ void X86SpeculativeLoadHardeningImpl::tracePredStateThroughBlocksAndHarden(
// which we will do post-load hardening and can defer it in certain
// circumstances.
for (MachineInstr &MI : MBB) {
- if (HardenLoads) {
+ if (Subtarget->getCLOpts().slh_loads) {
// We cannot both require hardening the def of a load and its address.
assert(!(HardenLoadAddr.count(&MI) && HardenPostLoad.count(&MI)) &&
"Requested to harden both the address and def of a load!");
@@ -1457,13 +1413,14 @@ void X86SpeculativeLoadHardeningImpl::tracePredStateThroughBlocksAndHarden(
// avoid hardening it for some reason. Note that here we cannot break
// out afterward as we may still need to handle any call aspect of this
// instruction.
- if ((MI.isCall() || MI.isBranch()) && HardenIndirectCallsAndJumps)
+ if ((MI.isCall() || MI.isBranch()) &&
+ Subtarget->getCLOpts().slh_indirect)
hardenIndirectCallOrJumpInstr(MI, AddrRegToHardenedReg);
}
// After we finish hardening loads we handle interprocedural hardening if
// enabled and relevant for this instruction.
- if (!HardenInterprocedurally)
+ if (!Subtarget->getCLOpts().slh_ip)
continue;
if (!MI.isCall() && !MI.isReturn())
continue;
@@ -2015,7 +1972,7 @@ void X86SpeculativeLoadHardeningImpl::hardenReturnInstr(MachineInstr &MI) {
const DebugLoc &Loc = MI.getDebugLoc();
auto InsertPt = MI.getIterator();
- if (FenceCallAndRet)
+ if (Subtarget->getCLOpts().slh_fence_call_and_ret)
// No need to fence here as we'll fence at the return site itself. That
// handles more cases than we can handle here.
return;
@@ -2063,7 +2020,7 @@ void X86SpeculativeLoadHardeningImpl::tracePredStateThroughCall(
auto InsertPt = MI.getIterator();
const DebugLoc &Loc = MI.getDebugLoc();
- if (FenceCallAndRet) {
+ if (Subtarget->getCLOpts().slh_fence_call_and_ret) {
if (MI.isReturn())
// Tail call, we don't return to this function.
// FIXME: We should also handle noreturn calls.
diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp
index ed2da3128b44af9..818c441f566bd2d 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -27,9 +27,9 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h"
+#include "llvm/Option/LibraryOptions.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetMachine.h"
@@ -47,12 +47,8 @@ using namespace llvm;
#define GET_SUBTARGETINFO_CTOR
#include "X86GenSubtargetInfo.inc"
-// Temporary option to control early if-conversion for x86 while adding machine
-// models.
-static cl::opt<bool>
-X86EarlyIfConv("x86-early-ifcvt", cl::Hidden,
- cl::desc("Enable early if-conversion on X86"));
-
+#define OPTIONS_STRUCT_DEFS
+#include "X86Options.inc"
/// Classify a blockaddress reference for the current subtarget according to how
/// we should reference it in a non-pcrel context.
@@ -319,7 +315,7 @@ X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
MaybeAlign StackAlignOverride,
unsigned PreferVectorWidthOverride,
unsigned RequiredVectorWidth)
- : X86GenSubtargetInfo(TT, CPU, TuneCPU, FS),
+ : X86GenSubtargetInfo(TT, CPU, TuneCPU, FS), CLOpts(TM.getCLOpts()),
PICStyle(PICStyles::Style::None), TM(TM), TargetTriple(TT),
StackAlignOverride(StackAlignOverride),
PreferVectorWidthOverride(PreferVectorWidthOverride),
@@ -368,7 +364,7 @@ const RegisterBankInfo *X86Subtarget::getRegBankInfo() const {
}
bool X86Subtarget::enableEarlyIfConversion() const {
- return canUseCMOV() && X86EarlyIfConv;
+ return canUseCMOV() && CLOpts.early_ifcvt;
}
void X86Subtarget::getPostRAMutations(
diff --git a/llvm/lib/Target/X86/X86Subtarget.h b/llvm/lib/Target/X86/X86Subtarget.h
index 6cfea5645791009..bc87ce9353d03e8 100644
--- a/llvm/lib/Target/X86/X86Subtarget.h
+++ b/llvm/lib/Target/X86/X86Subtarget.h
@@ -22,7 +22,12 @@
#include "llvm/TargetParser/Triple.h"
#include <bitset>
#include <climits>
+#include <cstdint>
#include <memory>
+#include <optional>
+
+#define OPTIONS_STRUCT_DECL
+#include "X86Options.inc"
#define GET_SUBTARGETINFO_HEADER
#include "X86GenSubtargetInfo.inc"
@@ -51,6 +56,8 @@ enum class Style {
} // end namespace PICStyles
class X86Subtarget final : public X86GenSubtargetInfo {
+ const X86Options &CLOpts;
+
enum X86SSEEnum {
NoSSE, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, AVX, AVX2, AVX512
};
@@ -121,6 +128,8 @@ class X86Subtarget final : public X86GenSubtargetInfo {
unsigned RequiredVectorWidth);
~X86Subtarget() override;
+ const X86Options &getCLOpts() const { return CLOpts; }
+
const X86TargetLowering *getTargetLowering() const override {
return &TLInfo;
}
diff --git a/llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp b/llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp
index db4454f91382656..e73ac5458b70218 100644
--- a/llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp
+++ b/llvm/lib/Target/X86/X86SuppressAPXForReloc.cpp
@@ -32,12 +32,6 @@ using namespace llvm;
#define DEBUG_TYPE "x86-suppress-apx-for-relocation"
-cl::opt<bool> X86EnableAPXForRelocation(
- "x86-enable-apx-for-relocation",
- cl::desc("Enable APX features (EGPR, NDD and NF) for instructions with "
- "relocations on x86-64 ELF"),
- cl::init(false));
-
namespace {
class X86SuppressAPXForRelocationLegacy : public MachineFunctionPass {
public:
@@ -250,9 +244,9 @@ static bool handleNDDOrNFInstructions(MachineFunction &MF,
}
static bool suppressAPXForRelocation(MachineFunction &MF) {
- if (X86EnableAPXForRelocation)
- return false;
const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();
+ if (ST.getCLOpts().enable_apx_for_relocation)
+ return false;
bool Changed = handleInstructionWithEGPR(MF, ST);
Changed |= handleNDDOrNFInstructions(MF, ST);
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index 72dab51b67eced2..e6e44ad5e83722d 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -40,9 +40,9 @@
#include "llvm/IR/Function.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Option/LibraryOptions.h"
#include "llvm/Pass.h"
#include "llvm/Support/CodeGen.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
@@ -53,20 +53,11 @@
using namespace llvm;
-cl::opt<bool>
- X86EnableMachineCombinerPass("x86-machine-combiner",
- cl::desc("Enable the machine combiner pass"),
- cl::init(true), cl::Hidden);
-
-static cl::opt<bool>
- EnableTileRAPass("x86-tile-ra",
- cl::desc("Enable the tile register allocation pass"),
- cl::init(true), cl::Hidden);
-
extern "C" LLVM_C_ABI void LLVMInitializeX86Target() {
// Register the target.
RegisterTargetMachine<X86TargetMachine> X(getTheX86_32Target());
RegisterTargetMachine<X86TargetMachine> Y(getTheX86_64Target());
+ static opt::RegisterLibraryOptions<X86Options> O;
PassRegistry &PR = *PassRegistry::getPassRegistry();
initializeX86LowerAMXIntrinsicsLegacyPassPass(PR);
@@ -193,7 +184,8 @@ X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT,
: CodeGenTargetMachineImpl(T, TT, CPU, FS, Options,
getEffectiveRelocModel(TT, JIT, RM),
getEffectiveX86CodeModel(TT, CM, JIT), OL),
- TLOF(createTLOF(getTargetTriple())), IsJIT(JIT) {
+ CLOpts(X86Options::Global), TLOF(createTLOF(getTargetTriple())),
+ IsJIT(JIT) {
// On PS4/PS5, the "return address" of a 'noreturn' call must still be within
// the calling function. Note that this also includes __stack_chk_fail,
// so there was some target-specific logic in the instruction selectors
@@ -498,7 +490,7 @@ void X86PassConfig::addPreLegalizeMachineIR() {
bool X86PassConfig::addILPOpts() {
addPass(&EarlyIfConverterLegacyID);
- if (X86EnableMachineCombinerPass)
+ if (getX86TargetMachine().getCLOpts().machine_combiner)
addPass(&MachineCombinerID);
addPass(createX86CmovConversionLegacyPass());
return true;
@@ -658,7 +650,7 @@ static bool onlyAllocateTileRegisters(const TargetRegisterInfo &TRI,
bool X86PassConfig::addRegAssignAndRewriteOptimized() {
// Don't support tile RA when RA is specified by command line "-regalloc".
- if (!isCustomizedRegAlloc() && EnableTileRAPass) {
+ if (!isCustomizedRegAlloc() && getX86TargetMachine().getCLOpts().tile_ra) {
// Allocate tile register first.
addPass(createGreedyRegisterAllocator(onlyAllocateTileRegisters));
addPass(createX86TileConfigLegacyPass());
diff --git a/llvm/lib/Target/X86/X86TargetMachine.h b/llvm/lib/Target/X86/X86TargetMachine.h
index 361541d4482a1e4..7e033e471006bf7 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.h
+++ b/llvm/lib/Target/X86/X86TargetMachine.h
@@ -26,6 +26,7 @@ class StringRef;
class TargetTransformInfo;
class X86TargetMachine final : public CodeGenTargetMachineImpl {
+ const X86Options &CLOpts;
std::unique_ptr<TargetLoweringObjectFile> TLOF;
mutable StringMap<std::unique_ptr<X86Subtarget>> SubtargetMap;
// True if this is used in JIT.
@@ -42,6 +43,8 @@ class X86TargetMachine final : public CodeGenTargetMachineImpl {
bool JIT);
~X86TargetMachine() override;
+ const X86Options &getCLOpts() const { return CLOpts; }
+
const X86Subtarget *getSubtargetImpl(const Function &F) const override;
// DO NOT IMPLEMENT: There is no such thing as a valid default subtarget,
// subtargets are per-function entities based on the target-specific
diff --git a/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp b/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp
index 79b91206e9d5b12..52ea0f08c41504c 100644
--- a/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp
+++ b/llvm/lib/Target/X86/X86WinEHUnwindV2.cpp
@@ -14,6 +14,7 @@
#include "MCTargetDesc/X86BaseInfo.h"
#include "X86.h"
+#include "X86Subtarget.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -33,24 +34,6 @@ STATISTIC(MeetsUnwindV2Criteria,
STATISTIC(FailsUnwindV2Criteria,
"Number of functions that fail Unwind v2 criteria");
-static cl::opt<unsigned>
- UnwindCodeThreshold("x86-wineh-unwindv2-unwind-codes-threshold", cl::Hidden,
- cl::desc("Maximum number of unwind codes before "
- "splitting into a new unwind info."),
- cl::init(UINT8_MAX));
-
-static cl::opt<unsigned>
- ForceMode("x86-wineh-unwindv2-force-mode", cl::Hidden,
- cl::desc("Overwrites the Unwind v2 mode for testing purposes."));
-
-// This threshold is for the *approximate* number of instructions, see the
-// comment in runAnalysisOnFuncOrFunclet for more details.
-static cl::opt<unsigned> InstructionCountThreshold(
- "x86-wineh-unwindv2-instruction-count-threshold", cl::Hidden,
- cl::desc("Maximum number of (approximate) instructions before splitting "
- "into a new unwind info."),
- cl::init(600));
-
namespace {
struct EpilogInfo {
@@ -373,10 +356,11 @@ runAnalysisOnFuncOrFunclet(MachineFunction &MF, MachineFunction::iterator &Iter,
}
bool runX86WinEHUnwindV2(MachineFunction &MF) {
+ const X86Options &CLOpts = MF.getSubtarget<X86Subtarget>().getCLOpts();
+ std::optional<unsigned> ForceMode = CLOpts.wineh_unwindv2_force_mode;
WinX64EHUnwindMode Mode =
- ForceMode.getNumOccurrences()
- ? static_cast<WinX64EHUnwindMode>(ForceMode.getValue())
- : MF.getFunction().getParent()->getWinX64EHUnwindMode();
+ ForceMode ? static_cast<WinX64EHUnwindMode>(*ForceMode)
+ : MF.getFunction().getParent()->getWinX64EHUnwindMode();
// Only act on V2 modes; V1 = disabled, V3 handled by the V3 pass.
if (Mode != WinX64EHUnwindMode::V2BestEffort &&
@@ -421,8 +405,8 @@ bool runX86WinEHUnwindV2(MachineFunction &MF) {
TII->get(X86::SEH_UnwindV2Start));
if ((LastUnwindInfoEndPosition - Info.ApproximateInstructionPosition >=
- InstructionCountThreshold) ||
- (UnwindCodeCount >= UnwindCodeThreshold)) {
+ CLOpts.wineh_unwindv2_instruction_count_threshold) ||
+ (UnwindCodeCount >= CLOpts.wineh_unwindv2_unwind_codes_threshold)) {
BuildMI(MBB, MBB.begin(), DL,
TII->get(X86::SEH_SplitChainedAtEndOfBlock));
LastUnwindInfoEndPosition = Info.ApproximateInstructionPosition;
diff --git a/llvm/lib/Target/X86/X86WinEHUnwindV3.cpp b/llvm/lib/Target/X86/X86WinEHUnwindV3.cpp
index 97529c5c5e7951a..5963167b70908f2 100644
--- a/llvm/lib/Target/X86/X86WinEHUnwindV3.cpp
+++ b/llvm/lib/Target/X86/X86WinEHUnwindV3.cpp
@@ -33,7 +33,6 @@
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
@@ -49,7 +48,6 @@ STATISTIC(SubFragmentSplits,
static constexpr unsigned MaxV3PrologOps = 31;
static constexpr unsigned MaxV3Epilogs = 7;
static constexpr unsigned MaxV3EpilogOps = 31;
-static constexpr unsigned EpilogDistanceThreshold = 32767;
/// Approximate byte distance between an epilog and its fragment tail beyond
/// which the funclet is split into a new chained sub-fragment. The V3
@@ -58,12 +56,7 @@ static constexpr unsigned EpilogDistanceThreshold = 32767;
/// exact byte offsets aren't known until MC layout, so (like the V2 pass) an
/// approximate byte count is used as a proxy — instructions are charged
/// ApproxBytesPerInstr each and alignment padding is added.
-static cl::opt<unsigned> ApproxBytesPerInstr(
- "x86-wineh-unwindv3-instr-avg-size", cl::Hidden,
- cl::desc(
- "Average size of an instruction. This value is used in determining "
- "split points for chained unwinder info"),
- cl::init(7));
+static constexpr unsigned EpilogDistanceThreshold = 32767;
/// After reporting a recoverable error for `MF`, erase all SEH pseudo-
/// instructions and clear the WinCFI flag so the AsmPrinter doesn't try to
@@ -160,6 +153,8 @@ FuncletInfo X86WinEHUnwindV3::analyzeFunclet(MachineFunction &MF,
bool InEpilog = false;
bool SeenProlog = false;
unsigned CurrentEpilogOpCount = 0;
+ const unsigned ApproxBytesPerInstr =
+ MF.getSubtarget<X86Subtarget>().getCLOpts().wineh_unwindv3_instr_avg_size;
for (; Iter != MF.end(); ++Iter) {
MachineBasicBlock &MBB = *Iter;
diff --git a/llvm/test/CodeGen/X86/apx/optimize-compare-multipred.mir b/llvm/test/CodeGen/X86/apx/optimize-compare-multipred.mir
index c8d5c1dd5dfb579..30b43406a8f27b2 100644
--- a/llvm/test/CodeGen/X86/apx/optimize-compare-multipred.mir
+++ b/llvm/test/CodeGen/X86/apx/optimize-compare-multipred.mir
@@ -628,9 +628,9 @@ body: |
...
# Self-loop where the below-CmpInstr region holds 7 NF-convertible dead clobbers,
-# exceeding the default MaxNFConversions cap of 6. The below-scan declines
-# staging and the redundant compare is kept. Exercises the cap-bail branch of
-# the below-scan.
+# exceeding the default -x86-max-nf-conversions-for-cmp-reuse cap of 6. The
+# below-scan declines staging and the redundant compare is kept. Exercises the
+# cap-bail branch of the below-scan.
---
name: selfloop_nfconvertible_below_cap
tracksRegLiveness: true
diff --git a/llvm/unittests/Option/LibraryOptionsTest.cpp b/llvm/unittests/Option/LibraryOptionsTest.cpp
index f13147b9feab528..2ee4e9c9716bad2 100644
--- a/llvm/unittests/Option/LibraryOptionsTest.cpp
+++ b/llvm/unittests/Option/LibraryOptionsTest.cpp
@@ -6,6 +6,8 @@
//
//===----------------------------------------------------------------------===//
+#include <optional>
+
#define OPTIONS_STRUCT_DECL
#include "LibraryOpts.inc"
@@ -27,6 +29,7 @@ TEST(LibraryOptionsTest, Apply) {
TestLibraryOptions O;
EXPECT_FALSE(O.enable);
EXPECT_EQ(O.count, 3u);
+ EXPECT_EQ(O.limit, std::nullopt);
EXPECT_EQ(O.ratio, 0.5);
EXPECT_EQ(O.Path, "p");
@@ -39,11 +42,12 @@ TEST(LibraryOptionsTest, Apply) {
Applied.push_back(O.apply(*A));
return Applied;
};
- EXPECT_THAT(Apply({"-lib-enable", "--lib-count=7", "-lib-ratio", "0.25",
- "-lib-path=a=b"}),
+ EXPECT_THAT(Apply({"-lib-enable", "--lib-count=7", "-lib-limit=0",
+ "-lib-ratio", "0.25", "-lib-path=a=b"}),
testing::Each(true));
EXPECT_TRUE(O.enable);
EXPECT_EQ(O.count, 7u);
+ EXPECT_EQ(O.limit, 0u);
EXPECT_EQ(O.ratio, 0.25);
EXPECT_EQ(O.Path, "a=b");
EXPECT_THAT(Apply({"-lib-enable=false"}), testing::Each(true));
@@ -52,10 +56,12 @@ TEST(LibraryOptionsTest, Apply) {
EXPECT_TRUE(O.enable);
// A rejected value leaves the member unchanged.
- EXPECT_THAT(Apply({"-lib-enable=2", "-lib-count=-1", "-lib-ratio=y"}),
- testing::Each(false));
+ EXPECT_THAT(
+ Apply({"-lib-enable=2", "-lib-count=-1", "-lib-limit=x", "-lib-ratio=y"}),
+ testing::Each(false));
EXPECT_TRUE(O.enable);
EXPECT_EQ(O.count, 7u);
+ EXPECT_EQ(O.limit, 0u);
EXPECT_EQ(O.ratio, 0.25);
}
@@ -73,6 +79,7 @@ TEST(LibraryOptionsTest, Parser) {
EXPECT_THAT(Rows, testing::ElementsAre(
"lib-count=|<value>|An unsigned", "lib-count||",
"lib-enable=|<value>|", "lib-enable||A bool",
+ "lib-limit=|<value>|An optional", "lib-limit||",
"lib-path=|<value>|A string", "lib-path||",
"lib-ratio=|<value>|A double", "lib-ratio||"));
diff --git a/llvm/unittests/Option/LibraryOpts.td b/llvm/unittests/Option/LibraryOpts.td
index ee1a838071b9c88..1f1a7dfcc7cfa09 100644
--- a/llvm/unittests/Option/LibraryOpts.td
+++ b/llvm/unittests/Option/LibraryOpts.td
@@ -12,5 +12,7 @@ def TestLibraryOptions : OptionsStruct<"test", prefix = "lib-">;
defm : BoolField<"lib-enable", "false", "A bool">;
defm : ValueField<"lib-count", "unsigned", "3", "An unsigned">;
+defm : ValueField<"lib-limit", "std::optional<unsigned>", "std::nullopt",
+ "An optional">;
defm : ValueField<"lib-ratio", "double", "0.5", "A double">;
defm Path : ValueField<"lib-path", "StringRef", "\"p\"", "A string">;
diff --git a/llvm/utils/gn/secondary/llvm/lib/Target/X86/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/X86/BUILD.gn
index cef2b85579d8d72..ab040c94487a178 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Target/X86/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Target/X86/BUILD.gn
@@ -85,6 +85,12 @@ tablegen("X86GenPostLegalizeGICombiner") {
td_file = "X86.td"
}
+tablegen("X86Options") {
+ visibility = [ ":LLVMX86CodeGen" ]
+ args = [ "-gen-opt-parser-defs" ]
+ td_file = "X86Options.td"
+}
+
static_library("LLVMX86CodeGen") {
deps = [
":X86GenAsmMatcher",
@@ -98,6 +104,7 @@ static_library("LLVMX86CodeGen") {
":X86GenPreLegalizeGICombiner",
":X86GenRegisterBank",
":X86GenSDNodeInfo",
+ ":X86Options",
"MCTargetDesc",
"TargetInfo",
"//llvm/include/llvm/Config:llvm-config",
@@ -109,6 +116,7 @@ static_library("LLVMX86CodeGen") {
"//llvm/lib/IR",
"//llvm/lib/IRPrinter",
"//llvm/lib/MC",
+ "//llvm/lib/Option",
"//llvm/lib/Passes",
"//llvm/lib/Support",
"//llvm/lib/Target",
diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
index 9464aa824f6c0a8..f9074a04a43a9df 100644
--- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -3727,6 +3727,9 @@ llvm_target_lib_list = [lib for lib in [
"lib/Target/X86/X86GenMnemonicTables.inc",
),
],
+ "tbl_deps": [
+ ":X86OptionsTableGen",
+ ],
},
{
"name": "XCore",
@@ -3949,6 +3952,15 @@ gentbl_cc_library(
deps = [":OptParserTdFiles"],
)
+gentbl_cc_library(
+ name = "X86OptionsTableGen",
+ strip_include_prefix = "lib/Target/X86",
+ tbl_outs = {"lib/Target/X86/X86Options.inc": ["-gen-opt-parser-defs"]},
+ tblgen = ":llvm-tblgen",
+ td_file = "lib/Target/X86/X86Options.td",
+ deps = [":OptParserTdFiles"],
+)
+
gentbl_cc_library(
name = "webassembly_isel_target_gen",
strip_include_prefix = "lib/Target/WebAssembly",
More information about the llvm-commits
mailing list