Skip to content

Commit 2ce168b

Browse files
[AArch64] SME implementation for agnostic-ZA functions (#120150)
This implements the lowering of calls from agnostic-ZA functions to non-agnostic-ZA functions, using the ABI routines `__arm_sme_state_size`, `__arm_sme_save` and `__arm_sme_restore`. This implements the proposal described in the following PRs: * ARM-software/acle#336 * ARM-software/abi-aa#264
1 parent d8e7929 commit 2ce168b

13 files changed

+486
-41
lines changed

llvm/lib/IR/Verifier.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2268,19 +2268,23 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
22682268
Check((Attrs.hasFnAttr("aarch64_new_za") + Attrs.hasFnAttr("aarch64_in_za") +
22692269
Attrs.hasFnAttr("aarch64_inout_za") +
22702270
Attrs.hasFnAttr("aarch64_out_za") +
2271-
Attrs.hasFnAttr("aarch64_preserves_za")) <= 1,
2271+
Attrs.hasFnAttr("aarch64_preserves_za") +
2272+
Attrs.hasFnAttr("aarch64_za_state_agnostic")) <= 1,
22722273
"Attributes 'aarch64_new_za', 'aarch64_in_za', 'aarch64_out_za', "
2273-
"'aarch64_inout_za' and 'aarch64_preserves_za' are mutually exclusive",
2274+
"'aarch64_inout_za', 'aarch64_preserves_za' and "
2275+
"'aarch64_za_state_agnostic' are mutually exclusive",
22742276
V);
22752277

2276-
Check(
2277-
(Attrs.hasFnAttr("aarch64_new_zt0") + Attrs.hasFnAttr("aarch64_in_zt0") +
2278-
Attrs.hasFnAttr("aarch64_inout_zt0") +
2279-
Attrs.hasFnAttr("aarch64_out_zt0") +
2280-
Attrs.hasFnAttr("aarch64_preserves_zt0")) <= 1,
2281-
"Attributes 'aarch64_new_zt0', 'aarch64_in_zt0', 'aarch64_out_zt0', "
2282-
"'aarch64_inout_zt0' and 'aarch64_preserves_zt0' are mutually exclusive",
2283-
V);
2278+
Check((Attrs.hasFnAttr("aarch64_new_zt0") +
2279+
Attrs.hasFnAttr("aarch64_in_zt0") +
2280+
Attrs.hasFnAttr("aarch64_inout_zt0") +
2281+
Attrs.hasFnAttr("aarch64_out_zt0") +
2282+
Attrs.hasFnAttr("aarch64_preserves_zt0") +
2283+
Attrs.hasFnAttr("aarch64_za_state_agnostic")) <= 1,
2284+
"Attributes 'aarch64_new_zt0', 'aarch64_in_zt0', 'aarch64_out_zt0', "
2285+
"'aarch64_inout_zt0', 'aarch64_preserves_zt0' and "
2286+
"'aarch64_za_state_agnostic' are mutually exclusive",
2287+
V);
22842288

22852289
if (Attrs.hasFnAttr(Attribute::JumpTable)) {
22862290
const GlobalValue *GV = cast<GlobalValue>(V);

llvm/lib/Target/AArch64/AArch64FastISel.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5197,7 +5197,8 @@ FastISel *AArch64::createFastISel(FunctionLoweringInfo &FuncInfo,
51975197
SMEAttrs CallerAttrs(*FuncInfo.Fn);
51985198
if (CallerAttrs.hasZAState() || CallerAttrs.hasZT0State() ||
51995199
CallerAttrs.hasStreamingInterfaceOrBody() ||
5200-
CallerAttrs.hasStreamingCompatibleInterface())
5200+
CallerAttrs.hasStreamingCompatibleInterface() ||
5201+
CallerAttrs.hasAgnosticZAInterface())
52015202
return nullptr;
52025203
return new AArch64FastISel(FuncInfo, LibInfo);
52035204
}

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 132 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2643,6 +2643,8 @@ const char *AArch64TargetLowering::getTargetNodeName(unsigned Opcode) const {
26432643
break;
26442644
MAKE_CASE(AArch64ISD::ALLOCATE_ZA_BUFFER)
26452645
MAKE_CASE(AArch64ISD::INIT_TPIDR2OBJ)
2646+
MAKE_CASE(AArch64ISD::GET_SME_SAVE_SIZE)
2647+
MAKE_CASE(AArch64ISD::ALLOC_SME_SAVE_BUFFER)
26462648
MAKE_CASE(AArch64ISD::COALESCER_BARRIER)
26472649
MAKE_CASE(AArch64ISD::VG_SAVE)
26482650
MAKE_CASE(AArch64ISD::VG_RESTORE)
@@ -3230,6 +3232,64 @@ AArch64TargetLowering::EmitAllocateZABuffer(MachineInstr &MI,
32303232
return BB;
32313233
}
32323234

3235+
// TODO: Find a way to merge this with EmitAllocateZABuffer.
3236+
MachineBasicBlock *
3237+
AArch64TargetLowering::EmitAllocateSMESaveBuffer(MachineInstr &MI,
3238+
MachineBasicBlock *BB) const {
3239+
MachineFunction *MF = BB->getParent();
3240+
MachineFrameInfo &MFI = MF->getFrameInfo();
3241+
AArch64FunctionInfo *FuncInfo = MF->getInfo<AArch64FunctionInfo>();
3242+
assert(!MF->getSubtarget<AArch64Subtarget>().isTargetWindows() &&
3243+
"Lazy ZA save is not yet supported on Windows");
3244+
3245+
const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3246+
if (FuncInfo->isSMESaveBufferUsed()) {
3247+
// Allocate a buffer object of the size given by MI.getOperand(1).
3248+
auto Size = MI.getOperand(1).getReg();
3249+
auto Dest = MI.getOperand(0).getReg();
3250+
BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(AArch64::SUBXrx64), AArch64::SP)
3251+
.addReg(AArch64::SP)
3252+
.addReg(Size)
3253+
.addImm(AArch64_AM::getArithExtendImm(AArch64_AM::UXTX, 0));
3254+
BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY), Dest)
3255+
.addReg(AArch64::SP);
3256+
3257+
// We have just allocated a variable sized object, tell this to PEI.
3258+
MFI.CreateVariableSizedObject(Align(16), nullptr);
3259+
} else
3260+
BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::IMPLICIT_DEF),
3261+
MI.getOperand(0).getReg());
3262+
3263+
BB->remove_instr(&MI);
3264+
return BB;
3265+
}
3266+
3267+
MachineBasicBlock *
3268+
AArch64TargetLowering::EmitGetSMESaveSize(MachineInstr &MI,
3269+
MachineBasicBlock *BB) const {
3270+
// If the buffer is used, emit a call to __arm_sme_state_size()
3271+
MachineFunction *MF = BB->getParent();
3272+
AArch64FunctionInfo *FuncInfo = MF->getInfo<AArch64FunctionInfo>();
3273+
const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3274+
if (FuncInfo->isSMESaveBufferUsed()) {
3275+
const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo();
3276+
BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(AArch64::BL))
3277+
.addExternalSymbol("__arm_sme_state_size")
3278+
.addReg(AArch64::X0, RegState::ImplicitDefine)
3279+
.addRegMask(TRI->getCallPreservedMask(
3280+
*MF, CallingConv::
3281+
AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1));
3282+
BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),
3283+
MI.getOperand(0).getReg())
3284+
.addReg(AArch64::X0);
3285+
} else
3286+
BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),
3287+
MI.getOperand(0).getReg())
3288+
.addReg(AArch64::XZR);
3289+
BB->remove_instr(&MI);
3290+
return BB;
3291+
}
3292+
32333293
MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
32343294
MachineInstr &MI, MachineBasicBlock *BB) const {
32353295

@@ -3264,6 +3324,10 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
32643324
return EmitInitTPIDR2Object(MI, BB);
32653325
case AArch64::AllocateZABuffer:
32663326
return EmitAllocateZABuffer(MI, BB);
3327+
case AArch64::AllocateSMESaveBuffer:
3328+
return EmitAllocateSMESaveBuffer(MI, BB);
3329+
case AArch64::GetSMESaveSize:
3330+
return EmitGetSMESaveSize(MI, BB);
32673331
case AArch64::F128CSEL:
32683332
return EmitF128CSEL(MI, BB);
32693333
case TargetOpcode::STATEPOINT:
@@ -7663,6 +7727,7 @@ CCAssignFn *AArch64TargetLowering::CCAssignFnForCall(CallingConv::ID CC,
76637727
case CallingConv::AArch64_VectorCall:
76647728
case CallingConv::AArch64_SVE_VectorCall:
76657729
case CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0:
7730+
case CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1:
76667731
case CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2:
76677732
return CC_AArch64_AAPCS;
76687733
case CallingConv::ARM64EC_Thunk_X64:
@@ -8122,6 +8187,31 @@ SDValue AArch64TargetLowering::LowerFormalArguments(
81228187
Chain = DAG.getNode(
81238188
AArch64ISD::INIT_TPIDR2OBJ, DL, DAG.getVTList(MVT::Other),
81248189
{/*Chain*/ Buffer.getValue(1), /*Buffer ptr*/ Buffer.getValue(0)});
8190+
} else if (SMEAttrs(MF.getFunction()).hasAgnosticZAInterface()) {
8191+
// Call __arm_sme_state_size().
8192+
SDValue BufferSize =
8193+
DAG.getNode(AArch64ISD::GET_SME_SAVE_SIZE, DL,
8194+
DAG.getVTList(MVT::i64, MVT::Other), Chain);
8195+
Chain = BufferSize.getValue(1);
8196+
8197+
SDValue Buffer;
8198+
if (!Subtarget->isTargetWindows() && !hasInlineStackProbe(MF)) {
8199+
Buffer =
8200+
DAG.getNode(AArch64ISD::ALLOC_SME_SAVE_BUFFER, DL,
8201+
DAG.getVTList(MVT::i64, MVT::Other), {Chain, BufferSize});
8202+
} else {
8203+
// Allocate space dynamically.
8204+
Buffer = DAG.getNode(
8205+
ISD::DYNAMIC_STACKALLOC, DL, DAG.getVTList(MVT::i64, MVT::Other),
8206+
{Chain, BufferSize, DAG.getConstant(1, DL, MVT::i64)});
8207+
MFI.CreateVariableSizedObject(Align(16), nullptr);
8208+
}
8209+
8210+
// Copy the value to a virtual register, and save that in FuncInfo.
8211+
Register BufferPtr =
8212+
MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
8213+
FuncInfo->setSMESaveBufferAddr(BufferPtr);
8214+
Chain = DAG.getCopyToReg(Chain, DL, BufferPtr, Buffer);
81258215
}
81268216

81278217
if (CallConv == CallingConv::PreserveNone) {
@@ -8410,6 +8500,7 @@ bool AArch64TargetLowering::isEligibleForTailCallOptimization(
84108500
auto CalleeAttrs = CLI.CB ? SMEAttrs(*CLI.CB) : SMEAttrs(SMEAttrs::Normal);
84118501
if (CallerAttrs.requiresSMChange(CalleeAttrs) ||
84128502
CallerAttrs.requiresLazySave(CalleeAttrs) ||
8503+
CallerAttrs.requiresPreservingAllZAState(CalleeAttrs) ||
84138504
CallerAttrs.hasStreamingBody())
84148505
return false;
84158506

@@ -8734,6 +8825,33 @@ SDValue AArch64TargetLowering::changeStreamingMode(SelectionDAG &DAG, SDLoc DL,
87348825
return DAG.getNode(Opcode, DL, DAG.getVTList(MVT::Other, MVT::Glue), Ops);
87358826
}
87368827

8828+
// Emit a call to __arm_sme_save or __arm_sme_restore.
8829+
static SDValue emitSMEStateSaveRestore(const AArch64TargetLowering &TLI,
8830+
SelectionDAG &DAG,
8831+
AArch64FunctionInfo *Info, SDLoc DL,
8832+
SDValue Chain, bool IsSave) {
8833+
MachineFunction &MF = DAG.getMachineFunction();
8834+
AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
8835+
FuncInfo->setSMESaveBufferUsed();
8836+
8837+
TargetLowering::ArgListTy Args;
8838+
TargetLowering::ArgListEntry Entry;
8839+
Entry.Ty = PointerType::getUnqual(*DAG.getContext());
8840+
Entry.Node =
8841+
DAG.getCopyFromReg(Chain, DL, Info->getSMESaveBufferAddr(), MVT::i64);
8842+
Args.push_back(Entry);
8843+
8844+
SDValue Callee =
8845+
DAG.getExternalSymbol(IsSave ? "__arm_sme_save" : "__arm_sme_restore",
8846+
TLI.getPointerTy(DAG.getDataLayout()));
8847+
auto *RetTy = Type::getVoidTy(*DAG.getContext());
8848+
TargetLowering::CallLoweringInfo CLI(DAG);
8849+
CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
8850+
CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1, RetTy,
8851+
Callee, std::move(Args));
8852+
return TLI.LowerCallTo(CLI).second;
8853+
}
8854+
87378855
static unsigned getSMCondition(const SMEAttrs &CallerAttrs,
87388856
const SMEAttrs &CalleeAttrs) {
87398857
if (!CallerAttrs.hasStreamingCompatibleInterface() ||
@@ -8894,6 +9012,8 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
88949012
};
88959013

88969014
bool RequiresLazySave = CallerAttrs.requiresLazySave(CalleeAttrs);
9015+
bool RequiresSaveAllZA =
9016+
CallerAttrs.requiresPreservingAllZAState(CalleeAttrs);
88979017
if (RequiresLazySave) {
88989018
const TPIDR2Object &TPIDR2 = FuncInfo->getTPIDR2Obj();
88999019
MachinePointerInfo MPI =
@@ -8920,6 +9040,11 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
89209040
&MF.getFunction());
89219041
return DescribeCallsite(R) << " sets up a lazy save for ZA";
89229042
});
9043+
} else if (RequiresSaveAllZA) {
9044+
assert(!CalleeAttrs.hasSharedZAInterface() &&
9045+
"Cannot share state that may not exist");
9046+
Chain = emitSMEStateSaveRestore(*this, DAG, FuncInfo, DL, Chain,
9047+
/*IsSave=*/true);
89239048
}
89249049

89259050
SDValue PStateSM;
@@ -9467,9 +9592,13 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
94679592
DAG.getConstant(Intrinsic::aarch64_sme_set_tpidr2, DL, MVT::i32),
94689593
DAG.getConstant(0, DL, MVT::i64));
94699594
TPIDR2.Uses++;
9595+
} else if (RequiresSaveAllZA) {
9596+
Result = emitSMEStateSaveRestore(*this, DAG, FuncInfo, DL, Chain,
9597+
/*IsSave=*/false);
94709598
}
94719599

