[clang] [llvm] [PowerPC] frontend get target feature from backend with cpu name (PR #137670)
zhijian lin via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 28 10:11:46 PDT 2025
https://github.com/diggerlin created https://github.com/llvm/llvm-project/pull/137670
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.
>From 97f10e6a0fb4c158359e79e24650f8fdf4d23ef2 Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Fri, 25 Apr 2025 13:09:47 +0000
Subject: [PATCH] implement getting target features from backend for clang
frontend
---
clang/lib/Basic/Targets/PPC.cpp | 150 +-----------------
.../cxx11-thread-local-reference.cpp | 2 +-
.../Driver/aix-shared-lib-tls-model-opt.c | 7 +-
.../Driver/aix-small-local-exec-dynamic-tls.c | 15 +-
clang/test/Driver/ppc-crbits.cpp | 4 -
clang/test/Driver/ppc-isa-features.cpp | 22 +--
llvm/include/llvm/MC/MCSubtargetInfo.h | 32 +++-
.../llvm/TargetParser/PPCTargetParser.h | 5 +
llvm/lib/MC/MCSubtargetInfo.cpp | 32 +++-
llvm/lib/Target/PowerPC/PPC.td | 4 +-
llvm/lib/TargetParser/CMakeLists.txt | 8 +
llvm/lib/TargetParser/PPCTargetParser.cpp | 26 +++
llvm/utils/TableGen/SubtargetEmitter.cpp | 52 ++++--
13 files changed, 159 insertions(+), 200 deletions(-)
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] = true;
+ }
+ return DefaultFeatures;
+}
+
void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef TuneCPU,
StringRef FS) {
FeatureBits =
diff --git a/llvm/lib/Target/PowerPC/PPC.td b/llvm/lib/Target/PowerPC/PPC.td
index 39da428461393..8e1204d574db0 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);
@@ -444,7 +444,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/CMakeLists.txt b/llvm/lib/TargetParser/CMakeLists.txt
index 8ec32f7410566..543524be2f30e 100644
--- a/llvm/lib/TargetParser/CMakeLists.txt
+++ b/llvm/lib/TargetParser/CMakeLists.txt
@@ -8,6 +8,12 @@ if (HAS_WERROR_GLOBAL_CTORS AND NOT LLVM_HAS_NOGLOBAL_CTOR_MUTEX)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=global-constructors")
endif()
+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)
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
# Solaris code uses kstat, so specify dependency explicitly for shared builds.
if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
set(system_libs kstat)
@@ -43,3 +49,5 @@ add_llvm_component_library(LLVMTargetParser
AArch64TargetParserTableGen
RISCVTargetParserTableGen
)
+
+add_dependencies(LLVMTargetParser PPCGenSubtargetInfo)
diff --git a/llvm/lib/TargetParser/PPCTargetParser.cpp b/llvm/lib/TargetParser/PPCTargetParser.cpp
index 422d758c772e1..bd460c7091fd3 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_SUBTARGETINFO_ENUM
+#define GET_SUBTARGETFEATURES_KV
+#include "PPCGenSubtargetInfo.inc"
+
namespace llvm {
namespace PPC {
@@ -117,5 +121,27 @@ 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 enabled by llvm back-end for
+ // power8 or power8 up, we disable the target feature if the triple is
+ // 32-bit.
+ if (Features.find("quadword-atomics") != Features.end() && !T.isArch64Bit())
+ Features["quadword-atomics"] = false;
+ return Features;
+}
} // namespace PPC
} // namespace llvm
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
index 8d2fc99f84670..be1409f651ef4 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -90,8 +90,10 @@ class SubtargetEmitter {
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);
+ unsigned featureKeyValues(raw_ostream &OS, const FeatureMapTy &FeatureMap,
+ bool IsEmitBasic = false);
+ unsigned cpuKeyValues(raw_ostream &OS, const FeatureMapTy &FeatureMap,
+ bool IsEmitBasic = false);
unsigned cpuNames(raw_ostream &OS);
void formItineraryStageString(const std::string &Names,
const Record *ItinData, std::string &ItinString,
@@ -255,7 +257,8 @@ void SubtargetEmitter::emitSubtargetInfoMacroCalls(raw_ostream &OS) {
// command line.
//
unsigned SubtargetEmitter::featureKeyValues(raw_ostream &OS,
- const FeatureMapTy &FeatureMap) {
+ const FeatureMapTy &FeatureMap,
+ bool IsEmitBasic) {
std::vector<const Record *> FeatureList =
Records.getAllDerivedDefinitions("SubtargetFeature");
@@ -271,8 +274,8 @@ unsigned SubtargetEmitter::featureKeyValues(raw_ostream &OS,
// Begin feature table.
OS << "// Sorted (by key) array of values for CPU features.\n"
- << "extern const llvm::SubtargetFeatureKV " << Target
- << "FeatureKV[] = {\n";
+ << "extern const llvm::" << (IsEmitBasic ? "Basic" : "") << "SubtargetFeatureKV "
+ << (IsEmitBasic ? "Basic" : "") << Target << "FeatureKV[] = {\n";
for (const Record *Feature : FeatureList) {
// Next feature
@@ -282,9 +285,11 @@ unsigned SubtargetEmitter::featureKeyValues(raw_ostream &OS,
// Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in
// } }
- OS << " { "
- << "\"" << CommandLineName << "\", "
- << "\"" << Desc << "\", " << Target << "::" << Name << ", ";
+ OS << " { " << "\"" << CommandLineName << "\", ";
+ if (!IsEmitBasic)
+ OS << "\"" << Desc << "\", ";
+
+ OS << Target << "::" << Name << ", ";
ConstRecVec ImpliesList = Feature->getValueAsListOfDefs("Implies");
@@ -338,7 +343,8 @@ unsigned SubtargetEmitter::cpuNames(raw_ostream &OS) {
// line.
//
unsigned SubtargetEmitter::cpuKeyValues(raw_ostream &OS,
- const FeatureMapTy &FeatureMap) {
+ const FeatureMapTy &FeatureMap,
+ bool IsEmitBasic) {
// Gather and sort processor information
std::vector<const Record *> ProcessorList =
Records.getAllDerivedDefinitions("Processor");
@@ -351,8 +357,8 @@ unsigned SubtargetEmitter::cpuKeyValues(raw_ostream &OS,
// Begin processor table.
OS << "// Sorted (by key) array of values for CPU subtype.\n"
- << "extern const llvm::SubtargetSubTypeKV " << Target
- << "SubTypeKV[] = {\n";
+ << "extern const llvm::" << (IsEmitBasic ? "Basic" : "") << "SubtargetSubTypeKV "
+ << (IsEmitBasic ? "Basic" : "") << Target << "SubTypeKV[] = {\n";
for (const Record *Processor : ProcessorList) {
StringRef Name = Processor->getValueAsString("Name");
@@ -365,13 +371,17 @@ unsigned SubtargetEmitter::cpuKeyValues(raw_ostream &OS,
<< "\"" << Name << "\", ";
printFeatureMask(OS, FeatureList, FeatureMap);
- OS << ", ";
- printFeatureMask(OS, TuneFeatureList, FeatureMap);
- // Emit the scheduler model pointer.
- const std::string &ProcModelName =
- SchedModels.getModelForProc(Processor).ModelName;
- OS << ", &" << ProcModelName << " },\n";
+ if (!IsEmitBasic) {
+ OS << ", ";
+ printFeatureMask(OS, TuneFeatureList, FeatureMap);
+
+ // Emit the scheduler model pointer.
+ const std::string &ProcModelName =
+ SchedModels.getModelForProc(Processor).ModelName;
+ OS << ", &" << ProcModelName;
+ }
+ OS << " },\n";
}
// End processor table.
@@ -2013,6 +2023,14 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "} // end namespace llvm\n\n";
OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
+ OS << "\n#ifdef GET_SUBTARGETFEATURES_KV\n";
+ OS << "#undef GET_SUBTARGETFEATURES_KV\n\n";
+ OS << "namespace llvm {\n";
+ featureKeyValues(OS, FeatureMap, true);
+ cpuKeyValues(OS, FeatureMap, true);
+ OS << "} // end namespace llvm\n\n";
+ OS << "#endif // GET_SUBTARGETFEATURES_KV\n\n";
+
emitSubtargetInfoMacroCalls(OS);
OS << "namespace llvm {\n";
More information about the cfe-commits
mailing list