Skip to content

Commit 9cc98e3

Browse files
authored
[AArch64] Add soft-float ABI (#74460)
This adds support for the AArch64 soft-float ABI. The specification for this ABI was added by ARM-software/abi-aa#232. Because all existing AArch64 hardware has floating-point hardware, we expect this to be a niche option, only used for embedded systems on R-profile systems. We are going to document that SysV-like systems should only ever use the base (hard-float) PCS variant: ARM-software/abi-aa#233. For that reason, I've not added an option to select the ABI independently of the FPU hardware, instead the new ABI is enabled iff the target architecture does not have an FPU. For testing, I have run this through an ABI fuzzer, but since this is the first implementation it can only test for internal consistency (callers and callees agree on the PCS), not for conformance to the ABI spec.
1 parent 32fcfcd commit 9cc98e3

17 files changed

+404
-28
lines changed

clang/include/clang/Basic/DiagnosticCommonKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,8 @@ def warn_target_unrecognized_env : Warning<
356356
def warn_knl_knm_isa_support_removed : Warning<
357357
"KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.">,
358358
InGroup<DiagGroup<"knl-knm-isa-support-removed">>;
359+
def err_target_unsupported_abi_with_fpu : Error<
360+
"'%0' ABI is not supported with FPU">;
359361

360362
// Source manager
361363
def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11314,6 +11314,8 @@ def err_omp_wrong_dependency_iterator_type : Error<
1131411314
def err_target_unsupported_type
1131511315
: Error<"%0 requires %select{|%2 bit size}1 %3 %select{|return }4type support,"
1131611316
" but target '%5' does not support it">;
11317+
def err_target_unsupported_type_for_abi
11318+
: Error<"%0 requires %1 type support, but ABI '%2' does not support it">;
1131711319
def err_omp_lambda_capture_in_declare_target_not_to : Error<
1131811320
"variable captured in declare target region must appear in a to clause">;
1131911321
def err_omp_device_type_mismatch : Error<

clang/include/clang/Basic/TargetInfo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ class TargetInfo : public TransferrableTargetInfo,
231231
bool HasIbm128;
232232
bool HasLongDouble;
233233
bool HasFPReturn;
234+
bool HasFPTypes;
234235
bool HasStrictFP;
235236

236237
unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
@@ -689,6 +690,9 @@ class TargetInfo : public TransferrableTargetInfo,
689690
/// on this target.
690691
virtual bool hasFPReturn() const { return HasFPReturn; }
691692

693+
/// Determine whether floating point types are supported for this target.
694+
virtual bool hasFPTypes() const { return HasFPTypes; }
695+
692696
/// Determine whether constrained floating point is supported on this target.
693697
virtual bool hasStrictFP() const { return HasStrictFP; }
694698

@@ -1331,6 +1335,10 @@ class TargetInfo : public TransferrableTargetInfo,
13311335
return false;
13321336
}
13331337

1338+
/// Make changes to the supported types which depend on both the target
1339+
/// features and ABI.
1340+
virtual void setSupportedArgTypes() {}
1341+
13341342
/// Use the specified unit for FP math.
13351343
///
13361344
/// \return False on error (invalid unit name).

clang/lib/Basic/TargetInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
6767
HasFullBFloat16 = false;
6868
HasLongDouble = true;
6969
HasFPReturn = true;
70+
HasFPTypes = true;
7071
HasStrictFP = false;
7172
PointerWidth = PointerAlign = 32;
7273
BoolWidth = BoolAlign = 8;

clang/lib/Basic/Targets.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,7 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
830830
Target->setSupportedOpenCLOpts();
831831
Target->setCommandLineOpenCLOpts();
832832
Target->setMaxAtomicWidth();
833+
Target->setSupportedArgTypes();
833834

834835
if (!Opts->DarwinTargetVariantTriple.empty())
835836
Target->DarwinTargetVariantTriple =

clang/lib/Basic/Targets/AArch64.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "AArch64.h"
14+
#include "clang/Basic/Diagnostic.h"
1415
#include "clang/Basic/LangOptions.h"
1516
#include "clang/Basic/TargetBuiltins.h"
1617
#include "clang/Basic/TargetInfo.h"
@@ -199,13 +200,32 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
199200
StringRef AArch64TargetInfo::getABI() const { return ABI; }
200201

201202
bool AArch64TargetInfo::setABI(const std::string &Name) {
202-
if (Name != "aapcs" && Name != "darwinpcs")
203+
if (Name != "aapcs" && Name != "aapcs-soft" && Name != "darwinpcs")
203204
return false;
204205

205206
ABI = Name;
206207
return true;
207208
}
208209

210+
void AArch64TargetInfo::setSupportedArgTypes() {
211+
if (!(FPU & FPUMode) && ABI != "aapcs-soft") {
212+
// When a hard-float ABI is used on a target without an FPU, all
213+
// floating-point argument and return types are rejected because they must
214+
// be passed in FP registers.
215+
HasFPTypes = false;
216+
}
217+
}
218+
219+
bool AArch64TargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
220+
if (hasFeature("fp") && ABI == "aapcs-soft") {
221+
// aapcs-soft is not allowed for targets with an FPU, to avoid there being
222+
// two incomatible ABIs.
223+
Diags.Report(diag::err_target_unsupported_abi_with_fpu) << ABI;
224+
return false;
225+
}
226+
return true;
227+
}
228+
209229
bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
210230
BranchProtectionInfo &BPI,
211231
StringRef &Err) const {
@@ -686,7 +706,8 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
686706
return llvm::StringSwitch<bool>(Feature)
687707
.Cases("aarch64", "arm64", "arm", true)
688708
.Case("fmv", HasFMV)
689-
.Cases("neon", "fp", "simd", FPU & NeonMode)
709+
.Case("fp", FPU & FPUMode)
710+
.Cases("neon", "simd", FPU & NeonMode)
690711
.Case("jscvt", HasJSCVT)
691712
.Case("fcma", HasFCMA)
692713
.Case("rng", HasRandGen)

clang/lib/Basic/Targets/AArch64.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
9696

9797
StringRef getABI() const override;
9898
bool setABI(const std::string &Name) override;
99+
void setSupportedArgTypes() override;
99100

100101
bool validateBranchProtection(StringRef Spec, StringRef Arch,
101102
BranchProtectionInfo &BPI,
@@ -199,6 +200,8 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
199200
bool hasInt128Type() const override;
200201

201202
bool hasBitIntType() const override { return true; }
203+
204+
bool validateTarget(DiagnosticsEngine &Diags) const override;
202205
};
203206

204207
class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo {

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
145145
Kind = AArch64ABIKind::DarwinPCS;
146146
else if (Triple.isOSWindows())
147147
return createWindowsAArch64TargetCodeGenInfo(CGM, AArch64ABIKind::Win64);
148+
else if (Target.getABI() == "aapcs-soft")
149+
Kind = AArch64ABIKind::AAPCSSoft;
148150

149151
return createAArch64TargetCodeGenInfo(CGM, Kind);
150152
}

clang/lib/CodeGen/TargetInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ enum class AArch64ABIKind {
416416
AAPCS = 0,
417417
DarwinPCS,
418418
Win64,
419+
AAPCSSoft,
419420
};
420421

421422
std::unique_ptr<TargetCodeGenInfo>

clang/lib/CodeGen/Targets/AArch64.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ class AArch64ABIInfo : public ABIInfo {
5353
Address EmitDarwinVAArg(Address VAListAddr, QualType Ty,
5454
CodeGenFunction &CGF) const;
5555

56-
Address EmitAAPCSVAArg(Address VAListAddr, QualType Ty,
57-
CodeGenFunction &CGF) const;
56+
Address EmitAAPCSVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF,
57+
AArch64ABIKind Kind) const;
5858

5959
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
6060
QualType Ty) const override {
@@ -65,7 +65,7 @@ class AArch64ABIInfo : public ABIInfo {
6565

6666
return Kind == AArch64ABIKind::Win64 ? EmitMSVAArg(CGF, VAListAddr, Ty)
6767
: isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF)
68-
: EmitAAPCSVAArg(VAListAddr, Ty, CGF);
68+
: EmitAAPCSVAArg(VAListAddr, Ty, CGF, Kind);
6969
}
7070

7171
Address EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
@@ -482,6 +482,11 @@ bool AArch64SwiftABIInfo::isLegalVectorType(CharUnits VectorSize,
482482
}
483483

484484
bool AArch64ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
485+
// For the soft-float ABI variant, no types are considered to be homogeneous
486+
// aggregates.
487+
if (Kind == AArch64ABIKind::AAPCSSoft)
488+
return false;
489+
485490
// Homogeneous aggregates for AAPCS64 must have base types of a floating
486491
// point type or a short-vector type. This is the same as the 32-bit ABI,
487492
// but with the difference that any floating-point type is allowed,
@@ -513,7 +518,8 @@ bool AArch64ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate()
513518
}
514519

515520
Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty,
516-
CodeGenFunction &CGF) const {
521+
CodeGenFunction &CGF,
522+
AArch64ABIKind Kind) const {
517523
ABIArgInfo AI = classifyArgumentType(Ty, /*IsVariadic=*/true,
518524
CGF.CurFnInfo->getCallingConvention());
519525
// Empty records are ignored for parameter passing purposes.
@@ -538,7 +544,8 @@ Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty,
538544
BaseTy = ArrTy->getElementType();
539545
NumRegs = ArrTy->getNumElements();
540546
}
541-
bool IsFPR = BaseTy->isFloatingPointTy() || BaseTy->isVectorTy();
547+
bool IsFPR = Kind != AArch64ABIKind::AAPCSSoft &&
548+
(BaseTy->isFloatingPointTy() || BaseTy->isVectorTy());
542549

543550
// The AArch64 va_list type and handling is specified in the Procedure Call
544551
// Standard, section B.4:

clang/lib/Sema/Sema.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,6 +1944,21 @@ Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID,
19441944
return DB;
19451945
}
19461946

1947+
static bool typeIsOrContainsFloat(const Type &Ty) {
1948+
if (Ty.isFloatingType())
1949+
return true;
1950+
1951+
if (const RecordDecl *Decl = Ty.getAsRecordDecl()) {
1952+
for (const FieldDecl *FD : Decl->fields()) {
1953+
const Type &FieldType = *FD->getType();
1954+
if (typeIsOrContainsFloat(FieldType))
1955+
return true;
1956+
}
1957+
}
1958+
1959+
return false;
1960+
}
1961+
19471962
void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) {
19481963
if (isUnevaluatedContext() || Ty.isNull())
19491964
return;
@@ -2088,6 +2103,25 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) {
20882103
!Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap))
20892104
Diag(D->getLocation(), diag::err_sve_vector_in_non_sve_target) << Ty;
20902105
}
2106+
2107+
// Don't allow any floating-point types (including structs containing
2108+
// floats) for ABIs which do not support them.
2109+
if (!TI.hasFPTypes() && typeIsOrContainsFloat(*UnqualTy)) {
2110+
PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type_for_abi);
2111+
2112+
if (D)
2113+
PD << D;
2114+
else
2115+
PD << "expression";
2116+
2117+
if (Diag(Loc, PD, FD) << Ty << TI.getABI()) {
2118+
if (D)
2119+
D->setInvalidDecl();
2120+
}
2121+
2122+
if (D)
2123+
targetDiag(D->getLocation(), diag::note_defined_here, FD) << D;
2124+
}
20912125
};
20922126

20932127
CheckType(Ty);
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// RUN: %clang_cc1 -triple aarch64 -target-feature +fp-armv8 -target-abi aapcs -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,HARD
2+
// RUN: %clang_cc1 -triple aarch64 -target-feature -fp-armv8 -target-abi aapcs-soft -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,SOFT
3+
4+
// See also llvm/test/CodeGen/AArch64/soft-float-abi.ll, which checks the LLVM
5+
// backend parts of the soft-float ABI.
6+
7+
// The va_list type does not change between the ABIs
8+
// CHECK: %struct.__va_list = type { ptr, ptr, ptr, i32, i32 }
9+
10+
// Floats are passed in integer registers, this will be handled by the backend.
11+
// CHECK: define dso_local half @test0(half noundef %a)
12+
// CHECK: define dso_local bfloat @test1(bfloat noundef %a)
13+
// CHECK: define dso_local float @test2(float noundef %a)
14+
// CHECK: define dso_local double @test3(double noundef %a)
15+
// CHECK: define dso_local fp128 @test4(fp128 noundef %a)
16+
__fp16 test0(__fp16 a) { return a; }
17+
__bf16 test1(__bf16 a) { return a; }
18+
float test2(float a) { return a; }
19+
double test3(double a) { return a; }
20+
long double test4(long double a) { return a; }
21+
22+
// No types are considered to be HFAs or HVAs by the soft-float PCS, so these
23+
// are converted to integer types.
24+
struct A {
25+
float x;
26+
};
27+
// SOFT: define dso_local i32 @test10(i64 %a.coerce)
28+
// HARD: define dso_local %struct.A @test10([1 x float] alignstack(8) %a.coerce)
29+
struct A test10(struct A a) { return a; }
30+
31+
struct B {
32+
double x;
33+
double y;
34+
};
35+
// SOFT: define dso_local [2 x i64] @test11([2 x i64] %a.coerce)
36+
// HARD: define dso_local %struct.B @test11([2 x double] alignstack(8) %a.coerce)
37+
struct B test11(struct B a) { return a; }
38+
39+
#include <stdarg.h>
40+
41+
// For variadic arguments, va_arg will always retreive
42+
// CHECK-LABEL: define dso_local double @test20(i32 noundef %a, ...)
43+
// CHECK: %vl = alloca %struct.__va_list, align 8
44+
// SOFT: %gr_offs_p = getelementptr inbounds %struct.__va_list, ptr %vl, i32 0, i32 3
45+
// SOFT: %reg_top_p = getelementptr inbounds %struct.__va_list, ptr %vl, i32 0, i32 1
46+
// HARD: %vr_offs_p = getelementptr inbounds %struct.__va_list, ptr %vl, i32 0, i32 4
47+
// HARD: %reg_top_p = getelementptr inbounds %struct.__va_list, ptr %vl, i32 0, i32 2
48+
double test20(int a, ...) {
49+
va_list vl;
50+
va_start(vl, a);
51+
return va_arg(vl, double);
52+
}
53+
54+
// Vector types are only available for targets with the correct hardware, and
55+
// their calling-convention is left undefined by the soft-float ABI, so they
56+
// aren't tested here.

