https://github.com/zhouguangyuan0718 updated 
https://github.com/llvm/llvm-project/pull/184606

>From 36bdd121d867a51b801fa04d0b1819e21800dbb9 Mon Sep 17 00:00:00 2001
From: ZhouGuangyuan <[email protected]>
Date: Wed, 4 Mar 2026 21:09:07 +0800
Subject: [PATCH] [X86] Reduce -ffixed-r compile-time overhead

PR #180242 added reserve-r support across the driver and backend, but it also 
introduced avoidable compile-time work in hot paths.

In Clang, delay +egpr detection until -ffixed-r16 through -ffixed-r31 are 
actually queried instead of computing it for every x86_64 invocation.

In LLVM, store X86Subtarget::ReservedRReg in a fixed-size std::bitset and 
update X86RegisterInfo::getReservedRegs() to iterate only over the reserve-r 
register ranges instead of scanning every target register.

These changes keep reserve-r behavior unchanged while trimming the extra 
compile-time overhead introduced by the PR.

Signed-off-by: ZhouGuangyuan <[email protected]>
---
 clang/lib/Driver/ToolChains/Arch/X86.cpp | 45 ++++++++++++++----------
 llvm/lib/Target/X86/X86RegisterInfo.cpp  | 14 ++++----
 llvm/lib/Target/X86/X86Subtarget.cpp     |  3 +-
 llvm/lib/Target/X86/X86Subtarget.h       |  5 +--
 4 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp 
b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index 6a71512193800..c113da6733370 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -151,16 +151,6 @@ void x86::getX86TargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
   }
 
   const llvm::Triple::ArchType ArchType = Triple.getArch();
-  bool HasEGPR = false;
-
-  // -ffixed-r16 through -ffixed-r31 are only valid when the selected x86_64
-  // CPU enables APX EGPR by default; later -target-feature arguments still get
-  // their own validation when translated to backend features.
-  if (ArchType == llvm::Triple::x86_64) {
-    SmallVector<StringRef, 16> CPUFeatures;
-    llvm::X86::getFeaturesForCPU(getX86TargetCPU(D, Args, Triple), 
CPUFeatures);
-    HasEGPR = llvm::is_contained(CPUFeatures, "+egpr");
-  }
 
   // Add features to be compatible with gcc for Android.
   if (Triple.isAndroid()) {
@@ -241,6 +231,8 @@ void x86::getX86TargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
         << D.getOpts().getOptionName(LVIOpt);
   }
 
