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