10b57cec5SDimitry Andric //===-- PPCSubtarget.h - Define Subtarget for the PPC ----------*- C++ -*--===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file declares the PowerPC specific subclass of TargetSubtargetInfo. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_POWERPC_PPCSUBTARGET_H 140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_POWERPC_PPCSUBTARGET_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "PPCFrameLowering.h" 170b57cec5SDimitry Andric #include "PPCISelLowering.h" 180b57cec5SDimitry Andric #include "PPCInstrInfo.h" 19e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/CallLowering.h" 20e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" 2181ad6265SDimitry Andric #include "llvm/CodeGen/RegisterBankInfo.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGTargetInfo.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 240b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCInstrItineraries.h" 2606c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 270b57cec5SDimitry Andric #include <string> 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric #define GET_SUBTARGETINFO_HEADER 300b57cec5SDimitry Andric #include "PPCGenSubtargetInfo.inc" 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric // GCC #defines PPC on Linux but we use it as our namespace name 330b57cec5SDimitry Andric #undef PPC 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric namespace llvm { 360b57cec5SDimitry Andric class StringRef; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric namespace PPC { 390b57cec5SDimitry Andric // -m directive values. 400b57cec5SDimitry Andric enum { 410b57cec5SDimitry Andric DIR_NONE, 420b57cec5SDimitry Andric DIR_32, 430b57cec5SDimitry Andric DIR_440, 440b57cec5SDimitry Andric DIR_601, 450b57cec5SDimitry Andric DIR_602, 460b57cec5SDimitry Andric DIR_603, 470b57cec5SDimitry Andric DIR_7400, 480b57cec5SDimitry Andric DIR_750, 490b57cec5SDimitry Andric DIR_970, 500b57cec5SDimitry Andric DIR_A2, 510b57cec5SDimitry Andric DIR_E500, 520b57cec5SDimitry Andric DIR_E500mc, 530b57cec5SDimitry Andric DIR_E5500, 540b57cec5SDimitry Andric DIR_PWR3, 550b57cec5SDimitry Andric DIR_PWR4, 560b57cec5SDimitry Andric DIR_PWR5, 570b57cec5SDimitry Andric DIR_PWR5X, 580b57cec5SDimitry Andric DIR_PWR6, 590b57cec5SDimitry Andric DIR_PWR6X, 600b57cec5SDimitry Andric DIR_PWR7, 610b57cec5SDimitry Andric DIR_PWR8, 620b57cec5SDimitry Andric DIR_PWR9, 635ffd83dbSDimitry Andric DIR_PWR10, 64480093f4SDimitry Andric DIR_PWR_FUTURE, 650b57cec5SDimitry Andric DIR_64 660b57cec5SDimitry Andric }; 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric class GlobalValue; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric class PPCSubtarget : public PPCGenSubtargetInfo { 720b57cec5SDimitry Andric public: 730b57cec5SDimitry Andric enum POPCNTDKind { 740b57cec5SDimitry Andric POPCNTD_Unavailable, 750b57cec5SDimitry Andric POPCNTD_Slow, 760b57cec5SDimitry Andric POPCNTD_Fast 770b57cec5SDimitry Andric }; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric protected: 800b57cec5SDimitry Andric /// TargetTriple - What processor and OS we're targeting. 810b57cec5SDimitry Andric Triple TargetTriple; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric /// stackAlignment - The minimum alignment known to hold of the stack frame on 840b57cec5SDimitry Andric /// entry to the function and which must be maintained by every function. 858bcb0991SDimitry Andric Align StackAlignment; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric /// Selected instruction itineraries (one entry per itinerary class.) 880b57cec5SDimitry Andric InstrItineraryData InstrItins; 890b57cec5SDimitry Andric 90bdd1243dSDimitry Andric // Bool members corresponding to the SubtargetFeatures defined in tablegen. 91bdd1243dSDimitry Andric #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ 92bdd1243dSDimitry Andric bool ATTRIBUTE = DEFAULT; 93bdd1243dSDimitry Andric #include "PPCGenSubtargetInfo.inc" 94bdd1243dSDimitry Andric 950b57cec5SDimitry Andric /// Which cpu directive was used. 96480093f4SDimitry Andric unsigned CPUDirective; 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric bool IsPPC64; 990b57cec5SDimitry Andric bool IsLittleEndian; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric POPCNTDKind HasPOPCNTD; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric const PPCTargetMachine &TM; 1040b57cec5SDimitry Andric PPCFrameLowering FrameLowering; 1050b57cec5SDimitry Andric PPCInstrInfo InstrInfo; 1060b57cec5SDimitry Andric PPCTargetLowering TLInfo; 1070b57cec5SDimitry Andric SelectionDAGTargetInfo TSInfo; 1080b57cec5SDimitry Andric 109e8d8bef9SDimitry Andric /// GlobalISel related APIs. 110e8d8bef9SDimitry Andric std::unique_ptr<CallLowering> CallLoweringInfo; 111e8d8bef9SDimitry Andric std::unique_ptr<LegalizerInfo> Legalizer; 112e8d8bef9SDimitry Andric std::unique_ptr<RegisterBankInfo> RegBankInfo; 113e8d8bef9SDimitry Andric std::unique_ptr<InstructionSelector> InstSelector; 114e8d8bef9SDimitry Andric 1150b57cec5SDimitry Andric public: 1160b57cec5SDimitry Andric /// This constructor initializes the data members to match that 1170b57cec5SDimitry Andric /// of the specified triple. 1180b57cec5SDimitry Andric /// 119bdd1243dSDimitry Andric PPCSubtarget(const Triple &TT, const std::string &CPU, 120bdd1243dSDimitry Andric const std::string &TuneCPU, const std::string &FS, 1210b57cec5SDimitry Andric const PPCTargetMachine &TM); 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric /// ParseSubtargetFeatures - Parses features string setting specified 1240b57cec5SDimitry Andric /// subtarget options. Definition of function is auto generated by tblgen. 125e8d8bef9SDimitry Andric void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric /// getStackAlignment - Returns the minimum alignment known to hold of the 1280b57cec5SDimitry Andric /// stack frame on entry to the function and which must be maintained by every 1290b57cec5SDimitry Andric /// function for this subtarget. getStackAlignment()1308bcb0991SDimitry Andric Align getStackAlignment() const { return StackAlignment; } 1310b57cec5SDimitry Andric 132480093f4SDimitry Andric /// getCPUDirective - Returns the -m directive specified for the cpu. 1330b57cec5SDimitry Andric /// getCPUDirective()134480093f4SDimitry Andric unsigned getCPUDirective() const { return CPUDirective; } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric /// getInstrItins - Return the instruction itineraries based on subtarget 1370b57cec5SDimitry Andric /// selection. getInstrItineraryData()1380b57cec5SDimitry Andric const InstrItineraryData *getInstrItineraryData() const override { 1390b57cec5SDimitry Andric return &InstrItins; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric getFrameLowering()1420b57cec5SDimitry Andric const PPCFrameLowering *getFrameLowering() const override { 1430b57cec5SDimitry Andric return &FrameLowering; 1440b57cec5SDimitry Andric } getInstrInfo()1450b57cec5SDimitry Andric const PPCInstrInfo *getInstrInfo() const override { return &InstrInfo; } getTargetLowering()1460b57cec5SDimitry Andric const PPCTargetLowering *getTargetLowering() const override { 1470b57cec5SDimitry Andric return &TLInfo; 1480b57cec5SDimitry Andric } getSelectionDAGInfo()1490b57cec5SDimitry Andric const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { 1500b57cec5SDimitry Andric return &TSInfo; 1510b57cec5SDimitry Andric } getRegisterInfo()1520b57cec5SDimitry Andric const PPCRegisterInfo *getRegisterInfo() const override { 1530b57cec5SDimitry Andric return &getInstrInfo()->getRegisterInfo(); 1540b57cec5SDimitry Andric } getTargetMachine()1550b57cec5SDimitry Andric const PPCTargetMachine &getTargetMachine() const { return TM; } 1560b57cec5SDimitry Andric 157bdd1243dSDimitry Andric /// initializeSubtargetDependencies - Initializes using a CPU, a TuneCPU, and 158bdd1243dSDimitry Andric /// feature string so that we can use initializer lists for subtarget 159bdd1243dSDimitry Andric /// initialization. 160bdd1243dSDimitry Andric PPCSubtarget &initializeSubtargetDependencies(StringRef CPU, 161bdd1243dSDimitry Andric StringRef TuneCPU, 162bdd1243dSDimitry Andric StringRef FS); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric private: 1650b57cec5SDimitry Andric void initializeEnvironment(); 166bdd1243dSDimitry Andric void initSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric public: 1690b57cec5SDimitry Andric /// isPPC64 - Return true if we are generating code for 64-bit pointer mode. 1700b57cec5SDimitry Andric /// 1710b57cec5SDimitry Andric bool isPPC64() const; 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric // useSoftFloat - Return true if soft-float option is turned on. useSoftFloat()1748bcb0991SDimitry Andric bool useSoftFloat() const { 1758bcb0991SDimitry Andric if (isAIXABI() && !HasHardFloat) 1768bcb0991SDimitry Andric report_fatal_error("soft-float is not yet supported on AIX."); 1778bcb0991SDimitry Andric return !HasHardFloat; 1788bcb0991SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // isLittleEndian - True if generating little-endian code isLittleEndian()1810b57cec5SDimitry Andric bool isLittleEndian() const { return IsLittleEndian; } 1820b57cec5SDimitry Andric 183bdd1243dSDimitry Andric // Getters for SubtargetFeatures defined in tablegen. 184bdd1243dSDimitry Andric #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ 185bdd1243dSDimitry Andric bool GETTER() const { return ATTRIBUTE; } 186bdd1243dSDimitry Andric #include "PPCGenSubtargetInfo.inc" 1870b57cec5SDimitry Andric getPlatformStackAlignment()1888bcb0991SDimitry Andric Align getPlatformStackAlignment() const { 1898bcb0991SDimitry Andric return Align(16); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric getRedZoneSize()1920b57cec5SDimitry Andric unsigned getRedZoneSize() const { 1935ffd83dbSDimitry Andric if (isPPC64()) 1945ffd83dbSDimitry Andric // 288 bytes = 18*8 (FPRs) + 18*8 (GPRs, GPR13 reserved) 1955ffd83dbSDimitry Andric return 288; 1965ffd83dbSDimitry Andric 1975ffd83dbSDimitry Andric // AIX PPC32: 220 bytes = 18*8 (FPRs) + 19*4 (GPRs); 1985ffd83dbSDimitry Andric // PPC32 SVR4ABI has no redzone. 1995ffd83dbSDimitry Andric return isAIXABI() ? 220 : 0; 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric needsSwapsForVSXMemOps()2020b57cec5SDimitry Andric bool needsSwapsForVSXMemOps() const { 2030b57cec5SDimitry Andric return hasVSX() && isLittleEndian() && !hasP9Vector(); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric hasPOPCNTD()2060b57cec5SDimitry Andric POPCNTDKind hasPOPCNTD() const { return HasPOPCNTD; } 2070b57cec5SDimitry Andric getTargetTriple()2080b57cec5SDimitry Andric const Triple &getTargetTriple() const { return TargetTriple; } 2090b57cec5SDimitry Andric isTargetELF()2100b57cec5SDimitry Andric bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } isTargetMachO()2110b57cec5SDimitry Andric bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); } isTargetLinux()2120b57cec5SDimitry Andric bool isTargetLinux() const { return TargetTriple.isOSLinux(); } 2130b57cec5SDimitry Andric isAIXABI()2140b57cec5SDimitry Andric bool isAIXABI() const { return TargetTriple.isOSAIX(); } isSVR4ABI()2155ffd83dbSDimitry Andric bool isSVR4ABI() const { return !isAIXABI(); } 2160b57cec5SDimitry Andric bool isELFv2ABI() const; 2170b57cec5SDimitry Andric is64BitELFABI()2188bcb0991SDimitry Andric bool is64BitELFABI() const { return isSVR4ABI() && isPPC64(); } is32BitELFABI()2198bcb0991SDimitry Andric bool is32BitELFABI() const { return isSVR4ABI() && !isPPC64(); } 2205ffd83dbSDimitry Andric bool isUsingPCRelativeCalls() const; 2218bcb0991SDimitry Andric 2220b57cec5SDimitry Andric /// Originally, this function return hasISEL(). Now we always enable it, 2230b57cec5SDimitry Andric /// but may expand the ISEL instruction later. enableEarlyIfConversion()2240b57cec5SDimitry Andric bool enableEarlyIfConversion() const override { return true; } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric /// Scheduling customization. 2270b57cec5SDimitry Andric bool enableMachineScheduler() const override; 2280b57cec5SDimitry Andric /// Pipeliner customization. 2290b57cec5SDimitry Andric bool enableMachinePipeliner() const override; 2300b57cec5SDimitry Andric /// Machine Pipeliner customization 2310b57cec5SDimitry Andric bool useDFAforSMS() const override; 2320b57cec5SDimitry Andric /// This overrides the PostRAScheduler bit in the SchedModel for each CPU. 2330b57cec5SDimitry Andric bool enablePostRAScheduler() const override; 2340b57cec5SDimitry Andric AntiDepBreakMode getAntiDepBreakMode() const override; 2350b57cec5SDimitry Andric void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const override; 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric void overrideSchedPolicy(MachineSchedPolicy &Policy, 2380b57cec5SDimitry Andric unsigned NumRegionInstrs) const override; 2390b57cec5SDimitry Andric bool useAA() const override; 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric bool enableSubRegLiveness() const override; 2420b57cec5SDimitry Andric enableSpillageCopyElimination()24306c3fb27SDimitry Andric bool enableSpillageCopyElimination() const override { return true; } 24406c3fb27SDimitry Andric 2458bcb0991SDimitry Andric /// True if the GV will be accessed via an indirect symbol. 2468bcb0991SDimitry Andric bool isGVIndirectSymbol(const GlobalValue *GV) const; 2470b57cec5SDimitry Andric 248480093f4SDimitry Andric /// True if the ABI is descriptor based. usesFunctionDescriptors()249480093f4SDimitry Andric bool usesFunctionDescriptors() const { 250480093f4SDimitry Andric // Both 32-bit and 64-bit AIX are descriptor based. For ELF only the 64-bit 251480093f4SDimitry Andric // v1 ABI uses descriptors. 252480093f4SDimitry Andric return isAIXABI() || (is64BitELFABI() && !isELFv2ABI()); 253480093f4SDimitry Andric } 254480093f4SDimitry Andric descriptorTOCAnchorOffset()255480093f4SDimitry Andric unsigned descriptorTOCAnchorOffset() const { 256480093f4SDimitry Andric assert(usesFunctionDescriptors() && 257480093f4SDimitry Andric "Should only be called when the target uses descriptors."); 258480093f4SDimitry Andric return IsPPC64 ? 8 : 4; 259480093f4SDimitry Andric } 260480093f4SDimitry Andric descriptorEnvironmentPointerOffset()261480093f4SDimitry Andric unsigned descriptorEnvironmentPointerOffset() const { 262480093f4SDimitry Andric assert(usesFunctionDescriptors() && 263480093f4SDimitry Andric "Should only be called when the target uses descriptors."); 264480093f4SDimitry Andric return IsPPC64 ? 16 : 8; 265480093f4SDimitry Andric } 266480093f4SDimitry Andric getEnvironmentPointerRegister()267480093f4SDimitry Andric MCRegister getEnvironmentPointerRegister() const { 268480093f4SDimitry Andric assert(usesFunctionDescriptors() && 269480093f4SDimitry Andric "Should only be called when the target uses descriptors."); 270480093f4SDimitry Andric return IsPPC64 ? PPC::X11 : PPC::R11; 271480093f4SDimitry Andric } 272480093f4SDimitry Andric getTOCPointerRegister()273480093f4SDimitry Andric MCRegister getTOCPointerRegister() const { 274480093f4SDimitry Andric assert((is64BitELFABI() || isAIXABI()) && 275480093f4SDimitry Andric "Should only be called when the target is a TOC based ABI."); 276480093f4SDimitry Andric return IsPPC64 ? PPC::X2 : PPC::R2; 277480093f4SDimitry Andric } 278480093f4SDimitry Andric getThreadPointerRegister()27906c3fb27SDimitry Andric MCRegister getThreadPointerRegister() const { 28006c3fb27SDimitry Andric assert((is64BitELFABI() || isAIXABI()) && 28106c3fb27SDimitry Andric "Should only be called for targets with a thread pointer register."); 28206c3fb27SDimitry Andric return IsPPC64 ? PPC::X13 : PPC::R13; 28306c3fb27SDimitry Andric } 28406c3fb27SDimitry Andric getStackPointerRegister()285480093f4SDimitry Andric MCRegister getStackPointerRegister() const { 286480093f4SDimitry Andric return IsPPC64 ? PPC::X1 : PPC::R1; 287480093f4SDimitry Andric } 288480093f4SDimitry Andric isXRaySupported()2890b57cec5SDimitry Andric bool isXRaySupported() const override { return IsPPC64 && IsLittleEndian; } 2905ffd83dbSDimitry Andric isPredictableSelectIsExpensive()2915ffd83dbSDimitry Andric bool isPredictableSelectIsExpensive() const { 2925ffd83dbSDimitry Andric return PredictableSelectIsExpensive; 2935ffd83dbSDimitry Andric } 294e8d8bef9SDimitry Andric 295fe6060f1SDimitry Andric // Select allocation orders of GPRC and G8RC. It should be strictly consistent 296fe6060f1SDimitry Andric // with corresponding AltOrders in PPCRegisterInfo.td. getGPRAllocationOrderIdx()297fe6060f1SDimitry Andric unsigned getGPRAllocationOrderIdx() const { 298fe6060f1SDimitry Andric if (is64BitELFABI()) 299fe6060f1SDimitry Andric return 1; 300fe6060f1SDimitry Andric if (isAIXABI()) 301fe6060f1SDimitry Andric return 2; 302fe6060f1SDimitry Andric return 0; 303fe6060f1SDimitry Andric } 304fe6060f1SDimitry Andric 305e8d8bef9SDimitry Andric // GlobalISEL 306e8d8bef9SDimitry Andric const CallLowering *getCallLowering() const override; 307e8d8bef9SDimitry Andric const RegisterBankInfo *getRegBankInfo() const override; 308e8d8bef9SDimitry Andric const LegalizerInfo *getLegalizerInfo() const override; 309e8d8bef9SDimitry Andric InstructionSelector *getInstructionSelector() const override; 3100b57cec5SDimitry Andric }; 3110b57cec5SDimitry Andric } // End llvm namespace 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric #endif 314