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
13using namespace llvm;
14
15void 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
43SMEAttrs::SMEAttrs(const CallBase &CB) {
44 *this = SMEAttrs(CB.getAttributes());
45 if (auto *F = CB.getCalledFunction()) {
46 set(M: SMEAttrs(*F).Bitmask | SMEAttrs(F->getName()).Bitmask);
47 }
48}
49
50SMEAttrs::SMEAttrs(StringRef FuncName) : Bitmask(0) {
51 if (FuncName == "__arm_tpidr2_save" || FuncName == "__arm_sme_state")
52 Bitmask |= (SMEAttrs::SM_Compatible | SMEAttrs::SME_ABI_Routine);
53 if (FuncName == "__arm_tpidr2_restore")
54 Bitmask |= SMEAttrs::SM_Compatible | encodeZAState(S: StateValue::In) |
55 SMEAttrs::SME_ABI_Routine;
56 if (FuncName == "__arm_sc_memcpy" || FuncName == "__arm_sc_memset" ||
57 FuncName == "__arm_sc_memmove" || FuncName == "__arm_sc_memchr")
58 Bitmask |= SMEAttrs::SM_Compatible;
59}
60
61SMEAttrs::SMEAttrs(const AttributeList &Attrs) {
62 Bitmask = 0;
63 if (Attrs.hasFnAttr(Kind: "aarch64_pstate_sm_enabled"))
64 Bitmask |= SM_Enabled;
65 if (Attrs.hasFnAttr(Kind: "aarch64_pstate_sm_compatible"))
66 Bitmask |= SM_Compatible;
67 if (Attrs.hasFnAttr(Kind: "aarch64_pstate_sm_body"))
68 Bitmask |= SM_Body;
69 if (Attrs.hasFnAttr(Kind: "aarch64_in_za"))
70 Bitmask |= encodeZAState(S: StateValue::In);
71 if (Attrs.hasFnAttr(Kind: "aarch64_out_za"))
72 Bitmask |= encodeZAState(S: StateValue::Out);
73 if (Attrs.hasFnAttr(Kind: "aarch64_inout_za"))
74 Bitmask |= encodeZAState(S: StateValue::InOut);
75 if (Attrs.hasFnAttr(Kind: "aarch64_preserves_za"))
76 Bitmask |= encodeZAState(S: StateValue::Preserved);
77 if (Attrs.hasFnAttr(Kind: "aarch64_new_za"))
78 Bitmask |= encodeZAState(S: StateValue::New);
79 if (Attrs.hasFnAttr(Kind: "aarch64_in_zt0"))
80 Bitmask |= encodeZT0State(S: StateValue::In);
81 if (Attrs.hasFnAttr(Kind: "aarch64_out_zt0"))
82 Bitmask |= encodeZT0State(S: StateValue::Out);
83 if (Attrs.hasFnAttr(Kind: "aarch64_inout_zt0"))
84 Bitmask |= encodeZT0State(S: StateValue::InOut);
85 if (Attrs.hasFnAttr(Kind: "aarch64_preserves_zt0"))
86 Bitmask |= encodeZT0State(S: StateValue::Preserved);
87 if (Attrs.hasFnAttr(Kind: "aarch64_new_zt0"))
88 Bitmask |= encodeZT0State(S: StateValue::New);
89}
90
91bool SMEAttrs::requiresSMChange(const SMEAttrs &Callee) const {
92 if (Callee.hasStreamingCompatibleInterface())
93 return false;
94
95 // Both non-streaming
96 if (hasNonStreamingInterfaceAndBody() && Callee.hasNonStreamingInterface())
97 return false;
98
99 // Both streaming
100 if (hasStreamingInterfaceOrBody() && Callee.hasStreamingInterface())
101 return false;
102
103 return true;
104}
105