|  | //===-- 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/SelectionDAGTargetInfo.h" | 
|  | #include "llvm/CodeGen/TargetSubtargetInfo.h" | 
|  | #include "llvm/IR/DataLayout.h" | 
|  | #include "llvm/MC/MCInstrItineraries.h" | 
|  | #include <string> | 
|  |  | 
|  | #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_PWR_FUTURE, | 
|  | DIR_64 | 
|  | }; | 
|  | } | 
|  |  | 
|  | class GlobalValue; | 
|  | class TargetMachine; | 
|  |  | 
|  | 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 HasQPX; | 
|  | bool HasVSX; | 
|  | bool NeedsTwoConstNR; | 
|  | bool HasP8Vector; | 
|  | bool HasP8Altivec; | 
|  | bool HasP8Crypto; | 
|  | bool HasP9Vector; | 
|  | bool HasP9Altivec; | 
|  | 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 HasLazyResolverStubs; | 
|  | bool IsLittleEndian; | 
|  | bool HasICBT; | 
|  | bool HasInvariantFunctionDescriptors; | 
|  | bool HasPartwordAtomics; | 
|  | bool HasDirectMove; | 
|  | bool HasHTM; | 
|  | bool HasFloat128; | 
|  | bool IsISA3_0; | 
|  | bool UseLongCalls; | 
|  | bool SecurePlt; | 
|  | bool VectorsUseTwoUnits; | 
|  | bool UsePPCPreRASchedStrategy; | 
|  | bool UsePPCPostRASchedStrategy; | 
|  |  | 
|  | POPCNTDKind HasPOPCNTD; | 
|  |  | 
|  | /// When targeting QPX running a stock PPC64 Linux kernel where the stack | 
|  | /// alignment has not been changed, we need to keep the 16-byte alignment | 
|  | /// of the stack. | 
|  | bool IsQPXStackUnaligned; | 
|  |  | 
|  | const PPCTargetMachine &TM; | 
|  | PPCFrameLowering FrameLowering; | 
|  | PPCInstrInfo InstrInfo; | 
|  | PPCTargetLowering TLInfo; | 
|  | SelectionDAGTargetInfo TSInfo; | 
|  |  | 
|  | 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 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; } | 
|  |  | 
|  | /// getDarwinDirective - Returns the -m directive specified for the cpu. | 
|  | unsigned getDarwinDirective() const { return CPUDirective; } | 
|  |  | 
|  | /// 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; } | 
|  |  | 
|  | /// hasLazyResolverStub - Return true if accesses to the specified global have | 
|  | /// to go through a dyld lazy resolution stub.  This means that an extra load | 
|  | /// is required to get the address of the global. | 
|  | bool hasLazyResolverStub(const GlobalValue *GV) const; | 
|  |  | 
|  | // 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 hasFPU() const { return HasFPU; } | 
|  | bool hasQPX() const { return HasQPX; } | 
|  | 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 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 hasDirectMove() const { return HasDirectMove; } | 
|  |  | 
|  | bool isQPXStackUnaligned() const { return IsQPXStackUnaligned; } | 
|  | Align getPlatformStackAlignment() const { | 
|  | if ((hasQPX() || isBGQ()) && !isQPXStackUnaligned()) | 
|  | return Align(32); | 
|  |  | 
|  | return Align(16); | 
|  | } | 
|  |  | 
|  | // DarwinABI has a 224-byte red zone. PPC32 SVR4ABI(Non-DarwinABI) has no | 
|  | // red zone and PPC64 SVR4ABI has a 288-byte red zone. | 
|  | unsigned  getRedZoneSize() const { | 
|  | return isDarwinABI() ? 224 : (isPPC64() ? 288 : 0); | 
|  | } | 
|  |  | 
|  | bool hasHTM() const { return HasHTM; } | 
|  | bool hasFloat128() const { return HasFloat128; } | 
|  | bool isISA3_0() const { return IsISA3_0; } | 
|  | bool useLongCalls() const { return UseLongCalls; } | 
|  | bool needsSwapsForVSXMemOps() const { | 
|  | return hasVSX() && isLittleEndian() && !hasP9Vector(); | 
|  | } | 
|  |  | 
|  | POPCNTDKind hasPOPCNTD() const { return HasPOPCNTD; } | 
|  |  | 
|  | const Triple &getTargetTriple() const { return TargetTriple; } | 
|  |  | 
|  | /// isDarwin - True if this is any darwin platform. | 
|  | bool isDarwin() const { return TargetTriple.isMacOSX(); } | 
|  | /// isBGQ - True if this is a BG/Q platform. | 
|  | bool isBGQ() const { return TargetTriple.getVendor() == Triple::BGQ; } | 
|  |  | 
|  | bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } | 
|  | bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); } | 
|  | bool isTargetLinux() const { return TargetTriple.isOSLinux(); } | 
|  |  | 
|  | bool isDarwinABI() const { return isTargetMachO() || isDarwin(); } | 
|  | bool isAIXABI() const { return TargetTriple.isOSAIX(); } | 
|  | bool isSVR4ABI() const { return !isDarwinABI() && !isAIXABI(); } | 
|  | bool isELFv2ABI() const; | 
|  |  | 
|  | bool is64BitELFABI() const { return  isSVR4ABI() && isPPC64(); } | 
|  | bool is32BitELFABI() const { return  isSVR4ABI() && !isPPC64(); } | 
|  |  | 
|  | /// 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; } | 
|  | }; | 
|  | } // End llvm namespace | 
|  |  | 
|  | #endif |