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, RegState::Kill);
936
937 MRI.setSimpleHint(NewExec, CondReg);
938
939 B.setInsertPt(*BodyBB, BodyBB->end());
940
941 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
942 B.buildInstr(LMC.XorTermOpc)
943 .addDef(LMC.ExecReg)
944 .addReg(LMC.ExecReg)
945 .addReg(NewExec);
946
947 // XXX - s_xor_b64 sets scc to 1 if the result is nonzero, so can we use
948 // s_cbranch_scc0?
949
950 // Loop back to V_READFIRSTLANE_B32 if there are still variants to cover.
951 B.buildInstr(AMDGPU::SI_WATERFALL_LOOP).addMBB(LoopBB);
952
953 // Save the EXEC mask before the loop.
954 BuildMI(MBB, MBB.end(), DL, TII->get(LMC.MovOpc), SaveExecReg)
955 .addReg(LMC.ExecReg);
956
957 // Restore the EXEC mask after the loop.
958 B.setMBB(*RestoreExecBB);
959 B.buildInstr(LMC.MovTermOpc).addDef(LMC.ExecReg).addReg(SaveExecReg);
960
961 // Set the insert point after the original instruction, so any new
962 // instructions will be in the remainder.
963 B.setInsertPt(*RemainderBB, RemainderBB->begin());
964
965 return true;
966}
967
968// Return any unique registers used by \p MI at \p OpIndices that need to be
969// handled in a waterfall loop. Returns these registers in \p
970// SGPROperandRegs. Returns true if there are any operands to handle and a
971// waterfall loop is necessary.
973 SmallSet<Register, 4> &SGPROperandRegs, MachineInstr &MI,
974 MachineRegisterInfo &MRI, ArrayRef<unsigned> OpIndices) const {
975 for (unsigned Op : OpIndices) {
976 assert(MI.getOperand(Op).isUse());
977 Register Reg = MI.getOperand(Op).getReg();
978 const RegisterBank *OpBank = getRegBank(Reg, MRI, *TRI);
979 if (OpBank->getID() != AMDGPU::SGPRRegBankID)
980 SGPROperandRegs.insert(Reg);
981 }
982
983 // No operands need to be replaced, so no need to loop.
984 return !SGPROperandRegs.empty();
985}
986
989 // Use a set to avoid extra readfirstlanes in the case where multiple operands
990 // are the same register.
991 SmallSet<Register, 4> SGPROperandRegs;
992
993 if (!collectWaterfallOperands(SGPROperandRegs, MI, *B.getMRI(), OpIndices))
994 return false;
995
996 MachineBasicBlock::iterator I = MI.getIterator();
997 return executeInWaterfallLoop(B, make_range(I, std::next(I)),
998 SGPROperandRegs);
999}
1000
1001// Legalize an operand that must be an SGPR by inserting a readfirstlane.
1003 MachineIRBuilder &B, MachineInstr &MI, unsigned OpIdx) const {
1004 Register Reg = MI.getOperand(OpIdx).getReg();
1005 MachineRegisterInfo &MRI = *B.getMRI();
1006 const RegisterBank *Bank = getRegBank(Reg, MRI, *TRI);
1007 if (Bank == &AMDGPU::SGPRRegBank)
1008 return;
1009
1010 Reg = buildReadFirstLane(B, MRI, Reg);
1011 MI.getOperand(OpIdx).setReg(Reg);
1012}
1013
1014/// Split \p Ty into 2 pieces. The first will have \p FirstSize bits, and the
1015/// rest will be in the remainder.
1016static std::pair<LLT, LLT> splitUnequalType(LLT Ty, unsigned FirstSize) {
1017 unsigned TotalSize = Ty.getSizeInBits();
1018 if (!Ty.isVector())
1019 return {LLT::scalar(FirstSize), LLT::scalar(TotalSize - FirstSize)};
1020
1021 LLT EltTy = Ty.getElementType();
1022 unsigned EltSize = EltTy.getSizeInBits();
1023 assert(FirstSize % EltSize == 0);
1024
1025 unsigned FirstPartNumElts = FirstSize / EltSize;
1026 unsigned RemainderElts = (TotalSize - FirstSize) / EltSize;
1027
1028 return {LLT::scalarOrVector(ElementCount::getFixed(FirstPartNumElts), EltTy),
1029 LLT::scalarOrVector(ElementCount::getFixed(RemainderElts), EltTy)};
1030}
1031
1033 if (!Ty.isVector())
1034 return LLT::scalar(128);
1035
1036 LLT EltTy = Ty.getElementType();
1037 assert(128 % EltTy.getSizeInBits() == 0);
1038 return LLT::fixed_vector(128 / EltTy.getSizeInBits(), EltTy);
1039}
1040
1044 MachineInstr &MI) const {
1045 MachineRegisterInfo &MRI = *B.getMRI();
1046 Register DstReg = MI.getOperand(0).getReg();
1047 const LLT LoadTy = MRI.getType(DstReg);
1048 unsigned LoadSize = LoadTy.getSizeInBits();
1049 MachineMemOperand *MMO = *MI.memoperands_begin();
1050 const unsigned MaxNonSmrdLoadSize = 128;
1051
1052 const RegisterBank *DstBank =
1053 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
1054 if (DstBank == &AMDGPU::SGPRRegBank) {
1055 // There are some special cases that we need to look at for 32 bit and 96
1056 // bit SGPR loads otherwise we have nothing to do.
1057 if (LoadSize != 32 && (LoadSize != 96 || Subtarget.hasScalarDwordx3Loads()))
1058 return false;
1059
1060 const unsigned MemSize = 8 * MMO->getSize().getValue();
1061 // Scalar loads of size 8 or 16 bit with proper alignment may be widened to
1062 // 32 bit. Check to see if we need to widen the memory access, 8 or 16 bit
1063 // scalar loads should have a load size of 32 but memory access size of less
1064 // than 32.
1065 if (LoadSize == 32 &&
1066 (MemSize == 32 || LoadTy.isVector() || !isScalarLoadLegal(MI)))
1067 return false;
1068
1069 if (LoadSize == 32 &&
1070 ((MemSize == 8 && MMO->getAlign() >= Align(1)) ||
1071 (MemSize == 16 && MMO->getAlign() >= Align(2))) &&
1073 Subtarget.getGeneration() >= AMDGPUSubtarget::GFX12)
1074 return false;
1075
1076 Register PtrReg = MI.getOperand(1).getReg();
1077
1078 ApplyRegBankMapping ApplyBank(B, *this, MRI, DstBank);
1079
1080 if (LoadSize == 32) {
1081 // This is an extending load from a sub-dword size. Widen the memory
1082 // access size to 4 bytes and clear the extra high bits appropriately
1083 const LLT S32 = LLT::scalar(32);
1084 if (MI.getOpcode() == AMDGPU::G_SEXTLOAD) {
1085 // Must extend the sign bit into higher bits for a G_SEXTLOAD
1086 auto WideLoad = B.buildLoadFromOffset(S32, PtrReg, *MMO, 0);
1087 B.buildSExtInReg(MI.getOperand(0), WideLoad, MemSize);
1088 } else if (MI.getOpcode() == AMDGPU::G_ZEXTLOAD) {
1089 // Must extend zero into higher bits with an AND for a G_ZEXTLOAD
1090 auto WideLoad = B.buildLoadFromOffset(S32, PtrReg, *MMO, 0);
1091 B.buildZExtInReg(MI.getOperand(0), WideLoad, MemSize);
1092 } else
1093 // We do not need to touch the higher bits for regular loads.
1094 B.buildLoadFromOffset(MI.getOperand(0), PtrReg, *MMO, 0);
1095 } else {
1096 // 96-bit loads are only available for vector loads. We need to split this
1097 // into a 64-bit part, and 32 (unless we can widen to a 128-bit load).
1098 if (MMO->getAlign() < Align(16)) {
1099 LegalizerHelper Helper(B.getMF(), ApplyBank, B);
1100 LLT Part64, Part32;
1101 std::tie(Part64, Part32) = splitUnequalType(LoadTy, 64);
1102 if (Helper.reduceLoadStoreWidth(cast<GAnyLoad>(MI), 0, Part64) !=
1104 return false;
1105 return true;
1106 }
1107 LLT WiderTy = widen96To128(LoadTy);
1108 auto WideLoad = B.buildLoadFromOffset(WiderTy, PtrReg, *MMO, 0);
1109 if (WiderTy.isScalar()) {
1110 B.buildTrunc(MI.getOperand(0), WideLoad);
1111 } else {
1112 B.buildDeleteTrailingVectorElements(MI.getOperand(0).getReg(),
1113 WideLoad);
1114 }
1115 }
1116
1117 MI.eraseFromParent();
1118 return true;
1119 }
1120
1121 // 128-bit loads are supported for all instruction types.
1122 if (LoadSize <= MaxNonSmrdLoadSize)
1123 return false;
1124
1125 SmallVector<Register, 1> SrcRegs(OpdMapper.getVRegs(1));
1126
1127 if (SrcRegs.empty())
1128 SrcRegs.push_back(MI.getOperand(1).getReg());
1129
1130 // RegBankSelect only emits scalar types, so we need to reset the pointer
1131 // operand to a pointer type.
1132 Register BasePtrReg = SrcRegs[0];
1133 LLT PtrTy = MRI.getType(MI.getOperand(1).getReg());
1134 MRI.setType(BasePtrReg, PtrTy);
1135
1136 // The following are the loads not splitted enough during legalization
1137 // because it was not clear they are smem-load or vmem-load
1140 assert(LoadSize % MaxNonSmrdLoadSize == 0);
1141 unsigned NumSplitParts = LoadTy.getSizeInBits() / MaxNonSmrdLoadSize;
1142 const LLT LoadSplitTy = LoadTy.divide(NumSplitParts);
1143 ApplyRegBankMapping O(B, *this, MRI, &AMDGPU::VGPRRegBank);
1144 LegalizerHelper Helper(B.getMF(), O, B);
1145 if (LoadTy.isVector()) {
1146 if (Helper.fewerElementsVector(MI, 0, LoadSplitTy) !=
1148 return false;
1149 } else {
1150 if (Helper.narrowScalar(MI, 0, LoadSplitTy) != LegalizerHelper::Legalized)
1151 return false;
1152 }
1153 }
1154
1155 MRI.setRegBank(DstReg, AMDGPU::VGPRRegBank);
1156 return true;
1157}
1158
1162 MachineInstr &MI) const {
1163 MachineRegisterInfo &MRI = *B.getMRI();
1164 const MachineFunction &MF = B.getMF();
1165 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
1166 const auto &TFI = *ST.getFrameLowering();
1167
1168 // Guard in case the stack growth direction ever changes with scratch
1169 // instructions.
1170 assert(TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp &&
1171 "Stack grows upwards for AMDGPU");
1172
1173 Register Dst = MI.getOperand(0).getReg();
1174 Register AllocSize = MI.getOperand(1).getReg();
1175 Align Alignment = assumeAligned(MI.getOperand(2).getImm());
1176
1177 // When using flat-scratch, the stack offset is unscaled.
1178 const bool HasFlatScratch = ST.hasFlatScratchEnabled();
1179 const unsigned WavefrontSizeLog2 = ST.getWavefrontSizeLog2();
1180
1181 const RegisterBank *SizeBank = getRegBank(AllocSize, MRI, *TRI);
1182
1183 if (SizeBank != &AMDGPU::SGPRRegBank) {
1184 auto WaveReduction =
1185 B.buildIntrinsic(Intrinsic::amdgcn_wave_reduce_umax, {LLT::scalar(32)})
1186 .addUse(AllocSize)
1187 .addImm(0);
1188 AllocSize = WaveReduction.getReg(0);
1189 }
1190
1191 LLT PtrTy = MRI.getType(Dst);
1193
1195 Register SPReg = Info->getStackPtrOffsetReg();
1196 ApplyRegBankMapping ApplyBank(B, *this, MRI, &AMDGPU::SGPRRegBank);
1197
1198 Register ScaledSize = AllocSize;
1199 if (!HasFlatScratch) {
1200 auto WaveSize = B.buildConstant(LLT::scalar(32), WavefrontSizeLog2);
1201 ScaledSize = B.buildShl(IntPtrTy, AllocSize, WaveSize).getReg(0);
1202 }
1203
1204 auto OldSP = B.buildCopy(PtrTy, SPReg);
1205 if (Alignment > TFI.getStackAlign()) {
1206 const uint64_t ScaledAlignment =
1207 HasFlatScratch ? Alignment.value()
1208 : (Alignment.value() << WavefrontSizeLog2);
1209 const uint64_t StackAlignMask = ScaledAlignment - 1;
1210 auto Tmp1 = B.buildPtrAdd(PtrTy, OldSP,
1211 B.buildConstant(LLT::scalar(32), StackAlignMask));
1212 B.buildMaskLowPtrBits(Dst, Tmp1,
1213 (HasFlatScratch
1214 ? Log2(Alignment)
1215 : Log2(Alignment) + WavefrontSizeLog2));
1216 } else {
1217 B.buildCopy(Dst, OldSP);
1218 }
1219 auto PtrAdd = B.buildPtrAdd(PtrTy, Dst, ScaledSize);
1220 B.buildCopy(SPReg, PtrAdd);
1221 MI.eraseFromParent();
1222 return true;
1223}
1224
1228 int RsrcIdx) const {
1229 const int NumDefs = MI.getNumExplicitDefs();
1230
1231 // The reported argument index is relative to the IR intrinsic call arguments,
1232 // so we need to shift by the number of defs and the intrinsic ID.
1233 RsrcIdx += NumDefs + 1;
1234
1235 // Insert copies to VGPR arguments.
1236 applyDefaultMapping(OpdMapper);
1237
1238 // Fixup any SGPR arguments.
1239 SmallVector<unsigned, 4> SGPRIndexes;
1240 for (int I = NumDefs, NumOps = MI.getNumOperands(); I != NumOps; ++I) {
1241 if (!MI.getOperand(I).isReg())
1242 continue;
1243
1244 // If this intrinsic has a sampler, it immediately follows rsrc.
1245 if (I == RsrcIdx || I == RsrcIdx + 1)
1246 SGPRIndexes.push_back(I);
1247 }
1248
1249 executeInWaterfallLoop(B, MI, SGPRIndexes);
1250 return true;
1251}
1252
1253// Analyze a combined offset from an llvm.amdgcn.s.buffer intrinsic and store
1254// the three offsets (voffset, soffset and instoffset)
1256 MachineIRBuilder &B, Register CombinedOffset, Register &VOffsetReg,
1257 Register &SOffsetReg, int64_t &InstOffsetVal, Align Alignment) const {
1258 const LLT S32 = LLT::scalar(32);
1259 MachineRegisterInfo *MRI = B.getMRI();
1260
1261 if (std::optional<int64_t> Imm =
1262 getIConstantVRegSExtVal(CombinedOffset, *MRI)) {
1263 uint32_t SOffset, ImmOffset;
1264 if (TII->splitMUBUFOffset(*Imm, SOffset, ImmOffset, Alignment)) {
1265 VOffsetReg = B.buildConstant(S32, 0).getReg(0);
1266 SOffsetReg = B.buildConstant(S32, SOffset).getReg(0);
1267 InstOffsetVal = ImmOffset;
1268
1269 B.getMRI()->setRegBank(VOffsetReg, AMDGPU::VGPRRegBank);
1270 B.getMRI()->setRegBank(SOffsetReg, AMDGPU::SGPRRegBank);
1271 return SOffset + ImmOffset;
1272 }
1273 }
1274
1275 const bool CheckNUW = Subtarget.hasGFX1250Insts();
1276 Register Base;
1277 unsigned Offset;
1278
1279 std::tie(Base, Offset) =
1280 AMDGPU::getBaseWithConstantOffset(*MRI, CombinedOffset,
1281 /*KnownBits=*/nullptr,
1282 /*CheckNUW=*/CheckNUW);
1283
1284 uint32_t SOffset, ImmOffset;
1285 if (static_cast<int32_t>(Offset) > 0 &&
1286 TII->splitMUBUFOffset(Offset, SOffset, ImmOffset, Alignment)) {
1287 if (getRegBank(Base, *MRI, *TRI) == &AMDGPU::VGPRRegBank) {
1288 VOffsetReg = Base;
1289 SOffsetReg = B.buildConstant(S32, SOffset).getReg(0);
1290 B.getMRI()->setRegBank(SOffsetReg, AMDGPU::SGPRRegBank);
1291 InstOffsetVal = ImmOffset;
1292 return 0; // XXX - Why is this 0?
1293 }
1294
1295 // If we have SGPR base, we can use it for soffset.
1296 if (SOffset == 0) {
1297 VOffsetReg = B.buildConstant(S32, 0).getReg(0);
1298 B.getMRI()->setRegBank(VOffsetReg, AMDGPU::VGPRRegBank);
1299 SOffsetReg = Base;
1300 InstOffsetVal = ImmOffset;
1301 return 0; // XXX - Why is this 0?
1302 }
1303 }
1304
1305 // Handle the variable sgpr + vgpr case.
1306 MachineInstr *Add = getOpcodeDef(AMDGPU::G_ADD, CombinedOffset, *MRI);
1307 if (Add && static_cast<int32_t>(Offset) >= 0 &&
1308 (!CheckNUW || Add->getFlag(MachineInstr::NoUWrap))) {
1309 Register Src0 = getSrcRegIgnoringCopies(Add->getOperand(1).getReg(), *MRI);
1310 Register Src1 = getSrcRegIgnoringCopies(Add->getOperand(2).getReg(), *MRI);
1311
1312 const RegisterBank *Src0Bank = getRegBank(Src0, *MRI, *TRI);
1313 const RegisterBank *Src1Bank = getRegBank(Src1, *MRI, *TRI);
1314
1315 if (Src0Bank == &AMDGPU::VGPRRegBank && Src1Bank == &AMDGPU::SGPRRegBank) {
1316 VOffsetReg = Src0;
1317 SOffsetReg = Src1;
1318 return 0;
1319 }
1320
1321 if (Src0Bank == &AMDGPU::SGPRRegBank && Src1Bank == &AMDGPU::VGPRRegBank) {
1322 VOffsetReg = Src1;
1323 SOffsetReg = Src0;
1324 return 0;
1325 }
1326 }
1327
1328 // Ensure we have a VGPR for the combined offset. This could be an issue if we
1329 // have an SGPR offset and a VGPR resource.
1330 if (getRegBank(CombinedOffset, *MRI, *TRI) == &AMDGPU::VGPRRegBank) {
1331 VOffsetReg = CombinedOffset;
1332 } else {
1333 VOffsetReg = B.buildCopy(S32, CombinedOffset).getReg(0);
1334 B.getMRI()->setRegBank(VOffsetReg, AMDGPU::VGPRRegBank);
1335 }
1336
1337 SOffsetReg = B.buildConstant(S32, 0).getReg(0);
1338 B.getMRI()->setRegBank(SOffsetReg, AMDGPU::SGPRRegBank);
1339 return 0;
1340}
1341
1343 switch (Opc) {
1344 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD:
1345 return AMDGPU::G_AMDGPU_BUFFER_LOAD;
1346 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
1347 return AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE;
1348 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE:
1349 return AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE;
1350 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
1351 return AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT;
1352 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT:
1353 return AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT;
1354 default:
1355 break;
1356 }
1357 llvm_unreachable("Unexpected s_buffer_load opcode");
1358}
1359
1361 MachineIRBuilder &B, const OperandsMapper &OpdMapper) const {
1362 MachineInstr &MI = OpdMapper.getMI();
1363 MachineRegisterInfo &MRI = OpdMapper.getMRI();
1364
1365 const LLT S32 = LLT::scalar(32);
1366 Register Dst = MI.getOperand(0).getReg();
1367 LLT Ty = MRI.getType(Dst);
1368
1369 const RegisterBank *RSrcBank =
1370 OpdMapper.getInstrMapping().getOperandMapping(1).BreakDown[0].RegBank;
1371 const RegisterBank *OffsetBank =
1372 OpdMapper.getInstrMapping().getOperandMapping(2).BreakDown[0].RegBank;
1373 if (RSrcBank == &AMDGPU::SGPRRegBank &&
1374 OffsetBank == &AMDGPU::SGPRRegBank)
1375 return true; // Legal mapping
1376
1377 // FIXME: 96-bit case was widened during legalize. We need to narrow it back
1378 // here but don't have an MMO.
1379
1380 unsigned LoadSize = Ty.getSizeInBits();
1381 int NumLoads = 1;
1382 if (LoadSize == 256 || LoadSize == 512) {
1383 NumLoads = LoadSize / 128;
1384 Ty = Ty.divide(NumLoads);
1385 }
1386
1387 // Use the alignment to ensure that the required offsets will fit into the
1388 // immediate offsets.
1389 const Align Alignment = NumLoads > 1 ? Align(16 * NumLoads) : Align(1);
1390
1391 MachineFunction &MF = B.getMF();
1392
1393 Register SOffset;
1394 Register VOffset;
1395 int64_t ImmOffset = 0;
1396
1397 unsigned MMOOffset = setBufferOffsets(B, MI.getOperand(2).getReg(), VOffset,
1398 SOffset, ImmOffset, Alignment);
1399
1400 // TODO: 96-bit loads were widened to 128-bit results. Shrink the result if we
1401 // can, but we need to track an MMO for that.
1402 const unsigned MemSize = (Ty.getSizeInBits() + 7) / 8;
1403 const Align MemAlign(4); // FIXME: ABI type alignment?
1408 MemSize, MemAlign);
1409 if (MMOOffset != 0)
1410 BaseMMO = MF.getMachineMemOperand(BaseMMO, MMOOffset, MemSize);
1411
1412 // If only the offset is divergent, emit a MUBUF buffer load instead. We can
1413 // assume that the buffer is unswizzled.
1414
1415 Register RSrc = MI.getOperand(1).getReg();
1416 Register VIndex = B.buildConstant(S32, 0).getReg(0);
1417 B.getMRI()->setRegBank(VIndex, AMDGPU::VGPRRegBank);
1418 unsigned CachePolicy = MI.getOperand(3).getImm();
1419
1420 SmallVector<Register, 4> LoadParts(NumLoads);
1421
1422 MachineBasicBlock::iterator MII = MI.getIterator();
1423 MachineInstrSpan Span(MII, &B.getMBB());
1424
1425 for (int i = 0; i < NumLoads; ++i) {
1426 if (NumLoads == 1) {
1427 LoadParts[i] = Dst;
1428 } else {
1429 LoadParts[i] = MRI.createGenericVirtualRegister(Ty);
1430 MRI.setRegBank(LoadParts[i], AMDGPU::VGPRRegBank);
1431 }
1432
1433 if (i != 0)
1434 BaseMMO = MF.getMachineMemOperand(BaseMMO, 16, MemSize);
1435
1436 B.buildInstr(getSBufferLoadCorrespondingBufferLoadOpcode(MI.getOpcode()))
1437 .addDef(LoadParts[i]) // vdata
1438 .addUse(RSrc) // rsrc
1439 .addUse(VIndex) // vindex
1440 .addUse(VOffset) // voffset
1441 .addUse(SOffset) // soffset
1442 .addImm(ImmOffset + 16 * i) // offset(imm)
1443 .addImm(CachePolicy) // cachepolicy, swizzled buffer(imm)
1444 .addImm(0) // idxen(imm)
1445 .addMemOperand(BaseMMO);
1446 }
1447
1448 // TODO: If only the resource is a VGPR, it may be better to execute the
1449 // scalar load in the waterfall loop if the resource is expected to frequently
1450 // be dynamically uniform.
1451 if (RSrcBank != &AMDGPU::SGPRRegBank) {
1452 // Remove the original instruction to avoid potentially confusing the
1453 // waterfall loop logic.
1454 B.setInstr(*Span.begin());
1455 MI.eraseFromParent();
1456
1457 SmallSet<Register, 4> OpsToWaterfall;
1458
1459 OpsToWaterfall.insert(RSrc);
1460 executeInWaterfallLoop(B, make_range(Span.begin(), Span.end()),
1461 OpsToWaterfall);
1462 }
1463
1464 if (NumLoads != 1) {
1465 if (Ty.isVector())
1466 B.buildConcatVectors(Dst, LoadParts);
1467 else
1468 B.buildMergeLikeInstr(Dst, LoadParts);
1469 }
1470
1471 // We removed the instruction earlier with a waterfall loop.
1472 if (RSrcBank == &AMDGPU::SGPRRegBank)
1473 MI.eraseFromParent();
1474
1475 return true;
1476}
1477
1479 const OperandsMapper &OpdMapper,
1480 bool Signed) const {
1481 MachineInstr &MI = OpdMapper.getMI();
1482 MachineRegisterInfo &MRI = OpdMapper.getMRI();
1483
1484 // Insert basic copies
1485 applyDefaultMapping(OpdMapper);
1486
1487 Register DstReg = MI.getOperand(0).getReg();
1488 LLT Ty = MRI.getType(DstReg);
1489
1490 const LLT S32 = LLT::scalar(32);
1491
1492 unsigned FirstOpnd = isa<GIntrinsic>(MI) ? 2 : 1;
1493 Register SrcReg = MI.getOperand(FirstOpnd).getReg();
1494 Register OffsetReg = MI.getOperand(FirstOpnd + 1).getReg();
1495 Register WidthReg = MI.getOperand(FirstOpnd + 2).getReg();
1496
1497 const RegisterBank *DstBank =
1498 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
1499 if (DstBank == &AMDGPU::VGPRRegBank) {
1500 if (Ty == S32)
1501 return true;
1502
1503 // There is no 64-bit vgpr bitfield extract instructions so the operation
1504 // is expanded to a sequence of instructions that implement the operation.
1505 ApplyRegBankMapping ApplyBank(B, *this, MRI, &AMDGPU::VGPRRegBank);
1506
1507 const LLT S64 = LLT::scalar(64);
1508 // Shift the source operand so that extracted bits start at bit 0.
1509 auto ShiftOffset = Signed ? B.buildAShr(S64, SrcReg, OffsetReg)
1510 : B.buildLShr(S64, SrcReg, OffsetReg);
1511 auto UnmergeSOffset = B.buildUnmerge({S32, S32}, ShiftOffset);
1512
1513 // A 64-bit bitfield extract uses the 32-bit bitfield extract instructions
1514 // if the width is a constant.
1515 if (auto ConstWidth = getIConstantVRegValWithLookThrough(WidthReg, MRI)) {
1516 // Use the 32-bit bitfield extract instruction if the width is a constant.
1517 // Depending on the width size, use either the low or high 32-bits.
1518 auto Zero = B.buildConstant(S32, 0);
1519 auto WidthImm = ConstWidth->Value.getZExtValue();
1520 if (WidthImm <= 32) {
1521 // Use bitfield extract on the lower 32-bit source, and then sign-extend
1522 // or clear the upper 32-bits.
1523 auto Extract =
1524 Signed ? B.buildSbfx(S32, UnmergeSOffset.getReg(0), Zero, WidthReg)
1525 : B.buildUbfx(S32, UnmergeSOffset.getReg(0), Zero, WidthReg);
1526 auto Extend =
1527 Signed ? B.buildAShr(S32, Extract, B.buildConstant(S32, 31)) : Zero;
1528 B.buildMergeLikeInstr(DstReg, {Extract, Extend});
1529 } else {
1530 // Use bitfield extract on upper 32-bit source, and combine with lower
1531 // 32-bit source.
1532 auto UpperWidth = B.buildConstant(S32, WidthImm - 32);
1533 auto Extract =
1534 Signed
1535 ? B.buildSbfx(S32, UnmergeSOffset.getReg(1), Zero, UpperWidth)
1536 : B.buildUbfx(S32, UnmergeSOffset.getReg(1), Zero, UpperWidth);
1537 B.buildMergeLikeInstr(DstReg, {UnmergeSOffset.getReg(0), Extract});
1538 }
1539 MI.eraseFromParent();
1540 return true;
1541 }
1542
1543 // Expand to Src >> Offset << (64 - Width) >> (64 - Width) using 64-bit
1544 // operations.
1545 auto ExtShift = B.buildSub(S32, B.buildConstant(S32, 64), WidthReg);
1546 auto SignBit = B.buildShl(S64, ShiftOffset, ExtShift);
1547 if (Signed)
1548 B.buildAShr(S64, SignBit, ExtShift);
1549 else
1550 B.buildLShr(S64, SignBit, ExtShift);
1551 MI.eraseFromParent();
1552 return true;
1553 }
1554
1555 // The scalar form packs the offset and width in a single operand.
1556
1557 ApplyRegBankMapping ApplyBank(B, *this, MRI, &AMDGPU::SGPRRegBank);
1558
1559 // Ensure the high bits are clear to insert the offset.
1560 auto OffsetMask = B.buildConstant(S32, maskTrailingOnes<unsigned>(6));
1561 auto ClampOffset = B.buildAnd(S32, OffsetReg, OffsetMask);
1562
1563 // Zeros out the low bits, so don't bother clamping the input value.
1564 auto ShiftWidth = B.buildShl(S32, WidthReg, B.buildConstant(S32, 16));
1565
1566 // Transformation function, pack the offset and width of a BFE into
1567 // the format expected by the S_BFE_I32 / S_BFE_U32. In the second
1568 // source, bits [5:0] contain the offset and bits [22:16] the width.
1569 auto MergedInputs = B.buildOr(S32, ClampOffset, ShiftWidth);
1570
1571 // TODO: It might be worth using a pseudo here to avoid scc clobber and
1572 // register class constraints.
1573 unsigned Opc = Ty == S32 ? (Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32) :
1574 (Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64);
1575
1576 auto MIB = B.buildInstr(Opc, {DstReg}, {SrcReg, MergedInputs});
1577 constrainSelectedInstRegOperands(*MIB, *TII, *TRI, *this);
1578
1579 MI.eraseFromParent();
1580 return true;
1581}
1582
1584 MachineIRBuilder &B, const OperandsMapper &OpdMapper) const {
1585 MachineInstr &MI = OpdMapper.getMI();
1586 MachineRegisterInfo &MRI = OpdMapper.getMRI();
1587
1588 // Insert basic copies.
1589 applyDefaultMapping(OpdMapper);
1590
1591 Register Dst0 = MI.getOperand(0).getReg();
1592 Register Dst1 = MI.getOperand(1).getReg();
1593 Register Src0 = MI.getOperand(2).getReg();
1594 Register Src1 = MI.getOperand(3).getReg();
1595 Register Src2 = MI.getOperand(4).getReg();
1596
1597 if (MRI.getRegBankOrNull(Src0) == &AMDGPU::VGPRRegBank)
1598 return true;
1599
1600 bool IsUnsigned = MI.getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32;
1601 LLT S1 = LLT::scalar(1);
1602 LLT S32 = LLT::scalar(32);
1603
1604 bool DstOnValu = MRI.getRegBankOrNull(Src2) == &AMDGPU::VGPRRegBank;
1605 bool Accumulate = true;
1606
1607 if (!DstOnValu) {
1608 if (mi_match(Src2, MRI, m_ZeroInt()))
1609 Accumulate = false;
1610 }
1611
1612 // Keep the multiplication on the SALU.
1613 Register DstHi;
1614 Register DstLo = B.buildMul(S32, Src0, Src1).getReg(0);
1615 bool MulHiInVgpr = false;
1616
1617 MRI.setRegBank(DstLo, AMDGPU::SGPRRegBank);
1618
1619 if (Subtarget.hasSMulHi()) {
1620 DstHi = IsUnsigned ? B.buildUMulH(S32, Src0, Src1).getReg(0)
1621 : B.buildSMulH(S32, Src0, Src1).getReg(0);
1622 MRI.setRegBank(DstHi, AMDGPU::SGPRRegBank);
1623 } else {
1624 Register VSrc0 = B.buildCopy(S32, Src0).getReg(0);
1625 Register VSrc1 = B.buildCopy(S32, Src1).getReg(0);
1626
1627 MRI.setRegBank(VSrc0, AMDGPU::VGPRRegBank);
1628 MRI.setRegBank(VSrc1, AMDGPU::VGPRRegBank);
1629
1630 DstHi = IsUnsigned ? B.buildUMulH(S32, VSrc0, VSrc1).getReg(0)
1631 : B.buildSMulH(S32, VSrc0, VSrc1).getReg(0);
1632 MRI.setRegBank(DstHi, AMDGPU::VGPRRegBank);
1633
1634 if (!DstOnValu) {
1635 DstHi = buildReadFirstLane(B, MRI, DstHi);
1636 } else {
1637 MulHiInVgpr = true;
1638 }
1639 }
1640
1641 // Accumulate and produce the "carry-out" bit.
1642 //
1643 // The "carry-out" is defined as bit 64 of the result when computed as a
1644 // big integer. For unsigned multiply-add, this matches the usual definition
1645 // of carry-out. For signed multiply-add, bit 64 is the sign bit of the
1646 // result, which is determined as:
1647 // sign(Src0 * Src1) + sign(Src2) + carry-out from unsigned 64-bit add
1648 LLT CarryType = DstOnValu ? S1 : S32;
1649 const RegisterBank &CarryBank =
1650 DstOnValu ? AMDGPU::VCCRegBank : AMDGPU::SGPRRegBank;
1651 const RegisterBank &DstBank =
1652 DstOnValu ? AMDGPU::VGPRRegBank : AMDGPU::SGPRRegBank;
1653 Register Carry;
1654 Register Zero;
1655
1656 if (!IsUnsigned) {
1657 Zero = B.buildConstant(S32, 0).getReg(0);
1658 MRI.setRegBank(Zero,
1659 MulHiInVgpr ? AMDGPU::VGPRRegBank : AMDGPU::SGPRRegBank);
1660
1661 Carry = B.buildICmp(CmpInst::ICMP_SLT, MulHiInVgpr ? S1 : S32, DstHi, Zero)
1662 .getReg(0);
1663 MRI.setRegBank(Carry, MulHiInVgpr ? AMDGPU::VCCRegBank
1664 : AMDGPU::SGPRRegBank);
1665
1666 if (DstOnValu && !MulHiInVgpr) {
1667 Carry = B.buildTrunc(S1, Carry).getReg(0);
1668 MRI.setRegBank(Carry, AMDGPU::VCCRegBank);
1669 }
1670 }
1671
1672 if (Accumulate) {
1673 if (DstOnValu) {
1674 DstLo = B.buildCopy(S32, DstLo).getReg(0);
1675 DstHi = B.buildCopy(S32, DstHi).getReg(0);
1676 MRI.setRegBank(DstLo, AMDGPU::VGPRRegBank);
1677 MRI.setRegBank(DstHi, AMDGPU::VGPRRegBank);
1678 }
1679
1680 auto Unmerge = B.buildUnmerge(S32, Src2);
1681 Register Src2Lo = Unmerge.getReg(0);
1682 Register Src2Hi = Unmerge.getReg(1);
1683 MRI.setRegBank(Src2Lo, DstBank);
1684 MRI.setRegBank(Src2Hi, DstBank);
1685
1686 if (!IsUnsigned) {
1687 auto Src2Sign = B.buildICmp(CmpInst::ICMP_SLT, CarryType, Src2Hi, Zero);
1688 MRI.setRegBank(Src2Sign.getReg(0), CarryBank);
1689
1690 Carry = B.buildXor(CarryType, Carry, Src2Sign).getReg(0);
1691 MRI.setRegBank(Carry, CarryBank);
1692 }
1693
1694 auto AddLo = B.buildUAddo(S32, CarryType, DstLo, Src2Lo);
1695 DstLo = AddLo.getReg(0);
1696 Register CarryLo = AddLo.getReg(1);
1697 MRI.setRegBank(DstLo, DstBank);
1698 MRI.setRegBank(CarryLo, CarryBank);
1699
1700 auto AddHi = B.buildUAdde(S32, CarryType, DstHi, Src2Hi, CarryLo);
1701 DstHi = AddHi.getReg(0);
1702 MRI.setRegBank(DstHi, DstBank);
1703
1704 Register CarryHi = AddHi.getReg(1);
1705 MRI.setRegBank(CarryHi, CarryBank);
1706
1707 if (IsUnsigned) {
1708 Carry = CarryHi;
1709 } else {
1710 Carry = B.buildXor(CarryType, Carry, CarryHi).getReg(0);
1711 MRI.setRegBank(Carry, CarryBank);
1712 }
1713 } else {
1714 if (IsUnsigned) {
1715 Carry = B.buildConstant(CarryType, 0).getReg(0);
1716 MRI.setRegBank(Carry, CarryBank);
1717 }
1718 }
1719
1720 B.buildMergeLikeInstr(Dst0, {DstLo, DstHi});
1721
1722 if (DstOnValu) {
1723 B.buildCopy(Dst1, Carry);
1724 } else {
1725 B.buildTrunc(Dst1, Carry);
1726 }
1727
1728 MI.eraseFromParent();
1729 return true;
1730}
1731
1732// Return a suitable opcode for extending the operands of Opc when widening.
1733static unsigned getExtendOp(unsigned Opc) {
1734 switch (Opc) {
1735 case TargetOpcode::G_ASHR:
1736 case TargetOpcode::G_SMIN:
1737 case TargetOpcode::G_SMAX:
1738 return TargetOpcode::G_SEXT;
1739 case TargetOpcode::G_LSHR:
1740 case TargetOpcode::G_UMIN:
1741 case TargetOpcode::G_UMAX:
1742 return TargetOpcode::G_ZEXT;
1743 default:
1744 return TargetOpcode::G_ANYEXT;
1745 }
1746}
1747
1748// Emit a legalized extension from <2 x s16> to 2 32-bit components, avoiding
1749// any illegal vector extend or unmerge operations.
1750static std::pair<Register, Register>
1751unpackV2S16ToS32(MachineIRBuilder &B, Register Src, unsigned ExtOpcode) {
1752 const LLT S32 = LLT::scalar(32);
1753 auto Bitcast = B.buildBitcast(S32, Src);
1754
1755 if (ExtOpcode == TargetOpcode::G_SEXT) {
1756 auto ExtLo = B.buildSExtInReg(S32, Bitcast, 16);
1757 auto ShiftHi = B.buildAShr(S32, Bitcast, B.buildConstant(S32, 16));
1758 return std::pair(ExtLo.getReg(0), ShiftHi.getReg(0));
1759 }
1760
1761 auto ShiftHi = B.buildLShr(S32, Bitcast, B.buildConstant(S32, 16));
1762 if (ExtOpcode == TargetOpcode::G_ZEXT) {
1763 auto ExtLo = B.buildAnd(S32, Bitcast, B.buildConstant(S32, 0xffff));
1764 return std::pair(ExtLo.getReg(0), ShiftHi.getReg(0));
1765 }
1766
1767 assert(ExtOpcode == TargetOpcode::G_ANYEXT);
1768 return std::pair(Bitcast.getReg(0), ShiftHi.getReg(0));
1769}
1770
1771// For cases where only a single copy is inserted for matching register banks.
1772// Replace the register in the instruction operand
1774 const AMDGPURegisterBankInfo::OperandsMapper &OpdMapper, unsigned OpIdx) {
1775 SmallVector<unsigned, 1> SrcReg(OpdMapper.getVRegs(OpIdx));
1776 if (!SrcReg.empty()) {
1777 assert(SrcReg.size() == 1);
1778 OpdMapper.getMI().getOperand(OpIdx).setReg(SrcReg[0]);
1779 return true;
1780 }
1781
1782 return false;
1783}
1784
1785/// Handle register layout difference for f16 images for some subtargets.
1788 Register Reg) const {
1789 if (!Subtarget.hasUnpackedD16VMem())
1790 return Reg;
1791
1792 const LLT S16 = LLT::scalar(16);
1793 LLT StoreVT = MRI.getType(Reg);
1794 if (!StoreVT.isVector() || StoreVT.getElementType() != S16)
1795 return Reg;
1796
1797 auto Unmerge = B.buildUnmerge(S16, Reg);
1798
1799
1800 SmallVector<Register, 4> WideRegs;
1801 for (int I = 0, E = Unmerge->getNumOperands() - 1; I != E; ++I)
1802 WideRegs.push_back(Unmerge.getReg(I));
1803
1804 const LLT S32 = LLT::scalar(32);
1805 int NumElts = StoreVT.getNumElements();
1806
1807 return B.buildMergeLikeInstr(LLT::fixed_vector(NumElts, S32), WideRegs)
1808 .getReg(0);
1809}
1810
1811static std::pair<Register, unsigned>
1813 int64_t Const;
1814 if (mi_match(Reg, MRI, m_ICst(Const)))
1815 return std::pair(Register(), Const);
1816
1817 Register Base;
1818 if (mi_match(Reg, MRI, m_GAdd(m_Reg(Base), m_ICst(Const))))
1819 return std::pair(Base, Const);
1820
1821 // TODO: Handle G_OR used for add case
1822 return std::pair(Reg, 0);
1823}
1824
1825std::pair<Register, unsigned>
1827 Register OrigOffset) const {
1828 const unsigned MaxImm = SIInstrInfo::getMaxMUBUFImmOffset(Subtarget);
1829 Register BaseReg;
1830 unsigned ImmOffset;
1831 const LLT S32 = LLT::scalar(32);
1832
1833 // TODO: Use AMDGPU::getBaseWithConstantOffset() instead.
1834 std::tie(BaseReg, ImmOffset) = getBaseWithConstantOffset(*B.getMRI(),
1835 OrigOffset);
1836
1837 unsigned C1 = 0;
1838 if (ImmOffset != 0) {
1839 // If the immediate value is too big for the immoffset field, put only bits
1840 // that would normally fit in the immoffset field. The remaining value that
1841 // is copied/added for the voffset field is a large power of 2, and it
1842 // stands more chance of being CSEd with the copy/add for another similar
1843 // load/store.
1844 // However, do not do that rounding down if that is a negative
1845 // number, as it appears to be illegal to have a negative offset in the
1846 // vgpr, even if adding the immediate offset makes it positive.
1847 unsigned Overflow = ImmOffset & ~MaxImm;
1848 ImmOffset -= Overflow;
1849 if (static_cast<int32_t>(Overflow) < 0) {
1850 Overflow += ImmOffset;
1851 ImmOffset = 0;
1852 }
1853
1854 C1 = ImmOffset;
1855 if (Overflow != 0) {
1856 if (!BaseReg)
1857 BaseReg = B.buildConstant(S32, Overflow).getReg(0);
1858 else {
1859 auto OverflowVal = B.buildConstant(S32, Overflow);
1860 BaseReg = B.buildAdd(S32, BaseReg, OverflowVal).getReg(0);
1861 }
1862 }
1863 }
1864
1865 if (!BaseReg)
1866 BaseReg = B.buildConstant(S32, 0).getReg(0);
1867
1868 return {BaseReg, C1};
1869}
1870
1872 Register SrcReg) const {
1873 MachineRegisterInfo &MRI = *B.getMRI();
1874 LLT SrcTy = MRI.getType(SrcReg);
1875 if (SrcTy.getSizeInBits() == 32) {
1876 // Use a v_mov_b32 here to make the exec dependency explicit.
1877 B.buildInstr(AMDGPU::V_MOV_B32_e32)
1878 .addDef(DstReg)
1879 .addUse(SrcReg);
1880 return constrainGenericRegister(DstReg, AMDGPU::VGPR_32RegClass, MRI) &&
1881 constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, MRI);
1882 }
1883
1884 Register TmpReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
1885 Register TmpReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
1886
1887 B.buildInstr(AMDGPU::V_MOV_B32_e32)
1888 .addDef(TmpReg0)
1889 .addUse(SrcReg, {}, AMDGPU::sub0);
1890 B.buildInstr(AMDGPU::V_MOV_B32_e32)
1891 .addDef(TmpReg1)
1892 .addUse(SrcReg, {}, AMDGPU::sub1);
1893 B.buildInstr(AMDGPU::REG_SEQUENCE)
1894 .addDef(DstReg)
1895 .addUse(TmpReg0)
1896 .addImm(AMDGPU::sub0)
1897 .addUse(TmpReg1)
1898 .addImm(AMDGPU::sub1);
1899
1900 return constrainGenericRegister(SrcReg, AMDGPU::SReg_64RegClass, MRI) &&
1901 constrainGenericRegister(DstReg, AMDGPU::VReg_64RegClass, MRI);
1902}
1903
1904/// Utility function for pushing dynamic vector indexes with a constant offset
1905/// into waterfall loops.
1907 MachineInstr &IdxUseInstr,
1908 unsigned OpIdx,
1909 unsigned ConstOffset) {
1910 MachineRegisterInfo &MRI = *B.getMRI();
1911 const LLT S32 = LLT::scalar(32);
1912 Register WaterfallIdx = IdxUseInstr.getOperand(OpIdx).getReg();
1913 B.setInsertPt(*IdxUseInstr.getParent(), IdxUseInstr.getIterator());
1914
1915 auto MaterializedOffset = B.buildConstant(S32, ConstOffset);
1916
1917 auto Add = B.buildAdd(S32, WaterfallIdx, MaterializedOffset);
1918 MRI.setRegBank(MaterializedOffset.getReg(0), AMDGPU::SGPRRegBank);
1919 MRI.setRegBank(Add.getReg(0), AMDGPU::SGPRRegBank);
1920 IdxUseInstr.getOperand(OpIdx).setReg(Add.getReg(0));
1921}
1922
1923/// Implement extending a 32-bit value to a 64-bit value. \p Lo32Reg is the
1924/// original 32-bit source value (to be inserted in the low part of the combined
1925/// 64-bit result), and \p Hi32Reg is the high half of the combined 64-bit
1926/// value.
1928 Register Hi32Reg, Register Lo32Reg,
1929 unsigned ExtOpc,
1930 const RegisterBank &RegBank,
1931 bool IsBooleanSrc = false) {
1932 if (ExtOpc == AMDGPU::G_ZEXT) {
1933 B.buildConstant(Hi32Reg, 0);
1934 } else if (ExtOpc == AMDGPU::G_SEXT) {
1935 if (IsBooleanSrc) {
1936 // If we know the original source was an s1, the high half is the same as
1937 // the low.
1938 B.buildCopy(Hi32Reg, Lo32Reg);
1939 } else {
1940 // Replicate sign bit from 32-bit extended part.
1941 auto ShiftAmt = B.buildConstant(LLT::scalar(32), 31);
1942 B.getMRI()->setRegBank(ShiftAmt.getReg(0), RegBank);
1943 B.buildAShr(Hi32Reg, Lo32Reg, ShiftAmt);
1944 }
1945 } else {
1946 assert(ExtOpc == AMDGPU::G_ANYEXT && "not an integer extension");
1947 B.buildUndef(Hi32Reg);
1948 }
1949}
1950
1951bool AMDGPURegisterBankInfo::foldExtractEltToCmpSelect(
1953 const OperandsMapper &OpdMapper) const {
1954 MachineRegisterInfo &MRI = *B.getMRI();
1955
1956 Register VecReg = MI.getOperand(1).getReg();
1957 Register Idx = MI.getOperand(2).getReg();
1958
1959 const RegisterBank &IdxBank =
1960 *OpdMapper.getInstrMapping().getOperandMapping(2).BreakDown[0].RegBank;
1961
1962 bool IsDivergentIdx = IdxBank != AMDGPU::SGPRRegBank;
1963
1964 LLT VecTy = MRI.getType(VecReg);
1965 unsigned EltSize = VecTy.getScalarSizeInBits();
1966 unsigned NumElem = VecTy.getNumElements();
1967
1968 if (!SITargetLowering::shouldExpandVectorDynExt(EltSize, NumElem,
1969 IsDivergentIdx, &Subtarget))
1970 return false;
1971
1972 LLT S32 = LLT::scalar(32);
1973
1974 const RegisterBank &DstBank =
1975 *OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
1976 const RegisterBank &SrcBank =
1977 *OpdMapper.getInstrMapping().getOperandMapping(1).BreakDown[0].RegBank;
1978
1979 const RegisterBank &CCBank =
1980 (DstBank == AMDGPU::SGPRRegBank &&
1981 SrcBank == AMDGPU::SGPRRegBank &&
1982 IdxBank == AMDGPU::SGPRRegBank) ? AMDGPU::SGPRRegBank
1983 : AMDGPU::VCCRegBank;
1984 LLT CCTy = (CCBank == AMDGPU::SGPRRegBank) ? S32 : LLT::scalar(1);
1985
1986 if (CCBank == AMDGPU::VCCRegBank && IdxBank == AMDGPU::SGPRRegBank) {
1987 Idx = B.buildCopy(S32, Idx)->getOperand(0).getReg();
1988 MRI.setRegBank(Idx, AMDGPU::VGPRRegBank);
1989 }
1990
1991 LLT EltTy = VecTy.getScalarType();
1992 SmallVector<Register, 2> DstRegs(OpdMapper.getVRegs(0));
1993 unsigned NumLanes = DstRegs.size();
1994 if (!NumLanes)
1995 NumLanes = 1;
1996 else
1997 EltTy = MRI.getType(DstRegs[0]);
1998
1999 auto UnmergeToEltTy = B.buildUnmerge(EltTy, VecReg);
2000 SmallVector<Register, 2> Res(NumLanes);
2001 for (unsigned L = 0; L < NumLanes; ++L)
2002 Res[L] = UnmergeToEltTy.getReg(L);
2003
2004 for (unsigned I = 1; I < NumElem; ++I) {
2005 auto IC = B.buildConstant(S32, I);
2006 MRI.setRegBank(IC->getOperand(0).getReg(), AMDGPU::SGPRRegBank);
2007 auto Cmp = B.buildICmp(CmpInst::ICMP_EQ, CCTy, Idx, IC);
2008 MRI.setRegBank(Cmp->getOperand(0).getReg(), CCBank);
2009
2010 for (unsigned L = 0; L < NumLanes; ++L) {
2011 auto S = B.buildSelect(EltTy, Cmp,
2012 UnmergeToEltTy.getReg(I * NumLanes + L), Res[L]);
2013
2014 for (unsigned N : { 0, 2, 3 })
2015 MRI.setRegBank(S->getOperand(N).getReg(), DstBank);
2016
2017 Res[L] = S->getOperand(0).getReg();
2018 }
2019 }
2020
2021 for (unsigned L = 0; L < NumLanes; ++L) {
2022 Register DstReg = (NumLanes == 1) ? MI.getOperand(0).getReg() : DstRegs[L];
2023 B.buildCopy(DstReg, Res[L]);
2024 MRI.setRegBank(DstReg, DstBank);
2025 }
2026
2027 MRI.setRegBank(MI.getOperand(0).getReg(), DstBank);
2028 MI.eraseFromParent();
2029
2030 return true;
2031}
2032
2033// Insert a cross regbank copy for a register if it already has a bank that
2034// differs from the one we want to set.
2037 const RegisterBank &Bank) {
2038 const RegisterBank *CurrBank = MRI.getRegBankOrNull(Reg);
2039 if (CurrBank && *CurrBank != Bank) {
2040 Register Copy = B.buildCopy(MRI.getType(Reg), Reg).getReg(0);
2041 MRI.setRegBank(Copy, Bank);
2042 return Copy;
2043 }
2044
2045 MRI.setRegBank(Reg, Bank);
2046 return Reg;
2047}
2048
2049bool AMDGPURegisterBankInfo::foldInsertEltToCmpSelect(
2051 const OperandsMapper &OpdMapper) const {
2052
2053 MachineRegisterInfo &MRI = *B.getMRI();
2054 Register VecReg = MI.getOperand(1).getReg();
2055 Register Idx = MI.getOperand(3).getReg();
2056
2057 const RegisterBank &IdxBank =
2058 *OpdMapper.getInstrMapping().getOperandMapping(3).BreakDown[0].RegBank;
2059
2060 bool IsDivergentIdx = IdxBank != AMDGPU::SGPRRegBank;
2061
2062 LLT VecTy = MRI.getType(VecReg);
2063 unsigned EltSize = VecTy.getScalarSizeInBits();
2064 unsigned NumElem = VecTy.getNumElements();
2065
2066 if (!SITargetLowering::shouldExpandVectorDynExt(EltSize, NumElem,
2067 IsDivergentIdx, &Subtarget))
2068 return false;
2069
2070 LLT S32 = LLT::scalar(32);
2071
2072 const RegisterBank &DstBank =
2073 *OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2074 const RegisterBank &SrcBank =
2075 *OpdMapper.getInstrMapping().getOperandMapping(1).BreakDown[0].RegBank;
2076 const RegisterBank &InsBank =
2077 *OpdMapper.getInstrMapping().getOperandMapping(2).BreakDown[0].RegBank;
2078
2079 const RegisterBank &CCBank =
2080 (DstBank == AMDGPU::SGPRRegBank &&
2081 SrcBank == AMDGPU::SGPRRegBank &&
2082 InsBank == AMDGPU::SGPRRegBank &&
2083 IdxBank == AMDGPU::SGPRRegBank) ? AMDGPU::SGPRRegBank
2084 : AMDGPU::VCCRegBank;
2085 LLT CCTy = (CCBank == AMDGPU::SGPRRegBank) ? S32 : LLT::scalar(1);
2086
2087 if (CCBank == AMDGPU::VCCRegBank && IdxBank == AMDGPU::SGPRRegBank) {
2088 Idx = B.buildCopy(S32, Idx)->getOperand(0).getReg();
2089 MRI.setRegBank(Idx, AMDGPU::VGPRRegBank);
2090 }
2091
2092 LLT EltTy = VecTy.getScalarType();
2093 SmallVector<Register, 2> InsRegs(OpdMapper.getVRegs(2));
2094 unsigned NumLanes = InsRegs.size();
2095 if (!NumLanes) {
2096 NumLanes = 1;
2097 InsRegs.push_back(MI.getOperand(2).getReg());
2098 } else {
2099 EltTy = MRI.getType(InsRegs[0]);
2100 }
2101
2102 auto UnmergeToEltTy = B.buildUnmerge(EltTy, VecReg);
2103 SmallVector<Register, 16> Ops(NumElem * NumLanes);
2104
2105 for (unsigned I = 0; I < NumElem; ++I) {
2106 auto IC = B.buildConstant(S32, I);
2107 MRI.setRegBank(IC->getOperand(0).getReg(), AMDGPU::SGPRRegBank);
2108 auto Cmp = B.buildICmp(CmpInst::ICMP_EQ, CCTy, Idx, IC);
2109 MRI.setRegBank(Cmp->getOperand(0).getReg(), CCBank);
2110
2111 for (unsigned L = 0; L < NumLanes; ++L) {
2112 Register Op0 = constrainRegToBank(MRI, B, InsRegs[L], DstBank);
2113 Register Op1 = UnmergeToEltTy.getReg(I * NumLanes + L);
2114 Op1 = constrainRegToBank(MRI, B, Op1, DstBank);
2115
2116 Register Select = B.buildSelect(EltTy, Cmp, Op0, Op1).getReg(0);
2117 MRI.setRegBank(Select, DstBank);
2118
2119 Ops[I * NumLanes + L] = Select;
2120 }
2121 }
2122
2123 LLT MergeTy = LLT::fixed_vector(Ops.size(), EltTy);
2124 if (MergeTy == MRI.getType(MI.getOperand(0).getReg())) {
2125 B.buildBuildVector(MI.getOperand(0), Ops);
2126 } else {
2127 auto Vec = B.buildBuildVector(MergeTy, Ops);
2128 MRI.setRegBank(Vec->getOperand(0).getReg(), DstBank);
2129 B.buildBitcast(MI.getOperand(0).getReg(), Vec);
2130 }
2131
2132 MRI.setRegBank(MI.getOperand(0).getReg(), DstBank);
2133 MI.eraseFromParent();
2134
2135 return true;
2136}
2137
2138// Break s_mul_u64 into 32-bit vector operations.
2140 MachineIRBuilder &B, const OperandsMapper &OpdMapper) const {
2141 SmallVector<Register, 2> DefRegs(OpdMapper.getVRegs(0));
2142 SmallVector<Register, 2> Src0Regs(OpdMapper.getVRegs(1));
2143 SmallVector<Register, 2> Src1Regs(OpdMapper.getVRegs(2));
2144
2145 // All inputs are SGPRs, nothing special to do.
2146 if (DefRegs.empty()) {
2147 assert(Src0Regs.empty() && Src1Regs.empty());
2148 applyDefaultMapping(OpdMapper);
2149 return;
2150 }
2151
2152 assert(DefRegs.size() == 2);
2153 assert(Src0Regs.size() == Src1Regs.size() &&
2154 (Src0Regs.empty() || Src0Regs.size() == 2));
2155
2156 MachineRegisterInfo &MRI = OpdMapper.getMRI();
2157 MachineInstr &MI = OpdMapper.getMI();
2158 Register DstReg = MI.getOperand(0).getReg();
2159 LLT HalfTy = LLT::scalar(32);
2160
2161 // Depending on where the source registers came from, the generic code may
2162 // have decided to split the inputs already or not. If not, we still need to
2163 // extract the values.
2164
2165 if (Src0Regs.empty())
2166 split64BitValueForMapping(B, Src0Regs, HalfTy, MI.getOperand(1).getReg());
2167 else
2168 setRegsToType(MRI, Src0Regs, HalfTy);
2169
2170 if (Src1Regs.empty())
2171 split64BitValueForMapping(B, Src1Regs, HalfTy, MI.getOperand(2).getReg());
2172 else
2173 setRegsToType(MRI, Src1Regs, HalfTy);
2174
2175 setRegsToType(MRI, DefRegs, HalfTy);
2176
2177 // The multiplication is done as follows:
2178 //
2179 // Op1H Op1L
2180 // * Op0H Op0L
2181 // --------------------
2182 // Op1H*Op0L Op1L*Op0L
2183 // + Op1H*Op0H Op1L*Op0H
2184 // -----------------------------------------
2185 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
2186 //
2187 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
2188 // value and that would overflow.
2189 // The low 32-bit value is Op1L*Op0L.
2190 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from
2191 // Op1L*Op0L).
2192
2193 ApplyRegBankMapping ApplyBank(B, *this, MRI, &AMDGPU::VGPRRegBank);
2194
2195 Register Hi = B.buildUMulH(HalfTy, Src0Regs[0], Src1Regs[0]).getReg(0);
2196 Register MulLoHi = B.buildMul(HalfTy, Src0Regs[0], Src1Regs[1]).getReg(0);
2197 Register Add = B.buildAdd(HalfTy, Hi, MulLoHi).getReg(0);
2198 Register MulHiLo = B.buildMul(HalfTy, Src0Regs[1], Src1Regs[0]).getReg(0);
2199 B.buildAdd(DefRegs[1], Add, MulHiLo);
2200 B.buildMul(DefRegs[0], Src0Regs[0], Src1Regs[0]);
2201
2202 MRI.setRegBank(DstReg, AMDGPU::VGPRRegBank);
2203 MI.eraseFromParent();
2204}
2205
2207 MachineIRBuilder &B, const OperandsMapper &OpdMapper) const {
2208 MachineInstr &MI = OpdMapper.getMI();
2209 B.setInstrAndDebugLoc(MI);
2210 unsigned Opc = MI.getOpcode();
2211 MachineRegisterInfo &MRI = OpdMapper.getMRI();
2212 switch (Opc) {
2213 case AMDGPU::G_CONSTANT:
2214 case AMDGPU::G_IMPLICIT_DEF: {
2215 Register DstReg = MI.getOperand(0).getReg();
2216 LLT DstTy = MRI.getType(DstReg);
2217 if (DstTy != LLT::scalar(1))
2218 break;
2219
2220 const RegisterBank *DstBank =
2221 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2222 if (DstBank == &AMDGPU::VCCRegBank)
2223 break;
2224 SmallVector<Register, 1> DefRegs(OpdMapper.getVRegs(0));
2225 if (DefRegs.empty())
2226 DefRegs.push_back(DstReg);
2227
2228 B.setInsertPt(*MI.getParent(), ++MI.getIterator());
2229
2231 LLVMContext &Ctx = B.getMF().getFunction().getContext();
2232
2233 MI.getOperand(0).setReg(NewDstReg);
2234 if (Opc != AMDGPU::G_IMPLICIT_DEF) {
2235 uint64_t ConstVal = MI.getOperand(1).getCImm()->getZExtValue();
2236 MI.getOperand(1).setCImm(
2237 ConstantInt::get(IntegerType::getInt32Ty(Ctx), ConstVal));
2238 }
2239
2240 MRI.setRegBank(NewDstReg, *DstBank);
2241 B.buildTrunc(DefRegs[0], NewDstReg);
2242 return;
2243 }
2244 case AMDGPU::G_PHI: {
2245 Register DstReg = MI.getOperand(0).getReg();
2246 LLT DstTy = MRI.getType(DstReg);
2247 if (DstTy != LLT::scalar(1))
2248 break;
2249
2250 const LLT S32 = LLT::scalar(32);
2251 const RegisterBank *DstBank =
2252 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2253 if (DstBank == &AMDGPU::VCCRegBank) {
2254 applyDefaultMapping(OpdMapper);
2255 // The standard handling only considers the result register bank for
2256 // phis. For VCC, blindly inserting a copy when the phi is lowered will
2257 // produce an invalid copy. We can only copy with some kind of compare to
2258 // get a vector boolean result. Insert a register bank copy that will be
2259 // correctly lowered to a compare.
2260 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
2261 Register SrcReg = MI.getOperand(I).getReg();
2262 const RegisterBank *SrcBank = getRegBank(SrcReg, MRI, *TRI);
2263
2264 if (SrcBank != &AMDGPU::VCCRegBank) {
2265 MachineBasicBlock *SrcMBB = MI.getOperand(I + 1).getMBB();
2266 B.setInsertPt(*SrcMBB, SrcMBB->getFirstTerminator());
2267
2268 auto Copy = B.buildCopy(LLT::scalar(1), SrcReg);
2269 MRI.setRegBank(Copy.getReg(0), AMDGPU::VCCRegBank);
2270 MI.getOperand(I).setReg(Copy.getReg(0));
2271 }
2272 }
2273
2274 return;
2275 }
2276
2277 // Phi handling is strange and only considers the bank of the destination.
2278 substituteSimpleCopyRegs(OpdMapper, 0);
2279
2280 // Promote SGPR/VGPR booleans to s32
2281 ApplyRegBankMapping ApplyBank(B, *this, MRI, DstBank);
2282 B.setInsertPt(B.getMBB(), MI);
2283 LegalizerHelper Helper(B.getMF(), ApplyBank, B);
2284
2285 if (Helper.widenScalar(MI, 0, S32) != LegalizerHelper::Legalized)
2286 llvm_unreachable("widen scalar should have succeeded");
2287
2288 return;
2289 }
2290 case AMDGPU::G_FCMP:
2291 if (!Subtarget.hasSALUFloatInsts())
2292 break;
2293 [[fallthrough]];
2294 case AMDGPU::G_ICMP:
2295 case AMDGPU::G_UADDO:
2296 case AMDGPU::G_USUBO:
2297 case AMDGPU::G_UADDE:
2298 case AMDGPU::G_SADDE:
2299 case AMDGPU::G_USUBE:
2300 case AMDGPU::G_SSUBE: {
2301 unsigned BoolDstOp =
2302 (Opc == AMDGPU::G_ICMP || Opc == AMDGPU::G_FCMP) ? 0 : 1;
2303 Register DstReg = MI.getOperand(BoolDstOp).getReg();
2304
2305 const RegisterBank *DstBank =
2306 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2307 if (DstBank != &AMDGPU::SGPRRegBank)
2308 break;
2309
2310 const bool HasCarryIn = MI.getNumOperands() == 5;
2311
2312 // If this is a scalar compare, promote the result to s32, as the selection
2313 // will end up using a copy to a 32-bit vreg.
2314 const LLT S32 = LLT::scalar(32);
2315 Register NewDstReg = MRI.createGenericVirtualRegister(S32);
2316 MRI.setRegBank(NewDstReg, AMDGPU::SGPRRegBank);
2317 MI.getOperand(BoolDstOp).setReg(NewDstReg);
2318
2319 if (HasCarryIn) {
2320 Register NewSrcReg = MRI.createGenericVirtualRegister(S32);
2321 MRI.setRegBank(NewSrcReg, AMDGPU::SGPRRegBank);
2322 B.buildZExt(NewSrcReg, MI.getOperand(4).getReg());
2323 MI.getOperand(4).setReg(NewSrcReg);
2324 }
2325
2326 MachineBasicBlock *MBB = MI.getParent();
2327 B.setInsertPt(*MBB, std::next(MI.getIterator()));
2328
2329 // If we had a constrained VCC result register, a copy was inserted to VCC
2330 // from SGPR.
2331 SmallVector<Register, 1> DefRegs(OpdMapper.getVRegs(0));
2332 if (DefRegs.empty())
2333 DefRegs.push_back(DstReg);
2334 B.buildTrunc(DefRegs[0], NewDstReg);
2335 return;
2336 }
2337 case AMDGPU::G_SELECT: {
2338 Register DstReg = MI.getOperand(0).getReg();
2339 LLT DstTy = MRI.getType(DstReg);
2340
2341 SmallVector<Register, 1> CondRegs(OpdMapper.getVRegs(1));
2342 if (CondRegs.empty())
2343 CondRegs.push_back(MI.getOperand(1).getReg());
2344 else {
2345 assert(CondRegs.size() == 1);
2346 }
2347
2348 const RegisterBank *CondBank = getRegBank(CondRegs[0], MRI, *TRI);
2349 if (CondBank == &AMDGPU::SGPRRegBank) {
2350 const LLT S32 = LLT::scalar(32);
2351 Register NewCondReg = MRI.createGenericVirtualRegister(S32);
2352 MRI.setRegBank(NewCondReg, AMDGPU::SGPRRegBank);
2353
2354 MI.getOperand(1).setReg(NewCondReg);
2355 B.buildZExt(NewCondReg, CondRegs[0]);
2356 }
2357
2358 if (DstTy.getSizeInBits() != 64)
2359 break;
2360
2361 LLT HalfTy = getHalfSizedType(DstTy);
2362
2363 SmallVector<Register, 2> DefRegs(OpdMapper.getVRegs(0));
2364 SmallVector<Register, 2> Src1Regs(OpdMapper.getVRegs(2));
2365 SmallVector<Register, 2> Src2Regs(OpdMapper.getVRegs(3));
2366
2367 // All inputs are SGPRs, nothing special to do.
2368 if (DefRegs.empty()) {
2369 assert(Src1Regs.empty() && Src2Regs.empty());
2370 break;
2371 }
2372
2373 if (Src1Regs.empty())
2374 split64BitValueForMapping(B, Src1Regs, HalfTy, MI.getOperand(2).getReg());
2375 else {
2376 setRegsToType(MRI, Src1Regs, HalfTy);
2377 }
2378
2379 if (Src2Regs.empty())
2380 split64BitValueForMapping(B, Src2Regs, HalfTy, MI.getOperand(3).getReg());
2381 else
2382 setRegsToType(MRI, Src2Regs, HalfTy);
2383
2384 setRegsToType(MRI, DefRegs, HalfTy);
2385
2386 auto Flags = MI.getFlags();
2387 B.buildSelect(DefRegs[0], CondRegs[0], Src1Regs[0], Src2Regs[0], Flags);
2388 B.buildSelect(DefRegs[1], CondRegs[0], Src1Regs[1], Src2Regs[1], Flags);
2389
2390 MRI.setRegBank(DstReg, AMDGPU::VGPRRegBank);
2391 MI.eraseFromParent();
2392 return;
2393 }
2394 case AMDGPU::G_BRCOND: {
2395 Register CondReg = MI.getOperand(0).getReg();
2396 // FIXME: Should use legalizer helper, but should change bool ext type.
2397 const RegisterBank *CondBank =
2398 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2399
2400 if (CondBank == &AMDGPU::SGPRRegBank) {
2401 const LLT S32 = LLT::scalar(32);
2402 Register NewCondReg = MRI.createGenericVirtualRegister(S32);
2403 MRI.setRegBank(NewCondReg, AMDGPU::SGPRRegBank);
2404
2405 MI.getOperand(0).setReg(NewCondReg);
2406 B.buildZExt(NewCondReg, CondReg);
2407 return;
2408 }
2409
2410 break;
2411 }
2412 case AMDGPU::G_AND:
2413 case AMDGPU::G_OR:
2414 case AMDGPU::G_XOR: {
2415 // 64-bit and is only available on the SALU, so split into 2 32-bit ops if
2416 // there is a VGPR input.
2417 Register DstReg = MI.getOperand(0).getReg();
2418 LLT DstTy = MRI.getType(DstReg);
2419
2420 const RegisterBank *DstBank =
2421 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2422
2423 if (DstTy.getSizeInBits() == 1) {
2424 if (DstBank == &AMDGPU::VCCRegBank)
2425 break;
2426
2427 MachineFunction *MF = MI.getMF();
2428 ApplyRegBankMapping ApplyBank(B, *this, MRI, DstBank);
2429 LegalizerHelper Helper(*MF, ApplyBank, B);
2430
2431 if (Helper.widenScalar(MI, 0, LLT::scalar(32)) !=
2433 llvm_unreachable("widen scalar should have succeeded");
2434 return;
2435 }
2436
2437 if (DstTy.getSizeInBits() == 16 && DstBank == &AMDGPU::SGPRRegBank) {
2438 const LLT S32 = LLT::scalar(32);
2439 MachineBasicBlock *MBB = MI.getParent();
2440 MachineFunction *MF = MBB->getParent();
2441 ApplyRegBankMapping ApplySALU(B, *this, MRI, &AMDGPU::SGPRRegBank);
2442 LegalizerHelper Helper(*MF, ApplySALU, B);
2443 // Widen to S32, but handle `G_XOR x, -1` differently. Legalizer widening
2444 // will use a G_ANYEXT to extend the -1 which prevents matching G_XOR -1
2445 // as "not".
2446 if (MI.getOpcode() == AMDGPU::G_XOR &&
2447 mi_match(MI.getOperand(2).getReg(), MRI, m_SpecificICstOrSplat(-1))) {
2448 Helper.widenScalarSrc(MI, S32, 1, AMDGPU::G_ANYEXT);
2449 Helper.widenScalarSrc(MI, S32, 2, AMDGPU::G_SEXT);
2450 Helper.widenScalarDst(MI, S32);
2451 } else {
2452 if (Helper.widenScalar(MI, 0, S32) != LegalizerHelper::Legalized)
2453 llvm_unreachable("widen scalar should have succeeded");
2454 }
2455 return;
2456 }
2457
2458 if (DstTy.getSizeInBits() != 64)
2459 break;
2460
2461 LLT HalfTy = getHalfSizedType(DstTy);
2462 SmallVector<Register, 2> DefRegs(OpdMapper.getVRegs(0));
2463 SmallVector<Register, 2> Src0Regs(OpdMapper.getVRegs(1));
2464 SmallVector<Register, 2> Src1Regs(OpdMapper.getVRegs(2));
2465
2466 // All inputs are SGPRs, nothing special to do.
2467 if (DefRegs.empty()) {
2468 assert(Src0Regs.empty() && Src1Regs.empty());
2469 break;
2470 }
2471
2472 assert(DefRegs.size() == 2);
2473 assert(Src0Regs.size() == Src1Regs.size() &&
2474 (Src0Regs.empty() || Src0Regs.size() == 2));
2475
2476 // Depending on where the source registers came from, the generic code may
2477 // have decided to split the inputs already or not. If not, we still need to
2478 // extract the values.
2479
2480 if (Src0Regs.empty())
2481 split64BitValueForMapping(B, Src0Regs, HalfTy, MI.getOperand(1).getReg());
2482 else
2483 setRegsToType(MRI, Src0Regs, HalfTy);
2484
2485 if (Src1Regs.empty())
2486 split64BitValueForMapping(B, Src1Regs, HalfTy, MI.getOperand(2).getReg());
2487 else
2488 setRegsToType(MRI, Src1Regs, HalfTy);
2489
2490 setRegsToType(MRI, DefRegs, HalfTy);
2491
2492 auto Flags = MI.getFlags();
2493 B.buildInstr(Opc, {DefRegs[0]}, {Src0Regs[0], Src1Regs[0]}, Flags);
2494 B.buildInstr(Opc, {DefRegs[1]}, {Src0Regs[1], Src1Regs[1]}, Flags);
2495
2496 MRI.setRegBank(DstReg, AMDGPU::VGPRRegBank);
2497 MI.eraseFromParent();
2498 return;
2499 }
2500 case AMDGPU::G_ABS: {
2501 Register SrcReg = MI.getOperand(1).getReg();
2502 const RegisterBank *SrcBank = MRI.getRegBankOrNull(SrcReg);
2503
2504 // There is no VALU abs instruction so we need to replace it with a sub and
2505 // max combination.
2506 if (SrcBank && SrcBank == &AMDGPU::VGPRRegBank) {
2507 MachineFunction *MF = MI.getMF();
2508 ApplyRegBankMapping Apply(B, *this, MRI, &AMDGPU::VGPRRegBank);
2509 LegalizerHelper Helper(*MF, Apply, B);
2510
2512 llvm_unreachable("lowerAbsToMaxNeg should have succeeded");
2513 return;
2514 }
2515 [[fallthrough]];
2516 }
2517 case AMDGPU::G_ADD:
2518 case AMDGPU::G_SUB:
2519 case AMDGPU::G_MUL:
2520 case AMDGPU::G_SHL:
2521 case AMDGPU::G_LSHR:
2522 case AMDGPU::G_ASHR:
2523 case AMDGPU::G_SMIN:
2524 case AMDGPU::G_SMAX:
2525 case AMDGPU::G_UMIN:
2526 case AMDGPU::G_UMAX: {
2527 Register DstReg = MI.getOperand(0).getReg();
2528 LLT DstTy = MRI.getType(DstReg);
2529
2530 // Special case for s_mul_u64. There is not a vector equivalent of
2531 // s_mul_u64. Hence, we have to break down s_mul_u64 into 32-bit vector
2532 // multiplications.
2533 if (!Subtarget.useVMulU64Inst() && Opc == AMDGPU::G_MUL &&
2534 DstTy.getSizeInBits() == 64) {
2535 applyMappingSMULU64(B, OpdMapper);
2536 return;
2537 }
2538
2539 // 16-bit operations are VALU only, but can be promoted to 32-bit SALU.
2540 // Packed 16-bit operations need to be scalarized and promoted.
2541 if (DstTy != LLT::scalar(16) && DstTy != LLT::fixed_vector(2, 16))
2542 break;
2543
2544 const RegisterBank *DstBank =
2545 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2546 if (DstBank == &AMDGPU::VGPRRegBank)
2547 break;
2548
2549 const LLT S32 = LLT::scalar(32);
2550 MachineBasicBlock *MBB = MI.getParent();
2551 MachineFunction *MF = MBB->getParent();
2552 ApplyRegBankMapping ApplySALU(B, *this, MRI, &AMDGPU::SGPRRegBank);
2553
2554 if (DstTy.isVector() && Opc == AMDGPU::G_ABS) {
2555 Register WideSrcLo, WideSrcHi;
2556
2557 std::tie(WideSrcLo, WideSrcHi) =
2558 unpackV2S16ToS32(B, MI.getOperand(1).getReg(), TargetOpcode::G_SEXT);
2559 auto Lo = B.buildInstr(AMDGPU::G_ABS, {S32}, {WideSrcLo});
2560 auto Hi = B.buildInstr(AMDGPU::G_ABS, {S32}, {WideSrcHi});
2561 B.buildBuildVectorTrunc(DstReg, {Lo.getReg(0), Hi.getReg(0)});
2562 MI.eraseFromParent();
2563 return;
2564 }
2565
2566 if (DstTy.isVector()) {
2567 Register WideSrc0Lo, WideSrc0Hi;
2568 Register WideSrc1Lo, WideSrc1Hi;
2569
2570 unsigned ExtendOp = getExtendOp(MI.getOpcode());
2571 std::tie(WideSrc0Lo, WideSrc0Hi)
2572 = unpackV2S16ToS32(B, MI.getOperand(1).getReg(), ExtendOp);
2573 std::tie(WideSrc1Lo, WideSrc1Hi)
2574 = unpackV2S16ToS32(B, MI.getOperand(2).getReg(), ExtendOp);
2575 auto Lo = B.buildInstr(MI.getOpcode(), {S32}, {WideSrc0Lo, WideSrc1Lo});
2576 auto Hi = B.buildInstr(MI.getOpcode(), {S32}, {WideSrc0Hi, WideSrc1Hi});
2577 B.buildBuildVectorTrunc(DstReg, {Lo.getReg(0), Hi.getReg(0)});
2578 MI.eraseFromParent();
2579 } else {
2580 LegalizerHelper Helper(*MF, ApplySALU, B);
2581
2582 if (Helper.widenScalar(MI, 0, S32) != LegalizerHelper::Legalized)
2583 llvm_unreachable("widen scalar should have succeeded");
2584
2585 // FIXME: s16 shift amounts should be legal.
2586 if (Opc == AMDGPU::G_SHL || Opc == AMDGPU::G_LSHR ||
2587 Opc == AMDGPU::G_ASHR) {
2588 B.setInsertPt(*MBB, MI.getIterator());
2589 if (Helper.widenScalar(MI, 1, S32) != LegalizerHelper::Legalized)
2590 llvm_unreachable("widen scalar should have succeeded");
2591 }
2592 }
2593
2594 return;
2595 }
2596 case AMDGPU::G_AMDGPU_S_MUL_I64_I32:
2597 case AMDGPU::G_AMDGPU_S_MUL_U64_U32: {
2598 // This is a special case for s_mul_u64. We use
2599 // G_AMDGPU_S_MUL_I64_I32 opcode to represent an s_mul_u64 operation
2600 // where the 33 higher bits are sign-extended and
2601 // G_AMDGPU_S_MUL_U64_U32 opcode to represent an s_mul_u64 operation
2602 // where the 32 higher bits are zero-extended. In case scalar registers are
2603 // selected, both opcodes are lowered as s_mul_u64. If the vector registers
2604 // are selected, then G_AMDGPU_S_MUL_I64_I32 and
2605 // G_AMDGPU_S_MUL_U64_U32 are lowered with a vector mad instruction.
2606
2607 // Insert basic copies.
2608 applyDefaultMapping(OpdMapper);
2609
2610 Register DstReg = MI.getOperand(0).getReg();
2611 Register SrcReg0 = MI.getOperand(1).getReg();
2612 Register SrcReg1 = MI.getOperand(2).getReg();
2613 const LLT S32 = LLT::scalar(32);
2614 const LLT S64 = LLT::scalar(64);
2615 assert(MRI.getType(DstReg) == S64 && "This is a special case for s_mul_u64 "
2616 "that handles only 64-bit operands.");
2617 const RegisterBank *DstBank =
2618 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2619
2620 // Replace G_AMDGPU_S_MUL_I64_I32 and G_AMDGPU_S_MUL_U64_U32
2621 // with s_mul_u64 operation.
2622 if (DstBank == &AMDGPU::SGPRRegBank) {
2623 MI.setDesc(TII->get(AMDGPU::S_MUL_U64));
2624 MRI.setRegClass(DstReg, &AMDGPU::SGPR_64RegClass);
2625 MRI.setRegClass(SrcReg0, &AMDGPU::SGPR_64RegClass);
2626 MRI.setRegClass(SrcReg1, &AMDGPU::SGPR_64RegClass);
2627 return;
2628 }
2629
2630 // Replace G_AMDGPU_S_MUL_I64_I32 and G_AMDGPU_S_MUL_U64_U32
2631 // with a vector mad.
2632 assert(MRI.getRegBankOrNull(DstReg) == &AMDGPU::VGPRRegBank &&
2633 "The destination operand should be in vector registers.");
2634
2635 // Extract the lower subregister from the first operand.
2636 Register Op0L = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2637 MRI.setRegClass(Op0L, &AMDGPU::VGPR_32RegClass);
2638 MRI.setType(Op0L, S32);
2639 B.buildTrunc(Op0L, SrcReg0);
2640
2641 // Extract the lower subregister from the second operand.
2642 Register Op1L = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2643 MRI.setRegClass(Op1L, &AMDGPU::VGPR_32RegClass);
2644 MRI.setType(Op1L, S32);
2645 B.buildTrunc(Op1L, SrcReg1);
2646
2647 unsigned NewOpc = Opc == AMDGPU::G_AMDGPU_S_MUL_U64_U32
2648 ? AMDGPU::G_AMDGPU_MAD_U64_U32
2649 : AMDGPU::G_AMDGPU_MAD_I64_I32;
2650
2652 Register Zero64 = B.buildConstant(S64, 0).getReg(0);
2653 MRI.setRegClass(Zero64, &AMDGPU::VReg_64RegClass);
2654 Register CarryOut = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
2655 MRI.setRegClass(CarryOut, &AMDGPU::VReg_64RegClass);
2656 B.buildInstr(NewOpc, {DstReg, CarryOut}, {Op0L, Op1L, Zero64});
2657 MI.eraseFromParent();
2658 return;
2659 }
2660 case AMDGPU::G_SEXT_INREG: {
2661 SmallVector<Register, 2> SrcRegs(OpdMapper.getVRegs(1));
2662 if (SrcRegs.empty())
2663 break; // Nothing to repair
2664
2665 const LLT S32 = LLT::scalar(32);
2666 ApplyRegBankMapping O(B, *this, MRI, &AMDGPU::VGPRRegBank);
2667
2668 // Don't use LegalizerHelper's narrowScalar. It produces unwanted G_SEXTs
2669 // we would need to further expand, and doesn't let us directly set the
2670 // result registers.
2671 SmallVector<Register, 2> DstRegs(OpdMapper.getVRegs(0));
2672
2673 int Amt = MI.getOperand(2).getImm();
2674 if (Amt <= 32) {
2675 // Downstream users have expectations for the high bit behavior, so freeze
2676 // incoming undefined bits.
2677 if (Amt == 32) {
2678 // The low bits are unchanged.
2679 B.buildFreeze(DstRegs[0], SrcRegs[0]);
2680 } else {
2681 auto Freeze = B.buildFreeze(S32, SrcRegs[0]);
2682 // Extend in the low bits and propagate the sign bit to the high half.
2683 B.buildSExtInReg(DstRegs[0], Freeze, Amt);
2684 }
2685
2686 B.buildAShr(DstRegs[1], DstRegs[0], B.buildConstant(S32, 31));
2687 } else {
2688 // The low bits are unchanged, and extend in the high bits.
2689 // No freeze required
2690 B.buildCopy(DstRegs[0], SrcRegs[0]);
2691 B.buildSExtInReg(DstRegs[1], DstRegs[0], Amt - 32);
2692 }
2693
2694 Register DstReg = MI.getOperand(0).getReg();
2695 MRI.setRegBank(DstReg, AMDGPU::VGPRRegBank);
2696 MI.eraseFromParent();
2697 return;
2698 }
2699 case AMDGPU::G_CTPOP:
2700 case AMDGPU::G_BITREVERSE: {
2701 const RegisterBank *DstBank =
2702 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2703 if (DstBank == &AMDGPU::SGPRRegBank)
2704 break;
2705
2706 Register SrcReg = MI.getOperand(1).getReg();
2707 const LLT S32 = LLT::scalar(32);
2708 LLT Ty = MRI.getType(SrcReg);
2709 if (Ty == S32)
2710 break;
2711
2712 ApplyRegBankMapping ApplyVALU(B, *this, MRI, &AMDGPU::VGPRRegBank);
2713
2714 MachineFunction &MF = B.getMF();
2715 LegalizerHelper Helper(MF, ApplyVALU, B);
2716
2717 if (Helper.narrowScalar(MI, 1, S32) != LegalizerHelper::Legalized)
2718 llvm_unreachable("narrowScalar should have succeeded");
2719 return;
2720 }
2721 case AMDGPU::G_AMDGPU_FFBH_U32:
2722 case AMDGPU::G_AMDGPU_FFBL_B32:
2723 case AMDGPU::G_CTLZ_ZERO_POISON:
2724 case AMDGPU::G_CTTZ_ZERO_POISON: {
2725 const RegisterBank *DstBank =
2726 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
2727 if (DstBank == &AMDGPU::SGPRRegBank)
2728 break;
2729
2730 Register SrcReg = MI.getOperand(1).getReg();
2731 const LLT S32 = LLT::scalar(32);
2732 LLT Ty = MRI.getType(SrcReg);
2733 if (Ty == S32)
2734 break;
2735
2736 // We can narrow this more efficiently than Helper can by using ffbh/ffbl
2737 // which return -1 when the input is zero:
2738 // (ctlz_zero_poison hi:lo) -> (umin (ffbh hi), (add (ffbh lo), 32))
2739 // (cttz_zero_poison hi:lo) -> (umin (add (ffbl hi), 32), (ffbl lo))
2740 // (ffbh hi:lo) -> (umin (ffbh hi), (uaddsat (ffbh lo), 32))
2741 // (ffbl hi:lo) -> (umin (uaddsat (ffbh hi), 32), (ffbh lo))
2742 ApplyRegBankMapping ApplyVALU(B, *this, MRI, &AMDGPU::VGPRRegBank);
2743 SmallVector<Register, 2> SrcRegs(OpdMapper.getVRegs(1));
2744 unsigned NewOpc = Opc == AMDGPU::G_CTLZ_ZERO_POISON
2745 ? (unsigned)AMDGPU::G_AMDGPU_FFBH_U32
2746 : Opc == AMDGPU::G_CTTZ_ZERO_POISON
2747 ? (unsigned)AMDGPU::G_AMDGPU_FFBL_B32
2748 : Opc;
2749 unsigned Idx = NewOpc == AMDGPU::G_AMDGPU_FFBH_U32;
2750 auto X = B.buildInstr(NewOpc, {S32}, {SrcRegs[Idx]});
2751 auto Y = B.buildInstr(NewOpc, {S32}, {SrcRegs[Idx ^ 1]});
2752 unsigned AddOpc =
2753 Opc == AMDGPU::G_CTLZ_ZERO_POISON || Opc == AMDGPU::G_CTTZ_ZERO_POISON
2754 ? AMDGPU::G_ADD
2755 : AMDGPU::G_UADDSAT;
2756 Y = B.buildInstr(AddOpc, {S32}, {Y, B.buildConstant(S32, 32)});
2757 Register DstReg = MI.getOperand(0).getReg();
2758 B.buildUMin(DstReg, X, Y);
2759 MI.eraseFromParent();
2760 return;
2761 }
2762 case AMDGPU::G_SEXT:
2763 case AMDGPU::G_ZEXT:
2764 case AMDGPU::G_ANYEXT: {
2765 Register SrcReg = MI.getOperand(1).getReg();
2766 LLT SrcTy = MRI.getType(SrcReg);
2767 const bool Signed = Opc == AMDGPU::G_SEXT;
2768
2769 assert(OpdMapper.getVRegs(1).empty());
2770
2771 const RegisterBank *SrcBank =
2772 OpdMapper.getInstrMapping().getOperandMapping(1).BreakDown[0].RegBank;
2773
2774 Register DstReg = MI.getOperand(0).getReg();
2775 LLT DstTy = MRI.getType(DstReg);
2776 if (DstTy.isScalar() &&
2777 SrcBank != &AMDGPU::SGPRRegBank &&
2778 SrcBank != &AMDGPU::VCCRegBank &&
2779 // FIXME: Should handle any type that round to s64 when irregular
2780 // breakdowns supported.
2781 DstTy.getSizeInBits() == 64 &&
2782 SrcTy.getSizeInBits() <= 32) {
2783 SmallVector<Register, 2> DefRegs(OpdMapper.getVRegs(0));
2784
2785 // Extend to 32-bit, and then extend the low half.
2786 if (Signed) {
2787 // TODO: Should really be buildSExtOrCopy
2788 B.buildSExtOrTrunc(DefRegs[0], SrcReg);
2789 } else if (Opc == AMDGPU::G_ZEXT) {
2790 B.buildZExtOrTrunc(DefRegs[0], SrcReg);
2791 } else {
2792 B.buildAnyExtOrTrunc(DefRegs[0], SrcReg);
2793 }
2794
2795 extendLow32IntoHigh32(B, DefRegs[1], DefRegs[0], Opc, *SrcBank);
2796 MRI.setRegBank(DstReg, *SrcBank);
2797 MI.eraseFromParent();
2798 return;
2799 }
2800
2801 if (SrcTy != LLT::scalar(1))
2802 return;
2803
2804 // It is not legal to have a legalization artifact with a VCC source. Rather
2805 // than introducing a copy, insert the select we would have to select the
2806 // copy to.
2807 if (SrcBank == &AMDGPU::VCCRegBank) {
2808 SmallVector<Register, 2> DefRegs(OpdMapper.getVRegs(0));
2809
2810 const RegisterBank *DstBank = &AMDGPU::VGPRRegBank;
2811
2812 unsigned DstSize = DstTy.getSizeInBits();
2813 // 64-bit select is SGPR only
2814 const bool UseSel64 = DstSize > 32 &&
2815 SrcBank->getID() == AMDGPU::SGPRRegBankID;
2816
2817 // TODO: Should s16 select be legal?
2818 LLT SelType = UseSel64 ? LLT::scalar(64) : LLT::scalar(32);
2819 auto True = B.buildConstant(SelType, Signed ? -1 : 1);
2820 auto False = B.buildConstant(SelType, 0);
2821
2822 MRI.setRegBank(True.getReg(0), *DstBank);
2823 MRI.setRegBank(False.getReg(0), *DstBank);
2824 MRI.setRegBank(DstReg, *DstBank);
2825
2826 if (DstSize > 32) {
2827 B.buildSelect(DefRegs[0], SrcReg, True, False);
2828 extendLow32IntoHigh32(B, DefRegs[1], DefRegs[0], Opc, *SrcBank, true);
2829 } else if (DstSize < 32) {
2830 auto Sel = B.buildSelect(SelType, SrcReg, True, False);
2831 MRI.setRegBank(Sel.getReg(0), *DstBank);
2832 B.buildTrunc(DstReg, Sel);
2833 } else {
2834 B.buildSelect(DstReg, SrcReg, True, False);
2835 }
2836
2837 MI.eraseFromParent();
2838 return;
2839 }
2840
2841 break;
2842 }
2843 case AMDGPU::G_EXTRACT_VECTOR_ELT: {
2844 SmallVector<Register, 2> DstRegs(OpdMapper.getVRegs(0));
2845
2846 assert(OpdMapper.getVRegs(1).empty() && OpdMapper.getVRegs(2).empty());
2847
2848 Register DstReg = MI.getOperand(0).getReg();
2849 Register SrcReg = MI.getOperand(1).getReg();
2850
2851 const LLT S32 = LLT::scalar(32);
2852 LLT DstTy = MRI.getType(DstReg);
2853 LLT SrcTy = MRI.getType(SrcReg);
2854
2855 if (foldExtractEltToCmpSelect(B, MI, OpdMapper))
2856 return;
2857
2858 const ValueMapping &DstMapping
2859 = OpdMapper.getInstrMapping().getOperandMapping(0);
2860 const RegisterBank *DstBank = DstMapping.BreakDown[0].RegBank;
2861 const RegisterBank *SrcBank =
2862 OpdMapper.getInstrMapping().getOperandMapping(1).BreakDown[0].RegBank;
2863 const RegisterBank *IdxBank =
2864 OpdMapper.getInstrMapping().getOperandMapping(2).BreakDown[0].RegBank;
2865
2866 Register BaseIdxReg;
2867 unsigned ConstOffset;
2868 std::tie(BaseIdxReg, ConstOffset) =
2869 AMDGPU::getBaseWithConstantOffset(MRI, MI.getOperand(2).getReg());
2870
2871 // See if the index is an add of a constant which will be foldable by moving
2872 // the base register of the index later if this is going to be executed in a
2873 // waterfall loop. This is essentially to reassociate the add of a constant
2874 // with the readfirstlane.
2875 bool ShouldMoveIndexIntoLoop = IdxBank != &AMDGPU::SGPRRegBank &&
2876 ConstOffset > 0 &&
2877 ConstOffset < SrcTy.getNumElements();
2878
2879 // Move the base register. We'll re-insert the add later.
2880 if (ShouldMoveIndexIntoLoop)
2881 MI.getOperand(2).setReg(BaseIdxReg);
2882
2883 // If this is a VGPR result only because the index was a VGPR result, the
2884 // actual indexing will be done on the SGPR source vector, which will
2885 // produce a scalar result. We need to copy to the VGPR result inside the
2886 // waterfall loop.
2887 const bool NeedCopyToVGPR = DstBank == &AMDGPU::VGPRRegBank &&
2888 SrcBank == &AMDGPU::SGPRRegBank;
2889 if (DstRegs.empty()) {
2890 applyDefaultMapping(OpdMapper);
2891
2893
2894 if (NeedCopyToVGPR) {
2895 // We don't want a phi for this temporary reg.
2896 Register TmpReg = MRI.createGenericVirtualRegister(DstTy);
2897 MRI.setRegBank(TmpReg, AMDGPU::SGPRRegBank);
2898 MI.getOperand(0).setReg(TmpReg);
2899 B.setInsertPt(*MI.getParent(), ++MI.getIterator());
2900
2901 // Use a v_mov_b32 here to make the exec dependency explicit.
2902 buildVCopy(B, DstReg, TmpReg);
2903 }
2904
2905 // Re-insert the constant offset add inside the waterfall loop.
2906 if (ShouldMoveIndexIntoLoop)
2907 reinsertVectorIndexAdd(B, MI, 2, ConstOffset);
2908
2909 return;
2910 }
2911
2912 assert(DstTy.getSizeInBits() == 64);
2913
2914 LLT Vec32 = LLT::fixed_vector(2 * SrcTy.getNumElements(), 32);
2915
2916 auto CastSrc = B.buildBitcast(Vec32, SrcReg);
2917 auto One = B.buildConstant(S32, 1);
2918
2919 MachineBasicBlock::iterator MII = MI.getIterator();
2920
2921 // Split the vector index into 32-bit pieces. Prepare to move all of the
2922 // new instructions into a waterfall loop if necessary.
2923 //
2924 // Don't put the bitcast or constant in the loop.
2925 MachineInstrSpan Span(MII, &B.getMBB());
2926
2927 // Compute 32-bit element indices, (2 * OrigIdx, 2 * OrigIdx + 1).
2928 auto IdxLo = B.buildShl(S32, BaseIdxReg, One);
2929 auto IdxHi = B.buildAdd(S32, IdxLo, One);
2930
2931 auto Extract0 = B.buildExtractVectorElement(DstRegs[0], CastSrc, IdxLo);
2932 auto Extract1 = B.buildExtractVectorElement(DstRegs[1], CastSrc, IdxHi);
2933
2934 MRI.setRegBank(DstReg, *DstBank);
2935 MRI.setRegBank(CastSrc.getReg(0), *SrcBank);
2936 MRI.setRegBank(One.getReg(0), AMDGPU::SGPRRegBank);
2937 MRI.setRegBank(IdxLo.getReg(0), AMDGPU::SGPRRegBank);
2938 MRI.setRegBank(IdxHi.getReg(0), AMDGPU::SGPRRegBank);
2939
2940 SmallSet<Register, 4> OpsToWaterfall;
2941 if (!collectWaterfallOperands(OpsToWaterfall, MI, MRI, { 2 })) {
2942 MI.eraseFromParent();
2943 return;
2944 }
2945
2946 // Remove the original instruction to avoid potentially confusing the
2947 // waterfall loop logic.
2948 B.setInstr(*Span.begin());
2949 MI.eraseFromParent();
2950 executeInWaterfallLoop(B, make_range(Span.begin(), Span.end()),
2951 OpsToWaterfall);
2952
2953 if (NeedCopyToVGPR) {
2954 MachineBasicBlock *LoopBB = Extract1->getParent();
2957 MRI.setRegBank(TmpReg0, AMDGPU::SGPRRegBank);
2958 MRI.setRegBank(TmpReg1, AMDGPU::SGPRRegBank);
2959
2960 Extract0->getOperand(0).setReg(TmpReg0);
2961 Extract1->getOperand(0).setReg(TmpReg1);
2962
2963 B.setInsertPt(*LoopBB, ++Extract1->getIterator());
2964
2965 buildVCopy(B, DstRegs[0], TmpReg0);
2966 buildVCopy(B, DstRegs[1], TmpReg1);
2967 }
2968
2969 if (ShouldMoveIndexIntoLoop)
2970 reinsertVectorIndexAdd(B, *IdxLo, 1, ConstOffset);
2971
2972 return;
2973 }
2974 case AMDGPU::G_INSERT_VECTOR_ELT: {
2975 SmallVector<Register, 2> InsRegs(OpdMapper.getVRegs(2));
2976
2977 Register DstReg = MI.getOperand(0).getReg();
2978 LLT VecTy = MRI.getType(DstReg);
2979
2980 assert(OpdMapper.getVRegs(0).empty());
2981 assert(OpdMapper.getVRegs(3).empty());
2982
2983 if (substituteSimpleCopyRegs(OpdMapper, 1))
2984 MRI.setType(MI.getOperand(1).getReg(), VecTy);
2985
2986 if (foldInsertEltToCmpSelect(B, MI, OpdMapper))
2987 return;
2988
2989 const RegisterBank *IdxBank =
2990 OpdMapper.getInstrMapping().getOperandMapping(3).BreakDown[0].RegBank;
2991
2992 Register SrcReg = MI.getOperand(1).getReg();
2993 Register InsReg = MI.getOperand(2).getReg();
2994 LLT InsTy = MRI.getType(InsReg);
2995 (void)InsTy;
2996
2997 Register BaseIdxReg;
2998 unsigned ConstOffset;
2999 std::tie(BaseIdxReg, ConstOffset) =
3000 AMDGPU::getBaseWithConstantOffset(MRI, MI.getOperand(3).getReg());
3001
3002 // See if the index is an add of a constant which will be foldable by moving
3003 // the base register of the index later if this is going to be executed in a
3004 // waterfall loop. This is essentially to reassociate the add of a constant
3005 // with the readfirstlane.
3006 bool ShouldMoveIndexIntoLoop = IdxBank != &AMDGPU::SGPRRegBank &&
3007 ConstOffset > 0 &&
3008 ConstOffset < VecTy.getNumElements();
3009
3010 // Move the base register. We'll re-insert the add later.
3011 if (ShouldMoveIndexIntoLoop)
3012 MI.getOperand(3).setReg(BaseIdxReg);
3013
3014
3015 if (InsRegs.empty()) {
3017
3018 // Re-insert the constant offset add inside the waterfall loop.
3019 if (ShouldMoveIndexIntoLoop) {
3020 reinsertVectorIndexAdd(B, MI, 3, ConstOffset);
3021 }
3022
3023 return;
3024 }
3025
3026 assert(InsTy.getSizeInBits() == 64);
3027
3028 const LLT S32 = LLT::scalar(32);
3029 LLT Vec32 = LLT::fixed_vector(2 * VecTy.getNumElements(), 32);
3030
3031 auto CastSrc = B.buildBitcast(Vec32, SrcReg);
3032 auto One = B.buildConstant(S32, 1);
3033
3034 // Split the vector index into 32-bit pieces. Prepare to move all of the
3035 // new instructions into a waterfall loop if necessary.
3036 //
3037 // Don't put the bitcast or constant in the loop.
3039
3040 // Compute 32-bit element indices, (2 * OrigIdx, 2 * OrigIdx + 1).
3041 auto IdxLo = B.buildShl(S32, BaseIdxReg, One);
3042 auto IdxHi = B.buildAdd(S32, IdxLo, One);
3043
3044 auto InsLo = B.buildInsertVectorElement(Vec32, CastSrc, InsRegs[0], IdxLo);
3045 auto InsHi = B.buildInsertVectorElement(Vec32, InsLo, InsRegs[1], IdxHi);
3046
3047 const RegisterBank *DstBank =
3048 OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank;
3049 const RegisterBank *SrcBank =
3050 OpdMapper.getInstrMapping().getOperandMapping(1).BreakDown[0].RegBank;
3051 const RegisterBank *InsSrcBank =
3052 OpdMapper.getInstrMapping().getOperandMapping(2).BreakDown[0].RegBank;
3053
3054 MRI.setRegBank(InsReg, *InsSrcBank);
3055 MRI.setRegBank(CastSrc.getReg(0), *SrcBank);
3056 MRI.setRegBank(InsLo.getReg(0), *DstBank);
3057 MRI.setRegBank(InsHi.getReg(0), *DstBank);
3058 MRI.setRegBank(One.getReg(0), AMDGPU::SGPRRegBank);
3059 MRI.setRegBank(IdxLo.getReg(0), AMDGPU::SGPRRegBank);
3060 MRI.setRegBank(IdxHi.getReg(0), AMDGPU::SGPRRegBank);
3061
3062
3063 SmallSet<Register, 4> OpsToWaterfall;
3064 if (!collectWaterfallOperands(OpsToWaterfall, MI, MRI, { 3 })) {
3065 B.setInsertPt(B.getMBB(), MI);
3066 B.buildBitcast(DstReg, InsHi);
3067 MI.eraseFromParent();
3068 return;
3069 }
3070
3071 B.setInstr(*Span.begin());
3072 MI.eraseFromParent();
3073
3074 // Figure out the point after the waterfall loop before mangling the control
3075 // flow.
3076 executeInWaterfallLoop(B, make_range(Span.begin(), Span.end()),
3077 OpsToWaterfall);
3078
3079 // The insertion point is now right after the original instruction.
3080 //
3081 // Keep the bitcast to the original vector type out of the loop. Doing this
3082 // saved an extra phi we don't need inside the loop.
3083 B.buildBitcast(DstReg, InsHi);
3084
3085 // Re-insert the constant offset add inside the waterfall loop.
3086 if (ShouldMoveIndexIntoLoop)
3087 reinsertVectorIndexAdd(B, *IdxLo, 1, ConstOffset);
3088
3089 return;
3090 }
3091 case AMDGPU::G_AMDGPU_BUFFER_LOAD:
3092 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
3093 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT:
3094 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
3095 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE:
3096 case AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE:
3097 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE:
3098 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT_TFE:
3099 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE:
3100 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE_TFE:
3101 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT:
3102 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE:
3103 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16:
3104 case AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT:
3105 case AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16:
3106 case AMDGPU::G_AMDGPU_BUFFER_STORE:
3107 case AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE:
3108 case AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT:
3109 case AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT:
3110 case AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16:
3111 case AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT:
3112 case AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16: {
3113 applyDefaultMapping(OpdMapper);
3114 executeInWaterfallLoop(B, MI, {1, 4});
3115 return;
3116 }
3117 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP:
3118 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD:
3119 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB:
3120 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN:
3121 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN:
3122 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX:
3123 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX:
3124 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND:
3125 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR:
3126 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR:
3127 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC:
3128 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC:
3129 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32:
3130 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32:
3131 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD:
3132 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN:
3133 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX: {
3134 applyDefaultMapping(OpdMapper);
3135 executeInWaterfallLoop(B, MI, {2, 5});
3136 return;
3137 }
3138 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP: {
3139 applyDefaultMapping(OpdMapper);
3140 executeInWaterfallLoop(B, MI, {3, 6});
3141 return;
3142 }
3143 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD:
3144 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
3145 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE:
3146 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
3147 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT: {
3148 applyMappingSBufferLoad(B, OpdMapper);
3149 return;
3150 }
3151 case AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH:
3154 return;
3155 case AMDGPU::G_INTRINSIC:
3156 case AMDGPU::G_INTRINSIC_CONVERGENT: {
3157 switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
3158 case Intrinsic::amdgcn_readlane: {
3159 substituteSimpleCopyRegs(OpdMapper, 2);
3160
3161 assert(OpdMapper.getVRegs(0).empty());
3162 assert(OpdMapper.getVRegs(3).empty());
3163
3164 // Make sure the index is an SGPR. It doesn't make sense to run this in a
3165 // waterfall loop, so assume it's a uniform value.
3166 constrainOpWithReadfirstlane(B, MI, 3); // Index
3167 return;
3168 }
3169 case Intrinsic::amdgcn_writelane: {
3170 assert(OpdMapper.getVRegs(0).empty());
3171 assert(OpdMapper.getVRegs(2).empty());
3172 assert(OpdMapper.getVRegs(3).empty());
3173
3174 substituteSimpleCopyRegs(OpdMapper, 4); // VGPR input val
3175 constrainOpWithReadfirstlane(B, MI, 2); // Source value
3176 constrainOpWithReadfirstlane(B, MI, 3); // Index
3177 return;
3178 }
3179 case Intrinsic::amdgcn_interp_p1:
3180 case Intrinsic::amdgcn_interp_p2:
3181 case Intrinsic::amdgcn_interp_mov:
3182 case Intrinsic::amdgcn_interp_p1_f16:
3183 case Intrinsic::amdgcn_interp_p2_f16:
3184 case Intrinsic::amdgcn_lds_param_load: {
3185 applyDefaultMapping(OpdMapper);
3186
3187 // Readlane for m0 value, which is always the last operand.
3188 // FIXME: Should this be a waterfall loop instead?
3189 constrainOpWithReadfirstlane(B, MI, MI.getNumOperands() - 1); // Index
3190 return;
3191 }
3192 case Intrinsic::amdgcn_interp_inreg_p10:
3193 case Intrinsic::amdgcn_interp_inreg_p2:
3194 case Intrinsic::amdgcn_interp_inreg_p10_f16:
3195 case Intrinsic::amdgcn_interp_inreg_p2_f16:
3196 case Intrinsic::amdgcn_interp_p10_rtz_f16:
3197 case Intrinsic::amdgcn_interp_p2_rtz_f16:
3198 case Intrinsic::amdgcn_permlane16_swap:
3199 case Intrinsic::amdgcn_permlane32_swap:
3200 applyDefaultMapping(OpdMapper);
3201 return;
3202 case Intrinsic::amdgcn_permlane16:
3203 case Intrinsic::amdgcn_permlanex16: {
3204 // Doing a waterfall loop over these wouldn't make any sense.
3205 substituteSimpleCopyRegs(OpdMapper, 2);
3206 substituteSimpleCopyRegs(OpdMapper, 3);
3209 return;
3210 }
3211 case Intrinsic::amdgcn_permlane_bcast:
3212 case Intrinsic::amdgcn_permlane_up:
3213 case Intrinsic::amdgcn_permlane_down:
3214 case Intrinsic::amdgcn_permlane_xor:
3215 // Doing a waterfall loop over these wouldn't make any sense.
3218 return;
3219 case Intrinsic::amdgcn_permlane_idx_gen: {
3221 return;
3222 }
3223 case Intrinsic::amdgcn_sbfe:
3224 applyMappingBFE(B, OpdMapper, true);
3225 return;
3226 case Intrinsic::amdgcn_ubfe:
3227 applyMappingBFE(B, OpdMapper, false);
3228 return;
3229 case Intrinsic::amdgcn_inverse_ballot:
3230 case Intrinsic::amdgcn_s_bitreplicate:
3231 case Intrinsic::amdgcn_s_quadmask:
3232 case Intrinsic::amdgcn_s_wqm:
3233 applyDefaultMapping(OpdMapper);
3234 constrainOpWithReadfirstlane(B, MI, 2); // Mask
3235 return;
3236 case Intrinsic::amdgcn_ballot:
3237 // Use default handling and insert copy to vcc source.
3238 break;
3239 }
3240 break;
3241 }
3242 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
3243 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
3244 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
3245 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
3246 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
3247 const AMDGPU::RsrcIntrinsic *RSrcIntrin =
3249 assert(RSrcIntrin && RSrcIntrin->IsImage);
3250 // Non-images can have complications from operands that allow both SGPR
3251 // and VGPR. For now it's too complicated to figure out the final opcode
3252 // to derive the register bank from the MCInstrDesc.
3253 applyMappingImage(B, MI, OpdMapper, RSrcIntrin->RsrcArg);
3254 return;
3255 }
3256 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
3257 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
3258 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY: {
3259 bool IsDualOrBVH8 =
3260 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY ||
3261 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY;
3262 unsigned NumMods = IsDualOrBVH8 ? 0 : 1; // Has A16 modifier
3263 unsigned LastRegOpIdx = MI.getNumExplicitOperands() - 1 - NumMods;
3264 applyDefaultMapping(OpdMapper);
3265 executeInWaterfallLoop(B, MI, {LastRegOpIdx});
3266 return;
3267 }
3268 case AMDGPU::G_INTRINSIC_W_SIDE_EFFECTS:
3269 case AMDGPU::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS: {
3270 auto IntrID = cast<GIntrinsic>(MI).getIntrinsicID();
3271 switch (IntrID) {
3272 case Intrinsic::amdgcn_ds_ordered_add:
3273 case Intrinsic::amdgcn_ds_ordered_swap: {
3274 // This is only allowed to execute with 1 lane, so readfirstlane is safe.
3275 assert(OpdMapper.getVRegs(0).empty());
3276 substituteSimpleCopyRegs(OpdMapper, 3);
3278 return;
3279 }
3280 case Intrinsic::amdgcn_ds_gws_init:
3281 case Intrinsic::amdgcn_ds_gws_barrier:
3282 case Intrinsic::amdgcn_ds_gws_sema_br: {
3283 // Only the first lane is executes, so readfirstlane is safe.
3284 substituteSimpleCopyRegs(OpdMapper, 1);
3286 return;
3287 }
3288 case Intrinsic::amdgcn_ds_gws_sema_v:
3289 case Intrinsic::amdgcn_ds_gws_sema_p:
3290 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
3291 // Only the first lane is executes, so readfirstlane is safe.
3293 return;
3294 }
3295 case Intrinsic::amdgcn_ds_append:
3296 case Intrinsic::amdgcn_ds_consume: {
3298 return;
3299 }
3300 case Intrinsic::amdgcn_s_alloc_vgpr:
3302 return;
3303 case Intrinsic::amdgcn_s_sendmsg:
3304 case Intrinsic::amdgcn_s_sendmsghalt: {
3305 // FIXME: Should this use a waterfall loop?
3307 return;
3308 }
3309 case Intrinsic::amdgcn_s_setreg: {
3311 return;
3312 }
3313 case Intrinsic::amdgcn_s_ttracedata:
3315 return;
3316 case Intrinsic::amdgcn_raw_buffer_load_lds:
3317 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
3318 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
3319 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds: {
3320 applyDefaultMapping(OpdMapper);
3321 constrainOpWithReadfirstlane(B, MI, 1); // rsrc
3323 constrainOpWithReadfirstlane(B, MI, 5); // soffset
3324 return;
3325 }
3326 case Intrinsic::amdgcn_struct_buffer_load_lds:
3327 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
3328 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
3329 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
3330 applyDefaultMapping(OpdMapper);
3331 constrainOpWithReadfirstlane(B, MI, 1); // rsrc
3333 constrainOpWithReadfirstlane(B, MI, 6); // soffset
3334 return;
3335 }
3336 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
3337 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
3338 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
3339 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
3340 applyDefaultMapping(OpdMapper);
3342 return;
3343 }
3344 case Intrinsic::amdgcn_load_to_lds:
3345 case Intrinsic::amdgcn_load_async_to_lds:
3346 case Intrinsic::amdgcn_global_load_lds:
3347 case Intrinsic::amdgcn_global_load_async_lds: {
3348 applyDefaultMapping(OpdMapper);
3350 return;
3351 }
3352 case Intrinsic::amdgcn_lds_direct_load: {
3353 applyDefaultMapping(OpdMapper);
3354 // Readlane for m0 value, which is always the last operand.
3355 constrainOpWithReadfirstlane(B, MI, MI.getNumOperands() - 1); // Index
3356 return;
3357 }
3358 case Intrinsic::amdgcn_exp_row:
3359 applyDefaultMapping(OpdMapper);
3361 return;
3362 case Intrinsic::amdgcn_cluster_load_b32:
3363 case Intrinsic::amdgcn_cluster_load_b64:
3364 case Intrinsic::amdgcn_cluster_load_b128: {
3365 applyDefaultMapping(OpdMapper);
3367 return;
3368 }
3369 case Intrinsic::amdgcn_s_sleep_var:
3370 assert(OpdMapper.getVRegs(1).empty());
3372 return;
3373 case Intrinsic::amdgcn_s_barrier_join:
3374 case Intrinsic::amdgcn_s_wakeup_barrier:
3376 return;
3377 case Intrinsic::amdgcn_s_barrier_init:
3378 case Intrinsic::amdgcn_s_barrier_signal_var:
3381 return;
3382 case Intrinsic::amdgcn_s_get_barrier_state:
3383 case Intrinsic::amdgcn_s_get_named_barrier_state: {
3385 return;
3386 }
3387 case Intrinsic::amdgcn_s_prefetch_data:
3388 case Intrinsic::amdgcn_s_prefetch_inst: {
3389 Register PtrReg = MI.getOperand(1).getReg();
3390 unsigned AS = MRI.getType(PtrReg).getAddressSpace();
3394 } else
3395 MI.eraseFromParent();
3396 return;
3397 }
3398 case Intrinsic::amdgcn_tensor_load_to_lds:
3399 case Intrinsic::amdgcn_tensor_store_from_lds: {
3405 return;
3406 }
3407 default: {
3408 if (const AMDGPU::RsrcIntrinsic *RSrcIntrin =
3410 // Non-images can have complications from operands that allow both SGPR
3411 // and VGPR. For now it's too complicated to figure out the final opcode
3412 // to derive the register bank from the MCInstrDesc.
3413 if (RSrcIntrin->IsImage) {
3414 applyMappingImage(B, MI, OpdMapper, RSrcIntrin->RsrcArg);
3415 return;
3416 }
3417 }
3418
3419 break;
3420 }
3421 }
3422 break;
3423 }
3424 case AMDGPU::G_SI_CALL: {
3425 // Use a set to avoid extra readfirstlanes in the case where multiple
3426 // operands are the same register.
3427 SmallSet<Register, 4> SGPROperandRegs;
3428
3429 if (!collectWaterfallOperands(SGPROperandRegs, MI, MRI, {1}))
3430 break;
3431
3432 // Move all copies to physical SGPRs that are used by the call instruction
3433 // into the loop block. Start searching for these copies until the
3434 // ADJCALLSTACKUP.
3435 unsigned FrameSetupOpcode = AMDGPU::ADJCALLSTACKUP;
3436 unsigned FrameDestroyOpcode = AMDGPU::ADJCALLSTACKDOWN;
3437
3438 // Move all non-copies before the copies, so that a complete range can be
3439 // moved into the waterfall loop.
3440 SmallVector<MachineInstr *, 4> NonCopyInstrs;
3441 // Count of NonCopyInstrs found until the current LastCopy.
3442 unsigned NonCopyInstrsLen = 0;
3444 MachineBasicBlock::iterator LastCopy = Start;
3445 MachineBasicBlock *MBB = MI.getParent();
3446 const SIMachineFunctionInfo *Info =
3447 MBB->getParent()->getInfo<SIMachineFunctionInfo>();
3448 while (Start->getOpcode() != FrameSetupOpcode) {
3449 --Start;
3450 bool IsCopy = false;
3451 if (Start->getOpcode() == AMDGPU::COPY) {
3452 auto &Dst = Start->getOperand(0);
3453 if (Dst.isReg()) {
3454 Register Reg = Dst.getReg();
3455 if (Reg.isPhysical() && MI.readsRegister(Reg, TRI)) {
3456 IsCopy = true;
3457 } else {
3458 // Also move the copy from the scratch rsrc descriptor into the loop
3459 // to allow it to be optimized away.
3460 auto &Src = Start->getOperand(1);
3461 if (Src.isReg()) {
3462 Reg = Src.getReg();
3463 IsCopy = Info->getScratchRSrcReg() == Reg;
3464 }
3465 }
3466 }
3467 }
3468
3469 if (IsCopy) {
3470 LastCopy = Start;
3471 NonCopyInstrsLen = NonCopyInstrs.size();
3472 } else {
3473 NonCopyInstrs.push_back(&*Start);
3474 }
3475 }
3476 NonCopyInstrs.resize(NonCopyInstrsLen);
3477
3478 for (auto *NonCopy : reverse(NonCopyInstrs)) {
3479 MBB->splice(LastCopy, MBB, NonCopy->getIterator());
3480 }
3481 Start = LastCopy;
3482
3483 // Do the same for copies after the loop
3484 NonCopyInstrs.clear();
3485 NonCopyInstrsLen = 0;
3487 LastCopy = End;
3488 while (End->getOpcode() != FrameDestroyOpcode) {
3489 ++End;
3490 bool IsCopy = false;
3491 if (End->getOpcode() == AMDGPU::COPY) {
3492 auto &Src = End->getOperand(1);
3493 if (Src.isReg()) {
3494 Register Reg = Src.getReg();
3495 IsCopy = Reg.isPhysical() && MI.modifiesRegister(Reg, TRI);
3496 }
3497 }
3498
3499 if (IsCopy) {
3500 LastCopy = End;
3501 NonCopyInstrsLen = NonCopyInstrs.size();
3502 } else {
3503 NonCopyInstrs.push_back(&*End);
3504 }
3505 }
3506 NonCopyInstrs.resize(NonCopyInstrsLen);
3507
3508 End = LastCopy;
3509 ++LastCopy;
3510 for (auto *NonCopy : reverse(NonCopyInstrs)) {
3511 MBB->splice(LastCopy, MBB, NonCopy->getIterator());
3512 }
3513
3514 ++End;
3515 B.setInsertPt(B.getMBB(), Start);
3516 executeInWaterfallLoop(B, make_range(Start, End), SGPROperandRegs);
3517 break;
3518 }
3519 case AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR:
3520 case AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR:
3521 case AMDGPU::G_LOAD:
3522 case AMDGPU::G_ZEXTLOAD:
3523 case AMDGPU::G_SEXTLOAD: {
3524 if (applyMappingLoad(B, OpdMapper, MI))
3525 return;
3526 break;
3527 }
3528 case AMDGPU::G_DYN_STACKALLOC:
3529 applyMappingDynStackAlloc(B, OpdMapper, MI);
3530 return;
3531 case AMDGPU::G_STACKRESTORE: {
3532 applyDefaultMapping(OpdMapper);
3534 return;
3535 }
3536 case AMDGPU::G_SBFX:
3537 applyMappingBFE(B, OpdMapper, /*Signed*/ true);
3538 return;
3539 case AMDGPU::G_UBFX:
3540 applyMappingBFE(B, OpdMapper, /*Signed*/ false);
3541 return;
3542 case AMDGPU::G_AMDGPU_MAD_U64_U32:
3543 case AMDGPU::G_AMDGPU_MAD_I64_I32:
3544 applyMappingMAD_64_32(B, OpdMapper);
3545 return;
3546 case AMDGPU::G_PREFETCH: {
3547 if (!Subtarget.hasSafeSmemPrefetch() && !Subtarget.hasVmemPrefInsts()) {
3548 MI.eraseFromParent();
3549 return;
3550 }
3551 Register PtrReg = MI.getOperand(0).getReg();
3552 unsigned PtrBank = getRegBankID(PtrReg, MRI, AMDGPU::SGPRRegBankID);
3553 if (PtrBank == AMDGPU::VGPRRegBankID &&
3554 (!Subtarget.hasVmemPrefInsts() || !MI.getOperand(3).getImm())) {
3555 // Cannot do I$ prefetch with divergent pointer.
3556 MI.eraseFromParent();
3557 return;
3558 }
3559 unsigned AS = MRI.getType(PtrReg).getAddressSpace();
3562 (!Subtarget.hasSafeSmemPrefetch() &&
3564 !MI.getOperand(3).getImm() /* I$ prefetch */))) {
3565 MI.eraseFromParent();
3566 return;
3567 }
3568 applyDefaultMapping(OpdMapper);
3569 return;
3570 }
3571 default:
3572 break;
3573 }
3574
3575 return applyDefaultMapping(OpdMapper);
3576}
3577
3578// vgpr, sgpr -> vgpr
3579// vgpr, agpr -> vgpr
3580// agpr, agpr -> agpr
3581// agpr, sgpr -> vgpr
3582static unsigned regBankUnion(unsigned RB0, unsigned RB1) {
3583 if (RB0 == AMDGPU::InvalidRegBankID)
3584 return RB1;
3585 if (RB1 == AMDGPU::InvalidRegBankID)
3586 return RB0;
3587
3588 if (RB0 == AMDGPU::SGPRRegBankID && RB1 == AMDGPU::SGPRRegBankID)
3589 return AMDGPU::SGPRRegBankID;
3590
3591 if (RB0 == AMDGPU::AGPRRegBankID && RB1 == AMDGPU::AGPRRegBankID)
3592 return AMDGPU::AGPRRegBankID;
3593
3594 return AMDGPU::VGPRRegBankID;
3595}
3596
3597static unsigned regBankBoolUnion(unsigned RB0, unsigned RB1) {
3598 if (RB0 == AMDGPU::InvalidRegBankID)
3599 return RB1;
3600 if (RB1 == AMDGPU::InvalidRegBankID)
3601 return RB0;
3602
3603 // vcc, vcc -> vcc
3604 // vcc, sgpr -> vcc
3605 // vcc, vgpr -> vcc
3606 if (RB0 == AMDGPU::VCCRegBankID || RB1 == AMDGPU::VCCRegBankID)
3607 return AMDGPU::VCCRegBankID;
3608
3609 // vcc, vgpr -> vgpr
3610 return regBankUnion(RB0, RB1);
3611}
3612
3614 const MachineInstr &MI) const {
3615 unsigned RegBank = AMDGPU::InvalidRegBankID;
3616
3617 for (const MachineOperand &MO : MI.operands()) {
3618 if (!MO.isReg())
3619 continue;
3620 Register Reg = MO.getReg();
3621 if (const RegisterBank *Bank = getRegBank(Reg, MRI, *TRI)) {
3622 RegBank = regBankUnion(RegBank, Bank->getID());
3623 if (RegBank == AMDGPU::VGPRRegBankID)
3624 break;
3625 }
3626 }
3627
3628 return RegBank;
3629}
3630
3632 const MachineFunction &MF = *MI.getMF();
3633 const MachineRegisterInfo &MRI = MF.getRegInfo();
3634 for (const MachineOperand &MO : MI.operands()) {
3635 if (!MO.isReg())
3636 continue;
3637 Register Reg = MO.getReg();
3638 if (const RegisterBank *Bank = getRegBank(Reg, MRI, *TRI)) {
3639 if (Bank->getID() != AMDGPU::SGPRRegBankID)
3640 return false;
3641 }
3642 }
3643 return true;
3644}
3645
3648 const MachineFunction &MF = *MI.getMF();
3649 const MachineRegisterInfo &MRI = MF.getRegInfo();
3650 SmallVector<const ValueMapping*, 8> OpdsMapping(MI.getNumOperands());
3651
3652 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
3653 const MachineOperand &SrcOp = MI.getOperand(i);
3654 if (!SrcOp.isReg())
3655 continue;
3656
3657 unsigned Size = getSizeInBits(SrcOp.getReg(), MRI, *TRI);
3658 OpdsMapping[i] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
3659 }
3660 return getInstructionMapping(1, 1, getOperandsMapping(OpdsMapping),
3661 MI.getNumOperands());
3662}
3663
3666 const MachineFunction &MF = *MI.getMF();
3667 const MachineRegisterInfo &MRI = MF.getRegInfo();
3668 SmallVector<const ValueMapping*, 8> OpdsMapping(MI.getNumOperands());
3669
3670 // Even though we technically could use SGPRs, this would require knowledge of
3671 // the constant bus restriction. Force all sources to VGPR (except for VCC).
3672 //
3673 // TODO: Unary ops are trivially OK, so accept SGPRs?
3674 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
3675 const MachineOperand &Src = MI.getOperand(i);
3676 if (!Src.isReg())
3677 continue;
3678
3679 unsigned Size = getSizeInBits(Src.getReg(), MRI, *TRI);
3680 unsigned BankID = Size == 1 ? AMDGPU::VCCRegBankID : AMDGPU::VGPRRegBankID;
3681 OpdsMapping[i] = AMDGPU::getValueMapping(BankID, Size);
3682 }
3683
3684 return getInstructionMapping(1, 1, getOperandsMapping(OpdsMapping),
3685 MI.getNumOperands());
3686}
3687
3690 const MachineFunction &MF = *MI.getMF();
3691 const MachineRegisterInfo &MRI = MF.getRegInfo();
3692 SmallVector<const ValueMapping*, 8> OpdsMapping(MI.getNumOperands());
3693
3694 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
3695 const MachineOperand &Op = MI.getOperand(I);
3696 if (!Op.isReg())
3697 continue;
3698
3699 unsigned Size = getSizeInBits(Op.getReg(), MRI, *TRI);
3700 OpdsMapping[I] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
3701 }
3702
3703 return getInstructionMapping(1, 1, getOperandsMapping(OpdsMapping),
3704 MI.getNumOperands());
3705}
3706
3709 const MachineInstr &MI,
3710 int RsrcIdx) const {
3711 // The reported argument index is relative to the IR intrinsic call arguments,
3712 // so we need to shift by the number of defs and the intrinsic ID.
3713 RsrcIdx += MI.getNumExplicitDefs() + 1;
3714
3715 const int NumOps = MI.getNumOperands();
3717
3718 // TODO: Should packed/unpacked D16 difference be reported here as part of
3719 // the value mapping?
3720 for (int I = 0; I != NumOps; ++I) {
3721 if (!MI.getOperand(I).isReg())
3722 continue;
3723
3724 Register OpReg = MI.getOperand(I).getReg();
3725 // We replace some dead address operands with $noreg
3726 if (!OpReg)
3727 continue;
3728
3729 unsigned Size = getSizeInBits(OpReg, MRI, *TRI);
3730
3731 // FIXME: Probably need a new intrinsic register bank searchable table to
3732 // handle arbitrary intrinsics easily.
3733 //
3734 // If this has a sampler, it immediately follows rsrc.
3735 const bool MustBeSGPR = I == RsrcIdx || I == RsrcIdx + 1;
3736
3737 if (MustBeSGPR) {
3738 // If this must be an SGPR, so we must report whatever it is as legal.
3739 unsigned NewBank = getRegBankID(OpReg, MRI, AMDGPU::SGPRRegBankID);
3740 OpdsMapping[I] = AMDGPU::getValueMapping(NewBank, Size);
3741 } else {
3742 // Some operands must be VGPR, and these are easy to copy to.
3743 OpdsMapping[I] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
3744 }
3745 }
3746
3747 return getInstructionMapping(1, 1, getOperandsMapping(OpdsMapping), NumOps);
3748}
3749
3750/// Return the mapping for a pointer argument.
3753 Register PtrReg) const {
3754 LLT PtrTy = MRI.getType(PtrReg);
3755 unsigned Size = PtrTy.getSizeInBits();
3756 if (Subtarget.useFlatForGlobal() ||
3758 return AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
3759
3760 // If we're using MUBUF instructions for global memory, an SGPR base register
3761 // is possible. Otherwise this needs to be a VGPR.
3762 const RegisterBank *PtrBank = getRegBank(PtrReg, MRI, *TRI);
3763 return AMDGPU::getValueMapping(PtrBank->getID(), Size);
3764}
3765
3768
3769 const MachineFunction &MF = *MI.getMF();
3770 const MachineRegisterInfo &MRI = MF.getRegInfo();
3772 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
3773 Register PtrReg = MI.getOperand(1).getReg();
3774 LLT PtrTy = MRI.getType(PtrReg);
3775 unsigned AS = PtrTy.getAddressSpace();
3776 unsigned PtrSize = PtrTy.getSizeInBits();
3777
3778 const ValueMapping *ValMapping;
3779 const ValueMapping *PtrMapping;
3780
3781 const RegisterBank *PtrBank = getRegBank(PtrReg, MRI, *TRI);
3782
3783 if (PtrBank == &AMDGPU::SGPRRegBank && AMDGPU::isFlatGlobalAddrSpace(AS)) {
3784 if (isScalarLoadLegal(MI)) {
3785 // We have a uniform instruction so we want to use an SMRD load
3786 ValMapping = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
3787 PtrMapping = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, PtrSize);
3788 } else {
3789 ValMapping = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
3790
3791 // If we're using MUBUF instructions for global memory, an SGPR base
3792 // register is possible. Otherwise this needs to be a VGPR.
3793 unsigned PtrBankID = Subtarget.useFlatForGlobal() ?
3794 AMDGPU::VGPRRegBankID : AMDGPU::SGPRRegBankID;
3795
3796 PtrMapping = AMDGPU::getValueMapping(PtrBankID, PtrSize);
3797 }
3798 } else {
3799 ValMapping = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
3800 PtrMapping = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, PtrSize);
3801 }
3802
3803 OpdsMapping[0] = ValMapping;
3804 OpdsMapping[1] = PtrMapping;
3806 1, 1, getOperandsMapping(OpdsMapping), MI.getNumOperands());
3807 return Mapping;
3808
3809 // FIXME: Do we want to add a mapping for FLAT load, or should we just
3810 // handle that during instruction selection?
3811}
3812
3813unsigned
3815 const MachineRegisterInfo &MRI,
3816 unsigned Default) const {
3817 const RegisterBank *Bank = getRegBank(Reg, MRI, *TRI);
3818 return Bank ? Bank->getID() : Default;
3819}
3820
3823 const MachineRegisterInfo &MRI,
3824 const TargetRegisterInfo &TRI) const {
3825 // Lie and claim anything is legal, even though this needs to be an SGPR
3826 // applyMapping will have to deal with it as a waterfall loop.
3827 unsigned Bank = getRegBankID(Reg, MRI, AMDGPU::SGPRRegBankID);
3828 unsigned Size = getSizeInBits(Reg, MRI, TRI);
3829 return AMDGPU::getValueMapping(Bank, Size);
3830}
3831
3834 const MachineRegisterInfo &MRI,
3835 const TargetRegisterInfo &TRI) const {
3836 unsigned Size = getSizeInBits(Reg, MRI, TRI);
3837 return AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
3838}
3839
3842 const MachineRegisterInfo &MRI,
3843 const TargetRegisterInfo &TRI) const {
3844 unsigned Size = getSizeInBits(Reg, MRI, TRI);
3845 return AMDGPU::getValueMapping(AMDGPU::AGPRRegBankID, Size);
3846}
3847
3848///
3849/// This function must return a legal mapping, because
3850/// AMDGPURegisterBankInfo::getInstrAlternativeMappings() is not called
3851/// in RegBankSelect::Mode::Fast. Any mapping that would cause a
3852/// VGPR to SGPR generated is illegal.
3853///
3854// Operands that must be SGPRs must accept potentially divergent VGPRs as
3855// legal. These will be dealt with in applyMappingImpl.
3856//
3859 const MachineFunction &MF = *MI.getMF();
3860 const MachineRegisterInfo &MRI = MF.getRegInfo();
3861
3862 if (MI.isCopy() || MI.getOpcode() == AMDGPU::G_FREEZE) {
3863 Register DstReg = MI.getOperand(0).getReg();
3864 Register SrcReg = MI.getOperand(1).getReg();
3865
3866 // The default logic bothers to analyze impossible alternative mappings. We
3867 // want the most straightforward mapping, so just directly handle this.
3868 const RegisterBank *DstBank = getRegBank(DstReg, MRI, *TRI);
3869 const RegisterBank *SrcBank = getRegBank(SrcReg, MRI, *TRI);
3870
3871 // For COPY between a physical reg and an s1, there is no type associated so
3872 // we need to take the virtual register's type as a hint on how to interpret
3873 // s1 values.
3874 unsigned Size;
3875 if (!SrcReg.isVirtual() && !DstBank &&
3876 MRI.getType(DstReg) == LLT::scalar(1)) {
3877 DstBank = &AMDGPU::VCCRegBank;
3878 Size = 1;
3879 } else if (!DstReg.isVirtual() && MRI.getType(SrcReg) == LLT::scalar(1)) {
3880 DstBank = &AMDGPU::VCCRegBank;
3881 Size = 1;
3882 } else {
3883 Size = getSizeInBits(DstReg, MRI, *TRI);
3884 }
3885
3886 if (!DstBank)
3887 DstBank = SrcBank;
3888 else if (!SrcBank)
3889 SrcBank = DstBank;
3890
3891 if (MI.getOpcode() != AMDGPU::G_FREEZE &&
3892 cannotCopy(*DstBank, *SrcBank, TypeSize::getFixed(Size)))
3894
3895 const ValueMapping &ValMap = getValueMapping(0, Size, *DstBank);
3896 unsigned OpdsMappingSize = MI.isCopy() ? 1 : 2;
3897 SmallVector<const ValueMapping *, 1> OpdsMapping(OpdsMappingSize);
3898 OpdsMapping[0] = &ValMap;
3899 if (MI.getOpcode() == AMDGPU::G_FREEZE)
3900 OpdsMapping[1] = &ValMap;
3901
3902 return getInstructionMapping(
3903 1, /*Cost*/ 1,
3904 /*OperandsMapping*/ getOperandsMapping(OpdsMapping), OpdsMappingSize);
3905 }
3906
3907 if (MI.isRegSequence()) {
3908 // If any input is a VGPR, the result must be a VGPR. The default handling
3909 // assumes any copy between banks is legal.
3910 unsigned BankID = AMDGPU::SGPRRegBankID;
3911
3912 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
3913 auto OpBank = getRegBankID(MI.getOperand(I).getReg(), MRI);
3914 // It doesn't make sense to use vcc or scc banks here, so just ignore
3915 // them.
3916 if (OpBank != AMDGPU::SGPRRegBankID) {
3917 BankID = AMDGPU::VGPRRegBankID;
3918 break;
3919 }
3920 }
3921 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
3922
3923 const ValueMapping &ValMap = getValueMapping(0, Size, getRegBank(BankID));
3924 return getInstructionMapping(
3925 1, /*Cost*/ 1,
3926 /*OperandsMapping*/ getOperandsMapping({&ValMap}), 1);
3927 }
3928
3929 // The default handling is broken and doesn't handle illegal SGPR->VGPR copies
3930 // properly.
3931 //
3932 // TODO: There are additional exec masking dependencies to analyze.
3933 if (auto *PHI = dyn_cast<GPhi>(&MI)) {
3934 unsigned ResultBank = AMDGPU::InvalidRegBankID;
3935 Register DstReg = PHI->getReg(0);
3936
3937 // Sometimes the result may have already been assigned a bank.
3938 if (const RegisterBank *DstBank = getRegBank(DstReg, MRI, *TRI))
3939 ResultBank = DstBank->getID();
3940
3941 for (unsigned I = 0; I < PHI->getNumIncomingValues(); ++I) {
3942 Register Reg = PHI->getIncomingValue(I);
3943 const RegisterBank *Bank = getRegBank(Reg, MRI, *TRI);
3944
3945 // FIXME: Assuming VGPR for any undetermined inputs.
3946 if (!Bank || Bank->getID() == AMDGPU::VGPRRegBankID) {
3947 ResultBank = AMDGPU::VGPRRegBankID;
3948 break;
3949 }
3950
3951 // FIXME: Need to promote SGPR case to s32
3952 unsigned OpBank = Bank->getID();
3953 ResultBank = regBankBoolUnion(ResultBank, OpBank);
3954 }
3955
3956 assert(ResultBank != AMDGPU::InvalidRegBankID);
3957
3958 unsigned Size = MRI.getType(DstReg).getSizeInBits();
3959
3960 const ValueMapping &ValMap =
3961 getValueMapping(0, Size, getRegBank(ResultBank));
3962 return getInstructionMapping(
3963 1, /*Cost*/ 1,
3964 /*OperandsMapping*/ getOperandsMapping({&ValMap}), 1);
3965 }
3966
3968 if (Mapping.isValid())
3969 return Mapping;
3970
3971 SmallVector<const ValueMapping*, 8> OpdsMapping(MI.getNumOperands());
3972
3973 switch (MI.getOpcode()) {
3974 default:
3976
3977 case AMDGPU::G_AND:
3978 case AMDGPU::G_OR:
3979 case AMDGPU::G_XOR:
3980 case AMDGPU::G_MUL: {
3981 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
3982 if (Size == 1) {
3983 const RegisterBank *DstBank
3984 = getRegBank(MI.getOperand(0).getReg(), MRI, *TRI);
3985
3986 unsigned TargetBankID = AMDGPU::InvalidRegBankID;
3987 unsigned BankLHS = AMDGPU::InvalidRegBankID;
3988 unsigned BankRHS = AMDGPU::InvalidRegBankID;
3989 if (DstBank) {
3990 TargetBankID = DstBank->getID();
3991 if (DstBank == &AMDGPU::VCCRegBank) {
3992 TargetBankID = AMDGPU::VCCRegBankID;
3993 BankLHS = AMDGPU::VCCRegBankID;
3994 BankRHS = AMDGPU::VCCRegBankID;
3995 } else {
3996 BankLHS = getRegBankID(MI.getOperand(1).getReg(), MRI,
3997 AMDGPU::SGPRRegBankID);
3998 BankRHS = getRegBankID(MI.getOperand(2).getReg(), MRI,
3999 AMDGPU::SGPRRegBankID);
4000 }
4001 } else {
4002 BankLHS = getRegBankID(MI.getOperand(1).getReg(), MRI,
4003 AMDGPU::VCCRegBankID);
4004 BankRHS = getRegBankID(MI.getOperand(2).getReg(), MRI,
4005 AMDGPU::VCCRegBankID);
4006
4007 // Both inputs should be true booleans to produce a boolean result.
4008 if (BankLHS == AMDGPU::VGPRRegBankID || BankRHS == AMDGPU::VGPRRegBankID) {
4009 TargetBankID = AMDGPU::VGPRRegBankID;
4010 } else if (BankLHS == AMDGPU::VCCRegBankID || BankRHS == AMDGPU::VCCRegBankID) {
4011 TargetBankID = AMDGPU::VCCRegBankID;
4012 BankLHS = AMDGPU::VCCRegBankID;
4013 BankRHS = AMDGPU::VCCRegBankID;
4014 } else if (BankLHS == AMDGPU::SGPRRegBankID && BankRHS == AMDGPU::SGPRRegBankID) {
4015 TargetBankID = AMDGPU::SGPRRegBankID;
4016 }
4017 }
4018
4019 OpdsMapping[0] = AMDGPU::getValueMapping(TargetBankID, Size);
4020 OpdsMapping[1] = AMDGPU::getValueMapping(BankLHS, Size);
4021 OpdsMapping[2] = AMDGPU::getValueMapping(BankRHS, Size);
4022 break;
4023 }
4024
4025 if (Size == 64) {
4026
4027 if (isSALUMapping(MI)) {
4028 OpdsMapping[0] = getValueMappingSGPR64Only(AMDGPU::SGPRRegBankID, Size);
4029 OpdsMapping[1] = OpdsMapping[2] = OpdsMapping[0];
4030 } else {
4031 if (MI.getOpcode() == AMDGPU::G_MUL && Subtarget.useVMulU64Inst())
4032 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
4033 else
4034 OpdsMapping[0] =
4035 getValueMappingSGPR64Only(AMDGPU::VGPRRegBankID, Size);
4036 unsigned Bank1 = getRegBankID(MI.getOperand(1).getReg(), MRI /*, DefaultBankID*/);
4037 OpdsMapping[1] = AMDGPU::getValueMapping(Bank1, Size);
4038
4039 unsigned Bank2 = getRegBankID(MI.getOperand(2).getReg(), MRI /*, DefaultBankID*/);
4040 OpdsMapping[2] = AMDGPU::getValueMapping(Bank2, Size);
4041 }
4042
4043 break;
4044 }
4045
4046 [[fallthrough]];
4047 }
4048 case AMDGPU::G_PTR_ADD:
4049 case AMDGPU::G_PTRMASK:
4050 case AMDGPU::G_ADD:
4051 case AMDGPU::G_SUB:
4052 case AMDGPU::G_SHL:
4053 case AMDGPU::G_LSHR:
4054 case AMDGPU::G_ASHR:
4055 case AMDGPU::G_UADDO:
4056 case AMDGPU::G_USUBO:
4057 case AMDGPU::G_UADDE:
4058 case AMDGPU::G_SADDE:
4059 case AMDGPU::G_USUBE:
4060 case AMDGPU::G_SSUBE:
4061 case AMDGPU::G_ABS:
4062 case AMDGPU::G_SHUFFLE_VECTOR:
4063 case AMDGPU::G_SBFX:
4064 case AMDGPU::G_UBFX:
4065 case AMDGPU::G_AMDGPU_S_MUL_I64_I32:
4066 case AMDGPU::G_AMDGPU_S_MUL_U64_U32:
4067 if (isSALUMapping(MI)) {
4068 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4069 unsigned Size = Ty.getSizeInBits();
4070 // Packed add and sub are VALU only.
4071 if (Subtarget.hasAnyPackedU64Ops() && Ty.isVector() && Size == 128)
4072 return getDefaultMappingVOP(MI);
4073 return getDefaultMappingSOP(MI);
4074 }
4075 return getDefaultMappingVOP(MI);
4076 case AMDGPU::G_SMIN:
4077 case AMDGPU::G_SMAX:
4078 case AMDGPU::G_UMIN:
4079 case AMDGPU::G_UMAX:
4080 if (isSALUMapping(MI)) {
4081 // There are no scalar 64-bit min and max, use vector instruction instead.
4082 if (MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 64 &&
4083 Subtarget.useMinMaxI64Insts())
4084 return getDefaultMappingVOP(MI);
4085 return getDefaultMappingSOP(MI);
4086 }
4087 return getDefaultMappingVOP(MI);
4088 case AMDGPU::G_FADD:
4089 case AMDGPU::G_FSUB:
4090 case AMDGPU::G_FMUL:
4091 case AMDGPU::G_FMA:
4092 case AMDGPU::G_FFLOOR:
4093 case AMDGPU::G_FCEIL:
4094 case AMDGPU::G_INTRINSIC_ROUNDEVEN:
4095 case AMDGPU::G_FMINNUM:
4096 case AMDGPU::G_FMAXNUM:
4097 case AMDGPU::G_FMINIMUMNUM:
4098 case AMDGPU::G_FMAXIMUMNUM:
4099 case AMDGPU::G_INTRINSIC_TRUNC:
4100 case AMDGPU::G_STRICT_FADD:
4101 case AMDGPU::G_STRICT_FSUB:
4102 case AMDGPU::G_STRICT_FMUL:
4103 case AMDGPU::G_STRICT_FMA: {
4104 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4105 unsigned Size = Ty.getSizeInBits();
4106 if (Subtarget.hasSALUFloatInsts() && Ty.isScalar() &&
4107 (Size == 32 || Size == 16) && isSALUMapping(MI))
4108 return getDefaultMappingSOP(MI);
4109 return getDefaultMappingVOP(MI);
4110 }
4111 case AMDGPU::G_FMINIMUM:
4112 case AMDGPU::G_FMAXIMUM: {
4113 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4114 unsigned Size = Ty.getSizeInBits();
4115 if (Subtarget.hasSALUMinimumMaximumInsts() && Ty.isScalar() &&
4116 (Size == 32 || Size == 16) && isSALUMapping(MI))
4117 return getDefaultMappingSOP(MI);
4118 return getDefaultMappingVOP(MI);
4119 }
4120 case AMDGPU::G_FPTOSI:
4121 case AMDGPU::G_FPTOUI:
4122 case AMDGPU::G_FPTOSI_SAT:
4123 case AMDGPU::G_FPTOUI_SAT:
4124 case AMDGPU::G_SITOFP:
4125 case AMDGPU::G_UITOFP: {
4126 unsigned SizeDst = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4127 unsigned SizeSrc = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4128 if (Subtarget.hasSALUFloatInsts() && SizeDst == 32 && SizeSrc == 32 &&
4130 return getDefaultMappingSOP(MI);
4131 return getDefaultMappingVOP(MI);
4132 }
4133 case AMDGPU::G_FPTRUNC:
4134 case AMDGPU::G_FPEXT: {
4135 unsigned SizeDst = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4136 unsigned SizeSrc = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4137 if (Subtarget.hasSALUFloatInsts() && SizeDst != 64 && SizeSrc != 64 &&
4139 return getDefaultMappingSOP(MI);
4140 return getDefaultMappingVOP(MI);
4141 }
4142 case AMDGPU::G_FSQRT:
4143 case AMDGPU::G_FEXP2:
4144 case AMDGPU::G_FLOG2: {
4145 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4146 if (Subtarget.hasPseudoScalarTrans() && (Size == 16 || Size == 32) &&
4148 return getDefaultMappingSOP(MI);
4149 return getDefaultMappingVOP(MI);
4150 }
4151 case AMDGPU::G_SADDSAT: // FIXME: Could lower sat ops for SALU
4152 case AMDGPU::G_SSUBSAT:
4153 case AMDGPU::G_UADDSAT:
4154 case AMDGPU::G_USUBSAT:
4155 case AMDGPU::G_FMAD:
4156 case AMDGPU::G_FLDEXP:
4157 case AMDGPU::G_FMINNUM_IEEE:
4158 case AMDGPU::G_FMAXNUM_IEEE:
4159 case AMDGPU::G_FCANONICALIZE:
4160 case AMDGPU::G_STRICT_FLDEXP:
4161 case AMDGPU::G_BSWAP: // TODO: Somehow expand for scalar?
4162 case AMDGPU::G_FSHR: // TODO: Expand for scalar
4163 case AMDGPU::G_AMDGPU_FMIN_LEGACY:
4164 case AMDGPU::G_AMDGPU_FMAX_LEGACY:
4165 case AMDGPU::G_AMDGPU_RCP_IFLAG:
4166 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE0:
4167 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE1:
4168 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE2:
4169 case AMDGPU::G_AMDGPU_CVT_F32_UBYTE3:
4170 case AMDGPU::G_AMDGPU_CVT_PK_I16_I32:
4171 case AMDGPU::G_AMDGPU_SMED3:
4172 case AMDGPU::G_AMDGPU_FMED3:
4173 return getDefaultMappingVOP(MI);
4174 case AMDGPU::G_UMULH:
4175 case AMDGPU::G_SMULH: {
4176 if (Subtarget.hasScalarMulHiInsts() && isSALUMapping(MI))
4177 return getDefaultMappingSOP(MI);
4178 return getDefaultMappingVOP(MI);
4179 }
4180 case AMDGPU::G_AMDGPU_MAD_U64_U32:
4181 case AMDGPU::G_AMDGPU_MAD_I64_I32: {
4182 // Three possible mappings:
4183 //
4184 // - Default SOP
4185 // - Default VOP
4186 // - Scalar multiply: src0 and src1 are SGPRs, the rest is VOP.
4187 //
4188 // This allows instruction selection to keep the multiplication part of the
4189 // instruction on the SALU.
4190 bool AllSalu = true;
4191 bool MulSalu = true;
4192 for (unsigned i = 0; i < 5; ++i) {
4193 Register Reg = MI.getOperand(i).getReg();
4194 if (const RegisterBank *Bank = getRegBank(Reg, MRI, *TRI)) {
4195 if (Bank->getID() != AMDGPU::SGPRRegBankID) {
4196 AllSalu = false;
4197 if (i == 2 || i == 3) {
4198 MulSalu = false;
4199 break;
4200 }
4201 }
4202 }
4203 }
4204
4205 if (AllSalu)
4206 return getDefaultMappingSOP(MI);
4207
4208 // If the multiply-add is full-rate in VALU, use that even if the
4209 // multiplication part is scalar. Accumulating separately on the VALU would
4210 // take two instructions.
4211 if (!MulSalu || Subtarget.hasFullRate64Ops())
4212 return getDefaultMappingVOP(MI);
4213
4214 // Keep the multiplication on the SALU, then accumulate on the VALU.
4215 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 64);
4216 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
4217 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32);
4218 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32);
4219 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 64);
4220 break;
4221 }
4222 case AMDGPU::G_IMPLICIT_DEF: {
4223 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4224 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
4225 break;
4226 }
4227 case AMDGPU::G_FCONSTANT:
4228 case AMDGPU::G_CONSTANT:
4229 case AMDGPU::G_GLOBAL_VALUE:
4230 case AMDGPU::G_FRAME_INDEX:
4231 case AMDGPU::G_BLOCK_ADDR:
4232 case AMDGPU::G_READSTEADYCOUNTER:
4233 case AMDGPU::G_READCYCLECOUNTER: {
4234 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4235 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
4236 break;
4237 }
4238 case AMDGPU::G_DYN_STACKALLOC: {
4239 // Result is always uniform, and a wave reduction is needed for the source.
4240 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32);
4241 unsigned SrcBankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4242 OpdsMapping[1] = AMDGPU::getValueMapping(SrcBankID, 32);
4243 break;
4244 }
4245 case AMDGPU::G_AMDGPU_WAVE_ADDRESS: {
4246 // This case is weird because we expect a physical register in the source,
4247 // but need to set a bank anyway.
4248 //
4249 // TODO: We could select the result to SGPR or VGPR
4250 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32);
4251 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32);
4252 break;
4253 }
4254 case AMDGPU::G_INSERT: {
4255 unsigned BankID = getMappingType(MRI, MI);
4256 unsigned DstSize = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
4257 unsigned SrcSize = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
4258 unsigned EltSize = getSizeInBits(MI.getOperand(2).getReg(), MRI, *TRI);
4259 OpdsMapping[0] = AMDGPU::getValueMapping(BankID, DstSize);
4260 OpdsMapping[1] = AMDGPU::getValueMapping(BankID, SrcSize);
4261 OpdsMapping[2] = AMDGPU::getValueMapping(BankID, EltSize);
4262 OpdsMapping[3] = nullptr;
4263 break;
4264 }
4265 case AMDGPU::G_EXTRACT: {
4266 unsigned BankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4267 unsigned DstSize = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
4268 unsigned SrcSize = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
4269 OpdsMapping[0] = AMDGPU::getValueMapping(BankID, DstSize);
4270 OpdsMapping[1] = AMDGPU::getValueMapping(BankID, SrcSize);
4271 OpdsMapping[2] = nullptr;
4272 break;
4273 }
4274 case AMDGPU::G_BUILD_VECTOR:
4275 case AMDGPU::G_BUILD_VECTOR_TRUNC: {
4276 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
4277 if (DstTy == LLT::fixed_vector(2, 16)) {
4278 unsigned DstSize = DstTy.getSizeInBits();
4279 unsigned SrcSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4280 unsigned Src0BankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4281 unsigned Src1BankID = getRegBankID(MI.getOperand(2).getReg(), MRI);
4282 unsigned DstBankID = regBankUnion(Src0BankID, Src1BankID);
4283
4284 OpdsMapping[0] = AMDGPU::getValueMapping(DstBankID, DstSize);
4285 OpdsMapping[1] = AMDGPU::getValueMapping(Src0BankID, SrcSize);
4286 OpdsMapping[2] = AMDGPU::getValueMapping(Src1BankID, SrcSize);
4287 break;
4288 }
4289
4290 [[fallthrough]];
4291 }
4292 case AMDGPU::G_MERGE_VALUES:
4293 case AMDGPU::G_CONCAT_VECTORS: {
4294 unsigned Bank = getMappingType(MRI, MI);
4295 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4296 unsigned SrcSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4297
4298 OpdsMapping[0] = AMDGPU::getValueMapping(Bank, DstSize);
4299 // Op1 and Dst should use the same register bank.
4300 for (unsigned i = 1, e = MI.getNumOperands(); i != e; ++i)
4301 OpdsMapping[i] = AMDGPU::getValueMapping(Bank, SrcSize);
4302 break;
4303 }
4304 case AMDGPU::G_BITREVERSE:
4305 case AMDGPU::G_BITCAST:
4306 case AMDGPU::G_INTTOPTR:
4307 case AMDGPU::G_PTRTOINT:
4308 case AMDGPU::G_FABS:
4309 case AMDGPU::G_FNEG: {
4310 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4311 unsigned BankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4312 OpdsMapping[0] = OpdsMapping[1] = AMDGPU::getValueMapping(BankID, Size);
4313 break;
4314 }
4315 case AMDGPU::G_AMDGPU_FFBH_U32:
4316 case AMDGPU::G_AMDGPU_FFBL_B32:
4317 case AMDGPU::G_CTLZ_ZERO_POISON:
4318 case AMDGPU::G_CTTZ_ZERO_POISON: {
4319 unsigned Size = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4320 unsigned BankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4321 OpdsMapping[0] = AMDGPU::getValueMapping(BankID, 32);
4322 OpdsMapping[1] = AMDGPU::getValueMappingSGPR64Only(BankID, Size);
4323 break;
4324 }
4325 case AMDGPU::G_CTPOP: {
4326 unsigned Size = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4327 unsigned BankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4328 OpdsMapping[0] = AMDGPU::getValueMapping(BankID, 32);
4329
4330 // This should really be getValueMappingSGPR64Only, but allowing the generic
4331 // code to handle the register split just makes using LegalizerHelper more
4332 // difficult.
4333 OpdsMapping[1] = AMDGPU::getValueMapping(BankID, Size);
4334 break;
4335 }
4336 case AMDGPU::G_TRUNC: {
4337 Register Dst = MI.getOperand(0).getReg();
4338 Register Src = MI.getOperand(1).getReg();
4339 unsigned Bank = getRegBankID(Src, MRI);
4340 unsigned DstSize = getSizeInBits(Dst, MRI, *TRI);
4341 unsigned SrcSize = getSizeInBits(Src, MRI, *TRI);
4342 OpdsMapping[0] = AMDGPU::getValueMapping(Bank, DstSize);
4343 OpdsMapping[1] = AMDGPU::getValueMapping(Bank, SrcSize);
4344 break;
4345 }
4346 case AMDGPU::G_ZEXT:
4347 case AMDGPU::G_SEXT:
4348 case AMDGPU::G_ANYEXT:
4349 case AMDGPU::G_SEXT_INREG: {
4350 Register Dst = MI.getOperand(0).getReg();
4351 Register Src = MI.getOperand(1).getReg();
4352 unsigned DstSize = getSizeInBits(Dst, MRI, *TRI);
4353 unsigned SrcSize = getSizeInBits(Src, MRI, *TRI);
4354
4355 unsigned DstBank;
4356 const RegisterBank *SrcBank = getRegBank(Src, MRI, *TRI);
4357 assert(SrcBank);
4358 switch (SrcBank->getID()) {
4359 case AMDGPU::SGPRRegBankID:
4360 DstBank = AMDGPU::SGPRRegBankID;
4361 break;
4362 default:
4363 DstBank = AMDGPU::VGPRRegBankID;
4364 break;
4365 }
4366
4367 // Scalar extend can use 64-bit BFE, but VGPRs require extending to
4368 // 32-bits, and then to 64.
4369 OpdsMapping[0] = AMDGPU::getValueMappingSGPR64Only(DstBank, DstSize);
4370 OpdsMapping[1] = AMDGPU::getValueMappingSGPR64Only(SrcBank->getID(),
4371 SrcSize);
4372 break;
4373 }
4374 case AMDGPU::G_IS_FPCLASS: {
4375 Register SrcReg = MI.getOperand(1).getReg();
4376 unsigned SrcSize = MRI.getType(SrcReg).getSizeInBits();
4377 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4378 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, DstSize);
4379 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, SrcSize);
4380 break;
4381 }
4382 case AMDGPU::G_STORE: {
4383 assert(MI.getOperand(0).isReg());
4384 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4385
4386 // FIXME: We need to specify a different reg bank once scalar stores are
4387 // supported.
4388 const ValueMapping *ValMapping =
4389 AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
4390 OpdsMapping[0] = ValMapping;
4391 OpdsMapping[1] = getValueMappingForPtr(MRI, MI.getOperand(1).getReg());
4392 break;
4393 }
4394 case AMDGPU::G_ICMP:
4395 case AMDGPU::G_FCMP: {
4396 unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
4397
4398 // See if the result register has already been constrained to vcc, which may
4399 // happen due to control flow intrinsic lowering.
4400 unsigned DstBank = getRegBankID(MI.getOperand(0).getReg(), MRI,
4401 AMDGPU::SGPRRegBankID);
4402 unsigned Op2Bank = getRegBankID(MI.getOperand(2).getReg(), MRI);
4403 unsigned Op3Bank = getRegBankID(MI.getOperand(3).getReg(), MRI);
4404
4405 auto canUseSCCICMP = [&]() {
4406 auto Pred =
4407 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
4408 return Size == 32 ||
4409 (Size == 64 &&
4410 (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE) &&
4411 Subtarget.hasScalarCompareEq64());
4412 };
4413 auto canUseSCCFCMP = [&]() {
4414 return Subtarget.hasSALUFloatInsts() && (Size == 32 || Size == 16);
4415 };
4416
4417 bool isICMP = MI.getOpcode() == AMDGPU::G_ICMP;
4418 bool CanUseSCC = DstBank == AMDGPU::SGPRRegBankID &&
4419 Op2Bank == AMDGPU::SGPRRegBankID &&
4420 Op3Bank == AMDGPU::SGPRRegBankID &&
4421 (isICMP ? canUseSCCICMP() : canUseSCCFCMP());
4422
4423 DstBank = CanUseSCC ? AMDGPU::SGPRRegBankID : AMDGPU::VCCRegBankID;
4424 unsigned SrcBank = CanUseSCC ? AMDGPU::SGPRRegBankID : AMDGPU::VGPRRegBankID;
4425
4426 // TODO: Use 32-bit for scalar output size.
4427 // SCC results will need to be copied to a 32-bit SGPR virtual register.
4428 const unsigned ResultSize = 1;
4429
4430 OpdsMapping[0] = AMDGPU::getValueMapping(DstBank, ResultSize);
4431 OpdsMapping[1] = nullptr; // Predicate Operand.
4432 OpdsMapping[2] = AMDGPU::getValueMapping(SrcBank, Size);
4433 OpdsMapping[3] = AMDGPU::getValueMapping(SrcBank, Size);
4434 break;
4435 }
4436 case AMDGPU::G_EXTRACT_VECTOR_ELT: {
4437 // VGPR index can be used for waterfall when indexing a SGPR vector.
4438 unsigned SrcBankID = getRegBankID(MI.getOperand(1).getReg(), MRI);
4439 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4440 unsigned SrcSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4441 unsigned IdxSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
4442 unsigned IdxBank = getRegBankID(MI.getOperand(2).getReg(), MRI);
4443 unsigned OutputBankID = regBankUnion(SrcBankID, IdxBank);
4444
4445 OpdsMapping[0] = AMDGPU::getValueMappingSGPR64Only(OutputBankID, DstSize);
4446 OpdsMapping[1] = AMDGPU::getValueMapping(SrcBankID, SrcSize);
4447
4448 // The index can be either if the source vector is VGPR.
4449 OpdsMapping[2] = AMDGPU::getValueMapping(IdxBank, IdxSize);
4450 break;
4451 }
4452 case AMDGPU::G_INSERT_VECTOR_ELT: {
4453 unsigned OutputBankID = isSALUMapping(MI) ?
4454 AMDGPU::SGPRRegBankID : AMDGPU::VGPRRegBankID;
4455
4456 unsigned VecSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4457 unsigned InsertSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
4458 unsigned IdxSize = MRI.getType(MI.getOperand(3).getReg()).getSizeInBits();
4459 unsigned InsertEltBankID = getRegBankID(MI.getOperand(2).getReg(), MRI);
4460 unsigned IdxBankID = getRegBankID(MI.getOperand(3).getReg(), MRI);
4461
4462 OpdsMapping[0] = AMDGPU::getValueMapping(OutputBankID, VecSize);
4463 OpdsMapping[1] = AMDGPU::getValueMapping(OutputBankID, VecSize);
4464
4465 // This is a weird case, because we need to break down the mapping based on
4466 // the register bank of a different operand.
4467 if (InsertSize == 64 && OutputBankID == AMDGPU::VGPRRegBankID) {
4468 OpdsMapping[2] = AMDGPU::getValueMappingSplit64(InsertEltBankID,
4469 InsertSize);
4470 } else {
4471 assert(InsertSize == 32 || InsertSize == 64);
4472 OpdsMapping[2] = AMDGPU::getValueMapping(InsertEltBankID, InsertSize);
4473 }
4474
4475 // The index can be either if the source vector is VGPR.
4476 OpdsMapping[3] = AMDGPU::getValueMapping(IdxBankID, IdxSize);
4477 break;
4478 }
4479 case AMDGPU::G_UNMERGE_VALUES: {
4480 unsigned Bank = getMappingType(MRI, MI);
4481
4482 // Op1 and Dst should use the same register bank.
4483 // FIXME: Shouldn't this be the default? Why do we need to handle this?
4484 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
4485 unsigned Size = getSizeInBits(MI.getOperand(i).getReg(), MRI, *TRI);
4486 OpdsMapping[i] = AMDGPU::getValueMapping(Bank, Size);
4487 }
4488 break;
4489 }
4490 case AMDGPU::G_AMDGPU_BUFFER_LOAD:
4491 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE:
4492 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE:
4493 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT:
4494 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT:
4495 case AMDGPU::G_AMDGPU_BUFFER_LOAD_TFE:
4496 case AMDGPU::G_AMDGPU_BUFFER_LOAD_UBYTE_TFE:
4497 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SBYTE_TFE:
4498 case AMDGPU::G_AMDGPU_BUFFER_LOAD_USHORT_TFE:
4499 case AMDGPU::G_AMDGPU_BUFFER_LOAD_SSHORT_TFE:
4500 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT:
4501 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_TFE:
4502 case AMDGPU::G_AMDGPU_BUFFER_LOAD_FORMAT_D16:
4503 case AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT:
4504 case AMDGPU::G_AMDGPU_TBUFFER_LOAD_FORMAT_D16:
4505 case AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT:
4506 case AMDGPU::G_AMDGPU_TBUFFER_STORE_FORMAT_D16:
4507 case AMDGPU::G_AMDGPU_BUFFER_STORE:
4508 case AMDGPU::G_AMDGPU_BUFFER_STORE_BYTE:
4509 case AMDGPU::G_AMDGPU_BUFFER_STORE_SHORT:
4510 case AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT:
4511 case AMDGPU::G_AMDGPU_BUFFER_STORE_FORMAT_D16: {
4512 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
4513
4514 // rsrc
4515 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
4516
4517 // vindex
4518 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
4519
4520 // voffset
4521 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
4522
4523 // soffset
4524 OpdsMapping[4] = getSGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
4525
4526 // Any remaining operands are immediates and were correctly null
4527 // initialized.
4528 break;
4529 }
4530 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SWAP:
4531 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_ADD:
4532 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB:
4533 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMIN:
4534 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMIN:
4535 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SMAX:
4536 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_UMAX:
4537 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_AND:
4538 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_OR:
4539 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_XOR:
4540 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_INC:
4541 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_DEC:
4542 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_SUB_CLAMP_U32:
4543 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_COND_SUB_U32:
4544 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD:
4545 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMIN:
4546 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FMAX: {
4547 // vdata_out
4548 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
4549
4550 // vdata_in
4551 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
4552
4553 // rsrc
4554 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
4555
4556 // vindex
4557 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
4558
4559 // voffset
4560 OpdsMapping[4] = getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
4561
4562 // soffset
4563 OpdsMapping[5] = getSGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
4564
4565 // Any remaining operands are immediates and were correctly null
4566 // initialized.
4567 break;
4568 }
4569 case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_CMPSWAP: {
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 // cmp
4577 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
4578
4579 // rsrc
4580 OpdsMapping[3] = getSGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
4581
4582 // vindex
4583 OpdsMapping[4] = getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
4584
4585 // voffset
4586 OpdsMapping[5] = getVGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
4587
4588 // soffset
4589 OpdsMapping[6] = getSGPROpMapping(MI.getOperand(6).getReg(), MRI, *TRI);
4590
4591 // Any remaining operands are immediates and were correctly null
4592 // initialized.
4593 break;
4594 }
4595 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD:
4596 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
4597 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE:
4598 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
4599 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT: {
4600 // Lie and claim everything is legal, even though some need to be
4601 // SGPRs. applyMapping will have to deal with it as a waterfall loop.
4602 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
4603 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
4604
4605 // We need to convert this to a MUBUF if either the resource of offset is
4606 // VGPR.
4607 unsigned RSrcBank = OpdsMapping[1]->BreakDown[0].RegBank->getID();
4608 unsigned OffsetBank = OpdsMapping[2]->BreakDown[0].RegBank->getID();
4609 unsigned ResultBank = regBankUnion(RSrcBank, OffsetBank);
4610
4611 unsigned Size0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4612 OpdsMapping[0] = AMDGPU::getValueMapping(ResultBank, Size0);
4613 break;
4614 }
4615 case AMDGPU::G_AMDGPU_S_BUFFER_PREFETCH:
4616 OpdsMapping[0] = getSGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
4617 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
4618 break;
4619 case AMDGPU::G_AMDGPU_SPONENTRY: {
4620 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4621 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
4622 break;
4623 }
4624 case AMDGPU::G_INTRINSIC:
4625 case AMDGPU::G_INTRINSIC_CONVERGENT: {
4626 switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
4627 default:
4629 case Intrinsic::amdgcn_div_fmas:
4630 case Intrinsic::amdgcn_div_fixup:
4631 case Intrinsic::amdgcn_trig_preop:
4632 case Intrinsic::amdgcn_sin:
4633 case Intrinsic::amdgcn_cos:
4634 case Intrinsic::amdgcn_log_clamp:
4635 case Intrinsic::amdgcn_rcp_legacy:
4636 case Intrinsic::amdgcn_rsq_legacy:
4637 case Intrinsic::amdgcn_rsq_clamp:
4638 case Intrinsic::amdgcn_tanh:
4639 case Intrinsic::amdgcn_fmul_legacy:
4640 case Intrinsic::amdgcn_fma_legacy:
4641 case Intrinsic::amdgcn_frexp_mant:
4642 case Intrinsic::amdgcn_frexp_exp:
4643 case Intrinsic::amdgcn_fract:
4644 case Intrinsic::amdgcn_cvt_pknorm_i16:
4645 case Intrinsic::amdgcn_cvt_pknorm_u16:
4646 case Intrinsic::amdgcn_cvt_pk_i16:
4647 case Intrinsic::amdgcn_cvt_pk_u16:
4648 case Intrinsic::amdgcn_cvt_sr_pk_f16_f32:
4649 case Intrinsic::amdgcn_cvt_sr_pk_bf16_f32:
4650 case Intrinsic::amdgcn_cvt_pk_f16_fp8:
4651 case Intrinsic::amdgcn_cvt_pk_f16_bf8:
4652 case Intrinsic::amdgcn_cvt_pk_fp8_f16:
4653 case Intrinsic::amdgcn_cvt_pk_bf8_f16:
4654 case Intrinsic::amdgcn_cvt_sr_fp8_f16:
4655 case Intrinsic::amdgcn_cvt_sr_bf8_f16:
4656 case Intrinsic::amdgcn_cvt_scale_pk8_f16_fp8:
4657 case Intrinsic::amdgcn_cvt_scale_pk8_bf16_fp8:
4658 case Intrinsic::amdgcn_cvt_scale_pk8_f16_bf8:
4659 case Intrinsic::amdgcn_cvt_scale_pk8_bf16_bf8:
4660 case Intrinsic::amdgcn_cvt_scale_pk8_f16_fp4:
4661 case Intrinsic::amdgcn_cvt_scale_pk8_bf16_fp4:
4662 case Intrinsic::amdgcn_cvt_scale_pk8_f32_fp8:
4663 case Intrinsic::amdgcn_cvt_scale_pk8_f32_bf8:
4664 case Intrinsic::amdgcn_cvt_scale_pk8_f32_fp4:
4665 case Intrinsic::amdgcn_cvt_scale_pk16_f16_fp6:
4666 case Intrinsic::amdgcn_cvt_scale_pk16_bf16_fp6:
4667 case Intrinsic::amdgcn_cvt_scale_pk16_f16_bf6:
4668 case Intrinsic::amdgcn_cvt_scale_pk16_bf16_bf6:
4669 case Intrinsic::amdgcn_cvt_scale_pk16_f32_fp6:
4670 case Intrinsic::amdgcn_cvt_scale_pk16_f32_bf6:
4671 case Intrinsic::amdgcn_cvt_scalef32_pk8_fp8_bf16:
4672 case Intrinsic::amdgcn_cvt_scalef32_pk8_bf8_bf16:
4673 case Intrinsic::amdgcn_cvt_scalef32_pk8_fp8_f16:
4674 case Intrinsic::amdgcn_cvt_scalef32_pk8_bf8_f16:
4675 case Intrinsic::amdgcn_cvt_scalef32_pk8_fp8_f32:
4676 case Intrinsic::amdgcn_cvt_scalef32_pk8_bf8_f32:
4677 case Intrinsic::amdgcn_cvt_scalef32_pk8_fp4_f32:
4678 case Intrinsic::amdgcn_cvt_scalef32_pk8_fp4_f16:
4679 case Intrinsic::amdgcn_cvt_scalef32_pk8_fp4_bf16:
4680 case Intrinsic::amdgcn_cvt_scalef32_pk16_fp6_f32:
4681 case Intrinsic::amdgcn_cvt_scalef32_pk16_bf6_f32:
4682 case Intrinsic::amdgcn_cvt_scalef32_pk16_fp6_f16:
4683 case Intrinsic::amdgcn_cvt_scalef32_pk16_bf6_f16:
4684 case Intrinsic::amdgcn_cvt_scalef32_pk16_fp6_bf16:
4685 case Intrinsic::amdgcn_cvt_scalef32_pk16_bf6_bf16:
4686 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_fp8_bf16:
4687 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_bf8_bf16:
4688 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_fp8_f16:
4689 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_bf8_f16:
4690 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_fp8_f32:
4691 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_bf8_f32:
4692 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_fp4_f32:
4693 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_fp4_f16:
4694 case Intrinsic::amdgcn_cvt_scalef32_sr_pk8_fp4_bf16:
4695 case Intrinsic::amdgcn_cvt_scalef32_sr_pk16_fp6_f32:
4696 case Intrinsic::amdgcn_cvt_scalef32_sr_pk16_bf6_f32:
4697 case Intrinsic::amdgcn_cvt_scalef32_sr_pk16_fp6_f16:
4698 case Intrinsic::amdgcn_cvt_scalef32_sr_pk16_bf6_f16:
4699 case Intrinsic::amdgcn_cvt_scalef32_sr_pk16_fp6_bf16:
4700 case Intrinsic::amdgcn_cvt_scalef32_sr_pk16_bf6_bf16:
4701 case Intrinsic::amdgcn_sat_pk4_i4_i8:
4702 case Intrinsic::amdgcn_sat_pk4_u4_u8:
4703 case Intrinsic::amdgcn_fmed3:
4704 case Intrinsic::amdgcn_cubeid:
4705 case Intrinsic::amdgcn_cubema:
4706 case Intrinsic::amdgcn_cubesc:
4707 case Intrinsic::amdgcn_cubetc:
4708 case Intrinsic::amdgcn_sffbh:
4709 case Intrinsic::amdgcn_fmad_ftz:
4710 case Intrinsic::amdgcn_mbcnt_lo:
4711 case Intrinsic::amdgcn_mbcnt_hi:
4712 case Intrinsic::amdgcn_mul_u24:
4713 case Intrinsic::amdgcn_mul_i24:
4714 case Intrinsic::amdgcn_mulhi_u24:
4715 case Intrinsic::amdgcn_mulhi_i24:
4716 case Intrinsic::amdgcn_lerp:
4717 case Intrinsic::amdgcn_sad_u8:
4718 case Intrinsic::amdgcn_msad_u8:
4719 case Intrinsic::amdgcn_sad_hi_u8:
4720 case Intrinsic::amdgcn_sad_u16:
4721 case Intrinsic::amdgcn_qsad_pk_u16_u8:
4722 case Intrinsic::amdgcn_mqsad_pk_u16_u8:
4723 case Intrinsic::amdgcn_mqsad_u32_u8:
4724 case Intrinsic::amdgcn_cvt_pk_u8_f32:
4725 case Intrinsic::amdgcn_alignbyte:
4726 case Intrinsic::amdgcn_perm:
4727 case Intrinsic::amdgcn_prng_b32:
4728 case Intrinsic::amdgcn_fdot2:
4729 case Intrinsic::amdgcn_sdot2:
4730 case Intrinsic::amdgcn_udot2:
4731 case Intrinsic::amdgcn_sdot4:
4732 case Intrinsic::amdgcn_udot4:
4733 case Intrinsic::amdgcn_sdot8:
4734 case Intrinsic::amdgcn_udot8:
4735 case Intrinsic::amdgcn_fdot2_bf16_bf16:
4736 case Intrinsic::amdgcn_fdot2_f16_f16:
4737 case Intrinsic::amdgcn_fdot2_f32_bf16:
4738 case Intrinsic::amdgcn_fdot2c_f32_bf16:
4739 case Intrinsic::amdgcn_sudot4:
4740 case Intrinsic::amdgcn_sudot8:
4741 case Intrinsic::amdgcn_dot4_f32_fp8_bf8:
4742 case Intrinsic::amdgcn_dot4_f32_bf8_fp8:
4743 case Intrinsic::amdgcn_dot4_f32_fp8_fp8:
4744 case Intrinsic::amdgcn_dot4_f32_bf8_bf8:
4745 case Intrinsic::amdgcn_cvt_f32_fp8:
4746 case Intrinsic::amdgcn_cvt_f32_fp8_e5m3:
4747 case Intrinsic::amdgcn_cvt_f32_bf8:
4748 case Intrinsic::amdgcn_cvt_off_f32_i4:
4749 case Intrinsic::amdgcn_cvt_pk_f32_fp8:
4750 case Intrinsic::amdgcn_cvt_pk_f32_bf8:
4751 case Intrinsic::amdgcn_cvt_pk_fp8_f32:
4752 case Intrinsic::amdgcn_cvt_pk_fp8_f32_e5m3:
4753 case Intrinsic::amdgcn_cvt_pk_bf8_f32:
4754 case Intrinsic::amdgcn_cvt_sr_fp8_f32:
4755 case Intrinsic::amdgcn_cvt_sr_fp8_f32_e5m3:
4756 case Intrinsic::amdgcn_cvt_sr_bf8_f32:
4757 case Intrinsic::amdgcn_cvt_sr_bf16_f32:
4758 case Intrinsic::amdgcn_cvt_sr_f16_f32:
4759 case Intrinsic::amdgcn_cvt_f16_fp8:
4760 case Intrinsic::amdgcn_cvt_f16_bf8:
4761 case Intrinsic::amdgcn_cvt_scalef32_pk32_fp6_f16:
4762 case Intrinsic::amdgcn_cvt_scalef32_pk32_bf6_f16:
4763 case Intrinsic::amdgcn_cvt_scalef32_pk32_fp6_bf16:
4764 case Intrinsic::amdgcn_cvt_scalef32_pk32_bf6_bf16:
4765 case Intrinsic::amdgcn_cvt_scalef32_pk32_fp6_f32:
4766 case Intrinsic::amdgcn_cvt_scalef32_pk32_bf6_f32:
4767 case Intrinsic::amdgcn_cvt_scalef32_f16_fp8:
4768 case Intrinsic::amdgcn_cvt_scalef32_f16_bf8:
4769 case Intrinsic::amdgcn_cvt_scalef32_f32_fp8:
4770 case Intrinsic::amdgcn_cvt_scalef32_f32_bf8:
4771 case Intrinsic::amdgcn_cvt_scalef32_pk_fp8_f32:
4772 case Intrinsic::amdgcn_cvt_scalef32_pk_bf8_f32:
4773 case Intrinsic::amdgcn_cvt_scalef32_pk_f32_fp8:
4774 case Intrinsic::amdgcn_cvt_scalef32_pk_f32_bf8:
4775 case Intrinsic::amdgcn_cvt_scalef32_pk_fp8_f16:
4776 case Intrinsic::amdgcn_cvt_scalef32_pk_fp8_bf16:
4777 case Intrinsic::amdgcn_cvt_scalef32_pk_bf8_f16:
4778 case Intrinsic::amdgcn_cvt_scalef32_pk_bf8_bf16:
4779 case Intrinsic::amdgcn_cvt_scalef32_pk_f32_fp4:
4780 case Intrinsic::amdgcn_cvt_scalef32_pk_fp4_f32:
4781 case Intrinsic::amdgcn_cvt_scalef32_pk_f16_fp4:
4782 case Intrinsic::amdgcn_cvt_scalef32_pk_bf16_fp4:
4783 case Intrinsic::amdgcn_cvt_scalef32_pk32_f32_fp6:
4784 case Intrinsic::amdgcn_cvt_scalef32_pk32_f32_bf6:
4785 case Intrinsic::amdgcn_cvt_scalef32_pk32_f16_bf6:
4786 case Intrinsic::amdgcn_cvt_scalef32_pk32_bf16_bf6:
4787 case Intrinsic::amdgcn_cvt_scalef32_pk32_f16_fp6:
4788 case Intrinsic::amdgcn_cvt_scalef32_pk32_bf16_fp6:
4789 case Intrinsic::amdgcn_cvt_scalef32_pk_f16_bf8:
4790 case Intrinsic::amdgcn_cvt_scalef32_pk_bf16_bf8:
4791 case Intrinsic::amdgcn_cvt_scalef32_pk_f16_fp8:
4792 case Intrinsic::amdgcn_cvt_scalef32_pk_bf16_fp8:
4793 case Intrinsic::amdgcn_cvt_scalef32_pk_fp4_f16:
4794 case Intrinsic::amdgcn_cvt_scalef32_pk_fp4_bf16:
4795 case Intrinsic::amdgcn_cvt_scalef32_sr_pk_fp4_f16:
4796 case Intrinsic::amdgcn_cvt_scalef32_sr_pk_fp4_bf16:
4797 case Intrinsic::amdgcn_cvt_scalef32_sr_pk_fp4_f32:
4798 case Intrinsic::amdgcn_cvt_scalef32_sr_pk32_bf6_bf16:
4799 case Intrinsic::amdgcn_cvt_scalef32_sr_pk32_bf6_f16:
4800 case Intrinsic::amdgcn_cvt_scalef32_sr_pk32_bf6_f32:
4801 case Intrinsic::amdgcn_cvt_scalef32_sr_pk32_fp6_bf16:
4802 case Intrinsic::amdgcn_cvt_scalef32_sr_pk32_fp6_f16:
4803 case Intrinsic::amdgcn_cvt_scalef32_sr_pk32_fp6_f32:
4804 case Intrinsic::amdgcn_cvt_scalef32_sr_bf8_bf16:
4805 case Intrinsic::amdgcn_cvt_scalef32_sr_bf8_f16:
4806 case Intrinsic::amdgcn_cvt_scalef32_sr_bf8_f32:
4807 case Intrinsic::amdgcn_cvt_scalef32_sr_fp8_bf16:
4808 case Intrinsic::amdgcn_cvt_scalef32_sr_fp8_f16:
4809 case Intrinsic::amdgcn_cvt_scalef32_sr_fp8_f32:
4810 case Intrinsic::amdgcn_ashr_pk_i8_i32:
4811 case Intrinsic::amdgcn_ashr_pk_u8_i32:
4812 case Intrinsic::amdgcn_cvt_scalef32_2xpk16_fp6_f32:
4813 case Intrinsic::amdgcn_cvt_scalef32_2xpk16_bf6_f32:
4814 case Intrinsic::amdgcn_wmma_bf16_16x16x16_bf16:
4815 case Intrinsic::amdgcn_wmma_f16_16x16x16_f16:
4816 case Intrinsic::amdgcn_wmma_bf16_16x16x16_bf16_tied:
4817 case Intrinsic::amdgcn_wmma_f16_16x16x16_f16_tied:
4818 case Intrinsic::amdgcn_wmma_f32_16x16x16_bf16:
4819 case Intrinsic::amdgcn_wmma_f32_16x16x16_f16:
4820 case Intrinsic::amdgcn_wmma_i32_16x16x16_iu4:
4821 case Intrinsic::amdgcn_wmma_i32_16x16x16_iu8:
4822 case Intrinsic::amdgcn_wmma_f32_16x16x16_fp8_fp8:
4823 case Intrinsic::amdgcn_wmma_f32_16x16x16_fp8_bf8:
4824 case Intrinsic::amdgcn_wmma_f32_16x16x16_bf8_fp8:
4825 case Intrinsic::amdgcn_wmma_f32_16x16x16_bf8_bf8:
4826 case Intrinsic::amdgcn_wmma_i32_16x16x32_iu4:
4827 case Intrinsic::amdgcn_swmmac_f32_16x16x32_f16:
4828 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf16:
4829 case Intrinsic::amdgcn_swmmac_f16_16x16x32_f16:
4830 case Intrinsic::amdgcn_swmmac_bf16_16x16x32_bf16:
4831 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu8:
4832 case Intrinsic::amdgcn_swmmac_i32_16x16x32_iu4:
4833 case Intrinsic::amdgcn_swmmac_i32_16x16x64_iu4:
4834 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_fp8:
4835 case Intrinsic::amdgcn_swmmac_f32_16x16x32_fp8_bf8:
4836 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_fp8:
4837 case Intrinsic::amdgcn_swmmac_f32_16x16x32_bf8_bf8:
4838 case Intrinsic::amdgcn_wmma_f64_16x16x4_f64:
4839 case Intrinsic::amdgcn_wmma_f32_16x16x4_f32:
4840 case Intrinsic::amdgcn_wmma_f32_16x16x32_bf16:
4841 case Intrinsic::amdgcn_wmma_f32_16x16x32_f16:
4842 case Intrinsic::amdgcn_wmma_f16_16x16x32_f16:
4843 case Intrinsic::amdgcn_wmma_bf16_16x16x32_bf16:
4844 case Intrinsic::amdgcn_wmma_bf16f32_16x16x32_bf16:
4845 case Intrinsic::amdgcn_wmma_f32_16x16x64_fp8_fp8:
4846 case Intrinsic::amdgcn_wmma_f32_16x16x64_fp8_bf8:
4847 case Intrinsic::amdgcn_wmma_f32_16x16x64_bf8_fp8:
4848 case Intrinsic::amdgcn_wmma_f32_16x16x64_bf8_bf8:
4849 case Intrinsic::amdgcn_wmma_f16_16x16x64_fp8_fp8:
4850 case Intrinsic::amdgcn_wmma_f16_16x16x64_fp8_bf8:
4851 case Intrinsic::amdgcn_wmma_f16_16x16x64_bf8_fp8:
4852 case Intrinsic::amdgcn_wmma_f16_16x16x64_bf8_bf8:
4853 case Intrinsic::amdgcn_wmma_f16_16x16x128_fp8_fp8:
4854 case Intrinsic::amdgcn_wmma_f16_16x16x128_fp8_bf8:
4855 case Intrinsic::amdgcn_wmma_f16_16x16x128_bf8_fp8:
4856 case Intrinsic::amdgcn_wmma_f16_16x16x128_bf8_bf8:
4857 case Intrinsic::amdgcn_wmma_f32_16x16x128_fp8_fp8:
4858 case Intrinsic::amdgcn_wmma_f32_16x16x128_fp8_bf8:
4859 case Intrinsic::amdgcn_wmma_f32_16x16x128_bf8_fp8:
4860 case Intrinsic::amdgcn_wmma_f32_16x16x128_bf8_bf8:
4861 case Intrinsic::amdgcn_wmma_i32_16x16x64_iu8:
4862 case Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4:
4863 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
4864 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4:
4865 case Intrinsic::amdgcn_wmma_f32_32x16x128_f4:
4866 case Intrinsic::amdgcn_wmma_scale_f32_32x16x128_f4:
4867 case Intrinsic::amdgcn_wmma_scale16_f32_32x16x128_f4:
4868 case Intrinsic::amdgcn_swmmac_f16_16x16x64_f16:
4869 case Intrinsic::amdgcn_swmmac_bf16_16x16x64_bf16:
4870 case Intrinsic::amdgcn_swmmac_f32_16x16x64_bf16:
4871 case Intrinsic::amdgcn_swmmac_bf16f32_16x16x64_bf16:
4872 case Intrinsic::amdgcn_swmmac_f32_16x16x64_f16:
4873 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_fp8:
4874 case Intrinsic::amdgcn_swmmac_f32_16x16x128_fp8_bf8:
4875 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_fp8:
4876 case Intrinsic::amdgcn_swmmac_f32_16x16x128_bf8_bf8:
4877 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_fp8:
4878 case Intrinsic::amdgcn_swmmac_f16_16x16x128_fp8_bf8:
4879 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_fp8:
4880 case Intrinsic::amdgcn_swmmac_f16_16x16x128_bf8_bf8:
4881 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
4882 case Intrinsic::amdgcn_perm_pk16_b4_u4:
4883 case Intrinsic::amdgcn_perm_pk16_b6_u4:
4884 case Intrinsic::amdgcn_perm_pk16_b8_u4:
4885 case Intrinsic::amdgcn_add_max_i32:
4886 case Intrinsic::amdgcn_add_max_u32:
4887 case Intrinsic::amdgcn_add_min_i32:
4888 case Intrinsic::amdgcn_add_min_u32:
4889 case Intrinsic::amdgcn_pk_add_max_i16:
4890 case Intrinsic::amdgcn_pk_add_max_u16:
4891 case Intrinsic::amdgcn_pk_add_min_i16:
4892 case Intrinsic::amdgcn_pk_add_min_u16:
4893 return getDefaultMappingVOP(MI);
4894 case Intrinsic::amdgcn_log:
4895 case Intrinsic::amdgcn_exp2:
4896 case Intrinsic::amdgcn_rcp:
4897 case Intrinsic::amdgcn_rsq:
4898 case Intrinsic::amdgcn_sqrt: {
4899 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4900 unsigned Size = Ty.getSizeInBits();
4901 // There is no pseudo scalar transcendental instruction for bf16.
4902 if (Subtarget.hasPseudoScalarTrans() && !Ty.isBFloat16() &&
4903 (Size == 16 || Size == 32) && isSALUMapping(MI))
4904 return getDefaultMappingSOP(MI);
4905 return getDefaultMappingVOP(MI);
4906 }
4907 case Intrinsic::amdgcn_sbfe:
4908 case Intrinsic::amdgcn_ubfe:
4909 if (isSALUMapping(MI))
4910 return getDefaultMappingSOP(MI);
4911 return getDefaultMappingVOP(MI);
4912 case Intrinsic::amdgcn_ds_swizzle:
4913 case Intrinsic::amdgcn_ds_permute:
4914 case Intrinsic::amdgcn_ds_bpermute:
4915 case Intrinsic::amdgcn_update_dpp:
4916 case Intrinsic::amdgcn_mov_dpp8:
4917 case Intrinsic::amdgcn_mov_dpp:
4918 case Intrinsic::amdgcn_strict_wwm:
4919 case Intrinsic::amdgcn_wwm:
4920 case Intrinsic::amdgcn_strict_wqm:
4921 case Intrinsic::amdgcn_wqm:
4922 case Intrinsic::amdgcn_softwqm:
4923 case Intrinsic::amdgcn_set_inactive:
4924 case Intrinsic::amdgcn_set_inactive_chain_arg:
4925 case Intrinsic::amdgcn_permlane64:
4926 case Intrinsic::amdgcn_ds_bpermute_fi_b32:
4928 case Intrinsic::amdgcn_cvt_pkrtz:
4929 if (Subtarget.hasSALUFloatInsts() && isSALUMapping(MI))
4930 return getDefaultMappingSOP(MI);
4931 return getDefaultMappingVOP(MI);
4932 case Intrinsic::amdgcn_kernarg_segment_ptr:
4933 case Intrinsic::amdgcn_s_getpc:
4934 case Intrinsic::amdgcn_groupstaticsize:
4935 case Intrinsic::amdgcn_reloc_constant:
4936 case Intrinsic::returnaddress: {
4937 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4938 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
4939 break;
4940 }
4941 case Intrinsic::amdgcn_wqm_vote: {
4942 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4943 OpdsMapping[0] = OpdsMapping[2]
4944 = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, Size);
4945 break;
4946 }
4947 case Intrinsic::amdgcn_ps_live: {
4948 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
4949 break;
4950 }
4951 case Intrinsic::amdgcn_div_scale: {
4952 unsigned Dst0Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4953 unsigned Dst1Size = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
4954 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Dst0Size);
4955 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, Dst1Size);
4956
4957 unsigned SrcSize = MRI.getType(MI.getOperand(3).getReg()).getSizeInBits();
4958 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, SrcSize);
4959 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, SrcSize);
4960 break;
4961 }
4962 case Intrinsic::amdgcn_class: {
4963 Register Src0Reg = MI.getOperand(2).getReg();
4964 Register Src1Reg = MI.getOperand(3).getReg();
4965 unsigned Src0Size = MRI.getType(Src0Reg).getSizeInBits();
4966 unsigned Src1Size = MRI.getType(Src1Reg).getSizeInBits();
4967 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4968 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, DstSize);
4969 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Src0Size);
4970 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Src1Size);
4971 break;
4972 }
4973 case Intrinsic::amdgcn_readlane: {
4974 // This must be an SGPR, but accept a VGPR.
4975 Register IdxReg = MI.getOperand(3).getReg();
4976 unsigned IdxSize = MRI.getType(IdxReg).getSizeInBits();
4977 unsigned IdxBank = getRegBankID(IdxReg, MRI, AMDGPU::SGPRRegBankID);
4978 OpdsMapping[3] = AMDGPU::getValueMapping(IdxBank, IdxSize);
4979 [[fallthrough]];
4980 }
4981 case Intrinsic::amdgcn_readfirstlane: {
4982 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4983 unsigned SrcSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
4984 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, DstSize);
4985 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, SrcSize);
4986 break;
4987 }
4988 case Intrinsic::amdgcn_writelane: {
4989 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
4990 Register SrcReg = MI.getOperand(2).getReg();
4991 unsigned SrcSize = MRI.getType(SrcReg).getSizeInBits();
4992 unsigned SrcBank = getRegBankID(SrcReg, MRI, AMDGPU::SGPRRegBankID);
4993 Register IdxReg = MI.getOperand(3).getReg();
4994 unsigned IdxSize = MRI.getType(IdxReg).getSizeInBits();
4995 unsigned IdxBank = getRegBankID(IdxReg, MRI, AMDGPU::SGPRRegBankID);
4996 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
4997
4998 // These 2 must be SGPRs, but accept VGPRs. Readfirstlane will be inserted
4999 // to legalize.
5000 OpdsMapping[2] = AMDGPU::getValueMapping(SrcBank, SrcSize);
5001 OpdsMapping[3] = AMDGPU::getValueMapping(IdxBank, IdxSize);
5002 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, SrcSize);
5003 break;
5004 }
5005 case Intrinsic::amdgcn_if_break: {
5006 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5007 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
5008 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
5009 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
5010 break;
5011 }
5012 case Intrinsic::amdgcn_permlane16:
5013 case Intrinsic::amdgcn_permlanex16: {
5014 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5015 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5016 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5017 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5018 OpdsMapping[4] = getSGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5019 OpdsMapping[5] = getSGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5020 break;
5021 }
5022 case Intrinsic::amdgcn_permlane_bcast:
5023 case Intrinsic::amdgcn_permlane_up:
5024 case Intrinsic::amdgcn_permlane_down:
5025 case Intrinsic::amdgcn_permlane_xor: {
5026 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5027 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5028 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5029 OpdsMapping[3] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5030 OpdsMapping[4] = getSGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5031 break;
5032 }
5033 case Intrinsic::amdgcn_permlane_idx_gen: {
5034 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5035 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5036 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5037 OpdsMapping[3] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5038 break;
5039 }
5040 case Intrinsic::amdgcn_permlane16_var:
5041 case Intrinsic::amdgcn_permlanex16_var: {
5042 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5043 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5044 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5045 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5046 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5047 break;
5048 }
5049 case Intrinsic::amdgcn_mfma_f32_4x4x1f32:
5050 case Intrinsic::amdgcn_mfma_f32_4x4x4f16:
5051 case Intrinsic::amdgcn_mfma_i32_4x4x4i8:
5052 case Intrinsic::amdgcn_mfma_f32_4x4x2bf16:
5053 case Intrinsic::amdgcn_mfma_f32_16x16x1f32:
5054 case Intrinsic::amdgcn_mfma_f32_16x16x4f32:
5055 case Intrinsic::amdgcn_mfma_f32_16x16x4f16:
5056 case Intrinsic::amdgcn_mfma_f32_16x16x16f16:
5057 case Intrinsic::amdgcn_mfma_i32_16x16x4i8:
5058 case Intrinsic::amdgcn_mfma_i32_16x16x16i8:
5059 case Intrinsic::amdgcn_mfma_f32_16x16x2bf16:
5060 case Intrinsic::amdgcn_mfma_f32_16x16x8bf16:
5061 case Intrinsic::amdgcn_mfma_f32_32x32x1f32:
5062 case Intrinsic::amdgcn_mfma_f32_32x32x2f32:
5063 case Intrinsic::amdgcn_mfma_f32_32x32x4f16:
5064 case Intrinsic::amdgcn_mfma_f32_32x32x8f16:
5065 case Intrinsic::amdgcn_mfma_i32_32x32x4i8:
5066 case Intrinsic::amdgcn_mfma_i32_32x32x8i8:
5067 case Intrinsic::amdgcn_mfma_f32_32x32x2bf16:
5068 case Intrinsic::amdgcn_mfma_f32_32x32x4bf16:
5069 case Intrinsic::amdgcn_mfma_f32_32x32x4bf16_1k:
5070 case Intrinsic::amdgcn_mfma_f32_16x16x4bf16_1k:
5071 case Intrinsic::amdgcn_mfma_f32_4x4x4bf16_1k:
5072 case Intrinsic::amdgcn_mfma_f32_32x32x8bf16_1k:
5073 case Intrinsic::amdgcn_mfma_f32_16x16x16bf16_1k:
5074 case Intrinsic::amdgcn_mfma_f64_16x16x4f64:
5075 case Intrinsic::amdgcn_mfma_f64_4x4x4f64:
5076 case Intrinsic::amdgcn_mfma_i32_16x16x32_i8:
5077 case Intrinsic::amdgcn_mfma_i32_32x32x16_i8:
5078 case Intrinsic::amdgcn_mfma_f32_16x16x8_xf32:
5079 case Intrinsic::amdgcn_mfma_f32_32x32x4_xf32:
5080 case Intrinsic::amdgcn_mfma_f32_16x16x32_bf8_bf8:
5081 case Intrinsic::amdgcn_mfma_f32_16x16x32_bf8_fp8:
5082 case Intrinsic::amdgcn_mfma_f32_16x16x32_fp8_bf8:
5083 case Intrinsic::amdgcn_mfma_f32_16x16x32_fp8_fp8:
5084 case Intrinsic::amdgcn_mfma_f32_32x32x16_bf8_bf8:
5085 case Intrinsic::amdgcn_mfma_f32_32x32x16_bf8_fp8:
5086 case Intrinsic::amdgcn_mfma_f32_32x32x16_fp8_bf8:
5087 case Intrinsic::amdgcn_mfma_f32_32x32x16_fp8_fp8:
5088 case Intrinsic::amdgcn_mfma_f32_16x16x32_f16:
5089 case Intrinsic::amdgcn_mfma_f32_32x32x16_f16:
5090 case Intrinsic::amdgcn_mfma_i32_16x16x64_i8:
5091 case Intrinsic::amdgcn_mfma_i32_32x32x32_i8:
5092 case Intrinsic::amdgcn_mfma_f32_16x16x32_bf16: {
5093 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5094 unsigned MinNumRegsRequired = DstSize / 32;
5095
5096 // Default for MAI intrinsics.
5097 // srcC can also be an immediate which can be folded later.
5098 // FIXME: Should we eventually add an alternative mapping with AGPR src
5099 // for srcA/srcB?
5100 //
5101 // vdst, srcA, srcB, srcC
5103
5104 bool UseAGPRForm = !Subtarget.hasGFX90AInsts() ||
5105 Info->selectAGPRFormMFMA(MinNumRegsRequired);
5106
5107 OpdsMapping[0] =
5108 UseAGPRForm ? getAGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI)
5109 : getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5110 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5111 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5112 OpdsMapping[4] =
5113 UseAGPRForm ? getAGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI)
5114 : getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5115 break;
5116 }
5117 case Intrinsic::amdgcn_mfma_scale_f32_16x16x128_f8f6f4:
5118 case Intrinsic::amdgcn_mfma_scale_f32_32x32x64_f8f6f4: {
5119 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5120 unsigned MinNumRegsRequired = DstSize / 32;
5121
5123 bool UseAGPRForm = Info->selectAGPRFormMFMA(MinNumRegsRequired);
5124
5125 OpdsMapping[0] =
5126 UseAGPRForm ? getAGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI)
5127 : getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5128
5129 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5130 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5131 OpdsMapping[4] =
5132 UseAGPRForm ? getAGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI)
5133 : getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5134
5135 OpdsMapping[8] = getVGPROpMapping(MI.getOperand(8).getReg(), MRI, *TRI);
5136 OpdsMapping[10] = getVGPROpMapping(MI.getOperand(10).getReg(), MRI, *TRI);
5137 break;
5138 }
5139 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
5140 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
5141 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
5142 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
5143 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
5144 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
5145 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
5146 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
5147 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
5148 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
5149 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
5150 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
5151 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
5152 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
5153 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
5154 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
5155 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
5156 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
5157 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
5158 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
5159 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
5160 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
5161 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
5162 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
5163 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
5164 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
5165 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
5166 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8: {
5167 Register DstReg = MI.getOperand(0).getReg();
5168 unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
5169 unsigned MinNumRegsRequired = DstSize / 32;
5171 bool UseAGPRForm = Info->selectAGPRFormMFMA(MinNumRegsRequired);
5172
5173 // vdst, srcA, srcB, srcC, idx
5174 OpdsMapping[0] = UseAGPRForm ? getAGPROpMapping(DstReg, MRI, *TRI)
5175 : getVGPROpMapping(DstReg, MRI, *TRI);
5176
5177 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5178 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5179 OpdsMapping[4] =
5180 UseAGPRForm ? getAGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI)
5181 : getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5182 OpdsMapping[5] = getVGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
5183 break;
5184 }
5185 case Intrinsic::amdgcn_interp_p1:
5186 case Intrinsic::amdgcn_interp_p2:
5187 case Intrinsic::amdgcn_interp_mov:
5188 case Intrinsic::amdgcn_interp_p1_f16:
5189 case Intrinsic::amdgcn_interp_p2_f16:
5190 case Intrinsic::amdgcn_lds_param_load: {
5191 const int M0Idx = MI.getNumOperands() - 1;
5192 Register M0Reg = MI.getOperand(M0Idx).getReg();
5193 unsigned M0Bank = getRegBankID(M0Reg, MRI, AMDGPU::SGPRRegBankID);
5194 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5195
5196 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5197 for (int I = 2; I != M0Idx && MI.getOperand(I).isReg(); ++I)
5198 OpdsMapping[I] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5199
5200 // Must be SGPR, but we must take whatever the original bank is and fix it
5201 // later.
5202 OpdsMapping[M0Idx] = AMDGPU::getValueMapping(M0Bank, 32);
5203 break;
5204 }
5205 case Intrinsic::amdgcn_interp_inreg_p10:
5206 case Intrinsic::amdgcn_interp_inreg_p2:
5207 case Intrinsic::amdgcn_interp_inreg_p10_f16:
5208 case Intrinsic::amdgcn_interp_inreg_p2_f16:
5209 case Intrinsic::amdgcn_interp_p10_rtz_f16:
5210 case Intrinsic::amdgcn_interp_p2_rtz_f16: {
5211 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5212 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5213 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5214 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5215 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5216 break;
5217 }
5218 case Intrinsic::amdgcn_permlane16_swap:
5219 case Intrinsic::amdgcn_permlane32_swap: {
5220 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5221 OpdsMapping[0] = OpdsMapping[1] = OpdsMapping[3] = OpdsMapping[4] =
5222 AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5223 break;
5224 }
5225 case Intrinsic::amdgcn_ballot: {
5226 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5227 unsigned SrcSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
5228 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, DstSize);
5229 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, SrcSize);
5230 break;
5231 }
5232 case Intrinsic::amdgcn_inverse_ballot: {
5233 // This must be an SGPR, but accept a VGPR.
5234 Register MaskReg = MI.getOperand(2).getReg();
5235 unsigned MaskSize = MRI.getType(MaskReg).getSizeInBits();
5236 unsigned MaskBank = getRegBankID(MaskReg, MRI, AMDGPU::SGPRRegBankID);
5237 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
5238 OpdsMapping[2] = AMDGPU::getValueMapping(MaskBank, MaskSize);
5239 break;
5240 }
5241 case Intrinsic::amdgcn_bitop3: {
5242 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5243 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5244 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5245 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5246 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5247 break;
5248 }
5249 case Intrinsic::amdgcn_s_quadmask:
5250 case Intrinsic::amdgcn_s_wqm: {
5251 Register MaskReg = MI.getOperand(2).getReg();
5252 unsigned MaskSize = MRI.getType(MaskReg).getSizeInBits();
5253 unsigned MaskBank = getRegBankID(MaskReg, MRI, AMDGPU::SGPRRegBankID);
5254 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, MaskSize);
5255 OpdsMapping[2] = AMDGPU::getValueMapping(MaskBank, MaskSize);
5256 break;
5257 }
5258 case Intrinsic::amdgcn_wave_reduce_add:
5259 case Intrinsic::amdgcn_wave_reduce_fadd:
5260 case Intrinsic::amdgcn_wave_reduce_sub:
5261 case Intrinsic::amdgcn_wave_reduce_fsub:
5262 case Intrinsic::amdgcn_wave_reduce_min:
5263 case Intrinsic::amdgcn_wave_reduce_umin:
5264 case Intrinsic::amdgcn_wave_reduce_fmin:
5265 case Intrinsic::amdgcn_wave_reduce_max:
5266 case Intrinsic::amdgcn_wave_reduce_umax:
5267 case Intrinsic::amdgcn_wave_reduce_fmax:
5268 case Intrinsic::amdgcn_wave_reduce_and:
5269 case Intrinsic::amdgcn_wave_reduce_or:
5270 case Intrinsic::amdgcn_wave_reduce_xor: {
5271 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5272 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, DstSize);
5273 unsigned OpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
5274 auto regBankID =
5275 isSALUMapping(MI) ? AMDGPU::SGPRRegBankID : AMDGPU::VGPRRegBankID;
5276 OpdsMapping[2] = AMDGPU::getValueMapping(regBankID, OpSize);
5277 break;
5278 }
5279 case Intrinsic::amdgcn_s_bitreplicate: {
5280 Register MaskReg = MI.getOperand(2).getReg();
5281 unsigned MaskBank = getRegBankID(MaskReg, MRI, AMDGPU::SGPRRegBankID);
5282 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 64);
5283 OpdsMapping[2] = AMDGPU::getValueMapping(MaskBank, 32);
5284 break;
5285 }
5286 case Intrinsic::amdgcn_wave_shuffle: {
5287 unsigned OpSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5288 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, OpSize);
5289 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, OpSize);
5290 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, OpSize);
5291 break;
5292 }
5293 }
5294 break;
5295 }
5296 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
5297 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
5298 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
5299 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
5300 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
5301 auto IntrID = AMDGPU::getIntrinsicID(MI);
5302 const AMDGPU::RsrcIntrinsic *RSrcIntrin = AMDGPU::lookupRsrcIntrinsic(IntrID);
5303 assert(RSrcIntrin && "missing RsrcIntrinsic for image intrinsic");
5304 // Non-images can have complications from operands that allow both SGPR
5305 // and VGPR. For now it's too complicated to figure out the final opcode
5306 // to derive the register bank from the MCInstrDesc.
5307 assert(RSrcIntrin->IsImage);
5308 return getImageMapping(MRI, MI, RSrcIntrin->RsrcArg);
5309 }
5310 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
5311 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
5312 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY: {
5313 bool IsDualOrBVH8 =
5314 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY ||
5315 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY;
5316 unsigned NumMods = IsDualOrBVH8 ? 0 : 1; // Has A16 modifier
5317 unsigned LastRegOpIdx = MI.getNumExplicitOperands() - 1 - NumMods;
5318 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5319 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5320 if (IsDualOrBVH8) {
5321 OpdsMapping[1] = AMDGPU::getValueMapping(
5322 AMDGPU::VGPRRegBankID,
5323 MRI.getType(MI.getOperand(1).getReg()).getSizeInBits());
5324 OpdsMapping[2] = AMDGPU::getValueMapping(
5325 AMDGPU::VGPRRegBankID,
5326 MRI.getType(MI.getOperand(2).getReg()).getSizeInBits());
5327 }
5328 OpdsMapping[LastRegOpIdx] =
5329 getSGPROpMapping(MI.getOperand(LastRegOpIdx).getReg(), MRI, *TRI);
5330 if (LastRegOpIdx == 3) {
5331 // Sequential form: all operands combined into VGPR256/VGPR512
5332 unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
5333 if (Size > 256)
5334 Size = 512;
5335 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5336 } else {
5337 // NSA form
5338 unsigned FirstSrcOpIdx = IsDualOrBVH8 ? 4 : 2;
5339 for (unsigned I = FirstSrcOpIdx; I < LastRegOpIdx; ++I) {
5340 unsigned Size = MRI.getType(MI.getOperand(I).getReg()).getSizeInBits();
5341 OpdsMapping[I] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5342 }
5343 }
5344 break;
5345 }
5346 case AMDGPU::G_INTRINSIC_W_SIDE_EFFECTS:
5347 case AMDGPU::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS: {
5348 auto IntrID = cast<GIntrinsic>(MI).getIntrinsicID();
5349 switch (IntrID) {
5350 case Intrinsic::amdgcn_s_getreg:
5351 case Intrinsic::amdgcn_s_memtime:
5352 case Intrinsic::amdgcn_s_memrealtime:
5353 case Intrinsic::amdgcn_s_get_waveid_in_workgroup:
5354 case Intrinsic::amdgcn_s_sendmsg_rtn: {
5355 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5356 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
5357 break;
5358 }
5359 case Intrinsic::amdgcn_global_atomic_fmin_num:
5360 case Intrinsic::amdgcn_global_atomic_fmax_num:
5361 case Intrinsic::amdgcn_flat_atomic_fmin_num:
5362 case Intrinsic::amdgcn_flat_atomic_fmax_num:
5363 case Intrinsic::amdgcn_global_atomic_ordered_add_b64:
5364 case Intrinsic::amdgcn_global_load_tr_b64:
5365 case Intrinsic::amdgcn_global_load_tr_b128:
5366 case Intrinsic::amdgcn_global_load_tr4_b64:
5367 case Intrinsic::amdgcn_global_load_tr6_b96:
5368 case Intrinsic::amdgcn_ds_load_tr8_b64:
5369 case Intrinsic::amdgcn_ds_load_tr16_b128:
5370 case Intrinsic::amdgcn_ds_load_tr4_b64:
5371 case Intrinsic::amdgcn_ds_load_tr6_b96:
5372 case Intrinsic::amdgcn_ds_read_tr4_b64:
5373 case Intrinsic::amdgcn_ds_read_tr6_b96:
5374 case Intrinsic::amdgcn_ds_read_tr8_b64:
5375 case Intrinsic::amdgcn_ds_read_tr16_b64:
5376 case Intrinsic::amdgcn_ds_atomic_async_barrier_arrive_b64:
5377 case Intrinsic::amdgcn_ds_atomic_barrier_arrive_rtn_b64:
5379 case Intrinsic::amdgcn_ds_ordered_add:
5380 case Intrinsic::amdgcn_ds_ordered_swap: {
5381 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5382 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5383 unsigned M0Bank = getRegBankID(MI.getOperand(2).getReg(), MRI,
5384 AMDGPU::SGPRRegBankID);
5385 OpdsMapping[2] = AMDGPU::getValueMapping(M0Bank, 32);
5386 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5387 break;
5388 }
5389 case Intrinsic::amdgcn_ds_append:
5390 case Intrinsic::amdgcn_ds_consume: {
5391 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5392 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5393 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5394 break;
5395 }
5396 case Intrinsic::amdgcn_exp_compr:
5397 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5398 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5399 break;
5400 case Intrinsic::amdgcn_exp:
5401 // FIXME: Could we support packed types here?
5402 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5403 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5404 OpdsMapping[5] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5405 OpdsMapping[6] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5406 break;
5407 case Intrinsic::amdgcn_exp_row:
5408 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5409 OpdsMapping[4] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5410 OpdsMapping[5] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5411 OpdsMapping[6] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5412 OpdsMapping[8] = getSGPROpMapping(MI.getOperand(8).getReg(), MRI, *TRI);
5413 break;
5414 case Intrinsic::amdgcn_s_alloc_vgpr:
5415 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 1);
5416 OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 32);
5417 break;
5418 case Intrinsic::amdgcn_s_sendmsg:
5419 case Intrinsic::amdgcn_s_sendmsghalt: {
5420 // This must be an SGPR, but accept a VGPR.
5421 unsigned Bank = getRegBankID(MI.getOperand(2).getReg(), MRI,
5422 AMDGPU::SGPRRegBankID);
5423 OpdsMapping[2] = AMDGPU::getValueMapping(Bank, 32);
5424 break;
5425 }
5426 case Intrinsic::amdgcn_s_setreg: {
5427 // This must be an SGPR, but accept a VGPR.
5428 unsigned Bank = getRegBankID(MI.getOperand(2).getReg(), MRI,
5429 AMDGPU::SGPRRegBankID);
5430 OpdsMapping[2] = AMDGPU::getValueMapping(Bank, 32);
5431 break;
5432 }
5433 case Intrinsic::amdgcn_s_ttracedata: {
5434 // This must be an SGPR, but accept a VGPR.
5435 unsigned Bank =
5436 getRegBankID(MI.getOperand(1).getReg(), MRI, AMDGPU::SGPRRegBankID);
5437 OpdsMapping[1] = AMDGPU::getValueMapping(Bank, 32);
5438 break;
5439 }
5440 case Intrinsic::amdgcn_end_cf: {
5441 unsigned Size = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
5442 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
5443 break;
5444 }
5445 case Intrinsic::amdgcn_else: {
5446 unsigned WaveSize = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
5447 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
5448 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, WaveSize);
5449 OpdsMapping[3] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, WaveSize);
5450 break;
5451 }
5452 case Intrinsic::amdgcn_init_whole_wave:
5453 case Intrinsic::amdgcn_live_mask: {
5454 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
5455 break;
5456 }
5457 case Intrinsic::amdgcn_wqm_demote:
5458 case Intrinsic::amdgcn_kill: {
5459 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
5460 break;
5461 }
5462 case Intrinsic::amdgcn_ptr_s_buffer_load: {
5463 OpdsMapping[0] = getSGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5464 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5465 OpdsMapping[3] = getSGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5466 break;
5467 }
5468 case Intrinsic::amdgcn_raw_buffer_load:
5469 case Intrinsic::amdgcn_raw_ptr_buffer_load:
5470 case Intrinsic::amdgcn_raw_atomic_buffer_load:
5471 case Intrinsic::amdgcn_raw_ptr_atomic_buffer_load:
5472 case Intrinsic::amdgcn_raw_tbuffer_load:
5473 case Intrinsic::amdgcn_raw_ptr_tbuffer_load: {
5474 // FIXME: Should make intrinsic ID the last operand of the instruction,
5475 // then this would be the same as store
5476 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5477 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5478 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5479 OpdsMapping[4] = getSGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5480 break;
5481 }
5482 case Intrinsic::amdgcn_raw_buffer_load_lds:
5483 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
5484 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
5485 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds: {
5486 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5487 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5488 OpdsMapping[4] = getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5489 OpdsMapping[5] = getSGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
5490 break;
5491 }
5492 case Intrinsic::amdgcn_raw_buffer_store:
5493 case Intrinsic::amdgcn_raw_ptr_buffer_store:
5494 case Intrinsic::amdgcn_raw_buffer_store_format:
5495 case Intrinsic::amdgcn_raw_ptr_buffer_store_format:
5496 case Intrinsic::amdgcn_raw_tbuffer_store:
5497 case Intrinsic::amdgcn_raw_ptr_tbuffer_store: {
5498 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5499 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5500 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5501 OpdsMapping[4] = getSGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5502 break;
5503 }
5504 case Intrinsic::amdgcn_struct_buffer_load:
5505 case Intrinsic::amdgcn_struct_ptr_buffer_load:
5506 case Intrinsic::amdgcn_struct_tbuffer_load:
5507 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:
5508 case Intrinsic::amdgcn_struct_atomic_buffer_load:
5509 case Intrinsic::amdgcn_struct_ptr_atomic_buffer_load: {
5510 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5511 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5512 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5513 OpdsMapping[4] = getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5514 OpdsMapping[5] = getSGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
5515 break;
5516 }
5517 case Intrinsic::amdgcn_struct_buffer_load_lds:
5518 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
5519 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
5520 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
5521 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5522 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5523 OpdsMapping[4] = getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5524 OpdsMapping[5] = getVGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
5525 OpdsMapping[6] = getSGPROpMapping(MI.getOperand(6).getReg(), MRI, *TRI);
5526 break;
5527 }
5528 case Intrinsic::amdgcn_struct_buffer_store:
5529 case Intrinsic::amdgcn_struct_ptr_buffer_store:
5530 case Intrinsic::amdgcn_struct_tbuffer_store:
5531 case Intrinsic::amdgcn_struct_ptr_tbuffer_store: {
5532 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5533 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5534 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5535 OpdsMapping[4] = getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI);
5536 OpdsMapping[5] = getSGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI);
5537 break;
5538 }
5539 case Intrinsic::amdgcn_init_exec_from_input: {
5540 unsigned Size = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
5541 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size);
5542 break;
5543 }
5544 case Intrinsic::amdgcn_ds_gws_init:
5545 case Intrinsic::amdgcn_ds_gws_barrier:
5546 case Intrinsic::amdgcn_ds_gws_sema_br: {
5547 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5548
5549 // This must be an SGPR, but accept a VGPR.
5550 unsigned Bank = getRegBankID(MI.getOperand(2).getReg(), MRI,
5551 AMDGPU::SGPRRegBankID);
5552 OpdsMapping[2] = AMDGPU::getValueMapping(Bank, 32);
5553 break;
5554 }
5555 case Intrinsic::amdgcn_ds_gws_sema_v:
5556 case Intrinsic::amdgcn_ds_gws_sema_p:
5557 case Intrinsic::amdgcn_ds_gws_sema_release_all: {
5558 // This must be an SGPR, but accept a VGPR.
5559 unsigned Bank = getRegBankID(MI.getOperand(1).getReg(), MRI,
5560 AMDGPU::SGPRRegBankID);
5561 OpdsMapping[1] = AMDGPU::getValueMapping(Bank, 32);
5562 break;
5563 }
5564 case Intrinsic::amdgcn_cluster_load_b32:
5565 case Intrinsic::amdgcn_cluster_load_b64:
5566 case Intrinsic::amdgcn_cluster_load_b128: {
5567 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5568 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5569 unsigned M0Bank =
5570 getRegBankID(MI.getOperand(4).getReg(), MRI, AMDGPU::SGPRRegBankID);
5571 OpdsMapping[4] = AMDGPU::getValueMapping(M0Bank, 32);
5572 break;
5573 }
5574 case Intrinsic::amdgcn_cluster_load_async_to_lds_b8:
5575 case Intrinsic::amdgcn_cluster_load_async_to_lds_b32:
5576 case Intrinsic::amdgcn_cluster_load_async_to_lds_b64:
5577 case Intrinsic::amdgcn_cluster_load_async_to_lds_b128: {
5578 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5579 // LDS address goes into $vdst (VGPR).
5580 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5581 unsigned M0Bank =
5582 getRegBankID(MI.getOperand(5).getReg(), MRI, AMDGPU::SGPRRegBankID);
5583 OpdsMapping[5] = AMDGPU::getValueMapping(M0Bank, 32);
5584 break;
5585 }
5586 case Intrinsic::amdgcn_global_store_async_from_lds_b8:
5587 case Intrinsic::amdgcn_global_store_async_from_lds_b32:
5588 case Intrinsic::amdgcn_global_store_async_from_lds_b64:
5589 case Intrinsic::amdgcn_global_store_async_from_lds_b128:
5590 case Intrinsic::amdgcn_global_load_async_to_lds_b8:
5591 case Intrinsic::amdgcn_global_load_async_to_lds_b32:
5592 case Intrinsic::amdgcn_global_load_async_to_lds_b64:
5593 case Intrinsic::amdgcn_global_load_async_to_lds_b128: {
5594 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5595 // LDS address goes into $vdst/$vdata (VGPR).
5596 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5597 break;
5598 }
5599 case Intrinsic::amdgcn_load_to_lds:
5600 case Intrinsic::amdgcn_load_async_to_lds:
5601 case Intrinsic::amdgcn_global_load_lds:
5602 case Intrinsic::amdgcn_global_load_async_lds: {
5603 OpdsMapping[1] = getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5604 // LDS address goes into M0 (SGPR).
5605 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5606 break;
5607 }
5608 case Intrinsic::amdgcn_lds_direct_load: {
5609 const int M0Idx = MI.getNumOperands() - 1;
5610 Register M0Reg = MI.getOperand(M0Idx).getReg();
5611 unsigned M0Bank = getRegBankID(M0Reg, MRI, AMDGPU::SGPRRegBankID);
5612 unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5613
5614 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize);
5615 for (int I = 2; I != M0Idx && MI.getOperand(I).isReg(); ++I)
5616 OpdsMapping[I] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32);
5617
5618 // Must be SGPR, but we must take whatever the original bank is and fix it
5619 // later.
5620 OpdsMapping[M0Idx] = AMDGPU::getValueMapping(M0Bank, 32);
5621 break;
5622 }
5623 case Intrinsic::amdgcn_ds_add_gs_reg_rtn:
5624 case Intrinsic::amdgcn_ds_sub_gs_reg_rtn:
5625 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5626 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5627 break;
5628 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
5629 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
5630 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
5631 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn: {
5632 OpdsMapping[0] =
5633 getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI); // %vdst
5634 OpdsMapping[1] =
5635 getVGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI); // %addr
5636 OpdsMapping[3] =
5637 getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI); // %addr
5638 OpdsMapping[4] =
5639 getVGPROpMapping(MI.getOperand(4).getReg(), MRI, *TRI); // %data0
5640 OpdsMapping[5] =
5641 getVGPROpMapping(MI.getOperand(5).getReg(), MRI, *TRI); // %data1
5642 break;
5643 }
5644 case Intrinsic::amdgcn_s_sleep_var:
5645 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5646 break;
5647 case Intrinsic::amdgcn_s_barrier_join:
5648 case Intrinsic::amdgcn_s_wakeup_barrier:
5649 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5650 break;
5651 case Intrinsic::amdgcn_s_barrier_init:
5652 case Intrinsic::amdgcn_s_barrier_signal_var:
5653 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5654 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5655 break;
5656 case Intrinsic::amdgcn_s_barrier_signal_isfirst: {
5657 const unsigned ResultSize = 1;
5658 OpdsMapping[0] =
5659 AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, ResultSize);
5660 break;
5661 }
5662 case Intrinsic::amdgcn_s_get_barrier_state:
5663 case Intrinsic::amdgcn_s_get_named_barrier_state: {
5664 OpdsMapping[0] = getSGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5665 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5666 break;
5667 }
5668 case Intrinsic::amdgcn_pops_exiting_wave_id:
5669 return getDefaultMappingSOP(MI);
5670 case Intrinsic::amdgcn_tensor_load_to_lds:
5671 case Intrinsic::amdgcn_tensor_store_from_lds: {
5672 // Lie and claim everything is legal, even all operands need to be
5673 // SGPRs. applyMapping will have to deal with it with readfirstlane.
5674 for (unsigned I = 1; I < MI.getNumOperands(); ++I) {
5675 if (MI.getOperand(I).isReg()) {
5676 Register Reg = MI.getOperand(I).getReg();
5677 auto OpBank = getRegBankID(Reg, MRI);
5678 unsigned Size = getSizeInBits(Reg, MRI, *TRI);
5679 OpdsMapping[I] = AMDGPU::getValueMapping(OpBank, Size);
5680 }
5681 }
5682 break;
5683 }
5684 case Intrinsic::amdgcn_s_prefetch_data:
5685 case Intrinsic::amdgcn_s_prefetch_inst: {
5686 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5687 OpdsMapping[2] = getSGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5688 break;
5689 }
5690 case Intrinsic::amdgcn_flat_prefetch:
5691 case Intrinsic::amdgcn_global_prefetch:
5692 return getDefaultMappingVOP(MI);
5693 default:
5695 }
5696 break;
5697 }
5698 case AMDGPU::G_SELECT: {
5699 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
5700 unsigned Op2Bank = getRegBankID(MI.getOperand(2).getReg(), MRI,
5701 AMDGPU::SGPRRegBankID);
5702 unsigned Op3Bank = getRegBankID(MI.getOperand(3).getReg(), MRI,
5703 AMDGPU::SGPRRegBankID);
5704 bool SGPRSrcs = Op2Bank == AMDGPU::SGPRRegBankID &&
5705 Op3Bank == AMDGPU::SGPRRegBankID;
5706
5707 unsigned CondBankDefault = SGPRSrcs ?
5708 AMDGPU::SGPRRegBankID : AMDGPU::VCCRegBankID;
5709 unsigned CondBank = getRegBankID(MI.getOperand(1).getReg(), MRI,
5710 CondBankDefault);
5711 if (CondBank == AMDGPU::SGPRRegBankID)
5712 CondBank = SGPRSrcs ? AMDGPU::SGPRRegBankID : AMDGPU::VCCRegBankID;
5713 else if (CondBank == AMDGPU::VGPRRegBankID)
5714 CondBank = AMDGPU::VCCRegBankID;
5715
5716 unsigned Bank = SGPRSrcs && CondBank == AMDGPU::SGPRRegBankID ?
5717 AMDGPU::SGPRRegBankID : AMDGPU::VGPRRegBankID;
5718
5719 assert(CondBank == AMDGPU::VCCRegBankID || CondBank == AMDGPU::SGPRRegBankID);
5720
5721 // TODO: Should report 32-bit for scalar condition type.
5722 if (Size == 64) {
5723 OpdsMapping[0] = AMDGPU::getValueMappingSGPR64Only(Bank, Size);
5724 OpdsMapping[1] = AMDGPU::getValueMapping(CondBank, 1);
5725 OpdsMapping[2] = AMDGPU::getValueMappingSGPR64Only(Bank, Size);
5726 OpdsMapping[3] = AMDGPU::getValueMappingSGPR64Only(Bank, Size);
5727 } else {
5728 OpdsMapping[0] = AMDGPU::getValueMapping(Bank, Size);
5729 OpdsMapping[1] = AMDGPU::getValueMapping(CondBank, 1);
5730 OpdsMapping[2] = AMDGPU::getValueMapping(Bank, Size);
5731 OpdsMapping[3] = AMDGPU::getValueMapping(Bank, Size);
5732 }
5733
5734 break;
5735 }
5736
5737 case AMDGPU::G_SI_CALL: {
5738 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 64);
5739 // Lie and claim everything is legal, even though some need to be
5740 // SGPRs. applyMapping will have to deal with it as a waterfall loop.
5741 OpdsMapping[1] = getSGPROpMapping(MI.getOperand(1).getReg(), MRI, *TRI);
5742
5743 // Allow anything for implicit arguments
5744 for (unsigned I = 4; I < MI.getNumOperands(); ++I) {
5745 if (MI.getOperand(I).isReg()) {
5746 Register Reg = MI.getOperand(I).getReg();
5747 auto OpBank = getRegBankID(Reg, MRI);
5748 unsigned Size = getSizeInBits(Reg, MRI, *TRI);
5749 OpdsMapping[I] = AMDGPU::getValueMapping(OpBank, Size);
5750 }
5751 }
5752 break;
5753 }
5754 case AMDGPU::G_LOAD:
5755 case AMDGPU::G_ZEXTLOAD:
5756 case AMDGPU::G_SEXTLOAD:
5757 return getInstrMappingForLoad(MI);
5758
5759 case AMDGPU::G_ATOMICRMW_XCHG:
5760 case AMDGPU::G_ATOMICRMW_ADD:
5761 case AMDGPU::G_ATOMICRMW_SUB:
5762 case AMDGPU::G_ATOMICRMW_AND:
5763 case AMDGPU::G_ATOMICRMW_OR:
5764 case AMDGPU::G_ATOMICRMW_XOR:
5765 case AMDGPU::G_ATOMICRMW_MAX:
5766 case AMDGPU::G_ATOMICRMW_MIN:
5767 case AMDGPU::G_ATOMICRMW_UMAX:
5768 case AMDGPU::G_ATOMICRMW_UMIN:
5769 case AMDGPU::G_ATOMICRMW_FADD:
5770 case AMDGPU::G_ATOMICRMW_FMIN:
5771 case AMDGPU::G_ATOMICRMW_FMAX:
5772 case AMDGPU::G_ATOMICRMW_UINC_WRAP:
5773 case AMDGPU::G_ATOMICRMW_UDEC_WRAP:
5774 case AMDGPU::G_ATOMICRMW_USUB_COND:
5775 case AMDGPU::G_ATOMICRMW_USUB_SAT:
5776 case AMDGPU::G_AMDGPU_ATOMIC_CMPXCHG: {
5777 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5778 OpdsMapping[1] = getValueMappingForPtr(MRI, MI.getOperand(1).getReg());
5779 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5780 break;
5781 }
5782 case AMDGPU::G_ATOMIC_CMPXCHG: {
5783 OpdsMapping[0] = getVGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5784 OpdsMapping[1] = getValueMappingForPtr(MRI, MI.getOperand(1).getReg());
5785 OpdsMapping[2] = getVGPROpMapping(MI.getOperand(2).getReg(), MRI, *TRI);
5786 OpdsMapping[3] = getVGPROpMapping(MI.getOperand(3).getReg(), MRI, *TRI);
5787 break;
5788 }
5789 case AMDGPU::G_BRCOND: {
5790 unsigned Bank = getRegBankID(MI.getOperand(0).getReg(), MRI,
5791 AMDGPU::SGPRRegBankID);
5792 assert(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 1);
5793 if (Bank != AMDGPU::SGPRRegBankID)
5794 Bank = AMDGPU::VCCRegBankID;
5795
5796 OpdsMapping[0] = AMDGPU::getValueMapping(Bank, 1);
5797 break;
5798 }
5799 case AMDGPU::G_INTRINSIC_FPTRUNC_ROUND:
5800 return getDefaultMappingVOP(MI);
5801 case AMDGPU::G_PREFETCH:
5802 OpdsMapping[0] = getSGPROpMapping(MI.getOperand(0).getReg(), MRI, *TRI);
5803 break;
5804 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP:
5805 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN:
5806 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, 1);
5807 break;
5808 case AMDGPU::G_AMDGPU_FLAT_LOAD_MONITOR:
5809 case AMDGPU::G_AMDGPU_GLOBAL_LOAD_MONITOR: {
5810 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI);
5811 unsigned PtrSize = getSizeInBits(MI.getOperand(1).getReg(), MRI, *TRI);
5812 OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size);
5813 OpdsMapping[1] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, PtrSize);
5814 break;
5815 }
5816 }
5817
5818 return getInstructionMapping(/*ID*/1, /*Cost*/1,
5819 getOperandsMapping(OpdsMapping),
5820 MI.getNumOperands());
5821}
static unsigned getIntrinsicID(const SDNode *N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned 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:223
iterator end()
Definition DenseMap.h:141
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:284
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:309
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:68
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...
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:343
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
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.
@ Kill
The last use of a register.
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:46
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
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:100
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition Alignment.h:197
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
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
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.
The llvm::once_flag structure.
Definition Threading.h:67