xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1bdd1243dSDimitry Andric //===-- AArch64SMEAttributes.cpp - Helper for interpreting SME attributes -===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdd1243dSDimitry Andric //
7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8bdd1243dSDimitry Andric 
9bdd1243dSDimitry Andric #include "AArch64SMEAttributes.h"
10bdd1243dSDimitry Andric #include "llvm/IR/InstrTypes.h"
11bdd1243dSDimitry Andric #include <cassert>
12bdd1243dSDimitry Andric 
13bdd1243dSDimitry Andric using namespace llvm;
14bdd1243dSDimitry Andric 
15bdd1243dSDimitry Andric void SMEAttrs::set(unsigned M, bool Enable) {
16bdd1243dSDimitry Andric   if (Enable)
17bdd1243dSDimitry Andric     Bitmask |= M;
18bdd1243dSDimitry Andric   else
19bdd1243dSDimitry Andric     Bitmask &= ~M;
20bdd1243dSDimitry Andric 
21bdd1243dSDimitry Andric   assert(!(hasStreamingInterface() && hasStreamingCompatibleInterface()) &&
22bdd1243dSDimitry Andric          "SM_Enabled and SM_Compatible are mutually exclusive");
23*5f757f3fSDimitry Andric   assert(!(hasNewZABody() && hasSharedZAInterface()) &&
24bdd1243dSDimitry Andric          "ZA_New and ZA_Shared are mutually exclusive");
25*5f757f3fSDimitry Andric   assert(!(hasNewZABody() && preservesZA()) &&
26bdd1243dSDimitry Andric          "ZA_New and ZA_Preserved are mutually exclusive");
27*5f757f3fSDimitry Andric   assert(!(hasNewZABody() && (Bitmask & ZA_NoLazySave)) &&
28*5f757f3fSDimitry Andric          "ZA_New and ZA_NoLazySave are mutually exclusive");
29*5f757f3fSDimitry Andric   assert(!(hasSharedZAInterface() && (Bitmask & ZA_NoLazySave)) &&
30*5f757f3fSDimitry Andric          "ZA_Shared and ZA_NoLazySave are mutually exclusive");
31bdd1243dSDimitry Andric }
32bdd1243dSDimitry Andric 
33bdd1243dSDimitry Andric SMEAttrs::SMEAttrs(const CallBase &CB) {
34bdd1243dSDimitry Andric   *this = SMEAttrs(CB.getAttributes());
35*5f757f3fSDimitry Andric   if (auto *F = CB.getCalledFunction()) {
36*5f757f3fSDimitry Andric     set(SMEAttrs(*F).Bitmask | SMEAttrs(F->getName()).Bitmask);
37*5f757f3fSDimitry Andric   }
38*5f757f3fSDimitry Andric }
39*5f757f3fSDimitry Andric 
40*5f757f3fSDimitry Andric SMEAttrs::SMEAttrs(StringRef FuncName) : Bitmask(0) {
41*5f757f3fSDimitry Andric   if (FuncName == "__arm_tpidr2_save" || FuncName == "__arm_sme_state")
42*5f757f3fSDimitry Andric     Bitmask |= (SMEAttrs::SM_Compatible | SMEAttrs::ZA_Preserved |
43*5f757f3fSDimitry Andric                 SMEAttrs::ZA_NoLazySave);
44*5f757f3fSDimitry Andric   if (FuncName == "__arm_tpidr2_restore")
45*5f757f3fSDimitry Andric     Bitmask |= (SMEAttrs::SM_Compatible | SMEAttrs::ZA_Shared |
46*5f757f3fSDimitry Andric                 SMEAttrs::ZA_NoLazySave);
47bdd1243dSDimitry Andric }
48bdd1243dSDimitry Andric 
49bdd1243dSDimitry Andric SMEAttrs::SMEAttrs(const AttributeList &Attrs) {
50bdd1243dSDimitry Andric   Bitmask = 0;
51bdd1243dSDimitry Andric   if (Attrs.hasFnAttr("aarch64_pstate_sm_enabled"))
52bdd1243dSDimitry Andric     Bitmask |= SM_Enabled;
53bdd1243dSDimitry Andric   if (Attrs.hasFnAttr("aarch64_pstate_sm_compatible"))
54bdd1243dSDimitry Andric     Bitmask |= SM_Compatible;
55bdd1243dSDimitry Andric   if (Attrs.hasFnAttr("aarch64_pstate_sm_body"))
56bdd1243dSDimitry Andric     Bitmask |= SM_Body;
57bdd1243dSDimitry Andric   if (Attrs.hasFnAttr("aarch64_pstate_za_shared"))
58bdd1243dSDimitry Andric     Bitmask |= ZA_Shared;
59bdd1243dSDimitry Andric   if (Attrs.hasFnAttr("aarch64_pstate_za_new"))
60bdd1243dSDimitry Andric     Bitmask |= ZA_New;
61bdd1243dSDimitry Andric   if (Attrs.hasFnAttr("aarch64_pstate_za_preserved"))
62bdd1243dSDimitry Andric     Bitmask |= ZA_Preserved;
63bdd1243dSDimitry Andric }
64bdd1243dSDimitry Andric 
65bdd1243dSDimitry Andric std::optional<bool>
66bdd1243dSDimitry Andric SMEAttrs::requiresSMChange(const SMEAttrs &Callee,
67bdd1243dSDimitry Andric                            bool BodyOverridesInterface) const {
68bdd1243dSDimitry Andric   // If the transition is not through a call (e.g. when considering inlining)
69bdd1243dSDimitry Andric   // and Callee has a streaming body, then we can ignore the interface of
70bdd1243dSDimitry Andric   // Callee.
71bdd1243dSDimitry Andric   if (BodyOverridesInterface && Callee.hasStreamingBody()) {
72bdd1243dSDimitry Andric     return hasStreamingInterfaceOrBody() ? std::nullopt
73bdd1243dSDimitry Andric                                          : std::optional<bool>(true);
74bdd1243dSDimitry Andric   }
75bdd1243dSDimitry Andric 
76bdd1243dSDimitry Andric   if (Callee.hasStreamingCompatibleInterface())
77bdd1243dSDimitry Andric     return std::nullopt;
78bdd1243dSDimitry Andric 
79bdd1243dSDimitry Andric   // Both non-streaming
80bdd1243dSDimitry Andric   if (hasNonStreamingInterfaceAndBody() && Callee.hasNonStreamingInterface())
81bdd1243dSDimitry Andric     return std::nullopt;
82bdd1243dSDimitry Andric 
83bdd1243dSDimitry Andric   // Both streaming
84bdd1243dSDimitry Andric   if (hasStreamingInterfaceOrBody() && Callee.hasStreamingInterface())
85bdd1243dSDimitry Andric     return std::nullopt;
86bdd1243dSDimitry Andric 
87bdd1243dSDimitry Andric   return Callee.hasStreamingInterface();
88bdd1243dSDimitry Andric }
89