https://github.com/diggerlin updated 
https://github.com/llvm/llvm-project/pull/144594

>From 2d0f536bdc6fc24f09053569a8c84056ffc31e0d Mon Sep 17 00:00:00 2001
From: zhijian lin <zhij...@ca.ibm.com>
Date: Thu, 12 Jun 2025 13:38:13 -0400
Subject: [PATCH 1/4]  [PowerPC] frontend get target feature from backend with
 cpu name

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.
---
 clang/lib/Basic/Targets/PPC.cpp               | 148 +-----------------
 .../cxx11-thread-local-reference.cpp          |   2 +-
 .../Driver/aix-shared-lib-tls-model-opt.c     |   7 +-
 .../Driver/aix-small-local-exec-dynamic-tls.c |  39 +++--
 clang/test/Driver/ppc-crbits.cpp              |   4 -
 clang/test/Driver/ppc-isa-features.cpp        |  22 +--
 llvm/include/llvm/TargetParser/CMakeLists.txt |   3 +
 .../llvm/TargetParser/PPCTargetParser.h       |   6 +
 llvm/include/llvm/TargetParser/TargetParser.h |  27 ++++
 llvm/lib/Target/PowerPC/PPC.td                |   4 +-
 llvm/lib/TargetParser/PPCTargetParser.cpp     |  25 +++
 llvm/lib/TargetParser/TargetParser.cpp        |  47 ++++++
 llvm/utils/TableGen/Basic/CMakeLists.txt      |   1 +
 13 files changed, 152 insertions(+), 183 deletions(-)

diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp
index e6ef0ecc526ba..77145e2891a8a 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,129 +517,14 @@ 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);
-  }
+  const llvm::Triple &TheTriple = getTriple();
 
-  // 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);
-  }
+  std::optional<llvm::StringMap<bool>> FeaturesOpt =
+      llvm::PPC::getPPCDefaultTargetFeatures(TheTriple,
+                                             llvm::PPC::normalizeCPUName(CPU));
+  if (FeaturesOpt)
+    Features = FeaturesOpt.value();
 
   if (!ppcUserFeaturesCheck(Diags, FeaturesVec))
     return false;
@@ -700,26 +586,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..6fc2b8efb4aed 100644
--- a/clang/test/Driver/aix-small-local-exec-dynamic-tls.c
+++ b/clang/test/Driver/aix-small-local-exec-dynamic-tls.c
@@ -1,37 +1,37 @@
-// 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: %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
 
-// RUN: %clang -target powerpc64-unknown-aix -maix-small-local-dynamic-tls -S 
-emit-llvm \
+// RUN: %clang --target=powerpc64-unknown-aix -maix-small-local-dynamic-tls -S 
-emit-llvm \
 // RUN:    %s -o - | FileCheck %s 
--check-prefix=CHECK-AIX_SMALL_LOCALDYNAMIC_TLS
 
-// RUN: not %clang -target powerpc-unknown-aix -maix-small-local-exec-tls \
+// RUN: not %clang --target=powerpc-unknown-aix -maix-small-local-exec-tls \
 // RUN:    -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=CHECK-UNSUPPORTED-AIX32 %s
-// RUN: not %clang -target powerpc64le-unknown-linux-gnu 
-maix-small-local-exec-tls \
+// RUN: not %clang --target=powerpc64le-unknown-linux-gnu 
-maix-small-local-exec-tls \
 // RUN:    -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=CHECK-UNSUPPORTED-LINUX %s
-// RUN: not %clang -target powerpc64-unknown-linux-gnu 
-maix-small-local-exec-tls \
+// RUN: not %clang --target=powerpc64-unknown-linux-gnu 
-maix-small-local-exec-tls \
 // RUN:    -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=CHECK-UNSUPPORTED-LINUX %s
-// RUN: not %clang -target powerpc64-unknown-aix -maix-small-local-exec-tls \
+// RUN: not %clang --target=powerpc64-unknown-aix -maix-small-local-exec-tls \
 // RUN:    -fsyntax-only -fno-data-sections %s 2>&1 | \
 // RUN:    FileCheck --check-prefix=CHECK-UNSUPPORTED-NO-DATASEC %s
-// RUN: not %clang -target powerpc64-unknown-linux-gnu 
-maix-small-local-exec-tls \
+// RUN: not %clang --target=powerpc64-unknown-linux-gnu 
-maix-small-local-exec-tls \
 // RUN:    -fsyntax-only -fno-data-sections %s 2>&1 | \
 // RUN:    FileCheck --check-prefix=CHECK-UNSUPPORTED-NO-DATASEC %s
 
-// RUN: not %clang -target powerpc-unknown-aix -maix-small-local-dynamic-tls \
+// RUN: not %clang --target=powerpc-unknown-aix -maix-small-local-dynamic-tls \
 // RUN:    -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=CHECK-UNSUPPORTED-AIX32 %s
-// RUN: not %clang -target powerpc64le-unknown-linux-gnu 
-maix-small-local-dynamic-tls \
+// RUN: not %clang --target=powerpc64le-unknown-linux-gnu 
-maix-small-local-dynamic-tls \
 // RUN:    -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=CHECK-UNSUPPORTED-LINUX %s
-// RUN: not %clang -target powerpc64-unknown-linux-gnu 
-maix-small-local-dynamic-tls \
+// RUN: not %clang --target=powerpc64-unknown-linux-gnu 
-maix-small-local-dynamic-tls \
 // RUN:    -fsyntax-only %s 2>&1 | FileCheck 
