aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/PowerPC/PPCSubtarget.h
blob: 306a52dca8362bb4f0d25ea199a6c757cac1c324 (plain)
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
//===-- 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/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/RegisterBankInfo.h"
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/TargetParser/Triple.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;

// Bool members corresponding to the SubtargetFeatures defined in tablegen.
#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \
  bool ATTRIBUTE = DEFAULT;
#include "PPCGenSubtargetInfo.inc"

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

  bool IsPPC64;
  bool IsLittleEndian;

  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 &TuneCPU, 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, a TuneCPU,  and
  /// feature string so that we can use initializer lists for subtarget
  /// initialization.
  PPCSubtarget &initializeSubtargetDependencies(StringRef CPU,
                                                StringRef TuneCPU,
                                                StringRef FS);

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

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

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

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

// Getters for SubtargetFeatures defined in tablegen.
#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \
  bool GETTER() const { return ATTRIBUTE; }
#include "PPCGenSubtargetInfo.inc"

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

  bool enableSpillageCopyElimination() const override { return true; }

  /// 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 getThreadPointerRegister() const {
    assert((is64BitELFABI() || isAIXABI()) &&
           "Should only be called for targets with a thread pointer register.");
    return IsPPC64 ? PPC::X13 : PPC::R13;
  }

  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