Skip to content

[PowerPC] frontend get target feature from backend with cpu name #137670

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 12 commits into from
Jun 12, 2025

Conversation

diggerlin
Copy link
Contributor

@diggerlin diggerlin commented Apr 28, 2025

  1. The PR proceeds with a backend target hook to allow front-ends to determine what target features are available in a compilation based on the CPU name.
  2. Fix a backend target feature bug that supports HTM for Power8/9/10/11. However, HTM is only supported on Power8/9 according to the ISA.
  3. All target features that are hardcoded in PPC.cpp can be retrieved from the backend target feature. I have double-checked that the hardcoded logic for inferring target features from the CPU in the frontend(PPC.cpp) is the same as in PPC.td.

@llvmbot llvmbot added clang Clang issues not falling into any other category backend:PowerPC clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" tablegen mc Machine (object) code labels Apr 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 28, 2025

@llvm/pr-subscribers-backend-powerpc
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-driver

Author: zhijian lin (diggerlin)

Changes
  1. The PR proceeds with a backend target hook to allow front-ends to determine what features are available in a compilation based on the CPU name.
  2. Fix a backend target feature bug that supports HTM for Power8/9/10/11. However, HTM is only supported on Power8/9 according to the ISA.
  3. All target features that are hardcoded in PPC.cpp can be retrieved from the backend target feature. I have double-checked that the hardcoded logic for inferring target features from the CPU in the frontend(PPC.cpp) is the same as in PPC.td.

Patch is 28.84 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/137670.diff

13 Files Affected:

  • (modified) clang/lib/Basic/Targets/PPC.cpp (+8-142)
  • (modified) clang/test/CodeGenCXX/cxx11-thread-local-reference.cpp (+1-1)
  • (modified) clang/test/Driver/aix-shared-lib-tls-model-opt.c (+3-4)
  • (modified) clang/test/Driver/aix-small-local-exec-dynamic-tls.c (+7-8)
  • (modified) clang/test/Driver/ppc-crbits.cpp (-4)
  • (modified) clang/test/Driver/ppc-isa-features.cpp (+11-11)
  • (modified) llvm/include/llvm/MC/MCSubtargetInfo.h (+25-7)
  • (modified) llvm/include/llvm/TargetParser/PPCTargetParser.h (+5)
  • (modified) llvm/lib/MC/MCSubtargetInfo.cpp (+28-4)
  • (modified) llvm/lib/Target/PowerPC/PPC.td (+2-2)
  • (modified) llvm/lib/TargetParser/CMakeLists.txt (+8)
  • (modified) llvm/lib/TargetParser/PPCTargetParser.cpp (+26)
  • (modified) llvm/utils/TableGen/SubtargetEmitter.cpp (+35-17)
diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp
index 425ad68bb9098..2a1024be1d537 100644
--- a/clang/lib/Basic/Targets/PPC.cpp
+++ b/clang/lib/Basic/Targets/PPC.cpp
@@ -15,6 +15,7 @@
 #include "clang/Basic/MacroBuilder.h"
 #include "clang/Basic/TargetBuiltins.h"
 #include "llvm/TargetParser/PPCTargetParser.h"
+#include <optional>
 
 using namespace clang;
 using namespace clang::targets;
