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 // Streaming Mode Attrs 22 assert(!(hasStreamingInterface() && hasStreamingCompatibleInterface()) && 23 "SM_Enabled and SM_Compatible are mutually exclusive"); 24 25 // ZA Attrs 26 assert(!(isNewZA() && (Bitmask & SME_ABI_Routine)) && 27 "ZA_New and SME_ABI_Routine are mutually exclusive"); 28 29 assert( 30 (!sharesZA() || 31 (isNewZA() ^ isInZA() ^ isInOutZA() ^ isOutZA() ^ isPreservesZA())) && 32 "Attributes 'aarch64_new_za', 'aarch64_in_za', 'aarch64_out_za', " 33 "'aarch64_inout_za' and 'aarch64_preserves_za' are mutually exclusive"); 34 35 // ZT0 Attrs 36 assert( 37 (!sharesZT0() || (isNewZT0() ^ isInZT0() ^ isInOutZT0() ^ isOutZT0() ^ 38 isPreservesZT0())) && 39 "Attributes 'aarch64_new_zt0', 'aarch64_in_zt0', 'aarch64_out_zt0', " 40 "'aarch64_inout_zt0' and 'aarch64_preserves_zt0' are mutually exclusive"); 41 42 assert(!(hasAgnosticZAInterface() && hasSharedZAInterface()) && 43 "Function cannot have a shared-ZA interface and an agnostic-ZA " 44 "interface"); 45 } 46 47 SMEAttrs::SMEAttrs(const CallBase &CB) { 48 *this = SMEAttrs(CB.getAttributes()); 49 if (auto *F = CB.getCalledFunction()) { 50 set(SMEAttrs(*F).Bitmask | SMEAttrs(F->getName()).Bitmask); 51 } 52 } 53 54 SMEAttrs::SMEAttrs(StringRef FuncName) : Bitmask(0) { 55 if (FuncName == "__arm_tpidr2_save" || FuncName == "__arm_sme_state") 56 Bitmask |= (SMEAttrs::SM_Compatible | SMEAttrs::SME_ABI_Routine); 57 if (FuncName == "__arm_tpidr2_restore") 58 Bitmask |= SMEAttrs::SM_Compatible | encodeZAState(StateValue::In) | 59 SMEAttrs::SME_ABI_Routine; 60 if (FuncName == "__arm_sc_memcpy" || FuncName == "__arm_sc_memset" || 61 FuncName == "__arm_sc_memmove" || FuncName == "__arm_sc_memchr") 62 Bitmask |= SMEAttrs::SM_Compatible; 63 if (FuncName == "__arm_sme_save" || FuncName == "__arm_sme_restore" || 64 FuncName == "__arm_sme_state_size") 65 Bitmask |= SMEAttrs::SM_Compatible | SMEAttrs::SME_ABI_Routine; 66 } 67 68 SMEAttrs::SMEAttrs(const AttributeList &Attrs) { 69 Bitmask = 0; 70 if (Attrs.hasFnAttr("aarch64_pstate_sm_enabled")) 71 Bitmask |= SM_Enabled; 72 if (Attrs.hasFnAttr("aarch64_pstate_sm_compatible")) 73 Bitmask |= SM_Compatible; 74 if (Attrs.hasFnAttr("aarch64_pstate_sm_body")) 75 Bitmask |= SM_Body; 76 if (Attrs.hasFnAttr("aarch64_za_state_agnostic")) 77 Bitmask |= ZA_State_Agnostic; 78 if (Attrs.hasFnAttr("aarch64_in_za")) 79 Bitmask |= encodeZAState(StateValue::In); 80 if (Attrs.hasFnAttr("aarch64_out_za")) 81 Bitmask |= encodeZAState(StateValue::Out); 82 if (Attrs.hasFnAttr("aarch64_inout_za")) 83 Bitmask |= encodeZAState(StateValue::InOut); 84 if (Attrs.hasFnAttr("aarch64_preserves_za")) 85 Bitmask |= encodeZAState(StateValue::Preserved); 86 if (Attrs.hasFnAttr("aarch64_new_za")) 87 Bitmask |= encodeZAState(StateValue::New); 88 if (Attrs.hasFnAttr("aarch64_in_zt0")) 89 Bitmask |= encodeZT0State(StateValue::In); 90 if (Attrs.hasFnAttr("aarch64_out_zt0")) 91 Bitmask |= encodeZT0State(StateValue::Out); 92 if (Attrs.hasFnAttr("aarch64_inout_zt0")) 93 Bitmask |= encodeZT0State(StateValue::InOut); 94 if (Attrs.hasFnAttr("aarch64_preserves_zt0")) 95 Bitmask |= encodeZT0State(StateValue::Preserved); 96 if (Attrs.hasFnAttr("aarch64_new_zt0")) 97 Bitmask |= encodeZT0State(StateValue::New); 98 } 99 100 bool SMEAttrs::requiresSMChange(const SMEAttrs &Callee) const { 101 if (Callee.hasStreamingCompatibleInterface()) 102 return false; 103 104 // Both non-streaming 105 if (hasNonStreamingInterfaceAndBody() && Callee.hasNonStreamingInterface()) 106 return false; 107 108 // Both streaming 109 if (hasStreamingInterfaceOrBody() && Callee.hasStreamingInterface()) 110 return false; 111 112 return true; 113 } 114