Skip to content

[AArch64] Implement __builtin_cpu_supports, compiler-rt tests. #82378

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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