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 using namespace clang; using namespace clang::targets; @@ -516,129 +517,14 @@ static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags, bool PPCTargetInfo::initFeatureMap( llvm::StringMap &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector &FeaturesVec) const { - Features["altivec"] = llvm::StringSwitch(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(CPU) - .Case("ppc64le", true) - .Case("pwr9", true) - .Case("pwr8", true) - .Default(false); - Features["power8-vector"] = llvm::StringSwitch(CPU) - .Case("ppc64le", true) - .Case("pwr9", true) - .Case("pwr8", true) - .Default(false); - Features["bpermd"] = llvm::StringSwitch(CPU) - .Case("ppc64le", true) - .Case("pwr9", true) - .Case("pwr8", true) - .Case("pwr7", true) - .Default(false); - Features["extdiv"] = llvm::StringSwitch(CPU) - .Case("ppc64le", true) - .Case("pwr9", true) - .Case("pwr8", true) - .Case("pwr7", true) - .Default(false); - Features["direct-move"] = llvm::StringSwitch(CPU) - .Case("ppc64le", true) - .Case("pwr9", true) - .Case("pwr8", true) - .Default(false); - Features["crbits"] = llvm::StringSwitch(CPU) - .Case("ppc64le", true) - .Case("pwr9", true) - .Case("pwr8", true) - .Default(false); - Features["vsx"] = llvm::StringSwitch(CPU) - .Case("ppc64le", true) - .Case("pwr9", true) - .Case("pwr8", true) - .Case("pwr7", true) - .Default(false); - Features["htm"] = llvm::StringSwitch(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(CPU) - .Case("8548", true) - .Case("e500", true) - .Default(false); - - Features["isa-v206-instructions"] = llvm::StringSwitch(CPU) - .Case("ppc64le", true) - .Case("pwr9", true) - .Case("pwr8", true) - .Case("pwr7", true) - .Case("a2", true) - .Default(false); - - Features["isa-v207-instructions"] = llvm::StringSwitch(CPU) - .Case("ppc64le", true) - .Case("pwr9", true) - .Case("pwr8", true) - .Default(false); - - Features["isa-v30-instructions"] = - llvm::StringSwitch(CPU).Case("pwr9", true).Default(false); - - Features["quadword-atomics"] = - getTriple().isArch64Bit() && llvm::StringSwitch(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> 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 &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 &Features) const {} - -// Add features specific to the "Future" CPU. -void PPCTargetInfo::addFutureSpecificFeatures( - llvm::StringMap &Features) const {} - bool PPCTargetInfo::hasFeature(StringRef Feature) const { return llvm::StringSwitch(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> +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 &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> +getCPUDefaultTargetFeatures(StringRef CPU, + ArrayRef ProcDesc, + ArrayRef 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 P8SpecificFeatures = [FeatureAddiLoadFusion, + FeatureHTM, FeatureAddisLoadFusion]; list 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 P9SpecificFeatures = [FeatureVectorsUseTwoUnits]; + list P9SpecificFeatures = [FeatureVectorsUseTwoUnits, FeatureHTM]; list P9InheritableFeatures = !listconcat(P8InheritableFeatures, P9AdditionalFeatures); list 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> getPPCDefaultTargetFeatures(const Triple &T, + StringRef CPU) { + std::optional> FeaturesOpt = + getCPUDefaultTargetFeatures(CPU, BasicPPCSubTypeKV, BasicPPCFeatureKV); + + if (!FeaturesOpt.has_value()) + return std::nullopt; + + StringMap 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 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 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::getCPUDefaultTargetFeatures( + StringRef CPU, ArrayRef ProcDesc, + ArrayRef 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 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..1f4d3a7bc123c 100644 --- a/llvm/utils/TableGen/Basic/CMakeLists.txt +++ b/llvm/utils/TableGen/Basic/CMakeLists.txt @@ -17,6 +17,7 @@ add_llvm_library(LLVMTableGenBasic OBJECT EXCLUDE_FROM_ALL DISABLE_LLVM_LINK_LLV RISCVTargetDefEmitter.cpp SDNodeProperties.cpp TableGen.cpp + TargetFeaturesEmitter.cpp VTEmitter.cpp ) diff --git a/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp b/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp new file mode 100644 index 0000000000000..f016cc43c0e3e --- /dev/null +++ b/llvm/utils/TableGen/Basic/TargetFeaturesEmitter.cpp @@ -0,0 +1,178 @@ +//===- 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. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend exports cpu target features +// and cpu sub-type. +// +//===----------------------------------------------------------------------===// + +#include "TargetFeaturesEmitter.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/TableGenBackend.h" +#include "llvm/TargetParser/SubtargetFeature.h" + +using namespace llvm; + +using FeatureMapTy = DenseMap; +using ConstRecVec = std::vector; + +TargetFeaturesEmitter::TargetFeaturesEmitter(const RecordKeeper &R) + : Records(R) { + ArrayRef Targets = Records.getAllDerivedDefinitions("Target"); + if (Targets.size() == 0) + PrintFatalError("No 'Target' subclasses defined!"); + if (Targets.size() != 1) + PrintFatalError("Multiple subclasses of Target defined!"); + Target = Targets[0]->getName(); +} + +FeatureMapTy TargetFeaturesEmitter::enumeration(raw_ostream &OS) { + ArrayRef 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"; + + 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; +} + +void TargetFeaturesEmitter::printFeatureMask( + raw_ostream &OS, ArrayRef FeatureList, + const FeatureMapTy &FeatureMap) { + std::array 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 << "} } }"; +} + +void TargetFeaturesEmitter::printFeatureKeyValues( + raw_ostream &OS, const FeatureMapTy &FeatureMap) { + std::vector 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, LessRecordFieldName()); + + // 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 TargetFeaturesEmitter::printCPUKeyValues(raw_ostream &OS, + const FeatureMapTy &FeatureMap) { + // Gather and sort processor information + std::vector ProcessorList = + Records.getAllDerivedDefinitions("Processor"); + llvm::sort(ProcessorList, LessRecordFieldName()); + + // 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; +} + +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 = enumeration(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(OS, FeatureMap); + OS << "\n"; + + printCPUKeyValues(OS, FeatureMap); + OS << "\n"; + OS << "} // end namespace llvm\n\n"; + OS << "#endif // GET_SUBTARGETFEATURES_KV\n\n"; +} + +static TableGen::Emitter::OptClass + 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..99e4820c614c2 --- /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; + +class TargetFeaturesEmitter { +protected: + const RecordKeeper &Records; + std::string Target; + +public: + TargetFeaturesEmitter(const RecordKeeper &R); + static void printFeatureMask(raw_ostream &OS, + ArrayRef 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 #include #include @@ -43,18 +41,7 @@ using namespace llvm; namespace { -using FeatureMapTy = DenseMap; - -/// 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 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 FeatureList, - const FeatureMapTy &FeatureMap) { - std::array 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) {