Skip to content

[X86] Support CFE flags for APX features #74199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Dec 4, 2023
Merged

Conversation

KanRobert
Copy link
Contributor

@KanRobert KanRobert commented Dec 2, 2023

Positive options: -mapx-features=
Negative options: -mno-apx-features=

-m[no-]apx-features is designed to be able to control separate APX
features.

Besides, we also support the flag -m[no-]apxf, which can be used like an
alias of -m[no-]apx-features=< all APX features covered by CPUID APX_F>

Behaviour when positive and negative options are used together:

For boolean flags, the last one wins

-mapxf -mno-apxf -> -mno-apxf
-mno-apxf -mapxf -> -mapxf

For flags that take a set as arguments, it sets the mask by order of the
flags

-mapx-features=egpr,ndd -mno-apx-features=egpr -> -egpr,+ndd
-mapx-features=egpr -mno-apx-features=egpr,ndd -> -egpr,-ndd
-mno-apx-features=egpr -mapx-features=egpr,ndd -> +egpr,+ndd
-mno-apx-features=egpr,ndd -mapx-features=egpr -> -ndd,+egpr

The design is aligned with gcc
https://gcc.gnu.org/pipermail/gcc-patches/2023-August/628905.html

Positive options: -mapx-features=<comma-separated-features>
Negative options: -mno-apx-features=<comma-separated-features>

-m[no-]apx-features is designed to be able to control separate APX
features.

Besides, we also support the flag -m[no-]apxf, which can be used like an
alias of -m[no-]apx-features=< all APX features covered by CPUID APX_F>

Behaviour when positive and negative options are used together:

For boolean flags, the last one wins

-mapxf   -mno-apxf   -> -mno-apxf
-mno-apxf   -mapxf   -> -mapxf

For flags that take a set as arguments, it sets the mask by order of the
flags

-mapx-features=egpr,ndd  -mno-apx-features=egpr  ->   -egpr,+ndd
-mapx-features=egpr  -mno-apx-features=egpr,ndd  ->   -egpr,-ndd
-mno-apx-features=egpr  -mapx-features=egpr,ndd  ->   +egpr,+ndd
-mno-apx-features=egpr,ndd  -mapx-features=egpr  ->   -ndd,+egpr

The design is aligned with gcc
https://gcc.gnu.org/pipermail/gcc-patches/2023-August/628905.html
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:X86 clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Dec 2, 2023
@llvmbot
Copy link
Member

llvmbot commented Dec 2, 2023

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-backend-x86

Author: Shengchen Kan (KanRobert)

Changes

Positive options: -mapx-features=<comma-separated-features>
Negative options: -mno-apx-features=<comma-separated-features>

-m[no-]apx-features is designed to be able to control separate APX
features.

Besides, we also support the flag -m[no-]apxf, which can be used like an
alias of -m[no-]apx-features=< all APX features covered by CPUID APX_F>

Behaviour when positive and negative options are used together:

For boolean flags, the last one wins

-mapxf -mno-apxf -> -mno-apxf
-mno-apxf -mapxf -> -mapxf

For flags that take a set as arguments, it sets the mask by order of the
flags

-mapx-features=egpr,ndd -mno-apx-features=egpr -> -egpr,+ndd
-mapx-features=egpr -mno-apx-features=egpr,ndd -> -egpr,-ndd
-mno-apx-features=egpr -mapx-features=egpr,ndd -> +egpr,+ndd
-mno-apx-features=egpr,ndd -mapx-features=egpr -> -ndd,+egpr

The design is aligned with gcc
https://gcc.gnu.org/pipermail/gcc-patches/2023-August/628905.html


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

