Skip to content

[X86][APX] Disable PP2/PPX generation on Windows#178122

Merged
phoebewang merged 4 commits intollvm:mainfrom
phoebewang:ppx
Feb 2, 2026
Merged

[X86][APX] Disable PP2/PPX generation on Windows#178122
phoebewang merged 4 commits intollvm:mainfrom
phoebewang:ppx

Conversation

@phoebewang
Copy link
Copy Markdown
Contributor

The PUSH2/POP2/PPX instructions for APX require updates to the Microsoft Windows OS x64 calling convention documented at https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-170 due to lack of suitable unwinder opcodes that can support APX PUSH2/POP2/PPX.

The PR request disables this support by default for code robustness; workloads that choose to explicitly enable this support can change the default behavior by explicitly specifying the flag options that enable this support e.g. for experimentation or code paths that do not need unwinder support.

The PUSH2/POP2/PPX instructions for APX require updates to the Microsoft Windows OS x64 calling convention documented at https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-170 due to lack of suitable unwinder opcodes that can support APX PUSH2/POP2/PPX. The PR request disables this support by default for code robustness; workloads that choose to explicitly enable this support can change the default behavior by explicitly specifying the flag options that enable this support e.g. for experimentation or code paths that do not need unwinder support.
@llvmbot llvmbot added backend:X86 clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jan 27, 2026
@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Jan 27, 2026

@llvm/pr-subscribers-clang-driver

Author: Phoebe Wang (phoebewang)

Changes

The PUSH2/POP2/PPX instructions for APX require updates to the Microsoft Windows OS x64 calling convention documented at https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-170 due to lack of suitable unwinder opcodes that can support APX PUSH2/POP2/PPX.

The PR request disables this support by default for code robustness; workloads that choose to explicitly enable this support can change the default behavior by explicitly specifying the flag options that enable this support e.g. for experimentation or code paths that do not need unwinder support.


Full diff: https://github.com/llvm/llvm-project/pull/178122.diff

8 Files Affected:

  • (modified) clang/include/clang/Options/Options.td (+2-6)
  • (modified) clang/lib/Basic/Targets/X86.cpp (+6-1)
  • (modified) clang/lib/Driver/ToolChains/Arch/X86.cpp (+21-4)
  • (modified) clang/test/Driver/cl-x86-flags.c (+2-2)
  • (modified) clang/test/Driver/x86-target-features.c (+2-2)
  • (modified) llvm/lib/Target/X86/X86Subtarget.cpp (+3)
  • (modified) llvm/lib/TargetParser/Host.cpp (+2)
  • (modified) llvm/test/CodeGen/X86/apx/push2-pop2-cfi-seh.ll (+2)
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 43727236ed5a4..1f67441fb389b 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -7043,12 +7043,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 mapxf : Flag<["-"], "mapxf">, Alias<mapx_features_EQ>,
-            AliasArgs<["egpr","push2pop2","ppx","ndd","ccmp","nf","zu"]>,
-            Group<m_x86_Features_Group>;
-def mno_apxf : Flag<["-"], "mno-apxf">, Alias<mno_apx_features_EQ>,
-               AliasArgs<["egpr","push2pop2","ppx","ndd","ccmp","nf","zu"]>,
-               Group<m_x86_Features_Group>;
+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">;
 } // let Flags = [TargetSpecific]
diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp
index f00d435937b92..f0a1874be8111 100644
--- a/clang/lib/Basic/Targets/X86.cpp
+++ b/clang/lib/Basic/Targets/X86.cpp
@@ -164,6 +164,11 @@ bool X86TargetInfo::initFeatureMap(
   for (auto &F : CPUFeatures)
     setFeatureEnabled(Features, F, true);
 
+  if (Features.lookup("egpr") && getTriple().isOSWindows()) {
+    setFeatureEnabled(Features, "push2pop2", false);
+    setFeatureEnabled(Features, "ppx", false);
+  }
+
   std::vector<std::string> UpdatedFeaturesVec;
   for (const auto &Feature : FeaturesVec) {
     // Expand general-regs-only to -x86, -mmx and -sse
@@ -967,7 +972,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
     Builder.defineMacro("__CF__");
   if (HasZU)
     Builder.defineMacro("__ZU__");
-  if (HasEGPR && HasPush2Pop2 && HasPPX && HasNDD && HasCCMP && HasNF && HasZU)
+  if (HasEGPR && HasNDD && HasCCMP && HasNF && HasZU)
     Builder.defineMacro("__APX_F__");
   if (HasEGPR && HasInlineAsmUseGPR32)
     Builder.defineMacro("__APX_INLINE_ASM_USE_GPR32__");
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index d6e6657c521f0..7a0dea030615d 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -252,14 +252,33 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
       D.Diag(diag::err_drv_unsupported_opt_for_target)
           << A->getSpelling() << Triple.getTriple();
 
-    if (A->getOption().matches(options::OPT_mapx_features_EQ) ||
+    if (IsNegative)
+      Name = Name.substr(3);
+    if (A->getOption().matches(options::OPT_mapxf) ||
+        A->getOption().matches(options::OPT_mno_apxf) ||
+        A->getOption().matches(options::OPT_mapx_features_EQ) ||
         A->getOption().matches(options::OPT_mno_apx_features_EQ)) {
 
       if (Not64Bit && !IsNegative)
         D.Diag(diag::err_drv_unsupported_opt_for_target)
-            << StringRef(A->getSpelling().str() + "|-mapxf")
+            << StringRef("-mapx-features=|-mapxf")
             << Triple.getTriple();
 
+      if (Name == "apxf") {
+        if (IsNegative) {
+          Features.insert(Features.end(),
+                          {"-egpr", "-ndd", "-ccmp", "-nf", "-zu"});
+          if (!Triple.isOSWindows())
+            Features.insert(Features.end(), {"-push2pop2", "-ppx"});
+        } else {
+          Features.insert(Features.end(),
+                          {"+egpr", "+ndd", "+ccmp", "+nf", "+zu"});
+          if (!Triple.isOSWindows())
+            Features.insert(Features.end(), {"+push2pop2", "+ppx"});
+        }
+        continue;
+      }
+
       for (StringRef Value : A->getValues()) {
         if (Value != "egpr" && Value != "push2pop2" && Value != "ppx" &&
             Value != "ndd" && Value != "ccmp" && Value != "nf" &&
@@ -272,8 +291,6 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
       }
       continue;
     }
-    if (IsNegative)
-      Name = Name.substr(3);
     Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
   }
 
diff --git a/clang/test/Driver/cl-x86-flags.c b/clang/test/Driver/cl-x86-flags.c
index 84270aae35f7a..f85828b370d9e 100644
--- a/clang/test/Driver/cl-x86-flags.c
+++ b/clang/test/Driver/cl-x86-flags.c
@@ -222,6 +222,6 @@ void f(void) {
 // RUN: %clang_cl --target=x86_64-pc-windows -mapxf -### -- 2>&1 %s | FileCheck -check-prefix=APXF %s
 // RUN: %clang_cl --target=x86_64-pc-windows -mapxf -mno-apxf -### -- 2>&1 %s | FileCheck -check-prefix=NO-APXF %s
 // RUN: %clang_cl --target=x86_64-pc-windows -mapx-features=egpr,push2pop2,ppx,ndd,ccmp,nf,cf,zu -### -- 2>&1 %s | FileCheck -check-prefix=APXALL %s
-// APXF: "-target-feature" "+egpr" "-target-feature" "+push2pop2" "-target-feature" "+ppx" "-target-feature" "+ndd" "-target-feature" "+ccmp" "-target-feature" "+nf" "-target-feature" "+zu"
-// NO-APXF: "-target-feature" "-egpr" "-target-feature" "-push2pop2" "-target-feature" "-ppx" "-target-feature" "-ndd" "-target-feature" "-ccmp" "-target-feature" "-nf" "-target-feature" "-zu"
+// APXF: "-target-feature" "+egpr" "-target-feature" "+ndd" "-target-feature" "+ccmp" "-target-feature" "+nf" "-target-feature" "+zu"
+// NO-APXF: "-target-feature" "-egpr" "-target-feature" "-ndd" "-target-feature" "-ccmp" "-target-feature" "-nf" "-target-feature" "-zu"
 // APXALL: "-target-feature" "+egpr" "-target-feature" "+push2pop2" "-target-feature" "+ppx" "-target-feature" "+ndd" "-target-feature" "+ccmp" "-target-feature" "+nf" "-target-feature" "+cf" "-target-feature" "+zu"
diff --git a/clang/test/Driver/x86-target-features.c b/clang/test/Driver/x86-target-features.c
index f1660b1afb518..c0f2340d0f9fe 100644
--- a/clang/test/Driver/x86-target-features.c
+++ b/clang/test/Driver/x86-target-features.c
@@ -443,8 +443,8 @@
 // RUN: %clang --target=x86_64-unknown-linux-gnu -mno-apxf -mapxf %s -### -o %t.o 2>&1 | FileCheck -check-prefix=APXF %s
 // RUN: %clang --target=x86_64-unknown-linux-gnu -mapxf -mno-apxf %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-APXF %s
 //
-// APXF: "-target-feature" "+egpr" "-target-feature" "+push2pop2" "-target-feature" "+ppx" "-target-feature" "+ndd" "-target-feature" "+ccmp" "-target-feature" "+nf" "-target-feature" "+zu"
-// NO-APXF: "-target-feature" "-egpr" "-target-feature" "-push2pop2" "-target-feature" "-ppx" "-target-feature" "-ndd" "-target-feature" "-ccmp" "-target-feature" "-nf" "-target-feature" "-zu"
+// APXF: "-target-feature" "+egpr" "-target-feature" "+ndd" "-target-feature" "+ccmp" "-target-feature" "+nf" "-target-feature" "+zu" "-target-feature" "+push2pop2" "-target-feature" "+ppx"
+// NO-APXF: "-target-feature" "-egpr" "-target-feature" "-ndd" "-target-feature" "-ccmp" "-target-feature" "-nf" "-target-feature" "-zu" "-target-feature" "-push2pop2" "-target-feature" "-ppx"
 
 // RUN: %clang --target=x86_64-unknown-linux-gnu -mapx-features=egpr %s -### -o %t.o 2>&1 | FileCheck -check-prefix=EGPR %s
 // RUN: %clang --target=x86_64-unknown-linux-gnu -mapx-features=push2pop2 %s -### -o %t.o 2>&1 | FileCheck -check-prefix=PUSH2POP2 %s
diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp
index 61f288ffb909b..4e2e98410f325 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -257,6 +257,9 @@ void X86Subtarget::initSubtargetFeatures(StringRef CPU, StringRef TuneCPU,
   std::string FullFS = X86_MC::ParseX86Triple(TargetTriple);
   assert(!FullFS.empty() && "Failed to parse X86 triple");
 
+  if (TargetTriple.isOSWindows())
+    FullFS += ",-push2pop2,-ppx";
+
   if (!FS.empty())
     FullFS = (Twine(FullFS) + "," + FS).str();
 
diff --git a/llvm/lib/TargetParser/Host.cpp b/llvm/lib/TargetParser/Host.cpp
index 5d4fa2c88153c..7b1af1779a24a 100644
--- a/llvm/lib/TargetParser/Host.cpp
+++ b/llvm/lib/TargetParser/Host.cpp
@@ -2167,8 +2167,10 @@ StringMap<bool> sys::getHostCPUFeatures() {
   bool HasAVX10 = HasLeaf7Subleaf1 && ((EDX >> 19) & 1);
   bool HasAPXF = HasLeaf7Subleaf1 && ((EDX >> 21) & 1) && HasAPXSave;
   Features["egpr"] = HasAPXF;
+#ifndef _WIN32
   Features["push2pop2"] = HasAPXF;
   Features["ppx"] = HasAPXF;
+#endif
   Features["ndd"] = HasAPXF;
   Features["ccmp"] = HasAPXF;
   Features["nf"] = HasAPXF;
diff --git a/llvm/test/CodeGen/X86/apx/push2-pop2-cfi-seh.ll b/llvm/test/CodeGen/X86/apx/push2-pop2-cfi-seh.ll
index d6d4db3509103..071b297b49dc1 100644
--- a/llvm/test/CodeGen/X86/apx/push2-pop2-cfi-seh.ll
+++ b/llvm/test/CodeGen/X86/apx/push2-pop2-cfi-seh.ll
@@ -2,7 +2,9 @@
 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=LIN-REF
 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+push2pop2 | FileCheck %s --check-prefix=LIN
 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+push2pop2,+ppx | FileCheck %s --check-prefix=LIN-PPX
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=diamondrapids | FileCheck %s --check-prefix=LIN-PPX
 ; RUN: llc < %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefix=WIN-REF
+; RUN: llc < %s -mtriple=x86_64-windows-msvc -mcpu=diamondrapids | FileCheck %s --check-prefix=WIN-REF
 ; RUN: llc < %s -mtriple=x86_64-windows-msvc -mattr=+push2pop2 | FileCheck %s --check-prefix=WIN
 ; RUN: llc < %s -mtriple=x86_64-windows-msvc -mattr=+push2pop2,+ppx | FileCheck %s --check-prefix=WIN-PPX
 

@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Jan 27, 2026

@llvm/pr-subscribers-backend-x86

Author: Phoebe Wang (phoebewang)

Changes

The PUSH2/POP2/PPX instructions for APX require updates to the Microsoft Windows OS x64 calling convention documented at https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-170 due to lack of suitable unwinder opcodes that can support APX PUSH2/POP2/PPX.

The PR request disables this support by default for code robustness; workloads that choose to explicitly enable this support can change the default behavior by explicitly specifying the flag options that enable this support e.g. for experimentation or code paths that do not need unwinder support.


Full diff: https://github.com/llvm/llvm-project/pull/178122.diff

8 Files Affected:

  • (modified) clang/include/clang/Options/Options.td (+2-6)
  • (modified) clang/lib/Basic/Targets/X86.cpp (+6-1)
  • (modified) clang/lib/Driver/ToolChains/Arch/X86.cpp (+21-4)
  • (modified) clang/test/Driver/cl-x86-flags.c (+2-2)
  • (modified) clang/test/Driver/x86-target-features.c (+2-2)
  • (modified) llvm/lib/Target/X86/X86Subtarget.cpp (+3)
  • (modified) llvm/lib/TargetParser/Host.cpp (+2)
  • (modified) llvm/test/CodeGen/X86/apx/push2-pop2-cfi-seh.ll (+2)
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 43727236ed5a4..1f67441fb389b 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -7043,12 +7043,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 mapxf : Flag<["-"], "mapxf">, Alias<mapx_features_EQ>,
-            AliasArgs<["egpr","push2pop2","ppx","ndd","ccmp","nf","zu"]>,
-            Group<m_x86_Features_Group>;
-def mno_apxf : Flag<["-"], "mno-apxf">, Alias<mno_apx_features_EQ>,
-               AliasArgs<["egpr","push2pop2","ppx","ndd","ccmp","nf","zu"]>,
-               Group<m_x86_Features_Group>;
+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">;
 } // let Flags = [TargetSpecific]
diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp
index f00d435937b92..f0a1874be8111 100644
--- a/clang/lib/Basic/Targets/X86.cpp
+++ b/clang/lib/Basic/Targets/X86.cpp
@@ -164,6 +164,11 @@ bool X86TargetInfo::initFeatureMap(
   for (auto &F : CPUFeatures)
     setFeatureEnabled(Features, F, true);
 
+  if (Features.lookup("egpr") && getTriple().isOSWindows()) {
+    setFeatureEnabled(Features, "push2pop2", false);
+    setFeatureEnabled(Features, "ppx", false);
+  }
+
   std::vector<std::string> UpdatedFeaturesVec;
   for (const auto &Feature : FeaturesVec) {
     // Expand general-regs-only to -x86, -mmx and -sse
@@ -967,7 +972,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
     Builder.defineMacro("__CF__");
   if (HasZU)
     Builder.defineMacro("__ZU__");
-  if (HasEGPR && HasPush2Pop2 && HasPPX && HasNDD && HasCCMP && HasNF && HasZU)
+  if (HasEGPR && HasNDD && HasCCMP && HasNF && HasZU)
     Builder.defineMacro("__APX_F__");
   if (HasEGPR && HasInlineAsmUseGPR32)
     Builder.defineMacro("__APX_INLINE_ASM_USE_GPR32__");
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index d6e6657c521f0..7a0dea030615d 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -252,14 +252,33 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
       D.Diag(diag::err_drv_unsupported_opt_for_target)
           << A->getSpelling() << Triple.getTriple();
 
-    if (A->getOption().matches(options::OPT_mapx_features_EQ) ||
+    if (IsNegative)
+      Name = Name.substr(3);
+    if (A->getOption().matches(options::OPT_mapxf) ||
+        A->getOption().matches(options::OPT_mno_apxf) ||
+        A->getOption().matches(options::OPT_mapx_features_EQ) ||
         A->getOption().matches(options::OPT_mno_apx_features_EQ)) {
 
       if (Not64Bit && !IsNegative)
         D.Diag(diag::err_drv_unsupported_opt_for_target)
-            << StringRef(A->getSpelling().str() + "|-mapxf")
+            << StringRef("-mapx-features=|-mapxf")
             << Triple.getTriple();
 
+      if (Name == "apxf") {
+        if (IsNegative) {
+          Features.insert(Features.end(),
+                          {"-egpr", "-ndd", "-ccmp", "-nf", "-zu"});
+          if (!Triple.isOSWindows())
+            Features.insert(Features.end(), {"-push2pop2", "-ppx"});
+        } else {
+          Features.insert(Features.end(),
+                          {"+egpr", "+ndd", "+ccmp", "+nf", "+zu"});
+          if (!Triple.isOSWindows())
+            Features.insert(Features.end(), {"+push2pop2", "+ppx"});
+        }
+        continue;
+      }
+
       for (StringRef Value : A->getValues()) {
         if (Value != "egpr" && Value != "push2pop2" && Value != "ppx" &&
             Value != "ndd" && Value != "ccmp" && Value != "nf" &&
@@ -272,8 +291,6 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
       }
       continue;
     }
-    if (IsNegative)
-      Name = Name.substr(3);
     Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
   }
 
diff --git a/clang/test/Driver/cl-x86-flags.c b/clang/test/Driver/cl-x86-flags.c
index 84270aae35f7a..f85828b370d9e 100644
--- a/clang/test/Driver/cl-x86-flags.c
+++ b/clang/test/Driver/cl-x86-flags.c
@@ -222,6 +222,6 @@ void f(void) {
 // RUN: %clang_cl --target=x86_64-pc-windows -mapxf -### -- 2>&1 %s | FileCheck -check-prefix=APXF %s
 // RUN: %clang_cl --target=x86_64-pc-windows -mapxf -mno-apxf -### -- 2>&1 %s | FileCheck -check-prefix=NO-APXF %s
 // RUN: %clang_cl --target=x86_64-pc-windows -mapx-features=egpr,push2pop2,ppx,ndd,ccmp,nf,cf,zu -### -- 2>&1 %s | FileCheck -check-prefix=APXALL %s
-// APXF: "-target-feature" "+egpr" "-target-feature" "+push2pop2" "-target-feature" "+ppx" "-target-feature" "+ndd" "-target-feature" "+ccmp" "-target-feature" "+nf" "-target-feature" "+zu"
-// NO-APXF: "-target-feature" "-egpr" "-target-feature" "-push2pop2" "-target-feature" "-ppx" "-target-feature" "-ndd" "-target-feature" "-ccmp" "-target-feature" "-nf" "-target-feature" "-zu"
+// APXF: "-target-feature" "+egpr" "-target-feature" "+ndd" "-target-feature" "+ccmp" "-target-feature" "+nf" "-target-feature" "+zu"
+// NO-APXF: "-target-feature" "-egpr" "-target-feature" "-ndd" "-target-feature" "-ccmp" "-target-feature" "-nf" "-target-feature" "-zu"
 // APXALL: "-target-feature" "+egpr" "-target-feature" "+push2pop2" "-target-feature" "+ppx" "-target-feature" "+ndd" "-target-feature" "+ccmp" "-target-feature" "+nf" "-target-feature" "+cf" "-target-feature" "+zu"
diff --git a/clang/test/Driver/x86-target-features.c b/clang/test/Driver/x86-target-features.c
index f1660b1afb518..c0f2340d0f9fe 100644
--- a/clang/test/Driver/x86-target-features.c
+++ b/clang/test/Driver/x86-target-features.c
@@ -443,8 +443,8 @@
 // RUN: %clang --target=x86_64-unknown-linux-gnu -mno-apxf -mapxf %s -### -o %t.o 2>&1 | FileCheck -check-prefix=APXF %s
 // RUN: %clang --target=x86_64-unknown-linux-gnu -mapxf -mno-apxf %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-APXF %s
 //
-// APXF: "-target-feature" "+egpr" "-target-feature" "+push2pop2" "-target-feature" "+ppx" "-target-feature" "+ndd" "-target-feature" "+ccmp" "-target-feature" "+nf" "-target-feature" "+zu"
-// NO-APXF: "-target-feature" "-egpr" "-target-feature" "-push2pop2" "-target-feature" "-ppx" "-target-feature" "-ndd" "-target-feature" "-ccmp" "-target-feature" "-nf" "-target-feature" "-zu"
+// APXF: "-target-feature" "+egpr" "-target-feature" "+ndd" "-target-feature" "+ccmp" "-target-feature" "+nf" "-target-feature" "+zu" "-target-feature" "+push2pop2" "-target-feature" "+ppx"
+// NO-APXF: "-target-feature" "-egpr" "-target-feature" "-ndd" "-target-feature" "-ccmp" "-target-feature" "-nf" "-target-feature" "-zu" "-target-feature" "-push2pop2" "-target-feature" "-ppx"
 
 // RUN: %clang --target=x86_64-unknown-linux-gnu -mapx-features=egpr %s -### -o %t.o 2>&1 | FileCheck -check-prefix=EGPR %s
 // RUN: %clang --target=x86_64-unknown-linux-gnu -mapx-features=push2pop2 %s -### -o %t.o 2>&1 | FileCheck -check-prefix=PUSH2POP2 %s
diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp
index 61f288ffb909b..4e2e98410f325 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -257,6 +257,9 @@ void X86Subtarget::initSubtargetFeatures(StringRef CPU, StringRef TuneCPU,
   std::string FullFS = X86_MC::ParseX86Triple(TargetTriple);
   assert(!FullFS.empty() && "Failed to parse X86 triple");
 
+  if (TargetTriple.isOSWindows())
+    FullFS += ",-push2pop2,-ppx";
+
   if (!FS.empty())
     FullFS = (Twine(FullFS) + "," + FS).str();
 
diff --git a/llvm/lib/TargetParser/Host.cpp b/llvm/lib/TargetParser/Host.cpp
index 5d4fa2c88153c..7b1af1779a24a 100644
--- a/llvm/lib/TargetParser/Host.cpp
+++ b/llvm/lib/TargetParser/Host.cpp
@@ -2167,8 +2167,10 @@ StringMap<bool> sys::getHostCPUFeatures() {
   bool HasAVX10 = HasLeaf7Subleaf1 && ((EDX >> 19) & 1);
   bool HasAPXF = HasLeaf7Subleaf1 && ((EDX >> 21) & 1) && HasAPXSave;
   Features["egpr"] = HasAPXF;
+#ifndef _WIN32
   Features["push2pop2"] = HasAPXF;
   Features["ppx"] = HasAPXF;
+#endif
   Features["ndd"] = HasAPXF;
   Features["ccmp"] = HasAPXF;
   Features["nf"] = HasAPXF;
diff --git a/llvm/test/CodeGen/X86/apx/push2-pop2-cfi-seh.ll b/llvm/test/CodeGen/X86/apx/push2-pop2-cfi-seh.ll
index d6d4db3509103..071b297b49dc1 100644
--- a/llvm/test/CodeGen/X86/apx/push2-pop2-cfi-seh.ll
+++ b/llvm/test/CodeGen/X86/apx/push2-pop2-cfi-seh.ll
@@ -2,7 +2,9 @@
 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=LIN-REF
 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+push2pop2 | FileCheck %s --check-prefix=LIN
 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+push2pop2,+ppx | FileCheck %s --check-prefix=LIN-PPX
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=diamondrapids | FileCheck %s --check-prefix=LIN-PPX
 ; RUN: llc < %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefix=WIN-REF
+; RUN: llc < %s -mtriple=x86_64-windows-msvc -mcpu=diamondrapids | FileCheck %s --check-prefix=WIN-REF
 ; RUN: llc < %s -mtriple=x86_64-windows-msvc -mattr=+push2pop2 | FileCheck %s --check-prefix=WIN
 ; RUN: llc < %s -mtriple=x86_64-windows-msvc -mattr=+push2pop2,+ppx | FileCheck %s --check-prefix=WIN-PPX
 

@github-actions
Copy link
Copy Markdown

github-actions bot commented Jan 27, 2026

✅ With the latest revision this PR passed the C/C++ code formatter.

@@ -2167,8 +2167,10 @@ StringMap<bool> sys::getHostCPUFeatures() {
bool HasAVX10 = HasLeaf7Subleaf1 && ((EDX >> 19) & 1);
bool HasAPXF = HasLeaf7Subleaf1 && ((EDX >> 21) & 1) && HasAPXSave;
Features["egpr"] = HasAPXF;
#ifndef _WIN32
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments? Is there a plan to support this in the future?

Ideally we wouldn't filter the host cpu features by OS like this - but I'm not sure what alternatives there are?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I think so, but it's not clear to me now. I think it's fine here now. Host means build and run must be on the same machine with the same OS (notes APXSave is OS dependent already). So we don't worry about it's enabled or disabled incorrectly.

@RKSimon RKSimon self-requested a review January 27, 2026 13:02
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< StringRef(A->getSpelling().str() + "|-mapxf")
<< Triple.getTriple();
<< StringRef("-mapx-features=|-mapxf") << Triple.getTriple();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"-mapx-features=-mapxf"?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was checked together. I split them now.

if (HasZU)
Builder.defineMacro("__ZU__");
if (HasEGPR && HasPush2Pop2 && HasPPX && HasNDD && HasCCMP && HasNF && HasZU)
if (HasEGPR && HasNDD && HasCCMP && HasNF && HasZU)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does GCC match this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GCC is a bit different. They don't define and check single features: https://godbolt.org/z/6esWPovj7

I changed to check OS to match GCC as possible.

@phoebewang phoebewang requested a review from RKSimon February 2, 2026 01:30
@phoebewang
Copy link
Copy Markdown
Contributor Author

Ping?

Copy link
Copy Markdown
Collaborator

@RKSimon RKSimon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - but I'm not very familiar with APX - if you want to backport this to 22.x I'd be more comfortable with a second reviewer

@phoebewang phoebewang merged commit 2f3935b into llvm:main Feb 2, 2026
10 checks passed
@phoebewang phoebewang deleted the ppx branch February 2, 2026 10:01
@phoebewang phoebewang added this to the LLVM 22.x Release milestone Feb 3, 2026
@phoebewang
Copy link
Copy Markdown
Contributor Author

/cherry-pick 2f3935b

@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Feb 3, 2026

/pull-request #179404

c-rhodes pushed a commit to llvmbot/llvm-project that referenced this pull request Feb 3, 2026
The PUSH2/POP2/PPX instructions for APX require updates to the Microsoft
Windows OS x64 calling convention documented at
https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-170
due to lack of suitable unwinder opcodes that can support APX
PUSH2/POP2/PPX.

The PR request disables this support by default for code robustness;
workloads that choose to explicitly enable this support can change the
default behavior by explicitly specifying the flag options that enable
this support e.g. for experimentation or code paths that do not need
unwinder support.

(cherry picked from commit 2f3935b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:X86 clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema"

Projects

Development

Successfully merging this pull request may close these issues.

3 participants