Skip to content

Commit

Permalink
[AArch64] Replace LLVM IR function attributes for PSTATE.ZA. (#79166)
Browse files Browse the repository at this point in the history
Since ARM-software/acle#276 the ACLE
defines attributes to better describe the use of a given SME state.

Previously the attributes merely described the possibility of it being
'shared' or 'preserved', whereas the new attributes have more semantics
and also describe how the data flows through the program.

For ZT0 we already had to add new LLVM IR attributes:
* aarch64_new_zt0
* aarch64_in_zt0
* aarch64_out_zt0
* aarch64_inout_zt0
* aarch64_preserves_zt0

We have now done the same for ZA, such that we add:
* aarch64_new_za       (previously `aarch64_pstate_za_new`)
* aarch64_in_za (more specific variation of `aarch64_pstate_za_shared`)
* aarch64_out_za (more specific variation of `aarch64_pstate_za_shared`)
* aarch64_inout_za (more specific variation of
`aarch64_pstate_za_shared`)
* aarch64_preserves_za (previously `aarch64_pstate_za_shared,
aarch64_pstate_za_preserved`)

This explicitly removes 'pstate' from the name, because with SME2 and
the new ACLE attributes there is a difference between "sharing ZA"
(sharing
the ZA matrix register with the caller) and "sharing PSTATE.ZA" (sharing
either the ZA or ZT0 register, both part of PSTATE.ZA with the caller).
  • Loading branch information
sdesmalen-arm committed Feb 1, 2024
1 parent f956e7f commit d313614
Show file tree
Hide file tree
Showing 28 changed files with 350 additions and 211 deletions.
6 changes: 2 additions & 4 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10676,10 +10676,8 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
llvm::FunctionType::get(StructType::get(CGM.Int64Ty, CGM.Int64Ty), {},
false),
"__arm_sme_state"));
auto Attrs =
AttributeList()
.addFnAttribute(getLLVMContext(), "aarch64_pstate_sm_compatible")
.addFnAttribute(getLLVMContext(), "aarch64_pstate_za_preserved");
auto Attrs = AttributeList().addFnAttribute(getLLVMContext(),
"aarch64_pstate_sm_compatible");
CI->setAttributes(Attrs);
CI->setCallingConv(
llvm::CallingConv::
Expand Down
16 changes: 8 additions & 8 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1774,14 +1774,14 @@ static void AddAttributesFromFunctionProtoType(ASTContext &Ctx,
FuncAttrs.addAttribute("aarch64_pstate_sm_compatible");

// ZA
if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Out ||
FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_InOut)
FuncAttrs.addAttribute("aarch64_pstate_za_shared");
if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Preserves ||
FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_In) {
FuncAttrs.addAttribute("aarch64_pstate_za_shared");
FuncAttrs.addAttribute("aarch64_pstate_za_preserved");
}
if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Preserves)
FuncAttrs.addAttribute("aarch64_preserves_za");
if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_In)
FuncAttrs.addAttribute("aarch64_in_za");
if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Out)
FuncAttrs.addAttribute("aarch64_out_za");
if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_InOut)
FuncAttrs.addAttribute("aarch64_inout_za");

// ZT0
if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_Preserves)
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2414,7 +2414,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,

