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 "SIDefines.h" |
17 | #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" |
18 | #include "llvm/IR/InstrTypes.h" |
19 | |
20 | namespace { |
21 | #define GET_GLOBALISEL_PREDICATE_BITSET |
22 | #define AMDGPUSubtarget GCNSubtarget |
23 | #include "AMDGPUGenGlobalISel.inc" |
24 | #undef GET_GLOBALISEL_PREDICATE_BITSET |
25 | #undef AMDGPUSubtarget |
26 | } |
27 | |
28 | namespace llvm { |
29 | |
30 | namespace AMDGPU { |
31 | struct ImageDimIntrinsicInfo; |
32 | } |
33 | |
34 | class AMDGPURegisterBankInfo; |
35 | class AMDGPUTargetMachine; |
36 | class BlockFrequencyInfo; |
37 | class ProfileSummaryInfo; |
38 | class GCNSubtarget; |
39 | class MachineInstr; |
40 | class MachineIRBuilder; |
41 | class MachineOperand; |
42 | class MachineRegisterInfo; |
43 | class RegisterBank; |
44 | class SIInstrInfo; |
45 | class SIRegisterInfo; |
46 | class TargetRegisterClass; |
47 | |
48 | class AMDGPUInstructionSelector final : public InstructionSelector { |
49 | private: |
50 | MachineRegisterInfo *MRI; |
51 | const GCNSubtarget *Subtarget; |
52 | |
53 | public: |
54 | AMDGPUInstructionSelector(const GCNSubtarget &STI, |
55 | const AMDGPURegisterBankInfo &RBI, |
56 | const AMDGPUTargetMachine &TM); |
57 | |
58 | bool select(MachineInstr &I) override; |
59 | static const char *getName(); |
60 | |
61 | void setupMF(MachineFunction &MF, GISelValueTracking *VT, |
62 | CodeGenCoverage *CoverageInfo, ProfileSummaryInfo *PSI, |
63 | BlockFrequencyInfo *BFI) override; |
64 | |
65 | private: |
66 | struct GEPInfo { |
67 | SmallVector<unsigned, 2> SgprParts; |
68 | SmallVector<unsigned, 2> VgprParts; |
69 | int64_t Imm = 0; |
70 | }; |
71 | |
72 | bool isSGPR(Register Reg) const; |
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 selectCOPY_SCC_VCC(MachineInstr &I) const; |
91 | bool selectCOPY_VCC_SCC(MachineInstr &I) const; |
92 | bool selectReadAnyLane(MachineInstr &I) const; |
93 | bool selectPHI(MachineInstr &I) const; |
94 | bool selectG_TRUNC(MachineInstr &I) const; |
95 | bool selectG_SZA_EXT(MachineInstr &I) const; |
96 | bool selectG_FPEXT(MachineInstr &I) const; |
97 | bool selectG_FNEG(MachineInstr &I) const; |
98 | bool selectG_FABS(MachineInstr &I) const; |
99 | bool selectG_AND_OR_XOR(MachineInstr &I) const; |
100 | bool selectG_ADD_SUB(MachineInstr &I) const; |
101 | bool selectG_UADDO_USUBO_UADDE_USUBE(MachineInstr &I) const; |
102 | bool selectG_AMDGPU_MAD_64_32(MachineInstr &I) const; |
103 | bool (MachineInstr &I) const; |
104 | bool selectG_FMA_FMAD(MachineInstr &I) const; |
105 | bool selectG_MERGE_VALUES(MachineInstr &I) const; |
106 | bool selectG_UNMERGE_VALUES(MachineInstr &I) const; |
107 | bool selectG_BUILD_VECTOR(MachineInstr &I) const; |
108 | bool selectG_IMPLICIT_DEF(MachineInstr &I) const; |
109 | bool selectG_INSERT(MachineInstr &I) const; |
110 | bool selectG_SBFX_UBFX(MachineInstr &I) const; |
111 | |
112 | bool selectInterpP1F16(MachineInstr &MI) const; |
113 | bool selectWritelane(MachineInstr &MI) const; |
114 | bool selectDivScale(MachineInstr &MI) const; |
115 | bool selectIntrinsicCmp(MachineInstr &MI) const; |
116 | bool selectBallot(MachineInstr &I) const; |
117 | bool selectRelocConstant(MachineInstr &I) const; |
118 | bool selectGroupStaticSize(MachineInstr &I) const; |
119 | bool selectReturnAddress(MachineInstr &I) const; |
120 | bool selectG_INTRINSIC(MachineInstr &I) const; |
121 | |
122 | bool selectEndCfIntrinsic(MachineInstr &MI) const; |
123 | bool selectDSOrderedIntrinsic(MachineInstr &MI, Intrinsic::ID IID) const; |
124 | bool selectDSGWSIntrinsic(MachineInstr &MI, Intrinsic::ID IID) const; |
125 | bool selectDSAppendConsume(MachineInstr &MI, bool IsAppend) const; |
126 | bool selectInitWholeWave(MachineInstr &MI) const; |
127 | bool selectSBarrier(MachineInstr &MI) const; |
128 | bool selectDSBvhStackIntrinsic(MachineInstr &MI) const; |
129 | |
130 | bool selectImageIntrinsic(MachineInstr &MI, |
131 | const AMDGPU::ImageDimIntrinsicInfo *Intr) const; |
132 | bool selectG_INTRINSIC_W_SIDE_EFFECTS(MachineInstr &I) const; |
133 | int getS_CMPOpcode(CmpInst::Predicate P, unsigned Size) const; |
134 | bool selectG_ICMP_or_FCMP(MachineInstr &I) const; |
135 | bool hasVgprParts(ArrayRef<GEPInfo> AddrInfo) const; |
136 | void getAddrModeInfo(const MachineInstr &Load, const MachineRegisterInfo &MRI, |
137 | SmallVectorImpl<GEPInfo> &AddrInfo) const; |
138 | |
139 | void initM0(MachineInstr &I) const; |
140 | bool selectG_LOAD_STORE_ATOMICRMW(MachineInstr &I) const; |
141 | bool selectG_SELECT(MachineInstr &I) const; |
142 | bool selectG_BRCOND(MachineInstr &I) const; |
143 | bool selectG_GLOBAL_VALUE(MachineInstr &I) const; |
144 | bool selectG_PTRMASK(MachineInstr &I) const; |
145 | bool (MachineInstr &I) const; |
146 | bool selectG_INSERT_VECTOR_ELT(MachineInstr &I) const; |
147 | bool selectBufferLoadLds(MachineInstr &MI) const; |
148 | bool selectGlobalLoadLds(MachineInstr &MI) const; |
149 | bool selectBVHIntersectRayIntrinsic(MachineInstr &I) const; |
150 | bool selectSMFMACIntrin(MachineInstr &I) const; |
151 | bool selectPermlaneSwapIntrin(MachineInstr &I, Intrinsic::ID IntrID) const; |
152 | bool selectWaveAddress(MachineInstr &I) const; |
153 | bool selectBITOP3(MachineInstr &I) const; |
154 | bool selectStackRestore(MachineInstr &MI) const; |
155 | bool selectNamedBarrierInit(MachineInstr &I, Intrinsic::ID IID) const; |
156 | bool selectNamedBarrierInst(MachineInstr &I, Intrinsic::ID IID) const; |
157 | bool selectSBarrierSignalIsfirst(MachineInstr &I, Intrinsic::ID IID) const; |
158 | bool selectSGetBarrierState(MachineInstr &I, Intrinsic::ID IID) const; |
159 | |
160 | std::pair<Register, unsigned> selectVOP3ModsImpl(Register Src, |
161 | bool IsCanonicalizing = true, |
162 | bool AllowAbs = true, |
163 | bool OpSel = false) const; |
164 | |
165 | Register copyToVGPRIfSrcFolded(Register Src, unsigned Mods, |
166 | MachineOperand Root, MachineInstr *InsertPt, |
167 | bool ForceVGPR = false) const; |
168 | |
169 | InstructionSelector::ComplexRendererFns |
170 | selectVCSRC(MachineOperand &Root) const; |
171 | |
172 | InstructionSelector::ComplexRendererFns |
173 | selectVSRC0(MachineOperand &Root) const; |
174 | |
175 | InstructionSelector::ComplexRendererFns |
176 | selectVOP3Mods0(MachineOperand &Root) const; |
177 | InstructionSelector::ComplexRendererFns |
178 | selectVOP3BMods0(MachineOperand &Root) const; |
179 | InstructionSelector::ComplexRendererFns |
180 | selectVOP3OMods(MachineOperand &Root) const; |
181 | InstructionSelector::ComplexRendererFns |
182 | selectVOP3Mods(MachineOperand &Root) const; |
183 | InstructionSelector::ComplexRendererFns |
184 | selectVOP3ModsNonCanonicalizing(MachineOperand &Root) const; |
185 | InstructionSelector::ComplexRendererFns |
186 | selectVOP3BMods(MachineOperand &Root) const; |
187 | |
188 | ComplexRendererFns selectVOP3NoMods(MachineOperand &Root) const; |
189 | |
190 | std::pair<Register, unsigned> |
191 | selectVOP3PModsImpl(Register Src, const MachineRegisterInfo &MRI, |
192 | bool IsDOT = false) const; |
193 | |
194 | InstructionSelector::ComplexRendererFns |
195 | selectVOP3PMods(MachineOperand &Root) const; |
196 | |
197 | InstructionSelector::ComplexRendererFns |
198 | selectVOP3PModsDOT(MachineOperand &Root) const; |
199 | |
200 | InstructionSelector::ComplexRendererFns |
201 | selectVOP3PModsNeg(MachineOperand &Root) const; |
202 | |
203 | InstructionSelector::ComplexRendererFns |
204 | selectWMMAOpSelVOP3PMods(MachineOperand &Root) const; |
205 | |
206 | InstructionSelector::ComplexRendererFns |
207 | selectWMMAModsF32NegAbs(MachineOperand &Root) const; |
208 | InstructionSelector::ComplexRendererFns |
209 | selectWMMAModsF16Neg(MachineOperand &Root) const; |
210 | InstructionSelector::ComplexRendererFns |
211 | selectWMMAModsF16NegAbs(MachineOperand &Root) const; |
212 | InstructionSelector::ComplexRendererFns |
213 | selectWMMAVISrc(MachineOperand &Root) const; |
214 | InstructionSelector::ComplexRendererFns |
215 | selectSWMMACIndex8(MachineOperand &Root) const; |
216 | InstructionSelector::ComplexRendererFns |
217 | selectSWMMACIndex16(MachineOperand &Root) const; |
218 | |
219 | InstructionSelector::ComplexRendererFns |
220 | selectVOP3OpSelMods(MachineOperand &Root) const; |
221 | |
222 | InstructionSelector::ComplexRendererFns |
223 | selectVINTERPMods(MachineOperand &Root) const; |
224 | InstructionSelector::ComplexRendererFns |
225 | selectVINTERPModsHi(MachineOperand &Root) const; |
226 | |
227 | bool selectSmrdOffset(MachineOperand &Root, Register &Base, Register *SOffset, |
228 | int64_t *Offset) const; |
229 | InstructionSelector::ComplexRendererFns |
230 | selectSmrdImm(MachineOperand &Root) const; |
231 | InstructionSelector::ComplexRendererFns |
232 | selectSmrdImm32(MachineOperand &Root) const; |
233 | InstructionSelector::ComplexRendererFns |
234 | selectSmrdSgpr(MachineOperand &Root) const; |
235 | InstructionSelector::ComplexRendererFns |
236 | selectSmrdSgprImm(MachineOperand &Root) const; |
237 | |
238 | std::pair<Register, int> selectFlatOffsetImpl(MachineOperand &Root, |
239 | uint64_t FlatVariant) const; |
240 | |
241 | InstructionSelector::ComplexRendererFns |
242 | selectFlatOffset(MachineOperand &Root) const; |
243 | InstructionSelector::ComplexRendererFns |
244 | selectGlobalOffset(MachineOperand &Root) const; |
245 | InstructionSelector::ComplexRendererFns |
246 | selectScratchOffset(MachineOperand &Root) const; |
247 | |
248 | InstructionSelector::ComplexRendererFns |
249 | selectGlobalSAddr(MachineOperand &Root) const; |
250 | |
251 | InstructionSelector::ComplexRendererFns |
252 | selectScratchSAddr(MachineOperand &Root) const; |
253 | bool checkFlatScratchSVSSwizzleBug(Register VAddr, Register SAddr, |
254 | uint64_t ImmOffset) const; |
255 | InstructionSelector::ComplexRendererFns |
256 | selectScratchSVAddr(MachineOperand &Root) const; |
257 | |
258 | InstructionSelector::ComplexRendererFns |
259 | selectMUBUFScratchOffen(MachineOperand &Root) const; |
260 | InstructionSelector::ComplexRendererFns |
261 | selectMUBUFScratchOffset(MachineOperand &Root) const; |
262 | |
263 | bool isDSOffsetLegal(Register Base, int64_t Offset) const; |
264 | bool isDSOffset2Legal(Register Base, int64_t Offset0, int64_t Offset1, |
265 | unsigned Size) const; |
266 | bool isFlatScratchBaseLegal(Register Addr) const; |
267 | bool isFlatScratchBaseLegalSV(Register Addr) const; |
268 | bool isFlatScratchBaseLegalSVImm(Register Addr) const; |
269 | |
270 | std::pair<Register, unsigned> |
271 | selectDS1Addr1OffsetImpl(MachineOperand &Root) const; |
272 | InstructionSelector::ComplexRendererFns |
273 | selectDS1Addr1Offset(MachineOperand &Root) const; |
274 | |
275 | InstructionSelector::ComplexRendererFns |
276 | selectDS64Bit4ByteAligned(MachineOperand &Root) const; |
277 | |
278 | InstructionSelector::ComplexRendererFns |
279 | selectDS128Bit8ByteAligned(MachineOperand &Root) const; |
280 | |
281 | std::pair<Register, unsigned> selectDSReadWrite2Impl(MachineOperand &Root, |
282 | unsigned size) const; |
283 | InstructionSelector::ComplexRendererFns |
284 | selectDSReadWrite2(MachineOperand &Root, unsigned size) const; |
285 | |
286 | std::pair<Register, int64_t> |
287 | getPtrBaseWithConstantOffset(Register Root, |
288 | const MachineRegisterInfo &MRI) const; |
289 | |
290 | // Parse out a chain of up to two g_ptr_add instructions. |
291 | // g_ptr_add (n0, _) |
292 | // g_ptr_add (n0, (n1 = g_ptr_add n2, n3)) |
293 | struct MUBUFAddressData { |
294 | Register N0, N2, N3; |
295 | int64_t Offset = 0; |
296 | }; |
297 | |
298 | bool shouldUseAddr64(MUBUFAddressData AddrData) const; |
299 | |
300 | void splitIllegalMUBUFOffset(MachineIRBuilder &B, |
301 | Register &SOffset, int64_t &ImmOffset) const; |
302 | |
303 | MUBUFAddressData parseMUBUFAddress(Register Src) const; |
304 | |
305 | bool selectMUBUFAddr64Impl(MachineOperand &Root, Register &VAddr, |
306 | Register &RSrcReg, Register &SOffset, |
307 | int64_t &Offset) const; |
308 | |
309 | bool selectMUBUFOffsetImpl(MachineOperand &Root, Register &RSrcReg, |
310 | Register &SOffset, int64_t &Offset) const; |
311 | |
312 | InstructionSelector::ComplexRendererFns |
313 | selectBUFSOffset(MachineOperand &Root) const; |
314 | |
315 | InstructionSelector::ComplexRendererFns |
316 | selectMUBUFAddr64(MachineOperand &Root) const; |
317 | |
318 | InstructionSelector::ComplexRendererFns |
319 | selectMUBUFOffset(MachineOperand &Root) const; |
320 | |
321 | ComplexRendererFns selectSMRDBufferImm(MachineOperand &Root) const; |
322 | ComplexRendererFns selectSMRDBufferImm32(MachineOperand &Root) const; |
323 | ComplexRendererFns selectSMRDBufferSgprImm(MachineOperand &Root) const; |
324 | |
325 | std::pair<Register, unsigned> selectVOP3PMadMixModsImpl(MachineOperand &Root, |
326 | bool &Matched) const; |
327 | ComplexRendererFns selectVOP3PMadMixModsExt(MachineOperand &Root) const; |
328 | ComplexRendererFns selectVOP3PMadMixMods(MachineOperand &Root) const; |
329 | |
330 | void renderTruncImm32(MachineInstrBuilder &MIB, const MachineInstr &MI, |
331 | int OpIdx = -1) const; |
332 | |
333 | void renderTruncTImm(MachineInstrBuilder &MIB, const MachineInstr &MI, |
334 | int OpIdx) const; |
335 | void renderZextBoolTImm(MachineInstrBuilder &MIB, const MachineInstr &MI, |
336 | int OpIdx) const; |
337 | |
338 | void renderOpSelTImm(MachineInstrBuilder &MIB, const MachineInstr &MI, |
339 | int OpIdx) const; |
340 | |
341 | void renderSrcAndDstSelToOpSelXForm_0_0(MachineInstrBuilder &MIB, |
342 | const MachineInstr &MI, |
343 | int OpIdx) const; |
344 | |
345 | void renderSrcAndDstSelToOpSelXForm_0_1(MachineInstrBuilder &MIB, |
346 | const MachineInstr &MI, |
347 | int OpIdx) const; |
348 | |
349 | void renderSrcAndDstSelToOpSelXForm_1_0(MachineInstrBuilder &MIB, |
350 | const MachineInstr &MI, |
351 | int OpIdx) const; |
352 | |
353 | void renderSrcAndDstSelToOpSelXForm_1_1(MachineInstrBuilder &MIB, |
354 | const MachineInstr &MI, |
355 | int OpIdx) const; |
356 | |
357 | void renderDstSelToOpSelXForm(MachineInstrBuilder &MIB, |
358 | const MachineInstr &MI, int OpIdx) const; |
359 | |
360 | void renderSrcSelToOpSelXForm(MachineInstrBuilder &MIB, |
361 | const MachineInstr &MI, int OpIdx) const; |
362 | |
363 | void renderSrcAndDstSelToOpSelXForm_2_0(MachineInstrBuilder &MIB, |
364 | const MachineInstr &MI, |
365 | int OpIdx) const; |
366 | |
367 | void renderDstSelToOpSel3XFormXForm(MachineInstrBuilder &MIB, |
368 | const MachineInstr &MI, int OpIdx) const; |
369 | |
370 | void renderNegateImm(MachineInstrBuilder &MIB, const MachineInstr &MI, |
371 | int OpIdx) const; |
372 | |
373 | void renderBitcastFPImm(MachineInstrBuilder &MIB, const MachineInstr &MI, |
374 | int OpIdx) const; |
375 | |
376 | void renderBitcastFPImm32(MachineInstrBuilder &MIB, const MachineInstr &MI, |
377 | int OpIdx) const { |
378 | renderBitcastFPImm(MIB, MI, OpIdx); |
379 | } |
380 | void renderBitcastFPImm64(MachineInstrBuilder &MIB, const MachineInstr &MI, |
381 | int OpIdx) const { |
382 | renderBitcastFPImm(MIB, MI, OpIdx); |
383 | } |
384 | |
385 | void renderPopcntImm(MachineInstrBuilder &MIB, const MachineInstr &MI, |
386 | int OpIdx) const; |
387 | void (MachineInstrBuilder &MIB, const MachineInstr &MI, |
388 | int OpIdx) const; |
389 | void (MachineInstrBuilder &MIB, const MachineInstr &MI, |
390 | int OpIdx) const; |
391 | void (MachineInstrBuilder &MIB, const MachineInstr &MI, |
392 | int OpIdx) const; |
393 | |
394 | void renderFrameIndex(MachineInstrBuilder &MIB, const MachineInstr &MI, |
395 | int OpIdx) const; |
396 | |
397 | void renderFPPow2ToExponent(MachineInstrBuilder &MIB, const MachineInstr &MI, |
398 | int OpIdx) const; |
399 | |
400 | void renderRoundMode(MachineInstrBuilder &MIB, const MachineInstr &MI, |
401 | int OpIdx) const; |
402 | void renderScaledMAIIntrinsicOperand(MachineInstrBuilder &MIB, |
403 | const MachineInstr &MI, int OpIdx) const; |
404 | |
405 | bool isInlineImmediate(const APInt &Imm) const; |
406 | bool isInlineImmediate(const APFloat &Imm) const; |
407 | |
408 | // Returns true if TargetOpcode::G_AND MachineInstr `MI`'s masking of the |
409 | // shift amount operand's `ShAmtBits` bits is unneeded. |
410 | bool isUnneededShiftMask(const MachineInstr &MI, unsigned ShAmtBits) const; |
411 | |
412 | const SIInstrInfo &TII; |
413 | const SIRegisterInfo &TRI; |
414 | const AMDGPURegisterBankInfo &RBI; |
415 | const AMDGPUTargetMachine &TM; |
416 | const GCNSubtarget &STI; |
417 | #define GET_GLOBALISEL_PREDICATES_DECL |
418 | #define AMDGPUSubtarget GCNSubtarget |
419 | #include "AMDGPUGenGlobalISel.inc" |
420 | #undef GET_GLOBALISEL_PREDICATES_DECL |
421 | #undef AMDGPUSubtarget |
422 | |
423 | #define GET_GLOBALISEL_TEMPORARIES_DECL |
424 | #include "AMDGPUGenGlobalISel.inc" |
425 | #undef GET_GLOBALISEL_TEMPORARIES_DECL |
426 | }; |
427 | |
428 | } // End llvm namespace. |
429 | #endif |
430 | |