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

>From 6cd2ccf54fdf7ef91bd8da37e3c7ba35d17739b7 Mon Sep 17 00:00:00 2001
From: ZhouGuangyuan <[email protected]>
Date: Sat, 7 Feb 2026 00:09:33 +0800
Subject: [PATCH 1/2] [X86] support reserve r8~r15 on X86_64

Add new options -ffixed_r{8~15} for clang X86 target, like option "-ffixed_x" 
for RISCV/AArch64 target.
Also, add target-feature +reserve-r{8~15} for the X86 backend.

The registers which are specified reserved will not be used in 
RegAlloc/CalleeSave. Then the reserved registers can be maintained by user. It 
will be useful for the runtime/interpreter implementation.

Other registers are used in specific instructions or mechanism, so they can't 
be reserved.

Signed-off-by: ZhouGuangyuan <[email protected]>
---
 clang/include/clang/Options/Options.td      |  8 +-
 clang/lib/Basic/Targets/X86.h               |  7 ++
 clang/lib/Driver/ToolChains/Arch/X86.cpp    | 14 ++++
 clang/test/Driver/x86_64-fixed-r-register.c | 65 ++++++++++++++
 llvm/lib/Target/X86/X86.td                  |  4 +
 llvm/lib/Target/X86/X86FrameLowering.cpp    |  8 ++
 llvm/lib/Target/X86/X86ISelLowering.cpp     | 12 +++
 llvm/lib/Target/X86/X86RegisterInfo.cpp     | 11 +++
 llvm/lib/Target/X86/X86Subtarget.cpp        |  3 +-
 llvm/lib/Target/X86/X86Subtarget.h          |  8 ++
 llvm/test/CodeGen/X86/reserveRreg.ll        | 93 +++++++++++++++++++++
 11 files changed, 230 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/Driver/x86_64-fixed-r-register.c
 create mode 100644 llvm/test/CodeGen/X86/reserveRreg.ll

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 1021d95e4005b..d71c599e3ac9a 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5526,8 +5526,8 @@ def mrestrict_it: Flag<["-"], "mrestrict-it">, 
Group<m_arm_Features_Group>,
 def mno_restrict_it: Flag<["-"], "mno-restrict-it">, 
Group<m_arm_Features_Group>,
   HelpText<"Allow generation of complex IT blocks.">;
 def marm : Flag<["-"], "marm">, Alias<mno_thumb>;
-def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group<m_arm_Features_Group>,
-  HelpText<"Reserve the r9 register (ARM only)">;
+def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group<m_Group>,
+  HelpText<"Reserve the r9 register (ARM/x86_64 only)">;
 def mno_movt : Flag<["-"], "mno-movt">, Group<m_arm_Features_Group>,
   HelpText<"Disallow use of movt/movw pairs (ARM only)">;
 def mcrc : Flag<["-"], "mcrc">, Group<m_Group>,
@@ -7168,6 +7168,10 @@ def mapxf : Flag<["-"], "mapxf">, 
Group<m_x86_Features_Group>;
 def mno_apxf : Flag<["-"], "mno-apxf">, Group<m_x86_Features_Group>;
 def mapx_inline_asm_use_gpr32 : Flag<["-"], "mapx-inline-asm-use-gpr32">, 
Group<m_Group>,
                                 HelpText<"Enable use of GPR32 in inline 
assembly for APX">;
+foreach i = {8, 10-15} in
+    def ffixed_r#i : Flag<["-"], "ffixed-r"#i>, Group<m_Group>,
+    HelpText<"Reserve the r"#i#" register (x86_64 only)">;
+
 } // let Flags = [TargetSpecific]
 
 // VE feature flags
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index 922e32906cd04..65617e4fcea21 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -807,6 +807,13 @@ class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public 
X86TargetInfo {
       return true;
     }
 