9472-
if (RequiresSMChange || RequiresLazySave || ShouldPreserveZT0) {
9600+
if (RequiresSMChange || RequiresLazySave || ShouldPreserveZT0 ||
9601+
RequiresSaveAllZA) {
94739602
for (unsigned I = 0; I < InVals.size(); ++I) {
94749603
// The smstart/smstop is chained as part of the call, but when the
94759604
// resulting chain is discarded (which happens when the call is not part
@@ -28084,7 +28213,8 @@ bool AArch64TargetLowering::fallBackToDAGISel(const Instruction &Inst) const {
2808428213
auto CalleeAttrs = SMEAttrs(*Base);
2808528214
if (CallerAttrs.requiresSMChange(CalleeAttrs) ||
2808628215
CallerAttrs.requiresLazySave(CalleeAttrs) ||
28087-
CallerAttrs.requiresPreservingZT0(CalleeAttrs))
28216+
CallerAttrs.requiresPreservingZT0(CalleeAttrs) ||
28217+
CallerAttrs.requiresPreservingAllZAState(CalleeAttrs))
2808828218
return true;
2808928219
}
2809028220
return false;

llvm/lib/Target/AArch64/AArch64ISelLowering.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,10 @@ enum NodeType : unsigned {
466466
ALLOCATE_ZA_BUFFER,
467467
INIT_TPIDR2OBJ,
468468

469+
// Needed for __arm_agnostic("sme_za_state")
470+
GET_SME_SAVE_SIZE,
471+
ALLOC_SME_SAVE_BUFFER,
472+
469473
// Asserts that a function argument (i32) is zero-extended to i8 by
470474
// the caller
471475
ASSERT_ZEXT_BOOL,
@@ -667,6 +671,10 @@ class AArch64TargetLowering : public TargetLowering {
667671
MachineBasicBlock *BB) const;
668672
MachineBasicBlock *EmitAllocateZABuffer(MachineInstr &MI,
669673
MachineBasicBlock *BB) const;
674+
MachineBasicBlock *EmitAllocateSMESaveBuffer(MachineInstr &MI,
675+
MachineBasicBlock *BB) const;
676+
MachineBasicBlock *EmitGetSMESaveSize(MachineInstr &MI,
677+
MachineBasicBlock *BB) const;
670678

671679
MachineBasicBlock *
672680
EmitInstrWithCustomInserter(MachineInstr &MI,

llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,14 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
229229
// on function entry to record the initial pstate of a function.
230230
Register PStateSMReg = MCRegister::NoRegister;
231231

232+
// Holds a pointer to a buffer that is large enough to represent
233+
// all SME ZA state and any additional state required by the
234+
// __arm_sme_save/restore support routines.
235+
Register SMESaveBufferAddr = MCRegister::NoRegister;
236+
237+
// true if SMESaveBufferAddr is used.
238+
bool SMESaveBufferUsed = false;
239+
232240
// Has the PNReg used to build PTRUE instruction.
233241
// The PTRUE is used for the LD/ST of ZReg pairs in save and restore.
234242
unsigned PredicateRegForFillSpill = 0;
@@ -252,6 +260,12 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
252260
return PredicateRegForFillSpill;
253261
}
254262

263+
Register getSMESaveBufferAddr() const { return SMESaveBufferAddr; };
264+
void setSMESaveBufferAddr(Register Reg) { SMESaveBufferAddr = Reg; };
265+
266+
unsigned isSMESaveBufferUsed() const { return SMESaveBufferUsed; };
267+
void setSMESaveBufferUsed(bool Used = true) { SMESaveBufferUsed = Used; };
268+
255269
Register getPStateSMReg() const { return PStateSMReg; };
256270
void setPStateSMReg(Register Reg) { PStateSMReg = Reg; };
257271

llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,22 @@ let usesCustomInserter = 1 in {
5252
def InitTPIDR2Obj : Pseudo<(outs), (ins GPR64:$buffer), [(AArch64InitTPIDR2Obj GPR64:$buffer)]>, Sched<[WriteI]> {}
5353
}
5454

55+
// Nodes to allocate a save buffer for SME.
56+
def AArch64SMESaveSize : SDNode<"AArch64ISD::GET_SME_SAVE_SIZE", SDTypeProfile<1, 0,
57+
[SDTCisInt<0>]>, [SDNPHasChain]>;
58+
let usesCustomInserter = 1, Defs = [X0] in {
59+
def GetSMESaveSize : Pseudo<(outs GPR64:$dst), (ins), []>, Sched<[]> {}
60+
}
61+
def : Pat<(i64 AArch64SMESaveSize), (GetSMESaveSize)>;
62+
63+
def AArch64AllocateSMESaveBuffer : SDNode<"AArch64ISD::ALLOC_SME_SAVE_BUFFER", SDTypeProfile<1, 1,
64+
[SDTCisInt<0>, SDTCisInt<1>]>, [SDNPHasChain]>;
65+
let usesCustomInserter = 1, Defs = [SP] in {
66+
def AllocateSMESaveBuffer : Pseudo<(outs GPR64sp:$dst), (ins GPR64:$size), []>, Sched<[WriteI]> {}
67+
}
68+
def : Pat<(i64 (AArch64AllocateSMESaveBuffer GPR64:$size)),
69+
(AllocateSMESaveBuffer $size)>;
70+
5571
//===----------------------------------------------------------------------===//
5672
// Instruction naming conventions.
5773
//===----------------------------------------------------------------------===//

llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,8 @@ bool AArch64TTIImpl::areInlineCompatible(const Function *Caller,
261261

262262
if (CallerAttrs.requiresLazySave(CalleeAttrs) ||
263263
CallerAttrs.requiresSMChange(CalleeAttrs) ||
264-
CallerAttrs.requiresPreservingZT0(CalleeAttrs)) {
264+
CallerAttrs.requiresPreservingZT0(CalleeAttrs) ||
265+
CallerAttrs.requiresPreservingAllZAState(CalleeAttrs)) {
265266
if (hasPossibleIncompatibleOps(Callee))
266267
return false;
267268
}

llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ void SMEAttrs::set(unsigned M, bool Enable) {
3838
isPreservesZT0())) &&
3939
"Attributes 'aarch64_new_zt0', 'aarch64_in_zt0', 'aarch64_out_zt0', "
4040
"'aarch64_inout_zt0' and 'aarch64_preserves_zt0' are mutually exclusive");
41+
42+
assert(!(hasAgnosticZAInterface() && hasSharedZAInterface()) &&
43+
"Function cannot have a shared-ZA interface and an agnostic-ZA "
44+
"interface");
4145
}
4246

4347
SMEAttrs::SMEAttrs(const CallBase &CB) {
@@ -56,6 +60,9 @@ SMEAttrs::SMEAttrs(StringRef FuncName) : Bitmask(0) {
5660
if (FuncName == "__arm_sc_memcpy" || FuncName == "__arm_sc_memset" ||
5761
FuncName == "__arm_sc_memmove" || FuncName == "__arm_sc_memchr")
5862
Bitmask |= SMEAttrs::SM_Compatible;
63+
if (FuncName == "__arm_sme_save" || FuncName == "__arm_sme_restore" ||
64+
FuncName == "__arm_sme_state_size")
65+
Bitmask |= SMEAttrs::SM_Compatible | SMEAttrs::SME_ABI_Routine;
5966
}
6067

6168
SMEAttrs::SMEAttrs(const AttributeList &Attrs) {
@@ -66,6 +73,8 @@ SMEAttrs::SMEAttrs(const AttributeList &Attrs) {
6673
Bitmask |= SM_Compatible;
6774
if (Attrs.hasFnAttr("aarch64_pstate_sm_body"))
6875
Bitmask |= SM_Body;
76+
if (Attrs.hasFnAttr("aarch64_za_state_agnostic"))
77+
Bitmask |= ZA_State_Agnostic;
6978
if (Attrs.hasFnAttr("aarch64_in_za"))
7079
Bitmask |= encodeZAState(StateValue::In);
7180
if (Attrs.hasFnAttr("aarch64_out_za"))

0 commit comments

Comments
 (0)