1234353Sdim//===-- PPCSubtarget.h - Define Subtarget for the PPC ----------*- C++ -*--===//
2193323Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193323Sed//
7193323Sed//===----------------------------------------------------------------------===//
8193323Sed//
9224145Sdim// This file declares the PowerPC specific subclass of TargetSubtargetInfo.
10193323Sed//
11193323Sed//===----------------------------------------------------------------------===//
12193323Sed
13280031Sdim#ifndef LLVM_LIB_TARGET_POWERPC_PPCSUBTARGET_H
14280031Sdim#define LLVM_LIB_TARGET_POWERPC_PPCSUBTARGET_H
15193323Sed
16276479Sdim#include "PPCFrameLowering.h"
17280031Sdim#include "PPCISelLowering.h"
18276479Sdim#include "PPCInstrInfo.h"
19249423Sdim#include "llvm/ADT/Triple.h"
20309124Sdim#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
21327952Sdim#include "llvm/CodeGen/TargetSubtargetInfo.h"
22276479Sdim#include "llvm/IR/DataLayout.h"
23249423Sdim#include "llvm/MC/MCInstrItineraries.h"
24193323Sed#include <string>
25193323Sed
26224145Sdim#define GET_SUBTARGETINFO_HEADER
27224145Sdim#include "PPCGenSubtargetInfo.inc"
28224145Sdim
29193323Sed// GCC #defines PPC on Linux but we use it as our namespace name
30193323Sed#undef PPC
31193323Sed
32193323Sednamespace llvm {
33224145Sdimclass StringRef;
34193323Sed
35193323Sednamespace PPC {
36193323Sed  // -m directive values.
37193323Sed  enum {
38193323Sed    DIR_NONE,
39193323Sed    DIR_32,
40243830Sdim    DIR_440,
41243830Sdim    DIR_601,
42243830Sdim    DIR_602,
43243830Sdim    DIR_603,
44193323Sed    DIR_7400,
45243830Sdim    DIR_750,
46243830Sdim    DIR_970,
47234353Sdim    DIR_A2,
48341825Sdim    DIR_E500,
49243830Sdim    DIR_E500mc,
50243830Sdim    DIR_E5500,
51249423Sdim    DIR_PWR3,
52249423Sdim    DIR_PWR4,
53249423Sdim    DIR_PWR5,
54249423Sdim    DIR_PWR5X,
55239462Sdim    DIR_PWR6,
56249423Sdim    DIR_PWR6X,
57239462Sdim    DIR_PWR7,
58276479Sdim    DIR_PWR8,
59309124Sdim    DIR_PWR9,
60360784Sdim    DIR_PWR_FUTURE,
61243830Sdim    DIR_64
62193323Sed  };
63193323Sed}
64193323Sed
65193323Sedclass GlobalValue;
66193323Sedclass TargetMachine;
67243830Sdim
68224145Sdimclass PPCSubtarget : public PPCGenSubtargetInfo {
69309124Sdimpublic:
70309124Sdim  enum POPCNTDKind {
71309124Sdim    POPCNTD_Unavailable,
72309124Sdim    POPCNTD_Slow,
73309124Sdim    POPCNTD_Fast
74309124Sdim  };
75309124Sdim
76193323Sedprotected:
77280031Sdim  /// TargetTriple - What processor and OS we're targeting.
78280031Sdim  Triple TargetTriple;
79280031Sdim
80193323Sed  /// stackAlignment - The minimum alignment known to hold of the stack frame on
81193323Sed  /// entry to the function and which must be maintained by every function.
82360784Sdim  Align StackAlignment;
83243830Sdim
84193323Sed  /// Selected instruction itineraries (one entry per itinerary class.)
85193323Sed  InstrItineraryData InstrItins;
86243830Sdim
87193323Sed  /// Which cpu directive was used.
88360784Sdim  unsigned CPUDirective;
89193323Sed
90193323Sed  /// Used by the ISel to turn in optimizations for POWER4-derived architectures
91239462Sdim  bool HasMFOCRF;
92193323Sed  bool Has64BitSupport;
93193323Sed  bool Use64BitRegs;
94276479Sdim  bool UseCRBits;
95309149Sdim  bool HasHardFloat;
96193323Sed  bool IsPPC64;
97193323Sed  bool HasAltivec;
98341825Sdim  bool HasFPU;
99280031Sdim  bool HasSPE;
100249423Sdim  bool HasQPX;
101261991Sdim  bool HasVSX;
102353358Sdim  bool NeedsTwoConstNR;
103280031Sdim  bool HasP8Vector;
104288943Sdim  bool HasP8Altivec;
105288943Sdim  bool HasP8Crypto;
106309124Sdim  bool HasP9Vector;
107309124Sdim  bool HasP9Altivec;
108261991Sdim  bool HasFCPSGN;
109193323Sed  bool HasFSQRT;
110249423Sdim  bool HasFRE, HasFRES, HasFRSQRTE, HasFRSQRTES;
111249423Sdim  bool HasRecipPrec;
112193323Sed  bool HasSTFIWX;
113249423Sdim  bool HasLFIWAX;
114249423Sdim  bool HasFPRND;
115249423Sdim  bool HasFPCVT;
116239462Sdim  bool HasISEL;
117288943Sdim  bool HasBPERMD;
118288943Sdim  bool HasExtDiv;
119280031Sdim  bool HasCMPB;
120249423Sdim  bool HasLDBRX;
121234353Sdim  bool IsBookE;
122280031Sdim  bool HasOnlyMSYNC;
123280031Sdim  bool IsE500;
124280031Sdim  bool IsPPC4xx;
125280031Sdim  bool IsPPC6xx;
126288943Sdim  bool FeatureMFTB;
127363496Sdim  bool AllowsUnalignedFPAccess;
128261991Sdim  bool DeprecatedDST;
129193323Sed  bool HasLazyResolverStubs;
130261991Sdim  bool IsLittleEndian;
131288943Sdim  bool HasICBT;
132288943Sdim  bool HasInvariantFunctionDescriptors;
133288943Sdim  bool HasPartwordAtomics;
134288943Sdim  bool HasDirectMove;
135288943Sdim  bool HasHTM;
136296417Sdim  bool HasFloat128;
137309124Sdim  bool IsISA3_0;
138309124Sdim  bool UseLongCalls;
139341825Sdim  bool SecurePlt;
140353358Sdim  bool VectorsUseTwoUnits;
141353358Sdim  bool UsePPCPreRASchedStrategy;
142353358Sdim  bool UsePPCPostRASchedStrategy;
143243830Sdim
144309124Sdim  POPCNTDKind HasPOPCNTD;
145309124Sdim
146288943Sdim  /// When targeting QPX running a stock PPC64 Linux kernel where the stack
147288943Sdim  /// alignment has not been changed, we need to keep the 16-byte alignment
148288943Sdim  /// of the stack.
149288943Sdim  bool IsQPXStackUnaligned;
150221345Sdim
151288943Sdim  const PPCTargetMachine &TM;
152276479Sdim  PPCFrameLowering FrameLowering;
153276479Sdim  PPCInstrInfo InstrInfo;
154276479Sdim  PPCTargetLowering TLInfo;
155309124Sdim  SelectionDAGTargetInfo TSInfo;
156276479Sdim
157193323Sedpublic:
158193323Sed  /// This constructor initializes the data members to match that
159198090Srdivacky  /// of the specified triple.
160193323Sed  ///
161288943Sdim  PPCSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS,
162288943Sdim               const PPCTargetMachine &TM);
163243830Sdim
164243830Sdim  /// ParseSubtargetFeatures - Parses features string setting specified
165193323Sed  /// subtarget options.  Definition of function is auto generated by tblgen.
166224145Sdim  void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
167243830Sdim
168193323Sed  /// getStackAlignment - Returns the minimum alignment known to hold of the
169193323Sed  /// stack frame on entry to the function and which must be maintained by every
170193323Sed  /// function for this subtarget.
171360784Sdim  Align getStackAlignment() const { return StackAlignment; }
172243830Sdim
173193323Sed  /// getDarwinDirective - Returns the -m directive specified for the cpu.
174360784Sdim  unsigned getDarwinDirective() const { return CPUDirective; }
175360784Sdim
176360784Sdim  /// getCPUDirective - Returns the -m directive specified for the cpu.
177193323Sed  ///
178360784Sdim  unsigned getCPUDirective() const { return CPUDirective; }
179243830Sdim
180276479Sdim  /// getInstrItins - Return the instruction itineraries based on subtarget
181193323Sed  /// selection.
182280031Sdim  const InstrItineraryData *getInstrItineraryData() const override {
183280031Sdim    return &InstrItins;
184280031Sdim  }
185193323Sed
186280031Sdim  const PPCFrameLowering *getFrameLowering() const override {
187280031Sdim    return &FrameLowering;
188280031Sdim  }
189280031Sdim  const PPCInstrInfo *getInstrInfo() const override { return &InstrInfo; }
190280031Sdim  const PPCTargetLowering *getTargetLowering() const override {
191280031Sdim    return &TLInfo;
192280031Sdim  }
193309124Sdim  const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
194280031Sdim    return &TSInfo;
195280031Sdim  }
196280031Sdim  const PPCRegisterInfo *getRegisterInfo() const override {
197280031Sdim    return &getInstrInfo()->getRegisterInfo();
198280031Sdim  }
199288943Sdim  const PPCTargetMachine &getTargetMachine() const { return TM; }
200276479Sdim
201276479Sdim  /// initializeSubtargetDependencies - Initializes using a CPU and feature string
202276479Sdim  /// so that we can use initializer lists for subtarget initialization.
203276479Sdim  PPCSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS);
204276479Sdim
205261991Sdimprivate:
206261991Sdim  void initializeEnvironment();
207280031Sdim  void initSubtargetFeatures(StringRef CPU, StringRef FS);
208261991Sdim
209261991Sdimpublic:
210193323Sed  /// isPPC64 - Return true if we are generating code for 64-bit pointer mode.
211193323Sed  ///
212288943Sdim  bool isPPC64() const;
213243830Sdim
214193323Sed  /// has64BitSupport - Return true if the selected CPU supports 64-bit
215193323Sed  /// instructions, regardless of whether we are in 32-bit or 64-bit mode.
216193323Sed  bool has64BitSupport() const { return Has64BitSupport; }
217296417Sdim  // useSoftFloat - Return true if soft-float option is turned on.
218360784Sdim  bool useSoftFloat() const {
219360784Sdim    if (isAIXABI() && !HasHardFloat)
220360784Sdim      report_fatal_error("soft-float is not yet supported on AIX.");
221360784Sdim    return !HasHardFloat;
222360784Sdim  }
223243830Sdim
224193323Sed  /// use64BitRegs - Return true if in 64-bit mode or if we should use 64-bit
225193323Sed  /// registers in 32-bit mode when possible.  This can only true if
226193323Sed  /// has64BitSupport() returns true.
227193323Sed  bool use64BitRegs() const { return Use64BitRegs; }
228243830Sdim
229276479Sdim  /// useCRBits - Return true if we should store and manipulate i1 values in
230276479Sdim  /// the individual condition register bits.
231276479Sdim  bool useCRBits() const { return UseCRBits; }
232276479Sdim
233193323Sed  /// hasLazyResolverStub - Return true if accesses to the specified global have
234193323Sed  /// to go through a dyld lazy resolution stub.  This means that an extra load
235193323Sed  /// is required to get the address of the global.
236288943Sdim  bool hasLazyResolverStub(const GlobalValue *GV) const;
237243830Sdim
238261991Sdim  // isLittleEndian - True if generating little-endian code
239261991Sdim  bool isLittleEndian() const { return IsLittleEndian; }
240261991Sdim
241193323Sed  // Specific obvious features.
242261991Sdim  bool hasFCPSGN() const { return HasFCPSGN; }
243193323Sed  bool hasFSQRT() const { return HasFSQRT; }
244249423Sdim  bool hasFRE() const { return HasFRE; }
245249423Sdim  bool hasFRES() const { return HasFRES; }
246249423Sdim  bool hasFRSQRTE() const { return HasFRSQRTE; }
247249423Sdim  bool hasFRSQRTES() const { return HasFRSQRTES; }
248249423Sdim  bool hasRecipPrec() const { return HasRecipPrec; }
249193323Sed  bool hasSTFIWX() const { return HasSTFIWX; }
250249423Sdim  bool hasLFIWAX() const { return HasLFIWAX; }
251249423Sdim  bool hasFPRND() const { return HasFPRND; }
252249423Sdim  bool hasFPCVT() const { return HasFPCVT; }
253193323Sed  bool hasAltivec() const { return HasAltivec; }
254280031Sdim  bool hasSPE() const { return HasSPE; }
255341825Sdim  bool hasFPU() const { return HasFPU; }
256249423Sdim  bool hasQPX() const { return HasQPX; }
257276479Sdim  bool hasVSX() const { return HasVSX; }
258353358Sdim  bool needsTwoConstNR() const { return NeedsTwoConstNR; }
259280031Sdim  bool hasP8Vector() const { return HasP8Vector; }
260288943Sdim  bool hasP8Altivec() const { return HasP8Altivec; }
261288943Sdim  bool hasP8Crypto() const { return HasP8Crypto; }
262309124Sdim  bool hasP9Vector() const { return HasP9Vector; }
263309124Sdim  bool hasP9Altivec() const { return HasP9Altivec; }
264239462Sdim  bool hasMFOCRF() const { return HasMFOCRF; }
265239462Sdim  bool hasISEL() const { return HasISEL; }
266288943Sdim  bool hasBPERMD() const { return HasBPERMD; }
267288943Sdim  bool hasExtDiv() const { return HasExtDiv; }
268280031Sdim  bool hasCMPB() const { return HasCMPB; }
269249423Sdim  bool hasLDBRX() const { return HasLDBRX; }
270234353Sdim  bool isBookE() const { return IsBookE; }
271280031Sdim  bool hasOnlyMSYNC() const { return HasOnlyMSYNC; }
272280031Sdim  bool isPPC4xx() const { return IsPPC4xx; }
273280031Sdim  bool isPPC6xx() const { return IsPPC6xx; }
274341825Sdim  bool isSecurePlt() const {return SecurePlt; }
275353358Sdim  bool vectorsUseTwoUnits() const {return VectorsUseTwoUnits; }
276280031Sdim  bool isE500() const { return IsE500; }
277288943Sdim  bool isFeatureMFTB() const { return FeatureMFTB; }
278363496Sdim  bool allowsUnalignedFPAccess() const { return AllowsUnalignedFPAccess; }
279261991Sdim  bool isDeprecatedDST() const { return DeprecatedDST; }
280288943Sdim  bool hasICBT() const { return HasICBT; }
281288943Sdim  bool hasInvariantFunctionDescriptors() const {
282288943Sdim    return HasInvariantFunctionDescriptors;
283288943Sdim  }
284353358Sdim  bool usePPCPreRASchedStrategy() const { return UsePPCPreRASchedStrategy; }
285353358Sdim  bool usePPCPostRASchedStrategy() const { return UsePPCPostRASchedStrategy; }
286288943Sdim  bool hasPartwordAtomics() const { return HasPartwordAtomics; }
287288943Sdim  bool hasDirectMove() const { return HasDirectMove; }
288193323Sed
289288943Sdim  bool isQPXStackUnaligned() const { return IsQPXStackUnaligned; }
290360784Sdim  Align getPlatformStackAlignment() const {
291288943Sdim    if ((hasQPX() || isBGQ()) && !isQPXStackUnaligned())
292360784Sdim      return Align(32);
293288943Sdim
294360784Sdim    return Align(16);
295288943Sdim  }
296321369Sdim
297321369Sdim  // DarwinABI has a 224-byte red zone. PPC32 SVR4ABI(Non-DarwinABI) has no
298321369Sdim  // red zone and PPC64 SVR4ABI has a 288-byte red zone.
299321369Sdim  unsigned  getRedZoneSize() const {
300321369Sdim    return isDarwinABI() ? 224 : (isPPC64() ? 288 : 0);
301321369Sdim  }
302321369Sdim
303288943Sdim  bool hasHTM() const { return HasHTM; }
304296417Sdim  bool hasFloat128() const { return HasFloat128; }
305309124Sdim  bool isISA3_0() const { return IsISA3_0; }
306309124Sdim  bool useLongCalls() const { return UseLongCalls; }
307314564Sdim  bool needsSwapsForVSXMemOps() const {
308314564Sdim    return hasVSX() && isLittleEndian() && !hasP9Vector();
309314564Sdim  }
310288943Sdim
311309124Sdim  POPCNTDKind hasPOPCNTD() const { return HasPOPCNTD; }
312309124Sdim
313221345Sdim  const Triple &getTargetTriple() const { return TargetTriple; }
314221345Sdim
315193323Sed  /// isDarwin - True if this is any darwin platform.
316221345Sdim  bool isDarwin() const { return TargetTriple.isMacOSX(); }
317249423Sdim  /// isBGQ - True if this is a BG/Q platform.
318249423Sdim  bool isBGQ() const { return TargetTriple.getVendor() == Triple::BGQ; }
319193323Sed
320270147Srdivacky  bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
321276479Sdim  bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
322309124Sdim  bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
323270147Srdivacky
324288943Sdim  bool isDarwinABI() const { return isTargetMachO() || isDarwin(); }
325353358Sdim  bool isAIXABI() const { return TargetTriple.isOSAIX(); }
326353358Sdim  bool isSVR4ABI() const { return !isDarwinABI() && !isAIXABI(); }
327288943Sdim  bool isELFv2ABI() const;
328193323Sed
329360784Sdim  bool is64BitELFABI() const { return  isSVR4ABI() && isPPC64(); }
330360784Sdim  bool is32BitELFABI() const { return  isSVR4ABI() && !isPPC64(); }
331360784Sdim
332321369Sdim  /// Originally, this function return hasISEL(). Now we always enable it,
333321369Sdim  /// but may expand the ISEL instruction later.
334321369Sdim  bool enableEarlyIfConversion() const override { return true; }
335261991Sdim
336353358Sdim  /// Scheduling customization.
337276479Sdim  bool enableMachineScheduler() const override;
338353358Sdim  /// Pipeliner customization.
339353358Sdim  bool enableMachinePipeliner() const override;
340353358Sdim  /// Machine Pipeliner customization
341353358Sdim  bool useDFAforSMS() const override;
342353358Sdim  /// This overrides the PostRAScheduler bit in the SchedModel for each CPU.
343288943Sdim  bool enablePostRAScheduler() const override;
344276479Sdim  AntiDepBreakMode getAntiDepBreakMode() const override;
345276479Sdim  void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const override;
346276479Sdim
347261991Sdim  void overrideSchedPolicy(MachineSchedPolicy &Policy,
348276479Sdim                           unsigned NumRegionInstrs) const override;
349276479Sdim  bool useAA() const override;
350280031Sdim
351280031Sdim  bool enableSubRegLiveness() const override;
352296417Sdim
353360784Sdim  /// True if the GV will be accessed via an indirect symbol.
354360784Sdim  bool isGVIndirectSymbol(const GlobalValue *GV) const;
355321369Sdim
356360784Sdim  /// True if the ABI is descriptor based.
357360784Sdim  bool usesFunctionDescriptors() const {
358360784Sdim    // Both 32-bit and 64-bit AIX are descriptor based. For ELF only the 64-bit
359360784Sdim    // v1 ABI uses descriptors.
360360784Sdim    return isAIXABI() || (is64BitELFABI() && !isELFv2ABI());
361360784Sdim  }
362360784Sdim
363360784Sdim  unsigned descriptorTOCAnchorOffset() const {
364360784Sdim    assert(usesFunctionDescriptors() &&
365360784Sdim           "Should only be called when the target uses descriptors.");
366360784Sdim    return IsPPC64 ? 8 : 4;
367360784Sdim  }
368360784Sdim
369360784Sdim  unsigned descriptorEnvironmentPointerOffset() const {
370360784Sdim    assert(usesFunctionDescriptors() &&
371360784Sdim           "Should only be called when the target uses descriptors.");
372360784Sdim    return IsPPC64 ? 16 : 8;
373360784Sdim  }
374360784Sdim
375360784Sdim  MCRegister getEnvironmentPointerRegister() const {
376360784Sdim    assert(usesFunctionDescriptors() &&
377360784Sdim           "Should only be called when the target uses descriptors.");
378360784Sdim     return IsPPC64 ? PPC::X11 : PPC::R11;
379360784Sdim  }
380360784Sdim
381360784Sdim  MCRegister getTOCPointerRegister() const {
382360784Sdim    assert((is64BitELFABI() || isAIXABI()) &&
383360784Sdim           "Should only be called when the target is a TOC based ABI.");
384360784Sdim    return IsPPC64 ? PPC::X2 : PPC::R2;
385360784Sdim  }
386360784Sdim
387360784Sdim  MCRegister getStackPointerRegister() const {
388360784Sdim    return IsPPC64 ? PPC::X1 : PPC::R1;
389360784Sdim  }
390360784Sdim
391321369Sdim  bool isXRaySupported() const override { return IsPPC64 && IsLittleEndian; }
392193323Sed};
393193323Sed} // End llvm namespace
394193323Sed
395193323Sed#endif
396