LLVM 24.0.0git
AMDGPURegisterBankInfo.cpp
Go to the documentation of this file.
1//===- AMDGPURegisterBankInfo.cpp -------------------------------*- 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 implements the targeting of the RegisterBankInfo class for
10/// AMDGPU.
11///
12/// \par
13///
14/// AMDGPU has unique register bank constraints that require special high level
15/// strategies to deal with. There are two main true physical register banks
16/// VGPR (vector), and SGPR (scalar). Additionally the VCC register bank is a
17/// sort of pseudo-register bank needed to represent SGPRs used in a vector
18/// boolean context. There is also the AGPR bank, which is a special purpose
19/// physical register bank present on some subtargets.
20///
21/// Copying from VGPR to SGPR is generally illegal, unless the value is known to
22/// be uniform. It is generally not valid to legalize operands by inserting
23/// copies as on other targets. Operations which require uniform, SGPR operands
24/// generally require scalarization by repeatedly executing the instruction,
25/// activating each set of lanes using a unique set of input values. This is
26/// referred to as a waterfall loop.
27///
28/// \par Booleans
29///
30/// Booleans (s1 values) requires special consideration. A vector compare result
31/// is naturally a bitmask with one bit per lane, in a 32 or 64-bit
32/// register. These are represented with the VCC bank. During selection, we need
33/// to be able to unambiguously go back from a register class to a register
34/// bank. To distinguish whether an SGPR should use the SGPR or VCC register
35/// bank, we need to know the use context type. An SGPR s1 value always means a
36/// VCC bank value, otherwise it will be the SGPR bank. A scalar compare sets
37/// SCC, which is a 1-bit unaddressable register. This will need to be copied to
38/// a 32-bit virtual register. Taken together, this means we need to adjust the
39/// type of boolean operations to be regbank legal. All SALU booleans need to be
40/// widened to 32-bits, and all VALU booleans need to be s1 values.
41///
42/// A noteworthy exception to the s1-means-vcc rule is for legalization artifact
43/// casts. G_TRUNC s1 results, and G_SEXT/G_ZEXT/G_ANYEXT sources are never vcc
44/// bank. A non-boolean source (such as a truncate from a 1-bit load from
45/// memory) will require a copy to the VCC bank which will require clearing the
46/// high bits and inserting a compare.
47///
48/// \par Constant bus restriction
49///
50/// VALU instructions have a limitation known as the constant bus
51/// restriction. Most VALU instructions can use SGPR operands, but may read at
52/// most 1 SGPR or constant literal value (this to 2 in gfx10 for most
53/// instructions). This is one unique SGPR, so the same SGPR may be used for
54/// multiple operands. From a register bank perspective, any combination of
55/// operands should be legal as an SGPR, but this is contextually dependent on
56/// the SGPR operands all being the same register. There is therefore optimal to
57/// choose the SGPR with the most uses to minimize the number of copies.
58///
59/// We avoid trying to solve this problem in RegBankSelect. Any VALU G_*
60/// operation should have its source operands all mapped to VGPRs (except for
61/// VCC), inserting copies from any SGPR operands. This the most trivial legal
62/// mapping. Anything beyond the simplest 1:1 instruction selection would be too
63/// complicated to solve here. Every optimization pattern or instruction
64/// selected to multiple outputs would have to enforce this rule, and there
65/// would be additional complexity in tracking this rule for every G_*
66/// operation. By forcing all inputs to VGPRs, it also simplifies the task of
67/// picking the optimal operand combination from a post-isel optimization pass.
68///
69//===----------------------------------------------------------------------===//
70
72
74#include "AMDGPUInstrInfo.h"
75#include "AMDGPULaneMaskUtils.h"
76#include "GCNSubtarget.h"
78#include "SIRegisterInfo.h"
84#include "llvm/IR/IntrinsicsAMDGPU.h"
85
86#define GET_TARGET_REGBANK_IMPL
87#include "AMDGPUGenRegisterBank.inc"
88
89// This file will be TableGen'ed at some point.
90#include "AMDGPUGenRegisterBankInfo.def"
91
92using namespace llvm;
93using namespace MIPatternMatch;
94
95namespace {
96
97// Observer to apply a register bank to new registers created by LegalizerHelper.
98class ApplyRegBankMapping final : public GISelChangeObserver {
99private:
101 const AMDGPURegisterBankInfo &RBI;
103 const RegisterBank *NewBank;
105
106public:
107 ApplyRegBankMapping(MachineIRBuilder &B, const AMDGPURegisterBankInfo &RBI_,
108 MachineRegisterInfo &MRI_, const RegisterBank *RB)
109 : B(B), RBI(RBI_), MRI(MRI_), NewBank(RB) {
110 assert(!B.isObservingChanges());
111 B.setChangeObserver(*this);
112 }
113
114 ~ApplyRegBankMapping() override {
115 for (MachineInstr *MI : NewInsts)
116 applyBank(*MI);
117
118 B.stopObservingChanges();
119 }
120
121 /// Set any registers that don't have a set register class or bank to SALU.
122 void applyBank(MachineInstr &MI) {
123 const unsigned Opc = MI.getOpcode();
124 if (Opc == AMDGPU::G_ANYEXT || Opc == AMDGPU::G_ZEXT ||
125 Opc == AMDGPU::G_SEXT) {
126 // LegalizerHelper wants to use the basic legalization artifacts when
127 // widening etc. We don't handle selection with vcc in artifact sources,
128 // so we need to use a select instead to handle these properly.
129 Register DstReg = MI.getOperand(0).getReg();
130 Register SrcReg = MI.getOperand(1).getReg();
131 const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, MRI, *RBI.TRI);
132 if (SrcBank == &AMDGPU::VCCRegBank) {
133 const LLT S32 = LLT::scalar(32);
134 assert(MRI.getType(SrcReg) == LLT::scalar(1));
135 assert(MRI.getType(DstReg) == S32);
136 assert(NewBank == &AMDGPU::VGPRRegBank);
137
138 // Replace the extension with a select, which really uses the boolean
139 // source.
140 B.setInsertPt(*MI.getParent(), MI);
141
142 auto True = B.buildConstant(S32, Opc == AMDGPU::G_SEXT ? -1 : 1);
143 auto False = B.buildConstant(S32, 0);
144 B.buildSelect(DstReg, SrcReg, True, False);
145 MRI.setRegBank(True.getReg(0), *NewBank);
146 MRI.setRegBank(False.getReg(0), *NewBank);
147 MI.eraseFromParent();
148 }
149
150 assert(!MRI.getRegClassOrRegBank(DstReg));
151 MRI.setRegBank(DstReg, *NewBank);
152 return;
153 }
154
155#ifndef NDEBUG
156 if (Opc == AMDGPU::G_TRUNC) {
157 Register DstReg = MI.getOperand(0).getReg();
158 const RegisterBank *DstBank = RBI.getRegBank(DstReg, MRI, *RBI.TRI);
159 assert(DstBank != &AMDGPU::VCCRegBank);
160 }
161#endif
162
163 for (MachineOperand &Op : MI.operands()) {
164 if (!Op.isReg())
165 continue;
166
167 // We may see physical registers if building a real MI
168 Register Reg = Op.getReg();
169 if (Reg.isPhysical() || MRI.getRegClassOrRegBank(Reg))
170 continue;
171
172 const RegisterBank *RB = NewBank;
173 if (MRI.getType(Reg) == LLT::scalar(1)) {
174 assert(NewBank == &AMDGPU::VGPRRegBank &&
175 "s1 operands should only be used for vector bools");
176 assert((MI.getOpcode() != AMDGPU::G_TRUNC &&
177 MI.getOpcode() != AMDGPU::G_ANYEXT) &&
178 "not expecting legalization artifacts here");
179 RB = &AMDGPU::VCCRegBank;
180 }
181
182 MRI.setRegBank(Reg, *RB);
183 }
184 }
185
186 void erasingInstr(MachineInstr &MI) override {}
187
188 void createdInstr(MachineInstr &MI) override {
189 // At this point, the instruction was just inserted and has no operands.
190 NewInsts.push_back(&MI);
191 }
192
193 void changingInstr(MachineInstr &MI) override {}
194 void changedInstr(MachineInstr &MI) override {
195 // FIXME: In principle we should probably add the instruction to NewInsts,
196 // but the way the LegalizerHelper uses the observer, we will always see the
197 // registers we need to set the regbank on also referenced in a new
198 // instruction.
199 }
200};
201
202} // anonymous namespace
203
205 : Subtarget(ST), TRI(Subtarget.getRegisterInfo()),
206 TII(Subtarget.getInstrInfo()) {
207
208 // HACK: Until this is fully tablegen'd.
209 static llvm::once_flag InitializeRegisterBankFlag;
210
211 static auto InitializeRegisterBankOnce = [this]() {
212 assert(&getRegBank(AMDGPU::SGPRRegBankID) == &AMDGPU::SGPRRegBank &&
213 &getRegBank(AMDGPU::VGPRRegBankID) == &AMDGPU::VGPRRegBank &&
214 &getRegBank(AMDGPU::AGPRRegBankID) == &AMDGPU::AGPRRegBank);
215 (void)this;
216 };
217
218 llvm::call_once(InitializeRegisterBankFlag, InitializeRegisterBankOnce);
219}
220
221static bool isVectorRegisterBank(const RegisterBank &Bank) {
222 unsigned BankID = Bank.getID();
223 return BankID == AMDGPU::VGPRRegBankID || BankID == AMDGPU::AGPRRegBankID;
224}
225
227 return RB != &AMDGPU::SGPRRegBank;
228}
229
231 const RegisterBank &Src,
232 TypeSize Size) const {
233 // TODO: Should there be a UniformVGPRRegBank which can use readfirstlane?
234 if (Dst.getID() == AMDGPU::SGPRRegBankID &&
235 (isVectorRegisterBank(Src) || Src.getID() == AMDGPU::VCCRegBankID)) {
236 return std::numeric_limits<unsigned>::max();
237 }
238
239 // Bool values are tricky, because the meaning is based on context. The SCC
240 // and VCC banks are for the natural scalar and vector conditions produced by
241 // a compare.
242 //
243 // Legalization doesn't know about the necessary context, so an s1 use may
244 // have been a truncate from an arbitrary value, in which case a copy (lowered
245 // as a compare with 0) needs to be inserted.
246 if (Size == 1 &&
247 (Dst.getID() == AMDGPU::SGPRRegBankID) &&
248 (isVectorRegisterBank(Src) ||
249 Src.getID() == AMDGPU::SGPRRegBankID ||
250 Src.getID() == AMDGPU::VCCRegBankID))
251 return std::numeric_limits<unsigned>::max();
252
253 // There is no direct copy between AGPRs.
254 if (Dst.getID() == AMDGPU::AGPRRegBankID &&
255 Src.getID() == AMDGPU::AGPRRegBankID)
256 return 4;
257
258 return RegisterBankInfo::copyCost(Dst, Src, Size);
259}
260
262 const ValueMapping &ValMapping,
263 const RegisterBank *CurBank) const {
264 // Check if this is a breakdown for G_LOAD to move the pointer from SGPR to
265 // VGPR.
266 // FIXME: Is there a better way to do this?
267 if (ValMapping.NumBreakDowns >= 2 || ValMapping.BreakDown[0].Length >= 64)
268 return 10; // This is expensive.
269
270 assert(ValMapping.NumBreakDowns == 2 &&
271 ValMapping.BreakDown[0].Length == 32 &&
272 ValMapping.BreakDown[0].StartIdx == 0 &&
273 ValMapping.BreakDown[1].Length == 32 &&
274 ValMapping.BreakDown[1].StartIdx == 32 &&
275 ValMapping.BreakDown[0].RegBank == ValMapping.BreakDown[1].RegBank);
276
277 // 32-bit extract of a 64-bit value is just access of a subregister, so free.
278 // TODO: Cost of 0 hits assert, though it's not clear it's what we really
279 // want.
280
281 // TODO: 32-bit insert to a 64-bit SGPR may incur a non-free copy due to SGPR
282 // alignment restrictions, but this probably isn't important.
283 return 1;
284}
285
286const RegisterBank &
288 LLT Ty) const {
289 // We promote real scalar booleans to SReg_32. Any SGPR using s1 is really a
290 // VCC-like use.
291 if (TRI->isSGPRClass(&RC)) {
292 // FIXME: This probably came from a copy from a physical register, which
293 // should be inferable from the copied to-type. We don't have many boolean
294 // physical register constraints so just assume a normal SGPR for now.
295 if (!Ty.isValid())
296 return AMDGPU::SGPRRegBank;
297
298 return Ty == LLT::scalar(1) ? AMDGPU::VCCRegBank : AMDGPU::SGPRRegBank;
299 }
300
301 return TRI->isAGPRClass(&RC) ? AMDGPU::AGPRRegBank : AMDGPU::VGPRRegBank;
302}
303
304template <unsigned NumOps>
307 const MachineInstr &MI, const MachineRegisterInfo &MRI,
308 const std::array<unsigned, NumOps> RegSrcOpIdx,
310
311 InstructionMappings AltMappings;
312
314
315 unsigned Sizes[NumOps];
316 for (unsigned I = 0; I < NumOps; ++I) {
317 Register Reg = MI.getOperand(RegSrcOpIdx[I]).getReg();
318 Sizes[I] = getSizeInBits(Reg, MRI, *TRI);
319 }
320
321 for (unsigned I = 0, E = MI.getNumExplicitDefs(); I != E; ++I) {
322 unsigned SizeI = getSizeInBits(MI.getOperand(I).getReg(), MRI, *TRI);
323 Operands[I] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, SizeI);
324 }
325
326 // getInstrMapping's default mapping uses ID 1, so start at 2.
327 unsigned MappingID = 2;
328 for (const auto &Entry : Table) {
329 for (unsigned I = 0; I < NumOps; ++I) {
330 int OpIdx = RegSrcOpIdx[I];
331 Operands[OpIdx] = AMDGPU::getValueMapping(Entry.RegBanks[I], Sizes[I]);
332 }
333
334 AltMappings.push_back(&getInstructionMapping(MappingID++, Entry.Cost,
336 Operands.size()));
337 }
338
339 return AltMappings;
340}
341
344 const MachineInstr &MI, const MachineRegisterInfo &MRI) const {
346 case Intrinsic::amdgcn_readlane: {
347 static const OpRegBankEntry<3> Table[2] = {
348 // Perfectly legal.
349 { { AMDGPU::SGPRRegBankID, AMDGPU::VGPRRegBankID, AMDGPU::SGPRRegBankID }, 1 },
350
351 // Need a readfirstlane for the index.
352 { { AMDGPU::SGPRRegBankID, AMDGPU::VGPRRegBankID, AMDGPU::VGPRRegBankID }, 2 }
353 };
354
355 const std::array<unsigned, 3> RegSrcOpIdx = { { 0, 2, 3 } };
356 return addMappingFromTable<3>(MI, MRI, RegSrcOpIdx, Table);
357 }
358 case Intrinsic::amdgcn_writelane: {
359 static const OpRegBankEntry<4> Table[4] = {
360 // Perfectly legal.
361 { { AMDGPU::VGPRRegBankID, AMDGPU::SGPRRegBankID, AMDGPU::SGPRRegBankID, AMDGPU::VGPRRegBankID }, 1 },
362
363 // Need readfirstlane of first op
364 { { AMDGPU::VGPRRegBankID, AMDGPU::VGPRRegBankID, AMDGPU::SGPRRegBankID, AMDGPU::VGPRRegBankID }, 2 },
365
366 // Need readfirstlane of second op
367 { { AMDGPU::VGPRRegBankID, AMDGPU::SGPRRegBankID, AMDGPU::VGPRRegBankID, AMDGPU::VGPRRegBankID }, 2 },
368
369 // Need readfirstlane of both ops
370 { { AMDGPU::VGPRRegBankID, AMDGPU::VGPRRegBankID, AMDGPU::VGPRRegBankID, AMDGPU::VGPRRegBankID }, 3 }
371 };
372
373 // rsrc, voffset, offset
374 const std::array<unsigned, 4> RegSrcOpIdx = { { 0, 2, 3, 4 } };
375 return addMappingFromTable<4>(MI, MRI, RegSrcOpIdx, Table);
376 }
377 default:
379 }
380}
381
384 const MachineInstr &MI, const MachineRegisterInfo &MRI) const {
385
387 case Intrinsic::amdgcn_s_buffer_load:
388 case Intrinsic::amdgcn_ptr_s_buffer_load: {
389 static const OpRegBankEntry<2> Table[4] = {
390 // Perfectly legal.
391 { { AMDGPU::SGPRRegBankID, AMDGPU::SGPRRegBankID }, 1 },
392
393 // Only need 1 register in loop
394 { { AMDGPU::SGPRRegBankID, AMDGPU::VGPRRegBankID }, 300 },
395
396 // Have to waterfall the resource.
397 { { AMDGPU::VGPRRegBankID, AMDGPU::SGPRRegBankID }, 1000 },
398
399 // Have to waterfall the resource, and the offset.
400 { { AMDGPU::VGPRRegBankID, AMDGPU::VGPRRegBankID }, 1500 }
401 };
402
403 // rsrc, offset
404 const std::array<unsigned, 2> RegSrcOpIdx = { { 2, 3 } };
405 return addMappingFromTable<2>(MI, MRI, RegSrcOpIdx, Table);
406 }
407 case Intrinsic::amdgcn_ds_ordered_add:
408 case Intrinsic::amdgcn_ds_ordered_swap: {
409 // VGPR = M0, VGPR
410 static const OpRegBankEntry<3> Table[2] = {
411 // Perfectly legal.
412 { { AMDGPU::VGPRRegBankID, AMDGPU::SGPRRegBankID, AMDGPU::VGPRRegBankID }, 1 },
413
414 // Need a readfirstlane for m0
415 { { AMDGPU::VGPRRegBankID, AMDGPU::VGPRRegBankID, AMDGPU::VGPRRegBankID }, 2 }
416 };
417
418 const std::array<unsigned, 3> RegSrcOpIdx = { { 0, 2, 3 } };
419 return addMappingFromTable<3>(MI, MRI, RegSrcOpIdx, Table);
420 }
421 case Intrinsic::amdgcn_s_sendmsg:
422 case Intrinsic::amdgcn_s_sendmsghalt: {
423 // FIXME: Should have no register for immediate
424 static const OpRegBankEntry<1> Table[2] = {
425 // Perfectly legal.
426 { { AMDGPU::SGPRRegBankID }, 1 },
427
428 // Need readlane
429 { { AMDGPU::VGPRRegBankID }, 3 }
430 };
431
432 const std::array<unsigned, 1> RegSrcOpIdx = { { 2 } };
433 return addMappingFromTable<1>(MI, MRI, RegSrcOpIdx, Table);
434 }
435 default:
437 }
438}
439
440// FIXME: Returns uniform if there's no source value information. This is
441// probably wrong.
443 if (!MI.hasOneMemOperand())
444 return false;
445
446 const MachineMemOperand *MMO = *MI.memoperands_begin();
447 const unsigned AS = MMO->getAddrSpace();
448 const bool IsConst = AS == AMDGPUAS::CONSTANT_ADDRESS ||
450 const unsigned MemSize = 8 * MMO->getSize().getValue();
451
452 // Require 4-byte alignment.
453 return (MMO->getAlign() >= Align(4) ||
454 (Subtarget.hasScalarSubwordLoads() &&
455 ((MemSize == 16 && MMO->getAlign() >= Align(2)) ||
456 (MemSize == 8 && MMO->getAlign() >= Align(1))))) &&
457 // Can't do a scalar atomic load.
458 !MMO->isAtomic() &&
459 // Don't use scalar loads for volatile accesses to non-constant address
460 // spaces.
461 (IsConst || !MMO->isVolatile()) &&
462 // Memory must be known constant, or not written before this load.
463 (IsConst || MMO->isInvariant() || (MMO->getFlags() & MONoClobber)) &&
465}
466
469 const MachineInstr &MI) const {
470
471 const MachineFunction &MF = *MI.getMF();
472 const MachineRegisterInfo &MRI = MF.getRegInfo();
473
474
475 InstructionMappings AltMappings;
476 switch (MI.getOpcode()) {
477 case TargetOpcode::G_CONSTANT:
478 case TargetOpcode::G_IMPLICIT_DEF: {
479 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
480 if (Size == 1) {
481 static const OpRegBankEntry<1> Table[3] = {
482 { { AMDGPU::VGPRRegBankID }, 1 },
483 { { AMDGPU::SGPRRegBankID }, 1 },
484 { { AMDGPU::VCCRegBankID }, 1 }
485 };
486
487 return addMappingFromTable<1>(MI, MRI, {{ 0 }}, Table);
488 }
489
490 [[fallthrough]];
491 }
492 case TargetOpcode::G_FCONSTANT:
493 case TargetOpcode::G_FRAME_INDEX:
494 case TargetOpcode::G_GLOBAL_VALUE: {
495 static const OpRegBankEntry<1> Table[2] = {
496 { { AMDGPU::VGPRRegBankID }, 1 },
497 { { AMDGPU::SGPRRegBankID }, 1 }
498 };
499
500 return addMappingFromTable<1>(MI, MRI, {{ 0 }}, Table);
501 }
502 case TargetOpcode::G_AND:
503 case TargetOpcode::G_OR:
504 case TargetOpcode::G_XOR: {
505 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
506
507 if (Size == 1) {
508 // s_{and|or|xor}_b32 set scc when the result of the 32-bit op is not 0.
509 const InstructionMapping &SCCMapping = getInstructionMapping(
510 1, 1, getOperandsMapping(
511 {AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32),
512 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32),
513 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32)}),
514 3); // Num Operands
515 AltMappings.push_back(&SCCMapping);
516
517 const InstructionMapping &VCCMapping0 = getInstructionMapping(
518 2, 1, getOperandsMapping(
519 {AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, Size),
520 AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, Size),
521 AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, Size)}),
522 3); // Num Operands
523 AltMappings.push_back(&VCCMapping0);
524 return AltMappings;
525 }
526
527 if (Size != 64)
528 break;
529
530 const InstructionMapping &SSMapping = getInstructionMapping(
531 1, 1, getOperandsMapping(
532 {AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size),
533 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size),
534 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size)}),
535 3); // Num Operands
536 AltMappings.push_back(&SSMapping);
537
538 const InstructionMapping &VVMapping = getInstructionMapping(
539 2, 2, getOperandsMapping(
540 {AMDGPU::getValueMappingSGPR64Only(AMDGPU::VGPRRegBankID, Size),
541 AMDGPU::getValueMappingSGPR64Only(AMDGPU::VGPRRegBankID, Size),
542 AMDGPU::getValueMappingSGPR64Only(AMDGPU::VGPRRegBankID, Size)}),
543 3); // Num Operands
544 AltMappings.push_back(&VVMapping);
545 break;
546 }
547 case TargetOpcode::G_LOAD:
548 case TargetOpcode::G_ZEXTLOAD:
549 case TargetOpcode::G_SEXTLOAD: {
550 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
551 LLT PtrTy = MRI.getType(MI.getOperand(1).getReg());
552 unsigned PtrSize = PtrTy.getSizeInBits();
553 unsigned AS = PtrTy.getAddressSpace();
554
558 const InstructionMapping &SSMapping = getInstructionMapping(
559 1, 1, getOperandsMapping(
560 {AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size),
561 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, PtrSize)}),
562 2); // Num Operands
563 AltMappings.push_back(&SSMapping);
564 }
565
566 const InstructionMapping &VVMapping = getInstructionMapping(
567 2, 1,
569 {AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size),
570 AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, PtrSize)}),
571 2); // Num Operands
572 AltMappings.push_back(&VVMapping);
573
574 // It may be possible to have a vgpr = load sgpr mapping here, because
575 // the mubuf instructions support this kind of load, but probably for only
576 // gfx7 and older. However, the addressing mode matching in the instruction
577 // selector should be able to do a better job of detecting and selecting
578 // these kinds of loads from the vgpr = load vgpr mapping.
579
580 return AltMappings;
581
582 }
583 case TargetOpcode::G_SELECT: {
584 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
585 const InstructionMapping &SSMapping = getInstructionMapping(1, 1,
586 getOperandsMapping({AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size),
587 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 1),
588 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size),
589 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size)}),
590 4); // Num Operands
591 AltMappings.push_back(&SSMapping);
592
593 const InstructionMapping &VVMapping = getInstructionMapping(2, 1,
594 getOperandsMapping({AMDGPU::getValueMappingSGPR64Only(AMDGPU::VGPRRegBankID, Size),
595 AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1),
596 AMDGPU::getValueMappingSGPR64Only(AMDGPU::VGPRRegBankID, Size),
597 AMDGPU::getValueMappingSGPR64Only(AMDGPU::VGPRRegBankID, Size)}),
598 4); // Num Operands
599 AltMappings.push_back(&VVMapping);
600
601 return AltMappings;
602 }
603 case TargetOpcode::G_UADDE:
604 case TargetOpcode::G_USUBE:
605 case TargetOpcode::G_SADDE:
606 case TargetOpcode::G_SSUBE: {
607 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
608 const InstructionMapping &SSMapping = getInstructionMapping(1, 1,
610 {AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size),
611 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 1),
612 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size),
613 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size),
614 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 1)}),
615 5); // Num Operands
616 AltMappings.push_back(&SSMapping);
617
618 const InstructionMapping &VVMapping = getInstructionMapping(2, 1,
619 getOperandsMapping({AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size),
620 AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1),
621 AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size),
622 AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size),
623 AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1)}),
624 5); // Num Operands
625 AltMappings.push_back(&VVMapping);
626 return AltMappings;
627 }
628 case AMDGPU::G_BRCOND: {
629 assert(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 1);
630
631 // TODO: Change type to 32 for scalar
633 1, 1, getOperandsMapping(
634 {AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 1), nullptr}),
635 2); // Num Operands
636 AltMappings.push_back(&SMapping);
637
639 1, 1, getOperandsMapping(
640 {AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1), nullptr }),
641 2); // Num Operands
642 AltMappings.push_back(&VMapping);
643 return AltMappings;
644 }
645 case AMDGPU::G_INTRINSIC:
646 case AMDGPU::G_INTRINSIC_CONVERGENT:
648 case AMDGPU::G_INTRINSIC_W_SIDE_EFFECTS:
649 case AMDGPU::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
651 default:
652 break;
653 }
655}
656
660 LLT HalfTy,
661 Register Reg) const {
662 assert(HalfTy.getSizeInBits() == 32);
663 MachineRegisterInfo *MRI = B.getMRI();
664 Register LoLHS = MRI->createGenericVirtualRegister(HalfTy);
665 Register HiLHS = MRI->createGenericVirtualRegister(HalfTy);
666 const RegisterBank *Bank = getRegBank(Reg, *MRI, *TRI);
667 MRI->setRegBank(LoLHS, *Bank);
668 MRI->setRegBank(HiLHS, *Bank);
669
670 Regs.push_back(LoLHS);
671 Regs.push_back(HiLHS);
672
673 B.buildInstr(AMDGPU::G_UNMERGE_VALUES)
674 .addDef(LoLHS)
675 .addDef(HiLHS)
676 .addUse(Reg);
677}
678
679/// Replace the current type each register in \p Regs has with \p NewTy
681 LLT NewTy) {
682 for (Register Reg : Regs) {
683 assert(MRI.getType(Reg).getSizeInBits() == NewTy.getSizeInBits());
684 MRI.setType(Reg, NewTy);
685 }
686}
687
689 if (Ty.isVector()) {
690 assert(Ty.getElementCount().isKnownMultipleOf(2));
691 return LLT::scalarOrVector(Ty.getElementCount().divideCoefficientBy(2),
692 Ty.getElementType());
693 }
694
695 assert(Ty.getScalarSizeInBits() % 2 == 0);
696 return LLT::scalar(Ty.getScalarSizeInBits() / 2);
697}
698
699// Build one or more V_READFIRSTLANE_B32 instructions to move the given vector
700// source value into a scalar register.
703 Register Src) const {
704 LLT Ty = MRI.getType(Src);
705 const RegisterBank *Bank = getRegBank(Src, MRI, *TRI);
706
707 if (Bank == &AMDGPU::SGPRRegBank)
708 return Src;
709
710 unsigned Bits = Ty.getSizeInBits();
711 assert(Bits % 32 == 0);
712
713 if (Bank != &AMDGPU::VGPRRegBank) {
714 // We need to copy from AGPR to VGPR
715 Src = B.buildCopy(Ty, Src).getReg(0);
716 MRI.setRegBank(Src, AMDGPU::VGPRRegBank);
717 }
718
719 LLT S32 = LLT::scalar(32);
720 unsigned NumParts = Bits / 32;
723
724 if (Bits == 32) {
725 SrcParts.push_back(Src);
726 } else {
727 auto Unmerge = B.buildUnmerge(S32, Src);
728 for (unsigned i = 0; i < NumParts; ++i)
729 SrcParts.push_back(Unmerge.getReg(i));
730 }
731
732 for (unsigned i = 0; i < NumParts; ++i) {
733 Register SrcPart = SrcParts[i];
734 Register DstPart = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
735 MRI.setType(DstPart, NumParts == 1 ? Ty : S32);
736
737 const TargetRegisterClass *Constrained =
738 constrainGenericRegister(SrcPart, AMDGPU::VGPR_32RegClass, MRI);
739 (void)Constrained;
740 assert(Constrained && "Failed to constrain readfirstlane src reg");
741
742 B.buildInstr(AMDGPU::V_READFIRSTLANE_B32, {DstPart}, {SrcPart});
743
744 DstParts.push_back(DstPart);
745 }
746
747 if (Bits == 32)
748 return DstParts[0];
749
750 Register Dst = B.buildMergeLikeInstr(Ty, DstParts).getReg(0);
751 MRI.setRegBank(Dst, AMDGPU::SGPRRegBank);
752 return Dst;
753}
754
755/// Legalize instruction \p MI where operands in \p OpIndices must be SGPRs. If
756/// any of the required SGPR operands are VGPRs, perform a waterfall loop to
757/// execute the instruction for each unique combination of values in all lanes
758/// in the wave. The block will be split such that rest of the instructions are
759/// moved to a new block.
760///
761/// Essentially performs this loop:
762//
763/// Save Execution Mask
764/// For (Lane : Wavefront) {
765/// Enable Lane, Disable all other lanes
766/// SGPR = read SGPR value for current lane from VGPR
767/// VGPRResult[Lane] = use_op SGPR
768/// }
769/// Restore Execution Mask
770///
771/// There is additional complexity to try for compare values to identify the
772/// unique values used.
775 SmallSet<Register, 4> &SGPROperandRegs) const {
776 // Track use registers which have already been expanded with a readfirstlane
777 // sequence. This may have multiple uses if moving a sequence.
778 DenseMap<Register, Register> WaterfalledRegMap;
779
780 MachineBasicBlock &MBB = B.getMBB();
781 MachineFunction *MF = &B.getMF();
782
783 const TargetRegisterClass *WaveRC = TRI->getWaveMaskRegClass();
784 const AMDGPU::LaneMaskConstants &LMC =
786
787#ifndef NDEBUG
788 const int OrigRangeSize = std::distance(Range.begin(), Range.end());
789#endif
790
791 MachineRegisterInfo &MRI = *B.getMRI();
792 Register SaveExecReg = MRI.createVirtualRegister(WaveRC);
793 Register InitSaveExecReg = MRI.createVirtualRegister(WaveRC);
794
795 // Don't bother using generic instructions/registers for the exec mask.
796 B.buildInstr(TargetOpcode::IMPLICIT_DEF)
797 .addDef(InitSaveExecReg);
798
799 Register PhiExec = MRI.createVirtualRegister(WaveRC);
800 Register NewExec = MRI.createVirtualRegister(WaveRC);
801
802 // To insert the loop we need to split the block. Move everything before this
803 // point to a new block, and insert a new empty block before this instruction.
806 MachineBasicBlock *RemainderBB = MF->CreateMachineBasicBlock();
807 MachineBasicBlock *RestoreExecBB = MF->CreateMachineBasicBlock();
809 ++MBBI;
810 MF->insert(MBBI, LoopBB);
811 MF->insert(MBBI, BodyBB);
812 MF->insert(MBBI, RestoreExecBB);
813 MF->insert(MBBI, RemainderBB);
814
815 LoopBB->addSuccessor(BodyBB);
816 BodyBB->addSuccessor(RestoreExecBB);
817 BodyBB->addSuccessor(LoopBB);
818
819 // Move the rest of the block into a new block.
821 RemainderBB->splice(RemainderBB->begin(), &MBB, Range.end(), MBB.end());
822
823 MBB.addSuccessor(LoopBB);
824 RestoreExecBB->addSuccessor(RemainderBB);
825
826 B.setInsertPt(*LoopBB, LoopBB->end());
827
828 B.buildInstr(TargetOpcode::PHI)
829 .addDef(PhiExec)
830 .addReg(InitSaveExecReg)
831 .addMBB(&MBB)
832 .addReg(NewExec)
833 .addMBB(BodyBB);
834
835 const DebugLoc &DL = B.getDL();
836
837 MachineInstr &FirstInst = *Range.begin();
838
839 // Move the instruction into the loop body. Note we moved everything after
840 // Range.end() already into a new block, so Range.end() is no longer valid.
841 BodyBB->splice(BodyBB->end(), &MBB, Range.begin(), MBB.end());
842
843 // Figure out the iterator range after splicing the instructions.
844 MachineBasicBlock::iterator NewBegin = FirstInst.getIterator();
845 auto NewEnd = BodyBB->end();
846
847 B.setMBB(*LoopBB);
848
849 LLT S1 = LLT::scalar(1);
850 Register CondReg;
851
852 assert(std::distance(NewBegin, NewEnd) == OrigRangeSize);
853
854 for (MachineInstr &MI : make_range(NewBegin, NewEnd)) {
855 for (MachineOperand &Op : MI.all_uses()) {
856 Register OldReg = Op.getReg();
857 if (!SGPROperandRegs.count(OldReg))
858 continue;
859
860 // See if we already processed this register in another instruction in the
861 // sequence.
862 auto OldVal = WaterfalledRegMap.find(OldReg);
863 if (OldVal != WaterfalledRegMap.end()) {
864 Op.setReg(OldVal->second);
865 continue;
866 }
867
868 Register OpReg = Op.getReg();
869 LLT OpTy = MRI.getType(OpReg);
870
871 const RegisterBank *OpBank = getRegBank(OpReg, MRI, *TRI);
872 if (OpBank != &AMDGPU::VGPRRegBank) {
873 // Insert copy from AGPR to VGPR before the loop.
874 B.setMBB(MBB);
875 OpReg = B.buildCopy(OpTy, OpReg).getReg(0);
876 MRI.setRegBank(OpReg, AMDGPU::VGPRRegBank);
877 B.setMBB(*LoopBB);
878 }
879
880 Register CurrentLaneReg = buildReadFirstLane(B, MRI, OpReg);
881
882 // Build the comparison(s).
883 unsigned OpSize = OpTy.getSizeInBits();
884 bool Is64 = OpSize % 64 == 0;
885 unsigned PartSize = Is64 ? 64 : 32;
886 LLT PartTy = LLT::scalar(PartSize);
887 unsigned NumParts = OpSize / PartSize;
889 SmallVector<Register, 8> CurrentLaneParts;
890
891 if (NumParts == 1) {
892 OpParts.push_back(OpReg);
893 CurrentLaneParts.push_back(CurrentLaneReg);
894 } else {
895 auto UnmergeOp = B.buildUnmerge(PartTy, OpReg);
896 auto UnmergeCurrentLane = B.buildUnmerge(PartTy, CurrentLaneReg);
897 for (unsigned i = 0; i < NumParts; ++i) {
898 OpParts.push_back(UnmergeOp.getReg(i));
899 CurrentLaneParts.push_back(UnmergeCurrentLane.getReg(i));
900 MRI.setRegBank(OpParts[i], AMDGPU::VGPRRegBank);
901 MRI.setRegBank(CurrentLaneParts[i], AMDGPU::SGPRRegBank);
902 }
903 }
904
905 for (unsigned i = 0; i < NumParts; ++i) {
906 auto CmpReg = B.buildICmp(CmpInst::ICMP_EQ, S1, CurrentLaneParts[i],
907 OpParts[i]).getReg(0);
908 MRI.setRegBank(CmpReg, AMDGPU::VCCRegBank);
909
910 if (!CondReg) {
911 CondReg = CmpReg;
912 } else {
913 CondReg = B.buildAnd(S1, CondReg, CmpReg).getReg(0);
914 MRI.setRegBank(CondReg, AMDGPU::VCCRegBank);
915 }
916 }
917
918 Op.setReg(CurrentLaneReg);
919
920 // Make sure we don't re-process this register again.
921 WaterfalledRegMap.insert(std::pair(OldReg, Op.getReg()));
922 }
923 }
924
925 // The ballot becomes a no-op during instruction selection.
926 CondReg = B.buildIntrinsic(Intrinsic::amdgcn_ballot,
927 {LLT::scalar(Subtarget.isWave32() ? 32 : 64)})
928 .addReg(CondReg)
929 .getReg(0);
930 MRI.setRegClass(CondReg, WaveRC);
931
932 // Update EXEC, save the original EXEC value to VCC.
933 B.buildInstr(LMC.AndSaveExecOpc)
934 .addDef(NewExec)
935 .addReg(CondReg)
936 .setOperandDead(3);
937
938 MRI.setSimpleHint(NewExec, CondReg);
939
940 B.setInsertPt(*BodyBB, BodyBB->end());
941
942 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
943 B.buildInstr(LMC.XorTermOpc)
944 .addDef(LMC.ExecReg)
945 .addReg(LMC.ExecReg)
946 .addReg(NewExec)
947 .setOperandDead(3);
948
949 // XXX - s_xor_b64 sets scc to 1 if the result is nonzero, so can we use
950 // s_cbranch_scc0?
951
952 // Loop back to V_READFIRSTLANE_B32 if there are still variants to cover.
953 B.buildInstr(AMDGPU::SI_WATERFALL_LOOP).addMBB(LoopBB);
954
955 // Save the EXEC mask before the loop.
956 BuildMI(MBB, MBB.end(), DL, TII->get(LMC.MovOpc), SaveExecReg)
957 .addReg(LMC.ExecReg);
958
959 // Restore the EXEC mask after the loop.
960 B.setMBB(*RestoreExecBB);
961 B.buildInstr(LMC.MovTermOpc).addDef(LMC.ExecReg).addReg(SaveExecReg);
962
963 // Set the insert point after the original instruction, so any new
964 // instructions will be in the remainder.
965 B.setInsertPt(*RemainderBB, RemainderBB->begin());
966
967 return true;
968}
969
970// Return any unique registers used by \p MI at \p OpIndices that need to be
971// handled in a waterfall loop. Returns these registers in \p
972// SGPROperandRegs. Returns true if there are any operands to handle and a
973// waterfall loop is necessary.
975 SmallSet<Register, 4> &SGPROperandRegs, MachineInstr &MI,
976 MachineRegisterInfo &MRI, ArrayRef<unsigned> OpIndices) const {
977 for (unsigned Op : OpIndices) {
978 assert(MI.getOperand(Op).isUse());
979 Register Reg = MI.getOperand(Op).getReg();
980 const RegisterBank *OpBank = getRegBank(Reg, MRI, *TRI);
981 if (OpBank->getID() != AMDGPU::SGPRRegBankID)
982 SGPROperandRegs.insert(Reg);
983 }
984
985 // No operands need to be replaced, so no need to loop.
986 return !SGPROperandRegs.empty();
987}
988
991 // Use a set to avoid extra readfirstlanes in the case where multiple operands
992 // are the same register.
993 SmallSet<Register, 4> SGPROperandRegs;
994
995 if (!collectWaterfallOperands(SGPROperandRegs, MI, *B.getMRI(), OpIndices))
996 return false;
997
998 MachineBasicBlock::iterator I = MI.getIterator();
999 return executeInWaterfallLoop(B, make_range(I, std::next(I)),
1000 SGPROperandRegs);
1001}
1002
1003// Legalize an operand that must be an SGPR by inserting a readfirstlane.
1005 MachineIRBuilder &B, MachineInstr &MI, unsigned OpIdx) const {
1006 Register Reg = MI.getOperand(OpIdx).getReg();
1007 MachineRegisterInfo &MRI = *B.getMRI();
1008 const RegisterBank *Bank = getRegBank(Reg, MRI, *TRI);
1009 if (Bank == &AMDGPU::SGPRRegBank)
1010 return;
1011
1012 Reg = buildReadFirstLane(B, MRI, Reg);
1013 MI.getOperand(OpIdx).setReg(Reg);
1014}
1015
1016/// Split \p Ty into 2 pieces. The first will have \p FirstSize bits, and the
1017/// rest will be in the remainder.
1018static std::pair<LLT, LLT> splitUnequalType(LLT Ty, unsigned FirstSize) {
1019 unsigned TotalSize = Ty.getSizeInBits();
1020 if (!Ty.isVector())
1021 return {LLT::scalar(FirstSize), LLT::scalar(TotalSize - FirstSize)};
1022
1023 LLT EltTy = Ty.getElementType();
1024 unsigned EltSize = EltTy.getSizeInBits();
1025 assert(FirstSize % EltSize == 0);
1026
1027 unsigned FirstPartNumElts = FirstSize / EltSize;
1028 unsigned RemainderElts = (TotalSize - FirstSize) / EltSize;
1029
1030 return {LLT::scalarOrVector(ElementCount::getFixed(FirstPartNumElts), EltTy),
1031 LLT::scalarOrVector(ElementCount::getFixed(RemainderElts), EltTy)};
1032}
1033
1035 if (!Ty.isVector())
1036 return LLT::scalar(128);
1037
1038 LLT EltTy = Ty.getElementType();
1039 assert(128 % EltTy.getSizeInBits() == 0);
1040 return LLT::fixed_vector(128 / EltTy.getSizeInBits(), EltTy);
1041}
1042
1046 MachineInstr &MI) const {
1047 MachineRegisterInfo &MRI = *B.getMRI();
1048 Register DstReg = MI.getOperand(0).getReg();
1049 const LLT LoadTy = MRI.getType(DstReg);
1050 unsigned LoadSize = LoadTy.getSizeInBits();
1051 MachineMemOperand *MMO = *MI.memoperands_begin();
1052 const unsigned MaxNonSmrdLoadSize = 128;
1053
1054 const RegisterBank *DstBank =
1055 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
1056 if (DstBank == &AMDGPU::SGPRRegBank) {
1057 // There are some special cases that we need to look at for 32 bit and 96
1058 // bit SGPR loads otherwise we have nothing to do.
1059 if (LoadSize != 32 && (LoadSize != 96 || Subtarget.hasScalarDwordx3Loads()))
1060 return false;
1061
1062 const unsigned MemSize = 8 * MMO->getSize().getValue();
1063 // Scalar loads of size 8 or 16 bit with proper alignment may be widened to
1064 // 32 bit. Check to see if we need to widen the memory access, 8 or 16 bit
1065 // scalar loads should have a load size of 32 but memory access size of less
1066 // than 32.
1067 if (LoadSize == 32 &&
1068 (MemSize == 32 || LoadTy.isVector() || !isScalarLoadLegal(MI)))
1069 return false;
1070
1071 if (LoadSize == 32 &&
1072 ((MemSize == 8 && MMO->getAlign() >= Align(1)) ||
1073 (MemSize == 16 && MMO->getAlign() >= Align(2))) &&
1075 Subtarget.getGeneration() >= AMDGPUSubtarget::GFX12)
1076 return false;
1077
1078 Register PtrReg = MI.getOperand(1).getReg();
1079
1080 ApplyRegBankMapping ApplyBank(B, *this, MRI, DstBank);
1081
1082 if (LoadSize == 32) {
1083 // This is an extending load from a sub-dword size. Widen the memory
1084 // access size to 4 bytes and clear the extra high bits appropriately
1085 const LLT S32 = LLT::scalar(32);
1086 if (MI.getOpcode() == AMDGPU::G_SEXTLOAD) {
1087 // Must extend the sign bit into higher bits for a G_SEXTLOAD
1088 auto WideLoad = B.buildLoadFromOffset(S32, PtrReg, *MMO, 0);
1089 B.buildSExtInReg(MI.getOperand(0), WideLoad, MemSize);
1090 } else if (MI.getOpcode() == AMDGPU::G_ZEXTLOAD) {
1091 // Must extend zero into higher bits with an AND for a G_ZEXTLOAD
1092 auto WideLoad = B.buildLoadFromOffset(S32, PtrReg, *MMO, 0);
1093 B.buildZExtInReg(MI.getOperand(0), WideLoad, MemSize);
1094 } else
1095 // We do not need to touch the higher bits for regular loads.
1096 B.buildLoadFromOffset(MI.getOperand(0), PtrReg, *MMO, 0);
1097 } else {
1098 // 96-bit loads are only available for vector loads. We need to split this
1099 // into a 64-bit part, and 32 (unless we can widen to a 128-bit load).
1100 if (MMO->getAlign() < Align(16)) {
1101 LegalizerHelper Helper(B.getMF(), ApplyBank, B);
1102 LLT Part64, Part32;
1103 std::tie(Part64, Part32) = splitUnequalType(LoadTy, 64);
1104 if (Helper.reduceLoadStoreWidth(cast<GAnyLoad>(MI), 0, Part64) !=
1106 return false;
1107 return true;
1108 }
1109 LLT WiderTy = widen96To128(LoadTy);
1110 auto WideLoad = B.buildLoadFromOffset(WiderTy, PtrReg, *MMO, 0);
1111 if (WiderTy.isScalar()) {
1112 B.buildTrunc(MI.getOperand(0), WideLoad);
1113 } else {
1114 B.buildDeleteTrailingVectorElements(MI.getOperand(0).getReg(),
1115 WideLoad);
1116 }
1117 }
1118
1119 MI.eraseFromParent();
1120 return true;
1121 }
1122
1123 // 128-bit loads are supported for all instruction types.
1124 if (LoadSize <= MaxNonSmrdLoadSize)
1125 return false;
1126
1127 SmallVector<Register, 1> SrcRegs(OpdMapper.getVRegs(1));
1128
1129 if (SrcRegs.empty())
1130 SrcRegs.push_back(MI.getOperand(1).getReg());
1131
1132 // RegBankSelect only emits scalar types, so we need to reset the pointer
1133 // operand to a pointer type.
1134 Register BasePtrReg = SrcRegs[0];
1135 LLT PtrTy = MRI.getType(MI.getOperand(1).getReg());
1136 MRI.setType(BasePtrReg, PtrTy);
1137
1138 // The following are the loads not splitted enough during legalization
1139 // because it was not clear they are smem-load or vmem-load
1142 assert(LoadSize % MaxNonSmrdLoadSize == 0);
1143 unsigned NumSplitParts = LoadTy.getSizeInBits() / MaxNonSmrdLoadSize;
1144 const LLT LoadSplitTy = LoadTy.divide(NumSplitParts);
1145 ApplyRegBankMapping O(B, *this, MRI, &AMDGPU::VGPRRegBank);
1146 LegalizerHelper Helper(B.getMF(), O, B);
1147 if (LoadTy.isVector()) {
1148 if (Helper.fewerElementsVector(MI, 0, LoadSplitTy) !=
1150 return false;
1151 } else {
1152 if (Helper.narrowScalar(MI, 0, LoadSplitTy) != LegalizerHelper::Legalized)
1153 return false;
1154 }
1155 }
1156
1157 MRI.setRegBank(DstReg, AMDGPU::VGPRRegBank);
1158 return true;
1159}
1160
1164 MachineInstr &MI) const {
1165 MachineRegisterInfo &MRI = *B.getMRI();
1166 const MachineFunction &MF = B.getMF();
1167 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
1168 const auto &TFI = *ST.getFrameLowering();
1169
1170 // Guard in case the stack growth direction ever changes with scratch
1171 // instructions.
1172 assert(TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp &&
1173 "Stack grows upwards for AMDGPU");
1174
1175 Register Dst = MI.getOperand(0).getReg();
1176 Register AllocSize = MI.getOperand(1).getReg();
1177 Align Alignment = assumeAligned(MI.getOperand(2).getImm());
1178
1179 // When using flat-scratch, the stack offset is unscaled.
1180 const bool HasFlatScratch = ST.hasFlatScratchEnabled();
1181 const unsigned WavefrontSizeLog2 = ST.getWavefrontSizeLog2();
1182
1183 const RegisterBank *SizeBank = getRegBank(AllocSize, MRI, *TRI);
1184
1185 if (SizeBank != &AMDGPU::SGPRRegBank) {
1186 auto WaveReduction =
1187 B.buildIntrinsic(Intrinsic::amdgcn_wave_reduce_umax, {LLT::scalar(32)})
1188 .addUse(AllocSize)
1189 .addImm(0);
1190 AllocSize = WaveReduction.getReg(0);
1191 }
1192
1193 LLT PtrTy = MRI.getType(Dst);
1195
1197 Register SPReg = Info->getStackPtrOffsetReg();
1198 ApplyRegBankMapping ApplyBank(B, *this, MRI, &AMDGPU::SGPRRegBank);
1199
1200 Register ScaledSize = AllocSize;
1201 if (!HasFlatScratch) {
1202 auto WaveSize = B.buildConstant(LLT::scalar(32), WavefrontSizeLog2);
1203 ScaledSize = B.buildShl(IntPtrTy, AllocSize, WaveSize).getReg(0);
1204 }
1205
1206 auto OldSP = B.buildCopy(PtrTy, SPReg);
1207 if (Alignment > TFI.getStackAlign()) {
1208 const uint64_t ScaledAlignment =
1209 HasFlatScratch ? Alignment.value()
1210 : (Alignment.value() << WavefrontSizeLog2);
1211 const uint64_t StackAlignMask = ScaledAlignment - 1;
1212 auto Tmp1 = B.buildPtrAdd(PtrTy, OldSP,
1213 B.buildConstant(LLT::scalar(32), StackAlignMask));
1214 B.buildMaskLowPtrBits(Dst, Tmp1,
1215 (HasFlatScratch
1216 ? Log2(Alignment)
1217 : Log2(Alignment) + WavefrontSizeLog2));
1218 } else {
1219 B.buildCopy(Dst, OldSP);
1220 }
1221 auto PtrAdd = B.buildPtrAdd(PtrTy, Dst, ScaledSize);
1222 B.buildCopy(SPReg, PtrAdd);
1223 MI.eraseFromParent();
1224 return true;
1225}
1226
1230 int RsrcIdx) const {
1231 const int NumDefs = MI.getNumExplicitDefs();
1232
1233 // The reported argument index is relative to the IR intrinsic call arguments,
1234 // so we need to shift by the number of defs and the intrinsic ID.
1235 RsrcIdx += NumDefs + 1;
1236
1237 // Insert copies to VGPR arguments.
1238 applyDefaultMapping(OpdMapper);
1239
1240 // Fixup any SGPR arguments.
1241 SmallVector<unsigned, 4> SGPRIndexes;
1242 for (int I = NumDefs, NumOps = MI.getNumOperands(); I != NumOps; ++I) {
1243 if (!MI.getOperand(I).isReg())
1244 continue;
1245
1246 // If this intrinsic has a sampler, it immediately follows rsrc.
1247 if (I == RsrcIdx || I == RsrcIdx + 1)
1248 SGPRIndexes.push_back(I);
1249 }
1250
1251 executeInWaterfallLoop(B, MI, SGPRIndexes);
1252 return true;
1253}
1254
1255// Analyze a combined offset from an llvm.amdgcn.s.buffer intrinsic and store
1256// the three offsets (voffset, soffset and instoffset)
1258 MachineIRBuilder &B, Register CombinedOffset, Register &VOffsetReg,
1259 Register &SOffsetReg, int64_t &InstOffsetVal, Align Alignment) const {
1260 const LLT S32 = LLT::scalar(32);
1261 MachineRegisterInfo *MRI = B.getMRI();
1262
1263 if (std::optional<int64_t> Imm =
1264 getIConstantVRegSExtVal(CombinedOffset, *MRI)) {
1265 uint32_t SOffset, ImmOffset;
1266 if (TII->splitMUBUFOffset(*Imm, SOffset, ImmOffset, Alignment)) {
1267 VOffsetReg = B.buildConstant(S32, 0).getReg(0);
1268 SOffsetReg = B.buildConstant(S32, SOffset).getReg(0);
1269 InstOffsetVal = ImmOffset;
1270
1271 B.getMRI()->setRegBank(VOffsetReg, AMDGPU::VGPRRegBank);
1272 B.getMRI()->setRegBank(SOffsetReg, AMDGPU::SGPRRegBank);
1273 return SOffset + ImmOffset;
1274 }
1275 }
1276
1277 const bool CheckNUW = Subtarget.hasGFX1250Insts();
1278 Register Base;
1279 unsigned Offset;
1280
1281 std::tie(Base, Offset) =
1282 AMDGPU::getBaseWithConstantOffset(*MRI, CombinedOffset,
1283 /*KnownBits=*/nullptr,
1284 /*CheckNUW=*/CheckNUW);
1285
1286 uint32_t SOffset, ImmOffset;
1287 if (static_cast<int32_t>(Offset) > 0 &&
1288 TII->splitMUBUFOffset(Offset, SOffset, ImmOffset, Alignment)) {
1289 if (getRegBank(Base, *MRI, *TRI) == &AMDGPU::VGPRRegBank) {
1290 VOffsetReg = Base;
1291 SOffsetReg = B.buildConstant(S32, SOffset).getReg(0);
1292 B.getMRI()->setRegBank(SOffsetReg, AMDGPU::SGPRRegBank);
1293 InstOffsetVal = ImmOffset;
1294 return 0; // XXX - Why is this 0?
1295 }
1296
1297 // If we have SGPR base, we can use it for soffset.
1298 if (SOffset == 0) {
1299 VOffsetReg = B.buildConstant(S32, 0).getReg(0);
1300 B.getMRI()->setRegBank(VOffsetReg, AMDGPU::VGPRRegBank);
1301 SOffsetReg = Base;
1302 InstOffsetVal = ImmOffset;
1303 return 0; // XXX - Why is this 0?
1304 }
1305 }
1306
1307 // Handle the variable sgpr + vgpr case.
1308 MachineInstr *Add = getOpcodeDef(AMDGPU::G_ADD, CombinedOffset, *MRI);
1309 if (Add && static_cast<int32_t>(Offset) >= 0 &&
1310 (!CheckNUW || Add->getFlag(MachineInstr::NoUWrap))) {
1311 Register Src0 = getSrcRegIgnoringCopies(Add->getOperand(1).getReg(), *MRI);
1312 Register Src1 = getSrcRegIgnoringCopies(Add->getOperand(2).getReg(), *MRI);
1313
1314 const RegisterBank *Src0Bank = getRegBank(Src0, *MRI, *TRI);
1315 const RegisterBank *Src1Bank = getRegBank(Src1, *MRI, *TRI);
1316
1317 if (Src0Bank == &AMDGPU::VGPRRegBank && Src1Bank == &AMDGPU::SGPRRegBank) {
1318 VOffsetReg = Src0;
1319 SOffsetReg = Src1;
1320 return 0;
1321 }
1322
1323 if (Src0Bank == &AMDGPU::SGPRRegBank && Src1Bank == &AMDGPU::VGPRRegBank) {
1324 VOffsetReg = Src1;
1325 SOffsetReg = Src0;
1326 return 0;
1327 }
1328 }
1329
1330 // Ensure we have a VGPR for the combined offset. This could be an issue if we
1331 // have an SGPR offset and a VGPR resource.
1332 if (getRegBank(CombinedOffset, *MRI, *TRI) == &AMDGPU::VGPRRegBank) {
1333 VOffsetReg = CombinedOffset;
1334 } else {
1335 VOffsetReg = B.buildCopy(S32, CombinedOffset).getReg(0);
1336 B.getMRI()->setRegBank(VOffsetReg, AMDGPU::VGPRRegBank);
1337 }
1338
1339 SOffsetReg = B.buildConstant(S32, 0).getReg(0);
1340 B.getMRI()->setRegBank(SOffsetReg, AMDGPU::SGPRRegBank);
1341 return 0;
1342}
1343
1345 switch (Opc) {
1346 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD:
1347 return AMDGPU::G_AMDGPU_BUFFER_LOAD;
1348 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
1349 return AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
1350 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE:
1351 return AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE;
1352 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
1353 return AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
1354 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT:
1355 return AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT;
1356 default:
1357 break;
1358 }
1359 llvm_unreachable("Unexpected s_buffer_load opcode");
1360}
1361
1363 MachineIRBuilder &B, const OperandsMapper &OpdMapper) const {
1364 MachineInstr &MI = OpdMapper.getMI();
1365 MachineRegisterInfo &MRI = OpdMapper.getMRI();
1366
1367 const LLT S32 = LLT::scalar(32);
1368 Register Dst = MI.getOperand(0).getReg();
1369 LLT Ty = MRI.getType(Dst);
1370
1371 const RegisterBank *RSrcBank =
1372 OpdMapper.getInstrMapping().getOperandMapping(1).BreakDown[0].RegBank;
1373 const RegisterBank *OffsetBank =
1374 OpdMapper.getInstrMapping().getOperandMapping(2).BreakDown[0].RegBank;
1375 if (RSrcBank == &AMDGPU::SGPRRegBank &&
1376 OffsetBank == &AMDGPU::SGPRRegBank)
1377 return true; // Legal mapping
1378
1379 // FIXME: 96-bit case was widened during legalize. We need to narrow it back
1380 // here but don't have an MMO.
1381
1382 unsigned LoadSize = Ty.getSizeInBits();
1383 int NumLoads = 1;
1384 if (LoadSize == 256 || LoadSize == 512) {
1385 NumLoads = LoadSize / 128;
1386 Ty = Ty.divide(NumLoads);
1387 }
1388
1389 // Use the alignment to ensure that the required offsets will fit into the
1390 // immediate offsets.
1391 const Align Alignment = NumLoads > 1 ? Align(16 * NumLoads) : Align(1);
1392
1393 MachineFunction &MF = B.getMF();
1394
1395 Register SOffset;
1396 Register VOffset;
1397 int64_t ImmOffset = 0;
1398
1399 unsigned MMOOffset = setBufferOffsets(B, MI.getOperand(2).getReg(), VOffset,
1400 SOffset, ImmOffset, Alignment);
1401
1402 // TODO: 96-bit loads were widened to 128-bit results. Shrink the result if we
1403 // can, but we need to track an MMO for that.
1404 const unsigned MemSize = (Ty.getSizeInBits() + 7) / 8;
1405 const Align MemAlign(4); // FIXME: ABI type alignment?
1410 MemSize, MemAlign);
1411 if (MMOOffset != 0)
1412 BaseMMO = MF.getMachineMemOperand(BaseMMO, MMOOffset, MemSize);
1413
1414 // If only the offset is divergent, emit a MUBUF buffer load instead. We can
1415 // assume that the buffer is unswizzled.
1416
1417 Register RSrc = MI.getOperand(1).getReg();
1418 Register VIndex = B.buildConstant(S32, 0).getReg(0);
1419 B.getMRI()->setRegBank(VIndex, AMDGPU::VGPRRegBank);
1420 unsigned CachePolicy = MI.getOperand(3).getImm();
1421
1422 SmallVector<Register, 4> LoadParts(NumLoads);
1423
1424 MachineBasicBlock::iterator MII = MI.getIterator();
1425 MachineInstrSpan Span(MII, &B.getMBB());
1426
1427 for (int i = 0; i < NumLoads; ++i) {
1428 if (NumLoads == 1) {
1429 LoadParts[i] = Dst;
1430 } else {
1431 LoadParts[i] = MRI.createGenericVirtualRegister(Ty);
1432 MRI.setRegBank(LoadParts[i], AMDGPU::VGPRRegBank);
1433 }
1434
1435 if (i != 0)
1436 BaseMMO = MF.getMachineMemOperand(BaseMMO, 16, MemSize);
1437
1438 B.buildInstr(getSBufferLoadCorrespondingBufferLoadOpcode(MI.getOpcode()))
1439 .addDef(LoadParts[i]) // vdata
1440 .addUse(RSrc) // rsrc
1441 .addUse(VIndex) // vindex
1442 .addUse(VOffset) // voffset
1443 .addUse(SOffset) // soffset
1444 .addImm(ImmOffset + 16 * i) // offset(imm)
1445 .addImm(CachePolicy) // cachepolicy, swizzled buffer(imm)
1446 .addImm(0) // idxen(imm)
1447 .addMemOperand(BaseMMO);
1448 }
1449
1450 // TODO: If only the resource is a VGPR, it may be better to execute the
1451 // scalar load in the waterfall loop if the resource is expected to frequently
1452 // be dynamically uniform.
1453 if (RSrcBank != &AMDGPU::SGPRRegBank) {
1454 // Remove the original instruction to avoid potentially confusing the
1455 // waterfall loop logic.
1456 B.setInstr(*Span.begin());
1457 MI.eraseFromParent();
1458
1459 SmallSet<Register, 4> OpsToWaterfall;
1460
1461 OpsToWaterfall.insert(RSrc);
1462 executeInWaterfallLoop(B, make_range(Span.begin(), Span.end()),
1463 OpsToWaterfall);
1464 }
1465
1466 if (NumLoads != 1) {
1467 if (Ty.isVector())
1468 B.buildConcatVectors(Dst, LoadParts);
1469 else
1470 B.buildMergeLikeInstr(Dst, LoadParts);
1471 }
1472
1473 // We removed the instruction earlier with a waterfall loop.
1474 if (RSrcBank == &AMDGPU::SGPRRegBank)
1475 MI.eraseFromParent();
1476
1477 return true;
1478}
1479
1481 const OperandsMapper &OpdMapper,
1482 bool Signed) const {
1483 MachineInstr &MI = OpdMapper.getMI();
1484 MachineRegisterInfo &MRI = OpdMapper.getMRI();
1485
1486 // Insert basic copies
1487 applyDefaultMapping(OpdMapper);
1488
1489 Register DstReg = MI.getOperand(0).getReg();
1490 LLT Ty = MRI.getType(DstReg);
1491
1492 const LLT S32 = LLT::scalar(32);
1493
1494 unsigned FirstOpnd = isa<GIntrinsic>(MI) ? 2 : 1;
1495 Register SrcReg = MI.getOperand(FirstOpnd).getReg();
1496 Register OffsetReg = MI.getOperand(FirstOpnd + 1).getReg();
1497 Register WidthReg = MI.getOperand(FirstOpnd + 2).getReg();
1498
1499 const RegisterBank *DstBank =
1500 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
1501 if (DstBank == &AMDGPU::VGPRRegBank) {
1502 if (Ty == S32)
1503 return true;
1504
1505 // There is no 64-bit vgpr bitfield extract instructions so the operation
1506 // is expanded to a sequence of instructions that implement the operation.
1507 ApplyRegBankMapping ApplyBank(B, *this, MRI, &AMDGPU::VGPRRegBank);
1508
1509 const LLT S64 = LLT::scalar(64);
1510 // Shift the source operand so that extracted bits start at bit 0.
1511 auto ShiftOffset = Signed ? B.buildAShr(S64, SrcReg, OffsetReg)
1512 : B.buildLShr(S64, SrcReg, OffsetReg);
1513 auto UnmergeSOffset = B.buildUnmerge({S32, S32}, ShiftOffset);
1514
1515 // A 64-bit bitfield extract uses the 32-bit bitfield extract instructions
1516 // if the width is a constant.
1517 if (auto ConstWidth = getIConstantVRegValWithLookThrough(WidthReg, MRI)) {
1518 // Use the 32-bit bitfield extract instruction if the width is a constant.
1519 // Depending on the width size, use either the low or high 32-bits.
1520 auto Zero = B.buildConstant(S32, 0);
1521 auto WidthImm = ConstWidth->Value.getZExtValue();
1522 if (WidthImm <= 32) {
1523 // Use bitfield extract on the lower 32-bit source, and then sign-extend
1524 // or clear the upper 32-bits.
1525 auto Extract =
1526 Signed ? B.buildSbfx(S32, UnmergeSOffset.getReg(0), Zero, WidthReg)
1527 : B.buildUbfx(S32, UnmergeSOffset.getReg(0), Zero, WidthReg);
1528 auto Extend =
1529 Signed ? B.buildAShr(S32, Extract, B.buildConstant(S32, 31)) : Zero;
1530 B.buildMergeLikeInstr(DstReg, {Extract, Extend});
1531 } else {
1532 // Use bitfield extract on upper 32-bit source, and combine with lower
1533 // 32-bit source.
1534 auto UpperWidth = B.buildConstant(S32, WidthImm - 32);
1535 auto Extract =
1536 Signed
1537 ? B.buildSbfx(S32, UnmergeSOffset.getReg(1), Zero, UpperWidth)
1538 : B.buildUbfx(S32, UnmergeSOffset.getReg(1), Zero, UpperWidth);
1539 B.buildMergeLikeInstr(DstReg, {UnmergeSOffset.getReg(0), Extract});
1540 }
1541 MI.eraseFromParent();
1542 return true;
1543 }
1544
1545 // Expand to Src >> Offset << (64 - Width) >> (64 - Width) using 64-bit
1546 // operations.
1547 auto ExtShift = B.buildSub(S32, B.buildConstant(S32, 64), WidthReg);
1548 auto SignBit = B.buildShl(S64, ShiftOffset, ExtShift);
1549 if (Signed)
1550 B.buildAShr(S64, SignBit, ExtShift);
1551 else
1552 B.buildLShr(S64, SignBit, ExtShift);
1553 MI.eraseFromParent();
1554 return true;
1555 }
1556
1557 // The scalar form packs the offset and width in a single operand.
1558
1559 ApplyRegBankMapping ApplyBank(B, *this, MRI, &AMDGPU::SGPRRegBank);
1560
1561 // Ensure the high bits are clear to insert the offset.
1562 auto OffsetMask = B.buildConstant(S32, maskTrailingOnes<unsigned>(6));
1563 auto ClampOffset = B.buildAnd(S32, OffsetReg, OffsetMask);
1564
1565 // Zeros out the low bits, so don't bother clamping the input value.
1566 auto ShiftWidth = B.buildShl(S32, WidthReg, B.buildConstant(S32, 16));
1567
1568 // Transformation function, pack the offset and width of a BFE into
1569 // the format expected by the S_BFE_I32 / S_BFE_U32. In the second
1570 // source, bits [5:0] contain the offset and bits [22:16] the width.
1571 auto MergedInputs = B.buildOr(S32, ClampOffset, ShiftWidth);
1572
1573 // TODO: It might be worth using a pseudo here to avoid scc clobber and
1574 // register class constraints.
1575 unsigned Opc = Ty == S32 ? (Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32) :
1576 (Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64);
1577
1578 auto MIB = B.buildInstr(Opc, {DstReg}, {SrcReg, MergedInputs});
1579 constrainSelectedInstRegOperands(*MIB, *TII, *TRI, *this);
1580
1581 MI.eraseFromParent();
1582 return true;
1583}
1584
1586 MachineIRBuilder &B, const OperandsMapper &OpdMapper) const {
1587 MachineInstr &MI = OpdMapper.getMI();
1588 MachineRegisterInfo &MRI = OpdMapper.getMRI();
1589
1590 // Insert basic copies.
1591 applyDefaultMapping(OpdMapper);
1592
1593 Register Dst0 = MI.getOperand(0).getReg();
1594 Register Dst1 = MI.getOperand(1).getReg();
1595 Register Src0 = MI.getOperand(2).getReg();
1596 Register Src1 = MI.getOperand(3).getReg();
1597 Register Src2 = MI.getOperand(4).getReg();
1598
1599 if (MRI.getRegBankOrNull(Src0) == &AMDGPU::VGPRRegBank)
1600 return true;
1601
1602 bool IsUnsigned = MI.getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32;
1603 LLT S1 = LLT::scalar(1);
1604 LLT S32 = LLT::scalar(32);
1605
1606 bool DstOnValu = MRI.getRegBankOrNull(Src2) == &AMDGPU::VGPRRegBank;
1607 bool Accumulate = true;
1608
1609 if (!DstOnValu) {
1610 if (mi_match(Src2, MRI, m_ZeroInt()))
1611 Accumulate = false;
1612 }
1613
1614 // Keep the multiplication on the SALU.
1615 Register DstHi;
1616 Register DstLo = B.buildMul(S32, Src0, Src1).getReg(0);
1617 bool MulHiInVgpr = false;
1618
1619 MRI.setRegBank(DstLo, AMDGPU::SGPRRegBank);
1620
1621 if (Subtarget.hasSMulHi()) {
1622 DstHi = IsUnsigned ? B.buildUMulH(S32, Src0, Src1).getReg(0)
1623 : B.buildSMulH(S32, Src0, Src1).getReg(0);
1624 MRI.setRegBank(DstHi, AMDGPU::SGPRRegBank);
1625 } else {
1626 Register VSrc0 = B.buildCopy(S32, Src0).getReg(0);
1627 Register VSrc1 = B.buildCopy(S32, Src1).getReg(0);
1628
1629 MRI.setRegBank(VSrc0, AMDGPU::VGPRRegBank);
1630 MRI.setRegBank(VSrc1, AMDGPU::VGPRRegBank);
1631
1632 DstHi = IsUnsigned ? B.buildUMulH(S32, VSrc0, VSrc1).getReg(0)
1633 : B.buildSMulH(S32, VSrc0, VSrc1).getReg(0);
1634 MRI.setRegBank(DstHi, AMDGPU::VGPRRegBank);
1635
1636 if (!DstOnValu) {
1637 DstHi = buildReadFirstLane(B, MRI, DstHi);
1638 } else {
1639 MulHiInVgpr = true;
1640 }
1641 }
1642
1643 // Accumulate and produce the "carry-out" bit.
1644 //
1645 // The "carry-out" is defined as bit 64 of the result when computed as a
1646 // big integer. For unsigned multiply-add, this matches the usual definition
1647 // of carry-out. For signed multiply-add, bit 64 is the sign bit of the
1648 // result, which is determined as:
1649 // sign(Src0 * Src1) + sign(Src2) + carry-out from unsigned 64-bit add
1650 LLT CarryType = DstOnValu ? S1 : S32;
1651 const RegisterBank &CarryBank =
1652 DstOnValu ? AMDGPU::VCCRegBank : AMDGPU::SGPRRegBank;
1653 const RegisterBank &DstBank =
1654 DstOnValu ? AMDGPU::VGPRRegBank : AMDGPU::SGPRRegBank;
1655 Register Carry;
1656 Register Zero;
1657
1658 if (!IsUnsigned) {
1659 Zero = B.buildConstant(S32, 0).getReg(0);
1660 MRI.setRegBank(Zero,
1661 MulHiInVgpr ? AMDGPU::VGPRRegBank : AMDGPU::SGPRRegBank);
1662
1663 Carry = B.buildICmp(CmpInst::ICMP_SLT, MulHiInVgpr ? S1 : S32, DstHi, Zero)
1664 .getReg(0);
1665 MRI.setRegBank(Carry, MulHiInVgpr ? AMDGPU::VCCRegBank
1666 : AMDGPU::SGPRRegBank);
1667
1668 if (DstOnValu && !MulHiInVgpr) {
1669 Carry = B.buildTrunc(S1, Carry).getReg(0);
1670 MRI.setRegBank(Carry, AMDGPU::VCCRegBank);
1671 }
1672 }
1673
1674 if (Accumulate) {
1675 if (DstOnValu) {
1676 DstLo = B.buildCopy(S32, DstLo).getReg(0);
1677 DstHi = B.buildCopy(S32, DstHi).getReg(0);
1678 MRI.setRegBank(DstLo, AMDGPU::VGPRRegBank);
1679 MRI.setRegBank(DstHi, AMDGPU::VGPRRegBank);
1680 }
1681
1682 auto Unmerge = B.buildUnmerge(S32, Src2);
1683 Register Src2Lo = Unmerge.getReg(0);
1684 Register Src2Hi = Unmerge.getReg(1);
1685 MRI.setRegBank(Src2Lo, DstBank);
1686 MRI.setRegBank(Src2Hi, DstBank);
1687
1688 if (!IsUnsigned) {
1689 auto Src2Sign = B.buildICmp(CmpInst::ICMP_SLT, CarryType, Src2Hi, Zero);
1690 MRI.setRegBank(Src2Sign.getReg(0), CarryBank);
1691
1692 Carry = B.buildXor(CarryType, Carry, Src2Sign).getReg(0);
1693 MRI.setRegBank(Carry, CarryBank);
1694 }
1695
1696 auto AddLo = B.buildUAddo(S32, CarryType, DstLo, Src2Lo);
1697 DstLo = AddLo.getReg(0);
1698 Register CarryLo = AddLo.getReg(1);
1699 MRI.setRegBank(DstLo, DstBank);
1700 MRI.setRegBank(CarryLo, CarryBank);
1701
1702 auto AddHi = B.buildUAdde(S32, CarryType, DstHi, Src2Hi, CarryLo);
1703 DstHi = AddHi.getReg(0);
1704 MRI.setRegBank(DstHi, DstBank);
1705
1706 Register CarryHi = AddHi.getReg(1);
1707 MRI.setRegBank(CarryHi, CarryBank);
1708
1709 if (IsUnsigned) {
1710 Carry = CarryHi;
1711 } else {
1712 Carry = B.buildXor(CarryType, Carry, CarryHi).getReg(0);
1713 MRI.setRegBank(Carry, CarryBank);
1714 }
1715 } else {
1716 if (IsUnsigned) {
1717 Carry = B.buildConstant(CarryType, 0).getReg(0);
1718 MRI.setRegBank(Carry, CarryBank);
1719 }
1720 }
1721
1722 B.buildMergeLikeInstr(Dst0, {DstLo, DstHi});
1723
1724 if (DstOnValu) {
1725 B.buildCopy(Dst1, Carry);
1726 } else {
1727 B.buildTrunc(Dst1, Carry);
1728 }
1729
1730 MI.eraseFromParent();
1731 return true;
1732}
1733
1734// Return a suitable opcode for extending the operands of Opc when widening.
1735static unsigned getExtendOp(unsigned Opc) {
1736 switch (Opc) {
1737 case TargetOpcode::G_ASHR:
1738 case TargetOpcode::G_SMIN:
1739 case TargetOpcode::G_SMAX:
1740 return TargetOpcode::G_SEXT;
1741 case TargetOpcode::G_LSHR:
1742 case TargetOpcode::G_UMIN:
1743 case TargetOpcode::G_UMAX:
1744 return TargetOpcode::G_ZEXT;
1745 default:
1746 return TargetOpcode::G_ANYEXT;
1747 }
1748}
1749
1750// Emit a legalized extension from <2 x s16> to 2 32-bit components, avoiding
1751// any illegal vector extend or unmerge operations.
1752static std::pair<Register, Register>
1753unpackV2S16ToS32(MachineIRBuilder &B, Register Src, unsigned ExtOpcode) {
1754 const LLT S32 = LLT::scalar(32);
1755 auto Bitcast = B.buildBitcast(S32, Src);
1756
1757 if (ExtOpcode == TargetOpcode::G_SEXT) {
1758 auto ExtLo = B.buildSExtInReg(S32, Bitcast, 16);
1759 auto ShiftHi = B.buildAShr(S32, Bitcast, B.buildConstant(S32, 16));
1760 return std::pair(ExtLo.getReg(0), ShiftHi.getReg(0));
1761 }
1762
1763 auto ShiftHi = B.buildLShr(S32, Bitcast, B.buildConstant(S32, 16));
1764 if (ExtOpcode == TargetOpcode::G_ZEXT) {
1765 auto ExtLo = B.buildAnd(S32, Bitcast, B.buildConstant(S32, 0xffff));
1766 return std::pair(ExtLo.getReg(0), ShiftHi.getReg(0));
1767 }
1768
1769 assert(ExtOpcode == TargetOpcode::G_ANYEXT);
1770 return std::pair(Bitcast.getReg(0), ShiftHi.getReg(0));
1771}
1772
1773// For cases where only a single copy is inserted for matching register banks.
1774// Replace the register in the instruction operand
1776 const AMDGPURegisterBankInfo::OperandsMapper &OpdMapper, unsigned OpIdx) {
1777 SmallVector<unsigned, 1> SrcReg(OpdMapper.getVRegs(OpIdx));
1778 if (!SrcReg.empty()) {
1779 assert(SrcReg.size() == 1);
1780 OpdMapper.getMI().getOperand(OpIdx).setReg(SrcReg[0]);
1781 return true;
1782 }
1783
1784 return false;
1785}
1786
1787/// Handle register layout difference for f16 images for some subtargets.
1790 Register Reg) const {
1791 if (!Subtarget.hasUnpackedD16VMem())
1792 return Reg;
1793
1794 const LLT S16 = LLT::scalar(16);
1795 LLT StoreVT = MRI.getType(Reg);
1796 if (!StoreVT.isVector() || StoreVT.getElementType() != S16)
1797 return Reg;
1798
1799 auto Unmerge = B.buildUnmerge(S16, Reg);
1800
1801
1802 SmallVector<Register, 4> WideRegs;
1803 for (int I = 0, E = Unmerge->getNumOperands() - 1; I != E; ++I)
1804 WideRegs.push_back(Unmerge.getReg(I));
1805
1806 const LLT S32 = LLT::scalar(32);
1807 int NumElts = StoreVT.getNumElements();
1808
1809 return B.buildMergeLikeInstr(LLT::fixed_vector(NumElts, S32), WideRegs)
1810 .getReg(0);
1811}
1812
1813static std::pair<Register, unsigned>
1815 int64_t Const;
1816 if (mi_match(Reg, MRI, m_ICst(Const)))
1817 return std::pair(Register(), Const);
1818
1819 Register Base;
1820 if (mi_match(Reg, MRI, m_GAdd(m_Reg(Base), m_ICst(Const))))
1821 return std::pair(Base, Const);
1822
1823 // TODO: Handle G_OR used for add case
1824 return std::pair(Reg, 0);
1825}
1826
1827std::pair<Register, unsigned>
1829 Register OrigOffset) const {
1830 const unsigned MaxImm = SIInstrInfo::getMaxMUBUFImmOffset(Subtarget);
1831 Register BaseReg;
1832 unsigned ImmOffset;
1833 const LLT S32 = LLT::scalar(32);
1834
1835 // TODO: Use AMDGPU::getBaseWithConstantOffset() instead.
1836 std::tie(BaseReg, ImmOffset) = getBaseWithConstantOffset(*B.getMRI(),
1837 OrigOffset);
1838
1839 unsigned C1 = 0;
1840 if (ImmOffset != 0) {
1841 // If the immediate value is too big for the immoffset field, put only bits
1842 // that would normally fit in the immoffset field. The remaining value that
1843 // is copied/added for the voffset field is a large power of 2, and it
1844 // stands more chance of being CSEd with the copy/add for another similar
1845 // load/store.
1846 // However, do not do that rounding down if that is a negative
1847 // number, as it appears to be illegal to have a negative offset in the
1848 // vgpr, even if adding the immediate offset makes it positive.
1849 unsigned Overflow = ImmOffset & ~MaxImm;
1850 ImmOffset -= Overflow;
1851 if (static_cast<int32_t>(Overflow) < 0) {
1852 Overflow += ImmOffset;
1853 ImmOffset = 0;
1854 }
1855
1856 C1 = ImmOffset;
1857 if (Overflow != 0) {
1858 if (!BaseReg)
1859 BaseReg = B.buildConstant(S32, Overflow).getReg(0);
1860 else {
1861 auto OverflowVal = B.buildConstant(S32, Overflow);
1862 BaseReg = B.buildAdd(S32, BaseReg, OverflowVal).getReg(0);
1863 }
1864 }
1865 }
1866
1867 if (!BaseReg)
1868 BaseReg = B.buildConstant(S32, 0).getReg(0);
1869
1870 return {BaseReg, C1};
1871}
1872
1874 Register SrcReg) const {
1875 MachineRegisterInfo &MRI = *B.getMRI();
1876 LLT SrcTy = MRI.getType(SrcReg);
1877 if (SrcTy.getSizeInBits() == 32) {
1878 // Use a v_mov_b32 here to make the exec dependency explicit.
1879 B.buildInstr(AMDGPU::V_MOV_B32_e32)
1880 .addDef(DstReg)
1881 .addUse(SrcReg);
1882 return constrainGenericRegister(DstReg, AMDGPU::VGPR_32RegClass, MRI) &&
1883 constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, MRI);
1884 }
1885
1886 Register TmpReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
1887 Register TmpReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
1888
1889 B.buildInstr(AMDGPU::V_MOV_B32_e32)
1890 .addDef(TmpReg0)
1891 .addUse(SrcReg, {}, AMDGPU::sub0);
1892 B.buildInstr(AMDGPU::V_MOV_B32_e32)
1893 .addDef(TmpReg1)
1894 .addUse(SrcReg, {}, AMDGPU::sub1);
1895 B.buildInstr(AMDGPU::REG_SEQUENCE)
1896 .addDef(DstReg)
1897 .addUse(TmpReg0)
1898 .addImm(AMDGPU::sub0)
1899 .addUse(TmpReg1)
1900 .addImm(AMDGPU::sub1);
1901
1902 return constrainGenericRegister(SrcReg, AMDGPU::SReg_64RegClass, MRI) &&
1903 constrainGenericRegister(DstReg, AMDGPU::VReg_64RegClass, MRI);
1904}
1905
1906/// Utility function for pushing dynamic vector indexes with a constant offset
1907/// into waterfall loops.
1909 MachineInstr &IdxUseInstr,
1910 unsigned OpIdx,
1911 unsigned ConstOffset) {
1912 MachineRegisterInfo &MRI = *B.getMRI();
1913 const LLT S32 = LLT::scalar(32);
1914 Register WaterfallIdx = IdxUseInstr.getOperand(OpIdx).getReg();
1915 B.setInsertPt(*IdxUseInstr.getParent(), IdxUseInstr.getIterator());
1916
1917 auto MaterializedOffset = B.buildConstant(S32, ConstOffset);
1918
1919 auto Add = B.buildAdd(S32, WaterfallIdx, MaterializedOffset);
1920 MRI.setRegBank(MaterializedOffset.getReg(0), AMDGPU::SGPRRegBank);
1921 MRI.setRegBank(Add.getReg(0), AMDGPU::SGPRRegBank);
1922 IdxUseInstr.getOperand(OpIdx).setReg(Add.getReg(0));
1923}
1924
1925/// Implement extending a 32-bit value to a 64-bit value. \p Lo32Reg is the
1926/// original 32-bit source value (to be inserted in the low part of the combined
1927/// 64-bit result), and \p Hi32Reg is the high half of the combined 64-bit
1928/// value.
1930 Register Hi32Reg, Register Lo32Reg,
1931 unsigned ExtOpc,
1932 const RegisterBank &RegBank,
1933 bool IsBooleanSrc = false) {
1934 if (ExtOpc == AMDGPU::G_ZEXT) {
1935 B.buildConstant(Hi32Reg, 0);
1936 } else if (ExtOpc == AMDGPU::G_SEXT) {
1937 if (IsBooleanSrc) {
1938 // If we know the original source was an s1, the high half is the same as
1939 // the low.
1940 B.buildCopy(Hi32Reg, Lo32Reg);
1941 } else {
1942 // Replicate sign bit from 32-bit extended part.
1943 auto ShiftAmt = B.buildConstant(LLT::scalar(32), 31);
1944 B.getMRI()->setRegBank(ShiftAmt.getReg(0), RegBank);
1945 B.buildAShr(Hi32Reg, Lo32Reg, ShiftAmt);
1946 }
1947 } else {
1948 assert(ExtOpc == AMDGPU::G_ANYEXT && "not an integer extension");
1949 B.buildUndef(Hi32Reg);
1950 }
1951}
1952
1953bool AMDGPURegisterBankInfo::foldExtractEltToCmpSelect(
1955 const OperandsMapper &OpdMapper) const {
1956 MachineRegisterInfo &MRI = *B.getMRI();
1957
1958 Register VecReg = MI.getOperand(1).getReg();
1959 Register Idx = MI.getOperand(2).getReg();
1960
1961 const RegisterBank &IdxBank =
1962 *OpdMapper.getInstrMapping().getOperandMapping(2).BreakDown[0].RegBank;
1963
1964 bool IsDivergentIdx = IdxBank != AMDGPU::SGPRRegBank;
1965
1966 LLT VecTy = MRI.getType(VecReg);
1967 unsigned EltSize = VecTy.getScalarSizeInBits();
1968 unsigned NumElem = VecTy.getNumElements();
1969
1970 if (!SITargetLowering::shouldExpandVectorDynExt(EltSize, NumElem,
1971 IsDivergentIdx, &Subtarget))
1972 return false;
1973
1974 LLT S32 = LLT::scalar(32);
1975
1976 const RegisterBank &DstBank =
1977 *OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
1978 const RegisterBank &SrcBank =
1979 *OpdMapper.getInstrMapping().getOperandMapping(1).BreakDown[0].RegBank;
1980
1981 const RegisterBank &CCBank =
1982 (DstBank == AMDGPU::SGPRRegBank &&
1983 SrcBank == AMDGPU::SGPRRegBank &&
1984 IdxBank == AMDGPU::SGPRRegBank) ? AMDGPU::SGPRRegBank
1985 : AMDGPU::VCCRegBank;
1986 LLT CCTy = (CCBank == AMDGPU::SGPRRegBank) ? S32 : LLT::scalar(1);
1987
1988 if (CCBank == AMDGPU::VCCRegBank && IdxBank == AMDGPU::SGPRRegBank) {
1989 Idx = B.buildCopy(S32, Idx)->getOperand(0).getReg();
1990 MRI.setRegBank(Idx, AMDGPU::VGPRRegBank);
1991 }
1992
1993 LLT EltTy = VecTy.getScalarType();
1994 SmallVector<Register, 2> DstRegs(OpdMapper.getVRegs(0));
1995 unsigned NumLanes = DstRegs.size();
1996 if (!NumLanes)
1997 NumLanes = 1;
1998 else
1999 EltTy = MRI.getType(DstRegs[0]);
2000
2001 auto UnmergeToEltTy = B.buildUnmerge(EltTy, VecReg);
2002 SmallVector<Register, 2> Res(NumLanes);
2003 for (unsigned L = 0; L < NumLanes; ++L)
2004 Res[L] = UnmergeToEltTy.getReg(L);
2005
2006 for (unsigned I = 1; I < NumElem; ++I) {
2007 auto IC = B.buildConstant(S32, I);
2008 MRI.setRegBank(IC->getOperand(0).getReg(), AMDGPU::SGPRRegBank);
2009 auto Cmp = B.buildICmp(CmpInst::ICMP_EQ, CCTy, Idx, IC);
2010 MRI.setRegBank(Cmp->getOperand(0).getReg(), CCBank);
2011
2012 for (unsigned L = 0; L < NumLanes; ++L) {
2013 auto S = B.buildSelect(EltTy, Cmp,
2014 UnmergeToEltTy.getReg(I * NumLanes + L), Res[L]);
2015
2016 for (unsigned N : { 0, 2, 3 })
2017 MRI.setRegBank(S->getOperand(N).getReg(), DstBank);
2018
2019 Res[L] = S->getOperand(0).getReg();
2020 }
2021 }
2022
2023 for (unsigned L = 0; L < NumLanes; ++L) {
2024 Register DstReg = (NumLanes == 1) ? MI.getOperand(0).getReg() : DstRegs[L];
2025 B.buildCopy(DstReg, Res[L]);
2026 MRI.setRegBank(DstReg, DstBank);
2027 }
2028
2029 MRI.setRegBank(MI.getOperand(0).getReg(), DstBank);
2030 MI.eraseFromParent();
2031
2032 return true;
2033}
2034
2035// Insert a cross regbank copy for a register if it already has a bank that
2036// differs from the one we want to set.
2039 const RegisterBank &Bank) {
2040 const RegisterBank *CurrBank = MRI.getRegBankOrNull(Reg);
2041 if (CurrBank && *CurrBank != Bank) {
2042 Register Copy = B.buildCopy(MRI.getType(Reg), Reg).getReg(0);
2043 MRI.setRegBank(Copy, Bank);
2044 return Copy;
2045 }
2046
2047 MRI.setRegBank(Reg, Bank);
2048 return Reg;
2049}
2050
2051bool AMDGPURegisterBankInfo::foldInsertEltToCmpSelect(
2053 const OperandsMapper &OpdMapper) const {
2054
2055 MachineRegisterInfo &MRI = *B.getMRI();
2056 Register VecReg = MI.getOperand(1).getReg();
2057 Register Idx = MI.getOperand(3).getReg();
2058
2059 const RegisterBank &IdxBank =
2060 *OpdMapper.getInstrMapping().getOperandMapping(3).BreakDown[0].RegBank;
2061
2062 bool IsDivergentIdx = IdxBank != AMDGPU::SGPRRegBank;
2063
2064 LLT VecTy = MRI.getType(VecReg);
2065 unsigned EltSize = VecTy.getScalarSizeInBits();
2066 unsigned NumElem = VecTy.getNumElements();
2067
2068 if (!SITargetLowering::shouldExpandVectorDynExt(EltSize, NumElem,
2069 IsDivergentIdx, &Subtarget))
2070 return false;
2071
2072 LLT S32 = LLT::scalar(32);
2073
2074 const RegisterBank &DstBank =
2075 *OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2076 const RegisterBank &SrcBank =
2077 *OpdMapper.getInstrMapping().getOperandMapping(1).BreakDown[0].RegBank;
2078 const RegisterBank &InsBank =
2079 *OpdMapper.getInstrMapping().getOperandMapping(2).BreakDown[0].RegBank;
2080
2081 const RegisterBank &CCBank =
2082 (DstBank == AMDGPU::SGPRRegBank &&
2083 SrcBank == AMDGPU::SGPRRegBank &&
2084 InsBank == AMDGPU::SGPRRegBank &&
2085 IdxBank == AMDGPU::SGPRRegBank) ? AMDGPU::SGPRRegBank
2086 : AMDGPU::VCCRegBank;
2087 LLT CCTy = (CCBank == AMDGPU::SGPRRegBank) ? S32 : LLT::scalar(1);
2088
2089 if (CCBank == AMDGPU::VCCRegBank && IdxBank == AMDGPU::SGPRRegBank) {
2090 Idx = B.buildCopy(S32, Idx)->getOperand(0).getReg();
2091 MRI.setRegBank(Idx, AMDGPU::VGPRRegBank);
2092 }
2093
2094 LLT EltTy = VecTy.getScalarType();
2095 SmallVector<Register, 2> InsRegs(OpdMapper.getVRegs(2));
2096 unsigned NumLanes = InsRegs.size();
2097 if (!NumLanes) {
2098 NumLanes = 1;
2099 InsRegs.push_back(MI.getOperand(2).getReg());
2100 } else {
2101 EltTy = MRI.getType(InsRegs[0]);
2102 }
2103
2104 auto UnmergeToEltTy = B.buildUnmerge(EltTy, VecReg);
2105 SmallVector<Register, 16> Ops(NumElem * NumLanes);
2106
2107 for (unsigned I = 0; I < NumElem; ++I) {
2108 auto IC = B.buildConstant(S32, I);
2109 MRI.setRegBank(IC->getOperand(0).getReg(), AMDGPU::SGPRRegBank);
2110 auto Cmp = B.buildICmp(CmpInst::ICMP_EQ, CCTy, Idx, IC);
2111 MRI.setRegBank(Cmp->getOperand(0).getReg(), CCBank);
2112
2113 for (unsigned L = 0; L < NumLanes; ++L) {
2114 Register Op0 = constrainRegToBank(MRI, B, InsRegs[L], DstBank);
2115 Register Op1 = UnmergeToEltTy.getReg(I * NumLanes + L);
2116 Op1 = constrainRegToBank(MRI, B, Op1, DstBank);
2117
2118 Register Select = B.buildSelect(EltTy, Cmp, Op0, Op1).getReg(0);
2119 MRI.setRegBank(Select, DstBank);
2120
2121 Ops[I * NumLanes + L] = Select;
2122 }
2123 }
2124
2125 LLT MergeTy = LLT::fixed_vector(Ops.size(), EltTy);
2126 if (MergeTy == MRI.getType(MI.getOperand(0).getReg())) {
2127 B.buildBuildVector(MI.getOperand(0), Ops);
2128 } else {
2129 auto Vec = B.buildBuildVector(MergeTy, Ops);
2130 MRI.setRegBank(Vec->getOperand(0).getReg(), DstBank);
2131 B.buildBitcast(MI.getOperand(0).getReg(), Vec);
2132 }
2133
2134 MRI.setRegBank(MI.getOperand(0).getReg(), DstBank);
2135 MI.eraseFromParent();
2136
2137 return true;
2138}
2139
2140// Break s_mul_u64 into 32-bit vector operations.
2142 MachineIRBuilder &B, const OperandsMapper &OpdMapper) const {
2143 SmallVector<Register, 2> DefRegs(OpdMapper.getVRegs(0));
2144 SmallVector<Register, 2> Src0Regs(OpdMapper.getVRegs(1));
2145 SmallVector<Register, 2> Src1Regs(OpdMapper.getVRegs(2));
2146
2147 // All inputs are SGPRs, nothing special to do.
2148 if (DefRegs.empty()) {
2149 assert(Src0Regs.empty() && Src1Regs.empty());
2150 applyDefaultMapping(OpdMapper);
2151 return;
2152 }
2153
2154 assert(DefRegs.size() == 2);
2155 assert(Src0Regs.size() == Src1Regs.size() &&
2156 (Src0Regs.empty() || Src0Regs.size() == 2));
2157
2158 MachineRegisterInfo &MRI = OpdMapper.getMRI();
2159 MachineInstr &MI = OpdMapper.getMI();
2160 Register DstReg = MI.getOperand(0).getReg();
2161 LLT HalfTy = LLT::scalar(32);
2162
2163 // Depending on where the source registers came from, the generic code may
2164 // have decided to split the inputs already or not. If not, we still need to
2165 // extract the values.
2166
2167 if (Src0Regs.empty())
2168 split64BitValueForMapping(B, Src0Regs, HalfTy, MI.getOperand(1).getReg());
2169 else
2170 setRegsToType(MRI, Src0Regs, HalfTy);
2171
2172 if (Src1Regs.empty())
2173 split64BitValueForMapping(B, Src1Regs, HalfTy, MI.getOperand(2).getReg());
2174 else
2175 setRegsToType(MRI, Src1Regs, HalfTy);
2176
2177 setRegsToType(MRI, DefRegs, HalfTy);
2178
2179 // The multiplication is done as follows:
2180 //
2181 // Op1H Op1L
2182 // * Op0H Op0L
2183 // --------------------
2184 // Op1H*Op0L Op1L*Op0L
2185 // + Op1H*Op0H Op1L*Op0H
2186 // -----------------------------------------
2187 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
2188 //
2189 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
2190 // value and that would overflow.
2191 // The low 32-bit value is Op1L*Op0L.
2192 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from
2193 // Op1L*Op0L).
2194
2195 ApplyRegBankMapping ApplyBank(B, *this, MRI, &AMDGPU::VGPRRegBank);
2196
2197 Register Hi = B.buildUMulH(HalfTy, Src0Regs[0], Src1Regs[0]).getReg(0);
2198 Register MulLoHi = B.buildMul(HalfTy, Src0Regs[0], Src1Regs[1]).getReg(0);
2199 Register Add = B.buildAdd(HalfTy, Hi, MulLoHi).getReg(0);
2200 Register MulHiLo = B.buildMul(HalfTy, Src0Regs[1], Src1Regs[0]).getReg(0);
2201 B.buildAdd(DefRegs[1], Add, MulHiLo);
2202 B.buildMul(DefRegs[0], Src0Regs[0], Src1Regs[0]);
2203
2204 MRI.setRegBank(DstReg, AMDGPU::VGPRRegBank);
2205 MI.eraseFromParent();
2206}
2207
2209 MachineIRBuilder &B, const OperandsMapper &OpdMapper) const {
2210 MachineInstr &MI = OpdMapper.getMI();
2211 B.setInstrAndDebugLoc(MI);
2212 unsigned Opc = MI.getOpcode();
2213 MachineRegisterInfo &MRI = OpdMapper.getMRI();
2214 switch (Opc) {
2215 case AMDGPU::G_CONSTANT:
2216 case AMDGPU::G_IMPLICIT_DEF: {
2217 Register DstReg = MI.getOperand(0).getReg();
2218 LLT DstTy = MRI.getType(DstReg);
2219 if (DstTy != LLT::scalar(1))
2220 break;
2221
2222 const RegisterBank *DstBank =
2223 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2224 if (DstBank == &AMDGPU::VCCRegBank)
2225 break;
2226 SmallVector<Register, 1> DefRegs(OpdMapper.getVRegs(0));
2227 if (DefRegs.empty())
2228 DefRegs.push_back(DstReg);
2229
2230 B.setInsertPt(*MI.getParent(), ++MI.getIterator());
2231
2233 LLVMContext &Ctx = B.getMF().getFunction().getContext();
2234
2235 MI.getOperand(0).setReg(NewDstReg);
2236 if (Opc != AMDGPU::G_IMPLICIT_DEF) {
2237 uint64_t ConstVal = MI.getOperand(1).getCImm()->getZExtValue();
2238 MI.getOperand(1).setCImm(
2239 ConstantInt::get(IntegerType::getInt32Ty(Ctx), ConstVal));
2240 }
2241
2242 MRI.setRegBank(NewDstReg, *DstBank);
2243 B.buildTrunc(DefRegs[0], NewDstReg);
2244 return;
2245 }
2246 case AMDGPU::G_PHI: {
2247 Register DstReg = MI.getOperand(0).getReg();
2248 LLT DstTy = MRI.getType(DstReg);
2249 if (DstTy != LLT::scalar(1))
2250 break;
2251
2252 const LLT S32 = LLT::scalar(32);
2253 const RegisterBank *DstBank =
2254 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2255 if (DstBank == &AMDGPU::VCCRegBank) {
2256 applyDefaultMapping(OpdMapper);
2257 // The standard handling only considers the result register bank for
2258 // phis. For VCC, blindly inserting a copy when the phi is lowered will
2259 // produce an invalid copy. We can only copy with some kind of compare to
2260 // get a vector boolean result. Insert a register bank copy that will be
2261 // correctly lowered to a compare.
2262 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2263 Register SrcReg = MI.getOperand(I).getReg();
2264 const RegisterBank *SrcBank = getRegBank(SrcReg, MRI, *TRI);
2265
2266 if (SrcBank != &AMDGPU::VCCRegBank) {
2267 MachineBasicBlock *SrcMBB = MI.getOperand(I + 1).getMBB();
2268 B.setInsertPt(*SrcMBB, SrcMBB->getFirstTerminator());
2269
2270 auto Copy = B.buildCopy(LLT::scalar(1), SrcReg);
2271 MRI.setRegBank(Copy.getReg(0), AMDGPU::VCCRegBank);
2272 MI.getOperand(I).setReg(Copy.getReg(0));
2273 }
2274 }
2275
2276 return;
2277 }
2278
2279 // Phi handling is strange and only considers the bank of the destination.
2280 substituteSimpleCopyRegs(OpdMapper, 0);
2281
2282 // Promote SGPR/VGPR booleans to s32
2283 ApplyRegBankMapping ApplyBank(B, *this, MRI, DstBank);
2284 B.setInsertPt(B.getMBB(), MI);
2285 LegalizerHelper Helper(B.getMF(), ApplyBank, B);
2286
2287 if (Helper.widenScalar(MI, 0, S32) != LegalizerHelper::Legalized)
2288 llvm_unreachable("widen scalar should have succeeded");
2289
2290 return;
2291 }
2292 case AMDGPU::G_FCMP:
2293 if (!Subtarget.hasSALUFloatInsts())
2294 break;
2295 [[fallthrough]];
2296 case AMDGPU::G_ICMP:
2297 case AMDGPU::G_UADDO:
2298 case AMDGPU::G_USUBO:
2299 case AMDGPU::G_UADDE:
2300 case AMDGPU::G_SADDE:
2301 case AMDGPU::G_USUBE:
2302 case AMDGPU::G_SSUBE: {
2303 unsigned BoolDstOp =
2304 (Opc == AMDGPU::G_ICMP || Opc == AMDGPU::G_FCMP) ? 0 : 1;
2305 Register DstReg = MI.getOperand(BoolDstOp).getReg();
2306
2307 const RegisterBank *DstBank =
2308 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2309 if (DstBank != &AMDGPU::SGPRRegBank)
2310 break;
2311
2312 const bool HasCarryIn = MI.getNumOperands() == 5;
2313
2314 // If this is a scalar compare, promote the result to s32, as the selection
2315 // will end up using a copy to a 32-bit vreg.
2316 const LLT S32 = LLT::scalar(32);
2317 Register NewDstReg = MRI.createGenericVirtualRegister(S32);
2318 MRI.setRegBank(NewDstReg, AMDGPU::SGPRRegBank);
2319 MI.getOperand(BoolDstOp).setReg(NewDstReg);
2320
2321 if (HasCarryIn) {
2322 Register NewSrcReg = MRI.createGenericVirtualRegister(S32);
2323 MRI.setRegBank(NewSrcReg, AMDGPU::SGPRRegBank);
2324 B.buildZExt(NewSrcReg, MI.getOperand(4).getReg());
2325 MI.getOperand(4).setReg(NewSrcReg);
2326 }
2327
2328 MachineBasicBlock *MBB = MI.getParent();
2329 B.setInsertPt(*MBB, std::next(MI.getIterator()));
2330
2331 // If we had a constrained VCC result register, a copy was inserted to VCC
2332 // from SGPR.
2333 SmallVector<Register, 1> DefRegs(OpdMapper.getVRegs(0));
2334 if (DefRegs.empty())
2335 DefRegs.push_back(DstReg);
2336 B.buildTrunc(DefRegs[0], NewDstReg);
2337 return;
2338 }
2339 case AMDGPU::G_SELECT: {
2340 Register DstReg = MI.getOperand(0).getReg();
2341 LLT DstTy = MRI.getType(DstReg);
2342
2343 SmallVector<Register, 1> CondRegs(OpdMapper.getVRegs(1));
2344 if (CondRegs.empty())
2345 CondRegs.push_back(MI.getOperand(1).getReg());
2346 else {
2347 assert(CondRegs.size() == 1);
2348 }
2349
2350 const RegisterBank *CondBank = getRegBank(CondRegs[0], MRI, *TRI);
2351 if (CondBank == &AMDGPU::SGPRRegBank) {
2352 const LLT S32 = LLT::scalar(32);
2353 Register NewCondReg = MRI.createGenericVirtualRegister(S32);
2354 MRI.setRegBank(NewCondReg, AMDGPU::SGPRRegBank);
2355
2356 MI.getOperand(1).setReg(NewCondReg);
2357 B.buildZExt(NewCondReg, CondRegs[0]);
2358 }
2359
2360 if (DstTy.getSizeInBits() != 64)
2361 break;
2362
2363 LLT HalfTy = getHalfSizedType(DstTy);
2364
2365 SmallVector<Register, 2> DefRegs(OpdMapper.getVRegs(0));
2366 SmallVector<Register, 2> Src1Regs(OpdMapper.getVRegs(2));
2367 SmallVector<Register, 2> Src2Regs(OpdMapper.getVRegs(3));
2368
2369 // All inputs are SGPRs, nothing special to do.
2370 if (DefRegs.empty()) {
2371 assert(Src1Regs.empty() && Src2Regs.empty());
2372 break;
2373 }
2374
2375 if (Src1Regs.empty())
2376 split64BitValueForMapping(B, Src1Regs, HalfTy, MI.getOperand(2).getReg());
2377 else {
2378 setRegsToType(MRI, Src1Regs, HalfTy);
2379 }
2380
2381 if (Src2Regs.empty())
2382 split64BitValueForMapping(B, Src2Regs, HalfTy, MI.getOperand(3).getReg());
2383 else
2384 setRegsToType(MRI, Src2Regs, HalfTy);
2385
2386 setRegsToType(MRI, DefRegs, HalfTy);
2387
2388 auto Flags = MI.getFlags();
2389 B.buildSelect(DefRegs[0], CondRegs[0], Src1Regs[0], Src2Regs[0], Flags);
2390 B.buildSelect(DefRegs[1], CondRegs[0], Src1Regs[1], Src2Regs[1], Flags);
2391
2392 MRI.setRegBank(DstReg, AMDGPU::VGPRRegBank);
2393 MI.eraseFromParent();
2394 return;
2395 }
2396 case AMDGPU::G_BRCOND: {
2397 Register CondReg = MI.getOperand(0).getReg();
2398 // FIXME: Should use legalizer helper, but should change bool ext type.
2399 const RegisterBank *CondBank =
2400 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2401
2402 if (CondBank == &AMDGPU::SGPRRegBank) {
2403 const LLT S32 = LLT::scalar(32);
2404 Register NewCondReg = MRI.createGenericVirtualRegister(S32);
2405 MRI.setRegBank(NewCondReg, AMDGPU::SGPRRegBank);
2406
2407 MI.getOperand(0).setReg(NewCondReg);
2408 B.buildZExt(NewCondReg, CondReg);
2409 return;
2410 }
2411
2412 break;
2413 }
2414 case AMDGPU::G_AND:
2415 case AMDGPU::G_OR:
2416 case AMDGPU::G_XOR: {
2417 // 64-bit and is only available on the SALU, so split into 2 32-bit ops if
2418 // there is a VGPR input.
2419 Register DstReg = MI.getOperand(0).getReg();
2420 LLT DstTy = MRI.getType(DstReg);
2421
2422 const RegisterBank *DstBank =
2423 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2424
2425 if (DstTy.getSizeInBits() == 1) {
2426 if (DstBank == &AMDGPU::VCCRegBank)
2427 break;
2428
2429 MachineFunction *MF = MI.getMF();
2430 ApplyRegBankMapping ApplyBank(B, *this, MRI, DstBank);
2431 LegalizerHelper Helper(*MF, ApplyBank, B);
2432
2433 if (Helper.widenScalar(MI, 0, LLT::scalar(32)) !=
2435 llvm_unreachable("widen scalar should have succeeded");
2436 return;
2437 }
2438
2439 if (DstTy.getSizeInBits() == 16 && DstBank == &AMDGPU::SGPRRegBank) {
2440 const LLT S32 = LLT::scalar(32);
2441 MachineBasicBlock *MBB = MI.getParent();
2442 MachineFunction *MF = MBB->getParent();
2443 ApplyRegBankMapping ApplySALU(B, *this, MRI, &AMDGPU::SGPRRegBank);
2444 LegalizerHelper Helper(*MF, ApplySALU, B);
2445 // Widen to S32, but handle `G_XOR x, -1` differently. Legalizer widening
2446 // will use a G_ANYEXT to extend the -1 which prevents matching G_XOR -1
2447 // as "not".
2448 if (MI.getOpcode() == AMDGPU::G_XOR &&
2449 mi_match(MI.getOperand(2).getReg(), MRI, m_SpecificICstOrSplat(-1))) {
2450 Helper.widenScalarSrc(MI, S32, 1, AMDGPU::G_ANYEXT);
2451 Helper.widenScalarSrc(MI, S32, 2, AMDGPU::G_SEXT);
2452 Helper.widenScalarDst(MI, S32);
2453 } else {
2454 if (Helper.widenScalar(MI, 0, S32) != LegalizerHelper::Legalized)
2455 llvm_unreachable("widen scalar should have succeeded");
2456 }
2457 return;
2458 }
2459
2460 if (DstTy.getSizeInBits() != 64)
2461 break;
2462
2463 LLT HalfTy = getHalfSizedType(DstTy);
2464 SmallVector<Register, 2> DefRegs(OpdMapper.getVRegs(0));
2465 SmallVector<Register, 2> Src0Regs(OpdMapper.getVRegs(1));
2466 SmallVector<Register, 2> Src1Regs(OpdMapper.getVRegs(2));
2467
2468 // All inputs are SGPRs, nothing special to do.
2469 if (DefRegs.empty()) {
2470 assert(Src0Regs.empty() && Src1Regs.empty());
2471 break;
2472 }
2473
2474 assert(DefRegs.size() == 2);
2475 assert(Src0Regs.size() == Src1Regs.size() &&
2476 (Src0Regs.empty() || Src0Regs.size() == 2));
2477
2478 // Depending on where the source registers came from, the generic code may
2479 // have decided to split the inputs already or not. If not, we still need to
2480 // extract the values.
2481
2482 if (Src0Regs.empty())
2483 split64BitValueForMapping(B, Src0Regs, HalfTy, MI.getOperand(1).getReg());
2484 else
2485 setRegsToType(MRI, Src0Regs, HalfTy);
2486
2487 if (Src1Regs.empty())
2488 split64BitValueForMapping(B, Src1Regs, HalfTy, MI.getOperand(2).getReg());
2489 else
2490 setRegsToType(MRI, Src1Regs, HalfTy);
2491
2492 setRegsToType(MRI, DefRegs, HalfTy);
2493
2494 auto Flags = MI.getFlags();
2495 B.buildInstr(Opc, {DefRegs[0]}, {Src0Regs[0], Src1Regs[0]}, Flags);
2496 B.buildInstr(Opc, {DefRegs[1]}, {Src0Regs[1], Src1Regs[1]}, Flags);
2497
2498 MRI.setRegBank(DstReg, AMDGPU::VGPRRegBank);
2499 MI.eraseFromParent();
2500 return;
2501 }
2502 case AMDGPU::G_ABS: {
2503 Register SrcReg = MI.getOperand(1).getReg();
2504 const RegisterBank *SrcBank = MRI.getRegBankOrNull(SrcReg);
2505
2506 // There is no VALU abs instruction so we need to replace it with a sub and
2507 // max combination.
2508 if (SrcBank && SrcBank == &AMDGPU::VGPRRegBank) {
2509 MachineFunction *MF = MI.getMF();
2510 ApplyRegBankMapping Apply(B, *this, MRI, &AMDGPU::VGPRRegBank);
2511 LegalizerHelper Helper(*MF, Apply, B);
2512
2514 llvm_unreachable("lowerAbsToMaxNeg should have succeeded");
2515 return;
2516 }
2517 [[fallthrough]];
2518 }
2519 case AMDGPU::G_ADD:
2520 case AMDGPU::G_SUB:
2521 case AMDGPU::G_MUL:
2522 case AMDGPU::G_SHL:
2523 case AMDGPU::G_LSHR:
2524 case AMDGPU::G_ASHR:
2525 case AMDGPU::G_SMIN:
2526 case AMDGPU::G_SMAX:
2527 case AMDGPU::G_UMIN:
2528 case AMDGPU::G_UMAX: {
2529 Register DstReg = MI.getOperand(0).getReg();
2530 LLT DstTy = MRI.getType(DstReg);
2531
2532 // Special case for s_mul_u64. There is not a vector equivalent of
2533 // s_mul_u64. Hence, we have to break down s_mul_u64 into 32-bit vector
2534 // multiplications.
2535 if (!Subtarget.useVMulU64Inst() && Opc == AMDGPU::G_MUL &&
2536 DstTy.getSizeInBits() == 64) {
2537 applyMappingSMULU64(B, OpdMapper);
2538 return;
2539 }
2540
2541 // 16-bit operations are VALU only, but can be promoted to 32-bit SALU.
2542 // Packed 16-bit operations need to be scalarized and promoted.
2543 if (DstTy != LLT::scalar(16) && DstTy != LLT::fixed_vector(2, 16))
2544 break;
2545
2546 const RegisterBank *DstBank =
2547 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2548 if (DstBank == &AMDGPU::VGPRRegBank)
2549 break;
2550
2551 const LLT S32 = LLT::scalar(32);
2552 MachineBasicBlock *MBB = MI.getParent();
2553 MachineFunction *MF = MBB->getParent();
2554 ApplyRegBankMapping ApplySALU(B, *this, MRI, &AMDGPU::SGPRRegBank);
2555
2556 if (DstTy.isVector() && Opc == AMDGPU::G_ABS) {
2557 Register WideSrcLo, WideSrcHi;
2558
2559 std::tie(WideSrcLo, WideSrcHi) =
2560 unpackV2S16ToS32(B, MI.getOperand(1).getReg(), TargetOpcode::G_SEXT);
2561 auto Lo = B.buildInstr(AMDGPU::G_ABS, {S32}, {WideSrcLo});
2562 auto Hi = B.buildInstr(AMDGPU::G_ABS, {S32}, {WideSrcHi});
2563 B.buildBuildVectorTrunc(DstReg, {Lo.getReg(0), Hi.getReg(0)});
2564 MI.eraseFromParent();
2565 return;
2566 }
2567
2568 if (DstTy.isVector()) {
2569 Register WideSrc0Lo, WideSrc0Hi;
2570 Register WideSrc1Lo, WideSrc1Hi;
2571
2572 unsigned ExtendOp = getExtendOp(MI.getOpcode());
2573 std::tie(WideSrc0Lo, WideSrc0Hi)
2574 = unpackV2S16ToS32(B, MI.getOperand(1).getReg(), ExtendOp);
2575 std::tie(WideSrc1Lo, WideSrc1Hi)
2576 = unpackV2S16ToS32(B, MI.getOperand(2).getReg(), ExtendOp);
2577 auto Lo = B.buildInstr(MI.getOpcode(), {S32}, {WideSrc0Lo, WideSrc1Lo});
2578 auto Hi = B.buildInstr(MI.getOpcode(), {S32}, {WideSrc0Hi, WideSrc1Hi});
2579 B.buildBuildVectorTrunc(DstReg, {Lo.getReg(0), Hi.getReg(0)});
2580 MI.eraseFromParent();
2581 } else {
2582 LegalizerHelper Helper(*MF, ApplySALU, B);
2583
2584 if (Helper.widenScalar(MI, 0, S32) != LegalizerHelper::Legalized)
2585 llvm_unreachable("widen scalar should have succeeded");
2586
2587 // FIXME: s16 shift amounts should be legal.
2588 if (Opc == AMDGPU::G_SHL || Opc == AMDGPU::G_LSHR ||
2589 Opc == AMDGPU::G_ASHR) {
2590 B.setInsertPt(*MBB, MI.getIterator());
2591 if (Helper.widenScalar(MI, 1, S32) != LegalizerHelper::Legalized)
2592 llvm_unreachable("widen scalar should have succeeded");
2593 }
2594 }
2595
2596 return;
2597 }
2598 case AMDGPU::G_AMDGPU_S_MUL_I64_I32:
2599 case AMDGPU::G_AMDGPU_S_MUL_U64_U32: {
2600 // This is a special case for s_mul_u64. We use
2601 // G_AMDGPU_S_MUL_I64_I32 opcode to represent an s_mul_u64 operation
2602 // where the 33 higher bits are sign-extended and
2603 // G_AMDGPU_S_MUL_U64_U32 opcode to represent an s_mul_u64 operation
2604 // where the 32 higher bits are zero-extended. In case scalar registers are
2605 // selected, both opcodes are lowered as s_mul_u64. If the vector registers
2606 // are selected, then G_AMDGPU_S_MUL_I64_I32 and
2607 // G_AMDGPU_S_MUL_U64_U32 are lowered with a vector mad instruction.
2608
2609 // Insert basic copies.
2610 applyDefaultMapping(OpdMapper);
2611
2612 Register DstReg = MI.getOperand(0).getReg();
2613 Register SrcReg0 = MI.getOperand(1).getReg();
2614 Register SrcReg1 = MI.getOperand(2).getReg();
2615 const LLT S32 = LLT::scalar(32);
2616 const LLT S64 = LLT::scalar(64);
2617 assert(MRI.getType(DstReg) == S64 && "This is a special case for s_mul_u64 "
2618 "that handles only 64-bit operands.");
2619 const RegisterBank *DstBank =
2620 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2621
2622 // Replace G_AMDGPU_S_MUL_I64_I32 and G_AMDGPU_S_MUL_U64_U32
2623 // with s_mul_u64 operation.
2624 if (DstBank == &AMDGPU::SGPRRegBank) {
2625 MI.setDesc(TII->get(AMDGPU::S_MUL_U64));
2626 MRI.setRegClass(DstReg, &AMDGPU::SGPR_64RegClass);
2627 MRI.setRegClass(SrcReg0, &AMDGPU::SGPR_64RegClass);
2628 MRI.setRegClass(SrcReg1, &AMDGPU::SGPR_64RegClass);
2629 return;
2630 }
2631
2632 // Replace G_AMDGPU_S_MUL_I64_I32 and G_AMDGPU_S_MUL_U64_U32
2633 // with a vector mad.
2634 assert(MRI.getRegBankOrNull(DstReg) == &AMDGPU::VGPRRegBank &&
2635 "The destination operand should be in vector registers.");
2636
2637 // Extract the lower subregister from the first operand.
2638 Register Op0L = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2639 MRI.setRegClass(Op0L, &AMDGPU::VGPR_32RegClass);
2640 MRI.setType(Op0L, S32);
2641 B.buildTrunc(Op0L, SrcReg0);
2642
2643 // Extract the lower subregister from the second operand.
2644 Register Op1L = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2645 MRI.setRegClass(Op1L, &AMDGPU::VGPR_32RegClass);
2646 MRI.setType(Op1L, S32);
2647 B.buildTrunc(Op1L, SrcReg1);
2648
2649 unsigned NewOpc = Opc == AMDGPU::G_AMDGPU_S_MUL_U64_U32
2650 ? AMDGPU::G_AMDGPU_MAD_U64_U32
2651 : AMDGPU::G_AMDGPU_MAD_I64_I32;
2652
2654 Register Zero64 = B.buildConstant(S64, 0).getReg(0);
2655 MRI.setRegClass(Zero64, &AMDGPU::VReg_64RegClass);
2656 Register CarryOut = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
2657 MRI.setRegClass(CarryOut, &AMDGPU::VReg_64RegClass);
2658 B.buildInstr(NewOpc, {DstReg, CarryOut}, {Op0L, Op1L, Zero64});
2659 MI.eraseFromParent();
2660 return;
2661 }
2662 case AMDGPU::G_SEXT_INREG: {
2663 SmallVector<Register, 2> SrcRegs(OpdMapper.getVRegs(1));
2664 if (SrcRegs.empty())
2665 break; // Nothing to repair
2666
2667 const LLT S32 = LLT::scalar(32);
2668 ApplyRegBankMapping O(B, *this, MRI, &AMDGPU::VGPRRegBank);
2669
2670 // Don't use LegalizerHelper's narrowScalar. It produces unwanted G_SEXTs
2671 // we would need to further expand, and doesn't let us directly set the
2672 // result registers.
2673 SmallVector<Register, 2> DstRegs(OpdMapper.getVRegs(0));
2674
2675 int Amt = MI.getOperand(2).getImm();
2676 if (Amt <= 32) {
2677 // Downstream users have expectations for the high bit behavior, so freeze
2678 // incoming undefined bits.
2679 if (Amt == 32) {
2680 // The low bits are unchanged.
2681 B.buildFreeze(DstRegs[0], SrcRegs[0]);
2682 } else {
2683 auto Freeze = B.buildFreeze(S32, SrcRegs[0]);
2684 // Extend in the low bits and propagate the sign bit to the high half.
2685 B.buildSExtInReg(DstRegs[0], Freeze, Amt);
2686 }
2687
2688 B.buildAShr(DstRegs[1], DstRegs[0], B.buildConstant(S32, 31));
2689 } else {
2690 // The low bits are unchanged, and extend in the high bits.
2691 // No freeze required
2692 B.buildCopy(DstRegs[0], SrcRegs[0]);
2693 B.buildSExtInReg(DstRegs[1], DstRegs[0], Amt - 32);
2694 }
2695
2696 Register DstReg = MI.getOperand(0).getReg();
2697 MRI.setRegBank(DstReg, AMDGPU::VGPRRegBank);
2698 MI.eraseFromParent();
2699 return;
2700 }
2701 case AMDGPU::G_CTPOP:
2702 case AMDGPU::G_BITREVERSE: {
2703 const RegisterBank *DstBank =
2704 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2705 if (DstBank == &AMDGPU::SGPRRegBank)
2706 break;
2707
2708 Register SrcReg = MI.getOperand(1).getReg();
2709 const LLT S32 = LLT::scalar(32);
2710 LLT Ty = MRI.getType(SrcReg);
2711 if (Ty == S32)
2712 break;
2713
2714 ApplyRegBankMapping ApplyVALU(B, *this, MRI, &AMDGPU::VGPRRegBank);
2715
2716 MachineFunction &MF = B.getMF();
2717 LegalizerHelper Helper(MF, ApplyVALU, B);
2718
2719 if (Helper.narrowScalar(MI, 1, S32) != LegalizerHelper::Legalized)
2720 llvm_unreachable("narrowScalar should have succeeded");
2721 return;
2722 }
2723 case AMDGPU::G_AMDGPU_FFBH_U32:
2724 case AMDGPU::G_AMDGPU_FFBL_B32:
2725 case AMDGPU::G_CTLZ_ZERO_POISON:
2726 case AMDGPU::G_CTTZ_ZERO_POISON: {
2727 const RegisterBank *DstBank =
2728 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2729 if (DstBank == &AMDGPU::SGPRRegBank)
2730 break;
2731
2732 Register SrcReg = MI.getOperand(1).getReg();
2733 const LLT S32 = LLT::scalar(32);
2734 LLT Ty = MRI.getType(SrcReg);
2735 if (Ty == S32)
2736 break;
2737
2738 // We can narrow this more efficiently than Helper can by using ffbh/ffbl
2739 // which return -1 when the input is zero:
2740 // (ctlz_zero_poison hi:lo) -> (umin (ffbh hi), (add (ffbh lo), 32))
2741 // (cttz_zero_poison hi:lo) -> (umin (add (ffbl hi), 32), (ffbl lo))
2742 // (ffbh hi:lo) -> (umin (ffbh hi), (uaddsat (ffbh lo), 32))
2743 // (ffbl hi:lo) -> (umin (uaddsat (ffbh hi), 32), (ffbh lo))
2744 ApplyRegBankMapping ApplyVALU(B, *this, MRI, &AMDGPU::VGPRRegBank);
2745 SmallVector<Register, 2> SrcRegs(OpdMapper.getVRegs(1));
2746 unsigned NewOpc = Opc == AMDGPU::G_CTLZ_ZERO_POISON
2747 ? (unsigned)AMDGPU::G_AMDGPU_FFBH_U32
2748 : Opc == AMDGPU::G_CTTZ_ZERO_POISON
2749 ? (unsigned)AMDGPU::G_AMDGPU_FFBL_B32
2750 : Opc;
2751 unsigned Idx = NewOpc == AMDGPU::G_AMDGPU_FFBH_U32;
2752 auto X = B.buildInstr(NewOpc, {S32}, {SrcRegs[Idx]});
2753 auto Y = B.buildInstr(NewOpc, {S32}, {SrcRegs[Idx ^ 1]});
2754 unsigned AddOpc =
2755 Opc == AMDGPU::G_CTLZ_ZERO_POISON || Opc == AMDGPU::G_CTTZ_ZERO_POISON
2756 ? AMDGPU::G_ADD
2757 : AMDGPU::G_UADDSAT;
2758 Y = B.buildInstr(AddOpc, {S32}, {Y, B.buildConstant(S32, 32)});
2759 Register DstReg = MI.getOperand(0).getReg();
2760 B.buildUMin(DstReg, X, Y);
2761 MI.eraseFromParent();
2762 return;
2763 }
2764 case AMDGPU::G_SEXT:
2765 case AMDGPU::G_ZEXT:
2766 case AMDGPU::G_ANYEXT: {
2767 Register SrcReg = MI.getOperand(1).getReg();
2768 LLT SrcTy = MRI.getType(SrcReg);
2769 const bool Signed = Opc == AMDGPU::G_SEXT;
2770
2771 assert(OpdMapper.getVRegs(1).empty());
2772
2773 const RegisterBank *SrcBank =
2774 OpdMapper.getInstrMapping().getOperandMapping(1).BreakDown[0].RegBank;
2775
2776 Register DstReg = MI.getOperand(0).getReg();
2777 LLT DstTy = MRI.getType(DstReg);
2778 if (DstTy.isScalar() &&
2779 SrcBank != &AMDGPU::SGPRRegBank &&
2780 SrcBank != &AMDGPU::VCCRegBank &&
2781 // FIXME: Should handle any type that round to s64 when irregular
2782 // breakdowns supported.
2783 DstTy.getSizeInBits() == 64 &&
2784 SrcTy.getSizeInBits() <= 32) {
2785 SmallVector<Register, 2> DefRegs(OpdMapper.getVRegs(0));
2786
2787 // Extend to 32-bit, and then extend the low half.
2788 if (Signed) {
2789 // TODO: Should really be buildSExtOrCopy
2790 B.buildSExtOrTrunc(DefRegs[0], SrcReg);
2791 } else if (Opc == AMDGPU::G_ZEXT) {
2792 B.buildZExtOrTrunc(DefRegs[0], SrcReg);
2793 } else {
2794 B.buildAnyExtOrTrunc(DefRegs[0], SrcReg);
2795 }
2796
2797 extendLow32IntoHigh32(B, DefRegs[1], DefRegs[0], Opc, *SrcBank);
2798 MRI.setRegBank(DstReg, *SrcBank);
2799 MI.eraseFromParent();
2800 return;
2801 }
2802
2803 if (SrcTy != LLT::scalar(1))
2804 return;
2805
2806 // It is not legal to have a legalization artifact with a VCC source. Rather
2807 // than introducing a copy, insert the select we would have to select the
2808 // copy to.
2809 if (SrcBank == &AMDGPU::VCCRegBank) {
2810 SmallVector<Register, 2> DefRegs(OpdMapper.getVRegs(0));
2811
2812 const RegisterBank *DstBank = &AMDGPU::VGPRRegBank;
2813
2814 unsigned DstSize = DstTy.getSizeInBits();
2815 // 64-bit select is SGPR only
2816 const bool UseSel64 = DstSize > 32 &&
2817 SrcBank->getID() == AMDGPU::SGPRRegBankID;
2818
2819 // TODO: Should s16 select be legal?
2820 LLT SelType = UseSel64 ? LLT::scalar(64) : LLT::scalar(32);
2821 auto True = B.buildConstant(SelType, Signed ? -1 : 1);
2822 auto False = B.buildConstant(SelType, 0);
2823
2824 MRI.setRegBank(True.getReg(0), *DstBank);
2825 MRI.setRegBank(False.getReg(0), *DstBank);
2826 MRI.setRegBank(DstReg, *DstBank);
2827
2828 if (DstSize > 32) {
2829 B.buildSelect(DefRegs[0], SrcReg, True, False);
2830 extendLow32IntoHigh32(B, DefRegs[1], DefRegs[0], Opc, *SrcBank, true);
2831 } else if (DstSize < 32) {
2832 auto Sel = B.buildSelect(SelType, SrcReg, True, False);
2833 MRI.setRegBank(Sel.getReg(0), *DstBank);
2834 B.buildTrunc(DstReg, Sel);
2835 } else {
2836 B.buildSelect(DstReg, SrcReg, True, False);
2837 }
2838
2839 MI.eraseFromParent();
2840 return;
2841 }
2842
2843 break;
2844 }
2845 case AMDGPU::G_EXTRACT_VECTOR_ELT: {
2846 SmallVector<Register, 2> DstRegs(OpdMapper.getVRegs(0));
2847
2848 assert(OpdMapper.getVRegs(1).empty() && OpdMapper.getVRegs(2).empty());
2849
2850 Register DstReg = MI.getOperand(0).getReg();
2851 Register SrcReg = MI.getOperand(1).getReg();
2852
2853 const LLT S32 = LLT::scalar(32);
2854 LLT DstTy = MRI.getType(DstReg);
2855 LLT SrcTy = MRI.getType(SrcReg);
2856
2857 if (foldExtractEltToCmpSelect(B, MI, OpdMapper))
2858 return;
2859
2860 const ValueMapping &DstMapping
2861 = OpdMapper.getInstrMapping().getOperandMapping(0);
2862 const RegisterBank *DstBank = DstMapping.BreakDown[0].RegBank;
2863 const RegisterBank *SrcBank =
2864 OpdMapper.getInstrMapping().getOperandMapping(1).BreakDown[0].RegBank;
2865 const RegisterBank *IdxBank =
2866 OpdMapper.getInstrMapping().getOperandMapping(2).BreakDown[0].RegBank;
2867
2868 Register BaseIdxReg;
2869 unsigned ConstOffset;
2870 std::tie(BaseIdxReg, ConstOffset) =
2871 AMDGPU::getBaseWithConstantOffset(MRI, MI.getOperand(2).getReg());
2872
2873 // See if the index is an add of a constant which will be foldable by moving
2874 // the base register of the index later if this is going to be executed in a
2875 // waterfall loop. This is essentially to reassociate the add of a constant
2876 // with the readfirstlane.
2877 bool ShouldMoveIndexIntoLoop = IdxBank != &AMDGPU::SGPRRegBank &&
2878 ConstOffset > 0 &&
2879 ConstOffset < SrcTy.getNumElements();
2880
2881 // Move the base register. We'll re-insert the add later.
2882 if (ShouldMoveIndexIntoLoop)
2883 MI.getOperand(2).setReg(BaseIdxReg);
2884
2885 // If this is a VGPR result only because the index was a VGPR result, the
2886 // actual indexing will be done on the SGPR source vector, which will
2887 // produce a scalar result. We need to copy to the VGPR result inside the
2888 // waterfall loop.
2889 const bool NeedCopyToVGPR = DstBank == &AMDGPU::VGPRRegBank &&
2890 SrcBank == &AMDGPU::SGPRRegBank;
2891 if (DstRegs.empty()) {
2892 applyDefaultMapping(OpdMapper);
2893
2895
2896 if (NeedCopyToVGPR) {
2897 // We don't want a phi for this temporary reg.
2898 Register TmpReg = MRI.createGenericVirtualRegister(DstTy);
2899 MRI.setRegBank(TmpReg, AMDGPU::SGPRRegBank);
2900 MI.getOperand(0).setReg(TmpReg);
2901 B.setInsertPt(*MI.getParent(), ++MI.getIterator());
2902
2903 // Use a v_mov_b32 here to make the exec dependency explicit.
2904 buildVCopy(B, DstReg, TmpReg);
2905 }
2906
2907 // Re-insert the constant offset add inside the waterfall loop.
2908 if (ShouldMoveIndexIntoLoop)
2909 reinsertVectorIndexAdd(B, MI, 2, ConstOffset);
2910
2911 return;
2912 }
2913
2914 assert(DstTy.getSizeInBits() == 64);
2915
2916 LLT Vec32 = LLT::fixed_vector(2 * SrcTy.getNumElements(), 32);
2917
2918 auto CastSrc = B.buildBitcast(Vec32, SrcReg);
2919 auto One = B.buildConstant(S32, 1);
2920
2921 MachineBasicBlock::iterator MII = MI.getIterator();
2922
2923 // Split the vector index into 32-bit pieces. Prepare to move all of the
2924 // new instructions into a waterfall loop if necessary.
2925 //
2926 // Don't put the bitcast or constant in the loop.
2927 MachineInstrSpan Span(MII, &B.getMBB());
2928
2929 // Compute 32-bit element indices, (2 * OrigIdx, 2 * OrigIdx + 1).
2930 auto IdxLo = B.buildShl(S32, BaseIdxReg, One);
2931 auto IdxHi = B.buildAdd(S32, IdxLo, One);
2932
2933 auto Extract0 = B.buildExtractVectorElement(DstRegs[0], CastSrc, IdxLo);
2934 auto Extract1 = B.buildExtractVectorElement(DstRegs[1], CastSrc, IdxHi);
2935
2936 MRI.setRegBank(DstReg, *DstBank);
2937 MRI.setRegBank(CastSrc.getReg(0), *SrcBank);
2938 MRI.setRegBank(One.getReg(0), AMDGPU::SGPRRegBank);
2939 MRI.setRegBank(IdxLo.getReg(0), AMDGPU::SGPRRegBank);
2940 MRI.setRegBank(IdxHi.getReg(0), AMDGPU::SGPRRegBank);
2941
2942 SmallSet<Register, 4> OpsToWaterfall;
2943 if (!collectWaterfallOperands(OpsToWaterfall, MI, MRI, { 2 })) {
2944 MI.eraseFromParent();
2945 return;
2946 }
2947
2948 // Remove the original instruction to avoid potentially confusing the
2949 // waterfall loop logic.
2950 B.setInstr(*Span.begin());
2951 MI.eraseFromParent();
2952 executeInWaterfallLoop(B, make_range(Span.begin(), Span.end()),
2953 OpsToWaterfall);
2954
2955 if (NeedCopyToVGPR) {
2956 MachineBasicBlock *LoopBB = Extract1->getParent();
2959 MRI.setRegBank(TmpReg0, AMDGPU::SGPRRegBank);
2960 MRI.setRegBank(TmpReg1, AMDGPU::SGPRRegBank);
2961
2962 Extract0->getOperand(0).setReg(TmpReg0);
2963 Extract1->getOperand(0).setReg(TmpReg1);
2964
2965 B.setInsertPt(*LoopBB, ++Extract1->getIterator());
2966
2967 buildVCopy(B, DstRegs[0], TmpReg0);
2968 buildVCopy(B, DstRegs[1], TmpReg1);
2969 }
2970
2971 if (ShouldMoveIndexIntoLoop)
2972 reinsertVectorIndexAdd(B, *IdxLo, 1, ConstOffset);
2973
2974 return;
2975 }
2976 case AMDGPU::G_INSERT_VECTOR_ELT: {
2977 SmallVector<Register, 2> InsRegs(OpdMapper.getVRegs(2));
2978
2979 Register DstReg = MI.getOperand(0).getReg();
2980 LLT VecTy = MRI.getType(DstReg);
2981
2982 assert(OpdMapper.getVRegs(0).empty());
2983 assert(OpdMapper.getVRegs(3).empty());
2984
2985 if (substituteSimpleCopyRegs(OpdMapper, 1))
2986 MRI.setType(MI.getOperand(1).getReg(), VecTy);
2987
2988 if (foldInsertEltToCmpSelect(B, MI, OpdMapper))
2989 return;
2990
2991 const RegisterBank *IdxBank =
2992 OpdMapper.getInstrMapping().getOperandMapping(3).BreakDown[0].RegBank;
2993
2994 Register SrcReg = MI.getOperand(1).getReg();
2995 Register InsReg = MI.getOperand(2).getReg();
2996 LLT InsTy = MRI.getType(InsReg);
2997 (void)InsTy;
2998
2999 Register BaseIdxReg;
3000 unsigned ConstOffset;
3001 std::tie(BaseIdxReg, ConstOffset) =
3002 AMDGPU::getBaseWithConstantOffset(MRI, MI.getOperand(3).getReg());
3003
3004 // See if the index is an add of a constant which will be foldable by moving
3005 // the base register of the index later if this is going to be executed in a
3006 // waterfall loop. This is essentially to reassociate the add of a constant
3007 // with the readfirstlane.
3008 bool ShouldMoveIndexIntoLoop = IdxBank != &AMDGPU::SGPRRegBank &&
3009 ConstOffset > 0 &&
3010 ConstOffset < VecTy.getNumElements();
3011
3012 // Move the base register. We'll re-insert the add later.
3013 if (ShouldMoveIndexIntoLoop)
3014 MI.getOperand(3).setReg(BaseIdxReg);
3015
3016
3017 if (InsRegs.empty()) {
3019
3020 // Re-insert the constant offset add inside the waterfall loop.
3021 if (ShouldMoveIndexIntoLoop) {
3022 reinsertVectorIndexAdd(B, MI, 3, ConstOffset);
3023 }
3024
3025 return;
3026 }
3027
3028 assert(InsTy.getSizeInBits() == 64);
3029
3030 const LLT S32 = LLT::scalar(32);
3031 LLT Vec32 = LLT::fixed_vector(2 * VecTy.getNumElements(), 32);
3032
3033 auto CastSrc = B.buildBitcast(Vec32, SrcReg);
3034 auto One = B.buildConstant(S32, 1);
3035
3036 // Split the vector index into 32-bit pieces. Prepare to move all of the
3037 // new instructions into a waterfall loop if necessary.
3038 //
3039 // Don't put the bitcast or constant in the loop.
3041
3042 // Compute 32-bit element indices, (2 * OrigIdx, 2 * OrigIdx + 1).
3043 auto IdxLo = B.buildShl(S32, BaseIdxReg, One);
3044 auto IdxHi = B.buildAdd(S32, IdxLo, One);
3045
3046 auto InsLo = B.buildInsertVectorElement(Vec32, CastSrc, InsRegs[0], IdxLo);
3047 auto InsHi = B.buildInsertVectorElement(Vec32, InsLo, InsRegs[1], IdxHi);
3048
3049 const RegisterBank *DstBank =
3050 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
3051 const RegisterBank *SrcBank =
3052 OpdMapper.getInstrMapping().getOperandMapping(1).BreakDown[0].RegBank;
3053 const RegisterBank *InsSrcBank =
3054 OpdMapper.getInstrMapping().getOperandMapping(2).BreakDown[0].RegBank;
3055
3056 MRI.setRegBank(InsReg, *InsSrcBank);
3057 MRI.setRegBank(CastSrc.getReg(0), *SrcBank);
3058 MRI.setRegBank(InsLo.getReg(0), *DstBank);
3059 MRI.setRegBank(InsHi.getReg(0), *DstBank);
3060 MRI.setRegBank(One.getReg(0), AMDGPU::SGPRRegBank);
3061 MRI.setRegBank(IdxLo.getReg(0), AMDGPU::SGPRRegBank);
3062 MRI.setRegBank(IdxHi.getReg(0), AMDGPU::SGPRRegBank);
3063
3064
3065 SmallSet<Register, 4> OpsToWaterfall;
3066 if (!collectWaterfallOperands(OpsToWaterfall, MI, MRI, { 3 })) {
3067 B.setInsertPt(B.getMBB(), MI);
3068 B.buildBitcast(DstReg, InsHi);
3069 MI.eraseFromParent();
3070 return;
3071 }
3072
3073 B.setInstr(*Span.begin());
3074 MI.eraseFromParent();
3075
3076 // Figure out the point after the waterfall loop before mangling the control
3077 // flow.
3078 executeInWaterfallLoop(B, make_range(Span.begin(), Span.end()),
3079 OpsToWaterfall);
3080
3081 // The insertion point is now right after the original instruction.
3082 //
3083 // Keep the bitcast to the original vector type out of the loop. Doing this
3084 // saved an extra phi we don't need inside the loop.
3085 B.buildBitcast(DstReg, InsHi);
3086
3087 // Re-insert the constant offset add inside the waterfall loop.
3088 if (ShouldMoveIndexIntoLoop)
3089 reinsertVectorIndexAdd(B, *IdxLo, 1, ConstOffset);
3090
3091 return;
3092 }
3093 case AMDGPU::G_AMDGPU_BUFFER_LOAD:
3094 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
3095 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT:
3096 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
3097 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE:
3098 case AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE:
3099 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE:
3100 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT_TFE:
3101 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE:
3102 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE_TFE:
3103 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT:
3104 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE:
3105 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16:
3106 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16_TFE:
3107 case AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT:
3108 case AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16:
3109 case AMDGPU::G_AMDGPU_BUFFER_STORE:
3110 case AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE:
3111 case AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT:
3112 case AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT:
3113 case AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16:
3114 case AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT:
3115 case AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16: {
3116 applyDefaultMapping(OpdMapper);
3117 executeInWaterfallLoop(B, MI, {1, 4});
3118 return;
3119 }
3120 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP:
3121 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD:
3122 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB:
3123 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN:
3124 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN:
3125 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX:
3126 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX:
3127 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND:
3128 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR:
3129 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR:
3130 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC:
3131 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC:
3132 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32:
3133 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32:
3134 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD:
3135 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN:
3136 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX: {
3137 applyDefaultMapping(OpdMapper);
3138 executeInWaterfallLoop(B, MI, {2, 5});
3139 return;
3140 }
3141 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP: {
3142 applyDefaultMapping(OpdMapper);
3143 executeInWaterfallLoop(B, MI, {3, 6});
3144 return;
3145 }
3146 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD:
3147 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
3148 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE:
3149 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
3150 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT: {
3151 applyMappingSBufferLoad(B, OpdMapper);
3152 return;
3153 }
3154 case AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH:
3157 return;
3158 case AMDGPU::G_INTRINSIC:
3159 case AMDGPU::G_INTRINSIC_CONVERGENT: {
3160 switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
3161 case Intrinsic::amdgcn_readlane: {
3162 substituteSimpleCopyRegs(OpdMapper, 2);
3163
3164 assert(OpdMapper.getVRegs(0).empty());
3165 assert(OpdMapper.getVRegs(3).empty());
3166
3167 // Make sure the index is an SGPR. It doesn't make sense to run this in a
3168 // waterfall loop, so assume it's a uniform value.
3169 constrainOpWithReadfirstlane(B, MI, 3); // Index
3170 return;
3171 }
3172 case Intrinsic::amdgcn_writelane: {
3173 assert(OpdMapper.getVRegs(0).empty());
3174 assert(OpdMapper.getVRegs(2).empty());
3175 assert(OpdMapper.getVRegs(3).empty());
3176
3177 substituteSimpleCopyRegs(OpdMapper, 4); // VGPR input val
3178 constrainOpWithReadfirstlane(B, MI, 2); // Source value
3179 constrainOpWithReadfirstlane(B, MI, 3); // Index
3180 return;
3181 }
3182 case Intrinsic::amdgcn_interp_p1:
3183 case Intrinsic::amdgcn_interp_p2:
3184 case Intrinsic::amdgcn_interp_mov:
3185 case Intrinsic::amdgcn_interp_p1_f16:
3186 case Intrinsic::amdgcn_interp_p2_f16:
3187 case Intrinsic::amdgcn_lds_param_load: {
3188 applyDefaultMapping(OpdMapper);
3189
3190 // Readlane for m0 value, which is always the last operand.
3191 // FIXME: Should this be a waterfall loop instead?
3192 constrainOpWithReadfirstlane(B, MI, MI.getNumOperands() - 1); // Index
3193 return;
3194 }
3195 case Intrinsic::amdgcn_interp_inreg_p10:
3196 case Intrinsic::amdgcn_interp_inreg_p2:
3197 case Intrinsic::amdgcn_interp_inreg_p10_f16:
3198 case Intrinsic::amdgcn_interp_inreg_p2_f16:
3199 case Intrinsic::amdgcn_interp_p10_rtz_f16:
3200 case Intrinsic::amdgcn_interp_p2_rtz_f16:
3201 case Intrinsic::amdgcn_permlane16_swap:
3202 case Intrinsic::amdgcn_permlane32_swap:
3203 applyDefaultMapping(OpdMapper);
3204 return;
3205 case Intrinsic::amdgcn_permlane16:
3206 case Intrinsic::amdgcn_permlanex16: {
3207 // Doing a waterfall loop over these wouldn't make any sense.
3208 substituteSimpleCopyRegs(OpdMapper, 2);
3209 substituteSimpleCopyRegs(OpdMapper, 3);
3212 return;
3213 }
3214 case Intrinsic::amdgcn_permlane_bcast:
3215 case Intrinsic::amdgcn_permlane_up:
3216 case Intrinsic::amdgcn_permlane_down:
3217 case Intrinsic::amdgcn_permlane_xor:
3218 // Doing a waterfall loop over these wouldn't make any sense.
3221 return;
3222 case Intrinsic::amdgcn_permlane_idx_gen: {
3224 return;
3225 }
3226 case Intrinsic::amdgcn_sbfe:
3227 applyMappingBFE(B, OpdMapper, true);
3228 return;
3229 case Intrinsic::amdgcn_ubfe:
3230 applyMappingBFE(B, OpdMapper, false);
3231 return;
3232 case Intrinsic::amdgcn_inverse_ballot:
3233 case Intrinsic::amdgcn_s_bitreplicate:
3234 case Intrinsic::amdgcn_s_quadmask:
3235 case Intrinsic::amdgcn_s_wqm:
3236 applyDefaultMapping(OpdMapper);
3237 constrainOpWithReadfirstlane(B, MI, 2); // Mask
3238 return;
3239 case Intrinsic::amdgcn_ballot:
3240 // Use default handling and insert copy to vcc source.
3241 break;
3242 }
3243 break;
3244 }
3245 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
3246 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
3247 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
3248 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
3249 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
3250 const AMDGPU::RsrcIntrinsic *RSrcIntrin =
3252 assert(RSrcIntrin && RSrcIntrin->IsImage);
3253 // Non-images can have complications from operands that allow both SGPR
3254 // and VGPR. For now it's too complicated to figure out the final opcode
3255 // to derive the register bank from the MCInstrDesc.
3256 applyMappingImage(B, MI, OpdMapper, RSrcIntrin->RsrcArg);
3257 return;
3258 }
3259 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
3260 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
3261 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY: {
3262 bool IsDualOrBVH8 =
3263 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY ||
3264 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY;
3265 unsigned NumMods = IsDualOrBVH8 ? 0 : 1; // Has A16 modifier
3266 unsigned LastRegOpIdx = MI.getNumExplicitOperands() - 1 - NumMods;
3267 applyDefaultMapping(OpdMapper);
3268 executeInWaterfallLoop(B, MI, {LastRegOpIdx});
3269 return;
3270 }
3271 case AMDGPU::G_INTRINSIC_W_SIDE_EFFECTS:
3272 case AMDGPU::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS: {
3273 auto IntrID = cast<GIntrinsic>(MI).getIntrinsicID();
3274 switch (IntrID) {
3275 case Intrinsic::amdgcn_ds_ordered_add:
3276 case Intrinsic::amdgcn_ds_ordered_swap: {
3277 // This is only allowed to execute with 1 lane, so readfirstlane is safe.
3278 assert(OpdMapper.getVRegs(0).empty());
3279 substituteSimpleCopyRegs(OpdMapper, 3);
3281 return;
3282 }
3283 case Intrinsic::amdgcn_ds_gws_init:
3284 case Intrinsic::amdgcn_ds_gws_barrier:
3285 case Intrinsic::amdgcn_ds_gws_sema_br: {
3286 // Only the first lane is executes, so readfirstlane is safe.
3287 substituteSimpleCopyRegs(OpdMapper, 1);
3289 return;
3290 }
3291 case Intrinsic::amdgcn_ds_gws_sema_v:
3292 case Intrinsic::amdgcn_ds_gws_sema_p:
3293 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
3294 // Only the first lane is executes, so readfirstlane is safe.
3296 return;
3297 }
3298 case Intrinsic::amdgcn_ds_append:
3299 case Intrinsic::amdgcn_ds_consume: {
3301 return;
3302 }
3303 case Intrinsic::amdgcn_s_alloc_vgpr:
3305 return;
3306 case Intrinsic::amdgcn_s_sendmsg:
3307 case Intrinsic::amdgcn_s_sendmsghalt: {
3308 // FIXME: Should this use a waterfall loop?
3310 return;
3311 }
3312 case Intrinsic::amdgcn_s_setreg: {
3314 return;
3315 }
3316 case Intrinsic::amdgcn_s_ttracedata:
3318 return;
3319 case Intrinsic::amdgcn_raw_buffer_load_lds:
3320 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
3321 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
3322 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds: {
3323 applyDefaultMapping(OpdMapper);
3324 constrainOpWithReadfirstlane(B, MI, 1); // rsrc
3326 constrainOpWithReadfirstlane(B, MI, 5); // soffset
3327 return;
3328 }
3329 case Intrinsic::amdgcn_struct_buffer_load_lds:
3330 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
3331 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
3332 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
3333 applyDefaultMapping(OpdMapper);
3334 constrainOpWithReadfirstlane(B, MI, 1); // rsrc
3336 constrainOpWithReadfirstlane(B, MI, 6); // soffset
3337 return;
3338 }
3339 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
3340 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
3341 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
3342 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
3343 applyDefaultMapping(OpdMapper);
3345 return;
3346 }
3347 case Intrinsic::amdgcn_load_to_lds:
3348 case Intrinsic::amdgcn_load_async_to_lds:
3349 case Intrinsic::amdgcn_global_load_lds:
3350 case Intrinsic::amdgcn_global_load_async_lds: {
3351 applyDefaultMapping(OpdMapper);
3353 return;
3354 }
3355 case Intrinsic::amdgcn_lds_direct_load: {
3356 applyDefaultMapping(OpdMapper);
3357 // Readlane for m0 value, which is always the last operand.
3358 constrainOpWithReadfirstlane(B, MI, MI.getNumOperands() - 1); // Index
3359 return;
3360 }
3361 case Intrinsic::amdgcn_exp_row:
3362 applyDefaultMapping(OpdMapper);
3364 return;
3365 case Intrinsic::amdgcn_cluster_load_b32:
3366 case Intrinsic::amdgcn_cluster_load_b64:
3367 case Intrinsic::amdgcn_cluster_load_b128: {
3368 applyDefaultMapping(OpdMapper);
3370 return;
3371 }
3372 case Intrinsic::amdgcn_s_sleep_var:
3373 assert(OpdMapper.getVRegs(1).empty());
3375 return;
3376 case Intrinsic::amdgcn_s_barrier_join:
3377 case Intrinsic::amdgcn_s_wakeup_barrier:
3379 return;
3380 case Intrinsic::amdgcn_s_barrier_init:
3381 case Intrinsic::amdgcn_s_barrier_signal_var:
3384 return;
3385 case Intrinsic::amdgcn_s_get_barrier_state:
3386 case Intrinsic::amdgcn_s_get_named_barrier_state: {
3388 return;
3389 }
3390 case Intrinsic::amdgcn_s_prefetch_data:
3391 case Intrinsic::amdgcn_s_prefetch_inst: {
3392 Register PtrReg = MI.getOperand(1).getReg();
3393 unsigned AS = MRI.getType(PtrReg).getAddressSpace();
3397 } else
3398 MI.eraseFromParent();
3399 return;
3400 }
3401 case Intrinsic::amdgcn_tensor_load_to_lds:
3402 case Intrinsic::amdgcn_tensor_store_from_lds: {
3408 return;
3409 }
3410 default: {
3411 if (const AMDGPU::RsrcIntrinsic *RSrcIntrin =
3413 // Non-images can have complications from operands that allow both SGPR
3414 // and VGPR. For now it's too complicated to figure out the final opcode
3415 // to derive the register bank from the MCInstrDesc.
3416 if (RSrcIntrin->IsImage) {
3417 applyMappingImage(B, MI, OpdMapper, RSrcIntrin->RsrcArg);
3418 return;
3419 }
3420 }
3421
3422 break;
3423 }
3424 }
3425 break;
3426 }
3427 case AMDGPU::G_SI_CALL: {
3428 // Use a set to avoid extra readfirstlanes in the case where multiple
3429 // operands are the same register.
3430 SmallSet<Register, 4> SGPROperandRegs;
3431
3432 if (!collectWaterfallOperands(SGPROperandRegs, MI, MRI, {1}))
3433 break;
3434
3435 // Move all copies to physical SGPRs that are used by the call instruction
3436 // into the loop block. Start searching for these copies until the
3437 // ADJCALLSTACKUP.
3438 unsigned FrameSetupOpcode = AMDGPU::ADJCALLSTACKUP;
3439 unsigned FrameDestroyOpcode = AMDGPU::ADJCALLSTACKDOWN;
3440
3441 // Move all non-copies before the copies, so that a complete range can be
3442 // moved into the waterfall loop.
3443 SmallVector<MachineInstr *, 4> NonCopyInstrs;
3444 // Count of NonCopyInstrs found until the current LastCopy.
3445 unsigned NonCopyInstrsLen = 0;
3447 MachineBasicBlock::iterator LastCopy = Start;
3448 MachineBasicBlock *MBB = MI.getParent();
3449 const SIMachineFunctionInfo *Info =
3450 MBB->getParent()->getInfo<SIMachineFunctionInfo>();
3451 while (Start->getOpcode() != FrameSetupOpcode) {
3452 --Start;
3453 bool IsCopy = false;
3454 if (Start->getOpcode() == AMDGPU::COPY) {
3455 auto &Dst = Start->getOperand(0);
3456 if (Dst.isReg()) {
3457 Register Reg = Dst.getReg();
3458 if (Reg.isPhysical() && MI.readsRegister(Reg, TRI)) {
3459 IsCopy = true;
3460 } else {
3461 // Also move the copy from the scratch rsrc descriptor into the loop
3462 // to allow it to be optimized away.
3463 auto &Src = Start->getOperand(1);
3464 if (Src.isReg()) {
3465 Reg = Src.getReg();
3466 IsCopy = Info->getScratchRSrcReg() == Reg;
3467 }
3468 }
3469 }
3470 }
3471
3472 if (IsCopy) {
3473 LastCopy = Start;
3474 NonCopyInstrsLen = NonCopyInstrs.size();
3475 } else {
3476 NonCopyInstrs.push_back(&*Start);
3477 }
3478 }
3479 NonCopyInstrs.resize(NonCopyInstrsLen);
3480
3481 for (auto *NonCopy : reverse(NonCopyInstrs)) {
3482 MBB->splice(LastCopy, MBB, NonCopy->getIterator());
3483 }
3484 Start = LastCopy;
3485
3486 // Do the same for copies after the loop
3487 NonCopyInstrs.clear();
3488 NonCopyInstrsLen = 0;
3490 LastCopy = End;
3491 while (End->getOpcode() != FrameDestroyOpcode) {
3492 ++End;
3493 bool IsCopy = false;
3494 if (End->getOpcode() == AMDGPU::COPY) {
3495 auto &Src = End->getOperand(1);
3496 if (Src.isReg()) {
3497 Register Reg = Src.getReg();
3498 IsCopy = Reg.isPhysical() && MI.modifiesRegister(Reg, TRI);
3499 }
3500 }
3501
3502 if (IsCopy) {
3503 LastCopy = End;
3504 NonCopyInstrsLen = NonCopyInstrs.size();
3505 } else {
3506 NonCopyInstrs.push_back(&*End);
3507 }
3508 }
3509 NonCopyInstrs.resize(NonCopyInstrsLen);
3510
3511 End = LastCopy;
3512 ++LastCopy;
3513 for (auto *NonCopy : reverse(NonCopyInstrs)) {
3514 MBB->splice(LastCopy, MBB, NonCopy->getIterator());
3515 }
3516
3517 ++End;
3518 B.setInsertPt(B.getMBB(), Start);
3519 executeInWaterfallLoop(B, make_range(Start, End), SGPROperandRegs);
3520 break;
3521 }
3522 case AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR:
3523 case AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR:
3524 case AMDGPU::G_LOAD:
3525 case AMDGPU::G_ZEXTLOAD:
3526 case AMDGPU::G_SEXTLOAD: {
3527 if (applyMappingLoad(B, OpdMapper, MI))
3528 return;
3529 break;
3530 }
3531 case AMDGPU::G_DYN_STACKALLOC:
3532 applyMappingDynStackAlloc(B, OpdMapper, MI);
3533 return;
3534 case AMDGPU::G_STACKRESTORE: {
3535 applyDefaultMapping(OpdMapper);
3537 return;
3538 }
3539 case AMDGPU::G_SBFX:
3540 applyMappingBFE(B, OpdMapper, /*Signed*/ true);
3541 return;
3542 case AMDGPU::G_UBFX:
3543 applyMappingBFE(B, OpdMapper, /*Signed*/ false);
3544 return;
3545 case AMDGPU::G_AMDGPU_MAD_U64_U32:
3546 case AMDGPU::G_AMDGPU_MAD_I64_I32:
3547 applyMappingMAD_64_32(B, OpdMapper);
3548 return;
3549 case AMDGPU::G_PREFETCH: {
3550 if (!Subtarget.hasSafeSmemPrefetch() && !Subtarget.hasVmemPrefInsts()) {
3551 MI.eraseFromParent();
3552 return;
3553 }
3554 Register PtrReg = MI.getOperand(0).getReg();
3555 unsigned PtrBank = getRegBankID(PtrReg, MRI, AMDGPU::SGPRRegBankID);
3556 if (PtrBank == AMDGPU::VGPRRegBankID &&
3557 (!Subtarget.hasVmemPrefInsts() || !MI.getOperand(3).getImm())) {
3558 // Cannot do I$ prefetch with divergent pointer.
3559 MI.eraseFromParent();
3560 return;
3561 }
3562 unsigned AS = MRI.getType(PtrReg).getAddressSpace();
3565 (!Subtarget.hasSafeSmemPrefetch() &&
3567 !MI.getOperand(3).getImm() /* I$ prefetch */))) {
3568 MI.eraseFromParent();
3569 return;
3570 }
3571 applyDefaultMapping(OpdMapper);
3572 return;
3573 }
3574 default:
3575 break;
3576 }
3577
3578 return applyDefaultMapping(OpdMapper);
3579}
3580
3581// vgpr, sgpr -> vgpr
3582// vgpr, agpr -> vgpr
3583// agpr, agpr -> agpr
3584// agpr, sgpr -> vgpr
3585static unsigned regBankUnion(unsigned RB0, unsigned RB1) {
3586 if (RB0 == AMDGPU::InvalidRegBankID)
3587 return RB1;
3588 if (RB1 == AMDGPU::InvalidRegBankID)
3589 return RB0;
3590
3591 if (RB0 == AMDGPU::SGPRRegBankID && RB1 == AMDGPU::SGPRRegBankID)
3592 return AMDGPU::SGPRRegBankID;
3593
3594 if (RB0 == AMDGPU::AGPRRegBankID && RB1 == AMDGPU::AGPRRegBankID)
3595 return AMDGPU::AGPRRegBankID;
3596
3597 return AMDGPU::VGPRRegBankID;
3598}
3599
3600static unsigned regBankBoolUnion(unsigned RB0, unsigned RB1) {
3601 if (RB0 == AMDGPU::InvalidRegBankID)
3602 return RB1;
3603 if (RB1 == AMDGPU::InvalidRegBankID)
3604 return RB0;
3605
3606 // vcc, vcc -> vcc
3607 // vcc, sgpr -> vcc
3608 // vcc, vgpr -> vcc
3609 if (RB0 == AMDGPU::VCCRegBankID || RB1 == AMDGPU::VCCRegBankID)
3610 return AMDGPU::VCCRegBankID;
3611
3612 // vcc, vgpr -> vgpr
3613 return regBankUnion(RB0, RB1);
3614}
3615
3617 const MachineInstr &MI) const {
3618 unsigned RegBank = AMDGPU::InvalidRegBankID;
3619
3620 for (const MachineOperand &MO : MI.operands()) {
3621 if (!MO.isReg())
3622 continue;
3623 Register Reg = MO.getReg();
3624 if (const RegisterBank *Bank = getRegBank(Reg, MRI, *TRI)) {
3625 RegBank = regBankUnion(RegBank, Bank->getID());
3626 if (RegBank == AMDGPU::VGPRRegBankID)
3627 break;
3628 }
3629 }
3630
3631 return RegBank;
3632}
3633
3635 const MachineFunction &MF = *MI.getMF();
3636 const MachineRegisterInfo &MRI = MF.getRegInfo();
3637 for (const MachineOperand &MO : MI.operands()) {
3638 if (!MO.isReg())
3639 continue;
3640 Register Reg = MO.getReg();
3641 if (const RegisterBank *Bank = getRegBank(Reg, MRI, *TRI)) {
3642 if (Bank->getID() != AMDGPU::SGPRRegBankID)
3643 return false;
3644 }
3645 }
3646 return true;
3647}
3648
3651 const MachineFunction &MF = *MI.getMF();
3652 const MachineRegisterInfo &MRI = MF.getRegInfo();
3653 SmallVector<const ValueMapping*, 8> OpdsMapping(MI.getNumOperands());
3654
3655 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
3656 const MachineOperand &SrcOp = MI.getOperand(i);
3657 if (!SrcOp.isReg())
3658 continue;
3659
3660 unsigned Size = getSizeInBits(SrcOp.getReg(), MRI, *TRI);
3661 OpdsMapping[i] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
3662 }
3663 return getInstructionMapping(1, 1, getOperandsMapping(OpdsMapping),
3664 MI.getNumOperands());
3665}
3666
3669 const MachineFunction &MF = *MI.getMF();
3670 const MachineRegisterInfo &MRI = MF.getRegInfo();
3671 SmallVector<const ValueMapping*, 8> OpdsMapping(MI.getNumOperands());
3672
3673 // Even though we technically could use SGPRs, this would require knowledge of
3674 // the constant bus restriction. Force all sources to VGPR (except for VCC).
3675 //
3676 // TODO: Unary ops are trivially OK, so accept SGPRs?
3677 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
3678 const MachineOperand &Src = MI.getOperand(i);
3679 if (!Src.isReg())
3680 continue;
3681
3682 unsigned Size = getSizeInBits(Src.getReg(), MRI, *TRI);
3683 unsigned BankID = Size == 1 ? AMDGPU::VCCRegBankID : AMDGPU::VGPRRegBankID;
3684 OpdsMapping[i] = AMDGPU::getValueMapping(BankID, Size);
3685 }
3686
3687 return getInstructionMapping(1, 1, getOperandsMapping(OpdsMapping),
3688 MI.getNumOperands());
3689}
3690
3693 const MachineFunction &MF = *MI.getMF();
3694 const MachineRegisterInfo &MRI = MF.getRegInfo();
3695 SmallVector<const ValueMapping*, 8> OpdsMapping(MI.getNumOperands());
3696
3697 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
3698 const MachineOperand &Op = MI.getOperand(I);
3699 if (!Op.isReg())
3700 continue;
3701
3702 unsigned Size = getSizeInBits(Op.getReg(), MRI, *TRI);
3703 OpdsMapping[I] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
3704 }
3705
3706 return getInstructionMapping(1, 1, getOperandsMapping(OpdsMapping),
3707 MI.getNumOperands());
3708}
3709
3712 const MachineInstr &MI,
3713 int RsrcIdx) const {
3714 // The reported argument index is relative to the IR intrinsic call arguments,
3715 // so we need to shift by the number of defs and the intrinsic ID.
3716 RsrcIdx += MI.getNumExplicitDefs() + 1;
3717
3718 const int NumOps = MI.getNumOperands();
3720
3721 // TODO: Should packed/unpacked D16 difference be reported here as part of
3722 // the value mapping?
3723 for (int I = 0; I != NumOps; ++I) {
3724 if (!MI.getOperand(I).isReg())
3725 continue;
3726
3727 Register OpReg = MI.getOperand(I).getReg();
3728 // We replace some dead address operands with $noreg
3729 if (!OpReg)
3730 continue;
3731
3732 unsigned Size = getSizeInBits(OpReg, MRI, *TRI);
3733
3734 // FIXME: Probably need a new intrinsic register bank searchable table to
3735 // handle arbitrary intrinsics easily.
3736 //
3737 // If this has a sampler, it immediately follows rsrc.
3738 const bool MustBeSGPR = I == RsrcIdx || I == RsrcIdx + 1;
3739
3740 if (MustBeSGPR) {
3741 // If this must be an SGPR, so we must report whatever it is as legal.
3742 unsigned NewBank = getRegBankID(OpReg, MRI, AMDGPU::SGPRRegBankID);
3743 OpdsMapping[I] = AMDGPU::getValueMapping(NewBank, Size);
3744 } else {
3745 // Some operands must be VGPR, and these are easy to copy to.
3746 OpdsMapping[I] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
3747 }
3748 }
3749
3750 return getInstructionMapping(1, 1, getOperandsMapping(OpdsMapping), NumOps);
3751}
3752
3753/// Return the mapping for a pointer argument.
3756 Register PtrReg) const {
3757 LLT PtrTy = MRI.getType(PtrReg);
3758 unsigned Size = PtrTy.getSizeInBits();
3759 if (Subtarget.useFlatForGlobal() ||
3761 return AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
3762
3763 // If we're using MUBUF instructions for global memory, an SGPR base register
3764 // is possible. Otherwise this needs to be a VGPR.
3765 const RegisterBank *PtrBank = getRegBank(PtrReg, MRI, *TRI);
3766 return AMDGPU::getValueMapping(PtrBank->getID(), Size);
3767}
3768
3771
3772 const MachineFunction &MF = *MI.getMF();
3773 const MachineRegisterInfo &MRI = MF.getRegInfo();
3775 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
3776 Register PtrReg = MI.getOperand(1).getReg();
3777 LLT PtrTy = MRI.getType(PtrReg);
3778 unsigned AS = PtrTy.getAddressSpace();
3779 unsigned PtrSize = PtrTy.getSizeInBits();
3780
3781 const ValueMapping *ValMapping;
3782 const ValueMapping *PtrMapping;
3783
3784 const RegisterBank *PtrBank = getRegBank(PtrReg, MRI, *TRI);
3785
3786 if (PtrBank == &AMDGPU::SGPRRegBank && AMDGPU::isFlatGlobalAddrSpace(AS)) {
3787 if (isScalarLoadLegal(MI)) {
3788 // We have a uniform instruction so we want to use an SMRD load
3789 ValMapping = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
3790 PtrMapping = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, PtrSize);
3791 } else {
3792 ValMapping = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
3793
3794 // If we're using MUBUF instructions for global memory, an SGPR base
3795 // register is possible. Otherwise this needs to be a VGPR.
3796 unsigned PtrBankID = Subtarget.useFlatForGlobal() ?
3797 AMDGPU::VGPRRegBankID : AMDGPU::SGPRRegBankID;
3798
3799 PtrMapping = AMDGPU::getValueMapping(PtrBankID, PtrSize);
3800 }
3801 } else {
3802 ValMapping = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
3803 PtrMapping = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, PtrSize);
3804 }
3805
3806 OpdsMapping[0] = ValMapping;
3807 OpdsMapping[1] = PtrMapping;
3809 1, 1, getOperandsMapping(OpdsMapping), MI.getNumOperands());
3810 return Mapping;
3811
3812 // FIXME: Do we want to add a mapping for FLAT load, or should we just
3813 // handle that during instruction selection?
3814}
3815
3816unsigned
3818 const MachineRegisterInfo &MRI,
3819 unsigned Default) const {
3820 const RegisterBank *Bank = getRegBank(Reg, MRI, *TRI);
3821 return Bank ? Bank->getID() : Default;
3822}
3823
3826 const MachineRegisterInfo &MRI,
3827 const TargetRegisterInfo &TRI) const {
3828 // Lie and claim anything is legal, even though this needs to be an SGPR
3829 // applyMapping will have to deal with it as a waterfall loop.
3830 unsigned Bank = getRegBankID(Reg, MRI, AMDGPU::SGPRRegBankID);
3831 unsigned Size = getSizeInBits(Reg, MRI, TRI);
3832 return AMDGPU::getValueMapping(Bank, Size);
3833}
3834
3837 const MachineRegisterInfo &MRI,
3838 const TargetRegisterInfo &TRI) const {
3839 unsigned Size = getSizeInBits(Reg, MRI, TRI);
3840 return AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
3841}
3842
3845 const MachineRegisterInfo &MRI,
3846 const TargetRegisterInfo &TRI) const {
3847 unsigned Size = getSizeInBits(Reg, MRI, TRI);
3848 return AMDGPU::getValueMapping(AMDGPU::AGPRRegBankID, Size);
3849}
3850
3851///
3852/// This function must return a legal mapping, because
3853/// AMDGPURegisterBankInfo::getInstrAlternativeMappings() is not called
3854/// in RegBankSelect::Mode::Fast. Any mapping that would cause a
3855/// VGPR to SGPR generated is illegal.
3856///
3857// Operands that must be SGPRs must accept potentially divergent VGPRs as
3858// legal. These will be dealt with in applyMappingImpl.
3859//
3862 const MachineFunction &MF = *MI.getMF();
3863 const MachineRegisterInfo &MRI = MF.getRegInfo();
3864
3865 if (MI.isCopy() || MI.getOpcode() == AMDGPU::G_FREEZE) {
3866 Register DstReg = MI.getOperand(0).getReg();
3867 Register SrcReg = MI.getOperand(1).getReg();
3868
3869 // The default logic bothers to analyze impossible alternative mappings. We
3870 // want the most straightforward mapping, so just directly handle this.
3871 const RegisterBank *DstBank = getRegBank(DstReg, MRI, *TRI);
3872 const RegisterBank *SrcBank = getRegBank(SrcReg, MRI, *TRI);
3873
3874 // For COPY between a physical reg and an s1, there is no type associated so
3875 // we need to take the virtual register's type as a hint on how to interpret
3876 // s1 values.
3877 unsigned Size;
3878 if (!SrcReg.isVirtual() && !DstBank &&
3879 MRI.getType(DstReg) == LLT::scalar(1)) {
3880 DstBank = &AMDGPU::VCCRegBank;
3881 Size = 1;
3882 } else if (!DstReg.isVirtual() && MRI.getType(SrcReg) == LLT::scalar(1)) {
3883 DstBank = &AMDGPU::VCCRegBank;
3884 Size = 1;
3885 } else {
3886 Size = getSizeInBits(DstReg, MRI, *TRI);
3887 }
3888
3889 if (!DstBank)
3890 DstBank = SrcBank;
3891 else if (!SrcBank)
3892 SrcBank = DstBank;
3893
3894 if (MI.getOpcode() != AMDGPU::G_FREEZE &&
3895 cannotCopy(*DstBank, *SrcBank, TypeSize::getFixed(Size)))
3897
3898 const ValueMapping &ValMap = getValueMapping(0, Size, *DstBank);
3899 unsigned OpdsMappingSize = MI.isCopy() ? 1 : 2;
3900 SmallVector<const ValueMapping *, 1> OpdsMapping(OpdsMappingSize);
3901 OpdsMapping[0] = &ValMap;
3902 if (MI.getOpcode() == AMDGPU::G_FREEZE)
3903 OpdsMapping[1] = &ValMap;
3904
3905 return getInstructionMapping(
3906 1, /*Cost*/ 1,
3907 /*OperandsMapping*/ getOperandsMapping(OpdsMapping), OpdsMappingSize);
3908 }
3909
3910 if (MI.isRegSequence()) {
3911 // If any input is a VGPR, the result must be a VGPR. The default handling
3912 // assumes any copy between banks is legal.
3913 unsigned BankID = AMDGPU::SGPRRegBankID;
3914
3915 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
3916 auto OpBank = getRegBankID(MI.getOperand(I).getReg(), MRI);
3917 // It doesn't make sense to use vcc or scc banks here, so just ignore
3918 // them.
3919 if (OpBank != AMDGPU::SGPRRegBankID) {
3920 BankID = AMDGPU::VGPRRegBankID;
3921 break;
3922 }
3923 }
3924 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
3925
3926 const ValueMapping &ValMap = getValueMapping(0, Size, getRegBank(BankID));
3927 return getInstructionMapping(
3928 1, /*Cost*/ 1,
3929 /*OperandsMapping*/ getOperandsMapping({&ValMap}), 1);
3930 }
3931
3932 // The default handling is broken and doesn't handle illegal SGPR->VGPR copies
3933 // properly.
3934 //
3935 // TODO: There are additional exec masking dependencies to analyze.
3936 if (auto *PHI = dyn_cast<GPhi>(&MI)) {
3937 unsigned ResultBank = AMDGPU::InvalidRegBankID;
3938 Register DstReg = PHI->getReg(0);
3939
3940 // Sometimes the result may have already been assigned a bank.
3941 if (const RegisterBank *DstBank = getRegBank(DstReg, MRI, *TRI))
3942 ResultBank = DstBank->getID();
3943
3944 for (unsigned I = 0; I < PHI->getNumIncomingValues(); ++I) {
3945 Register Reg = PHI->getIncomingValue(I);
3946 const RegisterBank *Bank = getRegBank(Reg, MRI, *TRI);
3947
3948 // FIXME: Assuming VGPR for any undetermined inputs.
3949 if (!Bank || Bank->getID() == AMDGPU::VGPRRegBankID) {
3950 ResultBank = AMDGPU::VGPRRegBankID;
3951 break;
3952 }
3953
3954 // FIXME: Need to promote SGPR case to s32
3955 unsigned OpBank = Bank->getID();
3956 ResultBank = regBankBoolUnion(ResultBank, OpBank);
3957 }
3958
3959 assert(ResultBank != AMDGPU::InvalidRegBankID);
3960
3961 unsigned Size = MRI.getType(DstReg).getSizeInBits();
3962
3963 const ValueMapping &ValMap =
3964 getValueMapping(0, Size, getRegBank(ResultBank));
3965 return getInstructionMapping(
3966 1, /*Cost*/ 1,
3967 /*OperandsMapping*/ getOperandsMapping({&ValMap}), 1);
3968 }
3969
3971 if (Mapping.isValid())
3972 return Mapping;
3973
3974 SmallVector<const ValueMapping*, 8> OpdsMapping(MI.getNumOperands());
3975
3976 switch (MI.getOpcode()) {
3977 default:
3979
3980 case AMDGPU::G_AND:
3981 case AMDGPU::G_OR:
3982 case AMDGPU::G_XOR:
3983 case AMDGPU::G_MUL: {
3984 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
3985 if (Size == 1) {
3986 const RegisterBank *DstBank
3987 = getRegBank(MI.getOperand(0).getReg(), MRI, *TRI);
3988
3989 unsigned TargetBankID = AMDGPU::InvalidRegBankID;
3990 unsigned BankLHS = AMDGPU::InvalidRegBankID;
3991 unsigned BankRHS = AMDGPU::InvalidRegBankID;
3992 if (DstBank) {
3993 TargetBankID = DstBank->getID();
3994 if (DstBank == &AMDGPU::VCCRegBank) {
3995 TargetBankID = AMDGPU::VCCRegBankID;
3996 BankLHS = AMDGPU::VCCRegBankID;
3997 BankRHS = AMDGPU::VCCRegBankID;
3998 } else {
3999 BankLHS = getRegBankID(MI.getOperand(1).getReg(), MRI,
4000 AMDGPU::SGPRRegBankID);
4001 BankRHS = getRegBankID(MI.getOperand(2).getReg(), MRI,
4002 AMDGPU::SGPRRegBankID);
4003 }
4004 } else {
4005 BankLHS = getRegBankID(MI.getOperand(1).getReg(), MRI,
4006 AMDGPU::VCCRegBankID);
4007 BankRHS = getRegBankID(MI.getOperand(2).getReg(), MRI,
4008 AMDGPU::VCCRegBankID);
4009
4010 // Both inputs should be true booleans to produce a boolean result.
4011 if (BankLHS == AMDGPU::VGPRRegBankID || BankRHS == AMDGPU::VGPRRegBankID) {
4012 TargetBankID = AMDGPU::VGPRRegBankID;
4013 } else if (BankLHS == AMDGPU::VCCRegBankID || BankRHS == AMDGPU::VCCRegBankID) {
4014 TargetBankID = AMDGPU::VCCRegBankID;
4015 BankLHS = AMDGPU::VCCRegBankID;
4016 BankRHS = AMDGPU::VCCRegBankID;
4017 } else if (BankLHS == AMDGPU::SGPRRegBankID && BankRHS == AMDGPU::SGPRRegBankID) {
4018 TargetBankID = AMDGPU::SGPRRegBankID;
4019 }
4020 }
4021
4022 OpdsMapping[0] = AMDGPU::getValueMapping(TargetBankID, Size);
4023 OpdsMapping[1] = AMDGPU::getValueMapping(BankLHS, Size);
4024 OpdsMapping[2] = AMDGPU::getValueMapping(BankRHS, Size);
4025 break;
4026 }
4027
4028 if (Size == 64) {
4029
4030 if (isSALUMapping(MI)) {
4031 OpdsMapping[0] = getValueMappingSGPR64Only(AMDGPU::SGPRRegBankID, Size);
4032 OpdsMapping[1] = OpdsMapping[2] = OpdsMapping[0];
4033 } else {
4034 if (MI.getOpcode() == AMDGPU::G_MUL && Subtarget.useVMulU64Inst())
4035 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
4036 else
4037 OpdsMapping[0] =
4038 getValueMappingSGPR64Only(AMDGPU::VGPRRegBankID, Size);
4039 unsigned Bank1 = getRegBankID(MI.getOperand(1).getReg(), MRI /*, DefaultBankID*/);
4040 OpdsMapping[1] = AMDGPU::getValueMapping(Bank1, Size);
4041
4042 unsigned Bank2 = getRegBankID(MI.getOperand(2).getReg(), MRI /*, DefaultBankID*/);
4043 OpdsMapping[2] = AMDGPU::getValueMapping(Bank2, Size);
4044 }
4045
4046 break;
4047 }
4048
4049 [[fallthrough]];
4050 }
4051 case AMDGPU::G_PTR_ADD:
4052 case AMDGPU::G_PTRMASK:
4053 case AMDGPU::G_ADD:
4054 case AMDGPU::G_SUB:
4055 case AMDGPU::G_SHL:
4056 case AMDGPU::G_LSHR:
4057 case AMDGPU::G_ASHR:
4058 case AMDGPU::G_UADDO:
4059 case AMDGPU::G_USUBO:
4060 case AMDGPU::G_UADDE:
4061 case AMDGPU::G_SADDE:
4062 case AMDGPU::G_USUBE:
4063 case AMDGPU::G_SSUBE:
4064 case AMDGPU::G_ABS:
4065 case AMDGPU::G_SHUFFLE_VECTOR:
4066 case AMDGPU::G_SBFX:
4067 case AMDGPU::G_UBFX:
4068 case AMDGPU::G_AMDGPU_S_MUL_I64_I32:
4069 case AMDGPU::G_AMDGPU_S_MUL_U64_U32:
4070 if (isSALUMapping(MI)) {
4071 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4072 unsigned Size = Ty.getSizeInBits();
4073 // Packed add and sub are VALU only.
4074 if (Subtarget.hasAnyPackedU64Ops() && Ty.isVector() && Size == 128)
4075 return getDefaultMappingVOP(MI);
4076 return getDefaultMappingSOP(MI);
4077 }
4078 return getDefaultMappingVOP(MI);
4079 case AMDGPU::G_SMIN:
4080 case AMDGPU::G_SMAX:
4081 case AMDGPU::G_UMIN:
4082 case AMDGPU::G_UMAX:
4083 if (isSALUMapping(MI)) {
4084 // There are no scalar 64-bit min and max, use vector instruction instead.
4085 if (MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 64 &&
4086 Subtarget.useMinMaxI64Insts())
4087 return getDefaultMappingVOP(MI);
4088 return getDefaultMappingSOP(MI);
4089 }
4090 return getDefaultMappingVOP(MI);
4091 case AMDGPU::G_FADD:
4092 case AMDGPU::G_FSUB:
4093 case AMDGPU::G_FMUL:
4094 case AMDGPU::G_FMA:
4095 case AMDGPU::G_FFLOOR:
4096 case AMDGPU::G_FCEIL:
4097 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
4098 case AMDGPU::G_INTRINSIC_TRUNC:
4099 case AMDGPU::G_STRICT_FADD:
4100 case AMDGPU::G_STRICT_FSUB:
4101 case AMDGPU::G_STRICT_FMUL:
4102 case AMDGPU::G_STRICT_FMA: {
4103 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4104 unsigned Size = Ty.getSizeInBits();
4105 if (Subtarget.hasSALUFloatInsts() && Ty.isScalar() &&
4106 (Size == 32 || Size == 16) && isSALUMapping(MI))
4107 return getDefaultMappingSOP(MI);
4108 return getDefaultMappingVOP(MI);
4109 }
4110 case AMDGPU::G_FMINNUM:
4111 case AMDGPU::G_FMAXNUM:
4112 case AMDGPU::G_FMINIMUMNUM:
4113 case AMDGPU::G_FMAXIMUMNUM: {
4114 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4115 unsigned Size = Ty.getSizeInBits();
4116 // This case is for GFX11.7, which has the following features:
4117 // 1. `hasIEEEMinimumMaximumInsts()` returns true
4118 // 2. `hasSALUMinimumMaximumInsts()` returns false
4119 // This indicates that GFX11.7 is using:
4120 // 1. `s_max/min_f32/f16` for scalar
4121 // 2. `v_max/min_num_f32/f16` for vector
4122 // By testing on real card, `s_max/min_f32/f16` has the same behavior
4123 // as `v_max/min_num_f32/f16`. So for GFX11.7, even if
4124 // `hasSALUMinimumMaximumInsts()` returns false, we can still choose SGPR
4126 bool ScalarNumIsSafe =
4127 !MFI->getMode().IEEE || Subtarget.hasIEEEMinimumMaximumInsts();
4128 if (Subtarget.hasSALUFloatInsts() && Ty.isScalar() &&
4129 (Size == 32 || Size == 16) && isSALUMapping(MI) && ScalarNumIsSafe)
4130 return getDefaultMappingSOP(MI);
4131 return getDefaultMappingVOP(MI);
4132 }
4133 case AMDGPU::G_FMINIMUM:
4134 case AMDGPU::G_FMAXIMUM: {
4135 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4136 unsigned Size = Ty.getSizeInBits();
4137 if (Subtarget.hasSALUMinimumMaximumInsts() && Ty.isScalar() &&
4138 (Size == 32 || Size == 16) && isSALUMapping(MI))
4139 return getDefaultMappingSOP(MI);
4140 return getDefaultMappingVOP(MI);
4141 }
4142 case AMDGPU::G_FPTOSI:
4143 case AMDGPU::G_FPTOUI:
4144 case AMDGPU::G_FPTOSI_SAT:
4145 case AMDGPU::G_FPTOUI_SAT:
4146 case AMDGPU::G_SITOFP:
4147 case AMDGPU::G_UITOFP: {
4148 unsigned SizeDst = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4149 unsigned SizeSrc = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4150 if (Subtarget.hasSALUFloatInsts() && SizeDst == 32 && SizeSrc == 32 &&
4152 return getDefaultMappingSOP(MI);
4153 return getDefaultMappingVOP(MI);
4154 }
4155 case AMDGPU::G_FPTRUNC:
4156 case AMDGPU::G_FPEXT: {
4157 unsigned SizeDst = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4158 unsigned SizeSrc = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4159 if (Subtarget.hasSALUFloatInsts() && SizeDst != 64 && SizeSrc != 64 &&
4161 return getDefaultMappingSOP(MI);
4162 return getDefaultMappingVOP(MI);
4163 }
4164 case AMDGPU::G_FSQRT:
4165 case AMDGPU::G_FEXP2:
4166 case AMDGPU::G_FLOG2: {
4167 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4168 if (Subtarget.hasPseudoScalarTrans() && (Size == 16 || Size == 32) &&
4170 return getDefaultMappingSOP(MI);
4171 return getDefaultMappingVOP(MI);
4172 }
4173 case AMDGPU::G_SADDSAT: // FIXME: Could lower sat ops for SALU
4174 case AMDGPU::G_SSUBSAT:
4175 case AMDGPU::G_UADDSAT:
4176 case AMDGPU::G_USUBSAT:
4177 case AMDGPU::G_FMAD:
4178 case AMDGPU::G_FLDEXP:
4179 case AMDGPU::G_FMINNUM_IEEE:
4180 case AMDGPU::G_FMAXNUM_IEEE:
4181 case AMDGPU::G_FCANONICALIZE:
4182 case AMDGPU::G_STRICT_FLDEXP:
4183 case AMDGPU::G_BSWAP: // TODO: Somehow expand for scalar?
4184 case AMDGPU::G_FSHR: // TODO: Expand for scalar
4185 case AMDGPU::G_AMDGPU_FMIN_LEGACY:
4186 case AMDGPU::G_AMDGPU_FMAX_LEGACY:
4187 case AMDGPU::G_AMDGPU_RCP_IFLAG:
4188 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
4189 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
4190 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
4191 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
4192 case AMDGPU::G_AMDGPU_CVT_PK_I16_I32:
4193 case AMDGPU::G_AMDGPU_SMED3:
4194 case AMDGPU::G_AMDGPU_FMED3:
4195 return getDefaultMappingVOP(MI);
4196 case AMDGPU::G_UMULH:
4197 case AMDGPU::G_SMULH: {
4198 if (Subtarget.hasScalarMulHiInsts() && isSALUMapping(MI))
4199 return getDefaultMappingSOP(MI);
4200 return getDefaultMappingVOP(MI);
4201 }
4202 case AMDGPU::G_AMDGPU_MAD_U64_U32:
4203 case AMDGPU::G_AMDGPU_MAD_I64_I32: {
4204 // Three possible mappings:
4205 //
4206 // - Default SOP
4207 // - Default VOP
4208 // - Scalar multiply: src0 and src1 are SGPRs, the rest is VOP.
4209 //
4210 // This allows instruction selection to keep the multiplication part of the
4211 // instruction on the SALU.
4212 bool AllSalu = true;
4213 bool MulSalu = true;
4214 for (unsigned i = 0; i < 5; ++i) {
4215 Register Reg = MI.getOperand(i).getReg();
4216 if (const RegisterBank *Bank = getRegBank(Reg, MRI, *TRI)) {
4217 if (Bank->getID() != AMDGPU::SGPRRegBankID) {
4218 AllSalu = false;
4219 if (i == 2 || i == 3) {
4220 MulSalu = false;
4221 break;
4222 }
4223 }
4224 }
4225 }
4226
4227 if (AllSalu)
4228 return getDefaultMappingSOP(MI);
4229
4230 // If the multiply-add is full-rate in VALU, use that even if the
4231 // multiplication part is scalar. Accumulating separately on the VALU would
4232 // take two instructions.
4233 if (!MulSalu || Subtarget.hasFullRate64Ops())
4234 return getDefaultMappingVOP(MI);
4235
4236 // Keep the multiplication on the SALU, then accumulate on the VALU.
4237 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 64);
4238 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
4239 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32);
4240 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32);
4241 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 64);
4242 break;
4243 }
4244 case AMDGPU::G_IMPLICIT_DEF: {
4245 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4246 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
4247 break;
4248 }
4249 case AMDGPU::G_FCONSTANT:
4250 case AMDGPU::G_CONSTANT:
4251 case AMDGPU::G_GLOBAL_VALUE:
4252 case AMDGPU::G_FRAME_INDEX:
4253 case AMDGPU::G_BLOCK_ADDR:
4254 case AMDGPU::G_READSTEADYCOUNTER:
4255 case AMDGPU::G_READCYCLECOUNTER: {
4256 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4257 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
4258 break;
4259 }
4260 case AMDGPU::G_DYN_STACKALLOC: {
4261 // Result is always uniform, and a wave reduction is needed for the source.
4262 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32);
4263 unsigned SrcBankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4264 OpdsMapping[1] = AMDGPU::getValueMapping(SrcBankID, 32);
4265 break;
4266 }
4267 case AMDGPU::G_AMDGPU_WAVE_ADDRESS: {
4268 // This case is weird because we expect a physical register in the source,
4269 // but need to set a bank anyway.
4270 //
4271 // TODO: We could select the result to SGPR or VGPR
4272 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32);
4273 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32);
4274 break;
4275 }
4276 case AMDGPU::G_INSERT: {
4277 unsigned BankID = getMappingType(MRI, MI);
4278 unsigned DstSize = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
4279 unsigned SrcSize = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
4280 unsigned EltSize = getSizeInBits(MI.getOperand(2).getReg(), MRI, *TRI);
4281 OpdsMapping[0] = AMDGPU::getValueMapping(BankID, DstSize);
4282 OpdsMapping[1] = AMDGPU::getValueMapping(BankID, SrcSize);
4283 OpdsMapping[2] = AMDGPU::getValueMapping(BankID, EltSize);
4284 OpdsMapping[3] = nullptr;
4285 break;
4286 }
4287 case AMDGPU::G_EXTRACT: {
4288 unsigned BankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4289 unsigned DstSize = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
4290 unsigned SrcSize = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
4291 OpdsMapping[0] = AMDGPU::getValueMapping(BankID, DstSize);
4292 OpdsMapping[1] = AMDGPU::getValueMapping(BankID, SrcSize);
4293 OpdsMapping[2] = nullptr;
4294 break;
4295 }
4296 case AMDGPU::G_BUILD_VECTOR:
4297 case AMDGPU::G_BUILD_VECTOR_TRUNC: {
4298 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
4299 if (DstTy == LLT::fixed_vector(2, 16)) {
4300 unsigned DstSize = DstTy.getSizeInBits();
4301 unsigned SrcSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4302 unsigned Src0BankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4303 unsigned Src1BankID = getRegBankID(MI.getOperand(2).getReg(), MRI);
4304 unsigned DstBankID = regBankUnion(Src0BankID, Src1BankID);
4305
4306 OpdsMapping[0] = AMDGPU::getValueMapping(DstBankID, DstSize);
4307 OpdsMapping[1] = AMDGPU::getValueMapping(Src0BankID, SrcSize);
4308 OpdsMapping[2] = AMDGPU::getValueMapping(Src1BankID, SrcSize);
4309 break;
4310 }
4311
4312 [[fallthrough]];
4313 }
4314 case AMDGPU::G_MERGE_VALUES:
4315 case AMDGPU::G_CONCAT_VECTORS: {
4316 unsigned Bank = getMappingType(MRI, MI);
4317 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4318 unsigned SrcSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4319
4320 OpdsMapping[0] = AMDGPU::getValueMapping(Bank, DstSize);
4321 // Op1 and Dst should use the same register bank.
4322 for (unsigned i = 1, e = MI.getNumOperands(); i != e; ++i)
4323 OpdsMapping[i] = AMDGPU::getValueMapping(Bank, SrcSize);
4324 break;
4325 }
4326 case AMDGPU::G_BITREVERSE:
4327 case AMDGPU::G_BITCAST:
4328 case AMDGPU::G_INTTOPTR:
4329 case AMDGPU::G_PTRTOINT:
4330 case AMDGPU::G_FABS:
4331 case AMDGPU::G_FNEG: {
4332 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4333 unsigned BankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4334 OpdsMapping[0] = OpdsMapping[1] = AMDGPU::getValueMapping(BankID, Size);
4335 break;
4336 }
4337 case AMDGPU::G_AMDGPU_FFBH_U32:
4338 case AMDGPU::G_AMDGPU_FFBL_B32:
4339 case AMDGPU::G_CTLZ_ZERO_POISON:
4340 case AMDGPU::G_CTTZ_ZERO_POISON: {
4341 unsigned Size = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4342 unsigned BankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4343 OpdsMapping[0] = AMDGPU::getValueMapping(BankID, 32);
4344 OpdsMapping[1] = AMDGPU::getValueMappingSGPR64Only(BankID, Size);
4345 break;
4346 }
4347 case AMDGPU::G_CTPOP: {
4348 unsigned Size = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4349 unsigned BankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4350 OpdsMapping[0] = AMDGPU::getValueMapping(BankID, 32);
4351
4352 // This should really be getValueMappingSGPR64Only, but allowing the generic
4353 // code to handle the register split just makes using LegalizerHelper more
4354 // difficult.
4355 OpdsMapping[1] = AMDGPU::getValueMapping(BankID, Size);
4356 break;
4357 }
4358 case AMDGPU::G_TRUNC: {
4359 Register Dst = MI.getOperand(0).getReg();
4360 Register Src = MI.getOperand(1).getReg();
4361 unsigned Bank = getRegBankID(Src, MRI);
4362 unsigned DstSize = getSizeInBits(Dst, MRI, *TRI);
4363 unsigned SrcSize = getSizeInBits(Src, MRI, *TRI);
4364 OpdsMapping[0] = AMDGPU::getValueMapping(Bank, DstSize);
4365 OpdsMapping[1] = AMDGPU::getValueMapping(Bank, SrcSize);
4366 break;
4367 }
4368 case AMDGPU::G_ZEXT:
4369 case AMDGPU::G_SEXT:
4370 case AMDGPU::G_ANYEXT:
4371 case AMDGPU::G_SEXT_INREG: {
4372 Register Dst = MI.getOperand(0).getReg();
4373 Register Src = MI.getOperand(1).getReg();
4374 unsigned DstSize = getSizeInBits(Dst, MRI, *TRI);
4375 unsigned SrcSize = getSizeInBits(Src, MRI, *TRI);
4376
4377 unsigned DstBank;
4378 const RegisterBank *SrcBank = getRegBank(Src, MRI, *TRI);
4379 assert(SrcBank);
4380 switch (SrcBank->getID()) {
4381 case AMDGPU::SGPRRegBankID:
4382 DstBank = AMDGPU::SGPRRegBankID;
4383 break;
4384 default:
4385 DstBank = AMDGPU::VGPRRegBankID;
4386 break;
4387 }
4388
4389 // Scalar extend can use 64-bit BFE, but VGPRs require extending to
4390 // 32-bits, and then to 64.
4391 OpdsMapping[0] = AMDGPU::getValueMappingSGPR64Only(DstBank, DstSize);
4392 OpdsMapping[1] = AMDGPU::getValueMappingSGPR64Only(SrcBank->getID(),
4393 SrcSize);
4394 break;
4395 }
4396 case AMDGPU::G_IS_FPCLASS: {
4397 Register SrcReg = MI.getOperand(1).getReg();
4398 unsigned SrcSize = MRI.getType(SrcReg).getSizeInBits();
4399 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4400 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, DstSize);
4401 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, SrcSize);
4402 break;
4403 }
4404 case AMDGPU::G_STORE: {
4405 assert(MI.getOperand(0).isReg());
4406 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4407
4408 // FIXME: We need to specify a different reg bank once scalar stores are
4409 // supported.
4410 const ValueMapping *ValMapping =
4411 AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
4412 OpdsMapping[0] = ValMapping;
4413 OpdsMapping[1] = getValueMappingForPtr(MRI, MI.getOperand(1).getReg());
4414 break;
4415 }
4416 case AMDGPU::G_ICMP:
4417 case AMDGPU::G_FCMP: {
4418 unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
4419
4420 // See if the result register has already been constrained to vcc, which may
4421 // happen due to control flow intrinsic lowering.
4422 unsigned DstBank = getRegBankID(MI.getOperand(0).getReg(), MRI,
4423 AMDGPU::SGPRRegBankID);
4424 unsigned Op2Bank = getRegBankID(MI.getOperand(2).getReg(), MRI);
4425 unsigned Op3Bank = getRegBankID(MI.getOperand(3).getReg(), MRI);
4426
4427 auto canUseSCCICMP = [&]() {
4428 auto Pred =
4429 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
4430 return Size == 32 ||
4431 (Size == 64 &&
4432 (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE) &&
4433 Subtarget.hasScalarCompareEq64());
4434 };
4435 auto canUseSCCFCMP = [&]() {
4436 return Subtarget.hasSALUFloatInsts() && (Size == 32 || Size == 16);
4437 };
4438
4439 bool isICMP = MI.getOpcode() == AMDGPU::G_ICMP;
4440 bool CanUseSCC = DstBank == AMDGPU::SGPRRegBankID &&
4441 Op2Bank == AMDGPU::SGPRRegBankID &&
4442 Op3Bank == AMDGPU::SGPRRegBankID &&
4443 (isICMP ? canUseSCCICMP() : canUseSCCFCMP());
4444
4445 DstBank = CanUseSCC ? AMDGPU::SGPRRegBankID : AMDGPU::VCCRegBankID;
4446 unsigned SrcBank = CanUseSCC ? AMDGPU::SGPRRegBankID : AMDGPU::VGPRRegBankID;
4447
4448 // TODO: Use 32-bit for scalar output size.
4449 // SCC results will need to be copied to a 32-bit SGPR virtual register.
4450 const unsigned ResultSize = 1;
4451
4452 OpdsMapping[0] = AMDGPU::getValueMapping(DstBank, ResultSize);
4453 OpdsMapping[1] = nullptr; // Predicate Operand.
4454 OpdsMapping[2] = AMDGPU::getValueMapping(SrcBank, Size);
4455 OpdsMapping[3] = AMDGPU::getValueMapping(SrcBank, Size);
4456 break;
4457 }
4458 case AMDGPU::G_EXTRACT_VECTOR_ELT: {
4459 // VGPR index can be used for waterfall when indexing a SGPR vector.
4460 unsigned SrcBankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4461 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4462 unsigned SrcSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4463 unsigned IdxSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
4464 unsigned IdxBank = getRegBankID(MI.getOperand(2).getReg(), MRI);
4465 unsigned OutputBankID = regBankUnion(SrcBankID, IdxBank);
4466
4467 OpdsMapping[0] = AMDGPU::getValueMappingSGPR64Only(OutputBankID, DstSize);
4468 OpdsMapping[1] = AMDGPU::getValueMapping(SrcBankID, SrcSize);
4469
4470 // The index can be either if the source vector is VGPR.
4471 OpdsMapping[2] = AMDGPU::getValueMapping(IdxBank, IdxSize);
4472 break;
4473 }
4474 case AMDGPU::G_INSERT_VECTOR_ELT: {
4475 unsigned OutputBankID = isSALUMapping(MI) ?
4476 AMDGPU::SGPRRegBankID : AMDGPU::VGPRRegBankID;
4477
4478 unsigned VecSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4479 unsigned InsertSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
4480 unsigned IdxSize = MRI.getType(MI.getOperand(3).getReg()).getSizeInBits();
4481 unsigned InsertEltBankID = getRegBankID(MI.getOperand(2).getReg(), MRI);
4482 unsigned IdxBankID = getRegBankID(MI.getOperand(3).getReg(), MRI);
4483
4484 OpdsMapping[0] = AMDGPU::getValueMapping(OutputBankID, VecSize);
4485 OpdsMapping[1] = AMDGPU::getValueMapping(OutputBankID, VecSize);
4486
4487 // This is a weird case, because we need to break down the mapping based on
4488 // the register bank of a different operand.
4489 if (InsertSize == 64 && OutputBankID == AMDGPU::VGPRRegBankID) {
4490 OpdsMapping[2] = AMDGPU::getValueMappingSplit64(InsertEltBankID,
4491 InsertSize);
4492 } else {
4493 assert(InsertSize == 32 || InsertSize == 64);
4494 OpdsMapping[2] = AMDGPU::getValueMapping(InsertEltBankID, InsertSize);
4495 }
4496
4497 // The index can be either if the source vector is VGPR.
4498 OpdsMapping[3] = AMDGPU::getValueMapping(IdxBankID, IdxSize);
4499 break;
4500 }
4501 case AMDGPU::G_UNMERGE_VALUES: {
4502 unsigned Bank = getMappingType(MRI, MI);
4503
4504 // Op1 and Dst should use the same register bank.
4505 // FIXME: Shouldn't this be the default? Why do we need to handle this?
4506 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
4507 unsigned Size = getSizeInBits(MI.getOperand(i).getReg(), MRI, *TRI);
4508 OpdsMapping[i] = AMDGPU::getValueMapping(Bank, Size);
4509 }
4510 break;
4511 }
4512 case AMDGPU::G_AMDGPU_BUFFER_LOAD:
4513 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
4514 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE:
4515 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
4516 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT:
4517 case AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE:
4518 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE:
4519 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE_TFE:
4520 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE:
4521 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT_TFE:
4522 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT:
4523 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE:
4524 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16:
4525 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16_TFE:
4526 case AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT:
4527 case AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16:
4528 case AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT:
4529 case AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16:
4530 case AMDGPU::G_AMDGPU_BUFFER_STORE:
4531 case AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE:
4532 case AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT:
4533 case AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT:
4534 case AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16: {
4535 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
4536
4537 // rsrc
4538 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
4539
4540 // vindex
4541 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
4542
4543 // voffset
4544 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
4545
4546 // soffset
4547 OpdsMapping[4] = getSGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
4548
4549 // Any remaining operands are immediates and were correctly null
4550 // initialized.
4551 break;
4552 }
4553 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP:
4554 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD:
4555 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB:
4556 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN:
4557 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN:
4558 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX:
4559 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX:
4560 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND:
4561 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR:
4562 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR:
4563 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC:
4564 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC:
4565 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32:
4566 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32:
4567 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD:
4568 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN:
4569 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX: {
4570 // vdata_out
4571 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
4572
4573 // vdata_in
4574 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
4575
4576 // rsrc
4577 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
4578
4579 // vindex
4580 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
4581
4582 // voffset
4583 OpdsMapping[4] = getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
4584
4585 // soffset
4586 OpdsMapping[5] = getSGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
4587
4588 // Any remaining operands are immediates and were correctly null
4589 // initialized.
4590 break;
4591 }
4592 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP: {
4593 // vdata_out
4594 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
4595
4596 // vdata_in
4597 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
4598
4599 // cmp
4600 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
4601
4602 // rsrc
4603 OpdsMapping[3] = getSGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
4604
4605 // vindex
4606 OpdsMapping[4] = getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
4607
4608 // voffset
4609 OpdsMapping[5] = getVGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
4610
4611 // soffset
4612 OpdsMapping[6] = getSGPROpMapping(MI.getOperand(6).getReg(), MRI, *TRI);
4613
4614 // Any remaining operands are immediates and were correctly null
4615 // initialized.
4616 break;
4617 }
4618 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD:
4619 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
4620 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE:
4621 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
4622 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT: {
4623 // Lie and claim everything is legal, even though some need to be
4624 // SGPRs. applyMapping will have to deal with it as a waterfall loop.
4625 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
4626 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
4627
4628 // We need to convert this to a MUBUF if either the resource of offset is
4629 // VGPR.
4630 unsigned RSrcBank = OpdsMapping[1]->BreakDown[0].RegBank->getID();
4631 unsigned OffsetBank = OpdsMapping[2]->BreakDown[0].RegBank->getID();
4632 unsigned ResultBank = regBankUnion(RSrcBank, OffsetBank);
4633
4634 unsigned Size0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4635 OpdsMapping[0] = AMDGPU::getValueMapping(ResultBank, Size0);
4636 break;
4637 }
4638 case AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH:
4639 OpdsMapping[0] = getSGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
4640 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
4641 break;
4642 case AMDGPU::G_AMDGPU_SPONENTRY: {
4643 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4644 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
4645 break;
4646 }
4647 case AMDGPU::G_INTRINSIC:
4648 case AMDGPU::G_INTRINSIC_CONVERGENT: {
4649 switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
4650 default:
4652 case Intrinsic::amdgcn_div_fmas:
4653 case Intrinsic::amdgcn_div_fixup:
4654 case Intrinsic::amdgcn_trig_preop:
4655 case Intrinsic::amdgcn_sin:
4656 case Intrinsic::amdgcn_cos:
4657 case Intrinsic::amdgcn_log_clamp:
4658 case Intrinsic::amdgcn_rcp_legacy:
4659 case Intrinsic::amdgcn_rsq_legacy:
4660 case Intrinsic::amdgcn_rsq_clamp:
4661 case Intrinsic::amdgcn_tanh:
4662 case Intrinsic::amdgcn_fmul_legacy:
4663 case Intrinsic::amdgcn_fma_legacy:
4664 case Intrinsic::amdgcn_frexp_mant:
4665 case Intrinsic::amdgcn_frexp_exp:
4666 case Intrinsic::amdgcn_fract:
4667 case Intrinsic::amdgcn_cvt_pknorm_i16:
4668 case Intrinsic::amdgcn_cvt_pknorm_u16:
4669 case Intrinsic::amdgcn_cvt_pk_i16:
4670 case Intrinsic::amdgcn_cvt_pk_u16:
4671 case Intrinsic::amdgcn_cvt_sr_pk_f16_f32:
4672 case Intrinsic::amdgcn_cvt_sr_pk_bf16_f32:
4673 case Intrinsic::amdgcn_cvt_pk_f16_fp8:
4674 case Intrinsic::amdgcn_cvt_pk_f16_bf8:
4675 case Intrinsic::amdgcn_cvt_pk_fp8_f16:
4676 case Intrinsic::amdgcn_cvt_pk_bf8_f16:
4677 case Intrinsic::amdgcn_cvt_sr_fp8_f16:
4678 case Intrinsic::amdgcn_cvt_sr_bf8_f16:
4679 case Intrinsic::amdgcn_cvt_scale_pk8_f16_fp8:
4680 case Intrinsic::amdgcn_cvt_scale_pk8_bf16_fp8:
4681 case Intrinsic::amdgcn_cvt_scale_pk8_f16_bf8:
4682 case Intrinsic::amdgcn_cvt_scale_pk8_bf16_bf8:
4683 case Intrinsic::amdgcn_cvt_scale_pk8_f16_fp4:
4684 case Intrinsic::amdgcn_cvt_scale_pk8_bf16_fp4:
4685 case Intrinsic::amdgcn_cvt_scale_pk8_f32_fp8:
4686 case Intrinsic::amdgcn_cvt_scale_pk8_f32_bf8:
4687 case Intrinsic::amdgcn_cvt_scale_pk8_f32_fp4:
4688 case Intrinsic::amdgcn_cvt_scale_pk16_f16_fp6:
4689 case Intrinsic::amdgcn_cvt_scale_pk16_bf16_fp6:
4690 case Intrinsic::amdgcn_cvt_scale_pk16_f16_bf6:
4691 case Intrinsic::amdgcn_cvt_scale_pk16_bf16_bf6:
4692 case Intrinsic::amdgcn_cvt_scale_pk16_f32_fp6:
4693 case Intrinsic::amdgcn_cvt_scale_pk16_f32_bf6:
4694 case Intrinsic::amdgcn_cvt_scale_pk32_f16_fp6:
4695 case Intrinsic::amdgcn_cvt_scale_pk32_bf16_fp6:
4696 case Intrinsic::amdgcn_cvt_scale_pk32_f16_bf6:
4697 case Intrinsic::amdgcn_cvt_scale_pk32_bf16_bf6:
4698 case Intrinsic::amdgcn_cvt_scale_pk32_f32_fp6:
4699 case Intrinsic::amdgcn_cvt_scale_pk32_f32_bf6:
4700 case Intrinsic::amdgcn_cvt_scalef32_pk8_fp8_bf16:
4701 case Intrinsic::amdgcn_cvt_scalef32_pk8_bf8_bf16:
4702 case Intrinsic::amdgcn_cvt_scalef32_pk8_fp8_f16:
4703 case Intrinsic::amdgcn_cvt_scalef32_pk8_bf8_f16:
4704 case Intrinsic::amdgcn_cvt_scalef32_pk8_fp8_f32:
4705 case Intrinsic::amdgcn_cvt_scalef32_pk8_bf8_f32:
4706 case Intrinsic::amdgcn_cvt_scalef32_pk8_fp4_f32:
4707 case Intrinsic::amdgcn_cvt_scalef32_pk8_fp4_f16:
4708 case Intrinsic::amdgcn_cvt_scalef32_pk8_fp4_bf16:
4709 case Intrinsic::amdgcn_cvt_scalef32_pk16_fp6_f32:
4710 case Intrinsic::amdgcn_cvt_scalef32_pk16_bf6_f32:
4711 case Intrinsic::amdgcn_cvt_scalef32_pk16_fp6_f16:
4712 case Intrinsic::amdgcn_cvt_scalef32_pk16_bf6_f16:
4713 case Intrinsic::amdgcn_cvt_scalef32_pk16_fp6_bf16:
4714 case Intrinsic::amdgcn_cvt_scalef32_pk16_bf6_bf16:
4715 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_fp8_bf16:
4716 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_bf8_bf16:
4717 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_fp8_f16:
4718 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_bf8_f16:
4719 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_fp8_f32:
4720 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_bf8_f32:
4721 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_fp4_f32:
4722 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_fp4_f16:
4723 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_fp4_bf16:
4724 case Intrinsic::amdgcn_cvt_scalef32_sr_pk16_fp6_f32:
4725 case Intrinsic::amdgcn_cvt_scalef32_sr_pk16_bf6_f32:
4726 case Intrinsic::amdgcn_cvt_scalef32_sr_pk16_fp6_f16:
4727 case Intrinsic::amdgcn_cvt_scalef32_sr_pk16_bf6_f16:
4728 case Intrinsic::amdgcn_cvt_scalef32_sr_pk16_fp6_bf16:
4729 case Intrinsic::amdgcn_cvt_scalef32_sr_pk16_bf6_bf16:
4730 case Intrinsic::amdgcn_sat_pk4_i4_i8:
4731 case Intrinsic::amdgcn_sat_pk4_u4_u8:
4732 case Intrinsic::amdgcn_fmed3:
4733 case Intrinsic::amdgcn_cubeid:
4734 case Intrinsic::amdgcn_cubema:
4735 case Intrinsic::amdgcn_cubesc:
4736 case Intrinsic::amdgcn_cubetc:
4737 case Intrinsic::amdgcn_sffbh:
4738 case Intrinsic::amdgcn_fmad_ftz:
4739 case Intrinsic::amdgcn_mbcnt_lo:
4740 case Intrinsic::amdgcn_mbcnt_hi:
4741 case Intrinsic::amdgcn_mul_u24:
4742 case Intrinsic::amdgcn_mul_i24:
4743 case Intrinsic::amdgcn_mulhi_u24:
4744 case Intrinsic::amdgcn_mulhi_i24:
4745 case Intrinsic::amdgcn_lerp:
4746 case Intrinsic::amdgcn_sad_u8:
4747 case Intrinsic::amdgcn_msad_u8:
4748 case Intrinsic::amdgcn_sad_hi_u8:
4749 case Intrinsic::amdgcn_sad_u16:
4750 case Intrinsic::amdgcn_qsad_pk_u16_u8:
4751 case Intrinsic::amdgcn_mqsad_pk_u16_u8:
4752 case Intrinsic::amdgcn_mqsad_u32_u8:
4753 case Intrinsic::amdgcn_cvt_pk_u8_f32:
4754 case Intrinsic::amdgcn_alignbyte:
4755 case Intrinsic::amdgcn_perm:
4756 case Intrinsic::amdgcn_prng_b32:
4757 case Intrinsic::amdgcn_exclusive_scan_sum_i32:
4758 case Intrinsic::amdgcn_exclusive_scan_sum_u32:
4759 case Intrinsic::amdgcn_exclusive_scan_xor_b32:
4760 case Intrinsic::amdgcn_exclusive_scan_or_b32:
4761 case Intrinsic::amdgcn_exclusive_scan_and_b32:
4762 case Intrinsic::amdgcn_exclusive_scan_min_i16:
4763 case Intrinsic::amdgcn_exclusive_scan_min_u16:
4764 case Intrinsic::amdgcn_exclusive_scan_min_i32:
4765 case Intrinsic::amdgcn_exclusive_scan_min_u32:
4766 case Intrinsic::amdgcn_exclusive_scan_max_i16:
4767 case Intrinsic::amdgcn_exclusive_scan_max_u16:
4768 case Intrinsic::amdgcn_exclusive_scan_max_i32:
4769 case Intrinsic::amdgcn_exclusive_scan_max_u32:
4770 case Intrinsic::amdgcn_wave_match_b32:
4771 case Intrinsic::amdgcn_fdot2:
4772 case Intrinsic::amdgcn_sdot2:
4773 case Intrinsic::amdgcn_udot2:
4774 case Intrinsic::amdgcn_sdot4:
4775 case Intrinsic::amdgcn_udot4:
4776 case Intrinsic::amdgcn_sdot8:
4777 case Intrinsic::amdgcn_udot8:
4778 case Intrinsic::amdgcn_fdot2_bf16_bf16:
4779 case Intrinsic::amdgcn_fdot2_f16_f16:
4780 case Intrinsic::amdgcn_fdot2_f32_bf16:
4781 case Intrinsic::amdgcn_fdot2c_f32_bf16:
4782 case Intrinsic::amdgcn_sudot4:
4783 case Intrinsic::amdgcn_sudot8:
4784 case Intrinsic::amdgcn_dot4_f32_fp8_bf8:
4785 case Intrinsic::amdgcn_dot4_f32_bf8_fp8:
4786 case Intrinsic::amdgcn_dot4_f32_fp8_fp8:
4787 case Intrinsic::amdgcn_dot4_f32_bf8_bf8:
4788 case Intrinsic::amdgcn_cvt_f32_fp8:
4789 case Intrinsic::amdgcn_cvt_f32_fp8_e5m3:
4790 case Intrinsic::amdgcn_cvt_f32_bf8:
4791 case Intrinsic::amdgcn_cvt_off_f32_i4:
4792 case Intrinsic::amdgcn_cvt_pk_f32_fp8:
4793 case Intrinsic::amdgcn_cvt_pk_f32_bf8:
4794 case Intrinsic::amdgcn_cvt_pk_fp8_f32:
4795 case Intrinsic::amdgcn_cvt_pk_fp8_f32_e5m3:
4796 case Intrinsic::amdgcn_cvt_pk_bf8_f32:
4797 case Intrinsic::amdgcn_cvt_sr_fp8_f32:
4798 case Intrinsic::amdgcn_cvt_sr_fp8_f32_e5m3:
4799 case Intrinsic::amdgcn_cvt_sr_bf8_f32:
4800 case Intrinsic::amdgcn_cvt_sr_bf16_f32:
4801 case Intrinsic::amdgcn_cvt_sr_f16_f32:
4802 case Intrinsic::amdgcn_cvt_f16_fp8:
4803 case Intrinsic::amdgcn_cvt_f16_bf8:
4804 case Intrinsic::amdgcn_cvt_scalef32_pk32_fp6_f16:
4805 case Intrinsic::amdgcn_cvt_scalef32_pk32_bf6_f16:
4806 case Intrinsic::amdgcn_cvt_scalef32_pk32_fp6_bf16:
4807 case Intrinsic::amdgcn_cvt_scalef32_pk32_bf6_bf16:
4808 case Intrinsic::amdgcn_cvt_scalef32_pk32_fp6_f32:
4809 case Intrinsic::amdgcn_cvt_scalef32_pk32_bf6_f32:
4810 case Intrinsic::amdgcn_cvt_scalef32_f16_fp8:
4811 case Intrinsic::amdgcn_cvt_scalef32_f16_bf8:
4812 case Intrinsic::amdgcn_cvt_scalef32_f32_fp8:
4813 case Intrinsic::amdgcn_cvt_scalef32_f32_bf8:
4814 case Intrinsic::amdgcn_cvt_scalef32_pk_fp8_f32:
4815 case Intrinsic::amdgcn_cvt_scalef32_pk_bf8_f32:
4816 case Intrinsic::amdgcn_cvt_scalef32_pk_f32_fp8:
4817 case Intrinsic::amdgcn_cvt_scalef32_pk_f32_bf8:
4818 case Intrinsic::amdgcn_cvt_scalef32_pk_fp8_f16:
4819 case Intrinsic::amdgcn_cvt_scalef32_pk_fp8_bf16:
4820 case Intrinsic::amdgcn_cvt_scalef32_pk_bf8_f16:
4821 case Intrinsic::amdgcn_cvt_scalef32_pk_bf8_bf16:
4822 case Intrinsic::amdgcn_cvt_scalef32_pk_f32_fp4:
4823 case Intrinsic::amdgcn_cvt_scalef32_pk_fp4_f32:
4824 case Intrinsic::amdgcn_cvt_scalef32_pk_f16_fp4:
4825 case Intrinsic::amdgcn_cvt_scalef32_pk_bf16_fp4:
4826 case Intrinsic::amdgcn_cvt_scalef32_pk32_f32_fp6:
4827 case Intrinsic::amdgcn_cvt_scalef32_pk32_f32_bf6:
4828 case Intrinsic::amdgcn_cvt_scalef32_pk32_f16_bf6:
4829 case Intrinsic::amdgcn_cvt_scalef32_pk32_bf16_bf6:
4830 case Intrinsic::amdgcn_cvt_scalef32_pk32_f16_fp6:
4831 case Intrinsic::amdgcn_cvt_scalef32_pk32_bf16_fp6:
4832 case Intrinsic::amdgcn_cvt_scalef32_pk_f16_bf8:
4833 case Intrinsic::amdgcn_cvt_scalef32_pk_bf16_bf8:
4834 case Intrinsic::amdgcn_cvt_scalef32_pk_f16_fp8:
4835 case Intrinsic::amdgcn_cvt_scalef32_pk_bf16_fp8:
4836 case Intrinsic::amdgcn_cvt_scalef32_pk_fp4_f16:
4837 case Intrinsic::amdgcn_cvt_scalef32_pk_fp4_bf16:
4838 case Intrinsic::amdgcn_cvt_scalef32_sr_pk_fp4_f16:
4839 case Intrinsic::amdgcn_cvt_scalef32_sr_pk_fp4_bf16:
4840 case Intrinsic::amdgcn_cvt_scalef32_sr_pk_fp4_f32:
4841 case Intrinsic::amdgcn_cvt_scalef32_sr_pk32_bf6_bf16:
4842 case Intrinsic::amdgcn_cvt_scalef32_sr_pk32_bf6_f16:
4843 case Intrinsic::amdgcn_cvt_scalef32_sr_pk32_bf6_f32:
4844 case Intrinsic::amdgcn_cvt_scalef32_sr_pk32_fp6_bf16:
4845 case Intrinsic::amdgcn_cvt_scalef32_sr_pk32_fp6_f16:
4846 case Intrinsic::amdgcn_cvt_scalef32_sr_pk32_fp6_f32:
4847 case Intrinsic::amdgcn_cvt_scalef32_sr_bf8_bf16:
4848 case Intrinsic::amdgcn_cvt_scalef32_sr_bf8_f16:
4849 case Intrinsic::amdgcn_cvt_scalef32_sr_bf8_f32:
4850 case Intrinsic::amdgcn_cvt_scalef32_sr_fp8_bf16:
4851 case Intrinsic::amdgcn_cvt_scalef32_sr_fp8_f16:
4852 case Intrinsic::amdgcn_cvt_scalef32_sr_fp8_f32:
4853 case Intrinsic::amdgcn_ashr_pk_i8_i32:
4854 case Intrinsic::amdgcn_ashr_pk_u8_i32:
4855 case Intrinsic::amdgcn_cvt_scalef32_2xpk16_fp6_f32:
4856 case Intrinsic::amdgcn_cvt_scalef32_2xpk16_bf6_f32:
4857 case Intrinsic::amdgcn_wmma_bf16_16x16x16_bf16:
4858 case Intrinsic::amdgcn_wmma_f16_16x16x16_f16:
4859 case Intrinsic::amdgcn_wmma_bf16_16x16x16_bf16_tied:
4860 case Intrinsic::amdgcn_wmma_f16_16x16x16_f16_tied:
4861 case Intrinsic::amdgcn_wmma_f32_16x16x16_bf16:
4862 case Intrinsic::amdgcn_wmma_f32_16x16x16_f16:
4863 case Intrinsic::amdgcn_wmma_i32_16x16x16_iu4:
4864 case Intrinsic::amdgcn_wmma_i32_16x16x16_iu8:
4865 case Intrinsic::amdgcn_wmma_f32_16x16x16_fp8_fp8:
4866 case Intrinsic::amdgcn_wmma_f32_16x16x16_fp8_bf8:
4867 case Intrinsic::amdgcn_wmma_f32_16x16x16_bf8_fp8:
4868 case Intrinsic::amdgcn_wmma_f32_16x16x16_bf8_bf8:
4869 case Intrinsic::amdgcn_wmma_i32_16x16x32_iu4:
4870 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
4871 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
4872 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
4873 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
4874 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
4875 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
4876 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4:
4877 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
4878 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
4879 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
4880 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8:
4881 case Intrinsic::amdgcn_wmma_f64_16x16x4_f64:
4882 case Intrinsic::amdgcn_wmma_f32_16x16x4_f32:
4883 case Intrinsic::amdgcn_wmma_f32_16x16x32_bf16:
4884 case Intrinsic::amdgcn_wmma_f32_16x16x32_f16:
4885 case Intrinsic::amdgcn_wmma_f16_16x16x32_f16:
4886 case Intrinsic::amdgcn_wmma_bf16_16x16x32_bf16:
4887 case Intrinsic::amdgcn_wmma_bf16f32_16x16x32_bf16:
4888 case Intrinsic::amdgcn_wmma_f32_16x16x64_fp8_fp8:
4889 case Intrinsic::amdgcn_wmma_f32_16x16x64_fp8_bf8:
4890 case Intrinsic::amdgcn_wmma_f32_16x16x64_bf8_fp8:
4891 case Intrinsic::amdgcn_wmma_f32_16x16x64_bf8_bf8:
4892 case Intrinsic::amdgcn_wmma_f16_16x16x64_fp8_fp8:
4893 case Intrinsic::amdgcn_wmma_f16_16x16x64_fp8_bf8:
4894 case Intrinsic::amdgcn_wmma_f16_16x16x64_bf8_fp8:
4895 case Intrinsic::amdgcn_wmma_f16_16x16x64_bf8_bf8:
4896 case Intrinsic::amdgcn_wmma_f16_16x16x128_fp8_fp8:
4897 case Intrinsic::amdgcn_wmma_f16_16x16x128_fp8_bf8:
4898 case Intrinsic::amdgcn_wmma_f16_16x16x128_bf8_fp8:
4899 case Intrinsic::amdgcn_wmma_f16_16x16x128_bf8_bf8:
4900 case Intrinsic::amdgcn_wmma_f32_16x16x128_fp8_fp8:
4901 case Intrinsic::amdgcn_wmma_f32_16x16x128_fp8_bf8:
4902 case Intrinsic::amdgcn_wmma_f32_16x16x128_bf8_fp8:
4903 case Intrinsic::amdgcn_wmma_f32_16x16x128_bf8_bf8:
4904 case Intrinsic::amdgcn_wmma_i32_16x16x64_iu8:
4905 case Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4:
4906 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
4907 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4:
4908 case Intrinsic::amdgcn_wmma_f32_32x16x128_f4:
4909 case Intrinsic::amdgcn_wmma_scale_f32_32x16x128_f4:
4910 case Intrinsic::amdgcn_wmma_scale16_f32_32x16x128_f4:
4911 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
4912 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
4913 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
4914 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
4915 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
4916 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
4917 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
4918 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
4919 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
4920 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
4921 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
4922 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
4923 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8:
4924 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
4925 case Intrinsic::amdgcn_perm_pk16_b4_u4:
4926 case Intrinsic::amdgcn_perm_pk16_b6_u4:
4927 case Intrinsic::amdgcn_perm_pk16_b8_u4:
4928 case Intrinsic::amdgcn_add_max_i32:
4929 case Intrinsic::amdgcn_add_max_u32:
4930 case Intrinsic::amdgcn_add_min_i32:
4931 case Intrinsic::amdgcn_add_min_u32:
4932 case Intrinsic::amdgcn_pk_add_max_i16:
4933 case Intrinsic::amdgcn_pk_add_max_u16:
4934 case Intrinsic::amdgcn_pk_add_min_i16:
4935 case Intrinsic::amdgcn_pk_add_min_u16:
4936 return getDefaultMappingVOP(MI);
4937 case Intrinsic::amdgcn_log:
4938 case Intrinsic::amdgcn_exp2:
4939 case Intrinsic::amdgcn_rcp:
4940 case Intrinsic::amdgcn_rsq:
4941 case Intrinsic::amdgcn_sqrt: {
4942 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4943 unsigned Size = Ty.getSizeInBits();
4944 // There is no pseudo scalar transcendental instruction for bf16.
4945 if (Subtarget.hasPseudoScalarTrans() && !Ty.isBFloat16() &&
4946 (Size == 16 || Size == 32) && isSALUMapping(MI))
4947 return getDefaultMappingSOP(MI);
4948 return getDefaultMappingVOP(MI);
4949 }
4950 case Intrinsic::amdgcn_sbfe:
4951 case Intrinsic::amdgcn_ubfe:
4952 if (isSALUMapping(MI))
4953 return getDefaultMappingSOP(MI);
4954 return getDefaultMappingVOP(MI);
4955 case Intrinsic::amdgcn_ds_swizzle:
4956 case Intrinsic::amdgcn_ds_permute:
4957 case Intrinsic::amdgcn_ds_bpermute:
4958 case Intrinsic::amdgcn_update_dpp:
4959 case Intrinsic::amdgcn_mov_dpp8:
4960 case Intrinsic::amdgcn_mov_dpp:
4961 case Intrinsic::amdgcn_strict_wwm:
4962 case Intrinsic::amdgcn_wwm:
4963 case Intrinsic::amdgcn_strict_wqm:
4964 case Intrinsic::amdgcn_wqm:
4965 case Intrinsic::amdgcn_softwqm:
4966 case Intrinsic::amdgcn_set_inactive:
4967 case Intrinsic::amdgcn_set_inactive_chain_arg:
4968 case Intrinsic::amdgcn_permlane64:
4969 case Intrinsic::amdgcn_ds_bpermute_fi_b32:
4971 case Intrinsic::amdgcn_cvt_pkrtz:
4972 if (Subtarget.hasSALUFloatInsts() && isSALUMapping(MI))
4973 return getDefaultMappingSOP(MI);
4974 return getDefaultMappingVOP(MI);
4975 case Intrinsic::amdgcn_kernarg_segment_ptr:
4976 case Intrinsic::amdgcn_s_getpc:
4977 case Intrinsic::amdgcn_groupstaticsize:
4978 case Intrinsic::amdgcn_reloc_constant:
4979 case Intrinsic::returnaddress: {
4980 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4981 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
4982 break;
4983 }
4984 case Intrinsic::amdgcn_wqm_vote: {
4985 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4986 OpdsMapping[0] = OpdsMapping[2]
4987 = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, Size);
4988 break;
4989 }
4990 case Intrinsic::amdgcn_ps_live: {
4991 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
4992 break;
4993 }
4994 case Intrinsic::amdgcn_div_scale: {
4995 unsigned Dst0Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4996 unsigned Dst1Size = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4997 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Dst0Size);
4998 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, Dst1Size);
4999
5000 unsigned SrcSize = MRI.getType(MI.getOperand(3).getReg()).getSizeInBits();
5001 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, SrcSize);
5002 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, SrcSize);
5003 break;
5004 }
5005 case Intrinsic::amdgcn_class: {
5006 Register Src0Reg = MI.getOperand(2).getReg();
5007 Register Src1Reg = MI.getOperand(3).getReg();
5008 unsigned Src0Size = MRI.getType(Src0Reg).getSizeInBits();
5009 unsigned Src1Size = MRI.getType(Src1Reg).getSizeInBits();
5010 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5011 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, DstSize);
5012 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Src0Size);
5013 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Src1Size);
5014 break;
5015 }
5016 case Intrinsic::amdgcn_readlane: {
5017 // This must be an SGPR, but accept a VGPR.
5018 Register IdxReg = MI.getOperand(3).getReg();
5019 unsigned IdxSize = MRI.getType(IdxReg).getSizeInBits();
5020 unsigned IdxBank = getRegBankID(IdxReg, MRI, AMDGPU::SGPRRegBankID);
5021 OpdsMapping[3] = AMDGPU::getValueMapping(IdxBank, IdxSize);
5022 [[fallthrough]];
5023 }
5024 case Intrinsic::amdgcn_readfirstlane: {
5025 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5026 unsigned SrcSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
5027 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, DstSize);
5028 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, SrcSize);
5029 break;
5030 }
5031 case Intrinsic::amdgcn_writelane: {
5032 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5033 Register SrcReg = MI.getOperand(2).getReg();
5034 unsigned SrcSize = MRI.getType(SrcReg).getSizeInBits();
5035 unsigned SrcBank = getRegBankID(SrcReg, MRI, AMDGPU::SGPRRegBankID);
5036 Register IdxReg = MI.getOperand(3).getReg();
5037 unsigned IdxSize = MRI.getType(IdxReg).getSizeInBits();
5038 unsigned IdxBank = getRegBankID(IdxReg, MRI, AMDGPU::SGPRRegBankID);
5039 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5040
5041 // These 2 must be SGPRs, but accept VGPRs. Readfirstlane will be inserted
5042 // to legalize.
5043 OpdsMapping[2] = AMDGPU::getValueMapping(SrcBank, SrcSize);
5044 OpdsMapping[3] = AMDGPU::getValueMapping(IdxBank, IdxSize);
5045 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, SrcSize);
5046 break;
5047 }
5048 case Intrinsic::amdgcn_if_break: {
5049 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5050 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
5051 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
5052 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
5053 break;
5054 }
5055 case Intrinsic::amdgcn_permlane16:
5056 case Intrinsic::amdgcn_permlanex16: {
5057 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5058 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5059 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5060 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5061 OpdsMapping[4] = getSGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5062 OpdsMapping[5] = getSGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5063 break;
5064 }
5065 case Intrinsic::amdgcn_permlane_bcast:
5066 case Intrinsic::amdgcn_permlane_up:
5067 case Intrinsic::amdgcn_permlane_down:
5068 case Intrinsic::amdgcn_permlane_xor: {
5069 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5070 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5071 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5072 OpdsMapping[3] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5073 OpdsMapping[4] = getSGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5074 break;
5075 }
5076 case Intrinsic::amdgcn_permlane_idx_gen: {
5077 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5078 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5079 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5080 OpdsMapping[3] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5081 break;
5082 }
5083 case Intrinsic::amdgcn_permlane16_var:
5084 case Intrinsic::amdgcn_permlanex16_var: {
5085 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5086 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5087 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5088 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5089 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5090 break;
5091 }
5092 case Intrinsic::amdgcn_mfma_f32_4x4x1f32:
5093 case Intrinsic::amdgcn_mfma_f32_4x4x4f16:
5094 case Intrinsic::amdgcn_mfma_i32_4x4x4i8:
5095 case Intrinsic::amdgcn_mfma_f32_4x4x2bf16:
5096 case Intrinsic::amdgcn_mfma_f32_16x16x1f32:
5097 case Intrinsic::amdgcn_mfma_f32_16x16x4f32:
5098 case Intrinsic::amdgcn_mfma_f32_16x16x4f16:
5099 case Intrinsic::amdgcn_mfma_f32_16x16x16f16:
5100 case Intrinsic::amdgcn_mfma_i32_16x16x4i8:
5101 case Intrinsic::amdgcn_mfma_i32_16x16x16i8:
5102 case Intrinsic::amdgcn_mfma_f32_16x16x2bf16:
5103 case Intrinsic::amdgcn_mfma_f32_16x16x8bf16:
5104 case Intrinsic::amdgcn_mfma_f32_32x32x1f32:
5105 case Intrinsic::amdgcn_mfma_f32_32x32x2f32:
5106 case Intrinsic::amdgcn_mfma_f32_32x32x4f16:
5107 case Intrinsic::amdgcn_mfma_f32_32x32x8f16:
5108 case Intrinsic::amdgcn_mfma_i32_32x32x4i8:
5109 case Intrinsic::amdgcn_mfma_i32_32x32x8i8:
5110 case Intrinsic::amdgcn_mfma_f32_32x32x2bf16:
5111 case Intrinsic::amdgcn_mfma_f32_32x32x4bf16:
5112 case Intrinsic::amdgcn_mfma_f32_32x32x4bf16_1k:
5113 case Intrinsic::amdgcn_mfma_f32_16x16x4bf16_1k:
5114 case Intrinsic::amdgcn_mfma_f32_4x4x4bf16_1k:
5115 case Intrinsic::amdgcn_mfma_f32_32x32x8bf16_1k:
5116 case Intrinsic::amdgcn_mfma_f32_16x16x16bf16_1k:
5117 case Intrinsic::amdgcn_mfma_f64_16x16x4f64:
5118 case Intrinsic::amdgcn_mfma_f64_4x4x4f64:
5119 case Intrinsic::amdgcn_mfma_i32_16x16x32_i8:
5120 case Intrinsic::amdgcn_mfma_i32_32x32x16_i8:
5121 case Intrinsic::amdgcn_mfma_f32_16x16x8_xf32:
5122 case Intrinsic::amdgcn_mfma_f32_32x32x4_xf32:
5123 case Intrinsic::amdgcn_mfma_f32_16x16x32_bf8_bf8:
5124 case Intrinsic::amdgcn_mfma_f32_16x16x32_bf8_fp8:
5125 case Intrinsic::amdgcn_mfma_f32_16x16x32_fp8_bf8:
5126 case Intrinsic::amdgcn_mfma_f32_16x16x32_fp8_fp8:
5127 case Intrinsic::amdgcn_mfma_f32_32x32x16_bf8_bf8:
5128 case Intrinsic::amdgcn_mfma_f32_32x32x16_bf8_fp8:
5129 case Intrinsic::amdgcn_mfma_f32_32x32x16_fp8_bf8:
5130 case Intrinsic::amdgcn_mfma_f32_32x32x16_fp8_fp8:
5131 case Intrinsic::amdgcn_mfma_f32_16x16x32_f16:
5132 case Intrinsic::amdgcn_mfma_f32_32x32x16_f16:
5133 case Intrinsic::amdgcn_mfma_i32_16x16x64_i8:
5134 case Intrinsic::amdgcn_mfma_i32_32x32x32_i8:
5135 case Intrinsic::amdgcn_mfma_f32_16x16x32_bf16: {
5136 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5137 unsigned MinNumRegsRequired = DstSize / 32;
5138
5139 // Default for MAI intrinsics.
5140 // srcC can also be an immediate which can be folded later.
5141 // FIXME: Should we eventually add an alternative mapping with AGPR src
5142 // for srcA/srcB?
5143 //
5144 // vdst, srcA, srcB, srcC
5146
5147 bool UseAGPRForm = !Subtarget.hasGFX90AInsts() ||
5148 Info->selectAGPRFormMFMA(MinNumRegsRequired);
5149
5150 OpdsMapping[0] =
5151 UseAGPRForm ? getAGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI)
5152 : getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5153 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5154 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5155 OpdsMapping[4] =
5156 UseAGPRForm ? getAGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI)
5157 : getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5158 break;
5159 }
5160 case Intrinsic::amdgcn_mfma_scale_f32_16x16x128_f8f6f4:
5161 case Intrinsic::amdgcn_mfma_scale_f32_32x32x64_f8f6f4: {
5162 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5163 unsigned MinNumRegsRequired = DstSize / 32;
5164
5166 bool UseAGPRForm = Info->selectAGPRFormMFMA(MinNumRegsRequired);
5167
5168 OpdsMapping[0] =
5169 UseAGPRForm ? getAGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI)
5170 : getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5171
5172 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5173 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5174 OpdsMapping[4] =
5175 UseAGPRForm ? getAGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI)
5176 : getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5177
5178 OpdsMapping[8] = getVGPROpMapping(MI.getOperand(8).getReg(), MRI, *TRI);
5179 OpdsMapping[10] = getVGPROpMapping(MI.getOperand(10).getReg(), MRI, *TRI);
5180 break;
5181 }
5182 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
5183 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
5184 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
5185 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
5186 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
5187 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
5188 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
5189 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
5190 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
5191 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
5192 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
5193 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
5194 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
5195 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
5196 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
5197 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
5198 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
5199 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
5200 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
5201 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
5202 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
5203 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
5204 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
5205 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
5206 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
5207 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
5208 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
5209 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8: {
5210 Register DstReg = MI.getOperand(0).getReg();
5211 unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
5212 unsigned MinNumRegsRequired = DstSize / 32;
5214 bool UseAGPRForm = Info->selectAGPRFormMFMA(MinNumRegsRequired);
5215
5216 // vdst, srcA, srcB, srcC, idx
5217 OpdsMapping[0] = UseAGPRForm ? getAGPROpMapping(DstReg, MRI, *TRI)
5218 : getVGPROpMapping(DstReg, MRI, *TRI);
5219
5220 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5221 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5222 OpdsMapping[4] =
5223 UseAGPRForm ? getAGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI)
5224 : getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5225 OpdsMapping[5] = getVGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
5226 break;
5227 }
5228 case Intrinsic::amdgcn_interp_p1:
5229 case Intrinsic::amdgcn_interp_p2:
5230 case Intrinsic::amdgcn_interp_mov:
5231 case Intrinsic::amdgcn_interp_p1_f16:
5232 case Intrinsic::amdgcn_interp_p2_f16:
5233 case Intrinsic::amdgcn_lds_param_load: {
5234 const int M0Idx = MI.getNumOperands() - 1;
5235 Register M0Reg = MI.getOperand(M0Idx).getReg();
5236 unsigned M0Bank = getRegBankID(M0Reg, MRI, AMDGPU::SGPRRegBankID);
5237 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5238
5239 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5240 for (int I = 2; I != M0Idx && MI.getOperand(I).isReg(); ++I)
5241 OpdsMapping[I] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5242
5243 // Must be SGPR, but we must take whatever the original bank is and fix it
5244 // later.
5245 OpdsMapping[M0Idx] = AMDGPU::getValueMapping(M0Bank, 32);
5246 break;
5247 }
5248 case Intrinsic::amdgcn_interp_inreg_p10:
5249 case Intrinsic::amdgcn_interp_inreg_p2:
5250 case Intrinsic::amdgcn_interp_inreg_p10_f16:
5251 case Intrinsic::amdgcn_interp_inreg_p2_f16:
5252 case Intrinsic::amdgcn_interp_p10_rtz_f16:
5253 case Intrinsic::amdgcn_interp_p2_rtz_f16: {
5254 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5255 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5256 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5257 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5258 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5259 break;
5260 }
5261 case Intrinsic::amdgcn_permlane16_swap:
5262 case Intrinsic::amdgcn_permlane32_swap: {
5263 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5264 OpdsMapping[0] = OpdsMapping[1] = OpdsMapping[3] = OpdsMapping[4] =
5265 AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5266 break;
5267 }
5268 case Intrinsic::amdgcn_ballot: {
5269 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5270 unsigned SrcSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
5271 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, DstSize);
5272 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, SrcSize);
5273 break;
5274 }
5275 case Intrinsic::amdgcn_inverse_ballot: {
5276 // This must be an SGPR, but accept a VGPR.
5277 Register MaskReg = MI.getOperand(2).getReg();
5278 unsigned MaskSize = MRI.getType(MaskReg).getSizeInBits();
5279 unsigned MaskBank = getRegBankID(MaskReg, MRI, AMDGPU::SGPRRegBankID);
5280 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
5281 OpdsMapping[2] = AMDGPU::getValueMapping(MaskBank, MaskSize);
5282 break;
5283 }
5284 case Intrinsic::amdgcn_bitop3: {
5285 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5286 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5287 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5288 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5289 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5290 break;
5291 }
5292 case Intrinsic::amdgcn_s_quadmask:
5293 case Intrinsic::amdgcn_s_wqm: {
5294 Register MaskReg = MI.getOperand(2).getReg();
5295 unsigned MaskSize = MRI.getType(MaskReg).getSizeInBits();
5296 unsigned MaskBank = getRegBankID(MaskReg, MRI, AMDGPU::SGPRRegBankID);
5297 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, MaskSize);
5298 OpdsMapping[2] = AMDGPU::getValueMapping(MaskBank, MaskSize);
5299 break;
5300 }
5301 case Intrinsic::amdgcn_wave_reduce_add:
5302 case Intrinsic::amdgcn_wave_reduce_fadd:
5303 case Intrinsic::amdgcn_wave_reduce_sub:
5304 case Intrinsic::amdgcn_wave_reduce_fsub:
5305 case Intrinsic::amdgcn_wave_reduce_min:
5306 case Intrinsic::amdgcn_wave_reduce_umin:
5307 case Intrinsic::amdgcn_wave_reduce_fmin:
5308 case Intrinsic::amdgcn_wave_reduce_max:
5309 case Intrinsic::amdgcn_wave_reduce_umax:
5310 case Intrinsic::amdgcn_wave_reduce_fmax:
5311 case Intrinsic::amdgcn_wave_reduce_and:
5312 case Intrinsic::amdgcn_wave_reduce_or:
5313 case Intrinsic::amdgcn_wave_reduce_xor: {
5314 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5315 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, DstSize);
5316 unsigned OpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
5317 auto regBankID =
5318 isSALUMapping(MI) ? AMDGPU::SGPRRegBankID : AMDGPU::VGPRRegBankID;
5319 OpdsMapping[2] = AMDGPU::getValueMapping(regBankID, OpSize);
5320 break;
5321 }
5322 case Intrinsic::amdgcn_s_bitreplicate: {
5323 Register MaskReg = MI.getOperand(2).getReg();
5324 unsigned MaskBank = getRegBankID(MaskReg, MRI, AMDGPU::SGPRRegBankID);
5325 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 64);
5326 OpdsMapping[2] = AMDGPU::getValueMapping(MaskBank, 32);
5327 break;
5328 }
5329 case Intrinsic::amdgcn_wave_shuffle: {
5330 unsigned OpSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5331 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, OpSize);
5332 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, OpSize);
5333 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, OpSize);
5334 break;
5335 }
5336 }
5337 break;
5338 }
5339 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
5340 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
5341 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
5342 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
5343 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
5344 auto IntrID = AMDGPU::getIntrinsicID(MI);
5345 const AMDGPU::RsrcIntrinsic *RSrcIntrin = AMDGPU::lookupRsrcIntrinsic(IntrID);
5346 assert(RSrcIntrin && "missing RsrcIntrinsic for image intrinsic");
5347 // Non-images can have complications from operands that allow both SGPR
5348 // and VGPR. For now it's too complicated to figure out the final opcode
5349 // to derive the register bank from the MCInstrDesc.
5350 assert(RSrcIntrin->IsImage);
5351 return getImageMapping(MRI, MI, RSrcIntrin->RsrcArg);
5352 }
5353 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
5354 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
5355 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY: {
5356 bool IsDualOrBVH8 =
5357 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY ||
5358 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY;
5359 unsigned NumMods = IsDualOrBVH8 ? 0 : 1; // Has A16 modifier
5360 unsigned LastRegOpIdx = MI.getNumExplicitOperands() - 1 - NumMods;
5361 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5362 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5363 if (IsDualOrBVH8) {
5364 OpdsMapping[1] = AMDGPU::getValueMapping(
5365 AMDGPU::VGPRRegBankID,
5366 MRI.getType(MI.getOperand(1).getReg()).getSizeInBits());
5367 OpdsMapping[2] = AMDGPU::getValueMapping(
5368 AMDGPU::VGPRRegBankID,
5369 MRI.getType(MI.getOperand(2).getReg()).getSizeInBits());
5370 }
5371 OpdsMapping[LastRegOpIdx] =
5372 getSGPROpMapping(MI.getOperand(LastRegOpIdx).getReg(), MRI, *TRI);
5373 if (LastRegOpIdx == 3) {
5374 // Sequential form: all operands combined into VGPR256/VGPR512
5375 unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
5376 if (Size > 256)
5377 Size = 512;
5378 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5379 } else {
5380 // NSA form
5381 unsigned FirstSrcOpIdx = IsDualOrBVH8 ? 4 : 2;
5382 for (unsigned I = FirstSrcOpIdx; I < LastRegOpIdx; ++I) {
5383 unsigned Size = MRI.getType(MI.getOperand(I).getReg()).getSizeInBits();
5384 OpdsMapping[I] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5385 }
5386 }
5387 break;
5388 }
5389 case AMDGPU::G_INTRINSIC_W_SIDE_EFFECTS:
5390 case AMDGPU::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS: {
5391 auto IntrID = cast<GIntrinsic>(MI).getIntrinsicID();
5392 switch (IntrID) {
5393 case Intrinsic::amdgcn_s_getreg:
5394 case Intrinsic::amdgcn_s_memtime:
5395 case Intrinsic::amdgcn_s_memrealtime:
5396 case Intrinsic::amdgcn_s_get_waveid_in_workgroup:
5397 case Intrinsic::amdgcn_s_sendmsg_rtn: {
5398 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5399 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
5400 break;
5401 }
5402 case Intrinsic::amdgcn_global_atomic_fmin_num:
5403 case Intrinsic::amdgcn_global_atomic_fmax_num:
5404 case Intrinsic::amdgcn_flat_atomic_fmin_num:
5405 case Intrinsic::amdgcn_flat_atomic_fmax_num:
5406 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
5407 case Intrinsic::amdgcn_global_load_tr_b64:
5408 case Intrinsic::amdgcn_global_load_tr_b128:
5409 case Intrinsic::amdgcn_global_load_tr4_b64:
5410 case Intrinsic::amdgcn_global_load_tr6_b96:
5411 case Intrinsic::amdgcn_ds_load_tr8_b64:
5412 case Intrinsic::amdgcn_ds_load_tr16_b128:
5413 case Intrinsic::amdgcn_ds_load_tr4_b64:
5414 case Intrinsic::amdgcn_ds_load_tr6_b96:
5415 case Intrinsic::amdgcn_ds_read_tr4_b64:
5416 case Intrinsic::amdgcn_ds_read_tr6_b96:
5417 case Intrinsic::amdgcn_ds_read_tr8_b64:
5418 case Intrinsic::amdgcn_ds_read_tr16_b64:
5419 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
5420 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
5422 case Intrinsic::amdgcn_ds_ordered_add:
5423 case Intrinsic::amdgcn_ds_ordered_swap: {
5424 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5425 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5426 unsigned M0Bank = getRegBankID(MI.getOperand(2).getReg(), MRI,
5427 AMDGPU::SGPRRegBankID);
5428 OpdsMapping[2] = AMDGPU::getValueMapping(M0Bank, 32);
5429 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5430 break;
5431 }
5432 case Intrinsic::amdgcn_ds_append:
5433 case Intrinsic::amdgcn_ds_consume: {
5434 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5435 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5436 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5437 break;
5438 }
5439 case Intrinsic::amdgcn_exp_compr:
5440 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5441 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5442 break;
5443 case Intrinsic::amdgcn_exp:
5444 // FIXME: Could we support packed types here?
5445 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5446 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5447 OpdsMapping[5] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5448 OpdsMapping[6] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5449 break;
5450 case Intrinsic::amdgcn_exp_row:
5451 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5452 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5453 OpdsMapping[5] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5454 OpdsMapping[6] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5455 OpdsMapping[8] = getSGPROpMapping(MI.getOperand(8).getReg(), MRI, *TRI);
5456 break;
5457 case Intrinsic::amdgcn_s_alloc_vgpr:
5458 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 1);
5459 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32);
5460 break;
5461 case Intrinsic::amdgcn_s_sendmsg:
5462 case Intrinsic::amdgcn_s_sendmsghalt: {
5463 // This must be an SGPR, but accept a VGPR.
5464 unsigned Bank = getRegBankID(MI.getOperand(2).getReg(), MRI,
5465 AMDGPU::SGPRRegBankID);
5466 OpdsMapping[2] = AMDGPU::getValueMapping(Bank, 32);
5467 break;
5468 }
5469 case Intrinsic::amdgcn_s_setreg: {
5470 // This must be an SGPR, but accept a VGPR.
5471 unsigned Bank = getRegBankID(MI.getOperand(2).getReg(), MRI,
5472 AMDGPU::SGPRRegBankID);
5473 OpdsMapping[2] = AMDGPU::getValueMapping(Bank, 32);
5474 break;
5475 }
5476 case Intrinsic::amdgcn_s_ttracedata: {
5477 // This must be an SGPR, but accept a VGPR.
5478 unsigned Bank =
5479 getRegBankID(MI.getOperand(1).getReg(), MRI, AMDGPU::SGPRRegBankID);
5480 OpdsMapping[1] = AMDGPU::getValueMapping(Bank, 32);
5481 break;
5482 }
5483 case Intrinsic::amdgcn_end_cf: {
5484 unsigned Size = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
5485 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
5486 break;
5487 }
5488 case Intrinsic::amdgcn_else: {
5489 unsigned WaveSize = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
5490 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
5491 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, WaveSize);
5492 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, WaveSize);
5493 break;
5494 }
5495 case Intrinsic::amdgcn_init_whole_wave:
5496 case Intrinsic::amdgcn_live_mask: {
5497 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
5498 break;
5499 }
5500 case Intrinsic::amdgcn_wqm_demote:
5501 case Intrinsic::amdgcn_kill: {
5502 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
5503 break;
5504 }
5505 case Intrinsic::amdgcn_ptr_s_buffer_load: {
5506 OpdsMapping[0] = getSGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5507 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5508 OpdsMapping[3] = getSGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5509 break;
5510 }
5511 case Intrinsic::amdgcn_raw_buffer_load:
5512 case Intrinsic::amdgcn_raw_ptr_buffer_load:
5513 case Intrinsic::amdgcn_raw_atomic_buffer_load:
5514 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
5515 case Intrinsic::amdgcn_raw_tbuffer_load:
5516 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
5517 // FIXME: Should make intrinsic ID the last operand of the instruction,
5518 // then this would be the same as store
5519 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5520 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5521 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5522 OpdsMapping[4] = getSGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5523 break;
5524 }
5525 case Intrinsic::amdgcn_raw_buffer_load_lds:
5526 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
5527 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
5528 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds: {
5529 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5530 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5531 OpdsMapping[4] = getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5532 OpdsMapping[5] = getSGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
5533 break;
5534 }
5535 case Intrinsic::amdgcn_raw_buffer_store:
5536 case Intrinsic::amdgcn_raw_ptr_buffer_store:
5537 case Intrinsic::amdgcn_raw_buffer_store_format:
5538 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
5539 case Intrinsic::amdgcn_raw_tbuffer_store:
5540 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
5541 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5542 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5543 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5544 OpdsMapping[4] = getSGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5545 break;
5546 }
5547 case Intrinsic::amdgcn_struct_buffer_load:
5548 case Intrinsic::amdgcn_struct_ptr_buffer_load:
5549 case Intrinsic::amdgcn_struct_tbuffer_load:
5550 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
5551 case Intrinsic::amdgcn_struct_atomic_buffer_load:
5552 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
5553 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5554 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5555 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5556 OpdsMapping[4] = getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5557 OpdsMapping[5] = getSGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
5558 break;
5559 }
5560 case Intrinsic::amdgcn_struct_buffer_load_lds:
5561 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
5562 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
5563 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
5564 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5565 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5566 OpdsMapping[4] = getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5567 OpdsMapping[5] = getVGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
5568 OpdsMapping[6] = getSGPROpMapping(MI.getOperand(6).getReg(), MRI, *TRI);
5569 break;
5570 }
5571 case Intrinsic::amdgcn_struct_buffer_store:
5572 case Intrinsic::amdgcn_struct_ptr_buffer_store:
5573 case Intrinsic::amdgcn_struct_tbuffer_store:
5574 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
5575 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5576 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5577 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5578 OpdsMapping[4] = getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5579 OpdsMapping[5] = getSGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
5580 break;
5581 }
5582 case Intrinsic::amdgcn_init_exec_from_input: {
5583 unsigned Size = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
5584 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
5585 break;
5586 }
5587 case Intrinsic::amdgcn_ds_gws_init:
5588 case Intrinsic::amdgcn_ds_gws_barrier:
5589 case Intrinsic::amdgcn_ds_gws_sema_br: {
5590 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5591
5592 // This must be an SGPR, but accept a VGPR.
5593 unsigned Bank = getRegBankID(MI.getOperand(2).getReg(), MRI,
5594 AMDGPU::SGPRRegBankID);
5595 OpdsMapping[2] = AMDGPU::getValueMapping(Bank, 32);
5596 break;
5597 }
5598 case Intrinsic::amdgcn_ds_gws_sema_v:
5599 case Intrinsic::amdgcn_ds_gws_sema_p:
5600 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
5601 // This must be an SGPR, but accept a VGPR.
5602 unsigned Bank = getRegBankID(MI.getOperand(1).getReg(), MRI,
5603 AMDGPU::SGPRRegBankID);
5604 OpdsMapping[1] = AMDGPU::getValueMapping(Bank, 32);
5605 break;
5606 }
5607 case Intrinsic::amdgcn_cluster_load_b32:
5608 case Intrinsic::amdgcn_cluster_load_b64:
5609 case Intrinsic::amdgcn_cluster_load_b128: {
5610 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5611 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5612 unsigned M0Bank =
5613 getRegBankID(MI.getOperand(4).getReg(), MRI, AMDGPU::SGPRRegBankID);
5614 OpdsMapping[4] = AMDGPU::getValueMapping(M0Bank, 32);
5615 break;
5616 }
5617 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
5618 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
5619 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
5620 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
5621 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5622 // LDS address goes into $vdst (VGPR).
5623 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5624 unsigned M0Bank =
5625 getRegBankID(MI.getOperand(5).getReg(), MRI, AMDGPU::SGPRRegBankID);
5626 OpdsMapping[5] = AMDGPU::getValueMapping(M0Bank, 32);
5627 break;
5628 }
5629 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
5630 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
5631 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
5632 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
5633 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
5634 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
5635 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
5636 case Intrinsic::amdgcn_global_load_async_to_lds_b128: {
5637 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5638 // LDS address goes into $vdst/$vdata (VGPR).
5639 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5640 break;
5641 }
5642 case Intrinsic::amdgcn_load_to_lds:
5643 case Intrinsic::amdgcn_load_async_to_lds:
5644 case Intrinsic::amdgcn_global_load_lds:
5645 case Intrinsic::amdgcn_global_load_async_lds: {
5646 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5647 // LDS address goes into M0 (SGPR).
5648 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5649 break;
5650 }
5651 case Intrinsic::amdgcn_lds_direct_load: {
5652 const int M0Idx = MI.getNumOperands() - 1;
5653 Register M0Reg = MI.getOperand(M0Idx).getReg();
5654 unsigned M0Bank = getRegBankID(M0Reg, MRI, AMDGPU::SGPRRegBankID);
5655 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5656
5657 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5658 for (int I = 2; I != M0Idx && MI.getOperand(I).isReg(); ++I)
5659 OpdsMapping[I] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5660
5661 // Must be SGPR, but we must take whatever the original bank is and fix it
5662 // later.
5663 OpdsMapping[M0Idx] = AMDGPU::getValueMapping(M0Bank, 32);
5664 break;
5665 }
5666 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
5667 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn:
5668 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5669 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5670 break;
5671 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
5672 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
5673 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
5674 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
5675 OpdsMapping[0] =
5676 getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI); // %vdst
5677 OpdsMapping[1] =
5678 getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI); // %addr
5679 OpdsMapping[3] =
5680 getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI); // %addr
5681 OpdsMapping[4] =
5682 getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI); // %data0
5683 OpdsMapping[5] =
5684 getVGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI); // %data1
5685 break;
5686 }
5687 case Intrinsic::amdgcn_s_sleep_var:
5688 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5689 break;
5690 case Intrinsic::amdgcn_s_barrier_join:
5691 case Intrinsic::amdgcn_s_wakeup_barrier:
5692 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5693 break;
5694 case Intrinsic::amdgcn_s_barrier_init:
5695 case Intrinsic::amdgcn_s_barrier_signal_var:
5696 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5697 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5698 break;
5699 case Intrinsic::amdgcn_s_barrier_signal_isfirst: {
5700 const unsigned ResultSize = 1;
5701 OpdsMapping[0] =
5702 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, ResultSize);
5703 break;
5704 }
5705 case Intrinsic::amdgcn_s_get_barrier_state:
5706 case Intrinsic::amdgcn_s_get_named_barrier_state: {
5707 OpdsMapping[0] = getSGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5708 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5709 break;
5710 }
5711 case Intrinsic::amdgcn_pops_exiting_wave_id:
5712 return getDefaultMappingSOP(MI);
5713 case Intrinsic::amdgcn_tensor_load_to_lds:
5714 case Intrinsic::amdgcn_tensor_store_from_lds: {
5715 // Lie and claim everything is legal, even all operands need to be
5716 // SGPRs. applyMapping will have to deal with it with readfirstlane.
5717 for (unsigned I = 1; I < MI.getNumOperands(); ++I) {
5718 if (MI.getOperand(I).isReg()) {
5719 Register Reg = MI.getOperand(I).getReg();
5720 auto OpBank = getRegBankID(Reg, MRI);
5721 unsigned Size = getSizeInBits(Reg, MRI, *TRI);
5722 OpdsMapping[I] = AMDGPU::getValueMapping(OpBank, Size);
5723 }
5724 }
5725 break;
5726 }
5727 case Intrinsic::amdgcn_s_prefetch_data:
5728 case Intrinsic::amdgcn_s_prefetch_inst: {
5729 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5730 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5731 break;
5732 }
5733 case Intrinsic::amdgcn_flat_prefetch:
5734 case Intrinsic::amdgcn_global_prefetch:
5735 return getDefaultMappingVOP(MI);
5736 default:
5738 }
5739 break;
5740 }
5741 case AMDGPU::G_SELECT: {
5742 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5743 unsigned Op2Bank = getRegBankID(MI.getOperand(2).getReg(), MRI,
5744 AMDGPU::SGPRRegBankID);
5745 unsigned Op3Bank = getRegBankID(MI.getOperand(3).getReg(), MRI,
5746 AMDGPU::SGPRRegBankID);
5747 bool SGPRSrcs = Op2Bank == AMDGPU::SGPRRegBankID &&
5748 Op3Bank == AMDGPU::SGPRRegBankID;
5749
5750 unsigned CondBankDefault = SGPRSrcs ?
5751 AMDGPU::SGPRRegBankID : AMDGPU::VCCRegBankID;
5752 unsigned CondBank = getRegBankID(MI.getOperand(1).getReg(), MRI,
5753 CondBankDefault);
5754 if (CondBank == AMDGPU::SGPRRegBankID)
5755 CondBank = SGPRSrcs ? AMDGPU::SGPRRegBankID : AMDGPU::VCCRegBankID;
5756 else if (CondBank == AMDGPU::VGPRRegBankID)
5757 CondBank = AMDGPU::VCCRegBankID;
5758
5759 unsigned Bank = SGPRSrcs && CondBank == AMDGPU::SGPRRegBankID ?
5760 AMDGPU::SGPRRegBankID : AMDGPU::VGPRRegBankID;
5761
5762 assert(CondBank == AMDGPU::VCCRegBankID || CondBank == AMDGPU::SGPRRegBankID);
5763
5764 // TODO: Should report 32-bit for scalar condition type.
5765 if (Size == 64) {
5766 OpdsMapping[0] = AMDGPU::getValueMappingSGPR64Only(Bank, Size);
5767 OpdsMapping[1] = AMDGPU::getValueMapping(CondBank, 1);
5768 OpdsMapping[2] = AMDGPU::getValueMappingSGPR64Only(Bank, Size);
5769 OpdsMapping[3] = AMDGPU::getValueMappingSGPR64Only(Bank, Size);
5770 } else {
5771 OpdsMapping[0] = AMDGPU::getValueMapping(Bank, Size);
5772 OpdsMapping[1] = AMDGPU::getValueMapping(CondBank, 1);
5773 OpdsMapping[2] = AMDGPU::getValueMapping(Bank, Size);
5774 OpdsMapping[3] = AMDGPU::getValueMapping(Bank, Size);
5775 }
5776
5777 break;
5778 }
5779
5780 case AMDGPU::G_SI_CALL: {
5781 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 64);
5782 // Lie and claim everything is legal, even though some need to be
5783 // SGPRs. applyMapping will have to deal with it as a waterfall loop.
5784 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5785
5786 // Allow anything for implicit arguments
5787 for (unsigned I = 4; I < MI.getNumOperands(); ++I) {
5788 if (MI.getOperand(I).isReg()) {
5789 Register Reg = MI.getOperand(I).getReg();
5790 auto OpBank = getRegBankID(Reg, MRI);
5791 unsigned Size = getSizeInBits(Reg, MRI, *TRI);
5792 OpdsMapping[I] = AMDGPU::getValueMapping(OpBank, Size);
5793 }
5794 }
5795 break;
5796 }
5797 case AMDGPU::G_LOAD:
5798 case AMDGPU::G_ZEXTLOAD:
5799 case AMDGPU::G_SEXTLOAD:
5800 return getInstrMappingForLoad(MI);
5801
5802 case AMDGPU::G_ATOMICRMW_XCHG:
5803 case AMDGPU::G_ATOMICRMW_ADD:
5804 case AMDGPU::G_ATOMICRMW_SUB:
5805 case AMDGPU::G_ATOMICRMW_AND:
5806 case AMDGPU::G_ATOMICRMW_OR:
5807 case AMDGPU::G_ATOMICRMW_XOR:
5808 case AMDGPU::G_ATOMICRMW_MAX:
5809 case AMDGPU::G_ATOMICRMW_MIN:
5810 case AMDGPU::G_ATOMICRMW_UMAX:
5811 case AMDGPU::G_ATOMICRMW_UMIN:
5812 case AMDGPU::G_ATOMICRMW_FADD:
5813 case AMDGPU::G_ATOMICRMW_FMIN:
5814 case AMDGPU::G_ATOMICRMW_FMAX:
5815 case AMDGPU::G_ATOMICRMW_UINC_WRAP:
5816 case AMDGPU::G_ATOMICRMW_UDEC_WRAP:
5817 case AMDGPU::G_ATOMICRMW_USUB_COND:
5818 case AMDGPU::G_ATOMICRMW_USUB_SAT:
5819 case AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG: {
5820 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5821 OpdsMapping[1] = getValueMappingForPtr(MRI, MI.getOperand(1).getReg());
5822 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5823 break;
5824 }
5825 case AMDGPU::G_ATOMIC_CMPXCHG: {
5826 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5827 OpdsMapping[1] = getValueMappingForPtr(MRI, MI.getOperand(1).getReg());
5828 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5829 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5830 break;
5831 }
5832 case AMDGPU::G_BRCOND: {
5833 unsigned Bank = getRegBankID(MI.getOperand(0).getReg(), MRI,
5834 AMDGPU::SGPRRegBankID);
5835 assert(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 1);
5836 if (Bank != AMDGPU::SGPRRegBankID)
5837 Bank = AMDGPU::VCCRegBankID;
5838
5839 OpdsMapping[0] = AMDGPU::getValueMapping(Bank, 1);
5840 break;
5841 }
5842 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
5843 return getDefaultMappingVOP(MI);
5844 case AMDGPU::G_PREFETCH:
5845 OpdsMapping[0] = getSGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5846 break;
5847 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP:
5848 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN:
5849 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
5850 break;
5851 case AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR:
5852 case AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR: {
5853 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5854 unsigned PtrSize = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
5855 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5856 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, PtrSize);
5857 break;
5858 }
5859 }
5860
5861 return getInstructionMapping(/*ID*/1, /*Cost*/1,
5862 getOperandsMapping(OpdsMapping),
5863 MI.getNumOperands());
5864}
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t Imm
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
constexpr LLT S16
constexpr LLT S1
constexpr LLT S32
constexpr LLT S64
AMDGPU Register Bank Select
static bool substituteSimpleCopyRegs(const AMDGPURegisterBankInfo::OperandsMapper &OpdMapper, unsigned OpIdx)
static unsigned regBankBoolUnion(unsigned RB0, unsigned RB1)
static std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg)
static Register constrainRegToBank(MachineRegisterInfo &MRI, MachineIRBuilder &B, Register &Reg, const RegisterBank &Bank)
static std::pair< Register, Register > unpackV2S16ToS32(MachineIRBuilder &B, Register Src, unsigned ExtOpcode)
static void extendLow32IntoHigh32(MachineIRBuilder &B, Register Hi32Reg, Register Lo32Reg, unsigned ExtOpc, const RegisterBank &RegBank, bool IsBooleanSrc=false)
Implement extending a 32-bit value to a 64-bit value.
static unsigned getExtendOp(unsigned Opc)
static bool isVectorRegisterBank(const RegisterBank &Bank)
static unsigned regBankUnion(unsigned RB0, unsigned RB1)
static std::pair< LLT, LLT > splitUnequalType(LLT Ty, unsigned FirstSize)
Split Ty into 2 pieces.
static void setRegsToType(MachineRegisterInfo &MRI, ArrayRef< Register > Regs, LLT NewTy)
Replace the current type each register in Regs has with NewTy.
static void reinsertVectorIndexAdd(MachineIRBuilder &B, MachineInstr &IdxUseInstr, unsigned OpIdx, unsigned ConstOffset)
Utility function for pushing dynamic vector indexes with a constant offset into waterfall loops.
static LLT widen96To128(LLT Ty)
static LLT getHalfSizedType(LLT Ty)
static unsigned getSBufferLoadCorrespondingBufferLoadOpcode(unsigned Opc)
This file declares the targeting of the RegisterBankInfo class for AMDGPU.
Rewrite undef for PHI
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
IRTranslator LLVM IR MI
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:57
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
static bool isReg(const MCInst &MI, unsigned OpNo)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static constexpr MCPhysReg SPReg
SI Fold Operands
Interface definition for SIRegisterInfo.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
bool applyMappingDynStackAlloc(MachineIRBuilder &B, const OperandsMapper &OpdMapper, MachineInstr &MI) const
std::pair< Register, unsigned > splitBufferOffsets(MachineIRBuilder &B, Register Offset) const
bool collectWaterfallOperands(SmallSet< Register, 4 > &SGPROperandRegs, MachineInstr &MI, MachineRegisterInfo &MRI, ArrayRef< unsigned > OpIndices) const
const InstructionMapping & getImageMapping(const MachineRegisterInfo &MRI, const MachineInstr &MI, int RsrcIdx) const
InstructionMappings addMappingFromTable(const MachineInstr &MI, const MachineRegisterInfo &MRI, const std::array< unsigned, NumOps > RegSrcOpIdx, ArrayRef< OpRegBankEntry< NumOps > > Table) const
unsigned copyCost(const RegisterBank &A, const RegisterBank &B, TypeSize Size) const override
Get the cost of a copy from B to A, or put differently, get the cost of A = COPY B.
RegisterBankInfo::InstructionMappings getInstrAlternativeMappingsIntrinsicWSideEffects(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
bool buildVCopy(MachineIRBuilder &B, Register DstReg, Register SrcReg) const
bool executeInWaterfallLoop(MachineIRBuilder &B, iterator_range< MachineBasicBlock::iterator > Range, SmallSet< Register, 4 > &SGPROperandRegs) const
Legalize instruction MI where operands in OpIndices must be SGPRs.
const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC, LLT) const override
Get a register bank that covers RC.
AMDGPURegisterBankInfo(const GCNSubtarget &STI)
bool applyMappingMAD_64_32(MachineIRBuilder &B, const OperandsMapper &OpdMapper) const
unsigned getRegBankID(Register Reg, const MachineRegisterInfo &MRI, unsigned Default=AMDGPU::VGPRRegBankID) const
Register handleD16VData(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Reg) const
Handle register layout difference for f16 images for some subtargets.
const RegisterBankInfo::InstructionMapping & getInstrMappingForLoad(const MachineInstr &MI) const
void applyMappingImpl(MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const override
See RegisterBankInfo::applyMapping.
bool applyMappingBFE(MachineIRBuilder &B, const OperandsMapper &OpdMapper, bool Signed) const
bool applyMappingImage(MachineIRBuilder &B, MachineInstr &MI, const OperandsMapper &OpdMapper, int RSrcIdx) const
const ValueMapping * getVGPROpMapping(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
bool isScalarLoadLegal(const MachineInstr &MI) const
unsigned setBufferOffsets(MachineIRBuilder &B, Register CombinedOffset, Register &VOffsetReg, Register &SOffsetReg, int64_t &InstOffsetVal, Align Alignment) const
const ValueMapping * getSGPROpMapping(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
bool applyMappingLoad(MachineIRBuilder &B, const OperandsMapper &OpdMapper, MachineInstr &MI) const
void split64BitValueForMapping(MachineIRBuilder &B, SmallVector< Register, 2 > &Regs, LLT HalfTy, Register Reg) const
Split 64-bit value Reg into two 32-bit halves and populate them into Regs.
const ValueMapping * getValueMappingForPtr(const MachineRegisterInfo &MRI, Register Ptr) const
Return the mapping for a pointer argument.
unsigned getMappingType(const MachineRegisterInfo &MRI, const MachineInstr &MI) const
RegisterBankInfo::InstructionMappings getInstrAlternativeMappingsIntrinsic(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
bool isDivergentRegBank(const RegisterBank *RB) const override
Returns true if the register bank is considered divergent.
void constrainOpWithReadfirstlane(MachineIRBuilder &B, MachineInstr &MI, unsigned OpIdx) const
InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const override
Get the alternative mappings for MI.
const InstructionMapping & getDefaultMappingSOP(const MachineInstr &MI) const
const InstructionMapping & getDefaultMappingAllVGPR(const MachineInstr &MI) const
const InstructionMapping & getInstrMapping(const MachineInstr &MI) const override
This function must return a legal mapping, because AMDGPURegisterBankInfo::getInstrAlternativeMapping...
unsigned getBreakDownCost(const ValueMapping &ValMapping, const RegisterBank *CurBank=nullptr) const override
Get the cost of using ValMapping to decompose a register.
const ValueMapping * getAGPROpMapping(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
const InstructionMapping & getDefaultMappingVOP(const MachineInstr &MI) const
bool isSALUMapping(const MachineInstr &MI) const
Register buildReadFirstLane(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Src) const
bool applyMappingSBufferLoad(MachineIRBuilder &B, const OperandsMapper &OpdMapper) const
void applyMappingSMULU64(MachineIRBuilder &B, const OperandsMapper &OpdMapper) const
static const LaneMaskConstants & get(const GCNSubtarget &ST)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ ICMP_SLT
signed less than
Definition InstrTypes.h:769
@ ICMP_NE
not equal
Definition InstrTypes.h:762
A debug info location.
Definition DebugLoc.h:126
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:766
iterator end()
Definition DenseMap.h:686
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:827
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:306
Abstract class that contains various methods for clients to notify about changes.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
LLT divide(int Factor) const
Return a type that is Factor times smaller.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
LLVM_ABI void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, unsigned ExtOpcode)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize an instruction by reducing the width of the underlying scalar type.
LLVM_ABI LegalizeResult reduceLoadStoreWidth(GLoadStore &MI, unsigned TypeIdx, LLT NarrowTy)
@ Legalized
Instruction has been legalized and the MachineFunction changed.
LLVM_ABI LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize a vector instruction by splitting into multiple components, each acting on the same scalar t...
LLVM_ABI LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy)
Legalize an instruction by performing the operation on a wider scalar type (for example a 16-bit addi...
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
TypeSize getValue() const
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
Helper class to build MachineInstr.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
MachineInstrSpan provides an interface to get an iteration range containing the instruction it was in...
MachineBasicBlock::iterator begin()
MachineBasicBlock::iterator end()
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
unsigned getAddrSpace() const
bool isAtomic() const
Returns true if this operation has an atomic ordering requirement of unordered or higher,...
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
Flags getFlags() const
Return the raw flags of the source value,.
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const RegClassOrRegBank & getRegClassOrRegBank(Register Reg) const
Return the register bank or register class of Reg.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
const RegisterBank * getRegBankOrNull(Register Reg) const
Return the register bank of Reg, or null if Reg has not been assigned a register bank or has been ass...
LLVM_ABI void setRegBank(Register Reg, const RegisterBank &RegBank)
Set the register bank to RegBank for Reg.
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
Helper class that represents how the value of an instruction may be mapped and what is the related co...
bool isValid() const
Check whether this object is valid.
Helper class used to get/create the virtual registers that will be used to replace the MachineOperand...
const InstructionMapping & getInstrMapping() const
The final mapping of the instruction.
MachineRegisterInfo & getMRI() const
The MachineRegisterInfo we used to realize the mapping.
LLVM_ABI iterator_range< SmallVectorImpl< Register >::const_iterator > getVRegs(unsigned OpIdx, bool ForDebug=false) const
Get all the virtual registers required to map the OpIdx-th operand of the instruction.
virtual InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const
Get the alternative mappings for MI.
static const TargetRegisterClass * constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
const InstructionMapping & getInstructionMapping(unsigned ID, unsigned Cost, const ValueMapping *OperandsMapping, unsigned NumOperands) const
Method to get a uniquely generated InstructionMapping.
static void applyDefaultMapping(const OperandsMapper &OpdMapper)
Helper method to apply something that is like the default mapping.
const ValueMapping & getValueMapping(unsigned StartIdx, unsigned Length, const RegisterBank &RegBank) const
The most common ValueMapping consists of a single PartialMapping.
const InstructionMapping & getInvalidInstructionMapping() const
Method to get a uniquely generated invalid InstructionMapping.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
const unsigned * Sizes
Hold the sizes of the register banks for all HwModes.
bool cannotCopy(const RegisterBank &Dst, const RegisterBank &Src, TypeSize Size) const
TypeSize getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
const ValueMapping * getOperandsMapping(Iterator Begin, Iterator End) const
Get the uniquely generated array of ValueMapping for the elements of between Begin and End.
SmallVector< const InstructionMapping *, 4 > InstructionMappings
Convenient type to represent the alternatives for mapping an instruction.
virtual unsigned copyCost(const RegisterBank &A, const RegisterBank &B, TypeSize Size) const
Get the cost of a copy from B to A, or put differently, get the cost of A = COPY B.
const InstructionMapping & getInstrMappingImpl(const MachineInstr &MI) const
Try to get the mapping of MI.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
SIModeRegisterDefaults getMode() const
bool selectAGPRFormMFMA(unsigned NumRegs) const
Return true if an MFMA that requires at least NumRegs should select to the AGPR form,...
static bool shouldExpandVectorDynExt(unsigned EltSize, unsigned NumElem, bool IsDivergentIdx, const GCNSubtarget *Subtarget)
Check if EXTRACT_VECTOR_ELT/INSERT_VECTOR_ELT (<n x e>, var-idx) should be expanded into a set of cmp...
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition SmallSet.h:176
bool empty() const
Definition SmallSet.h:169
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Register getReg() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:348
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
self_iterator getIterator()
Definition ilist_node.h:123
A range adaptor for a pair of iterators.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
bool isFlatGlobalAddrSpace(unsigned AS)
bool isUniformMMO(const MachineMemOperand *MMO)
bool isExtendedGlobalAddrSpace(unsigned AS)
Intrinsic::ID getIntrinsicID(const MachineInstr &I)
Return the intrinsic ID for opcodes with the G_AMDGPU_INTRIN_ prefix.
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const RsrcIntrinsic * lookupRsrcIntrinsic(unsigned Intr)
operand_type_match m_Reg()
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
ConstantMatch< APInt > m_ICst(APInt &Cst)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ADD, true > m_GAdd(const LHS &L, const RHS &R)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
SpecificConstantOrSplatMatch m_SpecificICstOrSplat(const APInt &RequestedValue)
Matches a RequestedValue constant or a constant splat of RequestedValue.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
Definition Utils.cpp:656
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI void constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition Utils.cpp:159
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
Definition Utils.cpp:317
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
Definition SIInstrInfo.h:45
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ Add
Sum of integers.
IntPtrTy
Definition InstrProf.h:82
DWARFExpression::Operation Op
void call_once(once_flag &flag, Function &&F, Args &&... ArgList)
Execute the function specified as a parameter once.
Definition Threading.h:86
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition Utils.cpp:436
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
Definition Alignment.h:105
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition Alignment.h:202
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
Definition Utils.cpp:504
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:267
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
This class contains a discriminated union of information about pointers in memory operands,...
unsigned StartIdx
Number of bits at which this partial mapping starts in the original value.
const RegisterBank * RegBank
Register bank where the partial value lives.
unsigned Length
Length of this mapping in bits.
Helper struct that represents how a value is mapped through different register banks.
unsigned NumBreakDowns
Number of partial mapping to break down this value.
const PartialMapping * BreakDown
How the value is broken down between the different register banks.
bool IEEE
Floating point opcodes that support exception flag gathering quiet and propagate signaling NaN inputs...
The llvm::once_flag structure.
Definition Threading.h:67