+    StringRef Reg64 = RegName;
+    if (Reg64.back() == 'd' || Reg64.back() == 'w' || Reg64.back() == 'b') {
+      Reg64 = Reg64.substr(0, Reg64.size() - 1);
+    }
+    if (getTargetOpts().FeatureMap.lookup(("reserve-" + Reg64).str()))
+      return true;
+
     // Check if the register is a 32-bit register the backend can handle.
     return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
                                                          HasSizeMismatch);
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp 
b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index 61d512f9e093f..c4ccddffca9fa 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -332,4 +332,18 @@ void x86::getX86TargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
     if (A->getOption().matches(options::OPT_m3dnow))
       D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args);
   }
+
+  // Handle features corresponding to "-ffixed-X" options
+#define RESERVE_REG(REG)                                                       
\
+  if (Args.hasArg(options::OPT_ffixed_##REG))                                  
\
+    Features.push_back("+reserve-" #REG);
+  RESERVE_REG(r8)
+  RESERVE_REG(r9)
+  RESERVE_REG(r10)
+  RESERVE_REG(r11)
+  RESERVE_REG(r12)
+  RESERVE_REG(r13)
+  RESERVE_REG(r14)
+  RESERVE_REG(r15)
+#undef RESERVE_REG
 }
diff --git a/clang/test/Driver/x86_64-fixed-r-register.c 
b/clang/test/Driver/x86_64-fixed-r-register.c
new file mode 100644
index 0000000000000..714db3fdfdc91
--- /dev/null
+++ b/clang/test/Driver/x86_64-fixed-r-register.c
@@ -0,0 +1,65 @@
+// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r8 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-R8 < %t %s
+// CHECK-FIXED-R8: "-target-feature" "+reserve-r8"
+
+// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r9 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-R9 < %t %s
+// CHECK-FIXED-R9: "-target-feature" "+reserve-r9"
+
+// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r10 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-R10 < %t %s
+// CHECK-FIXED-R10: "-target-feature" "+reserve-r10"
+
+// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r11 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-R11 < %t %s
+// CHECK-FIXED-R11: "-target-feature" "+reserve-r11"
+
+// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r12 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-R12 < %t %s
+// CHECK-FIXED-R12: "-target-feature" "+reserve-r12"
+
+// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r13 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-R13 < %t %s
+// CHECK-FIXED-R13: "-target-feature" "+reserve-r13"
+
+// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r14 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-R14 < %t %s
+// CHECK-FIXED-R14: "-target-feature" "+reserve-r14"
+
+// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r15 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-R15 < %t %s
+// CHECK-FIXED-R15: "-target-feature" "+reserve-r15"
+
+// Test multiple of reserve-r# options together.
+// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: -ffixed-r8 \
+// RUN: -ffixed-r9 \
+// RUN: -ffixed-r15 \
+// RUN: -### %s 2> %t
+// RUN: FileCheck \
+// RUN: --check-prefix=CHECK-FIXED-R8 \
+// RUN: --check-prefix=CHECK-FIXED-R9 \
+// RUN: --check-prefix=CHECK-FIXED-R15 \
+// RUN: < %t %s
+
+// Test all reserve-r# options together.
+// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: -ffixed-r8 \
+// RUN: -ffixed-r9 \
+// RUN: -ffixed-r10 \
+// RUN: -ffixed-r11 \
+// RUN: -ffixed-r12 \
+// RUN: -ffixed-r13 \
+// RUN: -ffixed-r14 \
+// RUN: -ffixed-r15 \
+// RUN: -### %s 2> %t
+// RUN: FileCheck \
+// RUN: --check-prefix=CHECK-FIXED-R8 \
+// RUN: --check-prefix=CHECK-FIXED-R9 \
+// RUN: --check-prefix=CHECK-FIXED-R10 \
+// RUN: --check-prefix=CHECK-FIXED-R11 \
+// RUN: --check-prefix=CHECK-FIXED-R12 \
+// RUN: --check-prefix=CHECK-FIXED-R13 \
+// RUN: --check-prefix=CHECK-FIXED-R14 \
+// RUN: --check-prefix=CHECK-FIXED-R15 \
+// RUN: < %t %s
diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td
index fa41d7a7a7c5e..e4eafc3487f37 100644
--- a/llvm/lib/Target/X86/X86.td
+++ b/llvm/lib/Target/X86/X86.td
@@ -32,6 +32,10 @@ def IsX32 : SubtargetFeature<"x32", "IsX32", "true",
 // X86 Subtarget ISA features
 
//===----------------------------------------------------------------------===//
 
+foreach i = {8-15} in
+    def FeatureReserveR#i : SubtargetFeature<"reserve-r"#i, 
"ReservedRReg[X86::R"#i#"]", "true",
+                                             "Reserve R"#i#", making it 
unavailable as a GPR">;
+
 def FeatureX87     : SubtargetFeature<"x87","HasX87", "true",
                                       "Enable X87 float instructions">;
 
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp 
b/llvm/lib/Target/X86/X86FrameLowering.cpp
index 8bca6344d6521..8791470b0b5e1 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -3211,6 +3211,14 @@ void 
X86FrameLowering::determineCalleeSaves(MachineFunction &MF,
       BasePtr = getX86SubSuperRegister(BasePtr, 64);
     SavedRegs.set(BasePtr);
   }
+  if (STI.is64Bit()) {
+    for (int Reg = SavedRegs.find_first(); Reg != -1;
+         Reg = SavedRegs.find_next(Reg)) {
+      if (STI.isRegisterReservedByUser(Reg)) {
+        SavedRegs.reset(Reg);
+      }
+    }
+  }
 }
 
 static bool HasNestArgument(const MachineFunction *MF) {
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp 
b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 2188f6466682b..42c4ac3b943c3 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -28732,6 +28732,9 @@ SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, 
SelectionDAG &DAG) const {
   return FrameAddr;
 }
 
+#define GET_REGISTER_MATCHER
+#include "X86GenAsmMatcher.inc"
+
 // FIXME? Maybe this could be a TableGen attribute on some registers and
 // this table could be generated automatically from RegInfo.
 Register X86TargetLowering::getRegisterByName(const char* RegName, LLT VT,
@@ -28761,6 +28764,15 @@ Register X86TargetLowering::getRegisterByName(const 
char* RegName, LLT VT,
 #endif
   }
 
+  if (Reg)
+    return Reg;
+
+  if (Subtarget.is64Bit()) {
+    Reg = MatchRegisterName(RegName);
+    if (!Subtarget.isRegisterReservedByUser(Reg))
+      Reg = Register();
+  }
+
   return Reg;
 }
 
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp 
b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index 72f38133e21ff..42d1bedb350f6 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -515,6 +515,17 @@ BitVector X86RegisterInfo::getReservedRegs(const 
MachineFunction &MF) const {
   // Set the Shadow Stack Pointer as reserved.
   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)) {
+        for (const MCPhysReg &SubReg : subregs_inclusive(Reg))
+          Reserved.set(SubReg);
+      }
+    }
+  }
+
   // Set the instruction pointer register and its aliases as reserved.
   for (const MCPhysReg &SubReg : subregs_inclusive(X86::RIP))
     Reserved.set(SubReg);
diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp 
b/llvm/lib/Target/X86/X86Subtarget.cpp
index 4e2e98410f325..f73ca37a45c07 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -317,7 +317,8 @@ X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, 
StringRef TuneCPU,
                            unsigned PreferVectorWidthOverride,
                            unsigned RequiredVectorWidth)
     : X86GenSubtargetInfo(TT, CPU, TuneCPU, FS),
-      PICStyle(PICStyles::Style::None), TM(TM), TargetTriple(TT),
+      PICStyle(PICStyles::Style::None), TM(TM),
+      ReservedRReg(X86::NUM_TARGET_REGS), 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 3b920bc4ef7c1..dd9a5de3030ed 100644
--- a/llvm/lib/Target/X86/X86Subtarget.h
+++ b/llvm/lib/Target/X86/X86Subtarget.h
@@ -17,6 +17,7 @@
 #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"
@@ -65,6 +66,9 @@ class X86Subtarget final : public X86GenSubtargetInfo {
 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    
\
   bool ATTRIBUTE = DEFAULT;
 #include "X86GenSubtargetInfo.inc"
+  /// ReservedRReg R#i is not available as a general purpose register.
+  BitVector ReservedRReg;
+
   /// The minimum alignment known to hold of the stack frame on
   /// entry to the function and which must be maintained by every function.
   Align stackAlignment = Align(4);
@@ -155,6 +159,10 @@ class X86Subtarget final : public X86GenSubtargetInfo {
   const LegalizerInfo *getLegalizerInfo() const override;
   const RegisterBankInfo *getRegBankInfo() const override;
 
+  bool isRegisterReservedByUser(Register i) const override {
+    return ReservedRReg[i.id()];
+  }
+
 private:
   /// Initialize the full set of dependencies so we can use an initializer
   /// list for X86Subtarget.
diff --git a/llvm/test/CodeGen/X86/reserveRreg.ll 
b/llvm/test/CodeGen/X86/reserveRreg.ll
new file mode 100644
index 0000000000000..cfd80022e3cc4
--- /dev/null
+++ b/llvm/test/CodeGen/X86/reserveRreg.ll
@@ -0,0 +1,93 @@
+;; Check if manually reserved registers are always excluded from being saved by
+;; the function prolog/epilog, even for callee-saved ones, as per GCC behavior.
+
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+
+define preserve_mostcc void @t8() "target-features"="+reserve-r8" {
+; CHECK-LABEL: t8:
+; CHECK: # %bb.0:
+; CHECK-NEXT:        movl      $256, %r8d
+; CHECK-NEXT:        #APP
+; CHECK-NEXT:        #NO_APP
+; CHECK-NEXT:        ret
+  call i64 asm sideeffect "", "={r8},{r8}"(i64 256)
+  ret void
+}
+
+define preserve_mostcc void @t9() "target-features"="+reserve-r9" {
+; CHECK-LABEL: t9:
+; CHECK: # %bb.0:
+; CHECK-NEXT:        movl      $256, %r9d
+; CHECK-NEXT:        #APP
+; CHECK-NEXT:        #NO_APP
+; CHECK-NEXT:        ret
+  call i64 asm sideeffect "", "={r9},{r9}"(i64 256)
+  ret void
+}
+
+define preserve_mostcc void @t10() "target-features"="+reserve-r10" {
+; CHECK-LABEL: t10:
+; CHECK: # %bb.0:
+; CHECK-NEXT:        movl      $256, %r10d
+; CHECK-NEXT:        #APP
+; CHECK-NEXT:        #NO_APP
+; CHECK-NEXT:        ret
+  call i64 asm sideeffect "", "={r10},{r10}"(i64 256)
+  ret void
+}
+
+define preserve_mostcc void @t11() "target-features"="+reserve-r11" {
+; CHECK-LABEL: t11:
+; CHECK: # %bb.0:
+; CHECK-NEXT:        movl      $256, %r11d
+; CHECK-NEXT:        #APP
+; CHECK-NEXT:        #NO_APP
+; CHECK-NEXT:        ret
+  call i64 asm sideeffect "", "={r11},{r11}"(i64 256)
+  ret void
+}
+
+define preserve_mostcc void @t12() "target-features"="+reserve-r12" {
+; CHECK-LABEL: t12:
+; CHECK: # %bb.0:
+; CHECK-NEXT:        movl      $256, %r12d
+; CHECK-NEXT:        #APP
+; CHECK-NEXT:        #NO_APP
+; CHECK-NEXT:        ret
+  call i64 asm sideeffect "", "={r12},{r12}"(i64 256)
+  ret void
+}
+
+define preserve_mostcc void @t13() "target-features"="+reserve-r13" {
+; CHECK-LABEL: t13:
+; CHECK: # %bb.0:
+; CHECK-NEXT:        movl      $256, %r13d
+; CHECK-NEXT:        #APP
+; CHECK-NEXT:        #NO_APP
+; CHECK-NEXT:        ret
+  call i64 asm sideeffect "", "={r13},{r13}"(i64 256)
+  ret void
+}
+
+define preserve_mostcc void @t14() "target-features"="+reserve-r14" {
+; CHECK-LABEL: t14:
+; CHECK: # %bb.0:
+; CHECK-NEXT:        movl   $256, %r14d
+; CHECK-NEXT:        #APP
+; CHECK-NEXT:        #NO_APP
+; CHECK-NEXT:        ret
+  call i64 asm sideeffect "", "={r14},{r14}"(i64 256)
+  ret void
+}
+
+define preserve_mostcc void @t15() "target-features"="+reserve-r15" {
+; CHECK-LABEL: t15:
+; CHECK: # %bb.0:
+; CHECK-NEXT:        movl   $256, %r15d
+; CHECK-NEXT:        #APP
+; CHECK-NEXT:        #NO_APP
+; CHECK-NEXT:        ret
+  call i64 asm sideeffect "", "={r15},{r15}"(i64 256)
+  ret void
+}
+

>From df6191d8797c8d296cb6191976bf4b71fc0e99ff Mon Sep 17 00:00:00 2001
From: ZhouGuangyuan <[email protected]>
Date: Sun, 1 Mar 2026 17:38:59 +0800
Subject: [PATCH 2/2] [X86] extend -ffixed-r16-r31 support under APX

Extend the x86_64 fixed-register support added for r8-r15 to cover\nAPX EGPR 
registers r16-r31 as well.\n\nOnly accept -ffixed-r16 through -ffixed-r31 when 
APX EGPR is\nenabled for the target, and diagnose them otherwise. When EGPR 
is\navailable, forward the options as reserve-r16 through reserve-r31\ntarget 
features so the backend marks those registers unavailable 
for\nallocation.\n\nAlso add driver tests for the APX-enabled and non-APX 
cases, plus\nCodeGen coverage for reserving r16 and r31.

Signed-off-by: ZhouGuangyuan <[email protected]>
---
 clang/include/clang/Options/Options.td      |  5 ++-
 clang/lib/Driver/ToolChains/Arch/X86.cpp    | 43 ++++++++++++++++++
 clang/test/Driver/x86_64-fixed-r-register.c | 49 +++++++++++++++++++++
 llvm/lib/Target/X86/X86.td                  |  3 ++
 llvm/test/CodeGen/X86/reserveRreg.ll        | 21 +++++++++
 5 files changed, 120 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index d71c599e3ac9a..34ddc29f6f738 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -6844,7 +6844,7 @@ def mno_hexagon_hvx_ieee_fp : Flag<["-"], 
"mno-hvx-ieee-fp">,
   Group<m_hexagon_Features_Group>,
   HelpText<"Disable Hexagon HVX IEEE floating-point">;
 def ffixed_r19: Flag<["-"], "ffixed-r19">, Group<f_Group>,
-  HelpText<"Reserve register r19 (Hexagon only)">;
+  HelpText<"Reserve register r19 (Hexagon/x86_64 only; x86_64 requires APX 
EGPR)">;
 } // let Flags = [TargetSpecific]
 def mmemops : Flag<["-"], "mmemops">, Group<m_hexagon_Features_Group>,
   Visibility<[ClangOption, CC1Option]>,