clang/test/CodeGen/attr-target-clones-aarch64.c

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes --check-globals --include-generated-funcs
2-
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -emit-llvm -o - %s | FileCheck %s
3-
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fmv -S -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NOFMV
2+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fp-armv8 -S -emit-llvm -o - %s | FileCheck %s
3+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fp-armv8 -target-feature -fmv -S -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NOFMV
44

55
int __attribute__((target_clones("lse+aes", "sve2"))) ftc(void) { return 0; }
66
int __attribute__((target_clones("sha2", "sha2+memtag2", " default "))) ftc_def(void) { return 1; }
@@ -414,23 +414,23 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
414414
// CHECK-NOFMV-NEXT: ret i32 [[ADD5]]
415415
//
416416
//.
417-
// CHECK: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+lse,+neon" }
418-
// CHECK: attributes #[[ATTR1:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2" }
419-
// CHECK: attributes #[[ATTR2:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
420-
// CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+sha2" }
421-
// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+mte,+neon,+sha2" }
422-
// CHECK: attributes #[[ATTR5:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" }
423-
// CHECK: attributes #[[ATTR6:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+dotprod,+fp-armv8,+neon" }
424-
// CHECK: attributes #[[ATTR7:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rand" }
425-
// CHECK: attributes #[[ATTR8:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+predres,+rcpc" }
426-
// CHECK: attributes #[[ATTR9:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+wfxt" }
427-
// CHECK: attributes #[[ATTR10:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
428-
// CHECK: attributes #[[ATTR11:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+complxnum,+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-bitperm" }
429-
// CHECK: attributes #[[ATTR12:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti" }
430-
// CHECK: attributes #[[ATTR13:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sb,+sve" }
417+
// CHECK: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,+neon,-fp-armv8" }
418+
// CHECK: attributes #[[ATTR1:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,-fp-armv8" }
419+
// CHECK: attributes #[[ATTR2:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fp-armv8" }
420+
// CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+sha2,-fp-armv8" }
421+
// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mte,+neon,+sha2,-fp-armv8" }
422+
// CHECK: attributes #[[ATTR5:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,-fp-armv8" }
423+
// CHECK: attributes #[[ATTR6:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+dotprod,+neon,-fp-armv8" }
424+
// CHECK: attributes #[[ATTR7:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+rand,-fp-armv8" }
425+
// CHECK: attributes #[[ATTR8:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+predres,+rcpc,-fp-armv8" }
426+
// CHECK: attributes #[[ATTR9:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,+sve2-aes,+wfxt,-fp-armv8" }
427+
// CHECK: attributes #[[ATTR10:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,-fp-armv8" }
428+
// CHECK: attributes #[[ATTR11:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+complxnum,+fullfp16,+neon,+sve,+sve2,+sve2-bitperm,-fp-armv8" }
429+
// CHECK: attributes #[[ATTR12:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti,-fp-armv8" }
430+
// CHECK: attributes #[[ATTR13:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sb,+sve,-fp-armv8" }
431431
//.
432-
// CHECK-NOFMV: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" }
433-
// CHECK-NOFMV: attributes #[[ATTR1:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" }
432+
// CHECK-NOFMV: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv,-fp-armv8" }
433+
// CHECK-NOFMV: attributes #[[ATTR1:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv,-fp-armv8" }
434434
//.
435435
// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
436436
// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}

0 commit comments

Comments
 (0)