xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.h (revision 36b606ae6aa4b24061096ba18582e0a08ccd5dba)
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,
64*36b606aeSDimitry Andric   DIR_PWR11,
65480093f4SDimitry Andric   DIR_PWR_FUTURE,
660b57cec5SDimitry Andric   DIR_64
670b57cec5SDimitry Andric };
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric class GlobalValue;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric class PPCSubtarget : public PPCGenSubtargetInfo {
730b57cec5SDimitry Andric public:
740b57cec5SDimitry Andric   enum POPCNTDKind {
750b57cec5SDimitry Andric     POPCNTD_Unavailable,
760b57cec5SDimitry Andric     POPCNTD_Slow,
770b57cec5SDimitry Andric     POPCNTD_Fast
780b57cec5SDimitry Andric   };
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric protected:
810b57cec5SDimitry Andric   /// TargetTriple - What processor and OS we're targeting.
820b57cec5SDimitry Andric   Triple TargetTriple;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   /// stackAlignment - The minimum alignment known to hold of the stack frame on
850b57cec5SDimitry Andric   /// entry to the function and which must be maintained by every function.
868bcb0991SDimitry Andric   Align StackAlignment;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   /// Selected instruction itineraries (one entry per itinerary class.)
890b57cec5SDimitry Andric   InstrItineraryData InstrItins;
900b57cec5SDimitry Andric 
91bdd1243dSDimitry Andric // Bool members corresponding to the SubtargetFeatures defined in tablegen.
92bdd1243dSDimitry Andric #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \
93bdd1243dSDimitry Andric   bool ATTRIBUTE = DEFAULT;
94bdd1243dSDimitry Andric #include "PPCGenSubtargetInfo.inc"
95bdd1243dSDimitry Andric 
960b57cec5SDimitry Andric   /// Which cpu directive was used.
97480093f4SDimitry Andric   unsigned CPUDirective;
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   bool IsPPC64;
1000b57cec5SDimitry Andric   bool IsLittleEndian;
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   POPCNTDKind HasPOPCNTD;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   const PPCTargetMachine &TM;
1050b57cec5SDimitry Andric   PPCFrameLowering FrameLowering;
1060b57cec5SDimitry Andric   PPCInstrInfo InstrInfo;
1070b57cec5SDimitry Andric   PPCTargetLowering TLInfo;
1080b57cec5SDimitry Andric   SelectionDAGTargetInfo TSInfo;
1090b57cec5SDimitry Andric 
110e8d8bef9SDimitry Andric   /// GlobalISel related APIs.
111e8d8bef9SDimitry Andric   std::unique_ptr<CallLowering> CallLoweringInfo;
112e8d8bef9SDimitry Andric   std::unique_ptr<LegalizerInfo> Legalizer;
113e8d8bef9SDimitry Andric   std::unique_ptr<RegisterBankInfo> RegBankInfo;
114e8d8bef9SDimitry Andric   std::unique_ptr<InstructionSelector> InstSelector;
115e8d8bef9SDimitry Andric 
1160b57cec5SDimitry Andric public:
1170b57cec5SDimitry Andric   /// This constructor initializes the data members to match that
1180b57cec5SDimitry Andric   /// of the specified triple.
1190b57cec5SDimitry Andric   ///
120bdd1243dSDimitry Andric   PPCSubtarget(const Triple &TT, const std::string &CPU,
121bdd1243dSDimitry Andric                const std::string &TuneCPU, const std::string &FS,
1220b57cec5SDimitry Andric                const PPCTargetMachine &TM);
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   /// ParseSubtargetFeatures - Parses features string setting specified
1250b57cec5SDimitry Andric   /// subtarget options.  Definition of function is auto generated by tblgen.
126e8d8bef9SDimitry Andric   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   /// getStackAlignment - Returns the minimum alignment known to hold of the
1290b57cec5SDimitry Andric   /// stack frame on entry to the function and which must be maintained by every
1300b57cec5SDimitry Andric   /// function for this subtarget.
1318bcb0991SDimitry Andric   Align getStackAlignment() const { return StackAlignment; }
1320b57cec5SDimitry Andric 
133480093f4SDimitry Andric   /// getCPUDirective - Returns the -m directive specified for the cpu.
1340b57cec5SDimitry Andric   ///
135480093f4SDimitry Andric   unsigned getCPUDirective() const { return CPUDirective; }
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   /// getInstrItins - Return the instruction itineraries based on subtarget
1380b57cec5SDimitry Andric   /// selection.
1390b57cec5SDimitry Andric   const InstrItineraryData *getInstrItineraryData() const override {
1400b57cec5SDimitry Andric     return &InstrItins;
1410b57cec5SDimitry Andric   }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   const PPCFrameLowering *getFrameLowering() const override {
1440b57cec5SDimitry Andric     return &FrameLowering;
1450b57cec5SDimitry Andric   }
1460b57cec5SDimitry Andric   const PPCInstrInfo *getInstrInfo() const override { return &InstrInfo; }
1470b57cec5SDimitry Andric   const PPCTargetLowering *getTargetLowering() const override {
1480b57cec5SDimitry Andric     return &TLInfo;
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric   const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
1510b57cec5SDimitry Andric     return &TSInfo;
1520b57cec5SDimitry Andric   }
1530b57cec5SDimitry Andric   const PPCRegisterInfo *getRegisterInfo() const override {
1540b57cec5SDimitry Andric     return &getInstrInfo()->getRegisterInfo();
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric   const PPCTargetMachine &getTargetMachine() const { return TM; }
1570b57cec5SDimitry Andric 
158bdd1243dSDimitry Andric   /// initializeSubtargetDependencies - Initializes using a CPU, a TuneCPU,  and
159bdd1243dSDimitry Andric   /// feature string so that we can use initializer lists for subtarget
160bdd1243dSDimitry Andric   /// initialization.
161bdd1243dSDimitry Andric   PPCSubtarget &initializeSubtargetDependencies(StringRef CPU,
162bdd1243dSDimitry Andric                                                 StringRef TuneCPU,
163bdd1243dSDimitry Andric                                                 StringRef FS);
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric private:
1660b57cec5SDimitry Andric   void initializeEnvironment();
167bdd1243dSDimitry Andric   void initSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric public:
1700b57cec5SDimitry Andric   /// isPPC64 - Return true if we are generating code for 64-bit pointer mode.
1710b57cec5SDimitry Andric   ///
1720b57cec5SDimitry Andric   bool isPPC64() const;
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   // useSoftFloat - Return true if soft-float option is turned on.
1758bcb0991SDimitry Andric   bool useSoftFloat() const {
1768bcb0991SDimitry Andric     if (isAIXABI() && !HasHardFloat)
1778bcb0991SDimitry Andric       report_fatal_error("soft-float is not yet supported on AIX.");
1788bcb0991SDimitry Andric     return !HasHardFloat;
1798bcb0991SDimitry Andric   }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   // isLittleEndian - True if generating little-endian code
1820b57cec5SDimitry Andric   bool isLittleEndian() const { return IsLittleEndian; }
1830b57cec5SDimitry Andric 
184bdd1243dSDimitry Andric // Getters for SubtargetFeatures defined in tablegen.
185bdd1243dSDimitry Andric #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \
186bdd1243dSDimitry Andric   bool GETTER() const { return ATTRIBUTE; }
187bdd1243dSDimitry Andric #include "PPCGenSubtargetInfo.inc"
1880b57cec5SDimitry Andric 
1898bcb0991SDimitry Andric   Align getPlatformStackAlignment() const {
1908bcb0991SDimitry Andric     return Align(16);
1910b57cec5SDimitry Andric   }
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   unsigned  getRedZoneSize() const {
1945ffd83dbSDimitry Andric     if (isPPC64())
1955ffd83dbSDimitry Andric       // 288 bytes = 18*8 (FPRs) + 18*8 (GPRs, GPR13 reserved)
1965ffd83dbSDimitry Andric       return 288;
1975ffd83dbSDimitry Andric 
1985ffd83dbSDimitry Andric     // AIX PPC32: 220 bytes = 18*8 (FPRs) + 19*4 (GPRs);
1995ffd83dbSDimitry Andric     // PPC32 SVR4ABI has no redzone.
2005ffd83dbSDimitry Andric     return isAIXABI() ? 220 : 0;
2010b57cec5SDimitry Andric   }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   bool needsSwapsForVSXMemOps() const {
2040b57cec5SDimitry Andric     return hasVSX() && isLittleEndian() && !hasP9Vector();
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   POPCNTDKind hasPOPCNTD() const { return HasPOPCNTD; }
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric   const Triple &getTargetTriple() const { return TargetTriple; }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
2120b57cec5SDimitry Andric   bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
2130b57cec5SDimitry Andric   bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   bool isAIXABI() const { return TargetTriple.isOSAIX(); }
2165ffd83dbSDimitry Andric   bool isSVR4ABI() const { return !isAIXABI(); }
2170b57cec5SDimitry Andric   bool isELFv2ABI() const;
2180b57cec5SDimitry Andric 
2198bcb0991SDimitry Andric   bool is64BitELFABI() const { return  isSVR4ABI() && isPPC64(); }
2208bcb0991SDimitry Andric   bool is32BitELFABI() const { return  isSVR4ABI() && !isPPC64(); }
2215ffd83dbSDimitry Andric   bool isUsingPCRelativeCalls() const;
2228bcb0991SDimitry Andric 
2230b57cec5SDimitry Andric   /// Originally, this function return hasISEL(). Now we always enable it,
2240b57cec5SDimitry Andric   /// but may expand the ISEL instruction later.
2250b57cec5SDimitry Andric   bool enableEarlyIfConversion() const override { return true; }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   /// Scheduling customization.
2280b57cec5SDimitry Andric   bool enableMachineScheduler() const override;
2290b57cec5SDimitry Andric   /// Pipeliner customization.
2300b57cec5SDimitry Andric   bool enableMachinePipeliner() const override;
2310b57cec5SDimitry Andric   /// Machine Pipeliner customization
2320b57cec5SDimitry Andric   bool useDFAforSMS() const override;
2330b57cec5SDimitry Andric   /// This overrides the PostRAScheduler bit in the SchedModel for each CPU.
2340b57cec5SDimitry Andric   bool enablePostRAScheduler() const override;
2350b57cec5SDimitry Andric   AntiDepBreakMode getAntiDepBreakMode() const override;
2360b57cec5SDimitry Andric   void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const override;
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   void overrideSchedPolicy(MachineSchedPolicy &Policy,
2390b57cec5SDimitry Andric                            unsigned NumRegionInstrs) const override;
2400b57cec5SDimitry Andric   bool useAA() const override;
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   bool enableSubRegLiveness() const override;
2430b57cec5SDimitry Andric 
24406c3fb27SDimitry Andric   bool enableSpillageCopyElimination() const override { return true; }
24506c3fb27SDimitry Andric 
2468bcb0991SDimitry Andric   /// True if the GV will be accessed via an indirect symbol.
2478bcb0991SDimitry Andric   bool isGVIndirectSymbol(const GlobalValue *GV) const;
2480b57cec5SDimitry Andric 
2490fca6ea1SDimitry Andric   /// Calculates the effective code model for argument GV.
2500fca6ea1SDimitry Andric   CodeModel::Model getCodeModel(const TargetMachine &TM,
2510fca6ea1SDimitry Andric                                 const GlobalValue *GV) const;
2520fca6ea1SDimitry Andric 
253480093f4SDimitry Andric   /// True if the ABI is descriptor based.
254480093f4SDimitry Andric   bool usesFunctionDescriptors() const {
255480093f4SDimitry Andric     // Both 32-bit and 64-bit AIX are descriptor based. For ELF only the 64-bit
256480093f4SDimitry Andric     // v1 ABI uses descriptors.
257480093f4SDimitry Andric     return isAIXABI() || (is64BitELFABI() && !isELFv2ABI());
258480093f4SDimitry Andric   }
259480093f4SDimitry Andric 
260480093f4SDimitry Andric   unsigned descriptorTOCAnchorOffset() const {
261480093f4SDimitry Andric     assert(usesFunctionDescriptors() &&
262480093f4SDimitry Andric            "Should only be called when the target uses descriptors.");
263480093f4SDimitry Andric     return IsPPC64 ? 8 : 4;
264480093f4SDimitry Andric   }
265480093f4SDimitry Andric 
266480093f4SDimitry Andric   unsigned descriptorEnvironmentPointerOffset() const {
267480093f4SDimitry Andric     assert(usesFunctionDescriptors() &&
268480093f4SDimitry Andric            "Should only be called when the target uses descriptors.");
269480093f4SDimitry Andric     return IsPPC64 ? 16 : 8;
270480093f4SDimitry Andric   }
271480093f4SDimitry Andric 
272480093f4SDimitry Andric   MCRegister getEnvironmentPointerRegister() const {
273480093f4SDimitry Andric     assert(usesFunctionDescriptors() &&
274480093f4SDimitry Andric            "Should only be called when the target uses descriptors.");
275480093f4SDimitry Andric      return IsPPC64 ? PPC::X11 : PPC::R11;
276480093f4SDimitry Andric   }
277480093f4SDimitry Andric 
278480093f4SDimitry Andric   MCRegister getTOCPointerRegister() const {
279480093f4SDimitry Andric     assert((is64BitELFABI() || isAIXABI()) &&
280480093f4SDimitry Andric            "Should only be called when the target is a TOC based ABI.");
281480093f4SDimitry Andric     return IsPPC64 ? PPC::X2 : PPC::R2;
282480093f4SDimitry Andric   }
283480093f4SDimitry Andric 
28406c3fb27SDimitry Andric   MCRegister getThreadPointerRegister() const {
28506c3fb27SDimitry Andric     assert((is64BitELFABI() || isAIXABI()) &&
28606c3fb27SDimitry Andric            "Should only be called for targets with a thread pointer register.");
28706c3fb27SDimitry Andric     return IsPPC64 ? PPC::X13 : PPC::R13;
28806c3fb27SDimitry Andric   }
28906c3fb27SDimitry Andric 
290480093f4SDimitry Andric   MCRegister getStackPointerRegister() const {
291480093f4SDimitry Andric     return IsPPC64 ? PPC::X1 : PPC::R1;
292480093f4SDimitry Andric   }
293480093f4SDimitry Andric 
2940b57cec5SDimitry Andric   bool isXRaySupported() const override { return IsPPC64 && IsLittleEndian; }
2955ffd83dbSDimitry Andric 
2965ffd83dbSDimitry Andric   bool isPredictableSelectIsExpensive() const {
2975ffd83dbSDimitry Andric     return PredictableSelectIsExpensive;
2985ffd83dbSDimitry Andric   }
299e8d8bef9SDimitry Andric 
300fe6060f1SDimitry Andric   // Select allocation orders of GPRC and G8RC. It should be strictly consistent
301fe6060f1SDimitry Andric   // with corresponding AltOrders in PPCRegisterInfo.td.
302fe6060f1SDimitry Andric   unsigned getGPRAllocationOrderIdx() const {
303fe6060f1SDimitry Andric     if (is64BitELFABI())
304fe6060f1SDimitry Andric       return 1;
305fe6060f1SDimitry Andric     if (isAIXABI())
306fe6060f1SDimitry Andric       return 2;
307fe6060f1SDimitry Andric     return 0;
308fe6060f1SDimitry Andric   }
309fe6060f1SDimitry Andric 
310e8d8bef9SDimitry Andric   // GlobalISEL
311e8d8bef9SDimitry Andric   const CallLowering *getCallLowering() const override;
312e8d8bef9SDimitry Andric   const RegisterBankInfo *getRegBankInfo() const override;
313e8d8bef9SDimitry Andric   const LegalizerInfo *getLegalizerInfo() const override;
314e8d8bef9SDimitry Andric   InstructionSelector *getInstructionSelector() const override;
3150b57cec5SDimitry Andric };
3160b57cec5SDimitry Andric } // End llvm namespace
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric #endif
319