Skip to content

Commit

Permalink
[AArch64] Implement __builtin_cpu_supports, compiler-rt tests. (#82378)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ilinpv committed Feb 22, 2024
1 parent aaf2d07 commit 568baba
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 10 deletions.
8 changes: 7 additions & 1 deletion clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/AArch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
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;
Expand Down
16 changes: 16 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -5013,10 +5013,10 @@ class CodeGenFunction : public CodeGenTypeCache {
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);
Expand Down
52 changes: 52 additions & 0 deletions clang/test/CodeGen/aarch64-cpu-supports-target.c
Original file line number Diff line number Diff line change
@@ -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 changes: 54 additions & 0 deletions clang/test/CodeGen/aarch64-cpu-supports.c
Original file line number Diff line number Diff line change
@@ -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;
}
5 changes: 0 additions & 5 deletions clang/test/Preprocessor/has_builtin_cpuid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 26 additions & 0 deletions clang/test/Sema/aarch64-cpu-supports.c
Original file line number Diff line number Diff line change
@@ -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;
}
2 changes: 1 addition & 1 deletion clang/test/Sema/builtin-cpu-supports.c
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down
17 changes: 17 additions & 0 deletions compiler-rt/test/builtins/Unit/aarch64_cpu_features_test.c
Original file line number Diff line number Diff line change
@@ -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;
}
2 changes: 1 addition & 1 deletion compiler-rt/test/builtins/Unit/cpu_model_test.c
Original file line number Diff line number Diff line change
@@ -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: *
Expand Down

0 comments on commit 568baba

Please sign in to comment.