1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
//===-- AArch64SMEAttributes.h - 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64SMEATTRIBUTES_H
#define LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64SMEATTRIBUTES_H
#include "llvm/IR/Function.h"
namespace llvm {
class Function;
class CallBase;
class AttributeList;
/// SMEAttrs is a utility class to parse the SME ACLE attributes on functions.
/// It helps determine a function's requirements for PSTATE.ZA and PSTATE.SM. It
/// has interfaces to query whether a streaming mode change or lazy-save
/// mechanism is required when going from one function to another (e.g. through
/// a call).
class SMEAttrs {
unsigned Bitmask;
public:
enum class StateValue {
None = 0,
In = 1, // aarch64_in_zt0
Out = 2, // aarch64_out_zt0
InOut = 3, // aarch64_inout_zt0
Preserved = 4, // aarch64_preserves_zt0
New = 5 // aarch64_new_zt0
};
// Enum with bitmasks for each individual SME feature.
enum Mask {
Normal = 0,
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
ZT0_Shift = 7,
ZT0_Mask = 0b111 << ZT0_Shift
};
SMEAttrs(unsigned Mask = Normal) : Bitmask(0) { set(Mask); }
SMEAttrs(const Function &F) : SMEAttrs(F.getAttributes()) {}
SMEAttrs(const CallBase &CB);
SMEAttrs(const AttributeList &L);
SMEAttrs(StringRef FuncName);
void set(unsigned M, bool Enable = true);
// Interfaces to query PSTATE.SM
bool hasStreamingBody() const { return Bitmask & SM_Body; }
bool hasStreamingInterface() const { return Bitmask & SM_Enabled; }
bool hasStreamingInterfaceOrBody() const {
return hasStreamingBody() || hasStreamingInterface();
}
bool hasStreamingCompatibleInterface() const {
return Bitmask & SM_Compatible;
}
bool hasNonStreamingInterface() const {
return !hasStreamingInterface() && !hasStreamingCompatibleInterface();
}
bool hasNonStreamingInterfaceAndBody() const {
return hasNonStreamingInterface() && !hasStreamingBody();
}
/// \return true if a call from Caller -> Callee requires a change in
/// 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; }
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 requiresLazySave(const SMEAttrs &Callee) const {
return hasZAState() && Callee.hasPrivateZAInterface() &&
!(Callee.Bitmask & SME_ABI_Routine);
}
// Interfaces to query ZT0 State
static StateValue decodeZT0State(unsigned Bitmask) {
return static_cast<StateValue>((Bitmask & ZT0_Mask) >> ZT0_Shift);
}
static unsigned encodeZT0State(StateValue S) {
return static_cast<unsigned>(S) << ZT0_Shift;
}
bool isNewZT0() const { return decodeZT0State(Bitmask) == StateValue::New; }
bool isInZT0() const { return decodeZT0State(Bitmask) == StateValue::In; }
bool isOutZT0() const { return decodeZT0State(Bitmask) == StateValue::Out; }
bool isInOutZT0() const {
return decodeZT0State(Bitmask) == StateValue::InOut;
}
bool isPreservesZT0() const {
return decodeZT0State(Bitmask) == StateValue::Preserved;
}
bool sharesZT0() const {
StateValue State = decodeZT0State(Bitmask);
return State == StateValue::In || State == StateValue::Out ||
State == StateValue::InOut || State == StateValue::Preserved;
}
bool hasZT0State() const { return isNewZT0() || sharesZT0(); }
bool requiresPreservingZT0(const SMEAttrs &Callee) const {
return hasZT0State() && !Callee.sharesZT0();
}
bool requiresDisablingZABeforeCall(const SMEAttrs &Callee) const {
return hasZT0State() && !hasZAState() && Callee.hasPrivateZAInterface() &&
!(Callee.Bitmask & SME_ABI_Routine);
}
bool requiresEnablingZAAfterCall(const SMEAttrs &Callee) const {
return requiresLazySave(Callee) || requiresDisablingZABeforeCall(Callee);
}
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64SMEATTRIBUTES_H
|