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 with bitmasks for each individual SME feature. 30 enum Mask { 31 Normal = 0, 32 SM_Enabled = 1 << 0, // aarch64_pstate_sm_enabled 33 SM_Compatible = 1 << 1, // aarch64_pstate_sm_compatible 34 SM_Body = 1 << 2, // aarch64_pstate_sm_body 35 ZA_Shared = 1 << 3, // aarch64_pstate_sm_shared 36 ZA_New = 1 << 4, // aarch64_pstate_sm_new 37 ZA_Preserved = 1 << 5, // aarch64_pstate_sm_preserved 38 All = ZA_Preserved - 1 39 }; 40 41 SMEAttrs(unsigned Mask = Normal) : Bitmask(0) { set(Mask); } 42 SMEAttrs(const Function &F) : SMEAttrs(F.getAttributes()) {} 43 SMEAttrs(const CallBase &CB); 44 SMEAttrs(const AttributeList &L); 45 46 void set(unsigned M, bool Enable = true); 47 48 // Interfaces to query PSTATE.SM 49 bool hasStreamingBody() const { return Bitmask & SM_Body; } 50 bool hasStreamingInterface() const { return Bitmask & SM_Enabled; } 51 bool hasStreamingInterfaceOrBody() const { 52 return hasStreamingBody() || hasStreamingInterface(); 53 } 54 bool hasStreamingCompatibleInterface() const { 55 return Bitmask & SM_Compatible; 56 } 57 bool hasNonStreamingInterface() const { 58 return !hasStreamingInterface() && !hasStreamingCompatibleInterface(); 59 } 60 bool hasNonStreamingInterfaceAndBody() const { 61 return hasNonStreamingInterface() && !hasStreamingBody(); 62 } 63 64 /// \return true if a call from Caller -> Callee requires a change in 65 /// streaming mode. 66 /// If \p BodyOverridesInterface is true and Callee has a streaming body, 67 /// then requiresSMChange considers a call to Callee as having a Streaming 68 /// interface. This can be useful when considering e.g. inlining, where we 69 /// explicitly want the body to overrule the interface (because after inlining 70 /// the interface is no longer relevant). 71 std::optional<bool> 72 requiresSMChange(const SMEAttrs &Callee, 73 bool BodyOverridesInterface = false) const; 74 75 // Interfaces to query PSTATE.ZA 76 bool hasNewZAInterface() const { return Bitmask & ZA_New; } 77 bool hasSharedZAInterface() const { return Bitmask & ZA_Shared; } 78 bool hasPrivateZAInterface() const { return !hasSharedZAInterface(); } 79 bool preservesZA() const { return Bitmask & ZA_Preserved; } 80 bool hasZAState() const { 81 return hasNewZAInterface() || hasSharedZAInterface(); 82 } 83 bool requiresLazySave(const SMEAttrs &Callee) const { 84 return hasZAState() && Callee.hasPrivateZAInterface() && 85 !Callee.preservesZA(); 86 } 87 }; 88 89 } // namespace llvm 90 91 #endif // LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64SMEATTRIBUTES_H 92