Skip to content

Commit 568baba

Browse files
authored
[AArch64] Implement __builtin_cpu_supports, compiler-rt tests. (#82378)
The patch complements #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 #75635 Original RFC was https://reviews.llvm.org/D153153
1 parent aaf2d07 commit 568baba

File tree

11 files changed

+176
-10
lines changed

11 files changed

+176
-10
lines changed

clang/lib/Basic/Targets/AArch64.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,13 @@ StringRef AArch64TargetInfo::getFeatureDependencies(StringRef Name) const {
667667
}
668668

669669
bool AArch64TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
670-
return llvm::AArch64::parseArchExtension(FeatureStr).has_value();
670+
// CPU features might be separated by '+', extract them and check
671+
llvm::SmallVector<StringRef, 8> Features;
672+
FeatureStr.split(Features, "+");
673+
for (auto &Feature : Features)
674+
if (!llvm::AArch64::parseArchExtension(Feature.trim()).has_value())
675+
return false;
676+
return true;
671677
}
672678

673679
bool AArch64TargetInfo::hasFeature(StringRef Feature) const {

clang/lib/Basic/Targets/AArch64.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
165165
DiagnosticsEngine &Diags) override;
166166
ParsedTargetAttr parseTargetAttr(StringRef Str) const override;
167167
bool supportsTargetAttributeTune() const override { return true; }
168-
168+
bool supportsCpuSupports() const override { return true; }
169169
bool checkArithmeticFenceSupported() const override { return true; }
170170

171171
bool hasBFloat16Type() const override;

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10638,6 +10638,9 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
1063810638
BuiltinID <= clang::AArch64::LastSMEBuiltin)
1063910639
return EmitAArch64SMEBuiltinExpr(BuiltinID, E);
1064010640

10641+
if (BuiltinID == Builtin::BI__builtin_cpu_supports)
10642+
return EmitAArch64CpuSupports(E);
10643+
1064110644
unsigned HintID = static_cast<unsigned>(-1);
1064210645
switch (BuiltinID) {
1064310646
default: break;
@@ -14025,6 +14028,19 @@ Value *CodeGenFunction::EmitX86CpuInit() {
1402514028
return Builder.CreateCall(Func);
1402614029
}
1402714030

14031+
Value *CodeGenFunction::EmitAArch64CpuSupports(const CallExpr *E) {
14032+
const Expr *ArgExpr = E->getArg(0)->IgnoreParenCasts();
14033+
StringRef ArgStr = cast<StringLiteral>(ArgExpr)->getString();
14034+
llvm::SmallVector<StringRef, 8> Features;
14035+
ArgStr.split(Features, "+");
14036+
for (auto &Feature : Features) {
14037+
Feature = Feature.trim();
14038+
if (Feature != "default")
14039+
Features.push_back(Feature);
14040+
}
14041+
return EmitAArch64CpuSupports(Features);
14042+
}
14043+
1402814044
llvm::Value *
1402914045
CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) {
1403014046
uint64_t FeaturesMask = llvm::AArch64::getCpuSupportsMask(FeaturesStrs);

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5013,10 +5013,10 @@ class CodeGenFunction : public CodeGenTypeCache {
50135013
llvm::Value *EmitAArch64CpuInit();
50145014
llvm::Value *
50155015
FormAArch64ResolverCondition(const MultiVersionResolverOption &RO);
5016+
llvm::Value *EmitAArch64CpuSupports(const CallExpr *E);
50165017
llvm::Value *EmitAArch64CpuSupports(ArrayRef<StringRef> FeatureStrs);
50175018
};
50185019

5019-
50205020
inline DominatingLLVMValue::saved_type
50215021
DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) {
50225022
if (!needsSaving(value)) return saved_type(value, false);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
2+
3+
int check_all_feature() {
4+
if (__builtin_cpu_supports("rng+flagm+flagm2+fp16fml+dotprod+sm4"))
5+
return 1;
6+
else if (__builtin_cpu_supports("rdm+lse+fp+simd+crc+sha1+sha2+sha3"))
7+
return 2;
8+
else if (__builtin_cpu_supports("aes+pmull+fp16+dit+dpb+dpb2+jscvt"))
9+
return 3;
10+
else if (__builtin_cpu_supports("fcma+rcpc+rcpc2+rcpc3+frintts+dgh"))
11+
return 4;
12+
else if (__builtin_cpu_supports("i8mm+bf16+ebf16+rpres+sve+sve-bf16"))
13+
return 5;
14+
else if (__builtin_cpu_supports("sve-ebf16+sve-i8mm+f32mm+f64mm"))
15+
return 6;
16+
else if (__builtin_cpu_supports("sve2+sve2-aes+sve2-pmull128"))
17+
return 7;
18+
else if (__builtin_cpu_supports("sve2-bitperm+sve2-sha3+sve2-sm4"))
19+
return 8;
20+
else if (__builtin_cpu_supports("sme+memtag+memtag2+memtag3+sb"))
21+
return 9;
22+
else if (__builtin_cpu_supports("predres+ssbs+ssbs2+bti+ls64+ls64_v"))
23+
return 10;
24+
else if (__builtin_cpu_supports("ls64_accdata+wfxt+sme-f64f64"))
25+
return 11;
26+
else if (__builtin_cpu_supports("sme-i16i64+sme2"))
27+
return 12;
28+
else
29+
return 0;
30+
}
31+
32+
// CHECK-LABEL: define dso_local i32 @neon_code() #1
33+
int __attribute__((target("simd"))) neon_code() { return 1; }
34+
35+
// CHECK-LABEL: define dso_local i32 @sve_code() #2
36+
int __attribute__((target("sve"))) sve_code() { return 2; }
37+
38+
// CHECK-LABEL: define dso_local i32 @code() #0
39+
int code() { return 3; }
40+
41+
// CHECK-LABEL: define dso_local i32 @test_versions() #0
42+
int test_versions() {
43+
if (__builtin_cpu_supports("sve"))
44+
return sve_code();
45+
else if (__builtin_cpu_supports("simd"))
46+
return neon_code();
47+
else
48+
return code();
49+
}
50+
// CHECK: attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
51+
// CHECK: attributes #1 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon" }
52+
// CHECK: attributes #2 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" }
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --version 2
2+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
3+
4+
// CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
5+
// CHECK-LABEL: define dso_local i32 @main
6+
// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
7+
// CHECK-NEXT: entry:
8+
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
9+
// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
10+
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
11+
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 70368744177664
12+
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 70368744177664
13+
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
14+
// CHECK-NEXT: br i1 [[TMP3]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
15+
// CHECK: if.then:
16+
// CHECK-NEXT: store i32 1, ptr [[RETVAL]], align 4
17+
// CHECK-NEXT: br label [[RETURN:%.*]]
18+
// CHECK: if.end:
19+
// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
20+
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 9070970929152
21+
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 9070970929152
22+
// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]]
23+
// CHECK-NEXT: br i1 [[TMP7]], label [[IF_THEN1:%.*]], label [[IF_END2:%.*]]
24+
// CHECK: if.then1:
25+
// CHECK-NEXT: store i32 2, ptr [[RETVAL]], align 4
26+
// CHECK-NEXT: br label [[RETURN]]
27+
// CHECK: if.end2:
28+
// CHECK-NEXT: [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
29+
// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 166633186212708352
30+
// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 166633186212708352
31+
// CHECK-NEXT: [[TMP11:%.*]] = and i1 true, [[TMP10]]
32+
// CHECK-NEXT: br i1 [[TMP11]], label [[IF_THEN3:%.*]], label [[IF_END4:%.*]]
33+
// CHECK: if.then3:
34+
// CHECK-NEXT: store i32 3, ptr [[RETVAL]], align 4
35+
// CHECK-NEXT: br label [[RETURN]]
36+
// CHECK: if.end4:
37+
// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
38+
// CHECK-NEXT: br label [[RETURN]]
39+
// CHECK: return:
40+
// CHECK-NEXT: [[TMP12:%.*]] = load i32, ptr [[RETVAL]], align 4
41+
// CHECK-NEXT: ret i32 [[TMP12]]
42+
//
43+
int main(void) {
44+
if (__builtin_cpu_supports("sb"))
45+
return 1;
46+
47+
if (__builtin_cpu_supports("sve2-pmull128+memtag"))
48+
return 2;
49+
50+
if (__builtin_cpu_supports("sme2+ls64_v+wfxt"))
51+
return 3;
52+
53+
return 0;
54+
}

clang/test/Preprocessor/has_builtin_cpuid.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,3 @@
1313
# error "ARM/PPC shouldn't have __builtin_cpu_init"
1414
# endif
1515
#endif
16-
#if __has_builtin(__builtin_cpu_supports)
17-
# ifdef ARM
18-
# error "ARM shouldn't have __builtin_cpu_supports"
19-
# endif
20-
#endif
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %clang_cc1 -fsyntax-only -triple aarch64-linux-gnu -verify %s
2+
3+
int test_aarch64_features(void) {
4+
char * ssbs2;
5+
// expected-error@+1 {{expression is not a string literal}}
6+
if (__builtin_cpu_supports(ssbs2))
7+
return 1;
8+
// expected-error@+1 {{invalid cpu feature string}}
9+
if (__builtin_cpu_supports(""))
10+
return 2;
11+
// expected-error@+1 {{invalid cpu feature string}}
12+
if (__builtin_cpu_supports("pmull128"))
13+
return 3;
14+
// expected-error@+1 {{invalid cpu feature string}}
15+
if (__builtin_cpu_supports("sve2,rpres"))
16+
return 4;
17+
// expected-error@+1 {{invalid cpu feature string}}
18+
if (__builtin_cpu_supports("dgh+sve2-pmull"))
19+
return 5;
20+
// expected-error@+1 {{invalid cpu feature string}}
21+
if (__builtin_cpu_supports("default"))
22+
return 6;
23+
if (__builtin_cpu_supports(" ssbs + bti "))
24+
return 7;
25+
return 0;
26+
}

clang/test/Sema/builtin-cpu-supports.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ int main(void) {
2727
(void)__builtin_cpu_supports("x86-64-v4");
2828
(void)__builtin_cpu_supports("x86-64-v5"); // expected-error {{invalid cpu feature string for builtin}}
2929
#else
30-
if (__builtin_cpu_supports("aes")) // expected-error {{builtin is not supported on this target}}
30+
if (__builtin_cpu_supports("neon")) // expected-error {{invalid cpu feature string for builtin}}
3131
a("vsx");
3232

3333
if (__builtin_cpu_is("cortex-x3")) // expected-error {{builtin is not supported on this target}}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// REQUIRES: aarch64-target-arch
2+
// REQUIRES: native-run
3+
// RUN: %clang_builtins %s %librt -o %t && %run %t
4+
// REQUIRES: librt_has_aarch64
5+
int main(void) {
6+
if (__builtin_cpu_supports("fp+simd+pmull+sha2+crc")) {
7+
if (__builtin_cpu_supports("fp") && __builtin_cpu_supports("simd") &&
8+
__builtin_cpu_supports("pmull") && __builtin_cpu_supports("sha2") &&
9+
__builtin_cpu_supports("crc")) {
10+
return 0;
11+
} else {
12+
// Something wrong in feature detection
13+
return 1;
14+
}
15+
}
16+
return 0;
17+
}

compiler-rt/test/builtins/Unit/cpu_model_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// REQUIRES: x86-target-arch
22
// RUN: %clang_builtins %s %librt -o %t && %run %t
3-
// REQUIRES: librt_has_cpu_model
3+
// REQUIRES: librt_has_x86
44

55
// FIXME: XFAIL the test because it is expected to return non-zero value.
66
// XFAIL: *

0 commit comments

Comments
 (0)