8 Files Affected:

  • (modified) clang/include/clang/Driver/Options.td (+6)
  • (modified) clang/lib/Basic/Targets/X86.cpp (+34)
  • (modified) clang/lib/Basic/Targets/X86.h (+6)
  • (modified) clang/lib/Driver/ToolChains/Arch/X86.cpp (+15)
  • (added) clang/test/Driver/apxf-target-features.c (+25)
  • (modified) llvm/include/llvm/TargetParser/X86TargetParser.def (+6)
  • (modified) llvm/lib/Target/X86/X86.td (+6)
  • (modified) llvm/lib/TargetParser/X86TargetParser.cpp (+8)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 19d04e82aed4d..631c5ad1c015d 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5999,6 +5999,12 @@ def mno_gather : Flag<["-"], "mno-gather">, Group<m_Group>,
                  HelpText<"Disable generation of gather instructions in auto-vectorization(x86 only)">;
 def mno_scatter : Flag<["-"], "mno-scatter">, Group<m_Group>,
                   HelpText<"Disable generation of scatter instructions in auto-vectorization(x86 only)">;
+def mapx_features_EQ : CommaJoined<["-"], "mapx-features=">, Group<m_x86_Features_Group>,
+    HelpText<"Enable features of APX">, Values<"egpr,push2pop2,ppx,ndd,ccmp,cf">;
+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,cf">;
+def mapxf : Flag<["-"], "mapxf">, Alias<mapx_features_EQ>, AliasArgs<["egpr","push2pop2","ppx","ndd","ccmp","cf"]>;
+def mno_apxf : Flag<["-"], "mno-apxf">, Alias<mno_apx_features_EQ>, AliasArgs<["egpr","push2pop2","ppx","ndd","ccmp","cf"]>;
 } // let Flags = [TargetSpecific]
 
 // VE feature flags
diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp
index 85d0697ad63ca..9392211aa6fdf 100644
--- a/clang/lib/Basic/Targets/X86.cpp
+++ b/clang/lib/Basic/Targets/X86.cpp
@@ -428,6 +428,18 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
       HasX87 = true;
     } else if (Feature == "+fullbf16") {
       HasFullBFloat16 = true;
+    } else if (Feature == "+egpr") {
+      HasEGPR = true;
+    } else if (Feature == "+push2pop2") {
+      HasPush2Pop2 = true;
+    } else if (Feature == "+ppx") {
+      HasPPX = true;
+    } else if (Feature == "+ndd") {
+      HasNDD = true;
+    } else if (Feature == "+ccmp") {
+      HasCCMP = true;
+    } else if (Feature == "+cf") {
+      HasCF = true;
     }
 
     X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature)
@@ -927,6 +939,16 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
     Builder.defineMacro("__USERMSR__");
   if (HasCRC32)
     Builder.defineMacro("__CRC32__");
+  if (HasEGPR)
+    Builder.defineMacro("__EGPR__");
+  if (HasPush2Pop2)
+    Builder.defineMacro("__PUSH2POP2__");
+  if (HasNDD)
+    Builder.defineMacro("__NDD__");
+  if (HasCCMP)
+    Builder.defineMacro("__CCMP__");
+  if (HasCF)
+    Builder.defineMacro("__CF__");
 
   // Each case falls through to the previous one here.
   switch (SSELevel) {
@@ -1122,6 +1144,12 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
       .Case("xsavec", true)
       .Case("xsaves", true)
       .Case("xsaveopt", true)
+      .Case("egpr", true)
+      .Case("push2pop2", true)
+      .Case("ppx", true)
+      .Case("ndd", true)
+      .Case("ccmp", true)
+      .Case("cf", true)
       .Default(false);
 }
 
@@ -1238,6 +1266,12 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
       .Case("xsaves", HasXSAVES)
       .Case("xsaveopt", HasXSAVEOPT)
       .Case("fullbf16", HasFullBFloat16)
+      .Case("egpr", HasEGPR)
+      .Case("push2pop2", HasPush2Pop2)
+      .Case("ppx", HasPPX)
+      .Case("ndd", HasNDD)
+      .Case("ccmp", HasCCMP)
+      .Case("cf", HasCF)
       .Default(false);
 }
 
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index 99a64501d263c..0ab1c10833db2 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -168,6 +168,12 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
   bool HasUINTR = false;
   bool HasCRC32 = false;
   bool HasX87 = false;
