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