if (auto *Attr = D->getAttr<ArmNewAttr>()) {
if (Attr->isNewZA())
B.addAttribute("aarch64_pstate_za_new");
B.addAttribute("aarch64_new_za");
if (Attr->isNewZT0())
B.addAttribute("aarch64_new_zt0");
}
Expand Down
18 changes: 9 additions & 9 deletions clang/test/CodeGen/aarch64-sme-intrinsics/aarch64-sme-attrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,20 +284,20 @@ int test_variadic_template() __arm_inout("za") {
// CHECK: attributes #[[SM_COMPATIBLE]] = { mustprogress noinline nounwind "aarch64_pstate_sm_compatible" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[SM_COMPATIBLE_DECL]] = { "aarch64_pstate_sm_compatible" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[SM_BODY]] = { mustprogress noinline nounwind "aarch64_pstate_sm_body" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_SHARED]] = { mustprogress noinline nounwind "aarch64_pstate_za_shared" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_SHARED_DECL]] = { "aarch64_pstate_za_shared" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_PRESERVED]] = { mustprogress noinline nounwind "aarch64_pstate_za_preserved" "aarch64_pstate_za_shared" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_PRESERVED_DECL]] = { "aarch64_pstate_za_preserved" "aarch64_pstate_za_shared" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_NEW]] = { mustprogress noinline nounwind "aarch64_pstate_za_new" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_SHARED]] = { mustprogress noinline nounwind "aarch64_inout_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_SHARED_DECL]] = { "aarch64_inout_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_PRESERVED]] = { mustprogress noinline nounwind "aarch64_preserves_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_PRESERVED_DECL]] = { "aarch64_preserves_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ZA_NEW]] = { mustprogress noinline nounwind "aarch64_new_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[NORMAL_DEF]] = { mustprogress noinline nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[SM_ENABLED_CALL]] = { "aarch64_pstate_sm_enabled" }
// CHECK: attributes #[[SM_COMPATIBLE_CALL]] = { "aarch64_pstate_sm_compatible" }
// CHECK: attributes #[[SM_BODY_CALL]] = { "aarch64_pstate_sm_body" }
// CHECK: attributes #[[ZA_SHARED_CALL]] = { "aarch64_pstate_za_shared" }
// CHECK: attributes #[[ZA_PRESERVED_CALL]] = { "aarch64_pstate_za_preserved" "aarch64_pstate_za_shared" }
// CHECK: attributes #[[ZA_SHARED_CALL]] = { "aarch64_inout_za" }
// CHECK: attributes #[[ZA_PRESERVED_CALL]] = { "aarch64_preserves_za" }
// CHECK: attributes #[[NOUNWIND_CALL]] = { nounwind }
// CHECK: attributes #[[NOUNWIND_SM_ENABLED_CALL]] = { nounwind "aarch64_pstate_sm_enabled" }
// CHECK: attributes #[[NOUNWIND_SM_COMPATIBLE_CALL]] = { nounwind "aarch64_pstate_sm_compatible" }
// CHECK: attributes #[[NOUNWIND_ZA_SHARED_CALL]] = { nounwind "aarch64_pstate_za_shared" }
// CHECK: attributes #[[NOUNWIND_ZA_PRESERVED_CALL]] = { nounwind "aarch64_pstate_za_preserved" "aarch64_pstate_za_shared" }
// CHECK: attributes #[[NOUNWIND_ZA_SHARED_CALL]] = { nounwind "aarch64_inout_za" }
// CHECK: attributes #[[NOUNWIND_ZA_PRESERVED_CALL]] = { nounwind "aarch64_preserves_za" }

4 changes: 2 additions & 2 deletions clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_zero.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ void test_svzero_mask_za_2(void) __arm_inout("za") {
}

// CHECK-C-LABEL: define dso_local void @test_svzero_za(
// CHECK-C-SAME: ) local_unnamed_addr #[[ATTR0]] {
// CHECK-C-SAME: ) local_unnamed_addr #[[ATTR2:[0-9]+]] {
// CHECK-C-NEXT: entry:
// CHECK-C-NEXT: tail call void @llvm.aarch64.sme.zero(i32 255)
// CHECK-C-NEXT: ret void
//
// CHECK-CXX-LABEL: define dso_local void @_Z14test_svzero_zav(
// CHECK-CXX-SAME: ) local_unnamed_addr #[[ATTR0]] {
// CHECK-CXX-SAME: ) local_unnamed_addr #[[ATTR2:[0-9]+]] {
// CHECK-CXX-NEXT: entry:
// CHECK-CXX-NEXT: tail call void @llvm.aarch64.sme.zero(i32 255)
// CHECK-CXX-NEXT: ret void
Expand Down
10 changes: 5 additions & 5 deletions clang/test/Modules/aarch64-sme-keywords.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ import A;
//
// CHECK:declare void @_ZW1A22f_streaming_compatiblev() #[[STREAMING_COMPATIBLE_DECL:[0-9]+]]
//
// CHECK-DAG: attributes #[[SHARED_ZA_DEF]] = {{{.*}} "aarch64_pstate_za_shared" {{.*}}}
// CHECK-DAG: attributes #[[SHARED_ZA_DECL]] = {{{.*}} "aarch64_pstate_za_shared" {{.*}}}
// CHECK-DAG: attributes #[[PRESERVES_ZA_DECL]] = {{{.*}} "aarch64_pstate_za_preserved" {{.*}}}
// CHECK-DAG: attributes #[[SHARED_ZA_DEF]] = {{{.*}} "aarch64_inout_za" {{.*}}}
// CHECK-DAG: attributes #[[SHARED_ZA_DECL]] = {{{.*}} "aarch64_inout_za" {{.*}}}
// CHECK-DAG: attributes #[[PRESERVES_ZA_DECL]] = {{{.*}} "aarch64_preserves_za" {{.*}}}
// CHECK-DAG: attributes #[[NORMAL_DEF]] = {{{.*}}}
// CHECK-DAG: attributes #[[STREAMING_DECL]] = {{{.*}} "aarch64_pstate_sm_enabled" {{.*}}}
// CHECK-DAG: attributes #[[STREAMING_COMPATIBLE_DECL]] = {{{.*}} "aarch64_pstate_sm_compatible" {{.*}}}
// CHECK-DAG: attributes #[[SHARED_ZA_USE]] = { "aarch64_pstate_za_shared" }
// CHECK-DAG: attributes #[[PRESERVES_ZA_USE]] = { "aarch64_pstate_za_preserved" "aarch64_pstate_za_shared" }
// CHECK-DAG: attributes #[[SHARED_ZA_USE]] = { "aarch64_inout_za" }
// CHECK-DAG: attributes #[[PRESERVES_ZA_USE]] = { "aarch64_preserves_za" }
// CHECK-DAG: attributes #[[STREAMING_USE]] = { "aarch64_pstate_sm_enabled" }
// CHECK-DAG: attributes #[[STREAMING_COMPATIBLE_USE]] = { "aarch64_pstate_sm_compatible" }

Expand Down
37 changes: 21 additions & 16 deletions llvm/docs/AArch64SME.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,32 @@ Below we describe the LLVM IR attributes and their relation to the C/C++
level ACLE attributes:

``aarch64_pstate_sm_enabled``
is used for functions with ``__attribute__((arm_streaming))``
is used for functions with ``__arm_streaming``

``aarch64_pstate_sm_compatible``
is used for functions with ``__attribute__((arm_streaming_compatible))``
is used for functions with ``__arm_streaming_compatible``

``aarch64_pstate_sm_body``
is used for functions with ``__attribute__((arm_locally_streaming))`` and is
is used for functions with ``__arm_locally_streaming`` and is
only valid on function definitions (not declarations)

``aarch64_pstate_za_new``
is used for functions with ``__attribute__((arm_new_za))``
``aarch64_new_za``
is used for functions with ``__arm_new("za")``

``aarch64_pstate_za_shared``
is used for functions with ``__attribute__((arm_shared_za))``
``aarch64_in_za``
is used for functions with ``__arm_in("za")``

``aarch64_pstate_za_preserved``
is used for functions with ``__attribute__((arm_preserves_za))``
``aarch64_out_za``
is used for functions with ``__arm_out("za")``

``aarch64_inout_za``
is used for functions with ``__arm_inout("za")``

``aarch64_preserves_za``
is used for functions with ``__arm_preserves("za")``

``aarch64_expanded_pstate_za``
is used for functions with ``__attribute__((arm_new_za))``
is used for functions with ``__arm_new_za``

Clang must ensure that the above attributes are added both to the
function's declaration/definition as well as to their call-sites. This is
Expand Down Expand Up @@ -89,11 +95,10 @@ Restrictions on attributes
* It is not allowed for a function to be decorated with both
``aarch64_pstate_sm_compatible`` and ``aarch64_pstate_sm_enabled``.

* It is not allowed for a function to be decorated with both
``aarch64_pstate_za_new`` and ``aarch64_pstate_za_preserved``.

* It is not allowed for a function to be decorated with both
``aarch64_pstate_za_new`` and ``aarch64_pstate_za_shared``.
* It is not allowed for a function to be decorated with more than one of the
following attributes:
``aarch64_new_za``, ``aarch64_in_za``, ``aarch64_out_za``, ``aarch64_inout_za``,
``aarch64_preserves_za``.

These restrictions also apply in the higher level SME ACLE, which means we can
emit diagnostics in Clang to signal users about incorrect behaviour.
Expand Down Expand Up @@ -426,7 +431,7 @@ to toggle PSTATE.ZA using intrinsics. This also makes it simpler to setup a
lazy-save mechanism for calls to private-ZA functions (i.e. functions that may
either directly or indirectly clobber ZA state).

For the purpose of handling functions marked with ``aarch64_pstate_za_new``,
For the purpose of handling functions marked with ``aarch64_new_za``,
we have introduced a new LLVM IR pass (SMEABIPass) that is run just before
SelectionDAG. Any such functions dealt with by this pass are marked with
``aarch64_expanded_pstate_za``.
Expand Down
18 changes: 7 additions & 11 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2155,17 +2155,13 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
V);
}

