aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm14/lib/Target/PowerPC/PPCSubtarget.h
blob: 1300b62b623a2dd4a55fda74c21673a5e0bae357 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
//===-- 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/ADT/Triple.h"
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCInstrItineraries.h"
#include <string>

#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;

  /// Which cpu directive was used.
  unsigned CPUDirective;

  /// Used by the ISel to turn in optimizations for POWER4-derived architectures
  bool HasMFOCRF;
  bool Has64BitSupport;
  bool Use64BitRegs;
  bool UseCRBits;
  bool HasHardFloat;
  bool IsPPC64;
  bool HasAltivec;
  bool HasFPU;
  bool HasSPE;
  bool HasEFPU2;
  bool HasVSX;
  bool NeedsTwoConstNR;
  bool HasP8Vector;
  bool HasP8Altivec;
  bool HasP8Crypto;
  bool HasP9Vector;
  bool HasP9Altivec;
  bool HasP10Vector;
  bool HasPrefixInstrs;
  bool HasPCRelativeMemops;
  bool HasMMA;
  bool HasROPProtect;
  bool HasPrivileged;
  bool HasFCPSGN;
  bool HasFSQRT;
  bool HasFRE, HasFRES, HasFRSQRTE, HasFRSQRTES;
  bool HasRecipPrec;
  bool HasSTFIWX;
  bool HasLFIWAX;
  bool HasFPRND;
  bool HasFPCVT;
  bool HasISEL;
  bool HasBPERMD;
  bool HasExtDiv;
  bool HasCMPB;
  bool HasLDBRX;
  bool IsBookE;
  bool HasOnlyMSYNC;
  bool IsE500;
  bool IsPPC4xx;
  bool IsPPC6xx;
  bool FeatureMFTB;
  bool AllowsUnalignedFPAccess;
  bool DeprecatedDST;
  bool IsLittleEndian;
  bool HasICBT;
  bool HasInvariantFunctionDescriptors;
  bool HasPartwordAtomics;
  bool HasQuadwordAtomics;
  bool HasDirectMove;
  bool HasHTM;
  bool HasFloat128;
  bool HasFusion;
  bool HasStoreFusion;
  bool HasAddiLoadFusion;
  bool HasAddisLoadFusion;
  bool HasArithAddFusion;
  bool HasAddLogicalFusion;
  bool HasLogicalAddFusion;
  bool HasLogicalFusion;
  bool HasSha3Fusion;
  bool HasCompareFusion;
  bool HasWideImmFusion;
  bool HasZeroMoveFusion;
  bool HasBack2BackFusion;
  bool IsISA2_06;
  bool IsISA2_07;
  bool IsISA3_0;
  bool IsISA3_1;
  bool UseLongCalls;
  bool SecurePlt;
  bool VectorsUseTwoUnits;
  bool UsePPCPreRASchedStrategy;
  bool UsePPCPostRASchedStrategy;
  bool PairedVectorMemops;
  bool PredictableSelectIsExpensive;
  bool HasModernAIXAs;
  bool IsAIX;

  POPCNTDKind HasPOPCNTD;

  const PPCTargetMachine &TM;
  PPCFrameLowering FrameLowering;
  PPCInstrInfo InstrInfo;
  PPCTargetLowering TLInfo;
  SelectionDAGTargetInfo TSInfo;

  /// GlobalISel related APIs.
  std::unique_ptr<CallLowering> CallLoweringInfo;
  std::unique_ptr<LegalizerInfo> Legalizer;
  std::unique_ptr<RegisterBankInfo> RegBankInfo;
  std::unique_ptr<InstructionSelector> 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 &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 and feature string
  /// so that we can use initializer lists for subtarget initialization.
  PPCSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS);

private:
  void initializeEnvironment();
  void initSubtargetFeatures(StringRef CPU, StringRef FS);

