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