+  enum class EGPRFeature { Unknown, Disabled, Enabled };
+  EGPRFeature EGPROpt = EGPRFeature::Unknown;
   // Now add any that the user explicitly requested on the command line,
   // which may override the defaults.
   for (const Arg *A : Args.filtered(options::OPT_m_x86_Features_Group,
@@ -271,13 +263,13 @@ void x86::getX86TargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
     if (A->getOption().matches(options::OPT_mapxf) ||
         A->getOption().matches(options::OPT_mno_apxf)) {
       if (IsNegative) {
-        HasEGPR = false;
+        EGPROpt = EGPRFeature::Disabled;
         Features.insert(Features.end(),
                         {"-egpr", "-ndd", "-ccmp", "-nf", "-zu"});
         if (!Triple.isOSWindows())
           Features.insert(Features.end(), {"-push2pop2", "-ppx"});
       } else {
-        HasEGPR = true;
+        EGPROpt = EGPRFeature::Enabled;
         Features.insert(Features.end(),
                         {"+egpr", "+ndd", "+ccmp", "+nf", "+zu"});
         if (!Triple.isOSWindows())
@@ -303,8 +295,9 @@ void x86::getX86TargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
           D.Diag(clang::diag::err_drv_unsupported_option_argument)
               << A->getSpelling() << Value;
 
-        if (Value == "egpr")
-          HasEGPR = !IsNegative;
+        if (Value == "egpr") {
+          EGPROpt = IsNegative ? EGPRFeature::Disabled : EGPRFeature::Enabled;
+        }
 
         Features.push_back(
             Args.MakeArgString((IsNegative ? "-" : "+") + Value));
@@ -312,8 +305,9 @@ void x86::getX86TargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
       continue;
     }
 
-    if (Name == "egpr")
-      HasEGPR = !IsNegative;
+    if (Name == "egpr") {
+      EGPROpt = IsNegative ? EGPRFeature::Disabled : EGPRFeature::Enabled;
+    }
     Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
   }
 
@@ -366,9 +360,25 @@ void x86::getX86TargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
   RESERVE_REG(r13)
   RESERVE_REG(r14)
   RESERVE_REG(r15)
+#undef RESERVE_REG
+
+  bool NeedDetectEGPR = Args.hasArg(
+      options::OPT_ffixed_r16, options::OPT_ffixed_r17, 
options::OPT_ffixed_r18,
+      options::OPT_ffixed_r19, options::OPT_ffixed_r20, 
options::OPT_ffixed_r21,
+      options::OPT_ffixed_r22, options::OPT_ffixed_r23, 
options::OPT_ffixed_r24,
+      options::OPT_ffixed_r25, options::OPT_ffixed_r26, 
options::OPT_ffixed_r27,
+      options::OPT_ffixed_r28, options::OPT_ffixed_r29, 
options::OPT_ffixed_r30,
+      options::OPT_ffixed_r31);
+  if (NeedDetectEGPR && EGPROpt == EGPRFeature::Unknown &&
+      ArchType == llvm::Triple::x86_64) {
+    SmallVector<StringRef, 16> CPUFeatures;
+    llvm::X86::getFeaturesForCPU(getX86TargetCPU(D, Args, Triple), 
CPUFeatures);
+    EGPROpt = llvm::is_contained(CPUFeatures, "+egpr") ? EGPRFeature::Enabled
+                                                       : EGPRFeature::Disabled;
+  }
 #define RESERVE_EGPR(REG)                                                      
\
   if (Args.hasArg(options::OPT_ffixed_##REG)) {                                
\
-    if (!HasEGPR)                                                              
\
+    if (EGPROpt != EGPRFeature::Enabled)                                       
\
       D.Diag(diag::err_drv_unsupported_opt_for_target)                         
\
           << "-ffixed-" #REG << Triple.getTriple();                            
\
     else                                                                       
\
@@ -391,5 +401,4 @@ void x86::getX86TargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
   RESERVE_EGPR(r30)
   RESERVE_EGPR(r31)
 #undef RESERVE_EGPR
-#undef RESERVE_REG
 }
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp 
b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index 42d1bedb350f6..86b9cdc366a85 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -516,14 +516,16 @@ BitVector X86RegisterInfo::getReservedRegs(const 
MachineFunction &MF) const {
   Reserved.set(X86::SSP);
 
   auto &ST = MF.getSubtarget<X86Subtarget>();
-  if (ST.is64Bit()) {
-    for (size_t Reg = 0; Reg < getNumRegs(); Reg++) {
-      // Set r# as reserved register if user required
-      if (ST.isRegisterReservedByUser(Reg)) {
+  if (ST.is64Bit() && ST.hasUserReservedRegisters()) {
+    // Set r# as reserved register if user required
+    for (unsigned Reg = X86::R8; Reg <= X86::R15; ++Reg)
+      if (ST.isRegisterReservedByUser(Reg))
+        for (const MCPhysReg &SubReg : subregs_inclusive(Reg))
+          Reserved.set(SubReg);
+    for (unsigned Reg = X86::R16; Reg <= X86::R31; ++Reg)
+      if (ST.isRegisterReservedByUser(Reg))
         for (const MCPhysReg &SubReg : subregs_inclusive(Reg))
           Reserved.set(SubReg);
-      }
-    }
   }
 
   // Set the instruction pointer register and its aliases as reserved.
diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp 
b/llvm/lib/Target/X86/X86Subtarget.cpp
index f73ca37a45c07..4e2e98410f325 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -317,8 +317,7 @@ X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, 
StringRef TuneCPU,
                            unsigned PreferVectorWidthOverride,
                            unsigned RequiredVectorWidth)
     : X86GenSubtargetInfo(TT, CPU, TuneCPU, FS),
-      PICStyle(PICStyles::Style::None), TM(TM),
-      ReservedRReg(X86::NUM_TARGET_REGS), TargetTriple(TT),
+      PICStyle(PICStyles::Style::None), TM(TM), TargetTriple(TT),
       StackAlignOverride(StackAlignOverride),
       PreferVectorWidthOverride(PreferVectorWidthOverride),
       RequiredVectorWidth(RequiredVectorWidth),
diff --git a/llvm/lib/Target/X86/X86Subtarget.h 
b/llvm/lib/Target/X86/X86Subtarget.h
index dd9a5de3030ed..2e3c23eeca35b 100644
--- a/llvm/lib/Target/X86/X86Subtarget.h
+++ b/llvm/lib/Target/X86/X86Subtarget.h
@@ -17,10 +17,10 @@
 #include "X86ISelLowering.h"
 #include "X86InstrInfo.h"
 #include "X86SelectionDAGInfo.h"
-#include "llvm/ADT/BitVector.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/CallingConv.h"
 #include "llvm/TargetParser/Triple.h"
+#include <bitset>
 #include <climits>
 #include <memory>
 
@@ -67,7 +67,7 @@ class X86Subtarget final : public X86GenSubtargetInfo {
   bool ATTRIBUTE = DEFAULT;
 #include "X86GenSubtargetInfo.inc"
   /// ReservedRReg R#i is not available as a general purpose register.
-  BitVector ReservedRReg;
+  std::bitset<X86::NUM_TARGET_REGS> ReservedRReg;
 
   /// The minimum alignment known to hold of the stack frame on
   /// entry to the function and which must be maintained by every function.
@@ -162,6 +162,7 @@ class X86Subtarget final : public X86GenSubtargetInfo {
   bool isRegisterReservedByUser(Register i) const override {
     return ReservedRReg[i.id()];
   }
+  bool hasUserReservedRegisters() const { return ReservedRReg.any(); }
 
 private:
   /// Initialize the full set of dependencies so we can use an initializer

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to