1 //===-- AArch64SMEAttributes.cpp - 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 "AArch64SMEAttributes.h" 10 #include "llvm/IR/InstrTypes.h" 11 #include <cassert> 12 13 using namespace llvm; 14 15 void SMEAttrs::set(unsigned M, bool Enable) { 16 if (Enable) 17 Bitmask |= M; 18 else 19 Bitmask &= ~M; 20 21 assert(!(hasStreamingInterface() && hasStreamingCompatibleInterface()) && 22 "SM_Enabled and SM_Compatible are mutually exclusive"); 23 assert(!(hasNewZABody() && hasSharedZAInterface()) && 24 "ZA_New and ZA_Shared are mutually exclusive"); 25 assert(!(hasNewZABody() && preservesZA()) && 26 "ZA_New and ZA_Preserved are mutually exclusive"); 27 assert(!(hasNewZABody() && (Bitmask & ZA_NoLazySave)) && 28 "ZA_New and ZA_NoLazySave are mutually exclusive"); 29 assert(!(hasSharedZAInterface() && (Bitmask & ZA_NoLazySave)) && 30 "ZA_Shared and ZA_NoLazySave are mutually exclusive"); 31 } 32 33 SMEAttrs::SMEAttrs(const CallBase &CB) { 34 *this = SMEAttrs(CB.getAttributes()); 35 if (auto *F = CB.getCalledFunction()) { 36 set(SMEAttrs(*F).Bitmask | SMEAttrs(F->getName()).Bitmask); 37 } 38 } 39 40 SMEAttrs::SMEAttrs(StringRef FuncName) : Bitmask(0) { 41 if (FuncName == "__arm_tpidr2_save" || FuncName == "__arm_sme_state") 42 Bitmask |= (SMEAttrs::SM_Compatible | SMEAttrs::ZA_Preserved | 43 SMEAttrs::ZA_NoLazySave); 44 if (FuncName == "__arm_tpidr2_restore") 45 Bitmask |= (SMEAttrs::SM_Compatible | SMEAttrs::ZA_Shared | 46 SMEAttrs::ZA_NoLazySave); 47 } 48 49 SMEAttrs::SMEAttrs(const AttributeList &Attrs) { 50 Bitmask = 0; 51 if (Attrs.hasFnAttr("aarch64_pstate_sm_enabled")) 52 Bitmask |= SM_Enabled; 53 if (Attrs.hasFnAttr("aarch64_pstate_sm_compatible")) 54 Bitmask |= SM_Compatible; 55 if (Attrs.hasFnAttr("aarch64_pstate_sm_body")) 56 Bitmask |= SM_Body; 57 if (Attrs.hasFnAttr("aarch64_pstate_za_shared")) 58 Bitmask |= ZA_Shared; 59 if (Attrs.hasFnAttr("aarch64_pstate_za_new")) 60 Bitmask |= ZA_New; 61 if (Attrs.hasFnAttr("aarch64_pstate_za_preserved")) 62 Bitmask |= ZA_Preserved; 63 } 64 65 std::optional<bool> 66 SMEAttrs::requiresSMChange(const SMEAttrs &Callee, 67 bool BodyOverridesInterface) const { 68 // If the transition is not through a call (e.g. when considering inlining) 69 // and Callee has a streaming body, then we can ignore the interface of 70 // Callee. 71 if (BodyOverridesInterface && Callee.hasStreamingBody()) { 72 return hasStreamingInterfaceOrBody() ? std::nullopt 73 : std::optional<bool>(true); 74 } 75 76 if (Callee.hasStreamingCompatibleInterface()) 77 return std::nullopt; 78 79 // Both non-streaming 80 if (hasNonStreamingInterfaceAndBody() && Callee.hasNonStreamingInterface()) 81 return std::nullopt; 82 83 // Both streaming 84 if (hasStreamingInterfaceOrBody() && Callee.hasStreamingInterface()) 85 return std::nullopt; 86 87 return Callee.hasStreamingInterface(); 88 } 89