brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · 28c397e Raw
222 lines · c
1//===-- AArch64SMEAttributes.h - 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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64SMEATTRIBUTES_H10#define LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64SMEATTRIBUTES_H11 12#include "llvm/IR/Function.h"13 14namespace llvm {15namespace RTLIB {16struct RuntimeLibcallsInfo;17}18 19class Function;20class CallBase;21class AttributeList;22 23/// SMEAttrs is a utility class to parse the SME ACLE attributes on functions.24/// It helps determine a function's requirements for PSTATE.ZA and PSTATE.SM.25class SMEAttrs {26  unsigned Bitmask = Normal;27 28public:29  enum class StateValue {30    None = 0,31    In = 1,        // aarch64_in_zt032    Out = 2,       // aarch64_out_zt033    InOut = 3,     // aarch64_inout_zt034    Preserved = 4, // aarch64_preserves_zt035    New = 5        // aarch64_new_zt036  };37 38  // Enum with bitmasks for each individual SME feature.39  enum Mask {40    Normal = 0,41    SM_Enabled = 1 << 0,      // aarch64_pstate_sm_enabled42    SM_Compatible = 1 << 1,   // aarch64_pstate_sm_compatible43    SM_Body = 1 << 2,         // aarch64_pstate_sm_body44    SME_ABI_Routine = 1 << 3, // Used for SME ABI routines to avoid lazy saves45    ZA_State_Agnostic = 1 << 4,46    ZT0_Undef = 1 << 5, // Use to mark ZT0 as undef to avoid spills47    ZA_Shift = 6,48    ZA_Mask = 0b111 << ZA_Shift,49    ZT0_Shift = 9,50    ZT0_Mask = 0b111 << ZT0_Shift,51    CallSiteFlags_Mask = ZT0_Undef52  };53 54  SMEAttrs() = default;55  SMEAttrs(unsigned Mask) { set(Mask); }56  SMEAttrs(const Function &F, const RTLIB::RuntimeLibcallsInfo *RTLCI = nullptr)57      : SMEAttrs(F.getAttributes()) {58    if (RTLCI)59      addKnownFunctionAttrs(F.getName(), *RTLCI);60  }61  SMEAttrs(const AttributeList &L);62  SMEAttrs(StringRef FuncName, const RTLIB::RuntimeLibcallsInfo &RTLCI) {63    addKnownFunctionAttrs(FuncName, RTLCI);64  };65 66  void set(unsigned M, bool Enable = true) {67    if (Enable)68      Bitmask |= M;69    else70      Bitmask &= ~M;71#ifndef NDEBUG72    validate();73#endif74  }75 76  // Interfaces to query PSTATE.SM77  bool hasStreamingBody() const { return Bitmask & SM_Body; }78  bool hasStreamingInterface() const { return Bitmask & SM_Enabled; }79  bool hasStreamingInterfaceOrBody() const {80    return hasStreamingBody() || hasStreamingInterface();81  }82  bool hasStreamingCompatibleInterface() const {83    return Bitmask & SM_Compatible;84  }85  bool hasNonStreamingInterface() const {86    return !hasStreamingInterface() && !hasStreamingCompatibleInterface();87  }88  bool hasNonStreamingInterfaceAndBody() const {89    return hasNonStreamingInterface() && !hasStreamingBody();90  }91 92  // Interfaces to query ZA93  static StateValue decodeZAState(unsigned Bitmask) {94    return static_cast<StateValue>((Bitmask & ZA_Mask) >> ZA_Shift);95  }96  static unsigned encodeZAState(StateValue S) {97    return static_cast<unsigned>(S) << ZA_Shift;98  }99 100  bool isNewZA() const { return decodeZAState(Bitmask) == StateValue::New; }101  bool isInZA() const { return decodeZAState(Bitmask) == StateValue::In; }102  bool isOutZA() const { return decodeZAState(Bitmask) == StateValue::Out; }103  bool isInOutZA() const { return decodeZAState(Bitmask) == StateValue::InOut; }104  bool isPreservesZA() const {105    return decodeZAState(Bitmask) == StateValue::Preserved;106  }107  bool sharesZA() const {108    StateValue State = decodeZAState(Bitmask);109    return State == StateValue::In || State == StateValue::Out ||110           State == StateValue::InOut || State == StateValue::Preserved;111  }112  bool hasAgnosticZAInterface() const { return Bitmask & ZA_State_Agnostic; }113  bool hasSharedZAInterface() const { return sharesZA() || sharesZT0(); }114  bool hasPrivateZAInterface() const {115    return !hasSharedZAInterface() && !hasAgnosticZAInterface();116  }117  bool hasZAState() const { return isNewZA() || sharesZA(); }118  bool isSMEABIRoutine() const { return Bitmask & SME_ABI_Routine; }119 120  // Interfaces to query ZT0 State121  static StateValue decodeZT0State(unsigned Bitmask) {122    return static_cast<StateValue>((Bitmask & ZT0_Mask) >> ZT0_Shift);123  }124  static unsigned encodeZT0State(StateValue S) {125    return static_cast<unsigned>(S) << ZT0_Shift;126  }127 128  bool isNewZT0() const { return decodeZT0State(Bitmask) == StateValue::New; }129  bool isInZT0() const { return decodeZT0State(Bitmask) == StateValue::In; }130  bool isOutZT0() const { return decodeZT0State(Bitmask) == StateValue::Out; }131  bool isInOutZT0() const {132    return decodeZT0State(Bitmask) == StateValue::InOut;133  }134  bool isPreservesZT0() const {135    return decodeZT0State(Bitmask) == StateValue::Preserved;136  }137  bool hasUndefZT0() const { return Bitmask & ZT0_Undef; }138  bool sharesZT0() const {139    StateValue State = decodeZT0State(Bitmask);140    return State == StateValue::In || State == StateValue::Out ||141           State == StateValue::InOut || State == StateValue::Preserved;142  }143  bool hasZT0State() const { return isNewZT0() || sharesZT0(); }144 145  SMEAttrs operator|(SMEAttrs Other) const {146    SMEAttrs Merged(*this);147    Merged.set(Other.Bitmask);148    return Merged;149  }150 151  SMEAttrs withoutPerCallsiteFlags() const {152    return (Bitmask & ~CallSiteFlags_Mask);153  }154 155  bool operator==(SMEAttrs const &Other) const {156    return Bitmask == Other.Bitmask;157  }158 159private:160  void addKnownFunctionAttrs(StringRef FuncName,161                             const RTLIB::RuntimeLibcallsInfo &RTLCI);162  void validate() const;163};164 165/// SMECallAttrs is a utility class to hold the SMEAttrs for a callsite. It has166/// interfaces to query whether a streaming mode change or lazy-save mechanism167/// is required when going from one function to another (e.g. through a call).168class SMECallAttrs {169  SMEAttrs CallerFn;170  SMEAttrs CalledFn;171  SMEAttrs Callsite;172  bool IsIndirect = false;173 174public:175  SMECallAttrs(SMEAttrs Caller, SMEAttrs Callee,176               SMEAttrs Callsite = SMEAttrs::Normal)177      : CallerFn(Caller), CalledFn(Callee), Callsite(Callsite) {}178 179  SMECallAttrs(const CallBase &CB, const RTLIB::RuntimeLibcallsInfo *RTLCI);180 181  SMEAttrs &caller() { return CallerFn; }182  SMEAttrs &callee() { return IsIndirect ? Callsite : CalledFn; }183  SMEAttrs &callsite() { return Callsite; }184  SMEAttrs const &caller() const { return CallerFn; }185  SMEAttrs const &callee() const {186    return const_cast<SMECallAttrs *>(this)->callee();187  }188  SMEAttrs const &callsite() const { return Callsite; }189 190  /// \return true if a call from Caller -> Callee requires a change in191  /// streaming mode.192  bool requiresSMChange() const;193 194  bool requiresLazySave() const {195    return caller().hasZAState() && callee().hasPrivateZAInterface() &&196           !callee().isSMEABIRoutine();197  }198 199  bool requiresPreservingZT0() const {200    return caller().hasZT0State() && !callsite().hasUndefZT0() &&201           !callee().sharesZT0() && !callee().hasAgnosticZAInterface();202  }203 204  bool requiresDisablingZABeforeCall() const {205    return caller().hasZT0State() && !caller().hasZAState() &&206           callee().hasPrivateZAInterface() && !callee().isSMEABIRoutine();207  }208 209  bool requiresEnablingZAAfterCall() const {210    return requiresDisablingZABeforeCall();211  }212 213  bool requiresPreservingAllZAState() const {214    return caller().hasAgnosticZAInterface() &&215           !callee().hasAgnosticZAInterface() && !callee().isSMEABIRoutine();216  }217};218 219} // namespace llvm220 221#endif // LLVM_LIB_TARGET_AARCH64_UTILS_AARCH64SMEATTRIBUTES_H222