@@ -7171,6 +7171,9 @@ def mapx_inline_asm_use_gpr32 : Flag<["-"], 
"mapx-inline-asm-use-gpr32">, Group<
 foreach i = {8, 10-15} in
     def ffixed_r#i : Flag<["-"], "ffixed-r"#i>, Group<m_Group>,
     HelpText<"Reserve the r"#i#" register (x86_64 only)">;
+foreach i = {16-18,20-31} in
+    def ffixed_r#i : Flag<["-"], "ffixed-r"#i>, Group<m_Group>,
+    HelpText<"Reserve the r"#i#" register (x86_64 with APX EGPR only)">;
 
 } // let Flags = [TargetSpecific]
 
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp 
b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index c4ccddffca9fa..c2e546ec8cbfc 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -9,10 +9,12 @@
 #include "X86.h"
 #include "clang/Driver/Driver.h"
 #include "clang/Options/Options.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/X86TargetParser.h"
 
 using namespace clang::driver;
 using namespace clang::driver::tools;
@@ -149,6 +151,14 @@ void x86::getX86TargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
   }
 
   const llvm::Triple::ArchType ArchType = Triple.getArch();
+  bool HasEGPR = false;
+
+  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()) {
     if (ArchType == llvm::Triple::x86_64) {
@@ -258,11 +268,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;
         Features.insert(Features.end(),
                         {"-egpr", "-ndd", "-ccmp", "-nf", "-zu"});
         if (!Triple.isOSWindows())
           Features.insert(Features.end(), {"-push2pop2", "-ppx"});
       } else {
+        HasEGPR = true;
         Features.insert(Features.end(),
                         {"+egpr", "+ndd", "+ccmp", "+nf", "+zu"});
         if (!Triple.isOSWindows())
@@ -288,11 +300,17 @@ 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;
+
         Features.push_back(
             Args.MakeArgString((IsNegative ? "-" : "+") + Value));
       }
       continue;
     }
