//===-- PPCSubtarget.h - Define Subtarget for the PPC ----------*- C++ -*--===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file declares the PowerPC specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #ifndef LLVM_LIB_TARGET_POWERPC_PPCSUBTARGET_H #define LLVM_LIB_TARGET_POWERPC_PPCSUBTARGET_H #include "PPCFrameLowering.h" #include "PPCISelLowering.h" #include "PPCInstrInfo.h" #include "llvm/ADT/Triple.h" #include "llvm/CodeGen/GlobalISel/CallLowering.h" #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/MC/MCInstrItineraries.h" #include #define GET_SUBTARGETINFO_HEADER #include "PPCGenSubtargetInfo.inc" // GCC #defines PPC on Linux but we use it as our namespace name #undef PPC namespace llvm { class StringRef; namespace PPC { // -m directive values. enum { DIR_NONE, DIR_32, DIR_440, DIR_601, DIR_602, DIR_603, DIR_7400, DIR_750, DIR_970, DIR_A2, DIR_E500, DIR_E500mc, DIR_E5500, DIR_PWR3, DIR_PWR4, DIR_PWR5, DIR_PWR5X, DIR_PWR6, DIR_PWR6X, DIR_PWR7, DIR_PWR8, DIR_PWR9, DIR_PWR10, DIR_PWR_FUTURE, DIR_64 }; } class GlobalValue; class PPCSubtarget : public PPCGenSubtargetInfo { public: enum POPCNTDKind { POPCNTD_Unavailable, POPCNTD_Slow, POPCNTD_Fast }; protected: /// TargetTriple - What processor and OS we're targeting. Triple TargetTriple; /// stackAlignment - The minimum alignment known to hold of the stack frame on /// entry to the function and which must be maintained by every function. Align StackAlignment; /// Selected instruction itineraries (one entry per itinerary class.) InstrItineraryData InstrItins; /// Which cpu directive was used. unsigned CPUDirective; /// Used by the ISel to turn in optimizations for POWER4-derived architectures bool HasMFOCRF; bool Has64BitSupport; bool Use64BitRegs; bool UseCRBits; bool HasHardFloat; bool IsPPC64; bool HasAltivec; bool HasFPU; bool HasSPE; bool HasEFPU2; bool HasVSX; bool NeedsTwoConstNR; bool HasP8Vector; bool HasP8Altivec; bool HasP8Crypto; bool HasP9Vector; bool HasP9Altivec; bool HasP10Vector; bool HasPrefixInstrs; bool HasPCRelativeMemops; bool HasMMA; bool HasROPProtect; bool HasPrivileged; bool HasFCPSGN; bool HasFSQRT; bool HasFRE, HasFRES, HasFRSQRTE, HasFRSQRTES; bool HasRecipPrec; bool HasSTFIWX; bool HasLFIWAX; bool HasFPRND; bool HasFPCVT; bool HasISEL; bool HasBPERMD; bool HasExtDiv; bool HasCMPB; bool HasLDBRX; bool IsBookE; bool HasOnlyMSYNC; bool IsE500; bool IsPPC4xx; bool IsPPC6xx; bool FeatureMFTB; bool AllowsUnalignedFPAccess; bool DeprecatedDST; bool IsLittleEndian; bool HasICBT; bool HasInvariantFunctionDescriptors; bool HasPartwordAtomics; bool HasQuadwordAtomics; bool HasDirectMove; bool HasHTM; bool HasFloat128; bool HasFusion; bool HasStoreFusion; bool HasAddiLoadFusion; bool HasAddisLoadFusion; bool HasArithAddFusion; bool HasAddLogicalFusion; bool HasLogicalAddFusion; bool HasLogicalFusion; bool HasSha3Fusion; bool HasCompareFusion; bool HasWideImmFusion; bool HasZeroMoveFusion; bool HasBack2BackFusion; bool IsISA2_06; bool IsISA2_07; bool IsISA3_0; bool IsISA3_1; bool UseLongCalls; bool SecurePlt; bool VectorsUseTwoUnits; bool UsePPCPreRASchedStrategy; bool UsePPCPostRASchedStrategy; bool PairedVectorMemops; bool PredictableSelectIsExpensive; bool HasModernAIXAs; bool IsAIX; POPCNTDKind HasPOPCNTD; const PPCTargetMachine &TM; PPCFrameLowering FrameLowering; PPCInstrInfo InstrInfo; PPCTargetLowering TLInfo; SelectionDAGTargetInfo TSInfo; /// GlobalISel related APIs. std::unique_ptr CallLoweringInfo; std::unique_ptr Legalizer; std::unique_ptr RegBankInfo; std::unique_ptr InstSelector; public: /// This constructor initializes the data members to match that /// of the specified triple. /// PPCSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS, const PPCTargetMachine &TM); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); /// getStackAlignment - Returns the minimum alignment known to hold of the /// stack frame on entry to the function and which must be maintained by every /// function for this subtarget. Align getStackAlignment() const { return StackAlignment; } /// getCPUDirective - Returns the -m directive specified for the cpu. /// unsigned getCPUDirective() const { return CPUDirective; } /// getInstrItins - Return the instruction itineraries based on subtarget /// selection. const InstrItineraryData *getInstrItineraryData() const override { return &InstrItins; } const PPCFrameLowering *getFrameLowering() const override { return &FrameLowering; } const PPCInstrInfo *getInstrInfo() const override { return &InstrInfo; } const PPCTargetLowering *getTargetLowering() const override { return &TLInfo; } const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { return &TSInfo; } const PPCRegisterInfo *getRegisterInfo() const override { return &getInstrInfo()->getRegisterInfo(); } const PPCTargetMachine &getTargetMachine() const { return TM; } /// initializeSubtargetDependencies - Initializes using a CPU and feature string /// so that we can use initializer lists for subtarget initialization. PPCSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); private: void initializeEnvironment(); void initSubtargetFeatures(StringRef CPU, StringRef FS); public: /// isPPC64 - Return true if we are generating code for 64-bit pointer mode. /// bool isPPC64() const; /// has64BitSupport - Return true if the selected CPU supports 64-bit /// instructions, regardless of whether we are in 32-bit or 64-bit mode. bool has64BitSupport() const { return Has64BitSupport; } // useSoftFloat - Return true if soft-float option is turned on. bool useSoftFloat() const { if (isAIXABI() && !HasHardFloat) report_fatal_error("soft-float is not yet supported on AIX."); return !HasHardFloat; } /// use64BitRegs - Return true if in 64-bit mode or if we should use 64-bit /// registers in 32-bit mode when possible. This can only true if /// has64BitSupport() returns true. bool use64BitRegs() const { return Use64BitRegs; } /// useCRBits - Return true if we should store and manipulate i1 values in /// the individual condition register bits. bool useCRBits() const { return UseCRBits; } // isLittleEndian - True if generating little-endian code bool isLittleEndian() const { return IsLittleEndian; } // Specific obvious features. bool hasFCPSGN() const { return HasFCPSGN; } bool hasFSQRT() const { return HasFSQRT; } bool hasFRE() const { return HasFRE; } bool hasFRES() const { return HasFRES; } bool hasFRSQRTE() const { return HasFRSQRTE; } bool hasFRSQRTES() const { return HasFRSQRTES; } bool hasRecipPrec() const { return HasRecipPrec; } bool hasSTFIWX() const { return HasSTFIWX; } bool hasLFIWAX() const { return HasLFIWAX; } bool hasFPRND() const { return HasFPRND; } bool hasFPCVT() const { return HasFPCVT; } bool hasAltivec() const { return HasAltivec; } bool hasSPE() const { return HasSPE; } bool hasEFPU2() const { return HasEFPU2; } bool hasFPU() const { return HasFPU; } bool hasVSX() const { return HasVSX; } bool needsTwoConstNR() const { return NeedsTwoConstNR; } bool hasP8Vector() const { return HasP8Vector; } bool hasP8Altivec() const { return HasP8Altivec; } bool hasP8Crypto() const { return HasP8Crypto; } bool hasP9Vector() const { return HasP9Vector; } bool hasP9Altivec() const { return HasP9Altivec; } bool hasP10Vector() const { return HasP10Vector; } bool hasPrefixInstrs() const { return HasPrefixInstrs; } bool hasPCRelativeMemops() const { return HasPCRelativeMemops; } bool hasMMA() const { return HasMMA; } bool hasROPProtect() const { return HasROPProtect; } bool hasPrivileged() const { return HasPrivileged; } bool pairedVectorMemops() const { return PairedVectorMemops; } bool hasMFOCRF() const { return HasMFOCRF; } bool hasISEL() const { return HasISEL; } bool hasBPERMD() const { return HasBPERMD; } bool hasExtDiv() const { return HasExtDiv; } bool hasCMPB() const { return HasCMPB; } bool hasLDBRX() const { return HasLDBRX; } bool isBookE() const { return IsBookE; } bool hasOnlyMSYNC() const { return HasOnlyMSYNC; } bool isPPC4xx() const { return IsPPC4xx; } bool isPPC6xx() const { return IsPPC6xx; } bool isSecurePlt() const {return SecurePlt; } bool vectorsUseTwoUnits() const {return VectorsUseTwoUnits; } bool isE500() const { return IsE500; } bool isFeatureMFTB() const { return FeatureMFTB; } bool allowsUnalignedFPAccess() const { return AllowsUnalignedFPAccess; } bool isDeprecatedDST() const { return DeprecatedDST; } bool hasICBT() const { return HasICBT; } bool hasInvariantFunctionDescriptors() const { return HasInvariantFunctionDescriptors; } bool usePPCPreRASchedStrategy() const { return UsePPCPreRASchedStrategy; } bool usePPCPostRASchedStrategy() const { return UsePPCPostRASchedStrategy; } bool hasPartwordAtomics() const { return HasPartwordAtomics; } bool hasQuadwordAtomics() const { return HasQuadwordAtomics; } bool hasDirectMove() const { return HasDirectMove; } Align getPlatformStackAlignment() const { return Align(16); } unsigned getRedZoneSize() const { if (isPPC64()) // 288 bytes = 18*8 (FPRs) + 18*8 (GPRs, GPR13 reserved) return 288; // AIX PPC32: 220 bytes = 18*8 (FPRs) + 19*4 (GPRs); // PPC32 SVR4ABI has no redzone. return isAIXABI() ? 220 : 0; } bool hasHTM() const { return HasHTM; } bool hasFloat128() const { return HasFloat128; } bool isISA2_06() const { return IsISA2_06; } bool isISA2_07() const { return IsISA2_07; } bool isISA3_0() const { return IsISA3_0; } bool isISA3_1() const { return IsISA3_1; } bool useLongCalls() const { return UseLongCalls; } bool hasFusion() const { return HasFusion; } bool hasStoreFusion() const { return HasStoreFusion; } bool hasAddiLoadFusion() const { return HasAddiLoadFusion; } bool hasAddisLoadFusion() const { return HasAddisLoadFusion; } bool hasArithAddFusion() const { return HasArithAddFusion; } bool hasAddLogicalFusion() const { return HasAddLogicalFusion; } bool hasLogicalAddFusion() const { return HasLogicalAddFusion; } bool hasLogicalFusion() const { return HasLogicalFusion; } bool hasCompareFusion() const { return HasCompareFusion; } bool hasWideImmFusion() const { return HasWideImmFusion; } bool hasSha3Fusion() const { return HasSha3Fusion; } bool hasZeroMoveFusion() const { return HasZeroMoveFusion; } bool hasBack2BackFusion() const { return HasBack2BackFusion; } bool needsSwapsForVSXMemOps() const { return hasVSX() && isLittleEndian() && !hasP9Vector(); } POPCNTDKind hasPOPCNTD() const { return HasPOPCNTD; } const Triple &getTargetTriple() const { return TargetTriple; } bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); } bool isTargetLinux() const { return TargetTriple.isOSLinux(); } bool isAIXABI() const { return TargetTriple.isOSAIX(); } bool isSVR4ABI() const { return !isAIXABI(); } bool isELFv2ABI() const; bool is64BitELFABI() const { return isSVR4ABI() && isPPC64(); } bool is32BitELFABI() const { return isSVR4ABI() && !isPPC64(); } bool isUsingPCRelativeCalls() const; /// Originally, this function return hasISEL(). Now we always enable it, /// but may expand the ISEL instruction later. bool enableEarlyIfConversion() const override { return true; } /// Scheduling customization. bool enableMachineScheduler() const override; /// Pipeliner customization. bool enableMachinePipeliner() const override; /// Machine Pipeliner customization bool useDFAforSMS() const override; /// This overrides the PostRAScheduler bit in the SchedModel for each CPU. bool enablePostRAScheduler() const override; AntiDepBreakMode getAntiDepBreakMode() const override; void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const override; void overrideSchedPolicy(MachineSchedPolicy &Policy, unsigned NumRegionInstrs) const override; bool useAA() const override; bool enableSubRegLiveness() const override; /// True if the GV will be accessed via an indirect symbol. bool isGVIndirectSymbol(const GlobalValue *GV) const; /// True if the ABI is descriptor based. bool usesFunctionDescriptors() const { // Both 32-bit and 64-bit AIX are descriptor based. For ELF only the 64-bit // v1 ABI uses descriptors. return isAIXABI() || (is64BitELFABI() && !isELFv2ABI()); } unsigned descriptorTOCAnchorOffset() const { assert(usesFunctionDescriptors() && "Should only be called when the target uses descriptors."); return IsPPC64 ? 8 : 4; } unsigned descriptorEnvironmentPointerOffset() const { assert(usesFunctionDescriptors() && "Should only be called when the target uses descriptors."); return IsPPC64 ? 16 : 8; } MCRegister getEnvironmentPointerRegister() const { assert(usesFunctionDescriptors() && "Should only be called when the target uses descriptors."); return IsPPC64 ? PPC::X11 : PPC::R11; } MCRegister getTOCPointerRegister() const { assert((is64BitELFABI() || isAIXABI()) && "Should only be called when the target is a TOC based ABI."); return IsPPC64 ? PPC::X2 : PPC::R2; } MCRegister getStackPointerRegister() const { return IsPPC64 ? PPC::X1 : PPC::R1; } bool isXRaySupported() const override { return IsPPC64 && IsLittleEndian; } bool isPredictableSelectIsExpensive() const { return PredictableSelectIsExpensive; } // Select allocation orders of GPRC and G8RC. It should be strictly consistent // with corresponding AltOrders in PPCRegisterInfo.td. unsigned getGPRAllocationOrderIdx() const { if (is64BitELFABI()) return 1; if (isAIXABI()) return 2; return 0; } // GlobalISEL const CallLowering *getCallLowering() const override; const RegisterBankInfo *getRegBankInfo() const override; const LegalizerInfo *getLegalizerInfo() const override; InstructionSelector *getInstructionSelector() const override; }; } // End llvm namespace #endif