@@ -516,130 +517,15 @@ static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags,
 bool PPCTargetInfo::initFeatureMap(
     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
     const std::vector<std::string> &FeaturesVec) const {
-  Features["altivec"] = llvm::StringSwitch<bool>(CPU)
-                            .Case("7400", true)
-                            .Case("g4", true)
-                            .Case("7450", true)
-                            .Case("g4+", true)
-                            .Case("970", true)
-                            .Case("g5", true)
-                            .Case("pwr6", true)
-                            .Case("pwr7", true)
-                            .Case("pwr8", true)
-                            .Case("pwr9", true)
-                            .Case("ppc64", true)
-                            .Case("ppc64le", true)
-                            .Default(false);
-
-  Features["power9-vector"] = (CPU == "pwr9");
-  Features["crypto"] = llvm::StringSwitch<bool>(CPU)
-                           .Case("ppc64le", true)
-                           .Case("pwr9", true)
-                           .Case("pwr8", true)
-                           .Default(false);
-  Features["power8-vector"] = llvm::StringSwitch<bool>(CPU)
-                                  .Case("ppc64le", true)
-                                  .Case("pwr9", true)
-                                  .Case("pwr8", true)
-                                  .Default(false);
-  Features["bpermd"] = llvm::StringSwitch<bool>(CPU)
-                           .Case("ppc64le", true)
-                           .Case("pwr9", true)
-                           .Case("pwr8", true)
-                           .Case("pwr7", true)
-                           .Default(false);
-  Features["extdiv"] = llvm::StringSwitch<bool>(CPU)
-                           .Case("ppc64le", true)
-                           .Case("pwr9", true)
-                           .Case("pwr8", true)
-                           .Case("pwr7", true)
-                           .Default(false);
-  Features["direct-move"] = llvm::StringSwitch<bool>(CPU)
-                                .Case("ppc64le", true)
-                                .Case("pwr9", true)
-                                .Case("pwr8", true)
-                                .Default(false);
-  Features["crbits"] = llvm::StringSwitch<bool>(CPU)
-                                .Case("ppc64le", true)
-                                .Case("pwr9", true)
-                                .Case("pwr8", true)
-                                .Default(false);
-  Features["vsx"] = llvm::StringSwitch<bool>(CPU)
-                        .Case("ppc64le", true)
-                        .Case("pwr9", true)
-                        .Case("pwr8", true)
-                        .Case("pwr7", true)
-                        .Default(false);
-  Features["htm"] = llvm::StringSwitch<bool>(CPU)
-                        .Case("ppc64le", true)
-                        .Case("pwr9", true)
-                        .Case("pwr8", true)
-                        .Default(false);
-
-  // ROP Protect is off by default.
-  Features["rop-protect"] = false;
-  // Privileged instructions are off by default.
-  Features["privileged"] = false;
 
-  if (getTriple().isOSAIX()) {
-    // The code generated by the -maix-small-local-[exec|dynamic]-tls option is
-    // turned off by default.
-    Features["aix-small-local-exec-tls"] = false;
-    Features["aix-small-local-dynamic-tls"] = false;
-
-    // Turn off TLS model opt by default.
-    Features["aix-shared-lib-tls-model-opt"] = false;
-  }
-
-  Features["spe"] = llvm::StringSwitch<bool>(CPU)
-                        .Case("8548", true)
-                        .Case("e500", true)
-                        .Default(false);
-
-  Features["isa-v206-instructions"] = llvm::StringSwitch<bool>(CPU)
-                                          .Case("ppc64le", true)
-                                          .Case("pwr9", true)
-                                          .Case("pwr8", true)
-                                          .Case("pwr7", true)
-                                          .Case("a2", true)
-                                          .Default(false);
-
-  Features["isa-v207-instructions"] = llvm::StringSwitch<bool>(CPU)
-                                          .Case("ppc64le", true)
-                                          .Case("pwr9", true)
-                                          .Case("pwr8", true)
-                                          .Default(false);
-
-  Features["isa-v30-instructions"] =
-      llvm::StringSwitch<bool>(CPU).Case("pwr9", true).Default(false);
-
-  Features["quadword-atomics"] =
-      getTriple().isArch64Bit() && llvm::StringSwitch<bool>(CPU)
-                                       .Case("pwr9", true)
-                                       .Case("pwr8", true)
-                                       .Default(false);
-
-  // Power10 includes all the same features as Power9 plus any features specific
-  // to the Power10 core.
-  if (CPU == "pwr10" || CPU == "power10") {
-    initFeatureMap(Features, Diags, "pwr9", FeaturesVec);
-    addP10SpecificFeatures(Features);
-  }
-
-  // Power11 includes all the same features as Power10 plus any features
-  // specific to the Power11 core.
-  if (CPU == "pwr11" || CPU == "power11") {
-    initFeatureMap(Features, Diags, "pwr10", FeaturesVec);
-    addP11SpecificFeatures(Features);
-  }
-
-  // Future CPU should include all of the features of Power 11 as well as any
-  // additional features (yet to be determined) specific to it.
-  if (CPU == "future") {
-    initFeatureMap(Features, Diags, "pwr11", FeaturesVec);
-    addFutureSpecificFeatures(Features);
-  }
+  const llvm::Triple &TheTriple = getTriple();
 
+  std::optional<llvm::StringMap<bool>> FeaturesOpt =
+      llvm::PPC::getPPCDefaultTargetFeatures(TheTriple,
+                                             llvm::PPC::normalizeCPUName(CPU));
+  if (FeaturesOpt.has_value())
+      Features = FeaturesOpt.value();
+  
   if (!ppcUserFeaturesCheck(Diags, FeaturesVec))
     return false;
 
@@ -694,26 +580,6 @@ bool PPCTargetInfo::initFeatureMap(
   return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
 }
 
-// Add any Power10 specific features.
-void PPCTargetInfo::addP10SpecificFeatures(
-    llvm::StringMap<bool> &Features) const {
-  Features["htm"] = false; // HTM was removed for P10.
-  Features["paired-vector-memops"] = true;
-  Features["mma"] = true;
-  Features["power10-vector"] = true;
-  Features["pcrelative-memops"] = true;
-  Features["prefix-instrs"] = true;
-  Features["isa-v31-instructions"] = true;
-}
-
-// Add any Power11 specific features.
-void PPCTargetInfo::addP11SpecificFeatures(
-    llvm::StringMap<bool> &Features) const {}
-
-// Add features specific to the "Future" CPU.
-void PPCTargetInfo::addFutureSpecificFeatures(
-    llvm::StringMap<bool> &Features) const {}
-
 bool PPCTargetInfo::hasFeature(StringRef Feature) const {
   return llvm::StringSwitch<bool>(Feature)
       .Case("powerpc", true)
diff --git a/clang/test/CodeGenCXX/cxx11-thread-local-reference.cpp b/clang/test/CodeGenCXX/cxx11-thread-local-reference.cpp
index cd5a18f39060e..a0e76e8a9a0b6 100644
--- a/clang/test/CodeGenCXX/cxx11-thread-local-reference.cpp
+++ b/clang/test/CodeGenCXX/cxx11-thread-local-reference.cpp
@@ -35,5 +35,5 @@ int &g() { return r; }
 // DARWIN-LABEL: define internal cxx_fast_tlscc void @__tls_init()
 // CHECK: call void @[[R_INIT]]()
 
-// LINUX_AIX: attributes [[ATTR0]] = { {{.*}}"target-features"{{.*}} }
+// LINUX_AIX: attributes [[ATTR0]] = { {{.*}} }
 // DARWIN: attributes [[ATTR1]] = { {{.*}}nounwind{{.*}}"target-features"{{.*}}  }
diff --git a/clang/test/Driver/aix-shared-lib-tls-model-opt.c b/clang/test/Driver/aix-shared-lib-tls-model-opt.c
index 7acf091f0a049..891caf4ed3fcd 100644
--- a/clang/test/Driver/aix-shared-lib-tls-model-opt.c
+++ b/clang/test/Driver/aix-shared-lib-tls-model-opt.c
@@ -1,5 +1,5 @@
-// RUN: %clang -target powerpc64-unknown-aix -S -emit-llvm %s -o - | FileCheck --check-prefixes=CHECK-AIX,CHECK-AIX-OFF %s
-// RUN: %clang -target powerpc-unknown-aix -S -emit-llvm %s -o - | FileCheck --check-prefixes=CHECK-AIX,CHECK-AIX-OFF %s
+// RUN: %clang -target powerpc64-unknown-aix -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-AIX %s
+// RUN: %clang -target powerpc-unknown-aix -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-AIX %s
 // RUN: %clang -target powerpc64le-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-LINUX %s
 // RUN: %clang -target powerpc64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-LINUX %s
 
@@ -19,9 +19,8 @@ int test(void) {
 
 // CHECK-AIX: test() #0 {
 // CHECK-AIX: attributes #0 = {
-// CHECK-AIX-OFF-SAME: -aix-shared-lib-tls-model-opt
 // CHECK-AIX-ON-SAME: +aix-shared-lib-tls-model-opt
 
-// CHECK-LINUX-NOT: {{[-+]aix-shared-lib-tls-model-opt}}
+// CHECK-LINUX-NOT: {{[+]aix-shared-lib-tls-model-opt}}
 
 // CHECK-UNSUPPORTED-TARGET: option '-maix-shared-lib-tls-model-opt' cannot be specified on this target
diff --git a/clang/test/Driver/aix-small-local-exec-dynamic-tls.c b/clang/test/Driver/aix-small-local-exec-dynamic-tls.c
index 1a0619b58e891..87250382f2357 100644
--- a/clang/test/Driver/aix-small-local-exec-dynamic-tls.c
+++ b/clang/test/Driver/aix-small-local-exec-dynamic-tls.c
@@ -1,7 +1,7 @@
-// RUN: %clang -target powerpc64-unknown-aix -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-AIX-DEFAULT %s
-// RUN: %clang -target powerpc-unknown-aix -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-AIX-DEFAULT %s
-// RUN: %clang -target powerpc64le-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-LINUX %s
-// RUN: %clang -target powerpc64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-LINUX %s
+// RUN: %clang -target powerpc64-unknown-aix -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-DEFAULT %s
+// RUN: %clang -target powerpc-unknown-aix -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-DEFAULT %s
+// RUN: %clang -target powerpc64le-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-DEFAULT %s
+// RUN: %clang -target powerpc64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-DEFAULT %s
 
 // RUN: %clang -target powerpc64-unknown-aix -maix-small-local-exec-tls -S -emit-llvm \
 // RUN:    %s -o - | FileCheck %s --check-prefix=CHECK-AIX_SMALL_LOCALEXEC_TLS
@@ -39,10 +39,9 @@ int test(void) {
   return 0;
 }
 
-// CHECK-AIX-DEFAULT: test() #0 {
-// CHECK-AIX-DEFAULT: attributes #0 = {
-// CHECK-AIX-DEFAULT-SAME: {{-aix-small-local-exec-tls,.*-aix-small-local-dynamic-tls|-aix-small-local-dynamic-tls,.*-aix-small-local-exec-tls}}
-// CHECK-LINUX-NOT: {{[-+]aix-small-local-exec-tls,.*[-+]aix-small-local-dynamic-tls|[-+]aix-small-local-dynamic-tls,.*[-+]aix-small-local-exec-tls}}
+// CHECK-DEFAULT: test() #0 {
+// CHECK-DEFAULT: attributes #0 = {
+// CHECK-DEFAULT-NOT: {{[-+]aix-small-local-exec-tls,.*[-+]aix-small-local-dynamic-tls|[-+]aix-small-local-dynamic-tls,.*[-+]aix-small-local-exec-tls}}
 
 // CHECK-UNSUPPORTED-AIX32: option '-maix-small-local-[exec|dynamic]-tls' cannot be specified on this target
 // CHECK-UNSUPPORTED-LINUX: option '-maix-small-local-[exec|dynamic]-tls' cannot be specified on this target
diff --git a/clang/test/Driver/ppc-crbits.cpp b/clang/test/Driver/ppc-crbits.cpp
index 3ed56308cb526..62893d3d0e87d 100644
--- a/clang/test/Driver/ppc-crbits.cpp
+++ b/clang/test/Driver/ppc-crbits.cpp
@@ -64,8 +64,6 @@
 // RUN: %clang -target powerpc64le-unknown-linux-gnu -mcpu=pwr8 -mno-crbits \
 // RUN:   -emit-llvm -S %s -o - | FileCheck %s --check-prefix=HAS-NOCRBITS
 
-// RUN: %clang -target powerpc64le-unknown-linux-gnu -mcpu=pwr7 -emit-llvm \
-// RUN:   -S %s -o - | FileCheck %s --check-prefix=HAS-NOCRBITS
 // RUN: %clang -target powerpc64le-unknown-linux-gnu -mcpu=pwr7 -mcrbits \
 // RUN:   -emit-llvm -S %s -o - | FileCheck %s --check-prefix=HAS-CRBITS
 // RUN: %clang -target powerpc64le-unknown-linux-gnu -mcpu=pwr7 -mno-crbits \
@@ -92,8 +90,6 @@
 // RUN: %clang -target powerpc-ibm-aix -mcpu=pwr8 -mno-crbits \
 // RUN:   -emit-llvm -S %s -o - | FileCheck %s --check-prefix=HAS-NOCRBITS
 
-// RUN: %clang -target powerpc-ibm-aix -mcpu=pwr7 -emit-llvm \
-// RUN:   -S %s -o - | FileCheck %s --check-prefix=HAS-NOCRBITS
 // RUN: %clang -target powerpc-ibm-aix -mcpu=pwr7 -mcrbits \
 // RUN:   -emit-llvm -S %s -o - | FileCheck %s --check-prefix=HAS-CRBITS
 // RUN: %clang -target powerpc-ibm-aix -mcpu=pwr7 -mno-crbits \
diff --git a/clang/test/Driver/ppc-isa-features.cpp b/clang/test/Driver/ppc-isa-features.cpp
index 92c5bc82f72b8..35dbfbcdf5699 100644
--- a/clang/test/Driver/ppc-isa-features.cpp
+++ b/clang/test/Driver/ppc-isa-features.cpp
@@ -5,20 +5,20 @@
 // RUN: %clang -target powerpc64-unknown-aix -mcpu=pwr9 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-PWR9
 // RUN: %clang -target powerpc-unknown-aix -mcpu=pwr10 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-PWR10
 
-// CHECK-PWR6: -isa-v206-instructions
-// CHECK-PWR6: -isa-v207-instructions
-// CHECK-PWR6: -isa-v30-instructions
+// CHECK-PWR6-NOT: isa-v206-instructions
+// CHECK-PWR6-NOT: isa-v207-instructions
+// CHECK-PWR6-NOT: isa-v30-instructions
 
-// CHECK-A2: +isa-v206-instructions
-// CHECK-A2: -isa-v207-instructions
-// CHECK-A2: -isa-v30-instructions
+// CHECK-A2:     +isa-v206-instructions
+// CHECK-A2-NOT: isa-v207-instructions
+// CHECK-A2-NOT: isa-v30-instructions
 
-// CHECK-PWR7: +isa-v206-instructions
-// CHECK-PWR7: -isa-v207-instructions
-// CHECK-PWR7: -isa-v30-instructions
+// CHECK-PWR7:     +isa-v206-instructions
+// CHECK-PWR7-NOT: isa-v207-instructions
+// CHECK-PWR7-NOT: isa-v30-instructions
 
-// CHECK-PWR8: +isa-v207-instructions
-// CHECK-PWR8: -isa-v30-instructions
+// CHECK-PWR8:     +isa-v207-instructions
+// CHECK-PWR8-NOT: isa-v30-instructions
 
 // CHECK-PWR9: +isa-v207-instructions
 // CHECK-PWR9: +isa-v30-instructions
diff --git a/llvm/include/llvm/MC/MCSubtargetInfo.h b/llvm/include/llvm/MC/MCSubtargetInfo.h
index 535bcfe2fb6d7..287aaf591c107 100644
--- a/llvm/include/llvm/MC/MCSubtargetInfo.h
+++ b/llvm/include/llvm/MC/MCSubtargetInfo.h
@@ -15,6 +15,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/MC/MCInstrItineraries.h"
 #include "llvm/MC/MCSchedule.h"
@@ -32,9 +33,8 @@ class MCInst;
 //===----------------------------------------------------------------------===//
 
 /// Used to provide key value pairs for feature and CPU bit flags.
-struct SubtargetFeatureKV {
+struct BasicSubtargetFeatureKV {
   const char *Key;                      ///< K-V key string
-  const char *Desc;                     ///< Help descriptor
   unsigned Value;                       ///< K-V integer value
   FeatureBitArray Implies;              ///< K-V bit mask
 
@@ -44,19 +44,27 @@ struct SubtargetFeatureKV {
   }
 
   /// Compare routine for std::is_sorted.
-  bool operator<(const SubtargetFeatureKV &Other) const {
+  bool operator<(const BasicSubtargetFeatureKV &Other) const {
     return StringRef(Key) < StringRef(Other.Key);
   }
+  BasicSubtargetFeatureKV(const char *Key, unsigned Value,
+                         FeatureBitArray Implies)
+      : Key(Key), Value(Value), Implies(Implies) {}
+};
+
+struct SubtargetFeatureKV : BasicSubtargetFeatureKV {
+  const char *Desc;                    ///< Help descriptor
+  SubtargetFeatureKV(const char *Key, const char *Desc, unsigned Value,
+                     FeatureBitArray Implies)
+      : BasicSubtargetFeatureKV(Key, Value, Implies), Desc(Desc) {}
 };
 
 //===----------------------------------------------------------------------===//
 
 /// Used to provide key value pairs for feature and CPU bit flags.
-struct SubtargetSubTypeKV {
+struct BasicSubtargetSubTypeKV {
   const char *Key;                      ///< K-V key string
   FeatureBitArray Implies;              ///< K-V bit mask
-  FeatureBitArray TuneImplies;          ///< K-V bit mask
-  const MCSchedModel *SchedModel;
 
   /// Compare routine for std::lower_bound
   bool operator<(StringRef S) const {
@@ -64,11 +72,21 @@ struct SubtargetSubTypeKV {
   }
 
   /// Compare routine for std::is_sorted.
-  bool operator<(const SubtargetSubTypeKV &Other) const {
+  bool operator<(const BasicSubtargetSubTypeKV &Other) const {
     return StringRef(Key) < StringRef(Other.Key);
   }
 };
 
+struct SubtargetSubTypeKV : BasicSubtargetSubTypeKV {
+  FeatureBitArray TuneImplies;	       ///< K-V bit mask
+  const MCSchedModel *SchedModel;
+};
+
+std::optional<llvm::StringMap<bool>>
+getCPUDefaultTargetFeatures(StringRef CPU,
+                            ArrayRef<BasicSubtargetSubTypeKV> ProcDesc,
+                            ArrayRef<BasicSubtargetFeatureKV> ProcFeatures);
+
 //===----------------------------------------------------------------------===//
 ///
 /// Generic base class for all target subtargets.
diff --git a/llvm/include/llvm/TargetParser/PPCTargetParser.h b/llvm/include/llvm/TargetParser/PPCTargetParser.h
index 5f9fe543aff0b..9018d6b919ebb 100644
--- a/llvm/include/llvm/TargetParser/PPCTargetParser.h
+++ b/llvm/include/llvm/TargetParser/PPCTargetParser.h
@@ -14,7 +14,9 @@
 #ifndef LLVM_TARGETPARSER_PPCTARGETPARSER_H
 #define LLVM_TARGETPARSER_PPCTARGETPARSER_H
 
+#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/TargetParser/Triple.h"
 
 namespace llvm {
@@ -34,6 +36,9 @@ StringRef getNormalizedPPCTuneCPU(const Triple &T, StringRef CPUName = "");
 // For PPC, there are some cpu names for same CPU, like pwr10 and power10,
 // normalize them.
 StringRef normalizeCPUName(StringRef CPUName);
+
+std::optional<llvm::StringMap<bool>>
+getPPCDefaultTargetFeatures(const Triple &T, StringRef CPUName);
 } // namespace PPC
 } // namespace llvm
 
diff --git a/llvm/lib/MC/MCSubtargetInfo.cpp b/llvm/lib/MC/MCSubtargetInfo.cpp
index d86eaad48420d..410ca55a53646 100644
--- a/llvm/lib/MC/MCSubtargetInfo.cpp
+++ b/llvm/lib/MC/MCSubtargetInfo.cpp
@@ -33,13 +33,13 @@ static const T *Find(StringRef S, ArrayRef<T> A) {
 }
 
 /// For each feature that is (transitively) implied by this feature, set it.
-static
-void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,
-                    ArrayRef<SubtargetFeatureKV> FeatureTable) {
+template <typename FeatureKVType>
+static void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,
+                           ArrayRef<FeatureKVType> FeatureTable) {
   // OR the Implies bits in outside the loop. This allows the Implies for CPUs
   // which might imply features not in FeatureTable to use this.
   Bits |= Implies;
-  for (const SubtargetFeatureKV &FE : FeatureTable)
+  for (const FeatureKVType &FE : FeatureTable)
     if (Implies.test(FE.Value))
       SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable);
 }
@@ -226,6 +226,30 @@ static FeatureBitset getFeatures(MCSubtargetInfo &STI, StringRef CPU,
   return Bits;
 }
 
+std::optional<llvm::StringMap<bool>> llvm::getCPUDefaultTargetFeatures(
+    StringRef CPU, ArrayRef<BasicSubtargetSubTypeKV> ProcDesc,
+    ArrayRef<BasicSubtargetFeatureKV> ProcFeatures) {
+  if (CPU.empty())
+    return std::nullopt;
+
+  const BasicSubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
+  if (!CPUEntry)
+    return std::nullopt;
+
+  // Set the features implied by this CPU feature if there is a match.
+  FeatureBitset Bits;
+  llvm::StringMap<bool> DefaultFeatures;
+  SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), ProcFeatures);
+
+  unsigned BitSize = Bits.size();
+  for (const BasicSubtargetFeatureKV &FE : ProcFeatures) {
+    assert(FE.Value < BitSize && "Target Feature is out of range");
+    if (Bits[FE.Value])
+      DefaultFeatures[FE.Key] = tr...
[truncated]

Copy link

github-actions bot commented Apr 28, 2025

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

// RUN: %clang -target powerpc-unknown-aix -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-AIX-DEFAULT %s
// RUN: %clang -target powerpc64le-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-LINUX %s
// RUN: %clang -target powerpc64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-LINUX %s
// RUN: %clang -target powerpc64-unknown-aix -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK-DEFAULT %s
Copy link
Member

Choose a reason for hiding this comment

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

If you are updating RUN lines with %clang, replace long deprecated -target with --target=

std::optional<llvm::StringMap<bool>> FeaturesOpt =
llvm::PPC::getPPCDefaultTargetFeatures(TheTriple,
llvm::PPC::normalizeCPUName(CPU));
if (FeaturesOpt.has_value())
Copy link
Member

Choose a reason for hiding this comment

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

for optional, it's more popular to just use if (xxx) and *xxx

@diggerlin diggerlin requested a review from MaskRay May 7, 2025 22:50
@diggerlin
Copy link
Contributor Author

Just a gentle follow-up — I’d truly appreciate any feedback when you have a moment.

@diggerlin diggerlin requested a review from amy-kwan May 15, 2025 18:36
Copy link
Member

@daltenty daltenty left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

Copy link
Contributor

@amy-kwan amy-kwan left a comment

Choose a reason for hiding this comment

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

I think I do not have any further comments, LGTM.

@@ -16,6 +16,7 @@

#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCSubtargetInfo.h"
Copy link
Member

@MaskRay MaskRay Jun 3, 2025

Choose a reason for hiding this comment

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

Since MC depends on TargetParser, TargetParser should not include MC/ headers. https://llvm.org/docs/CodingStandards.html#library-layering

With CMake, certain problems can be detected with BUILD_SHARED_LIBS=on. The unofficial bazel can usually more reliably catch such violations.

Copy link
Member

Choose a reason for hiding this comment

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

@diggerlin This is blocking and should be addressed before landing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I addressed your comment , would you help to take a look again? @MaskRay

@diggerlin diggerlin requested a review from MaskRay June 3, 2025 20:37
@diggerlin
Copy link
Contributor Author

@MaskRay, Just checking in to see if you have any further comments on the patch. If not, I’d like to go ahead and proceed with landing it. Thanks!

@@ -18,6 +18,53 @@
using namespace llvm;
using namespace AMDGPU;

/// Find KV in array using binary search.
static const BasicSubtargetSubTypeKV *
Find(StringRef S, ArrayRef<BasicSubtargetSubTypeKV> A) {
Copy link
Member

Choose a reason for hiding this comment

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

find (functionName in new code)

}

/// For each feature that is (transitively) implied by this feature, set it.
static void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,
Copy link
Member

Choose a reason for hiding this comment

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

setImpliedBits

@diggerlin diggerlin merged commit 9208b34 into llvm:main Jun 12, 2025
7 checks passed
set(LLVM_TARGET_DEFINITIONS ${LLVM_MAIN_SRC_DIR}/lib/Target/PowerPC/PPC.td)

tablegen(LLVM PPCGenSubtargetInfo.inc -gen-subtarget -I${LLVM_MAIN_SRC_DIR}/lib/Target/PowerPC)
add_public_tablegen_target(PPCGenSubtargetInfo)
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like there is a missing dependency between LLVMTargetParser and PPCGenSubtargetInfo now. I see the following build error:

llvm/lib/TargetParser/PPCTargetParser.cpp:20:10: fatal error: PPCGenSubtargetInfo.inc: No such file or directory
   20 | #include "PPCGenSubtargetInfo.inc"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, I do see add_dependencies below now. So maybe it is a red herring, and my cmake config phase did not work out well.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Reusing the generated subtarget info doesn't seem right to me. I would feel more comfortable if this were handled along the same lines as the other Targets, which generate defs in the include/.../TargetParser directory:
https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/TargetParser/CMakeLists.txt

Let me roll this back for now to mitigate the risk of missing CMake dependencies.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did a clean build when I worked on the patch and never encountered the above problem. I also checked the build bot, and it looks like the build bot is green for this patch. Can you give me a hint on how to reproduce your problem? @vzakhari

Copy link
Contributor Author

@diggerlin diggerlin Jun 17, 2025

Choose a reason for hiding this comment

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

Reusing the generated subtarget info doesn't seem right to me. I would feel more comfortable if this were handled along the same lines as the other Targets, which generate defs in the include/.../TargetParser directory: https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/TargetParser/CMakeLists.txt

Let me roll this back for now to mitigate the risk of missing CMake dependencies.

I create the patch #144594 to address your comment. @rnk

rnk added a commit that referenced this pull request Jun 12, 2025
…name (#137670)"

This reverts commit 9208b34.

TargetParser shouldn't re-run the PPC subtarget tablegen target, it
should define its own `-gen-ppc-target-def` rule like all the other
targets do in llvm/include/llvm/TargetParser/CMakeLists.txt .

One user reported that there are incorrect CMake dependencies after this
change, so I will roll this back in the meantime.
tomtor pushed a commit to tomtor/llvm-project that referenced this pull request Jun 14, 2025
…vm#137670)

1. The PR proceeds with a backend target hook to allow front-ends to
determine what target features are available in a compilation based on
the CPU name.
2. Fix a backend target feature bug that supports HTM for
Power8/9/10/11. However, HTM is only supported on Power8/9 according to
the ISA.
3. All target features that are hardcoded in PPC.cpp can be retrieved
from the backend target feature. I have double-checked that the
hardcoded logic for inferring target features from the CPU in the
frontend(PPC.cpp) is the same as in PPC.td.
tomtor pushed a commit to tomtor/llvm-project that referenced this pull request Jun 14, 2025
…name (llvm#137670)"

This reverts commit 9208b34.

TargetParser shouldn't re-run the PPC subtarget tablegen target, it
should define its own `-gen-ppc-target-def` rule like all the other
targets do in llvm/include/llvm/TargetParser/CMakeLists.txt .

One user reported that there are incorrect CMake dependencies after this
change, so I will roll this back in the meantime.
diggerlin added a commit that referenced this pull request Jun 19, 2025
…name (#144594)

1. The PR proceeds with a backend target hook to allow front-ends to
determine what target features are available in a compilation based on
the CPU name.
2. Fix a backend target feature bug that supports HTM for
Power8/9/10/11. However, HTM is only supported on Power8/9 according to
the ISA.
3. All target features that are hardcoded in PPC.cpp can be retrieved
from the backend target feature. I have double-checked that the
hardcoded logic for inferring target features from the CPU in the
frontend(PPC.cpp) is the same as in PPC.td.

The reland patch addressed the comment
#137670 (comment)
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Jun 19, 2025
…d with cpu name (#144594)

1. The PR proceeds with a backend target hook to allow front-ends to
determine what target features are available in a compilation based on
the CPU name.
2. Fix a backend target feature bug that supports HTM for
Power8/9/10/11. However, HTM is only supported on Power8/9 according to
the ISA.
3. All target features that are hardcoded in PPC.cpp can be retrieved
from the backend target feature. I have double-checked that the
hardcoded logic for inferring target features from the CPU in the
frontend(PPC.cpp) is the same as in PPC.td.

The reland patch addressed the comment
llvm/llvm-project#137670 (comment)
akuhlens pushed a commit to akuhlens/llvm-project that referenced this pull request Jun 24, 2025
…vm#137670)

1. The PR proceeds with a backend target hook to allow front-ends to
determine what target features are available in a compilation based on
the CPU name.
2. Fix a backend target feature bug that supports HTM for
Power8/9/10/11. However, HTM is only supported on Power8/9 according to
the ISA.
3. All target features that are hardcoded in PPC.cpp can be retrieved
from the backend target feature. I have double-checked that the
hardcoded logic for inferring target features from the CPU in the
frontend(PPC.cpp) is the same as in PPC.td.
akuhlens pushed a commit to akuhlens/llvm-project that referenced this pull request Jun 24, 2025
…name (llvm#137670)"

This reverts commit 9208b34.

TargetParser shouldn't re-run the PPC subtarget tablegen target, it
should define its own `-gen-ppc-target-def` rule like all the other
targets do in llvm/include/llvm/TargetParser/CMakeLists.txt .

One user reported that there are incorrect CMake dependencies after this
change, so I will roll this back in the meantime.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:PowerPC 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 mc Machine (object) code tablegen
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants