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 #include "llvm/IR/Function.h"
10 
11 #ifndef LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64SMEATTRIBUTES_H
12 #define LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64SMEATTRIBUTES_H
13 namespace llvm {
14 
15 class Function;
16 class CallBase;
17 class AttributeList;
18 
19 /// SMEAttrs is a utility class to parse the SME ACLE attributes on functions.
20 /// It helps determine a function's requirements for PSTATE.ZA and PSTATE.SM. It
21 /// has interfaces to query whether a streaming mode change or lazy-save
22 /// mechanism is required when going from one function to another (e.g. through
23 /// a call).
24 class SMEAttrs {
25   unsigned Bitmask;
26 
27 public:
28   // Enum with bitmasks for each individual SME feature.
29   enum Mask {
30     Normal = 0,
31     SM_Enabled = 1 << 0,    // aarch64_pstate_sm_enabled
32     SM_Compatible = 1 << 1, // aarch64_pstate_sm_compatible
33     SM_Body = 1 << 2,       // aarch64_pstate_sm_locally
34     ZA_Shared = 1 << 3,     // aarch64_pstate_sm_shared
35     ZA_New = 1 << 4,        // aarch64_pstate_sm_new
36     ZA_Preserved = 1 << 5,  // aarch64_pstate_sm_preserved
37     All = ZA_Preserved - 1
38   };
39 
40   SMEAttrs(unsigned Mask = Normal) : Bitmask(0) { set(Mask); }
41   SMEAttrs(const Function &F) : SMEAttrs(F.getAttributes()) {}
42   SMEAttrs(const CallBase &CB);
43   SMEAttrs(const AttributeList &L);
44 
45   void set(unsigned M, bool Enable = true);
46 
47   // Interfaces to query PSTATE.SM
48   bool hasStreamingBody() const { return Bitmask & SM_Body; }
49   bool hasStreamingInterface() const { return Bitmask & SM_Enabled; }
50   bool hasStreamingInterfaceOrBody() const {
51     return hasStreamingBody() || hasStreamingInterface();
52   }
53   bool hasStreamingCompatibleInterface() const {
54     return Bitmask & SM_Compatible;
55   }
56   bool hasNonStreamingInterface() const {
57     return !hasStreamingInterface() && !hasStreamingCompatibleInterface();
58   }
59   bool hasNonStreamingInterfaceAndBody() const {
60     return hasNonStreamingInterface() && !hasStreamingBody();
61   }
62 
63   /// \return true if a call from Caller -> Callee requires a change in
64   /// streaming mode.
65   /// If \p BodyOverridesInterface is true and Callee has a streaming body,
66   /// then requiresSMChange considers a call to Callee as having a Streaming
67   /// interface. This can be useful when considering e.g. inlining, where we
68   /// explicitly want the body to overrule the interface (because after inlining
69   /// the interface is no longer relevant).
70   std::optional<bool>
71   requiresSMChange(const SMEAttrs &Callee,
72                    bool BodyOverridesInterface = false) const;
73 
74   // Interfaces to query PSTATE.ZA
75   bool hasNewZAInterface() const { return Bitmask & ZA_New; }
76   bool hasSharedZAInterface() const { return Bitmask & ZA_Shared; }
77   bool hasPrivateZAInterface() const { return !hasSharedZAInterface(); }
78   bool preservesZA() const { return Bitmask & ZA_Preserved; }
79   bool hasZAState() const {
80     return hasNewZAInterface() || hasSharedZAInterface();
81   }
82   bool requiresLazySave(const SMEAttrs &Callee) const {
83     return hasZAState() && Callee.hasPrivateZAInterface() &&
84            !Callee.preservesZA();
85   }
86 };
87 
88 } // namespace llvm
89 
90 #endif // LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64SMEATTRIBUTES_H
91