mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 02:46:11 +00:00
[AArch64] Implement __builtin_cpu_supports, compiler-rt tests. (#82378)
The patch complements https://github.com/llvm/llvm-project/pull/68919 and adds AArch64 support for builtin `__builtin_cpu_supports("feature1+...+featureN")` which return true if all specified CPU features in argument are detected. Also compiler-rt aarch64 native run tests for features detection mechanism were added and 'cpu_model' check was fixed after its refactor merged https://github.com/llvm/llvm-project/pull/75635 Original RFC was https://reviews.llvm.org/D153153
This commit is contained in:
parent
aaf2d078b6
commit
568babab7e
@ -667,7 +667,13 @@ StringRef AArch64TargetInfo::getFeatureDependencies(StringRef Name) const {
|
||||
}
|
||||
|
||||
bool AArch64TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
|
||||
return llvm::AArch64::parseArchExtension(FeatureStr).has_value();
|
||||
// CPU features might be separated by '+', extract them and check
|
||||
llvm::SmallVector<StringRef, 8> Features;
|
||||
FeatureStr.split(Features, "+");
|
||||
for (auto &Feature : Features)
|
||||
if (!llvm::AArch64::parseArchExtension(Feature.trim()).has_value())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
|
||||
|
@ -165,7 +165,7 @@ public:
|
||||
DiagnosticsEngine &Diags) override;
|
||||
ParsedTargetAttr parseTargetAttr(StringRef Str) const override;
|
||||
bool supportsTargetAttributeTune() const override { return true; }
|
||||
|
||||
bool supportsCpuSupports() const override { return true; }
|
||||
bool checkArithmeticFenceSupported() const override { return true; }
|
||||
|
||||
bool hasBFloat16Type() const override;
|
||||
|
@ -10638,6 +10638,9 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
|
||||
BuiltinID <= clang::AArch64::LastSMEBuiltin)
|
||||
return EmitAArch64SMEBuiltinExpr(BuiltinID, E);
|
||||
|
||||
if (BuiltinID == Builtin::BI__builtin_cpu_supports)
|
||||
return EmitAArch64CpuSupports(E);
|
||||
|
||||
unsigned HintID = static_cast<unsigned>(-1);
|
||||
switch (BuiltinID) {
|
||||
default: break;
|
||||
@ -14025,6 +14028,19 @@ Value *CodeGenFunction::EmitX86CpuInit() {
|
||||
return Builder.CreateCall(Func);
|
||||
}
|
||||
|
||||
Value *CodeGenFunction::EmitAArch64CpuSupports(const CallExpr *E) {
|
||||
const Expr *ArgExpr = E->getArg(0)->IgnoreParenCasts();
|
||||
StringRef ArgStr = cast<StringLiteral>(ArgExpr)->getString();
|
||||
llvm::SmallVector<StringRef, 8> Features;
|
||||
ArgStr.split(Features, "+");
|
||||
for (auto &Feature : Features) {
|
||||
Feature = Feature.trim();
|
||||
if (Feature != "default")
|
||||
Features.push_back(Feature);
|
||||
}
|
||||
return EmitAArch64CpuSupports(Features);
|
||||
}
|
||||
|
||||
llvm::Value *
|
||||
CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) {
|
||||
uint64_t FeaturesMask = llvm::AArch64::getCpuSupportsMask(FeaturesStrs);
|
||||
|
@ -5013,10 +5013,10 @@ private:
|
||||
llvm::Value *EmitAArch64CpuInit();
|
||||
llvm::Value *
|
||||
FormAArch64ResolverCondition(const MultiVersionResolverOption &RO);
|
||||
llvm::Value *EmitAArch64CpuSupports(const CallExpr *E);
|
||||
llvm::Value *EmitAArch64CpuSupports(ArrayRef<StringRef> FeatureStrs);
|
||||
};
|
||||
|
||||
|
||||
inline DominatingLLVMValue::saved_type
|
||||
DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) {
|
||||
if (!needsSaving(value)) return saved_type(value, false);
|
||||
|
52
clang/test/CodeGen/aarch64-cpu-supports-target.c
Normal file
52
clang/test/CodeGen/aarch64-cpu-supports-target.c
Normal file
@ -0,0 +1,52 @@
|
||||
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
int check_all_feature() {
|
||||
if (__builtin_cpu_supports("rng+flagm+flagm2+fp16fml+dotprod+sm4"))
|
||||
return 1;
|
||||
else if (__builtin_cpu_supports("rdm+lse+fp+simd+crc+sha1+sha2+sha3"))
|
||||
return 2;
|
||||
else if (__builtin_cpu_supports("aes+pmull+fp16+dit+dpb+dpb2+jscvt"))
|
||||
return 3;
|
||||
else if (__builtin_cpu_supports("fcma+rcpc+rcpc2+rcpc3+frintts+dgh"))
|
||||
return 4;
|
||||
else if (__builtin_cpu_supports("i8mm+bf16+ebf16+rpres+sve+sve-bf16"))
|
||||
return 5;
|
||||
else if (__builtin_cpu_supports("sve-ebf16+sve-i8mm+f32mm+f64mm"))
|
||||
return 6;
|
||||
else if (__builtin_cpu_supports("sve2+sve2-aes+sve2-pmull128"))
|
||||
return 7;
|
||||
else if (__builtin_cpu_supports("sve2-bitperm+sve2-sha3+sve2-sm4"))
|
||||
return 8;
|
||||
else if (__builtin_cpu_supports("sme+memtag+memtag2+memtag3+sb"))
|
||||
return 9;
|
||||
else if (__builtin_cpu_supports("predres+ssbs+ssbs2+bti+ls64+ls64_v"))
|
||||
return 10;
|
||||
else if (__builtin_cpu_supports("ls64_accdata+wfxt+sme-f64f64"))
|
||||
return 11;
|
||||
else if (__builtin_cpu_supports("sme-i16i64+sme2"))
|
||||
return 12;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define dso_local i32 @neon_code() #1
|
||||
int __attribute__((target("simd"))) neon_code() { return 1; }
|
||||
|
||||
// CHECK-LABEL: define dso_local i32 @sve_code() #2
|
||||
int __attribute__((target("sve"))) sve_code() { return 2; }
|
||||
|
||||
// CHECK-LABEL: define dso_local i32 @code() #0
|
||||
int code() { return 3; }
|
||||
|
||||
// CHECK-LABEL: define dso_local i32 @test_versions() #0
|
||||
int test_versions() {
|
||||
if (__builtin_cpu_supports("sve"))
|
||||
return sve_code();
|
||||
else if (__builtin_cpu_supports("simd"))
|
||||
return neon_code();
|
||||
else
|
||||
return code();
|
||||
}
|
||||
// CHECK: attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
|
||||
// CHECK: attributes #1 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon" }
|
||||
// CHECK: attributes #2 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" }
|
54
clang/test/CodeGen/aarch64-cpu-supports.c
Normal file
54
clang/test/CodeGen/aarch64-cpu-supports.c
Normal file
@ -0,0 +1,54 @@
|
||||
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --version 2
|
||||
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
// CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
|
||||
// CHECK-LABEL: define dso_local i32 @main
|
||||
// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
|
||||
// CHECK-NEXT: entry:
|
||||
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
|
||||
// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
|
||||
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
|
||||
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 70368744177664
|
||||
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 70368744177664
|
||||
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
|
||||
// CHECK-NEXT: br i1 [[TMP3]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
||||
// CHECK: if.then:
|
||||
// CHECK-NEXT: store i32 1, ptr [[RETVAL]], align 4
|
||||
// CHECK-NEXT: br label [[RETURN:%.*]]
|
||||
// CHECK: if.end:
|
||||
// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
|
||||
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 9070970929152
|
||||
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 9070970929152
|
||||
// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]]
|
||||
// CHECK-NEXT: br i1 [[TMP7]], label [[IF_THEN1:%.*]], label [[IF_END2:%.*]]
|
||||
// CHECK: if.then1:
|
||||
// CHECK-NEXT: store i32 2, ptr [[RETVAL]], align 4
|
||||
// CHECK-NEXT: br label [[RETURN]]
|
||||
// CHECK: if.end2:
|
||||
// CHECK-NEXT: [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
|
||||
// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 166633186212708352
|
||||
// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 166633186212708352
|
||||
// CHECK-NEXT: [[TMP11:%.*]] = and i1 true, [[TMP10]]
|
||||
// CHECK-NEXT: br i1 [[TMP11]], label [[IF_THEN3:%.*]], label [[IF_END4:%.*]]
|
||||
// CHECK: if.then3:
|
||||
// CHECK-NEXT: store i32 3, ptr [[RETVAL]], align 4
|
||||
// CHECK-NEXT: br label [[RETURN]]
|
||||
// CHECK: if.end4:
|
||||
// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
|
||||
// CHECK-NEXT: br label [[RETURN]]
|
||||
// CHECK: return:
|
||||
// CHECK-NEXT: [[TMP12:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
// CHECK-NEXT: ret i32 [[TMP12]]
|
||||
//
|
||||
int main(void) {
|
||||
if (__builtin_cpu_supports("sb"))
|
||||
return 1;
|
||||
|
||||
if (__builtin_cpu_supports("sve2-pmull128+memtag"))
|
||||
return 2;
|
||||
|
||||
if (__builtin_cpu_supports("sme2+ls64_v+wfxt"))
|
||||
return 3;
|
||||
|
||||
return 0;
|
||||
}
|
@ -13,8 +13,3 @@
|
||||
# error "ARM/PPC shouldn't have __builtin_cpu_init"
|
||||
# endif
|
||||
#endif
|
||||
#if __has_builtin(__builtin_cpu_supports)
|
||||
# ifdef ARM
|
||||
# error "ARM shouldn't have __builtin_cpu_supports"
|
||||
# endif
|
||||
#endif
|
||||
|
26
clang/test/Sema/aarch64-cpu-supports.c
Normal file
26
clang/test/Sema/aarch64-cpu-supports.c
Normal file
@ -0,0 +1,26 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -triple aarch64-linux-gnu -verify %s
|
||||
|
||||
int test_aarch64_features(void) {
|
||||
char * ssbs2;
|
||||
// expected-error@+1 {{expression is not a string literal}}
|
||||
if (__builtin_cpu_supports(ssbs2))
|
||||
return 1;
|
||||
// expected-error@+1 {{invalid cpu feature string}}
|
||||
if (__builtin_cpu_supports(""))
|
||||
return 2;
|
||||
// expected-error@+1 {{invalid cpu feature string}}
|
||||
if (__builtin_cpu_supports("pmull128"))
|
||||
return 3;
|
||||
// expected-error@+1 {{invalid cpu feature string}}
|
||||
if (__builtin_cpu_supports("sve2,rpres"))
|
||||
return 4;
|
||||
// expected-error@+1 {{invalid cpu feature string}}
|
||||
if (__builtin_cpu_supports("dgh+sve2-pmull"))
|
||||
return 5;
|
||||
// expected-error@+1 {{invalid cpu feature string}}
|
||||
if (__builtin_cpu_supports("default"))
|
||||
return 6;
|
||||
if (__builtin_cpu_supports(" ssbs + bti "))
|
||||
return 7;
|
||||
return 0;
|
||||
}
|
@ -27,7 +27,7 @@ int main(void) {
|
||||
(void)__builtin_cpu_supports("x86-64-v4");
|
||||
(void)__builtin_cpu_supports("x86-64-v5"); // expected-error {{invalid cpu feature string for builtin}}
|
||||
#else
|
||||
if (__builtin_cpu_supports("aes")) // expected-error {{builtin is not supported on this target}}
|
||||
if (__builtin_cpu_supports("neon")) // expected-error {{invalid cpu feature string for builtin}}
|
||||
a("vsx");
|
||||
|
||||
if (__builtin_cpu_is("cortex-x3")) // expected-error {{builtin is not supported on this target}}
|
||||
|
17
compiler-rt/test/builtins/Unit/aarch64_cpu_features_test.c
Normal file
17
compiler-rt/test/builtins/Unit/aarch64_cpu_features_test.c
Normal file
@ -0,0 +1,17 @@
|
||||
// REQUIRES: aarch64-target-arch
|
||||
// REQUIRES: native-run
|
||||
// RUN: %clang_builtins %s %librt -o %t && %run %t
|
||||
// REQUIRES: librt_has_aarch64
|
||||
int main(void) {
|
||||
if (__builtin_cpu_supports("fp+simd+pmull+sha2+crc")) {
|
||||
if (__builtin_cpu_supports("fp") && __builtin_cpu_supports("simd") &&
|
||||
__builtin_cpu_supports("pmull") && __builtin_cpu_supports("sha2") &&
|
||||
__builtin_cpu_supports("crc")) {
|
||||
return 0;
|
||||
} else {
|
||||
// Something wrong in feature detection
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
// REQUIRES: x86-target-arch
|
||||
// RUN: %clang_builtins %s %librt -o %t && %run %t
|
||||
// REQUIRES: librt_has_cpu_model
|
||||
// REQUIRES: librt_has_x86
|
||||
|
||||
// FIXME: XFAIL the test because it is expected to return non-zero value.
|
||||
// XFAIL: *
|
||||
|
Loading…
x
Reference in New Issue
Block a user