Since https://github.com/ARM-software/acle/pull/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).
102 lines
3.5 KiB
C++
102 lines
3.5 KiB
C++
//===-- AArch64SMEAttributes.cpp - Helper for interpreting SME attributes -===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "AArch64SMEAttributes.h"
|
|
#include "llvm/IR/InstrTypes.h"
|
|
#include <cassert>
|
|
|
|
using namespace llvm;
|
|
|
|
void SMEAttrs::set(unsigned M, bool Enable) {
|
|
if (Enable)
|
|
Bitmask |= M;
|
|
else
|
|
Bitmask &= ~M;
|
|
|
|
// Streaming Mode Attrs
|
|
assert(!(hasStreamingInterface() && hasStreamingCompatibleInterface()) &&
|
|
"SM_Enabled and SM_Compatible are mutually exclusive");
|
|
|
|
// ZA Attrs
|
|
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() ^
|
|
isPreservesZT0())) &&
|
|
"Attributes 'aarch64_new_zt0', 'aarch64_in_zt0', 'aarch64_out_zt0', "
|
|
"'aarch64_inout_zt0' and 'aarch64_preserves_zt0' are mutually exclusive");
|
|
}
|
|
|
|
SMEAttrs::SMEAttrs(const CallBase &CB) {
|
|
*this = SMEAttrs(CB.getAttributes());
|
|
if (auto *F = CB.getCalledFunction()) {
|
|
set(SMEAttrs(*F).Bitmask | SMEAttrs(F->getName()).Bitmask);
|
|
}
|
|
}
|
|
|
|
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 | encodeZAState(StateValue::In) |
|
|
SMEAttrs::SME_ABI_Routine;
|
|
}
|
|
|
|
SMEAttrs::SMEAttrs(const AttributeList &Attrs) {
|
|
Bitmask = 0;
|
|
if (Attrs.hasFnAttr("aarch64_pstate_sm_enabled"))
|
|
Bitmask |= SM_Enabled;
|
|
if (Attrs.hasFnAttr("aarch64_pstate_sm_compatible"))
|
|
Bitmask |= SM_Compatible;
|
|
if (Attrs.hasFnAttr("aarch64_pstate_sm_body"))
|
|
Bitmask |= SM_Body;
|
|
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"))
|
|
Bitmask |= encodeZT0State(StateValue::Out);
|
|
if (Attrs.hasFnAttr("aarch64_inout_zt0"))
|
|
Bitmask |= encodeZT0State(StateValue::InOut);
|
|
if (Attrs.hasFnAttr("aarch64_preserves_zt0"))
|
|
Bitmask |= encodeZT0State(StateValue::Preserved);
|
|
if (Attrs.hasFnAttr("aarch64_new_zt0"))
|
|
Bitmask |= encodeZT0State(StateValue::New);
|
|
}
|
|
|
|
bool SMEAttrs::requiresSMChange(const SMEAttrs &Callee) const {
|
|
if (Callee.hasStreamingCompatibleInterface())
|
|
return false;
|
|
|
|
// Both non-streaming
|
|
if (hasNonStreamingInterfaceAndBody() && Callee.hasNonStreamingInterface())
|
|
return false;
|
|
|
|
// Both streaming
|
|
if (hasStreamingInterfaceOrBody() && Callee.hasStreamingInterface())
|
|
return false;
|
|
|
|
return true;
|
|
}
|