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