Skip to content

Commit 1f80d30

Browse files
committed
[AArch64] SME implementation for agnostic-ZA functions
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 b85ddba commit 1f80d30

12 files changed

+342
-38
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: 127 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,39 @@ 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->getSMESaveBufferUsed()) {
3247+
// Allocate a lazy-save buffer object of the size given, normally SVL * SVL
3248+
auto Size = MI.getOperand(1).getReg();
3249+
auto Dest = MI.getOperand(0).getReg();
3250+
BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(AArch64::SUBXrx64), Dest)
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),
3255+
AArch64::SP)
3256+
.addReg(Dest);
3257+
3258+
// We have just allocated a variable sized object, tell this to PEI.
3259+
MFI.CreateVariableSizedObject(Align(16), nullptr);
3260+
} else
3261+
BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::IMPLICIT_DEF),
3262+
MI.getOperand(0).getReg());
3263+
3264+
BB->remove_instr(&MI);
3265+
return BB;
3266+
}
3267+
32333268
MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
32343269
MachineInstr &MI, MachineBasicBlock *BB) const {
32353270

@@ -3264,6 +3299,31 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
32643299
return EmitInitTPIDR2Object(MI, BB);
32653300
case AArch64::AllocateZABuffer:
32663301
return EmitAllocateZABuffer(MI, BB);
3302+
case AArch64::AllocateSMESaveBuffer:
3303+
return EmitAllocateSMESaveBuffer(MI, BB);
3304+
case AArch64::GetSMESaveSize: {
3305+
// If the buffer is used, emit a call to __arm_sme_state_size()
3306+
MachineFunction *MF = BB->getParent();
3307+
AArch64FunctionInfo *FuncInfo = MF->getInfo<AArch64FunctionInfo>();
3308+
const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3309+
if (FuncInfo->getSMESaveBufferUsed()) {
3310+
const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo();
3311+
BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(AArch64::BL))
3312+
.addExternalSymbol("__arm_sme_state_size")
3313+
.addReg(AArch64::X0, RegState::ImplicitDefine)
3314+
.addRegMask(TRI->getCallPreservedMask(
3315+
*MF, CallingConv::
3316+
AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1));
3317+
BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),
3318+
MI.getOperand(0).getReg())
3319+
.addReg(AArch64::X0);
3320+
} else
3321+
BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(TargetOpcode::COPY),
3322+
MI.getOperand(0).getReg())
3323+
.addReg(AArch64::XZR);
3324+
BB->remove_instr(&MI);
3325+
return BB;
3326+
}
32673327
case AArch64::F128CSEL:
32683328
return EmitF128CSEL(MI, BB);
32693329
case TargetOpcode::STATEPOINT:
@@ -7663,6 +7723,7 @@ CCAssignFn *AArch64TargetLowering::CCAssignFnForCall(CallingConv::ID CC,
76637723
case CallingConv::AArch64_VectorCall:
76647724
case CallingConv::AArch64_SVE_VectorCall:
76657725
case CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0:
7726+
case CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1:
76667727
case CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2:
76677728
return CC_AArch64_AAPCS;
76687729
case CallingConv::ARM64EC_Thunk_X64:
@@ -8122,6 +8183,31 @@ SDValue AArch64TargetLowering::LowerFormalArguments(
81228183
Chain = DAG.getNode(
81238184
AArch64ISD::INIT_TPIDR2OBJ, DL, DAG.getVTList(MVT::Other),
81248185
{/*Chain*/ Buffer.getValue(1), /*Buffer ptr*/ Buffer.getValue(0)});
8186+
} else if (SMEAttrs(MF.getFunction()).hasAgnosticZAInterface()) {
8187+
// Call __arm_sme_state_size().
8188+
SDValue BufferSize =
8189+
DAG.getNode(AArch64ISD::GET_SME_SAVE_SIZE, DL,
8190+
DAG.getVTList(MVT::i64, MVT::Other), Chain);
8191+
Chain = BufferSize.getValue(1);
8192+
8193+
SDValue Buffer;
8194+
if (!Subtarget->isTargetWindows() && !hasInlineStackProbe(MF)) {
8195+
Buffer =
8196+
DAG.getNode(AArch64ISD::ALLOC_SME_SAVE_BUFFER, DL,
8197+
DAG.getVTList(MVT::i64, MVT::Other), {Chain, BufferSize});
8198+
} else {
8199+
// Allocate space dynamically.
8200+
Buffer = DAG.getNode(
8201+
ISD::DYNAMIC_STACKALLOC, DL, DAG.getVTList(MVT::i64, MVT::Other),
8202+
{Chain, BufferSize, DAG.getConstant(1, DL, MVT::i64)});
8203+
MFI.CreateVariableSizedObject(Align(16), nullptr);
8204+
}
8205+
8206+
// Copy the value to a virtual register, and save that in FuncInfo.
8207+
Register BufferPtr =
8208+
MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
8209+
FuncInfo->setSMESaveBufferAddr(BufferPtr);
8210+
Chain = DAG.getCopyToReg(Chain, DL, BufferPtr, Buffer);
81258211
}
81268212

81278213
if (CallConv == CallingConv::PreserveNone) {
@@ -8410,6 +8496,7 @@ bool AArch64TargetLowering::isEligibleForTailCallOptimization(
84108496
auto CalleeAttrs = CLI.CB ? SMEAttrs(*CLI.CB) : SMEAttrs(SMEAttrs::Normal);
84118497
if (CallerAttrs.requiresSMChange(CalleeAttrs) ||
84128498
CallerAttrs.requiresLazySave(CalleeAttrs) ||
8499+
CallerAttrs.requiresPreservingAllZAState(CalleeAttrs) ||
84138500
CallerAttrs.hasStreamingBody())
84148501
return false;
84158502

@@ -8734,6 +8821,30 @@ SDValue AArch64TargetLowering::changeStreamingMode(SelectionDAG &DAG, SDLoc DL,
87348821
return DAG.getNode(Opcode, DL, DAG.getVTList(MVT::Other, MVT::Glue), Ops);
87358822
}
87368823

8824+
// Emit a call to __arm_sme_save or __arm_sme_restore.
8825+
static SDValue emitSMEStateSaveRestore(const AArch64TargetLowering &TLI,
8826+
SelectionDAG &DAG,
8827+
AArch64FunctionInfo *Info, SDLoc DL,
8828+
SDValue Chain, bool IsSave) {
8829+
TargetLowering::ArgListTy Args;
8830+
TargetLowering::ArgListEntry Entry;
8831+
Entry.Ty = PointerType::getUnqual(*DAG.getContext());
8832+
Entry.Node =
8833+
DAG.getCopyFromReg(Chain, DL, Info->getSMESaveBufferAddr(), MVT::i64);
8834+
Args.push_back(Entry);
8835+
8836+
SDValue Callee =
8837+
DAG.getExternalSymbol(IsSave ? "__arm_sme_save" : "__arm_sme_restore",
8838+
TLI.getPointerTy(DAG.getDataLayout()));
8839+
auto *RetTy = Type::getVoidTy(*DAG.getContext());
8840+
TargetLowering::CallLoweringInfo CLI(DAG);
8841+
CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
8842+
CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X1, RetTy,
8843+
Callee, std::move(Args));
8844+
8845+
return TLI.LowerCallTo(CLI).second;
8846+
}
8847+
87378848
static unsigned getSMCondition(const SMEAttrs &CallerAttrs,
87388849
const SMEAttrs &CalleeAttrs) {
87398850
if (!CallerAttrs.hasStreamingCompatibleInterface() ||
@@ -8894,6 +9005,9 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
88949005
};
88959006

88969007
bool RequiresLazySave = CallerAttrs.requiresLazySave(CalleeAttrs);
9008+
bool RequiresSaveAllZA =
9009+
CallerAttrs.requiresPreservingAllZAState(CalleeAttrs);
9010+
SDValue ZAStateBuffer;
88979011
if (RequiresLazySave) {
88989012
const TPIDR2Object &TPIDR2 = FuncInfo->getTPIDR2Obj();
88999013
MachinePointerInfo MPI =
@@ -8920,6 +9034,11 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
89209034
&MF.getFunction());
89219035
return DescribeCallsite(R) << " sets up a lazy save for ZA";
89229036
});
9037+
} else if (RequiresSaveAllZA) {
9038+
assert(!CalleeAttrs.hasSharedZAInterface() &&
9039+
"Cannot share state that may not exist");
9040+
Chain = emitSMEStateSaveRestore(*this, DAG, FuncInfo, DL, Chain,
9041+
/*IsSave=*/true);
89239042
}
89249043

89259044
SDValue PStateSM;
@@ -9467,9 +9586,14 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
94679586
DAG.getConstant(Intrinsic::aarch64_sme_set_tpidr2, DL, MVT::i32),
94689587
DAG.getConstant(0, DL, MVT::i64));
94699588
TPIDR2.Uses++;
9589+
} else if (RequiresSaveAllZA) {
9590+
Result = emitSMEStateSaveRestore(*this, DAG, FuncInfo, DL, Chain,
9591+
/*IsSave=*/false);
9592+
FuncInfo->setSMESaveBufferUsed();
94709593
}
94719594

9472-
if (RequiresSMChange || RequiresLazySave || ShouldPreserveZT0) {
9595+
if (RequiresSMChange || RequiresLazySave || ShouldPreserveZT0 ||
9596+
RequiresSaveAllZA) {
94739597
for (unsigned I = 0; I < InVals.size(); ++I) {
94749598
// The smstart/smstop is chained as part of the call, but when the
94759599
// resulting chain is discarded (which happens when the call is not part
@@ -28084,7 +28208,8 @@ bool AArch64TargetLowering::fallBackToDAGISel(const Instruction &Inst) const {
2808428208
auto CalleeAttrs = SMEAttrs(*Base);
2808528209
if (CallerAttrs.requiresSMChange(CalleeAttrs) ||
2808628210
CallerAttrs.requiresLazySave(CalleeAttrs) ||
28087-
CallerAttrs.requiresPreservingZT0(CalleeAttrs))
28211+
CallerAttrs.requiresPreservingZT0(CalleeAttrs) ||
28212+
CallerAttrs.requiresPreservingAllZAState(CalleeAttrs))
2808828213
return true;
2808928214
}
2809028215
return false;

llvm/lib/Target/AArch64/AArch64ISelLowering.h

Lines changed: 6 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,8 @@ 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;
670676

671677
MachineBasicBlock *
672678
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 getSMESaveBufferUsed() 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: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,13 @@ 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)) {
266+
if (hasPossibleIncompatibleOps(Callee))
267+
return false;
268+
}
269+
270+
if (CalleeAttrs.hasAgnosticZAInterface()) {
265271
if (hasPossibleIncompatibleOps(Callee))
266272
return false;
267273
}

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)