//===-- 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/CodeGen/GlobalISel/CallLowering.h" #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" #include "llvm/CodeGen/RegisterBankInfo.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/MC/MCInstrItineraries.h" #include "llvm/TargetParser/Triple.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; // Bool members corresponding to the SubtargetFeatures defined in tablegen. #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ bool ATTRIBUTE = DEFAULT; #include "PPCGenSubtargetInfo.inc" /// Which cpu directive was used. unsigned CPUDirective; bool IsPPC64; bool IsLittleEndian; 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 &TuneCPU, 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, a TuneCPU, and /// feature string so that we can use initializer lists for subtarget /// initialization. PPCSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef TuneCPU, StringRef FS); private: void initializeEnvironment(); void initSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); public: /// isPPC64 - Return true if we are generating code for 64-bit pointer mode. /// bool isPPC64() const; // 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; } // isLittleEndian - True if generating little-endian code bool isLittleEndian() const { return IsLittleEndian; } // Getters for SubtargetFeatures defined in tablegen. #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ bool GETTER() const { return ATTRIBUTE; } #include "PPCGenSubtargetInfo.inc" 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 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; bool enableSpillageCopyElimination() const override { return true; } /// 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 getThreadPointerRegister() const { assert((is64BitELFABI() || isAIXABI()) && "Should only be called for targets with a thread pointer register."); return IsPPC64 ? PPC::X13 : PPC::R13; } 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