https://github.com/phoebewang updated 
https://github.com/llvm/llvm-project/pull/173224

>From 5d765591ccb28b4323a4616e9a63a6795034d603 Mon Sep 17 00:00:00 2001
From: Phoebe Wang <[email protected]>
Date: Mon, 22 Dec 2025 15:36:20 +0800
Subject: [PATCH 1/3] [WIP][APX] Allow EGPR registers used as non-volatile
 registers

---
 clang/include/clang/Options/Options.td     |  2 +
 clang/lib/Driver/ToolChains/Arch/X86.cpp   |  3 +
 clang/lib/Driver/ToolChains/CommonArgs.cpp |  6 ++
 llvm/lib/Target/X86/X86CallingConv.td      | 17 ++++++
 llvm/lib/Target/X86/X86RegisterInfo.cpp    | 65 ++++++++++++++++++++--
 5 files changed, 89 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 8cd31a3be109a..c98bb969b28d9 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -9330,6 +9330,8 @@ def : CLFlag<"Qscatter-">, Alias<mno_scatter>,
 
 // Non-aliases:
 
+def _SLASH_apx_features_egprnv : CLCompileJoined<"apx-features=egpr-nv:">,
+  HelpText<"Set number of non-volatile registers of APX features">;
 def _SLASH_arch : CLCompileJoined<"arch:">,
   HelpText<"Set architecture for code generation">;
 def _SLASH_vlen : CLFlag<"vlen">,
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp 
b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index d6e6657c521f0..e90edd0a203b1 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -277,6 +277,9 @@ void x86::getX86TargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
     Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
   }
 
+  if (Args.hasArgNoClaim(options::OPT__SLASH_apx_features_egprnv))
+    Features.push_back("+egpr");
+
   // Enable/disable straight line speculation hardening.
   if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
     StringRef Scope = A->getValue();
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 882283a99d4f1..ce4a199668b60 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -922,6 +922,12 @@ void tools::getTargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
     CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature");
     CmdArgs.push_back(Feature.data());
   }
+
+  if (Arg *A = Args.getLastArg(options::OPT__SLASH_apx_features_egprnv)) {
+    StringRef Value = A->getValue();
+    CmdArgs.push_back("-mllvm");
+    CmdArgs.push_back(Args.MakeArgString("-apx-egpr-csr=" + Value));
+  }
 }
 
 llvm::StringRef tools::getLTOParallelism(const ArgList &Args, const Driver &D) 
{
diff --git a/llvm/lib/Target/X86/X86CallingConv.td 
b/llvm/lib/Target/X86/X86CallingConv.td
index f020e0b55141c..e62e5292f6374 100644
--- a/llvm/lib/Target/X86/X86CallingConv.td
+++ b/llvm/lib/Target/X86/X86CallingConv.td
@@ -1134,6 +1134,23 @@ def CSR_Win64_NoSSE : CalleeSavedRegs<(add RBX, RBP, 
RDI, RSI, R12, R13, R14, R1
 def CSR_Win64 : CalleeSavedRegs<(add CSR_Win64_NoSSE,
                                      (sequence "XMM%u", 6, 15))>;
 
+def CSR_Win64_EGPR1 : CalleeSavedRegs<(add CSR_Win64, R31)>;
+def CSR_Win64_EGPR2 : CalleeSavedRegs<(add CSR_Win64_EGPR1, R30)>;
+def CSR_Win64_EGPR3 : CalleeSavedRegs<(add CSR_Win64_EGPR2, R29)>;
+def CSR_Win64_EGPR4 : CalleeSavedRegs<(add CSR_Win64_EGPR3, R28)>;
+def CSR_Win64_EGPR5 : CalleeSavedRegs<(add CSR_Win64_EGPR4, R27)>;
+def CSR_Win64_EGPR6 : CalleeSavedRegs<(add CSR_Win64_EGPR5, R26)>;
+def CSR_Win64_EGPR7 : CalleeSavedRegs<(add CSR_Win64_EGPR6, R25)>;
+def CSR_Win64_EGPR8 : CalleeSavedRegs<(add CSR_Win64_EGPR7, R24)>;
+def CSR_Win64_EGPR9 : CalleeSavedRegs<(add CSR_Win64_EGPR8, R23)>;
+def CSR_Win64_EGPR10 : CalleeSavedRegs<(add CSR_Win64_EGPR9, R22)>;
+def CSR_Win64_EGPR11 : CalleeSavedRegs<(add CSR_Win64_EGPR10, R21)>;
+def CSR_Win64_EGPR12 : CalleeSavedRegs<(add CSR_Win64_EGPR11, R20)>;
+def CSR_Win64_EGPR13 : CalleeSavedRegs<(add CSR_Win64_EGPR12, R19)>;
+def CSR_Win64_EGPR14 : CalleeSavedRegs<(add CSR_Win64_EGPR13, R18)>;
+def CSR_Win64_EGPR15 : CalleeSavedRegs<(add CSR_Win64_EGPR14, R17)>;
+def CSR_Win64_EGPR16 : CalleeSavedRegs<(add CSR_Win64_EGPR15, R16)>;
+
 def CSR_Win64_SwiftError : CalleeSavedRegs<(sub CSR_Win64, R12)>;
 def CSR_Win64_SwiftTail : CalleeSavedRegs<(sub CSR_Win64, R13, R14)>;
 
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp 
b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index 72f38133e21ff..b22e0ab704786 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -52,6 +52,9 @@ static cl::opt<bool>
 
 extern cl::opt<bool> X86EnableAPXForRelocation;
 
+static cl::opt<unsigned> ApxEgprCSR("apx-egpr-csr", cl::init(0),
+    cl::desc("Set N egpr as callee-saved register for APX calling 
convention"));
+
 X86RegisterInfo::X86RegisterInfo(const Triple &TT)
     : X86GenRegisterInfo((TT.isX86_64() ? X86::RIP : X86::EIP),
                          X86_MC::getDwarfRegFlavour(TT, false),
@@ -245,6 +248,7 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction 
*MF) const {
   bool HasAVX = Subtarget.hasAVX();
   bool HasAVX512 = Subtarget.hasAVX512();
   bool CallsEHReturn = MF->callsEHReturn();
+  bool HasEGPR = Subtarget.hasEGPR();
 
   CallingConv::ID CC = F.getCallingConv();
 
@@ -258,6 +262,32 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction 
*MF) const {
   if (MF->getFunction().hasFnAttribute("no_callee_saved_registers"))
     return CSR_NoRegs_SaveList;
 
+  auto CSR_Win64_Or_EGPR_SaveList = [HasEGPR]() {
+    if (!HasEGPR)
+      return CSR_Win64_SaveList;
+
+    switch (ApxEgprCSR) {
+    case 0: return CSR_Win64_SaveList;
+    case 1: return CSR_Win64_EGPR1_SaveList;
+    case 2: return CSR_Win64_EGPR2_SaveList;
+    case 3: return CSR_Win64_EGPR3_SaveList;
+    case 4: return CSR_Win64_EGPR4_SaveList;
+    case 5: return CSR_Win64_EGPR5_SaveList;
+    case 6: return CSR_Win64_EGPR6_SaveList;
+    case 7: return CSR_Win64_EGPR7_SaveList;
+    case 8: return CSR_Win64_EGPR8_SaveList;
+    case 9: return CSR_Win64_EGPR9_SaveList;
+    case 10: return CSR_Win64_EGPR10_SaveList;
+    case 11: return CSR_Win64_EGPR11_SaveList;
+    case 12: return CSR_Win64_EGPR12_SaveList;
+    case 13: return CSR_Win64_EGPR13_SaveList;
+    case 14: return CSR_Win64_EGPR14_SaveList;
+    case 15: return CSR_Win64_EGPR15_SaveList;
+    case 16: return CSR_Win64_EGPR16_SaveList;
+    default: llvm_unreachable("Invalid reg number!");
+    }
+  };
+
   switch (CC) {
   case CallingConv::GHC:
   case CallingConv::HiPE:
@@ -317,7 +347,7 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction 
*MF) const {
   case CallingConv::Win64:
     if (!HasSSE)
       return CSR_Win64_NoSSE_SaveList;
-    return CSR_Win64_SaveList;
+    return CSR_Win64_Or_EGPR_SaveList();
   case CallingConv::SwiftTail:
     if (!Is64Bit)
       return CSR_32_SaveList;
@@ -356,7 +386,7 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction 
*MF) const {
                      : CSR_64_SwiftError_SaveList;
 
     if (IsWin64 || IsUEFI64)
-      return HasSSE ? CSR_Win64_SaveList : CSR_Win64_NoSSE_SaveList;
+      return HasSSE ? CSR_Win64_Or_EGPR_SaveList() : CSR_Win64_NoSSE_SaveList;
     if (CallsEHReturn)
       return CSR_64EHRet_SaveList;
     return CSR_64_SaveList;
@@ -386,6 +416,33 @@ X86RegisterInfo::getCallPreservedMask(const 
MachineFunction &MF,
   bool HasSSE = Subtarget.hasSSE1();
   bool HasAVX = Subtarget.hasAVX();
   bool HasAVX512 = Subtarget.hasAVX512();
+  bool HasEGPR = Subtarget.hasEGPR();
+
+  auto CSR_Win64_Or_EGPR_RegMask = [HasEGPR]() {
+    if (!HasEGPR)
+      return CSR_Win64_RegMask;
+
+    switch (ApxEgprCSR) {
+    case 0: return CSR_Win64_RegMask;
+    case 1: return CSR_Win64_EGPR1_RegMask;
+    case 2: return CSR_Win64_EGPR2_RegMask;
+    case 3: return CSR_Win64_EGPR3_RegMask;
+    case 4: return CSR_Win64_EGPR4_RegMask;
+    case 5: return CSR_Win64_EGPR5_RegMask;
+    case 6: return CSR_Win64_EGPR6_RegMask;
+    case 7: return CSR_Win64_EGPR7_RegMask;
+    case 8: return CSR_Win64_EGPR8_RegMask;
+    case 9: return CSR_Win64_EGPR9_RegMask;
+    case 10: return CSR_Win64_EGPR10_RegMask;
+    case 11: return CSR_Win64_EGPR11_RegMask;
+    case 12: return CSR_Win64_EGPR12_RegMask;
+    case 13: return CSR_Win64_EGPR13_RegMask;
+    case 14: return CSR_Win64_EGPR14_RegMask;
+    case 15: return CSR_Win64_EGPR15_RegMask;
+    case 16: return CSR_Win64_EGPR16_RegMask;
+    default: llvm_unreachable("Invalid reg number!");
+    }
+  };
 
   switch (CC) {
   case CallingConv::GHC:
@@ -442,7 +499,7 @@ X86RegisterInfo::getCallPreservedMask(const MachineFunction 
&MF,
       return CSR_64_MostRegs_RegMask;
     break;
   case CallingConv::Win64:
-    return CSR_Win64_RegMask;
+    return CSR_Win64_Or_EGPR_RegMask();
   case CallingConv::SwiftTail:
     if (!Is64Bit)
       return CSR_32_RegMask;
@@ -480,7 +537,7 @@ X86RegisterInfo::getCallPreservedMask(const MachineFunction 
&MF,
     if (IsSwiftCC)
       return IsWin64 ? CSR_Win64_SwiftError_RegMask : 
CSR_64_SwiftError_RegMask;
 
-    return (IsWin64 || IsUEFI64) ? CSR_Win64_RegMask : CSR_64_RegMask;
+    return (IsWin64 || IsUEFI64) ? CSR_Win64_Or_EGPR_RegMask() : 
CSR_64_RegMask;
   }
 
   return CSR_32_RegMask;

>From 5843987c512e32bffd437db2e06eb3c67d6cced8 Mon Sep 17 00:00:00 2001
From: Phoebe Wang <[email protected]>
Date: Tue, 17 Mar 2026 17:02:48 +0800
Subject: [PATCH 2/3] Adjust register priority

---
 llvm/lib/Target/X86/X86RegisterInfo.td | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/X86/X86RegisterInfo.td 
b/llvm/lib/Target/X86/X86RegisterInfo.td
index 692e42ae5e752..dfb5ceae0dae3 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.td
+++ b/llvm/lib/Target/X86/X86RegisterInfo.td
@@ -544,9 +544,9 @@ def SSP : X86Reg<"ssp", 0>;
 // cannot be encoded.
 def GR8 : RegisterClass<"X86", [i8], 8,
                         (add AL, CL, DL, AH, CH, DH, BL, BH, SIL, DIL, BPL, 
SPL,
-                             R8B, R9B, R10B, R11B, R16B, R17B, R18B, R19B, 
R22B,
-                             R23B, R24B, R25B, R26B, R27B, R30B, R31B, R14B,
-                             R15B, R12B, R13B, R20B, R21B, R28B, R29B)> {
+                             R8B, R9B, R10B, R11B, R14B, R15B, R12B, R13B, 
R16B,
+                             R17B, R18B, R19B, R22B, R23B, R24B, R25B, R26B,
+                             R27B, R30B, R31B, R20B, R21B, R28B, R29B)> {
   let AltOrders = [(sub GR8, AH, BH, CH, DH)];
   let AltOrderSelect = [{
     return MF.getSubtarget<X86Subtarget>().is64Bit();
@@ -561,9 +561,9 @@ def GRH8 : RegisterClass<"X86", [i8], 8,
                               R26BH, R27BH, R28BH, R29BH, R30BH, R31BH)>;
 def GR16 : RegisterClass<"X86", [i16], 16,
                          (add AX, CX, DX, SI, DI, BX, BP, SP, R8W, R9W, R10W,
-                              R11W, R16W, R17W, R18W, R19W, R22W, R23W, R24W,
-                              R25W, R26W, R27W, R30W, R31W, R14W, R15W, R12W,
-                              R13W, R20W, R21W, R28W, R29W)>;
+                              R11W, R14W, R15W, R12W, R13W, R16W, R17W, R18W,
+                              R19W, R22W, R23W, R24W, R25W, R26W, R27W, R30W,
+                              R31W, R20W, R21W, R28W, R29W)>;
 
 let isAllocatable = 0 in
 def GRH16 : RegisterClass<"X86", [i16], 16,
@@ -573,9 +573,9 @@ def GRH16 : RegisterClass<"X86", [i16], 16,
                          R25WH, R26WH, R27WH, R28WH, R29WH, R30WH, R31WH)>;
 def GR32 : RegisterClass<"X86", [i32], 32,
                          (add EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP, R8D, R9D,
-                              R10D, R11D, R16D, R17D, R18D, R19D, R22D, R23D,
-                              R24D, R25D, R26D, R27D, R30D, R31D, R14D, R15D,
-                              R12D, R13D, R20D, R21D, R28D, R29D)>;
+                              R10D, R11D, R14D, R15D, R12D, R13D, R16D, R17D,
+                              R18D, R19D, R22D, R23D, R24D, R25D, R26D, R27D,
+                              R30D, R31D, R20D, R21D, R28D, R29D)>;
 
 // GR64 - 64-bit GPRs. This oddly includes RIP, which isn't accurate, since
 // RIP isn't really a register and it can't be used anywhere except in an
@@ -583,9 +583,9 @@ def GR32 : RegisterClass<"X86", [i32], 32,
 // FIXME: it *does* cause trouble - CheckBaseRegAndIndexReg() has extra
 // tests because of the inclusion of RIP in this register class.
 def GR64 : RegisterClass<"X86", [i64], 64,
-                    (add RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, R16, R17,
-                         R18, R19, R22, R23, R24, R25, R26, R27, R30, R31, RBX,
-                         R14, R15, R12, R13, R20, R21, R28, R29, RBP, RSP, 
RIP)>;
+                    (add RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, RBX, R14,
+                         R15, R12, R13, RBP, R16, R17, R18, R19, R22, R23, R24,
+                         R25, R26, R27, R30, R31, R20, R21, R28, R29, RSP, 
RIP)>;
 
 // GR64PLTSafe - 64-bit GPRs without R10, R11, RSP and RIP. Could be used when
 // emitting code for intrinsics, which use implict input registers.

>From f7f431ddbcd4fbab9ceb01fde42c04ceebaecdf1 Mon Sep 17 00:00:00 2001
From: Phoebe Wang <[email protected]>
Date: Tue, 24 Mar 2026 11:28:00 +0800
Subject: [PATCH 3/3] Apply azwolski's diff

---
 clang/include/clang/Options/Options.td     | 2 ++
 clang/lib/Driver/ToolChains/Arch/X86.cpp   | 8 ++++++++
 clang/lib/Driver/ToolChains/CommonArgs.cpp | 3 ++-
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index c98bb969b28d9..022901ec2fe6d 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -6999,6 +6999,8 @@ def mapx_features_EQ : CommaJoined<["-"], 
"mapx-features=">, Group<m_x86_Feature
     HelpText<"Enable features of APX">, 
Values<"egpr,push2pop2,ppx,ndd,ccmp,nf,cf,zu">,  Visibility<[ClangOption, 
CLOption, FlangOption]>;
 def mno_apx_features_EQ : CommaJoined<["-"], "mno-apx-features=">, 
Group<m_x86_Features_Group>,
     HelpText<"Disable features of APX">, 
Values<"egpr,push2pop2,ppx,ndd,ccmp,nf,cf,zu">, Visibility<[ClangOption, 
CLOption, FlangOption]>;
+def mapx_features_egpr_nv_EQ : Joined<["-"], "mapx-features=egpr-nv:">, 
Group<m_x86_Features_Group>,
+    HelpText<"Set number of non-volatile registers of APX EGPR feature">;
 def mapxf : Flag<["-"], "mapxf">, Alias<mapx_features_EQ>,
             AliasArgs<["egpr","push2pop2","ppx","ndd","ccmp","nf","zu"]>,
             Group<m_x86_Features_Group>;
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp 
b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index e90edd0a203b1..74767a0d6b73e 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -272,11 +272,19 @@ void x86::getX86TargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
       }
       continue;
     }
+
+    // Handle -mapx-features=egpr-nv:N
+    if (A->getOption().matches(options::OPT_mapx_features_egpr_nv_EQ)) {
+      Features.push_back("+egpr");
+      continue;
+    }
+
     if (IsNegative)
       Name = Name.substr(3);
     Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
   }
 
+  // Handle Windows-style /apx-features=egpr-nv:N option
   if (Args.hasArgNoClaim(options::OPT__SLASH_apx_features_egprnv))
     Features.push_back("+egpr");
 
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index ce4a199668b60..0f5bcf5f58836 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -923,7 +923,8 @@ void tools::getTargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
     CmdArgs.push_back(Feature.data());
   }
 
-  if (Arg *A = Args.getLastArg(options::OPT__SLASH_apx_features_egprnv)) {
+  if (Arg *A = Args.getLastArg(options::OPT__SLASH_apx_features_egprnv,
+                               options::OPT_mapx_features_egpr_nv_EQ)) {
     StringRef Value = A->getValue();
     CmdArgs.push_back("-mllvm");
     CmdArgs.push_back(Args.MakeArgString("-apx-egpr-csr=" + Value));

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

Reply via email to