public:
  /// isPPC64 - Return true if we are generating code for 64-bit pointer mode.
  ///
  bool isPPC64() const;

  /// has64BitSupport - Return true if the selected CPU supports 64-bit
  /// instructions, regardless of whether we are in 32-bit or 64-bit mode.
  bool has64BitSupport() const { return Has64BitSupport; }
  // 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;
  }

  /// use64BitRegs - Return true if in 64-bit mode or if we should use 64-bit
  /// registers in 32-bit mode when possible.  This can only true if
  /// has64BitSupport() returns true.
  bool use64BitRegs() const { return Use64BitRegs; }

  /// useCRBits - Return true if we should store and manipulate i1 values in
  /// the individual condition register bits.
  bool useCRBits() const { return UseCRBits; }

  // isLittleEndian - True if generating little-endian code
  bool isLittleEndian() const { return IsLittleEndian; }

  // Specific obvious features.
  bool hasFCPSGN() const { return HasFCPSGN; }
  bool hasFSQRT() const { return HasFSQRT; }
  bool hasFRE() const { return HasFRE; }
  bool hasFRES() const { return HasFRES; }
  bool hasFRSQRTE() const { return HasFRSQRTE; }
  bool hasFRSQRTES() const { return HasFRSQRTES; }
  bool hasRecipPrec() const { return HasRecipPrec; }
  bool hasSTFIWX() const { return HasSTFIWX; }
  bool hasLFIWAX() const { return HasLFIWAX; }
  bool hasFPRND() const { return HasFPRND; }
  bool hasFPCVT() const { return HasFPCVT; }
  bool hasAltivec() const { return HasAltivec; }
  bool hasSPE() const { return HasSPE; }
  bool hasEFPU2() const { return HasEFPU2; }
  bool hasFPU() const { return HasFPU; }
  bool hasVSX() const { return HasVSX; }
  bool needsTwoConstNR() const { return NeedsTwoConstNR; }
  bool hasP8Vector() const { return HasP8Vector; }
  bool hasP8Altivec() const { return HasP8Altivec; }
  bool hasP8Crypto() const { return HasP8Crypto; }
  bool hasP9Vector() const { return HasP9Vector; }
  bool hasP9Altivec() const { return HasP9Altivec; }
  bool hasP10Vector() const { return HasP10Vector; }
  bool hasPrefixInstrs() const { return HasPrefixInstrs; }
  bool hasPCRelativeMemops() const { return HasPCRelativeMemops; }
  bool hasMMA() const { return HasMMA; }
  bool hasROPProtect() const { return HasROPProtect; }
  bool hasPrivileged() const { return HasPrivileged; }
  bool pairedVectorMemops() const { return PairedVectorMemops; }
  bool hasMFOCRF() const { return HasMFOCRF; }
  bool hasISEL() const { return HasISEL; }
  bool hasBPERMD() const { return HasBPERMD; }
  bool hasExtDiv() const { return HasExtDiv; }
  bool hasCMPB() const { return HasCMPB; }
  bool hasLDBRX() const { return HasLDBRX; }
  bool isBookE() const { return IsBookE; }
  bool hasOnlyMSYNC() const { return HasOnlyMSYNC; }
  bool isPPC4xx() const { return IsPPC4xx; }
  bool isPPC6xx() const { return IsPPC6xx; }
  bool isSecurePlt() const {return SecurePlt; }
  bool vectorsUseTwoUnits() const {return VectorsUseTwoUnits; }
  bool isE500() const { return IsE500; }
  bool isFeatureMFTB() const { return FeatureMFTB; }
  bool allowsUnalignedFPAccess() const { return AllowsUnalignedFPAccess; }
  bool isDeprecatedDST() const { return DeprecatedDST; }
  bool hasICBT() const { return HasICBT; }
  bool hasInvariantFunctionDescriptors() const {
    return HasInvariantFunctionDescriptors;
  }
  bool usePPCPreRASchedStrategy() const { return UsePPCPreRASchedStrategy; }
  bool usePPCPostRASchedStrategy() const { return UsePPCPostRASchedStrategy; }
  bool hasPartwordAtomics() const { return HasPartwordAtomics; }
  bool hasQuadwordAtomics() const { return HasQuadwordAtomics; }
  bool hasDirectMove() const { return HasDirectMove; }

  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 hasHTM() const { return HasHTM; }
  bool hasFloat128() const { return HasFloat128; }
  bool isISA2_06() const { return IsISA2_06; }
  bool isISA2_07() const { return IsISA2_07; }
  bool isISA3_0() const { return IsISA3_0; }
  bool isISA3_1() const { return IsISA3_1; }
  bool useLongCalls() const { return UseLongCalls; }
  bool hasFusion() const { return HasFusion; }
  bool hasStoreFusion() const { return HasStoreFusion; }
  bool hasAddiLoadFusion() const { return HasAddiLoadFusion; }
  bool hasAddisLoadFusion() const { return HasAddisLoadFusion; }
  bool hasArithAddFusion() const { return HasArithAddFusion; }
  bool hasAddLogicalFusion() const { return HasAddLogicalFusion; }
  bool hasLogicalAddFusion() const { return HasLogicalAddFusion; }
  bool hasLogicalFusion() const { return HasLogicalFusion; }
  bool hasCompareFusion() const { return HasCompareFusion; }
  bool hasWideImmFusion() const { return HasWideImmFusion; }
  bool hasSha3Fusion() const { return HasSha3Fusion; }
  bool hasZeroMoveFusion() const { return HasZeroMoveFusion; }
  bool hasBack2BackFusion() const { return HasBack2BackFusion; }
  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;

  /// 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 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