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