xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
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