+  bool HasEGPR = false;
+  bool HasPush2Pop2 = false;
+  bool HasPPX = false;
+  bool HasNDD = false;
+  bool HasCCMP = false;
+  bool HasCF = false;
 
 protected:
   llvm::X86::CPUKind CPU = llvm::X86::CK_None;
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index fbe665bdd5c8a..3e51b2b5ce864 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -270,6 +270,21 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
     }
 
     bool IsNegative = Name.startswith("no-");
+    if (A->getOption().matches(options::OPT_mapx_features_EQ) ||
+        A->getOption().matches(options::OPT_mno_apx_features_EQ)) {
+
+      for (StringRef Value : A->getValues()) {
+        if (Value == "egpr" || Value == "push2pop2" || Value == "ppx" ||
+            Value == "ndd" || Value == "ccmp" || Value == "cf") {
+          Features.push_back(
+              Args.MakeArgString((IsNegative ? "-" : "+") + Value));
+          continue;
+        }
+        D.Diag(clang::diag::err_drv_unsupported_option_argument)
+            << A->getSpelling() << Value;
+      }
+      continue;
+    }
     if (IsNegative)
       Name = Name.substr(3);
     Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
diff --git a/clang/test/Driver/apxf-target-features.c b/clang/test/Driver/apxf-target-features.c
new file mode 100644
index 0000000000000..fa66b688f6220
--- /dev/null
+++ b/clang/test/Driver/apxf-target-features.c
@@ -0,0 +1,25 @@
+// RUN: %clang -target x86_64-unknown-linux-gnu -mapxf %s -### -o %t.o 2>&1 | FileCheck -check-prefix=APXF %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -mno-apxf %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-APXF %s
+// 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" "+cf"
+// NO-APXF: "-target-feature" "-egpr" "-target-feature" "-push2pop2" "-target-feature" "-ppx" "-target-feature" "-ndd" "-target-feature" "-ccmp" "-target-feature" "-cf"
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -mapx-features=egpr,ndd %s -### -o %t.o 2>&1 | FileCheck -check-prefix=EGPR-NDD %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -mapx-features=egpr -mapx-features=ndd %s -### -o %t.o 2>&1 | FileCheck -check-prefix=EGPR-NDD %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -mno-apx-features=egpr -mno-apx-features=ndd %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-EGPR-NO-NDD %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -mno-apx-features=egpr -mapx-features=egpr,ndd %s -### -o %t.o 2>&1 | FileCheck -check-prefix=EGPR-NDD %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -mno-apx-features=egpr,ndd -mapx-features=egpr %s -### -o %t.o 2>&1 | FileCheck -check-prefix=EGPR-NO-NDD %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -mapx-features=egpr,ndd -mno-apx-features=egpr %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-EGPR-NDD %s
+// RUN: %clang -target x86_64-unknown-linux-gnu -mapx-features=egpr -mno-apx-features=egpr,ndd %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-EGPR-NO-NDD %s
+//
+// EGPR-NDD: "-target-feature" "+egpr" "-target-feature" "+ndd"
+// EGPR-NO-NDD: "-target-feature" "-ndd" "-target-feature" "+egpr"
+// NO-EGPR-NDD: "-target-feature" "+ndd" "-target-feature" "-egpr"
+// NO-EGPR-NO-NDD: "-target-feature" "-egpr" "-target-feature" "-ndd"
+
+// RUN: not %clang -target x86_64-unknown-linux-gnu -mapx-features=egpr,foo,bar %s -### -o %t.o 2>&1 | FileCheck -check-prefix=ERROR %s
+//
+// ERROR: unsupported argument 'foo' to option '-mapx-features='
+// ERROR: unsupported argument 'bar' to option '-mapx-features='
diff --git a/llvm/include/llvm/TargetParser/X86TargetParser.def b/llvm/include/llvm/TargetParser/X86TargetParser.def
index 4204811a6a379..b58feafe4e8c2 100644
--- a/llvm/include/llvm/TargetParser/X86TargetParser.def
+++ b/llvm/include/llvm/TargetParser/X86TargetParser.def
@@ -246,6 +246,12 @@ X86_FEATURE       (EVEX512,         "evex512")
 X86_FEATURE       (AVX10_1,         "avx10.1-256")
 X86_FEATURE       (AVX10_1_512,     "avx10.1-512")
 X86_FEATURE       (USERMSR,         "usermsr")