--check-prefix=CHECK-UNSUPPORTED-LINUX %s
-// RUN: not %clang -target powerpc64-unknown-aix -maix-small-local-dynamic-tls 
\
+// RUN: not %clang --target=powerpc64-unknown-aix 
-maix-small-local-dynamic-tls \
 // RUN:    -fsyntax-only -fno-data-sections %s 2>&1 | \
 // RUN:    FileCheck --check-prefix=CHECK-UNSUPPORTED-NO-DATASEC %s
-// RUN: not %clang -target powerpc64-unknown-linux-gnu 
-maix-small-local-dynamic-tls \
+// RUN: not %clang --target=powerpc64-unknown-linux-gnu 
-maix-small-local-dynamic-tls \
 // RUN:    -fsyntax-only -fno-data-sections %s 2>&1 | \
 // RUN:    FileCheck --check-prefix=CHECK-UNSUPPORTED-NO-DATASEC %s
 
@@ -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/TargetParser/CMakeLists.txt 
b/llvm/include/llvm/TargetParser/CMakeLists.txt
index b456da66a022f..bb6d58d74a35c 100644
--- a/llvm/include/llvm/TargetParser/CMakeLists.txt
+++ b/llvm/include/llvm/TargetParser/CMakeLists.txt
@@ -7,5 +7,8 @@ tablegen(LLVM AArch64TargetParserDef.inc -gen-arm-target-def -I 
${PROJECT_SOURCE
 set(LLVM_TARGET_DEFINITIONS ${PROJECT_SOURCE_DIR}/lib/Target/RISCV/RISCV.td)
 tablegen(LLVM RISCVTargetParserDef.inc -gen-riscv-target-def -I 
${PROJECT_SOURCE_DIR}/lib/Target/RISCV/)
 
+set(LLVM_TARGET_DEFINITIONS ${PROJECT_SOURCE_DIR}/lib/Target/PowerPC/PPC.td)
+tablegen(LLVM PPCGenTargetFeatures.inc -gen-target-features 
-I${PROJECT_SOURCE_DIR}/lib/Target/PowerPC)
+
 # This covers all of the tablegen calls above.
 add_public_tablegen_target(target_parser_gen)
diff --git a/llvm/include/llvm/TargetParser/PPCTargetParser.h 
b/llvm/include/llvm/TargetParser/PPCTargetParser.h
index 59d9f867005a4..d3d44afb5f544 100644
--- a/llvm/include/llvm/TargetParser/PPCTargetParser.h
+++ b/llvm/include/llvm/TargetParser/PPCTargetParser.h
@@ -14,6 +14,8 @@
 #ifndef LLVM_TARGETPARSER_PPCTARGETPARSER_H
 #define LLVM_TARGETPARSER_PPCTARGETPARSER_H
 
+#include "TargetParser.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/TargetParser/Triple.h"
@@ -37,6 +39,10 @@ LLVM_ABI StringRef getNormalizedPPCTuneCPU(const Triple &T,
 // For PPC, there are some cpu names for same CPU, like pwr10 and power10,
 // normalize them.
 LLVM_ABI StringRef normalizeCPUName(StringRef CPUName);
+
+LLVM_ABI std::optional<llvm::StringMap<bool>>
+getPPCDefaultTargetFeatures(const Triple &T, StringRef CPUName);
+
 } // namespace PPC
 } // namespace llvm
 
diff --git a/llvm/include/llvm/TargetParser/TargetParser.h 
b/llvm/include/llvm/TargetParser/TargetParser.h
index 176205e17ae00..b4a92cc6b6c4b 100644
--- a/llvm/include/llvm/TargetParser/TargetParser.h
+++ b/llvm/include/llvm/TargetParser/TargetParser.h
@@ -14,6 +14,8 @@
 #ifndef LLVM_TARGETPARSER_TARGETPARSER_H
 #define LLVM_TARGETPARSER_TARGETPARSER_H
 
+#include "SubtargetFeature.h"
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
@@ -190,6 +192,31 @@ insertWaveSizeFeature(StringRef GPU, const Triple &T,
                       StringMap<bool> &Features);
 
 } // namespace AMDGPU
+
+struct BasicSubtargetFeatureKV {
+  const char *Key;         ///< K-V key string
+  unsigned Value;          ///< K-V integer value
+  FeatureBitArray Implies; ///< K-V bit mask
+};
+
+/// Used to provide key value pairs for feature and CPU bit flags.
+struct BasicSubtargetSubTypeKV {
+  const char *Key;         ///< K-V key string
+  FeatureBitArray Implies; ///< K-V bit mask
+
+  /// Compare routine for std::lower_bound
+  bool operator<(StringRef S) const { return StringRef(Key) < S; }
+
+  /// Compare routine for std::is_sorted.
+  bool operator<(const BasicSubtargetSubTypeKV &Other) const {
+    return StringRef(Key) < StringRef(Other.Key);
+  }
+};
+
+std::optional<llvm::StringMap<bool>>
+getCPUDefaultTargetFeatures(StringRef CPU,
+                            ArrayRef<BasicSubtargetSubTypeKV> ProcDesc,
+                            ArrayRef<BasicSubtargetFeatureKV> ProcFeatures);
 } // namespace llvm
 
 #endif
diff --git a/llvm/lib/Target/PowerPC/PPC.td b/llvm/lib/Target/PowerPC/PPC.td
index fd850faf7b2fb..ea7c2203662bd 100644
--- a/llvm/lib/Target/PowerPC/PPC.td
+++ b/llvm/lib/Target/PowerPC/PPC.td
@@ -411,7 +411,6 @@ def ProcessorFeatures {
      FeatureP8Altivec,
      FeatureP8Vector,
      FeatureP8Crypto,
-     FeatureHTM,
      FeatureDirectMove,
      FeatureICBT,
      FeaturePartwordAtomic,
@@ -422,6 +421,7 @@ def ProcessorFeatures {
     ];
 
   list<SubtargetFeature> P8SpecificFeatures = [FeatureAddiLoadFusion,
+                                               FeatureHTM,
                                                FeatureAddisLoadFusion];
   list<SubtargetFeature> P8InheritableFeatures =
     !listconcat(P7InheritableFeatures, P8AdditionalFeatures);
@@ -443,7 +443,7 @@ def ProcessorFeatures {
   // dispatch for vector operations than scalar ones. For the time being,
   // this list also includes scheduling-related features since we do not have
   // enough info to create custom scheduling strategies for future CPUs.
-  list<SubtargetFeature> P9SpecificFeatures = [FeatureVectorsUseTwoUnits];
+  list<SubtargetFeature> P9SpecificFeatures = [FeatureVectorsUseTwoUnits, 
FeatureHTM];
   list<SubtargetFeature> P9InheritableFeatures =
     !listconcat(P8InheritableFeatures, P9AdditionalFeatures);
   list<SubtargetFeature> P9Features =
diff --git a/llvm/lib/TargetParser/PPCTargetParser.cpp 
b/llvm/lib/TargetParser/PPCTargetParser.cpp
index 422d758c772e1..d51044529a49d 100644
--- a/llvm/lib/TargetParser/PPCTargetParser.cpp
+++ b/llvm/lib/TargetParser/PPCTargetParser.cpp
@@ -15,6 +15,10 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/TargetParser/Host.h"
 
+#define GET_SUBTARGETFEATURES_ENUM
+#define GET_SUBTARGETFEATURES_KV
+#include "llvm/TargetParser/PPCGenTargetFeatures.inc"
+
 namespace llvm {
 namespace PPC {
 
@@ -117,5 +121,26 @@ StringRef getNormalizedPPCTuneCPU(const Triple &T, 
StringRef CPUName) {
   return getNormalizedPPCTargetCPU(T, CPUName);
 }
 
+std::optional<StringMap<bool>> getPPCDefaultTargetFeatures(const Triple &T,
+                                                           StringRef CPU) {
+  std::optional<StringMap<bool>> FeaturesOpt =
+      getCPUDefaultTargetFeatures(CPU, BasicPPCSubTypeKV, BasicPPCFeatureKV);
+
+  if (!FeaturesOpt.has_value())
+    return std::nullopt;
+
+  StringMap<bool> Features = FeaturesOpt.value();
+  // FIXME: We need to check for the processor model 8548, since the backend
+  // does not support this processor. When this processor model is implemented
+  // within the backend, the following code can be removed.
+  if (CPU == "8548")
+    Features["spe"] = true;
+
+  // The target feature `quadword-atomics` is only supported for 64-bit
+  // POWER8 and above.
+  if (Features.find("quadword-atomics") != Features.end() && !T.isArch64Bit())
+    Features["quadword-atomics"] = false;
+  return Features;
+}
 } // namespace PPC
 } // namespace llvm
diff --git a/llvm/lib/TargetParser/TargetParser.cpp 
b/llvm/lib/TargetParser/TargetParser.cpp
index 7c54901dae47d..03f7d3899c2e7 100644
--- a/llvm/lib/TargetParser/TargetParser.cpp
+++ b/llvm/lib/TargetParser/TargetParser.cpp
@@ -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) {
+  // Binary search the array
+  auto F = llvm::lower_bound(A, S);
+  // If not found then return NULL
+  if (F == A.end() || StringRef(F->Key) != S)
+    return nullptr;
+  // Return the found array item
+  return F;
+}
+
+/// For each feature that is (transitively) implied by this feature, set it.
+static void setImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,
+                           ArrayRef<BasicSubtargetFeatureKV> 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 auto &FE : FeatureTable)
+    if (Implies.test(FE.Value))
+      setImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable);
+}
+
+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] = true;
+  }
+  return DefaultFeatures;
+}
+
 namespace {
 
 struct GPUInfo {
diff --git a/llvm/utils/TableGen/Basic/CMakeLists.txt 
b/llvm/utils/TableGen/Basic/CMakeLists.txt
index b058fba78eb05..7d0f3b3f4f6aa 100644
--- a/llvm/utils/TableGen/Basic/CMakeLists.txt
+++ b/llvm/utils/TableGen/Basic/CMakeLists.txt
@@ -18,6 +18,7 @@ add_llvm_library(LLVMTableGenBasic OBJECT EXCLUDE_FROM_ALL 
DISABLE_LLVM_LINK_LLV
   SDNodeProperties.cpp
   TableGen.cpp
   VTEmitter.cpp
+  EmitTargetFeature.cpp
 )
 
 # Users may include its headers as "Basic/*.h"

>From 67f239f46352202c171d2e1e2bc7a92e9f6d8f6c Mon Sep 17 00:00:00 2001
From: zhijian <zhij...@ca.ibm.com>
Date: Tue, 17 Jun 2025 20:09:22 +0000
Subject: [PATCH 2/4] add a new option -gen-target-features

---
 .../TableGen/Basic/EmitTargetFeature.cpp      | 191 ++++++++++++++++++
 1 file changed, 191 insertions(+)
 create mode 100644 llvm/utils/TableGen/Basic/EmitTargetFeature.cpp

diff --git a/llvm/utils/TableGen/Basic/EmitTargetFeature.cpp 
b/llvm/utils/TableGen/Basic/EmitTargetFeature.cpp
new file mode 100644
index 0000000000000..c73f4124c4e02
--- /dev/null
+++ b/llvm/utils/TableGen/Basic/EmitTargetFeature.cpp
@@ -0,0 +1,191 @@
+//===- EmitTargetFeature.cpp - Generate CPU Targer feature ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  This tablegen backend exports cpu target features
+//  and cpu sub-type for all platform.  
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
+
+using namespace llvm;
+
+using FeatureMapTy = DenseMap<const Record *, unsigned>;
+using ConstRecVec = std::vector<const Record *>;
+
+struct LessRecordFieldNameAndID {
+  bool operator()(const Record *Rec1, const Record *Rec2) const {
+    return std::tuple(Rec1->getValueAsString("Name"), Rec1->getID()) <
+           std::tuple(Rec2->getValueAsString("Name"), Rec2->getID());
+  }
+};
+
+static StringRef getTargetName(const RecordKeeper &Records) {
+  ArrayRef<const Record *> Targets = 
Records.getAllDerivedDefinitions("Target");
+  if (Targets.size() == 0)
+    PrintFatalError("No 'Target' subclasses defined!");
+  if (Targets.size() != 1)
+    PrintFatalError("Multiple subclasses of Target defined!");
+  return Targets[0]->getName();
+}
+
+static FeatureMapTy enumeration(const RecordKeeper &Records, raw_ostream &OS) {
+  ArrayRef<const Record *> DefList =
+      Records.getAllDerivedDefinitions("SubtargetFeature");
+
+  unsigned N = DefList.size();
+  if (N == 0)
+    return FeatureMapTy();
+
+  if (N + 1 > MAX_SUBTARGET_FEATURES)
+    PrintFatalError(
+        "Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
+
+  StringRef Target = getTargetName(Records);
+
+  OS << "namespace " << Target << " {\n";
+
+  OS << "enum {\n";
+
+  FeatureMapTy FeatureMap;
+  for (unsigned I = 0; I < N; ++I) {
+    const Record *Def = DefList[I];
+    // Print the Feature Name.
+    OS << "  " << Def->getName() << " = " << I << ",\n";
+
+    FeatureMap[Def] = I;
+  }
+
+  OS << "  " << "NumSubtargetFeatures = " << N << "\n";
+
+  // Close enumeration and namespace
+  OS << "};\n";
+  OS << "} // end namespace " << Target << "\n";
+  return FeatureMap;
+}
+
+static void printFeatureMask(raw_ostream &OS,
+                             ArrayRef<const Record *> FeatureList,
+                             const FeatureMapTy &FeatureMap) {
+  std::array<uint64_t, MAX_SUBTARGET_WORDS> Mask = {};
+  for (const Record *Feature : FeatureList) {
+    unsigned Bit = FeatureMap.lookup(Feature);
+    Mask[Bit / 64] |= 1ULL << (Bit % 64);
+  }
+
+  OS << "{ { { ";
+  for (unsigned I = 0; I != Mask.size(); ++I) {
+    OS << "0x";
+    OS.write_hex(Mask[I]);
+    OS << "ULL, ";
+  }
+  OS << "} } }";
+}
+
+static void printFeatureKeyValues(const RecordKeeper &Records, raw_ostream &OS,
+                                  const FeatureMapTy &FeatureMap) {
+  std::vector<const Record *> FeatureList =
+      Records.getAllDerivedDefinitions("SubtargetFeature");
+
+  // Remove features with empty name.
+  llvm::erase_if(FeatureList, [](const Record *Rec) {
+    return Rec->getValueAsString("Name").empty();
+  });
+
+  if (FeatureList.empty())
+    return;
+
+  llvm::sort(FeatureList, LessRecordFieldNameAndID());
+
+  StringRef Target = getTargetName(Records);
+  // Begin feature table.
+  OS << "// Sorted (by key) array of values for CPU features.\n"
+     << "extern const llvm::BasicSubtargetFeatureKV " << "Basic" << Target
+     << "FeatureKV[] = {\n";
+
+  for (const Record *Feature : FeatureList) {
+    StringRef Name = Feature->getName();
+    StringRef ValueName = Feature->getValueAsString("Name");
+
+    OS << "  { " << "\"" << ValueName << "\", " << Target << "::" << Name
+       << ", ";
+
+    ConstRecVec ImpliesList = Feature->getValueAsListOfDefs("Implies");
+
+    printFeatureMask(OS, ImpliesList, FeatureMap);
+
+    OS << " },\n";
+  }
+
+  // End feature table.
+  OS << "};\n";
+
+  return;
+}
+
+void printCPUKeyValues(const RecordKeeper &Records, raw_ostream &OS,
+                       const FeatureMapTy &FeatureMap) {
+  // Gather and sort processor information
+  std::vector<const Record *> ProcessorList =
+      Records.getAllDerivedDefinitions("Processor");
+  llvm::sort(ProcessorList, LessRecordFieldName());
+
+  StringRef Target = getTargetName(Records);
+
+  // Begin processor table.
+  OS << "// Sorted (by key) array of values for CPU subtype.\n"
+     << "extern const llvm::BasicSubtargetSubTypeKV " << "Basic" << Target
+     << "SubTypeKV[] = {\n";
+
+  for (const Record *Processor : ProcessorList) {
+    StringRef Name = Processor->getValueAsString("Name");
+    ConstRecVec FeatureList = Processor->getValueAsListOfDefs("Features");
+
+    OS << " { " << "\"" << Name << "\", ";
+
+    printFeatureMask(OS, FeatureList, FeatureMap);
+    OS << " },\n";
+  }
+
+  // End processor table.
+  OS << "};\n";
+
+  return;
+}
+
+static void emitTargetFeature(const RecordKeeper &RK, raw_ostream &OS) {
+  OS << "// Autogenerated by TargetFeatureEmitter.cpp\n\n";
+
+  OS << "\n#ifdef GET_SUBTARGETFEATURES_ENUM\n";
+  OS << "#undef GET_SUBTARGETFEATURES_ENUM\n\n";
+
+  OS << "namespace llvm {\n";
+  auto FeatureMap = enumeration(RK, OS);
+  OS << "} // end namespace llvm\n\n";
+  OS << "#endif // GET_SUBTARGETFEATURES_ENUM\n\n";
+
+  OS << "\n#ifdef GET_SUBTARGETFEATURES_KV\n";
+  OS << "#undef GET_SUBTARGETFEATURES_KV\n\n";
+
+  OS << "namespace llvm {\n";
+  printFeatureKeyValues(RK, OS, FeatureMap);
+  OS << "\n";
+
+  printCPUKeyValues(RK, OS, FeatureMap);
+  OS << "\n";
+  OS << "} // end namespace llvm\n\n";
+  OS << "#endif // GET_SUBTARGETFEATURES_KV\n\n";
+}
+
+static TableGen::Emitter::Opt
+    X("gen-target-features", emitTargetFeature,
+      "Generate the default Target features and CPU sub types");

>From 7df292d6e57680329515b5f081d8e55fd3393959 Mon Sep 17 00:00:00 2001
From: zhijian <zhij...@ca.ibm.com>
Date: Tue, 17 Jun 2025 20:44:28 +0000
Subject: [PATCH 3/4] minor change

---
 llvm/utils/TableGen/Basic/EmitTargetFeature.cpp | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/llvm/utils/TableGen/Basic/EmitTargetFeature.cpp 
b/llvm/utils/TableGen/Basic/EmitTargetFeature.cpp
index c73f4124c4e02..61c4698cfdcda 100644
--- a/llvm/utils/TableGen/Basic/EmitTargetFeature.cpp
+++ b/llvm/utils/TableGen/Basic/EmitTargetFeature.cpp
@@ -1,4 +1,4 @@
-//===- EmitTargetFeature.cpp - Generate CPU Targer feature ----===//
+//===- EmitTargetFeature.cpp - Generate CPU Target feature ----===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +7,7 @@
 
//===----------------------------------------------------------------------===//
 //
 //  This tablegen backend exports cpu target features
-//  and cpu sub-type for all platform.  
+//  and cpu sub-type.
 //
 
//===----------------------------------------------------------------------===//
 
@@ -22,7 +22,7 @@ using namespace llvm;
 using FeatureMapTy = DenseMap<const Record *, unsigned>;
 using ConstRecVec = std::vector<const Record *>;
 
-struct LessRecordFieldNameAndID {
+struct lessRecordFieldNameAndID {
   bool operator()(const Record *Rec1, const Record *Rec2) const {
     return std::tuple(Rec1->getValueAsString("Name"), Rec1->getID()) <
            std::tuple(Rec2->getValueAsString("Name"), Rec2->getID());
@@ -38,7 +38,8 @@ static StringRef getTargetName(const RecordKeeper &Records) {
   return Targets[0]->getName();
 }
 
-static FeatureMapTy enumeration(const RecordKeeper &Records, raw_ostream &OS) {
+static FeatureMapTy enumerationFeatures(const RecordKeeper &Records,
+                                        raw_ostream &OS) {
   ArrayRef<const Record *> DefList =
       Records.getAllDerivedDefinitions("SubtargetFeature");
 
@@ -67,7 +68,7 @@ static FeatureMapTy enumeration(const RecordKeeper &Records, 
raw_ostream &OS) {
 
   OS << "  " << "NumSubtargetFeatures = " << N << "\n";
 
-  // Close enumeration and namespace
+  // Close enumerationFeatures and namespace
   OS << "};\n";
   OS << "} // end namespace " << Target << "\n";
   return FeatureMap;
@@ -104,7 +105,7 @@ static void printFeatureKeyValues(const RecordKeeper 
&Records, raw_ostream &OS,
   if (FeatureList.empty())
     return;
 
-  llvm::sort(FeatureList, LessRecordFieldNameAndID());
+  llvm::sort(FeatureList, lessRecordFieldNameAndID());
 
   StringRef Target = getTargetName(Records);
   // Begin feature table.
@@ -169,7 +170,7 @@ static void emitTargetFeature(const RecordKeeper &RK, 
raw_ostream &OS) {
   OS << "#undef GET_SUBTARGETFEATURES_ENUM\n\n";
 
   OS << "namespace llvm {\n";
-  auto FeatureMap = enumeration(RK, OS);
+  auto FeatureMap = enumerationFeatures(RK, OS);
   OS << "} // end namespace llvm\n\n";
   OS << "#endif // GET_SUBTARGETFEATURES_ENUM\n\n";
 

>From c92ac11dfffeb8da8a45bba8c7f5838c372dae35 Mon Sep 17 00:00:00 2001
From: zhijian <zhij...@ca.ibm.com>
Date: Wed, 18 Jun 2025 18:14:28 +0000
Subject: [PATCH 4/4] address comment: refactore to reuse the code

---
 llvm/utils/TableGen/Basic/CMakeLists.txt      |  2 +-
 ...tFeature.cpp => TargetFeaturesEmitter.cpp} | 55 +++++-------
 .../TableGen/Basic/TargetFeaturesEmitter.h    | 49 +++++++++++
 llvm/utils/TableGen/SubtargetEmitter.cpp      | 84 +------------------
 4 files changed, 74 insertions(+), 116 deletions(-)
 rename llvm/utils/TableGen/Basic/{EmitTargetFeature.cpp => 
TargetFeaturesEmitter.cpp} (72%)
 create mode 100644 llvm/utils/TableGen/Basic/TargetFeaturesEmitter.h

diff --git a/llvm/utils/TableGen/Basic/CMakeLists.txt 
b/llvm/utils/TableGen/Basic/CMakeLists.txt
index 7d0f3b3f4f6aa..1f4d3a7bc123c 100644
--- a/llvm/utils/TableGen/Basic/CMakeLists.txt
+++ b/llvm/utils/TableGen/Basic/CMakeLists.txt
@@ -17,8 +17,8 @@ add_llvm_library(LLVMTableGenBasic OBJECT EXCLUDE_FROM_ALL 
DISABLE_LLVM_LINK_LLV
   RISCVTargetDefEmitter.cpp
   SDNodeProperties.cpp
   TableGen.cpp
+  TargetFeaturesEmitter.cpp
   VTEmitter.cpp
-  EmitTargetFeature.cpp
 )
 
 # Users may include its headers as "Basic/*.h"
diff --git a/llvm/utils/TableGen/Basic/EmitTargetFeature.cpp 
b/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp
similarity index 72%
rename from llvm/utils/TableGen/Basic/EmitTargetFeature.cpp
rename to llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp
index 61c4698cfdcda..85293a5fbf77f 100644
--- a/llvm/utils/TableGen/Basic/EmitTargetFeature.cpp
+++ b/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp
@@ -1,4 +1,4 @@
-//===- EmitTargetFeature.cpp - Generate CPU Target feature ----===//
+//===- TargetFeaturesEmitter.cpp - Generate CPU Target feature ----===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -11,9 +11,8 @@
 //
 
//===----------------------------------------------------------------------===//
 
-#include "llvm/ADT/DenseMap.h"
+#include "TargetFeaturesEmitter.h"
 #include "llvm/TableGen/Error.h"
-#include "llvm/TableGen/Record.h"
 #include "llvm/TableGen/TableGenBackend.h"
 #include "llvm/TargetParser/SubtargetFeature.h"
 
@@ -22,24 +21,16 @@ using namespace llvm;
 using FeatureMapTy = DenseMap<const Record *, unsigned>;
 using ConstRecVec = std::vector<const Record *>;
 
-struct lessRecordFieldNameAndID {
-  bool operator()(const Record *Rec1, const Record *Rec2) const {
-    return std::tuple(Rec1->getValueAsString("Name"), Rec1->getID()) <
-           std::tuple(Rec2->getValueAsString("Name"), Rec2->getID());
-  }
-};
-
-static StringRef getTargetName(const RecordKeeper &Records) {
+TargetFeaturesEmitter::TargetFeaturesEmitter(const RecordKeeper &R) : 
Records(R) {
   ArrayRef<const Record *> Targets = 
Records.getAllDerivedDefinitions("Target");
   if (Targets.size() == 0)
     PrintFatalError("No 'Target' subclasses defined!");
   if (Targets.size() != 1)
     PrintFatalError("Multiple subclasses of Target defined!");
-  return Targets[0]->getName();
+  Target = Targets[0]->getName();
 }
 
-static FeatureMapTy enumerationFeatures(const RecordKeeper &Records,
-                                        raw_ostream &OS) {
+FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) {
   ArrayRef<const Record *> DefList =
       Records.getAllDerivedDefinitions("SubtargetFeature");
 
@@ -51,8 +42,6 @@ static FeatureMapTy enumerationFeatures(const RecordKeeper 
&Records,
     PrintFatalError(
         "Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
 
-  StringRef Target = getTargetName(Records);
-
   OS << "namespace " << Target << " {\n";
 
   OS << "enum {\n";
@@ -68,15 +57,15 @@ static FeatureMapTy enumerationFeatures(const RecordKeeper 
&Records,
 
   OS << "  " << "NumSubtargetFeatures = " << N << "\n";
 
-  // Close enumerationFeatures and namespace
+  // Close enumeration and namespace
   OS << "};\n";
   OS << "} // end namespace " << Target << "\n";
   return FeatureMap;
 }
 
-static void printFeatureMask(raw_ostream &OS,
-                             ArrayRef<const Record *> FeatureList,
-                             const FeatureMapTy &FeatureMap) {
+void TargetFeaturesEmitter::printFeatureMask(raw_ostream &OS,
+                                         ArrayRef<const Record *> FeatureList,
+                                         const FeatureMapTy &FeatureMap) {
   std::array<uint64_t, MAX_SUBTARGET_WORDS> Mask = {};
   for (const Record *Feature : FeatureList) {
     unsigned Bit = FeatureMap.lookup(Feature);
@@ -92,8 +81,8 @@ static void printFeatureMask(raw_ostream &OS,
   OS << "} } }";
 }
 
-static void printFeatureKeyValues(const RecordKeeper &Records, raw_ostream &OS,
-                                  const FeatureMapTy &FeatureMap) {
+void TargetFeaturesEmitter::printFeatureKeyValues(raw_ostream &OS,
+                                              const FeatureMapTy &FeatureMap) {
   std::vector<const Record *> FeatureList =
       Records.getAllDerivedDefinitions("SubtargetFeature");
 
@@ -105,9 +94,8 @@ static void printFeatureKeyValues(const RecordKeeper 
&Records, raw_ostream &OS,
   if (FeatureList.empty())
     return;
 
-  llvm::sort(FeatureList, lessRecordFieldNameAndID());
+  llvm::sort(FeatureList, LessRecordFieldName());
 
-  StringRef Target = getTargetName(Records);
   // Begin feature table.
   OS << "// Sorted (by key) array of values for CPU features.\n"
      << "extern const llvm::BasicSubtargetFeatureKV " << "Basic" << Target
@@ -133,15 +121,13 @@ static void printFeatureKeyValues(const RecordKeeper 
&Records, raw_ostream &OS,
   return;
 }
 
-void printCPUKeyValues(const RecordKeeper &Records, raw_ostream &OS,
-                       const FeatureMapTy &FeatureMap) {
+void TargetFeaturesEmitter::printCPUKeyValues(raw_ostream &OS,
+                                          const FeatureMapTy &FeatureMap) {
   // Gather and sort processor information
   std::vector<const Record *> ProcessorList =
       Records.getAllDerivedDefinitions("Processor");
   llvm::sort(ProcessorList, LessRecordFieldName());
 
-  StringRef Target = getTargetName(Records);
-
   // Begin processor table.
   OS << "// Sorted (by key) array of values for CPU subtype.\n"
      << "extern const llvm::BasicSubtargetSubTypeKV " << "Basic" << Target
@@ -163,14 +149,14 @@ void printCPUKeyValues(const RecordKeeper &Records, 
raw_ostream &OS,
   return;
 }
 
-static void emitTargetFeature(const RecordKeeper &RK, raw_ostream &OS) {
+void TargetFeaturesEmitter::run(raw_ostream &OS) {
   OS << "// Autogenerated by TargetFeatureEmitter.cpp\n\n";
 
   OS << "\n#ifdef GET_SUBTARGETFEATURES_ENUM\n";
   OS << "#undef GET_SUBTARGETFEATURES_ENUM\n\n";
 
   OS << "namespace llvm {\n";
-  auto FeatureMap = enumerationFeatures(RK, OS);
+  auto FeatureMap = enumeration(OS);
   OS << "} // end namespace llvm\n\n";
   OS << "#endif // GET_SUBTARGETFEATURES_ENUM\n\n";
 
@@ -178,15 +164,14 @@ static void emitTargetFeature(const RecordKeeper &RK, 
raw_ostream &OS) {
   OS << "#undef GET_SUBTARGETFEATURES_KV\n\n";
 
   OS << "namespace llvm {\n";
-  printFeatureKeyValues(RK, OS, FeatureMap);
+  printFeatureKeyValues(OS, FeatureMap);
   OS << "\n";
 
-  printCPUKeyValues(RK, OS, FeatureMap);
+  printCPUKeyValues(OS, FeatureMap);
   OS << "\n";
   OS << "} // end namespace llvm\n\n";
   OS << "#endif // GET_SUBTARGETFEATURES_KV\n\n";
 }
 
-static TableGen::Emitter::Opt
-    X("gen-target-features", emitTargetFeature,
-      "Generate the default Target features and CPU sub types");
+static TableGen::Emitter::OptClass<TargetFeaturesEmitter>
+    X("gen-target-features", "Generate subtarget enumerations");
diff --git a/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.h 
b/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.h
new file mode 100644
index 0000000000000..b8a2150a4c542
--- /dev/null
+++ b/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.h
@@ -0,0 +1,49 @@
+//===- TargetFeaturesEmitter.h- Generate CPU Target features ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the TargetFeaturesEmitter class, which is used to export
+// CPU target features and CPU subtypes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_BASIC_EMITTARGETFEATURE_H
+#define LLVM_UTILS_TABLEGEN_BASIC_EMITTARGETFEATURE_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/TableGen/Record.h"
+
+namespace llvm {
+/// Sorting predicate to sort record pointers by their
+/// FieldName field.
+struct LessRecordFieldFieldName {
+  bool operator()(const Record *Rec1, const Record *Rec2) const {
+    return Rec1->getValueAsString("FieldName") <
+           Rec2->getValueAsString("FieldName");
+  }
+};
+
+using FeatureMapTy = DenseMap<const Record *, unsigned>;
+
+class TargetFeaturesEmitter {
+protected:
+  const RecordKeeper &Records;
+  std::string Target;
+
+public:
+  TargetFeaturesEmitter(const RecordKeeper &R);
+  static void printFeatureMask(raw_ostream &OS,
+                               ArrayRef<const Record *> FeatureList,
+                               const FeatureMapTy &FeatureMap);
+  FeatureMapTy enumeration(raw_ostream &OS);
+  void printFeatureKeyValues(raw_ostream &OS, const FeatureMapTy &FeatureMap);
+  void printCPUKeyValues(raw_ostream &OS, const FeatureMapTy &FeatureMap);
+  virtual void run(raw_ostream &O);
+  virtual ~TargetFeaturesEmitter(){};
+};
+} // namespace llvm
+#endif
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp 
b/llvm/utils/TableGen/SubtargetEmitter.cpp
index ca008e256a70f..77618b24cf115 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -10,12 +10,12 @@
 //
 
//===----------------------------------------------------------------------===//
 
+#include "Basic/TargetFeaturesEmitter.h"
 #include "Common/CodeGenHwModes.h"
 #include "Common/CodeGenSchedule.h"
 #include "Common/CodeGenTarget.h"
 #include "Common/PredicateExpander.h"
 #include "Common/Utils.h"
-#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/StringExtras.h"
@@ -27,9 +27,7 @@
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TableGen/Error.h"
-#include "llvm/TableGen/Record.h"
 #include "llvm/TableGen/TableGenBackend.h"
-#include "llvm/TargetParser/SubtargetFeature.h"
 #include <algorithm>
 #include <cassert>
 #include <cstdint>
@@ -43,18 +41,7 @@ using namespace llvm;
 
 namespace {
 
-using FeatureMapTy = DenseMap<const Record *, unsigned>;
-
-/// Sorting predicate to sort record pointers by their
-/// FieldName field.
-struct LessRecordFieldFieldName {
-  bool operator()(const Record *Rec1, const Record *Rec2) const {
-    return Rec1->getValueAsString("FieldName") <
-           Rec2->getValueAsString("FieldName");
-  }
-};
-
-class SubtargetEmitter {
+class SubtargetEmitter : TargetFeaturesEmitter {
   // Each processor has a SchedClassDesc table with an entry for each
   // SchedClass. The SchedClassDesc table indexes into a global write resource
   // table, write latency table, and read advance table.
@@ -83,11 +70,8 @@ class SubtargetEmitter {
   };
 
   CodeGenTarget TGT;
-  const RecordKeeper &Records;
   CodeGenSchedModels &SchedModels;
-  std::string Target;
 
-  FeatureMapTy enumeration(raw_ostream &OS);
   void emitSubtargetInfoMacroCalls(raw_ostream &OS);
   unsigned featureKeyValues(raw_ostream &OS, const FeatureMapTy &FeatureMap);
   unsigned cpuKeyValues(raw_ostream &OS, const FeatureMapTy &FeatureMap);
@@ -143,73 +127,13 @@ class SubtargetEmitter {
 
 public:
   SubtargetEmitter(const RecordKeeper &R)
-      : TGT(R), Records(R), SchedModels(TGT.getSchedModels()),
-        Target(TGT.getName()) {}
+      : TargetFeaturesEmitter(R), TGT(R), SchedModels(TGT.getSchedModels()) {}
 
-  void run(raw_ostream &O);
+  void run(raw_ostream &O) override;
 };
 
 } // end anonymous namespace
 
-//
-// Enumeration - Emit the specified class as an enumeration.
-//
-FeatureMapTy SubtargetEmitter::enumeration(raw_ostream &OS) {
-  ArrayRef<const Record *> DefList =
-      Records.getAllDerivedDefinitions("SubtargetFeature");
-
-  unsigned N = DefList.size();
-  if (N == 0)
-    return FeatureMapTy();
-  if (N + 1 > MAX_SUBTARGET_FEATURES)
-    PrintFatalError(
-        "Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
-
-  OS << "namespace " << Target << " {\n";
-
-  // Open enumeration.
-  OS << "enum {\n";
-
-  FeatureMapTy FeatureMap;
-  // For each record
-  for (unsigned I = 0; I < N; ++I) {
-    // Next record
-    const Record *Def = DefList[I];
-
-    // Get and emit name
-    OS << "  " << Def->getName() << " = " << I << ",\n";
-
-    // Save the index for this feature.
-    FeatureMap[Def] = I;
-  }
-
-  OS << "  "
-     << "NumSubtargetFeatures = " << N << "\n";
-
-  // Close enumeration and namespace
-  OS << "};\n";
-  OS << "} // end namespace " << Target << "\n";
-  return FeatureMap;
-}
-
-static void printFeatureMask(raw_ostream &OS,
-                             ArrayRef<const Record *> FeatureList,
-                             const FeatureMapTy &FeatureMap) {
-  std::array<uint64_t, MAX_SUBTARGET_WORDS> Mask = {};
-  for (const Record *Feature : FeatureList) {
-    unsigned Bit = FeatureMap.lookup(Feature);
-    Mask[Bit / 64] |= 1ULL << (Bit % 64);
-  }
-
-  OS << "{ { { ";
-  for (unsigned I = 0; I != Mask.size(); ++I) {
-    OS << "0x";
-    OS.write_hex(Mask[I]);
-    OS << "ULL, ";
-  }
-  OS << "} } }";
-}
-
 /// Emit some information about the SubtargetFeature as calls to a macro so
 /// that they can be used from C++.
 void SubtargetEmitter::emitSubtargetInfoMacroCalls(raw_ostream &OS) {

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to