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(!(hasNewZAInterface() && hasSharedZAInterface()) &&
24          "ZA_New and ZA_Shared are mutually exclusive");
25   assert(!(hasNewZAInterface() && preservesZA()) &&
26          "ZA_New and ZA_Preserved are mutually exclusive");
27 }
28 
29 SMEAttrs::SMEAttrs(const CallBase &CB) {
30   *this = SMEAttrs(CB.getAttributes());
31   if (auto *F = CB.getCalledFunction())
32     set(SMEAttrs(*F).Bitmask);
33 }
34 
35 SMEAttrs::SMEAttrs(const AttributeList &Attrs) {
36   Bitmask = 0;
37   if (Attrs.hasFnAttr("aarch64_pstate_sm_enabled"))
38     Bitmask |= SM_Enabled;
39   if (Attrs.hasFnAttr("aarch64_pstate_sm_compatible"))
40     Bitmask |= SM_Compatible;
41   if (Attrs.hasFnAttr("aarch64_pstate_sm_body"))
42     Bitmask |= SM_Body;
43   if (Attrs.hasFnAttr("aarch64_pstate_za_shared"))
44     Bitmask |= ZA_Shared;
45   if (Attrs.hasFnAttr("aarch64_pstate_za_new"))
46     Bitmask |= ZA_New;
47   if (Attrs.hasFnAttr("aarch64_pstate_za_preserved"))
48     Bitmask |= ZA_Preserved;
49 }
50 
51 std::optional<bool>
52 SMEAttrs::requiresSMChange(const SMEAttrs &Callee,
53                            bool BodyOverridesInterface) const {
54   // If the transition is not through a call (e.g. when considering inlining)
55   // and Callee has a streaming body, then we can ignore the interface of
56   // Callee.
57   if (BodyOverridesInterface && Callee.hasStreamingBody()) {
58     return hasStreamingInterfaceOrBody() ? std::nullopt
59                                          : std::optional<bool>(true);
60   }
61 
62   if (Callee.hasStreamingCompatibleInterface())
63     return std::nullopt;
64 
65   // Both non-streaming
66   if (hasNonStreamingInterfaceAndBody() && Callee.hasNonStreamingInterface())
67     return std::nullopt;
68 
69   // Both streaming
70   if (hasStreamingInterfaceOrBody() && Callee.hasStreamingInterface())
71     return std::nullopt;
72 
73   return Callee.hasStreamingInterface();
74 }
75