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 | |
43 | SMEAttrs::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 | |
50 | SMEAttrs::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 | |
61 | SMEAttrs::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 | |
91 | bool 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 |