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 ZA_Shared = 1 << 3, // aarch64_pstate_sm_shared 45 ZA_New = 1 << 4, // aarch64_pstate_sm_new 46 ZA_Preserved = 1 << 5, // aarch64_pstate_sm_preserved 47 SME_ABI_Routine = 1 << 6, // Used for SME ABI routines to avoid lazy saves 48 ZT0_Shift = 7, 49 ZT0_Mask = 0b111 << ZT0_Shift 50 }; 51 52 SMEAttrs(unsigned Mask = Normal) : Bitmask(0) { set(Mask); } 53 SMEAttrs(const Function &F) : SMEAttrs(F.getAttributes()) {} 54 SMEAttrs(const CallBase &CB); 55 SMEAttrs(const AttributeList &L); 56 SMEAttrs(StringRef FuncName); 57 58 void set(unsigned M, bool Enable = true); 59 60 // Interfaces to query PSTATE.SM 61 bool hasStreamingBody() const { return Bitmask & SM_Body; } 62 bool hasStreamingInterface() const { return Bitmask & SM_Enabled; } 63 bool hasStreamingInterfaceOrBody() const { 64 return hasStreamingBody() || hasStreamingInterface(); 65 } 66 bool hasStreamingCompatibleInterface() const { 67 return Bitmask & SM_Compatible; 68 } 69 bool hasNonStreamingInterface() const { 70 return !hasStreamingInterface() && !hasStreamingCompatibleInterface(); 71 } 72 bool hasNonStreamingInterfaceAndBody() const { 73 return hasNonStreamingInterface() && !hasStreamingBody(); 74 } 75 76 /// \return true if a call from Caller -> Callee requires a change in 77 /// streaming mode. 78 bool requiresSMChange(const SMEAttrs &Callee) const; 79 80 // Interfaces to query PSTATE.ZA 81 bool hasNewZABody() const { return Bitmask & ZA_New; } 82 bool sharesZA() const { return Bitmask & ZA_Shared; } 83 bool hasSharedZAInterface() const { return sharesZA() || sharesZT0(); } 84 bool hasPrivateZAInterface() const { return !hasSharedZAInterface(); } 85 bool preservesZA() const { return Bitmask & ZA_Preserved; } 86 bool hasZAState() const { return hasNewZABody() || sharesZA(); } 87 bool requiresLazySave(const SMEAttrs &Callee) const { 88 return hasZAState() && Callee.hasPrivateZAInterface() && 89 !(Callee.Bitmask & SME_ABI_Routine); 90 } 91 92 // Interfaces to query ZT0 State 93 static StateValue decodeZT0State(unsigned Bitmask) { 94 return static_cast<StateValue>((Bitmask & ZT0_Mask) >> ZT0_Shift); 95 } 96 static unsigned encodeZT0State(StateValue S) { 97 return static_cast<unsigned>(S) << ZT0_Shift; 98 } 99 100 bool isNewZT0() const { return decodeZT0State(Bitmask) == StateValue::New; } 101 bool isInZT0() const { return decodeZT0State(Bitmask) == StateValue::In; } 102 bool isOutZT0() const { return decodeZT0State(Bitmask) == StateValue::Out; } 103 bool isInOutZT0() const { 104 return decodeZT0State(Bitmask) == StateValue::InOut; 105 } 106 bool isPreservesZT0() const { 107 return decodeZT0State(Bitmask) == StateValue::Preserved; 108 } 109 bool sharesZT0() const { 110 StateValue State = decodeZT0State(Bitmask); 111 return State == StateValue::In || State == StateValue::Out || 112 State == StateValue::InOut || State == StateValue::Preserved; 113 } 114 bool hasZT0State() const { return isNewZT0() || sharesZT0(); } 115 bool requiresPreservingZT0(const SMEAttrs &Callee) const { 116 return hasZT0State() && !Callee.sharesZT0(); 117 } 118 bool requiresDisablingZABeforeCall(const SMEAttrs &Callee) const { 119 return hasZT0State() && !hasZAState() && Callee.hasPrivateZAInterface() && 120 !(Callee.Bitmask & SME_ABI_Routine); 121 } 122 bool requiresEnablingZAAfterCall(const SMEAttrs &Callee) const { 123 return requiresLazySave(Callee) || requiresDisablingZABeforeCall(Callee); 124 } 125 }; 126 127 } // namespace llvm 128 129 #endif // LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64SMEATTRIBUTES_H 130