MaskRay created this revision.
MaskRay added reviewers: FreddyYe, pengfei, RKSimon, skan, erichkeane.
Herald added a subscriber: hiraditya.
Herald added a reviewer: ctetreau.
Herald added a project: All.
MaskRay requested review of this revision.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.
GCC 12 (https://gcc.gnu.org/PR101696) allows
__builtin_cpu_supports("x86-64") (and -v2 -v3 -v4).
This patch ports the feature.
- Add `FEATURE_X86_64_{BASELINE,V2,V3,V4}` to enum ProcessorFeatures, but keep
CPU_FEATURE_MAX unchanged to make FeatureInfos/FeatureInfos_WithPLUS happy.
- Change validateCpuSupports to allow `x86-64{,-v2,-v3,-v4}`
- Change getCpuSupportsMask to return `std::array<uint32_t, 4> where
`x86-64{,-v2,-v3,-v4}` set bits `FEATURE_X86_64_{BASELINE,V2,V3,V4}`.
- `cpu_dispatch` feels legacy. It doesn't support `x86-64{,-v2,-v3,-v4}`. Add
tests.
Close https://github.com/llvm/llvm-project/issues/55830
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D158811
Files:
clang/lib/Basic/Targets/X86.cpp
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/test/CodeGen/builtin-cpu-supports.c
clang/test/Sema/attr-cpuspecific.c
clang/test/Sema/attr-target.c
llvm/include/llvm/TargetParser/X86TargetParser.def
llvm/include/llvm/TargetParser/X86TargetParser.h
llvm/lib/TargetParser/X86TargetParser.cpp
Index: llvm/lib/TargetParser/X86TargetParser.cpp
===================================================================
--- llvm/lib/TargetParser/X86TargetParser.cpp
+++ llvm/lib/TargetParser/X86TargetParser.cpp
@@ -703,18 +703,21 @@
return I != std::end(Processors);
}
-uint64_t llvm::X86::getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs) {
+std::array<uint32_t, 4>
+llvm::X86::getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs) {
// Processor features and mapping to processor feature value.
- uint64_t FeaturesMask = 0;
- for (const StringRef &FeatureStr : FeatureStrs) {
+ std::array<uint32_t, 4> FeatureMask{};
+ for (StringRef FeatureStr : FeatureStrs) {
unsigned Feature = StringSwitch<unsigned>(FeatureStr)
#define X86_FEATURE_COMPAT(ENUM, STR, PRIORITY) \
.Case(STR, llvm::X86::FEATURE_##ENUM)
+#define X86_MICROARCH_LEVEL(ENUM, STR, PRIORITY) \
+ .Case(STR, llvm::X86::FEATURE_##ENUM)
#include "llvm/TargetParser/X86TargetParser.def"
;
- FeaturesMask |= (1ULL << Feature);
+ FeatureMask[Feature / 32] |= 1U << (Feature % 32);
}
- return FeaturesMask;
+ return FeatureMask;
}
unsigned llvm::X86::getFeaturePriority(ProcessorFeatures Feat) {
Index: llvm/include/llvm/TargetParser/X86TargetParser.h
===================================================================
--- llvm/include/llvm/TargetParser/X86TargetParser.h
+++ llvm/include/llvm/TargetParser/X86TargetParser.h
@@ -15,6 +15,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
+#include <array>
namespace llvm {
template <typename T> class SmallVectorImpl;
@@ -57,7 +58,11 @@
enum ProcessorFeatures {
#define X86_FEATURE(ENUM, STRING) FEATURE_##ENUM,
#include "llvm/TargetParser/X86TargetParser.def"
- CPU_FEATURE_MAX
+ CPU_FEATURE_MAX,
+
+#define X86_FEATURE(ENUM, STRING)
+#define X86_MICROARCH_LEVEL(ENUM, STRING, PRIORITY) FEATURE_##ENUM = PRIORITY,
+#include "llvm/TargetParser/X86TargetParser.def"
};
enum CPUKind {
@@ -171,7 +176,7 @@
char getCPUDispatchMangling(StringRef Name);
bool validateCPUSpecificCPUDispatch(StringRef Name);
-uint64_t getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
+std::array<uint32_t, 4> getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
unsigned getFeaturePriority(ProcessorFeatures Feat);
} // namespace X86
Index: llvm/include/llvm/TargetParser/X86TargetParser.def
===================================================================
--- llvm/include/llvm/TargetParser/X86TargetParser.def
+++ llvm/include/llvm/TargetParser/X86TargetParser.def
@@ -128,6 +128,10 @@
#define X86_FEATURE(ENUM, STR)
#endif
+#ifndef X86_MICROARCH_LEVEL
+#define X86_MICROARCH_LEVEL(ENUM, STR, PRIORITY)
+#endif
+
X86_FEATURE_COMPAT(CMOV, "cmov", 0)
X86_FEATURE_COMPAT(MMX, "mmx", 1)
X86_FEATURE_COMPAT(POPCNT, "popcnt", 9)
@@ -242,5 +246,11 @@
X86_FEATURE (RETPOLINE_INDIRECT_CALLS, "retpoline-indirect-calls")
X86_FEATURE (LVI_CFI, "lvi-cfi")
X86_FEATURE (LVI_LOAD_HARDENING, "lvi-load-hardening")
+
+X86_MICROARCH_LEVEL(X86_64_BASELINE,"x86-64", 95)
+X86_MICROARCH_LEVEL(X86_64_V2, "x86-64-v2", 96)
+X86_MICROARCH_LEVEL(X86_64_V3, "x86-64-v3", 97)
+X86_MICROARCH_LEVEL(X86_64_V4, "x86-64-v4", 98)
#undef X86_FEATURE_COMPAT
#undef X86_FEATURE
+#undef X86_MICROARCH_LEVEL
Index: clang/test/Sema/attr-target.c
===================================================================
--- clang/test/Sema/attr-target.c
+++ clang/test/Sema/attr-target.c
@@ -26,6 +26,11 @@
//expected-warning@+1 {{unknown tune CPU 'hiss' in the 'target' attribute string; 'target' attribute ignored}}
int __attribute__((target("tune=hiss,tune=woof"))) apple_tree(void) { return 4; }
+//expected-warning@+1 {{unsupported 'x86-64' in the 'target' attribute string}}
+void __attribute__((target("x86-64"))) baseline(void) {}
+//expected-warning@+1 {{unsupported 'x86-64-v2' in the 'target' attribute string}}
+void __attribute__((target("x86-64-v2"))) v2(void) {}
+
#elifdef __aarch64__
int __attribute__((target("sve,arch=armv8-a"))) foo(void) { return 4; }
Index: clang/test/Sema/attr-cpuspecific.c
===================================================================
--- clang/test/Sema/attr-cpuspecific.c
+++ clang/test/Sema/attr-cpuspecific.c
@@ -181,3 +181,8 @@
// expected-error@+1 {{attribute 'cpu_specific' multiversioning cannot be combined with attribute 'overloadable'}}
int __attribute__((__overloadable__)) __attribute__((cpu_specific(atom))) good_overload7(void);
int __attribute__((cpu_specific(ivybridge))) good_overload7(int);
+
+// expected-error@+1 {{invalid option 'x86_64'}}
+int __attribute__((cpu_specific(x86_64))) baseline(void);
+// expected-error@+1 {{invalid option 'x86_64_v2'}}
+int __attribute__((cpu_specific(x86_64_v2))) baseline(void);
Index: clang/test/CodeGen/builtin-cpu-supports.c
===================================================================
--- clang/test/CodeGen/builtin-cpu-supports.c
+++ clang/test/CodeGen/builtin-cpu-supports.c
@@ -30,3 +30,23 @@
}
// CHECK: declare dso_local void @__cpu_indicator_init()
+
+// CHECK-LABEL: define{{.*}} @baseline(
+// CHECK: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 1)
+// CHECK-NEXT: and i32 [[LOAD]], -2147483648
+int baseline() { return __builtin_cpu_supports("x86-64"); }
+
+// CHECK-LABEL: define{{.*}} @v2(
+// CHECK: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 2)
+// CHECK-NEXT: and i32 [[LOAD]], 1
+int v2() { return __builtin_cpu_supports("x86-64-v2"); }
+
+// CHECK-LABEL: define{{.*}} @v3(
+// CHECK: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 2)
+// CHECK-NEXT: and i32 [[LOAD]], 2
+int v3() { return __builtin_cpu_supports("x86-64-v3"); }
+
+// CHECK-LABEL: define{{.*}} @v4(
+// CHECK: [[LOAD:%.*]] = load i32, ptr getelementptr inbounds ([[[#]] x i32], ptr @__cpu_features2, i32 0, i32 2)
+// CHECK-NEXT: and i32 [[LOAD]], 4
+int v4() { return __builtin_cpu_supports("x86-64-v4"); }
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -4168,8 +4168,9 @@
// always run on at least a 'pentium'). We do this by deleting the 'least
// advanced' (read, lowest mangling letter).
while (Options.size() > 1 &&
- llvm::X86::getCpuSupportsMask(
- (Options.end() - 2)->Conditions.Features) == 0) {
+ llvm::all_of(llvm::X86::getCpuSupportsMask(
+ (Options.end() - 2)->Conditions.Features),
+ [](auto X) { return X == 0; })) {
StringRef LHSName = (Options.end() - 2)->Function->getName();
StringRef RHSName = (Options.end() - 1)->Function->getName();
if (LHSName.compare(RHSName) < 0)
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2683,24 +2683,12 @@
if (!RO.Conditions.Architecture.empty()) {
StringRef Arch = RO.Conditions.Architecture;
- std::array<uint32_t, 4> Mask{};
- // If arch= specifies an x86-64 micro-architecture level, test a special
- // feature named FEATURE_X86_64_*, otherwise we use __builtin_cpu_is.
- if (Arch.consume_front("x86-64")) {
- if (Arch.empty()) // FEATURE_X86_64_BASELINE 95=2*32+31
- Mask[2] = 1u << 31;
- else if (Arch == "-v2") // FEATURE_X86_64_V2 96==3*32+0
- Mask[3] = 1u << 0;
- else if (Arch == "-v3") // FEATURE_X86_64_V3 97==3*32+1
- Mask[3] = 1u << 1;
- else if (Arch == "-v4") // FEATURE_X86_64_V3 98==3*32+2
- Mask[3] = 1u << 2;
- else
- llvm_unreachable("invalid x86-64 micro-architecture level");
- Condition = EmitX86CpuSupports(Mask);
- } else {
+ // If arch= specifies an x86-64 micro-architecture level, test the feature
+ // with __builtin_cpu_supports, otherwise use __builtin_cpu_is.
+ if (Arch.starts_with("x86-64"))
+ Condition = EmitX86CpuSupports({Arch});
+ else
Condition = EmitX86CpuIs(Arch);
- }
}
if (!RO.Conditions.Features.empty()) {
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -13325,9 +13325,7 @@
}
Value *CodeGenFunction::EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs) {
- uint64_t Mask = llvm::X86::getCpuSupportsMask(FeatureStrs);
- std::array<uint32_t, 4> FeatureMask{Lo_32(Mask), Hi_32(Mask), 0, 0};
- return EmitX86CpuSupports(FeatureMask);
+ return EmitX86CpuSupports(llvm::X86::getCpuSupportsMask(FeatureStrs));
}
llvm::Value *
Index: clang/lib/Basic/Targets/X86.cpp
===================================================================
--- clang/lib/Basic/Targets/X86.cpp
+++ clang/lib/Basic/Targets/X86.cpp
@@ -1170,6 +1170,7 @@
bool X86TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
return llvm::StringSwitch<bool>(FeatureStr)
#define X86_FEATURE_COMPAT(ENUM, STR, PRIORITY) .Case(STR, true)
+#define X86_MICROARCH_LEVEL(ENUM, STR, PRIORITY) .Case(STR, true)
#include "llvm/TargetParser/X86TargetParser.def"
.Default(false);
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits