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(M: Mask); } |
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 |
60 | bool hasStreamingBody() const { return Bitmask & SM_Body; } |
61 | bool hasStreamingInterface() const { return Bitmask & SM_Enabled; } |
62 | bool hasStreamingInterfaceOrBody() const { |
63 | return hasStreamingBody() || hasStreamingInterface(); |
64 | } |
65 | bool hasStreamingCompatibleInterface() const { |
66 | return Bitmask & SM_Compatible; |
67 | } |
68 | bool hasNonStreamingInterface() const { |
69 | return !hasStreamingInterface() && !hasStreamingCompatibleInterface(); |
70 | } |
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 |
80 | static StateValue decodeZAState(unsigned Bitmask) { |
81 | return static_cast<StateValue>((Bitmask & ZA_Mask) >> ZA_Shift); |
82 | } |
83 | static unsigned encodeZAState(StateValue S) { |
84 | return static_cast<unsigned>(S) << ZA_Shift; |
85 | } |
86 | |
87 | bool isNewZA() const { return decodeZAState(Bitmask) == StateValue::New; } |
88 | bool isInZA() const { return decodeZAState(Bitmask) == StateValue::In; } |
89 | bool isOutZA() const { return decodeZAState(Bitmask) == StateValue::Out; } |
90 | bool isInOutZA() const { return decodeZAState(Bitmask) == StateValue::InOut; } |
91 | bool isPreservesZA() const { |
92 | return decodeZAState(Bitmask) == StateValue::Preserved; |
93 | } |
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 | } |
99 | bool hasSharedZAInterface() const { return sharesZA() || sharesZT0(); } |
100 | bool hasPrivateZAInterface() const { return !hasSharedZAInterface(); } |
101 | bool hasZAState() const { return isNewZA() || sharesZA(); } |
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 |
108 | static StateValue decodeZT0State(unsigned Bitmask) { |
109 | return static_cast<StateValue>((Bitmask & ZT0_Mask) >> ZT0_Shift); |
110 | } |
111 | static unsigned encodeZT0State(StateValue S) { |
112 | return static_cast<unsigned>(S) << ZT0_Shift; |
113 | } |
114 | |
115 | bool isNewZT0() const { return decodeZT0State(Bitmask) == StateValue::New; } |
116 | bool isInZT0() const { return decodeZT0State(Bitmask) == StateValue::In; } |
117 | bool isOutZT0() const { return decodeZT0State(Bitmask) == StateValue::Out; } |
118 | bool isInOutZT0() const { |
119 | return decodeZT0State(Bitmask) == StateValue::InOut; |
120 | } |
121 | bool isPreservesZT0() const { |
122 | return decodeZT0State(Bitmask) == StateValue::Preserved; |
123 | } |
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 | } |
129 | bool hasZT0State() const { return isNewZT0() || sharesZT0(); } |
130 | bool requiresPreservingZT0(const SMEAttrs &Callee) const { |
131 | return hasZT0State() && !Callee.sharesZT0(); |
132 | } |
133 | bool requiresDisablingZABeforeCall(const SMEAttrs &Callee) const { |
134 | return hasZT0State() && !hasZAState() && Callee.hasPrivateZAInterface() && |
135 | !(Callee.Bitmask & SME_ABI_Routine); |
136 | } |
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 | |