+X86_FEATURE       (EGPR,            "egpr")
+X86_FEATURE       (Push2Pop2,       "push2pop2")
+X86_FEATURE       (PPX,             "ppx")
+X86_FEATURE       (NDD,             "ndd")
+X86_FEATURE       (CCMP,            "ccmp")
+X86_FEATURE       (CF,              "cf")
 // These features aren't really CPU features, but the frontend can set them.
 X86_FEATURE       (RETPOLINE_EXTERNAL_THUNK,    "retpoline-external-thunk")
 X86_FEATURE       (RETPOLINE_INDIRECT_BRANCHES, "retpoline-indirect-branches")
diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td
index 522d8513c9aff..5fd6828f43129 100644
--- a/llvm/lib/Target/X86/X86.td
+++ b/llvm/lib/Target/X86/X86.td
@@ -347,6 +347,12 @@ def FeaturePush2Pop2 : SubtargetFeature<"push2pop2", "HasPush2Pop2", "true",
                                         "Support PUSH2/POP2 instructions">;
 def FeaturePPX : SubtargetFeature<"ppx", "HasPPX", "true",
                                   "Support Push-Pop Acceleration">;
+def FeatureNDD : SubtargetFeature<"ndd", "HasNDD", "true",
+                                  "Support non-destructive destination">;
+def FeatureCCMP : SubtargetFeature<"ccmp", "HasCCMP", "true",
+                                   "Support conditional cmp & test instructions">;
+def FeatureCF : SubtargetFeature<"cf", "HasCF", "true",
+                                 "Support conditional faulting">;
 
 // Ivy Bridge and newer processors have enhanced REP MOVSB and STOSB (aka
 // "string operations"). See "REP String Enhancement" in the Intel Software
diff --git a/llvm/lib/TargetParser/X86TargetParser.cpp b/llvm/lib/TargetParser/X86TargetParser.cpp
index cde36021ee958..085554f18b2b6 100644
--- a/llvm/lib/TargetParser/X86TargetParser.cpp
+++ b/llvm/lib/TargetParser/X86TargetParser.cpp
@@ -628,6 +628,14 @@ constexpr FeatureBitset ImpliedFeaturesAVX10_1 =
 constexpr FeatureBitset ImpliedFeaturesAVX10_1_512 =
     FeatureAVX10_1 | FeatureEVEX512;
 
+// APX Features
+constexpr FeatureBitset ImpliedFeaturesEGPR = {};
+constexpr FeatureBitset ImpliedFeaturesPush2Pop2 = {};
+constexpr FeatureBitset ImpliedFeaturesPPX = {};
+constexpr FeatureBitset ImpliedFeaturesNDD = {};
+constexpr FeatureBitset ImpliedFeaturesCCMP = {};
+constexpr FeatureBitset ImpliedFeaturesCF = {};
+
 constexpr FeatureInfo FeatureInfos[X86::CPU_FEATURE_MAX] = {
 #define X86_FEATURE(ENUM, STR) {{"+" STR}, ImpliedFeatures##ENUM},
 #include "llvm/TargetParser/X86TargetParser.def"

Copy link
Contributor

@phoebewang phoebewang left a comment

Choose a reason for hiding this comment

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

LGTM.

@KanRobert
Copy link
Contributor Author

@phoebewang Thanks for the review!

@KanRobert KanRobert merged commit 6d6baef into llvm:main Dec 4, 2023
KanRobert added a commit that referenced this pull request May 11, 2024
KanRobert added a commit that referenced this pull request Jun 25, 2024
AlexisPerry pushed a commit to llvm-project-tlp/llvm-project that referenced this pull request Jul 9, 2024
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" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants