xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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