brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.9 KiB · 8974965 Raw
476 lines · c
1//===--- AArch64Subtarget.h - Define Subtarget for the AArch64 -*- C++ -*--===//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// This file declares the AArch64 specific subclass of TargetSubtarget.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64SUBTARGET_H14#define LLVM_LIB_TARGET_AARCH64_AARCH64SUBTARGET_H15 16#include "AArch64FrameLowering.h"17#include "AArch64ISelLowering.h"18#include "AArch64InstrInfo.h"19#include "AArch64PointerAuth.h"20#include "AArch64RegisterInfo.h"21#include "AArch64SelectionDAGInfo.h"22#include "llvm/CodeGen/GlobalISel/CallLowering.h"23#include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h"24#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"25#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"26#include "llvm/CodeGen/RegisterBankInfo.h"27#include "llvm/CodeGen/TargetSubtargetInfo.h"28#include "llvm/IR/DataLayout.h"29#include "llvm/TargetParser/Triple.h"30 31#define GET_SUBTARGETINFO_HEADER32#include "AArch64GenSubtargetInfo.inc"33 34namespace llvm {35class GlobalValue;36class StringRef;37 38class AArch64Subtarget final : public AArch64GenSubtargetInfo {39public:40  enum ARMProcFamilyEnum : uint8_t {41    Generic,42#define ARM_PROCESSOR_FAMILY(ENUM) ENUM,43#include "llvm/TargetParser/AArch64TargetParserDef.inc"44#undef ARM_PROCESSOR_FAMILY45  };46 47protected:48  /// ARMProcFamily - ARM processor family: Cortex-A53, Cortex-A57, and others.49  ARMProcFamilyEnum ARMProcFamily = Generic;50 51  // Enable 64-bit vectorization in SLP.52  unsigned MinVectorRegisterBitWidth = 64;53 54// Bool members corresponding to the SubtargetFeatures defined in tablegen55#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \56  bool ATTRIBUTE = DEFAULT;57#include "AArch64GenSubtargetInfo.inc"58 59  unsigned EpilogueVectorizationMinVF = 16;60  uint8_t MaxInterleaveFactor = 2;61  uint8_t VectorInsertExtractBaseCost = 2;62  uint16_t CacheLineSize = 0;63  // Default scatter/gather overhead.64  unsigned ScatterOverhead = 10;65  unsigned GatherOverhead = 10;66  uint16_t PrefetchDistance = 0;67  uint16_t MinPrefetchStride = 1;68  unsigned MaxPrefetchIterationsAhead = UINT_MAX;69  Align PrefFunctionAlignment;70  Align PrefLoopAlignment;71  unsigned MaxBytesForLoopAlignment = 0;72  unsigned MinimumJumpTableEntries = 4;73  unsigned MaxJumpTableSize = 0;74 75  // ReserveXRegister[i] - X#i is not available as a general purpose register.76  BitVector ReserveXRegister;77 78  // ReserveXRegisterForRA[i] - X#i is not available for register allocator.79  BitVector ReserveXRegisterForRA;80 81  // CustomCallUsedXRegister[i] - X#i call saved.82  BitVector CustomCallSavedXRegs;83 84  bool IsLittle;85 86  bool IsStreaming;87  bool IsStreamingCompatible;88  std::optional<unsigned> StreamingHazardSize;89  unsigned MinSVEVectorSizeInBits;90  unsigned MaxSVEVectorSizeInBits;91  unsigned VScaleForTuning = 1;92  TailFoldingOpts DefaultSVETFOpts = TailFoldingOpts::Disabled;93 94  bool EnableSubregLiveness;95 96  /// TargetTriple - What processor and OS we're targeting.97  Triple TargetTriple;98 99  AArch64FrameLowering FrameLowering;100  AArch64InstrInfo InstrInfo;101  AArch64SelectionDAGInfo TSInfo;102  AArch64TargetLowering TLInfo;103 104  /// GlobalISel related APIs.105  std::unique_ptr<CallLowering> CallLoweringInfo;106  std::unique_ptr<InlineAsmLowering> InlineAsmLoweringInfo;107  std::unique_ptr<InstructionSelector> InstSelector;108  std::unique_ptr<LegalizerInfo> Legalizer;109  std::unique_ptr<RegisterBankInfo> RegBankInfo;110 111private:112  /// initializeSubtargetDependencies - Initializes using CPUString and the113  /// passed in feature string so that we can use initializer lists for114  /// subtarget initialization.115  AArch64Subtarget &initializeSubtargetDependencies(StringRef FS,116                                                    StringRef CPUString,117                                                    StringRef TuneCPUString,118                                                    bool HasMinSize);119 120  /// Initialize properties based on the selected processor family.121  void initializeProperties(bool HasMinSize);122 123public:124  /// This constructor initializes the data members to match that125  /// of the specified triple.126  AArch64Subtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,127                   StringRef FS, const TargetMachine &TM, bool LittleEndian,128                   unsigned MinSVEVectorSizeInBitsOverride = 0,129                   unsigned MaxSVEVectorSizeInBitsOverride = 0,130                   bool IsStreaming = false, bool IsStreamingCompatible = false,131                   bool HasMinSize = false);132 133// Getters for SubtargetFeatures defined in tablegen134#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \135  bool GETTER() const { return ATTRIBUTE; }136#include "AArch64GenSubtargetInfo.inc"137 138  const AArch64SelectionDAGInfo *getSelectionDAGInfo() const override {139    return &TSInfo;140  }141  const AArch64FrameLowering *getFrameLowering() const override {142    return &FrameLowering;143  }144  const AArch64TargetLowering *getTargetLowering() const override {145    return &TLInfo;146  }147  const AArch64InstrInfo *getInstrInfo() const override { return &InstrInfo; }148  const AArch64RegisterInfo *getRegisterInfo() const override {149    return &getInstrInfo()->getRegisterInfo();150  }151  const CallLowering *getCallLowering() const override;152  const InlineAsmLowering *getInlineAsmLowering() const override;153  InstructionSelector *getInstructionSelector() const override;154  const LegalizerInfo *getLegalizerInfo() const override;155  const RegisterBankInfo *getRegBankInfo() const override;156  const Triple &getTargetTriple() const { return TargetTriple; }157  bool enableMachineScheduler() const override { return true; }158  bool enablePostRAScheduler() const override { return usePostRAScheduler(); }159  bool enableSubRegLiveness() const override { return EnableSubregLiveness; }160 161  bool enableMachinePipeliner() const override;162  bool useDFAforSMS() const override { return false; }163 164  /// Returns ARM processor family.165  /// Avoid this function! CPU specifics should be kept local to this class166  /// and preferably modeled with SubtargetFeatures or properties in167  /// initializeProperties().168  ARMProcFamilyEnum getProcFamily() const {169    return ARMProcFamily;170  }171 172  bool isXRaySupported() const override { return true; }173 174  /// Returns true if the function has a streaming body.175  bool isStreaming() const { return IsStreaming; }176 177  /// Returns true if the function has a streaming-compatible body.178  bool isStreamingCompatible() const { return IsStreamingCompatible; }179 180  /// Returns the size of memory region that if accessed by both the CPU and181  /// the SME unit could result in a hazard. 0 = disabled.182  unsigned getStreamingHazardSize() const {183    return StreamingHazardSize.value_or(184        !hasSMEFA64() && hasSME() && hasSVE() ? 1024 : 0);185  }186 187  /// Returns true if the target has NEON and the function at runtime is known188  /// to have NEON enabled (e.g. the function is known not to be in streaming-SVE189  /// mode, which disables NEON instructions).190  bool isNeonAvailable() const {191    return hasNEON() &&192           (hasSMEFA64() || (!isStreaming() && !isStreamingCompatible()));193  }194 195  /// Returns true if the target has SVE and can use the full range of SVE196  /// instructions, for example because it knows the function is known not to be197  /// in streaming-SVE mode or when the target has FEAT_FA64 enabled.198  bool isSVEAvailable() const {199    return hasSVE() &&200           (hasSMEFA64() || (!isStreaming() && !isStreamingCompatible()));201  }202 203  /// Returns true if the target has access to the streaming-compatible subset204  /// of SVE instructions.205  bool isStreamingSVEAvailable() const { return hasSME() && isStreaming(); }206 207  /// Returns true if the target has access to either the full range of SVE208  /// instructions, or the streaming-compatible subset of SVE instructions.209  bool isSVEorStreamingSVEAvailable() const {210    return hasSVE() || isStreamingSVEAvailable();211  }212 213  /// Returns true if the target has access to either the full range of SVE214  /// instructions, or the streaming-compatible subset of SVE instructions215  /// available to SME2.216  bool isNonStreamingSVEorSME2Available() const {217    return isSVEAvailable() || (isSVEorStreamingSVEAvailable() && hasSME2());218  }219 220  unsigned getMinVectorRegisterBitWidth() const {221    // Don't assume any minimum vector size when PSTATE.SM may not be 0, because222    // we don't yet support streaming-compatible codegen support that we trust223    // is safe for functions that may be executed in streaming-SVE mode.224    // By returning '0' here, we disable vectorization.225    if (!isSVEAvailable() && !isNeonAvailable())226      return 0;227    return MinVectorRegisterBitWidth;228  }229 230  bool isXRegisterReserved(size_t i) const { return ReserveXRegister[i]; }231  bool isXRegisterReservedForRA(size_t i) const { return ReserveXRegisterForRA[i]; }232  unsigned getNumXRegisterReserved() const {233    BitVector AllReservedX(AArch64::GPR64commonRegClass.getNumRegs());234    AllReservedX |= ReserveXRegister;235    AllReservedX |= ReserveXRegisterForRA;236    return AllReservedX.count();237  }238  bool isLRReservedForRA() const { return ReserveLRForRA; }239  bool isXRegCustomCalleeSaved(size_t i) const {240    return CustomCallSavedXRegs[i];241  }242  bool hasCustomCallingConv() const { return CustomCallSavedXRegs.any(); }243 244  /// Return true if the CPU supports any kind of instruction fusion.245  bool hasFusion() const {246    return hasArithmeticBccFusion() || hasArithmeticCbzFusion() ||247           hasFuseAES() || hasFuseArithmeticLogic() || hasFuseCmpCSel() ||248           hasFuseCmpCSet() || hasFuseAdrpAdd() || hasFuseLiterals();249  }250 251  unsigned getEpilogueVectorizationMinVF() const {252    return EpilogueVectorizationMinVF;253  }254  unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; }255  unsigned getVectorInsertExtractBaseCost() const;256  unsigned getCacheLineSize() const override { return CacheLineSize; }257  unsigned getScatterOverhead() const { return ScatterOverhead; }258  unsigned getGatherOverhead() const { return GatherOverhead; }259  unsigned getPrefetchDistance() const override { return PrefetchDistance; }260  unsigned getMinPrefetchStride(unsigned NumMemAccesses,261                                unsigned NumStridedMemAccesses,262                                unsigned NumPrefetches,263                                bool HasCall) const override {264    return MinPrefetchStride;265  }266  unsigned getMaxPrefetchIterationsAhead() const override {267    return MaxPrefetchIterationsAhead;268  }269  Align getPrefFunctionAlignment() const {270    return PrefFunctionAlignment;271  }272  Align getPrefLoopAlignment() const { return PrefLoopAlignment; }273 274  unsigned getMaxBytesForLoopAlignment() const {275    return MaxBytesForLoopAlignment;276  }277 278  unsigned getMaximumJumpTableSize() const { return MaxJumpTableSize; }279  unsigned getMinimumJumpTableEntries() const {280    return MinimumJumpTableEntries;281  }282 283  /// CPU has TBI (top byte of addresses is ignored during HW address284  /// translation) and OS enables it.285  bool supportsAddressTopByteIgnored() const;286 287  bool isLittleEndian() const { return IsLittle; }288 289  bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }290  bool isTargetIOS() const { return TargetTriple.isiOS(); }291  bool isTargetLinux() const { return TargetTriple.isOSLinux(); }292  bool isTargetWindows() const { return TargetTriple.isOSWindows(); }293  bool isTargetAndroid() const { return TargetTriple.isAndroid(); }294  bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); }295  bool isWindowsArm64EC() const { return TargetTriple.isWindowsArm64EC(); }296 297  bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }298  bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }299  bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }300 301  bool isTargetILP32() const {302    return TargetTriple.isArch32Bit() ||303           TargetTriple.getEnvironment() == Triple::GNUILP32;304  }305 306  bool useAA() const override;307 308  bool addrSinkUsingGEPs() const override {309    // Keeping GEPs inbounds is important for exploiting AArch64310    // addressing-modes in ILP32 mode.311    return useAA() || isTargetILP32();312  }313 314  bool useSmallAddressing() const {315    switch (TLInfo.getTargetMachine().getCodeModel()) {316      case CodeModel::Kernel:317        // Kernel is currently allowed only for Fuchsia targets,318        // where it is the same as Small for almost all purposes.319      case CodeModel::Small:320        return true;321      default:322        return false;323    }324  }325 326  /// Returns whether the operating system makes it safer to store sensitive327  /// values in x16 and x17 as opposed to other registers.328  bool isX16X17Safer() const;329 330  /// ParseSubtargetFeatures - Parses features string setting specified331  /// subtarget options.  Definition of function is auto generated by tblgen.332  void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);333 334  /// ClassifyGlobalReference - Find the target operand flags that describe335  /// how a global value should be referenced for the current subtarget.336  unsigned ClassifyGlobalReference(const GlobalValue *GV,337                                   const TargetMachine &TM) const;338 339  unsigned classifyGlobalFunctionReference(const GlobalValue *GV,340                                           const TargetMachine &TM) const;341 342  /// This function is design to compatible with the function def in other343  /// targets and escape build error about the virtual function def in base344  /// class TargetSubtargetInfo. Updeate me if AArch64 target need to use it.345  unsigned char346  classifyGlobalFunctionReference(const GlobalValue *GV) const override {347    return 0;348  }349 350  void overrideSchedPolicy(MachineSchedPolicy &Policy,351                           const SchedRegion &Region) const override;352 353  void adjustSchedDependency(SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx,354                             SDep &Dep,355                             const TargetSchedModel *SchedModel) const override;356 357  bool enableEarlyIfConversion() const override;358 359  std::unique_ptr<PBQPRAConstraint> getCustomPBQPConstraints() const override;360 361  bool isCallingConvWin64(CallingConv::ID CC, bool IsVarArg) const {362    switch (CC) {363    case CallingConv::C:364    case CallingConv::Fast:365    case CallingConv::Swift:366    case CallingConv::SwiftTail:367      return isTargetWindows();368    case CallingConv::PreserveNone:369      return IsVarArg && isTargetWindows();370    case CallingConv::Win64:371      return true;372    default:373      return false;374    }375  }376 377  /// Return whether FrameLowering should always set the "extended frame378  /// present" bit in FP, or set it based on a symbol in the runtime.379  bool swiftAsyncContextIsDynamicallySet() const {380    // Older OS versions (particularly system unwinders) are confused by the381    // Swift extended frame, so when building code that might be run on them we382    // must dynamically query the concurrency library to determine whether383    // extended frames should be flagged as present.384    const Triple &TT = getTargetTriple();385 386    unsigned Major = TT.getOSVersion().getMajor();387    switch(TT.getOS()) {388    default:389      return false;390    case Triple::IOS:391    case Triple::TvOS:392      return Major < 15;393    case Triple::WatchOS:394      return Major < 8;395    case Triple::MacOSX:396    case Triple::Darwin:397      return Major < 12;398    }399  }400 401  void mirFileLoaded(MachineFunction &MF) const override;402 403  // Return the known range for the bit length of SVE data registers. A value404  // of 0 means nothing is known about that particular limit beyond what's405  // implied by the architecture.406  unsigned getMaxSVEVectorSizeInBits() const {407    assert(isSVEorStreamingSVEAvailable() &&408           "Tried to get SVE vector length without SVE support!");409    return MaxSVEVectorSizeInBits;410  }411 412  unsigned getMinSVEVectorSizeInBits() const {413    assert(isSVEorStreamingSVEAvailable() &&414           "Tried to get SVE vector length without SVE support!");415    return MinSVEVectorSizeInBits;416  }417 418  // Return the known bit length of SVE data registers. A value of 0 means the419  // length is unknown beyond what's implied by the architecture.420  unsigned getSVEVectorSizeInBits() const {421    assert(isSVEorStreamingSVEAvailable() &&422           "Tried to get SVE vector length without SVE support!");423    if (MinSVEVectorSizeInBits == MaxSVEVectorSizeInBits)424      return MaxSVEVectorSizeInBits;425    return 0;426  }427 428  bool useSVEForFixedLengthVectors() const {429    if (!isSVEorStreamingSVEAvailable())430      return false;431 432    // Prefer NEON unless larger SVE registers are available.433    return !isNeonAvailable() || getMinSVEVectorSizeInBits() >= 256;434  }435 436  bool useSVEForFixedLengthVectors(EVT VT) const {437    if (!useSVEForFixedLengthVectors() || !VT.isFixedLengthVector())438      return false;439    return VT.getFixedSizeInBits() > AArch64::SVEBitsPerBlock ||440           !isNeonAvailable();441  }442 443  unsigned getVScaleForTuning() const { return VScaleForTuning; }444 445  TailFoldingOpts getSVETailFoldingDefaultOpts() const {446    return DefaultSVETFOpts;447  }448 449  /// Returns true to use the addvl/inc/dec instructions, as opposed to separate450  /// add + cnt instructions.451  bool useScalarIncVL() const;452 453  const char* getChkStkName() const {454    if (isWindowsArm64EC())455      return "#__chkstk_arm64ec";456    return "__chkstk";457  }458 459  /// Choose a method of checking LR before performing a tail call.460  AArch64PAuth::AuthCheckMethod461  getAuthenticatedLRCheckMethod(const MachineFunction &MF) const;462 463  /// Compute the integer discriminator for a given BlockAddress constant, if464  /// blockaddress signing is enabled, or std::nullopt otherwise.465  /// Blockaddress signing is controlled by the function attribute466  /// "ptrauth-indirect-gotos" on the parent function.467  /// Note that this assumes the discriminator is independent of the indirect468  /// goto branch site itself, i.e., it's the same for all BlockAddresses in469  /// a function.470  std::optional<uint16_t>471  getPtrAuthBlockAddressDiscriminatorIfEnabled(const Function &ParentFn) const;472};473} // End llvm namespace474 475#endif476