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