if (Attrs.hasFnAttr("aarch64_pstate_za_new")) {
Check(!Attrs.hasFnAttr("aarch64_pstate_za_preserved"),
"Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_preserved' "
"are incompatible!",
V);

Check(!Attrs.hasFnAttr("aarch64_pstate_za_shared"),
"Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_shared' "
"are incompatible!",
V);
}
Check((Attrs.hasFnAttr("aarch64_new_za") + Attrs.hasFnAttr("aarch64_in_za") +
Attrs.hasFnAttr("aarch64_inout_za") +
Attrs.hasFnAttr("aarch64_out_za") +
Attrs.hasFnAttr("aarch64_preserves_za")) <= 1,
"Attributes 'aarch64_new_za', 'aarch64_in_za', 'aarch64_out_za', "
"'aarch64_inout_za' and 'aarch64_preserves_za' are mutually exclusive",
V);

Check(
(Attrs.hasFnAttr("aarch64_new_zt0") + Attrs.hasFnAttr("aarch64_in_zt0") +
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ bool AArch64TTIImpl::areInlineCompatible(const Function *Caller,
CalleeAttrs.set(SMEAttrs::SM_Enabled, true);
}

if (CalleeAttrs.hasNewZABody())
if (CalleeAttrs.isNewZA())
return false;

if (CallerAttrs.requiresLazySave(CalleeAttrs) ||
Expand Down
12 changes: 5 additions & 7 deletions llvm/lib/Target/AArch64/SMEABIPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,8 @@ FunctionPass *llvm::createSMEABIPass() { return new SMEABI(); }
void emitTPIDR2Save(Module *M, IRBuilder<> &Builder) {
auto *TPIDR2SaveTy =
FunctionType::get(Builder.getVoidTy(), {}, /*IsVarArgs=*/false);
auto Attrs =
AttributeList()
.addFnAttribute(M->getContext(), "aarch64_pstate_sm_compatible")
.addFnAttribute(M->getContext(), "aarch64_pstate_za_preserved");
auto Attrs = AttributeList().addFnAttribute(M->getContext(),
"aarch64_pstate_sm_compatible");
FunctionCallee Callee =
M->getOrInsertFunction("__arm_tpidr2_save", TPIDR2SaveTy, Attrs);
CallInst *Call = Builder.CreateCall(Callee);
Expand All @@ -78,7 +76,7 @@ void emitTPIDR2Save(Module *M, IRBuilder<> &Builder) {
}

/// This function generates code at the beginning and end of a function marked
/// with either `aarch64_pstate_za_new` or `aarch64_new_zt0`.
/// with either `aarch64_new_za` or `aarch64_new_zt0`.
/// At the beginning of the function, the following code is generated:
/// - Commit lazy-save if active [Private-ZA Interface*]
/// - Enable PSTATE.ZA [Private-ZA Interface]
Expand Down Expand Up @@ -133,7 +131,7 @@ bool SMEABI::updateNewStateFunctions(Module *M, Function *F,
Builder.CreateCall(EnableZAIntr->getFunctionType(), EnableZAIntr);
}

if (FnAttrs.hasNewZABody()) {
if (FnAttrs.isNewZA()) {
Function *ZeroIntr =
Intrinsic::getDeclaration(M, Intrinsic::aarch64_sme_zero);
Builder.CreateCall(ZeroIntr->getFunctionType(), ZeroIntr,
Expand Down Expand Up @@ -174,7 +172,7 @@ bool SMEABI::runOnFunction(Function &F) {

bool Changed = false;
SMEAttrs FnAttrs(F);
if (FnAttrs.hasNewZABody() || FnAttrs.isNewZT0())
if (FnAttrs.isNewZA() || FnAttrs.isNewZT0())
Changed |= updateNewStateFunctions(M, &F, Builder, FnAttrs);

return Changed;
Expand Down
32 changes: 19 additions & 13 deletions llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ void SMEAttrs::set(unsigned M, bool Enable) {
"SM_Enabled and SM_Compatible are mutually exclusive");

// ZA Attrs
assert(!(hasNewZABody() && sharesZA()) &&
"ZA_New and ZA_Shared are mutually exclusive");
assert(!(hasNewZABody() && preservesZA()) &&
"ZA_New and ZA_Preserved are mutually exclusive");
assert(!(hasNewZABody() && (Bitmask & SME_ABI_Routine)) &&
assert(!(isNewZA() && (Bitmask & SME_ABI_Routine)) &&
"ZA_New and SME_ABI_Routine are mutually exclusive");

assert(
(!sharesZA() ||
(isNewZA() ^ isInZA() ^ isInOutZA() ^ isOutZA() ^ isPreservesZA())) &&
"Attributes 'aarch64_new_za', 'aarch64_in_za', 'aarch64_out_za', "
"'aarch64_inout_za' and 'aarch64_preserves_za' are mutually exclusive");

// ZT0 Attrs
assert(
(!sharesZT0() || (isNewZT0() ^ isInZT0() ^ isInOutZT0() ^ isOutZT0() ^
Expand All @@ -49,8 +51,8 @@ SMEAttrs::SMEAttrs(StringRef FuncName) : Bitmask(0) {
if (FuncName == "__arm_tpidr2_save" || FuncName == "__arm_sme_state")
Bitmask |= (SMEAttrs::SM_Compatible | SMEAttrs::SME_ABI_Routine);
if (FuncName == "__arm_tpidr2_restore")
Bitmask |= (SMEAttrs::SM_Compatible | SMEAttrs::ZA_Shared |
SMEAttrs::SME_ABI_Routine);
Bitmask |= SMEAttrs::SM_Compatible | encodeZAState(StateValue::In) |
SMEAttrs::SME_ABI_Routine;
}

SMEAttrs::SMEAttrs(const AttributeList &Attrs) {
Expand All @@ -61,12 +63,16 @@ SMEAttrs::SMEAttrs(const AttributeList &Attrs) {
Bitmask |= SM_Compatible;
if (Attrs.hasFnAttr("aarch64_pstate_sm_body"))
Bitmask |= SM_Body;
if (Attrs.hasFnAttr("aarch64_pstate_za_shared"))
Bitmask |= ZA_Shared;
if (Attrs.hasFnAttr("aarch64_pstate_za_new"))
Bitmask |= ZA_New;
if (Attrs.hasFnAttr("aarch64_pstate_za_preserved"))
Bitmask |= ZA_Preserved;
if (Attrs.hasFnAttr("aarch64_in_za"))
Bitmask |= encodeZAState(StateValue::In);
if (Attrs.hasFnAttr("aarch64_out_za"))
Bitmask |= encodeZAState(StateValue::Out);
if (Attrs.hasFnAttr("aarch64_inout_za"))
Bitmask |= encodeZAState(StateValue::InOut);
if (Attrs.hasFnAttr("aarch64_preserves_za"))
Bitmask |= encodeZAState(StateValue::Preserved);
if (Attrs.hasFnAttr("aarch64_new_za"))
Bitmask |= encodeZAState(StateValue::New);
if (Attrs.hasFnAttr("aarch64_in_zt0"))
Bitmask |= encodeZT0State(StateValue::In);
if (Attrs.hasFnAttr("aarch64_out_zt0"))
Expand Down
33 changes: 24 additions & 9 deletions llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,9 @@ class SMEAttrs {
SM_Enabled = 1 << 0, // aarch64_pstate_sm_enabled
SM_Compatible = 1 << 1, // aarch64_pstate_sm_compatible
SM_Body = 1 << 2, // aarch64_pstate_sm_body
ZA_Shared = 1 << 3, // aarch64_pstate_sm_shared
ZA_New = 1 << 4, // aarch64_pstate_sm_new
ZA_Preserved = 1 << 5, // aarch64_pstate_sm_preserved
SME_ABI_Routine = 1 << 6, // Used for SME ABI routines to avoid lazy saves
SME_ABI_Routine = 1 << 3, // Used for SME ABI routines to avoid lazy saves
ZA_Shift = 4,
ZA_Mask = 0b111 << ZA_Shift,
ZT0_Shift = 7,
ZT0_Mask = 0b111 << ZT0_Shift
};
Expand Down Expand Up @@ -77,13 +76,29 @@ class SMEAttrs {
/// streaming mode.
bool requiresSMChange(const SMEAttrs &Callee) const;

// Interfaces to query PSTATE.ZA
bool hasNewZABody() const { return Bitmask & ZA_New; }
bool sharesZA() const { return Bitmask & ZA_Shared; }
// Interfaces to query ZA
static StateValue decodeZAState(unsigned Bitmask) {
return static_cast<StateValue>((Bitmask & ZA_Mask) >> ZA_Shift);
}
static unsigned encodeZAState(StateValue S) {
return static_cast<unsigned>(S) << ZA_Shift;
}

bool isNewZA() const { return decodeZAState(Bitmask) == StateValue::New; }
bool isInZA() const { return decodeZAState(Bitmask) == StateValue::In; }
bool isOutZA() const { return decodeZAState(Bitmask) == StateValue::Out; }
bool isInOutZA() const { return decodeZAState(Bitmask) == StateValue::InOut; }
bool isPreservesZA() const {
return decodeZAState(Bitmask) == StateValue::Preserved;
}
bool sharesZA() const {
StateValue State = decodeZAState(Bitmask);
return State == StateValue::In || State == StateValue::Out ||
State == StateValue::InOut || State == StateValue::Preserved;
}
bool hasSharedZAInterface() const { return sharesZA() || sharesZT0(); }
bool hasPrivateZAInterface() const { return !hasSharedZAInterface(); }
bool preservesZA() const { return Bitmask & ZA_Preserved; }
bool hasZAState() const { return hasNewZABody() || sharesZA(); }
bool hasZAState() const { return isNewZA() || sharesZA(); }
bool requiresLazySave(const SMEAttrs &Callee) const {
return hasZAState() && Callee.hasPrivateZAInterface() &&
!(Callee.Bitmask & SME_ABI_Routine);
Expand Down

0 comments on commit d313614

Please sign in to comment.