1//===- AMDGPUInstructionSelector --------------------------------*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file declares the targeting of the InstructionSelector class for
10/// AMDGPU.
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUINSTRUCTIONSELECTOR_H
14#define LLVM_LIB_TARGET_AMDGPU_AMDGPUINSTRUCTIONSELECTOR_H
15
16#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
17#include "llvm/CodeGen/Register.h"
18#include "llvm/IR/InstrTypes.h"
19#include "llvm/IR/Intrinsics.h"
20#include "llvm/IR/IntrinsicsAMDGPU.h"
21
22namespace {
23#define GET_GLOBALISEL_PREDICATE_BITSET
24#define AMDGPUSubtarget GCNSubtarget
25#include "AMDGPUGenGlobalISel.inc"
26#undef GET_GLOBALISEL_PREDICATE_BITSET
27#undef AMDGPUSubtarget
28}
29
30namespace llvm {
31
32namespace AMDGPU {
33struct ImageDimIntrinsicInfo;
34}
35
36class AMDGPUInstrInfo;
37class AMDGPURegisterBankInfo;
38class AMDGPUTargetMachine;
39class BlockFrequencyInfo;
40class ProfileSummaryInfo;
41class GCNSubtarget;
42class MachineInstr;
43class MachineIRBuilder;
44class MachineOperand;
45class MachineRegisterInfo;
46class RegisterBank;
47class SIInstrInfo;
48class SIMachineFunctionInfo;
49class SIRegisterInfo;
50class TargetRegisterClass;
51
52class AMDGPUInstructionSelector final : public InstructionSelector {
53private:
54  MachineRegisterInfo *MRI;
55  const GCNSubtarget *Subtarget;
56
57public:
58  AMDGPUInstructionSelector(const GCNSubtarget &STI,
59                            const AMDGPURegisterBankInfo &RBI,
60                            const AMDGPUTargetMachine &TM);
61
62  bool select(MachineInstr &I) override;
63  static const char *getName();
64
65  void setupMF(MachineFunction &MF, GISelKnownBits *KB,
66               CodeGenCoverage &CoverageInfo, ProfileSummaryInfo *PSI,
67               BlockFrequencyInfo *BFI) override;
68
69private:
70  struct GEPInfo {
71    const MachineInstr &GEP;
72    SmallVector<unsigned, 2> SgprParts;
73    SmallVector<unsigned, 2> VgprParts;
74    int64_t Imm;
75    GEPInfo(const MachineInstr &GEP) : GEP(GEP), Imm(0) { }
76  };
77
78  bool isSGPR(Register Reg) const;
79
80  bool isInstrUniform(const MachineInstr &MI) const;
81  bool isVCC(Register Reg, const MachineRegisterInfo &MRI) const;
82
83  const RegisterBank *getArtifactRegBank(
84    Register Reg, const MachineRegisterInfo &MRI,
85    const TargetRegisterInfo &TRI) const;
86
87  /// tblgen-erated 'select' implementation.
88  bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
89
90  MachineOperand getSubOperand64(MachineOperand &MO,
91                                 const TargetRegisterClass &SubRC,
92                                 unsigned SubIdx) const;
93
94  bool constrainCopyLikeIntrin(MachineInstr &MI, unsigned NewOpc) const;
95  bool selectCOPY(MachineInstr &I) const;
96  bool selectPHI(MachineInstr &I) const;
97  bool selectG_TRUNC(MachineInstr &I) const;
98  bool selectG_SZA_EXT(MachineInstr &I) const;
99  bool selectG_CONSTANT(MachineInstr &I) const;
100  bool selectG_FNEG(MachineInstr &I) const;
101  bool selectG_FABS(MachineInstr &I) const;
102  bool selectG_AND_OR_XOR(MachineInstr &I) const;
103  bool selectG_ADD_SUB(MachineInstr &I) const;
104  bool selectG_UADDO_USUBO_UADDE_USUBE(MachineInstr &I) const;
105  bool selectG_EXTRACT(MachineInstr &I) const;
106  bool selectG_MERGE_VALUES(MachineInstr &I) const;
107  bool selectG_UNMERGE_VALUES(MachineInstr &I) const;
108  bool selectG_BUILD_VECTOR_TRUNC(MachineInstr &I) const;
109  bool selectG_PTR_ADD(MachineInstr &I) const;
110  bool selectG_IMPLICIT_DEF(MachineInstr &I) const;
111  bool selectG_INSERT(MachineInstr &I) const;
112
113  bool selectInterpP1F16(MachineInstr &MI) const;
114  bool selectWritelane(MachineInstr &MI) const;
115  bool selectDivScale(MachineInstr &MI) const;
116  bool selectIntrinsicIcmp(MachineInstr &MI) const;
117  bool selectBallot(MachineInstr &I) const;
118  bool selectRelocConstant(MachineInstr &I) const;
119  bool selectGroupStaticSize(MachineInstr &I) const;
120  bool selectReturnAddress(MachineInstr &I) const;
121  bool selectG_INTRINSIC(MachineInstr &I) const;
122
123  bool selectEndCfIntrinsic(MachineInstr &MI) const;
124  bool selectDSOrderedIntrinsic(MachineInstr &MI, Intrinsic::ID IID) const;
125  bool selectDSGWSIntrinsic(MachineInstr &MI, Intrinsic::ID IID) const;
126  bool selectDSAppendConsume(MachineInstr &MI, bool IsAppend) const;
127  bool selectSBarrier(MachineInstr &MI) const;
128
129  bool selectImageIntrinsic(MachineInstr &MI,
130                            const AMDGPU::ImageDimIntrinsicInfo *Intr) const;
131  bool selectG_INTRINSIC_W_SIDE_EFFECTS(MachineInstr &I) const;
132  int getS_CMPOpcode(CmpInst::Predicate P, unsigned Size) const;
133  bool selectG_ICMP(MachineInstr &I) const;
134  bool hasVgprParts(ArrayRef<GEPInfo> AddrInfo) const;
135  void getAddrModeInfo(const MachineInstr &Load, const MachineRegisterInfo &MRI,
136                       SmallVectorImpl<GEPInfo> &AddrInfo) const;
137  bool selectSMRD(MachineInstr &I, ArrayRef<GEPInfo> AddrInfo) const;
138
139  void initM0(MachineInstr &I) const;
140  bool selectG_LOAD_STORE_ATOMICRMW(MachineInstr &I) const;
141  bool selectG_AMDGPU_ATOMIC_CMPXCHG(MachineInstr &I) const;
142  bool selectG_SELECT(MachineInstr &I) const;
143  bool selectG_BRCOND(MachineInstr &I) const;
144  bool selectG_GLOBAL_VALUE(MachineInstr &I) const;
145  bool selectG_PTRMASK(MachineInstr &I) const;
146  bool selectG_EXTRACT_VECTOR_ELT(MachineInstr &I) const;
147  bool selectG_INSERT_VECTOR_ELT(MachineInstr &I) const;
148  bool selectG_SHUFFLE_VECTOR(MachineInstr &I) const;
149  bool selectAMDGPU_BUFFER_ATOMIC_FADD(MachineInstr &I) const;
150  bool selectGlobalAtomicFadd(MachineInstr &I, MachineOperand &AddrOp,
151                              MachineOperand &DataOp) const;
152  bool selectBVHIntrinsic(MachineInstr &I) const;
153
154  std::pair<Register, unsigned> selectVOP3ModsImpl(MachineOperand &Root,
155                                                   bool AllowAbs = true) const;
156
157  InstructionSelector::ComplexRendererFns
158  selectVCSRC(MachineOperand &Root) const;
159
160  InstructionSelector::ComplexRendererFns
161  selectVSRC0(MachineOperand &Root) const;
162
163  InstructionSelector::ComplexRendererFns
164  selectVOP3Mods0(MachineOperand &Root) const;
165  InstructionSelector::ComplexRendererFns
166  selectVOP3BMods0(MachineOperand &Root) const;
167  InstructionSelector::ComplexRendererFns
168  selectVOP3OMods(MachineOperand &Root) const;
169  InstructionSelector::ComplexRendererFns
170  selectVOP3Mods(MachineOperand &Root) const;
171  InstructionSelector::ComplexRendererFns
172  selectVOP3BMods(MachineOperand &Root) const;
173
174  ComplexRendererFns selectVOP3NoMods(MachineOperand &Root) const;
175
176  InstructionSelector::ComplexRendererFns
177  selectVOP3Mods_nnan(MachineOperand &Root) const;
178
179  std::pair<Register, unsigned>
180  selectVOP3PModsImpl(Register Src, const MachineRegisterInfo &MRI) const;
181
182  InstructionSelector::ComplexRendererFns
183  selectVOP3PMods(MachineOperand &Root) const;
184
185  InstructionSelector::ComplexRendererFns
186  selectVOP3OpSelMods(MachineOperand &Root) const;
187
188  InstructionSelector::ComplexRendererFns
189  selectSmrdImm(MachineOperand &Root) const;
190  InstructionSelector::ComplexRendererFns
191  selectSmrdImm32(MachineOperand &Root) const;
192  InstructionSelector::ComplexRendererFns
193  selectSmrdSgpr(MachineOperand &Root) const;
194
195  std::pair<Register, int> selectFlatOffsetImpl(MachineOperand &Root,
196                                                uint64_t FlatVariant) const;
197
198  InstructionSelector::ComplexRendererFns
199  selectFlatOffset(MachineOperand &Root) const;
200  InstructionSelector::ComplexRendererFns
201  selectGlobalOffset(MachineOperand &Root) const;
202  InstructionSelector::ComplexRendererFns
203  selectScratchOffset(MachineOperand &Root) const;
204
205  InstructionSelector::ComplexRendererFns
206  selectGlobalSAddr(MachineOperand &Root) const;
207
208  InstructionSelector::ComplexRendererFns
209  selectScratchSAddr(MachineOperand &Root) const;
210
211  InstructionSelector::ComplexRendererFns
212  selectMUBUFScratchOffen(MachineOperand &Root) const;
213  InstructionSelector::ComplexRendererFns
214  selectMUBUFScratchOffset(MachineOperand &Root) const;
215
216  bool isDSOffsetLegal(Register Base, int64_t Offset) const;
217  bool isDSOffset2Legal(Register Base, int64_t Offset0, int64_t Offset1,
218                        unsigned Size) const;
219
220  std::pair<Register, unsigned>
221  selectDS1Addr1OffsetImpl(MachineOperand &Root) const;
222  InstructionSelector::ComplexRendererFns
223  selectDS1Addr1Offset(MachineOperand &Root) const;
224
225  InstructionSelector::ComplexRendererFns
226  selectDS64Bit4ByteAligned(MachineOperand &Root) const;
227
228  InstructionSelector::ComplexRendererFns
229  selectDS128Bit8ByteAligned(MachineOperand &Root) const;
230
231  std::pair<Register, unsigned> selectDSReadWrite2Impl(MachineOperand &Root,
232                                                       unsigned size) const;
233  InstructionSelector::ComplexRendererFns
234  selectDSReadWrite2(MachineOperand &Root, unsigned size) const;
235
236  std::pair<Register, int64_t>
237  getPtrBaseWithConstantOffset(Register Root,
238                               const MachineRegisterInfo &MRI) const;
239
240  // Parse out a chain of up to two g_ptr_add instructions.
241  // g_ptr_add (n0, _)
242  // g_ptr_add (n0, (n1 = g_ptr_add n2, n3))
243  struct MUBUFAddressData {
244    Register N0, N2, N3;
245    int64_t Offset = 0;
246  };
247
248  bool shouldUseAddr64(MUBUFAddressData AddrData) const;
249
250  void splitIllegalMUBUFOffset(MachineIRBuilder &B,
251                               Register &SOffset, int64_t &ImmOffset) const;
252
253  MUBUFAddressData parseMUBUFAddress(Register Src) const;
254
255  bool selectMUBUFAddr64Impl(MachineOperand &Root, Register &VAddr,
256                             Register &RSrcReg, Register &SOffset,
257                             int64_t &Offset) const;
258
259  bool selectMUBUFOffsetImpl(MachineOperand &Root, Register &RSrcReg,
260                             Register &SOffset, int64_t &Offset) const;
261
262  InstructionSelector::ComplexRendererFns
263  selectMUBUFAddr64(MachineOperand &Root) const;
264
265  InstructionSelector::ComplexRendererFns
266  selectMUBUFOffset(MachineOperand &Root) const;
267
268  InstructionSelector::ComplexRendererFns
269  selectMUBUFOffsetAtomic(MachineOperand &Root) const;
270
271  InstructionSelector::ComplexRendererFns
272  selectMUBUFAddr64Atomic(MachineOperand &Root) const;
273
274  ComplexRendererFns selectSMRDBufferImm(MachineOperand &Root) const;
275  ComplexRendererFns selectSMRDBufferImm32(MachineOperand &Root) const;
276
277  void renderTruncImm32(MachineInstrBuilder &MIB, const MachineInstr &MI,
278                        int OpIdx = -1) const;
279
280  void renderTruncTImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
281                       int OpIdx) const;
282
283  void renderNegateImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
284                       int OpIdx) const;
285
286  void renderBitcastImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
287                        int OpIdx) const;
288
289  void renderPopcntImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
290                       int OpIdx) const;
291  void renderExtractCPol(MachineInstrBuilder &MIB, const MachineInstr &MI,
292                         int OpIdx) const;
293  void renderExtractSWZ(MachineInstrBuilder &MIB, const MachineInstr &MI,
294                        int OpIdx) const;
295  void renderSetGLC(MachineInstrBuilder &MIB, const MachineInstr &MI,
296                    int OpIdx) const;
297
298  void renderFrameIndex(MachineInstrBuilder &MIB, const MachineInstr &MI,
299                        int OpIdx) const;
300
301  bool isInlineImmediate16(int64_t Imm) const;
302  bool isInlineImmediate32(int64_t Imm) const;
303  bool isInlineImmediate64(int64_t Imm) const;
304  bool isInlineImmediate(const APFloat &Imm) const;
305
306  const SIInstrInfo &TII;
307  const SIRegisterInfo &TRI;
308  const AMDGPURegisterBankInfo &RBI;
309  const AMDGPUTargetMachine &TM;
310  const GCNSubtarget &STI;
311  bool EnableLateStructurizeCFG;
312#define GET_GLOBALISEL_PREDICATES_DECL
313#define AMDGPUSubtarget GCNSubtarget
314#include "AMDGPUGenGlobalISel.inc"
315#undef GET_GLOBALISEL_PREDICATES_DECL
316#undef AMDGPUSubtarget
317
318#define GET_GLOBALISEL_TEMPORARIES_DECL
319#include "AMDGPUGenGlobalISel.inc"
320#undef GET_GLOBALISEL_TEMPORARIES_DECL
321};
322
323} // End llvm namespace.
324#endif
325