+
+    if (Name == "egpr")
+      HasEGPR = !IsNegative;
     Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
   }
 
@@ -345,5 +363,30 @@ void x86::getX86TargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
   RESERVE_REG(r13)
   RESERVE_REG(r14)
   RESERVE_REG(r15)
+#define RESERVE_EGPR(REG)                                                      
\
+  if (Args.hasArg(options::OPT_ffixed_##REG)) {                                
\
+    if (!HasEGPR)                                                              
\
+      D.Diag(diag::err_drv_unsupported_opt_for_target)                         
\
+          << "-ffixed-" #REG << Triple.getTriple();                            
\
+    else                                                                       
\
+      Features.push_back("+reserve-" #REG);                                    
\
+  }
+  RESERVE_EGPR(r16)
+  RESERVE_EGPR(r17)
+  RESERVE_EGPR(r18)
+  RESERVE_EGPR(r19)
+  RESERVE_EGPR(r20)
+  RESERVE_EGPR(r21)
+  RESERVE_EGPR(r22)
+  RESERVE_EGPR(r23)
+  RESERVE_EGPR(r24)
+  RESERVE_EGPR(r25)
+  RESERVE_EGPR(r26)
+  RESERVE_EGPR(r27)
+  RESERVE_EGPR(r28)
+  RESERVE_EGPR(r29)
+  RESERVE_EGPR(r30)
+  RESERVE_EGPR(r31)
+#undef RESERVE_EGPR
 #undef RESERVE_REG
 }
diff --git a/clang/test/Driver/x86_64-fixed-r-register.c 
b/clang/test/Driver/x86_64-fixed-r-register.c
index 714db3fdfdc91..90f50a94e9606 100644
--- a/clang/test/Driver/x86_64-fixed-r-register.c
+++ b/clang/test/Driver/x86_64-fixed-r-register.c
@@ -30,6 +30,17 @@
 // RUN: FileCheck --check-prefix=CHECK-FIXED-R15 < %t %s
 // CHECK-FIXED-R15: "-target-feature" "+reserve-r15"
 
+// RUN: %clang --target=x86_64-unknown-linux-gnu -mapx-features=egpr 
-ffixed-r16 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-R16 < %t %s
+// CHECK-FIXED-R16: "-target-feature" "+reserve-r16"
+
+// RUN: %clang --target=x86_64-unknown-linux-gnu -mapx-features=egpr 
-ffixed-r31 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-FIXED-R31 < %t %s
+// CHECK-FIXED-R31: "-target-feature" "+reserve-r31"
+
+// RUN: not %clang --target=x86_64-unknown-linux-gnu -ffixed-r16 -### %s 2>&1 
| FileCheck --check-prefix=CHECK-NO-APX %s
+// CHECK-NO-APX: error: unsupported option '-ffixed-r16' for target 
'x86_64-unknown-linux-gnu'
+
 // Test multiple of reserve-r# options together.
 // RUN: %clang --target=x86_64-unknown-linux-gnu \
 // RUN: -ffixed-r8 \
@@ -63,3 +74,41 @@
 // RUN: --check-prefix=CHECK-FIXED-R14 \
 // RUN: --check-prefix=CHECK-FIXED-R15 \
 // RUN: < %t %s
+
+// Test all reserve-r# options together with APX EGPR.
+// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: -mapx-features=egpr \
+// RUN: -ffixed-r16 \
+// RUN: -ffixed-r17 \
+// RUN: -ffixed-r18 \
+// RUN: -ffixed-r19 \
+// RUN: -ffixed-r20 \
+// RUN: -ffixed-r21 \
+// RUN: -ffixed-r22 \
+// RUN: -ffixed-r23 \
+// RUN: -ffixed-r24 \
+// RUN: -ffixed-r25 \
+// RUN: -ffixed-r26 \
+// RUN: -ffixed-r27 \
+// RUN: -ffixed-r28 \
+// RUN: -ffixed-r29 \
+// RUN: -ffixed-r30 \
+// RUN: -ffixed-r31 \
+// RUN: -### %s 2> %t
+// RUN: FileCheck \
+// RUN: --check-prefix=CHECK-ALL-EGPR \
+// RUN: < %t %s
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r17"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r18"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r19"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r20"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r21"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r22"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r23"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r24"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r25"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r26"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r27"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r28"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r29"
+// CHECK-ALL-EGPR: "-target-feature" "+reserve-r30"
diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td
index e4eafc3487f37..eca763735c315 100644
--- a/llvm/lib/Target/X86/X86.td
+++ b/llvm/lib/Target/X86/X86.td
@@ -35,6 +35,9 @@ def IsX32 : SubtargetFeature<"x32", "IsX32", "true",
 foreach i = {8-15} in
     def FeatureReserveR#i : SubtargetFeature<"reserve-r"#i, 
"ReservedRReg[X86::R"#i#"]", "true",
                                              "Reserve R"#i#", making it 
unavailable as a GPR">;
+foreach i = {16-31} in
+    def FeatureReserveR#i : SubtargetFeature<"reserve-r"#i, 
"ReservedRReg[X86::R"#i#"]", "true",
+                                             "Reserve R"#i#", making it 
unavailable as a GPR">;
 
 def FeatureX87     : SubtargetFeature<"x87","HasX87", "true",
                                       "Enable X87 float instructions">;
diff --git a/llvm/test/CodeGen/X86/reserveRreg.ll 
b/llvm/test/CodeGen/X86/reserveRreg.ll
index cfd80022e3cc4..b6b10ad5169a4 100644
--- a/llvm/test/CodeGen/X86/reserveRreg.ll
+++ b/llvm/test/CodeGen/X86/reserveRreg.ll
@@ -91,3 +91,24 @@ define preserve_mostcc void @t15() 
"target-features"="+reserve-r15" {
   ret void
 }
 
+define preserve_mostcc void @t16() "target-features"="+egpr,+reserve-r16" {
+; CHECK-LABEL: t16:
+; CHECK: # %bb.0:
+; CHECK-NEXT:        movl   $256, %r16d
+; CHECK-NEXT:        #APP
+; CHECK-NEXT:        #NO_APP
+; CHECK-NEXT:        ret
+  call i64 asm sideeffect "", "={r16},{r16}"(i64 256)
+  ret void
+}
+
+define preserve_mostcc void @t31() "target-features"="+egpr,+reserve-r31" {
+; CHECK-LABEL: t31:
+; CHECK: # %bb.0:
+; CHECK-NEXT:        movl   $256, %r31d
+; CHECK-NEXT:        #APP
+; CHECK-NEXT:        #NO_APP
+; CHECK-NEXT:        ret
+  call i64 asm sideeffect "", "={r31},{r31}"(i64 256)
+  ret void
+}

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

Reply via email to