LLVM 24.0.0git
SIInstrInfo.cpp
Go to the documentation of this file.
1//===- SIInstrInfo.cpp - SI Instruction Information ----------------------===//
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//
9/// \file
10/// SI Implementation of TargetInstrInfo.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SIInstrInfo.h"
15#include "AMDGPU.h"
16#include "AMDGPUInstrInfo.h"
17#include "AMDGPULaneMaskUtils.h"
18#include "GCNHazardRecognizer.h"
19#include "GCNSubtarget.h"
22#include "llvm/ADT/STLExtras.h"
33#include "llvm/IR/IntrinsicsAMDGPU.h"
34#include "llvm/MC/MCContext.h"
38#include <tuple>
39
40using namespace llvm;
41
42#define DEBUG_TYPE "si-instr-info"
43
44#define GET_INSTRINFO_CTOR_DTOR
45#include "AMDGPUGenInstrInfo.inc"
46
47namespace llvm::AMDGPU {
48#define GET_ImageDimIntrinsicTable_IMPL
49#define GET_RsrcIntrinsics_IMPL
50#define GET_GFX1250BlockingCyclesTable_DECL
51#define GET_GFX1250BlockingCyclesTable_IMPL
52
57
58#include "AMDGPUGenSearchableTables.inc"
59} // namespace llvm::AMDGPU
60
61// Must be at least 4 to be able to branch over minimum unconditional branch
62// code. This is only for making it possible to write reasonably small tests for
63// long branches.
65BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16),
66 cl::desc("Restrict range of branch instructions (DEBUG)"));
67
69 "amdgpu-fix-16-bit-physreg-copies",
70 cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"),
71 cl::init(true),
73
75 : AMDGPUGenInstrInfo(ST, RI, AMDGPU::ADJCALLSTACKUP,
76 AMDGPU::ADJCALLSTACKDOWN),
77 RI(ST), ST(ST) {
78 SchedModel.init(&ST);
79}
80
81//===----------------------------------------------------------------------===//
82// TargetInstrInfo callbacks
83//===----------------------------------------------------------------------===//
84
85static unsigned getNumOperandsNoGlue(SDNode *Node) {
86 unsigned N = Node->getNumOperands();
87 while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
88 --N;
89 return N;
90}
91
92/// Returns true if both nodes have the same value for the given
93/// operand \p Op, or if both nodes do not have this operand.
95 AMDGPU::OpName OpName) {
96 unsigned Opc0 = N0->getMachineOpcode();
97 unsigned Opc1 = N1->getMachineOpcode();
98
99 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName);
100 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName);
101
102 if (Op0Idx == -1 && Op1Idx == -1)
103 return true;
104
105
106 if ((Op0Idx == -1 && Op1Idx != -1) ||
107 (Op1Idx == -1 && Op0Idx != -1))
108 return false;
109
110 // getNamedOperandIdx returns the index for the MachineInstr's operands,
111 // which includes the result as the first operand. We are indexing into the
112 // MachineSDNode's operands, so we need to skip the result operand to get
113 // the real index.
114 --Op0Idx;
115 --Op1Idx;
116
117 return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx);
118}
119
120static bool canRemat(const MachineInstr &MI) {
121
125 return true;
126
127 if (SIInstrInfo::isSMRD(MI)) {
128 return !MI.memoperands_empty() &&
129 llvm::all_of(MI.memoperands(), [](const MachineMemOperand *MMO) {
130 return MMO->isLoad() && MMO->isInvariant();
131 });
132 }
133
134 return false;
135}
136
137// Split relocation flags for 64-bit global-address materialization into a
138// common base and the hi/lo relocation variants.
139static std::tuple<unsigned, unsigned, unsigned>
141 const MachineOperand &SrcOp) {
142 const unsigned BaseFlags = SrcOp.getTargetFlags() & ~SIInstrInfo::MO_MASK;
143 const unsigned Reloc = SrcOp.getTargetFlags() & SIInstrInfo::MO_MASK;
144
145 // Infer the relocation type from the existing flags on the global operand.
146 // The relocation type should have been determined earlier in the pipeline.
147 unsigned LoReloc, HiReloc;
148 switch (Reloc) {
152 LoReloc = SIInstrInfo::MO_REL32_LO;
153 HiReloc = SIInstrInfo::MO_REL32_HI;
154 break;
159 break;
162 // For 64-bit GOT-relative, use the 64-bit relocation.
165 break;
169 LoReloc = SIInstrInfo::MO_ABS32_LO;
170 HiReloc = SIInstrInfo::MO_ABS32_HI;
171 break;
172 default:
173 llvm_unreachable("unknown relocation type for global address");
174 break;
175 }
176
177 return {BaseFlags, LoReloc, HiReloc};
178}
179
181 const MachineInstr &MI) const {
182
183 if (canRemat(MI)) {
184 // Normally VALU use of exec would block the rematerialization, but that
185 // is OK in this case to have an implicit exec read as all VALU do.
186 // We really want all of the generic logic for this except for this.
187
188 // Another potential implicit use is mode register. The core logic of
189 // the RA will not attempt rematerialization if mode is set anywhere
190 // in the function, otherwise it is safe since mode is not changed.
191
192 // There is difference to generic method which does not allow
193 // rematerialization if there are virtual register uses. We allow this,
194 // therefore this method includes SOP instructions as well.
195 if (!MI.hasImplicitDef() &&
196 MI.getNumImplicitOperands() == MI.getDesc().implicit_uses().size() &&
197 !MI.mayRaiseFPException())
198 return true;
199 }
200
201 // Everything below copied from TargetInstrInfo::isReMaterializableImpl. The
202 // only difference is that we allow operations that perform read-modify-write
203 // on sub-registers.
204
205 // Remat clients assume operand 0 is the defined register.
206 if (!MI.getNumOperands() || !MI.getOperand(0).isReg())
207 return false;
208 Register DefReg = MI.getOperand(0).getReg();
209
210 const MachineFunction &MF = *MI.getMF();
211
212 // A load from a fixed stack slot can be rematerialized. This may be
213 // redundant with subsequent checks, but it's target-independent,
214 // simple, and a common case.
215 int FrameIdx = 0;
216 if (isLoadFromStackSlot(MI, FrameIdx) &&
218 return true;
219
220 // Avoid instructions obviously unsafe for remat.
221 if (MI.isNotDuplicable() || MI.mayStore() || MI.mayRaiseFPException() ||
222 MI.hasUnmodeledSideEffects())
223 return false;
224
225 // Don't remat inline asm. We have no idea how expensive it is
226 // even if it's side effect free.
227 if (MI.isInlineAsm())
228 return false;
229
230 // Avoid instructions which load from potentially varying memory.
231 if (MI.mayLoad() && !MI.isDereferenceableInvariantLoad())
232 return false;
233
234 const MachineRegisterInfo &MRI = MF.getRegInfo();
235
236 // If any of the registers accessed are non-constant, conservatively assume
237 // the instruction is not rematerializable.
238 for (const MachineOperand &MO : MI.operands()) {
239 if (!MO.isReg())
240 continue;
241 Register Reg = MO.getReg();
242 if (Reg == 0)
243 continue;
244
245 // Check for a well-behaved physical register.
246 if (Reg.isPhysical()) {
247 if (MO.isUse()) {
248 // If the physreg has no defs anywhere, it's just an ambient register
249 // and we can freely move its uses. Alternatively, if it's allocatable,
250 // it could get allocated to something with a def during allocation.
251 if (!MRI.isConstantPhysReg(Reg))
252 return false;
253 } else {
254 // A physreg def. We can't remat it.
255 return false;
256 }
257 continue;
258 }
259
260 // Only allow one virtual-register def. There may be multiple defs of the
261 // same virtual register, though.
262 if (MO.isDef() && Reg != DefReg)
263 return false;
264 }
265
266 return true;
267}
268
270 switch (Opcode) {
271 // v_subrev_u16 (gfx9)
272 case AMDGPU::V_SUBREV_U16_e32:
273 case AMDGPU::V_SUBREV_U16_e64:
274 // v_subrev_u32 (gfx9) / v_subrev_nc_u32 (gfx10+)
275 case AMDGPU::V_SUBREV_U32_e32:
276 case AMDGPU::V_SUBREV_U32_e64:
277 // v_subrev_co_u32
278 case AMDGPU::V_SUBREV_CO_U32_e32:
279 case AMDGPU::V_SUBREV_CO_U32_e64:
280 // v_subbrev_u32 (gfx9) / v_subrev_co_ci_u32 (gfx10+)
281 case AMDGPU::V_SUBBREV_U32_e32:
282 case AMDGPU::V_SUBBREV_U32_e64:
283 return true;
284 // REV shift opcodes worked this way before GFX11, verified on hardware
285 case AMDGPU::V_ASHRREV_I16_e32:
286 case AMDGPU::V_ASHRREV_I16_e64:
287 case AMDGPU::V_ASHRREV_I32_e32:
288 case AMDGPU::V_ASHRREV_I32_e64:
289 case AMDGPU::V_ASHRREV_I64_e64:
290 case AMDGPU::V_LSHLREV_B16_e32:
291 case AMDGPU::V_LSHLREV_B16_e64:
292 case AMDGPU::V_LSHLREV_B32_e32:
293 case AMDGPU::V_LSHLREV_B32_e64:
294 case AMDGPU::V_LSHLREV_B64_e64:
295 case AMDGPU::V_LSHRREV_B16_e32:
296 case AMDGPU::V_LSHRREV_B16_e64:
297 case AMDGPU::V_LSHRREV_B32_e32:
298 case AMDGPU::V_LSHRREV_B32_e64:
299 case AMDGPU::V_LSHRREV_B64_e64:
300 return !ST.hasGFX11Insts();
301 default:
302 return false;
303 }
304}
305
306// Returns true if the result of a VALU instruction depends on exec.
307bool SIInstrInfo::resultDependsOnExec(const MachineInstr &MI) const {
308 assert(isVALU(MI, /*AllowLDSDMA=*/true));
309
310 // If it is convergent it depends on EXEC.
311 if (MI.isConvergent())
312 return true;
313
314 // If it defines an SGPR it depends on EXEC, unless it's dead.
315 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
316 for (const MachineOperand &Def : MI.defs()) {
317 if (Def.isDead())
318 continue;
319
320 Register Reg = Def.getReg();
321 if (Reg && RI.isSGPRReg(MRI, Reg))
322 return true;
323 }
324
325 return false;
326}
327
328bool SIInstrInfo::isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const {
329 const MachineOperand &MO = MI.getOperand(OpIdx);
330 // Any implicit use of exec by VALU is not a real register read.
331 return MO.getReg() == AMDGPU::EXEC && MO.isImplicit() &&
332 isVALU(MI, /*AllowLDSDMA=*/true) && !resultDependsOnExec(MI);
333}
334
336 MachineBasicBlock *SuccToSinkTo,
337 MachineCycleInfo *CI) const {
338 // Allow sinking if MI edits lane mask (divergent i1 in sgpr).
339 if (MI.getOpcode() == AMDGPU::SI_IF_BREAK)
340 return true;
341
342 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
343 // Check if sinking of MI would create temporal divergent use.
344 for (auto Op : MI.uses()) {
345 if (Op.isReg() && Op.getReg().isVirtual() &&
346 RI.isSGPRClass(MRI.getRegClass(Op.getReg()))) {
347 MachineInstr *SgprDef = MRI.getVRegDef(Op.getReg());
348 if (!SgprDef)
349 continue;
350
351 // SgprDef defined inside cycle
352 CycleRef FromCycle = CI->getCycle(SgprDef->getParent());
353 if (!FromCycle)
354 continue;
355
356 CycleRef ToCycle = CI->getCycle(SuccToSinkTo);
357 // Check if there is a FromCycle that contains SgprDef's basic block but
358 // does not contain SuccToSinkTo and also has divergent exit condition.
359 while (FromCycle && !(ToCycle && CI->contains(FromCycle, ToCycle))) {
361 CI->getExitingBlocks(FromCycle, ExitingBlocks);
362
363 // FromCycle has divergent exit condition.
364 for (MachineBasicBlock *ExitingBlock : ExitingBlocks) {
365 if (hasDivergentBranch(ExitingBlock))
366 return false;
367 }
368
369 FromCycle = CI->getParentCycle(FromCycle);
370 }
371 }
372 }
373
374 return true;
375}
376
378 int64_t &Offset0,
379 int64_t &Offset1) const {
380 if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode())
381 return false;
382
383 unsigned Opc0 = Load0->getMachineOpcode();
384 unsigned Opc1 = Load1->getMachineOpcode();
385
386 // Make sure both are actually loads.
387 if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad())
388 return false;
389
390 // A mayLoad instruction without a def is not a load. Likely a prefetch.
391 if (!get(Opc0).getNumDefs() || !get(Opc1).getNumDefs())
392 return false;
393
394 if (isDS(Opc0) && isDS(Opc1)) {
395
396 // FIXME: Handle this case:
397 if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1))
398 return false;
399
400 // Check base reg.
401 if (Load0->getOperand(0) != Load1->getOperand(0))
402 return false;
403
404 // Skip read2 / write2 variants for simplicity.
405 // TODO: We should report true if the used offsets are adjacent (excluded
406 // st64 versions).
407 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
408 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
409 if (Offset0Idx == -1 || Offset1Idx == -1)
410 return false;
411
412 // XXX - be careful of dataless loads
413 // getNamedOperandIdx returns the index for MachineInstrs. Since they
414 // include the output in the operand list, but SDNodes don't, we need to
415 // subtract the index by one.
416 Offset0Idx -= get(Opc0).NumDefs;
417 Offset1Idx -= get(Opc1).NumDefs;
418 Offset0 = Load0->getConstantOperandVal(Offset0Idx);
419 Offset1 = Load1->getConstantOperandVal(Offset1Idx);
420 return true;
421 }
422
423 if (isSMRD(Opc0) && isSMRD(Opc1)) {
424 // Skip time and cache invalidation instructions.
425 if (!AMDGPU::hasNamedOperand(Opc0, AMDGPU::OpName::sbase) ||
426 !AMDGPU::hasNamedOperand(Opc1, AMDGPU::OpName::sbase))
427 return false;
428
429 unsigned NumOps = getNumOperandsNoGlue(Load0);
430 if (NumOps != getNumOperandsNoGlue(Load1))
431 return false;
432
433 // Check base reg.
434 if (Load0->getOperand(0) != Load1->getOperand(0))
435 return false;
436
437 // Match register offsets, if both register and immediate offsets present.
438 assert(NumOps == 4 || NumOps == 5);
439 if (NumOps == 5 && Load0->getOperand(1) != Load1->getOperand(1))
440 return false;
441
442 const ConstantSDNode *Load0Offset =
444 const ConstantSDNode *Load1Offset =
446
447 if (!Load0Offset || !Load1Offset)
448 return false;
449
450 Offset0 = Load0Offset->getZExtValue();
451 Offset1 = Load1Offset->getZExtValue();
452 return true;
453 }
454
455 // MUBUF and MTBUF can access the same addresses.
456 if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) {
457
458 // MUBUF and MTBUF have vaddr at different indices.
459 if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) ||
460 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) ||
461 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc))
462 return false;
463
464 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
465 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
466
467 if (OffIdx0 == -1 || OffIdx1 == -1)
468 return false;
469
470 // getNamedOperandIdx returns the index for MachineInstrs. Since they
471 // include the output in the operand list, but SDNodes don't, we need to
472 // subtract the index by one.
473 OffIdx0 -= get(Opc0).NumDefs;
474 OffIdx1 -= get(Opc1).NumDefs;
475
476 SDValue Off0 = Load0->getOperand(OffIdx0);
477 SDValue Off1 = Load1->getOperand(OffIdx1);
478
479 // The offset might be a FrameIndexSDNode.
480 if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1))
481 return false;
482
483 Offset0 = Off0->getAsZExtVal();
484 Offset1 = Off1->getAsZExtVal();
485 return true;
486 }
487
488 return false;
489}
490
491static bool isStride64(unsigned Opc) {
492 switch (Opc) {
493 case AMDGPU::DS_READ2ST64_B32:
494 case AMDGPU::DS_READ2ST64_B64:
495 case AMDGPU::DS_WRITE2ST64_B32:
496 case AMDGPU::DS_WRITE2ST64_B64:
497 return true;
498 default:
499 return false;
500 }
501}
502
505 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const {
506 if (!LdSt.mayLoadOrStore())
507 return false;
508
509 unsigned Opc = LdSt.getOpcode();
510 OffsetIsScalable = false;
511 const MachineOperand *BaseOp, *OffsetOp;
512 int DataOpIdx;
513
514 if (isDS(LdSt)) {
515 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr);
516 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
517 if (OffsetOp) {
518 // Normal, single offset LDS instruction.
519 if (!BaseOp) {
520 // DS_CONSUME/DS_APPEND use M0 for the base address.
521 // TODO: find the implicit use operand for M0 and use that as BaseOp?
522 return false;
523 }
524 BaseOps.push_back(BaseOp);
525 Offset = OffsetOp->getImm();
526 // Get appropriate operand, and compute width accordingly.
527 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
528 if (DataOpIdx == -1)
529 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
530 if (Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
531 Width = LocationSize::precise(64);
532 else
533 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
534 } else {
535 // The 2 offset instructions use offset0 and offset1 instead. We can treat
536 // these as a load with a single offset if the 2 offsets are consecutive.
537 // We will use this for some partially aligned loads.
538 const MachineOperand *Offset0Op =
539 getNamedOperand(LdSt, AMDGPU::OpName::offset0);
540 const MachineOperand *Offset1Op =
541 getNamedOperand(LdSt, AMDGPU::OpName::offset1);
542
543 unsigned Offset0 = Offset0Op->getImm() & 0xff;
544 unsigned Offset1 = Offset1Op->getImm() & 0xff;
545 if (Offset0 + 1 != Offset1)
546 return false;
547
548 // Each of these offsets is in element sized units, so we need to convert
549 // to bytes of the individual reads.
550
551 unsigned EltSize;
552 if (LdSt.mayLoad())
553 EltSize = RI.getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16;
554 else {
555 assert(LdSt.mayStore());
556 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
557 EltSize = RI.getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8;
558 }
559
560 if (isStride64(Opc))
561 EltSize *= 64;
562
563 BaseOps.push_back(BaseOp);
564 Offset = EltSize * Offset0;
565 // Get appropriate operand(s), and compute width accordingly.
566 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
567 if (DataOpIdx == -1) {
568 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
569 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
570 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
571 Width = LocationSize::precise(
572 Width.getValue() + TypeSize::getFixed(getOpSize(LdSt, DataOpIdx)));
573 } else {
574 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
575 }
576 }
577 return true;
578 }
579
580 if (isMUBUF(LdSt) || isMTBUF(LdSt)) {
581 const MachineOperand *RSrc = getNamedOperand(LdSt, AMDGPU::OpName::srsrc);
582 if (!RSrc) // e.g. BUFFER_WBINVL1_VOL
583 return false;
584 BaseOps.push_back(RSrc);
585 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
586 if (BaseOp && !BaseOp->isFI())
587 BaseOps.push_back(BaseOp);
588 const MachineOperand *OffsetImm =
589 getNamedOperand(LdSt, AMDGPU::OpName::offset);
590 Offset = OffsetImm->getImm();
591 const MachineOperand *SOffset =
592 getNamedOperand(LdSt, AMDGPU::OpName::soffset);
593 if (SOffset) {
594 if (SOffset->isReg())
595 BaseOps.push_back(SOffset);
596 else
597 Offset += SOffset->getImm();
598 }
599 // Get appropriate operand, and compute width accordingly.
600 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
601 if (DataOpIdx == -1)
602 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
603 if (DataOpIdx == -1) // LDS DMA
604 return false;
605 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
606 return true;
607 }
608
609 if (isImage(LdSt)) {
610 auto RsrcOpName =
611 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
612 int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RsrcOpName);
613 BaseOps.push_back(&LdSt.getOperand(SRsrcIdx));
614 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
615 if (VAddr0Idx >= 0) {
616 // GFX10 possible NSA encoding.
617 for (int I = VAddr0Idx; I < SRsrcIdx; ++I)
618 BaseOps.push_back(&LdSt.getOperand(I));
619 } else {
620 BaseOps.push_back(getNamedOperand(LdSt, AMDGPU::OpName::vaddr));
621 }
622 Offset = 0;
623 // Get appropriate operand, and compute width accordingly.
624 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
625 if (DataOpIdx == -1)
626 return false; // no return sampler
627 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
628 return true;
629 }
630
631 if (isSMRD(LdSt)) {
632 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::sbase);
633 if (!BaseOp) // e.g. S_MEMTIME
634 return false;
635 BaseOps.push_back(BaseOp);
636 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
637 Offset = OffsetOp ? OffsetOp->getImm() : 0;
638 // Get appropriate operand, and compute width accordingly.
639 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
640 if (DataOpIdx == -1)
641 return false;
642 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
643 return true;
644 }
645
646 if (isFLAT(LdSt)) {
647 // Instructions have either vaddr or saddr or both or none.
648 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
649 if (BaseOp)
650 BaseOps.push_back(BaseOp);
651 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr);
652 if (BaseOp)
653 BaseOps.push_back(BaseOp);
654 Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm();
655 // Get appropriate operand, and compute width accordingly.
656 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
657 if (DataOpIdx == -1)
658 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
659 if (DataOpIdx == -1) // LDS DMA
660 return false;
661 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
662 return true;
663 }
664
665 return false;
666}
667
668static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
670 const MachineInstr &MI2,
672 // Only examine the first "base" operand of each instruction, on the
673 // assumption that it represents the real base address of the memory access.
674 // Other operands are typically offsets or indices from this base address.
675 if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
676 return true;
677
678 if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
679 return false;
680
681 auto *MO1 = *MI1.memoperands_begin();
682 auto *MO2 = *MI2.memoperands_begin();
683 if (MO1->getAddrSpace() != MO2->getAddrSpace())
684 return false;
685
686 const auto *Base1 = MO1->getValue();
687 const auto *Base2 = MO2->getValue();
688 if (!Base1 || !Base2)
689 return false;
690 Base1 = getUnderlyingObject(Base1);
691 Base2 = getUnderlyingObject(Base2);
692
693 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
694 return false;
695
696 return Base1 == Base2;
697}
698
701 ArrayRef<const MachineOperand *> BaseOps2) const {
702 // Accesses without base operands (e.g. scratch addressed only by an
703 // immediate offset) share the same implicit base.
704 if (BaseOps1.empty() || BaseOps2.empty())
705 return BaseOps1.empty() && BaseOps2.empty();
706 return memOpsHaveSameBasePtr(*BaseOps1.front()->getParent(), BaseOps1,
707 *BaseOps2.front()->getParent(), BaseOps2);
708}
709
711 int64_t Offset1, bool OffsetIsScalable1,
713 int64_t Offset2, bool OffsetIsScalable2,
714 unsigned ClusterSize,
715 unsigned NumBytes) const {
716 // If the mem ops (to be clustered) do not have the same base ptr, then they
717 // should not be clustered
718 if (!memOpsHaveSameBase(BaseOps1, BaseOps2))
719 return false;
720
721 // Both lists are empty or neither is, so BaseOps1 alone decides whether
722 // there is an instruction to read the budget from.
723 assert(BaseOps1.empty() == BaseOps2.empty());
724 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;
725 if (!BaseOps1.empty()) {
726 const MachineFunction *MF = BaseOps1.front()->getParent()->getMF();
727 MaxMemoryClusterDWords =
728 MF->getInfo<SIMachineFunctionInfo>()->getMaxMemoryClusterDWords();
729 }
730
731 // In order to avoid register pressure, on an average, the number of DWORDS
732 // loaded together by all clustered mem ops should not exceed
733 // MaxMemoryClusterDWords. This is an empirical value based on certain
734 // observations and performance related experiments.
735 // The good thing about this heuristic is - it avoids clustering of too many
736 // sub-word loads, and also avoids clustering of wide loads. Below is the
737 // brief summary of how the heuristic behaves for various `LoadSize` when
738 // MaxMemoryClusterDWords is 8.
739 //
740 // (1) 1 <= LoadSize <= 4: cluster at max 8 mem ops
741 // (2) 5 <= LoadSize <= 8: cluster at max 4 mem ops
742 // (3) 9 <= LoadSize <= 12: cluster at max 2 mem ops
743 // (4) 13 <= LoadSize <= 16: cluster at max 2 mem ops
744 // (5) LoadSize >= 17: do not cluster
745 const unsigned LoadSize = NumBytes / ClusterSize;
746 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
747 return NumDWords <= MaxMemoryClusterDWords;
748}
749
750// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
751// the first 16 loads will be interleaved with the stores, and the next 16 will
752// be clustered as expected. It should really split into 2 16 store batches.
753//
754// Loads are clustered until this returns false, rather than trying to schedule
755// groups of stores. This also means we have to deal with saying different
756// address space loads should be clustered, and ones which might cause bank
757// conflicts.
758//
759// This might be deprecated so it might not be worth that much effort to fix.
761 int64_t Offset0, int64_t Offset1,
762 unsigned NumLoads) const {
763 assert(Offset1 > Offset0 &&
764 "Second offset should be larger than first offset!");
765 // If we have less than 16 loads in a row, and the offsets are within 64
766 // bytes, then schedule together.
767
768 // A cacheline is 64 bytes (for global memory).
769 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
770}
771
774 const DebugLoc &DL, MCRegister DestReg,
775 MCRegister SrcReg, bool KillSrc,
776 const char *Msg = "illegal VGPR to SGPR copy") {
777 MachineFunction *MF = MBB.getParent();
778
781
782 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg)
783 .addReg(SrcReg, getKillRegState(KillSrc));
784}
785
786/// Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908. It is not
787/// possible to have a direct copy in these cases on GFX908, so an intermediate
788/// VGPR copy is required.
791 const DebugLoc &DL, MCRegister DestReg,
792 MCRegister SrcReg, bool KillSrc,
793 RegScavenger &RS, bool RegsOverlap,
794 Register ImpUseSuperReg = Register()) {
795 assert((TII.getSubtarget().hasMAIInsts() &&
796 !TII.getSubtarget().hasGFX90AInsts()) &&
797 "Expected GFX908 subtarget.");
798
799 assert((AMDGPU::SReg_32RegClass.contains(SrcReg) ||
800 AMDGPU::AGPR_32RegClass.contains(SrcReg)) &&
801 "Source register of the copy should be either an SGPR or an AGPR.");
802
803 assert(AMDGPU::AGPR_32RegClass.contains(DestReg) &&
804 "Destination register of the copy should be an AGPR.");
805
806 const SIRegisterInfo &RI = TII.getRegisterInfo();
807
808 // First try to find defining accvgpr_write to avoid temporary registers.
809 // In the case of copies of overlapping AGPRs, we conservatively do not
810 // reuse previous accvgpr_writes. Otherwise, we may incorrectly pick up
811 // an accvgpr_write used for this same copy due to implicit-defs
812 if (!RegsOverlap) {
813 for (auto Def = MI, E = MBB.begin(); Def != E; ) {
814 --Def;
815
816 if (!Def->modifiesRegister(SrcReg, &RI))
817 continue;
818
819 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
820 Def->getOperand(0).getReg() != SrcReg)
821 break;
822
823 MachineOperand &DefOp = Def->getOperand(1);
824 assert(DefOp.isReg() || DefOp.isImm());
825
826 if (DefOp.isReg()) {
827 bool SafeToPropagate = true;
828 // Check that register source operand is not clobbered before MI.
829 // Immediate operands are always safe to propagate.
830 for (auto I = Def; I != MI && SafeToPropagate; ++I)
831 if (I->modifiesRegister(DefOp.getReg(), &RI))
832 SafeToPropagate = false;
833
834 if (!SafeToPropagate)
835 break;
836
837 for (auto I = Def; I != MI; ++I)
838 I->clearRegisterKills(DefOp.getReg(), &RI);
839 }
840
841 MachineInstrBuilder Builder =
842 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64),
843 DestReg)
844 .add(DefOp);
845
846 if (ImpUseSuperReg) {
847 Builder.addReg(ImpUseSuperReg,
849 }
850
851 return;
852 }
853 }
854
855 RS.enterBasicBlockEnd(MBB);
856 RS.backward(std::next(MI));
857
858 // Ideally we want to have three registers for a long reg_sequence copy
859 // to hide 2 waitstates between v_mov_b32 and accvgpr_write.
860 unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass,
861 *MBB.getParent());
862
863 // Registers in the sequence are allocated contiguously so we can just
864 // use register number to pick one of three round-robin temps.
865 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
866 Register Tmp =
867 MBB.getParent()->getInfo<SIMachineFunctionInfo>()->getVGPRForAGPRCopy();
868 assert(MBB.getParent()->getRegInfo().isReserved(Tmp) &&
869 "VGPR used for an intermediate copy should have been reserved.");
870
871 // Only loop through if there are any free registers left. We don't want to
872 // spill.
873 while (RegNo--) {
874 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI,
875 /* RestoreAfter */ false, 0,
876 /* AllowSpill */ false);
877 if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs)
878 break;
879 Tmp = Tmp2;
880 RS.setRegUsed(Tmp);
881 }
882
883 // Insert copy to temporary VGPR.
884 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
885 if (AMDGPU::AGPR_32RegClass.contains(SrcReg)) {
886 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
887 } else {
888 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
889 }
890
891 MachineInstrBuilder UseBuilder = BuildMI(MBB, MI, DL, TII.get(TmpCopyOp), Tmp)
892 .addReg(SrcReg, getKillRegState(KillSrc));
893 if (ImpUseSuperReg) {
894 UseBuilder.addReg(ImpUseSuperReg,
896 }
897
898 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
899 .addReg(Tmp, RegState::Kill);
900}
901
904 MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
905 const TargetRegisterClass *RC, bool Forward) {
906 const SIRegisterInfo &RI = TII.getRegisterInfo();
907 ArrayRef<int16_t> BaseIndices = RI.getRegSplitParts(RC, 4);
909 MachineInstr *FirstMI = nullptr, *LastMI = nullptr;
910
911 for (unsigned Idx = 0; Idx < BaseIndices.size(); ++Idx) {
912 int16_t SubIdx = BaseIndices[Idx];
913 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
914 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
915 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
916 unsigned Opcode = AMDGPU::S_MOV_B32;
917
918 // Is SGPR aligned? If so try to combine with next.
919 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
920 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
921 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.size())) {
922 // Can use SGPR64 copy
923 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
924 SubIdx = RI.getSubRegFromChannel(Channel, 2);
925 DestSubReg = RI.getSubReg(DestReg, SubIdx);
926 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
927 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
928 Opcode = AMDGPU::S_MOV_B64;
929 Idx++;
930 }
931
932 LastMI = BuildMI(MBB, I, DL, TII.get(Opcode), DestSubReg)
933 .addReg(SrcSubReg)
934 .addReg(SrcReg, RegState::Implicit);
935
936 if (!FirstMI)
937 FirstMI = LastMI;
938
939 if (!Forward)
940 I--;
941 }
942
943 assert(FirstMI && LastMI);
944 if (!Forward)
945 std::swap(FirstMI, LastMI);
946
947 if (KillSrc)
948 LastMI->addRegisterKilled(SrcReg, &RI);
949}
950
953 const DebugLoc &DL, Register DestReg,
954 Register SrcReg, bool KillSrc, bool RenamableDest,
955 bool RenamableSrc) const {
956 const TargetRegisterClass *RC = RI.getPhysRegBaseClass(DestReg);
957 unsigned Size = RI.getRegSizeInBits(*RC);
958 const TargetRegisterClass *SrcRC = RI.getPhysRegBaseClass(SrcReg);
959 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
960
961 // The rest of copyPhysReg assumes Src and Dst size are the same size.
962 // TODO-GFX11_16BIT If all true 16 bit instruction patterns are completed can
963 // we remove Fix16BitCopies and this code block?
964 if (Fix16BitCopies) {
965 if (((Size == 16) != (SrcSize == 16))) {
966 // Non-VGPR Src and Dst will later be expanded back to 32 bits.
967 assert(ST.useRealTrue16Insts());
968 Register &RegToFix = (Size == 32) ? DestReg : SrcReg;
969 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
970 RegToFix = SubReg;
971
972 if (DestReg == SrcReg) {
973 // Identity copy. Insert empty bundle since ExpandPostRA expects an
974 // instruction here.
975 BuildMI(MBB, MI, DL, get(AMDGPU::BUNDLE));
976 return;
977 }
978 RC = RI.getPhysRegBaseClass(DestReg);
979 Size = RI.getRegSizeInBits(*RC);
980 SrcRC = RI.getPhysRegBaseClass(SrcReg);
981 SrcSize = RI.getRegSizeInBits(*SrcRC);
982 }
983 }
984
985 if (RC == &AMDGPU::VGPR_32RegClass) {
986 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
987 AMDGPU::SReg_32RegClass.contains(SrcReg) ||
988 AMDGPU::AGPR_32RegClass.contains(SrcReg));
989 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
990 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
991 BuildMI(MBB, MI, DL, get(Opc), DestReg)
992 .addReg(SrcReg, getKillRegState(KillSrc));
993 return;
994 }
995
996 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
997 RC == &AMDGPU::SReg_32RegClass) {
998 if (SrcReg == AMDGPU::SCC) {
999 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg)
1000 .addImm(1)
1001 .addImm(0);
1002 return;
1003 }
1004
1005 if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) {
1006 if (DestReg == AMDGPU::VCC_LO) {
1007 // FIXME: Hack until VReg_1 removed.
1008 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
1009 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
1010 .addImm(0)
1011 .addReg(SrcReg, getKillRegState(KillSrc));
1012 return;
1013 }
1014
1015 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1016 return;
1017 }
1018
1019 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
1020 .addReg(SrcReg, getKillRegState(KillSrc));
1021 return;
1022 }
1023
1024 if (RC == &AMDGPU::SReg_64RegClass) {
1025 if (SrcReg == AMDGPU::SCC) {
1026 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B64), DestReg)
1027 .addImm(1)
1028 .addImm(0);
1029 return;
1030 }
1031
1032 if (!AMDGPU::SReg_64_EncodableRegClass.contains(SrcReg)) {
1033 if (DestReg == AMDGPU::VCC) {
1034 // FIXME: Hack until VReg_1 removed.
1035 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
1036 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
1037 .addImm(0)
1038 .addReg(SrcReg, getKillRegState(KillSrc));
1039 return;
1040 }
1041
1042 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1043 return;
1044 }
1045
1046 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
1047 .addReg(SrcReg, getKillRegState(KillSrc));
1048 return;
1049 }
1050
1051 if (DestReg == AMDGPU::SCC) {
1052 // Copying 64-bit or 32-bit sources to SCC barely makes sense,
1053 // but SelectionDAG emits such copies for i1 sources.
1054 if (AMDGPU::SReg_64RegClass.contains(SrcReg)) {
1055 // This copy can only be produced by patterns
1056 // with explicit SCC, which are known to be enabled
1057 // only for subtargets with S_CMP_LG_U64 present.
1058 assert(ST.hasScalarCompareEq64());
1059 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U64))
1060 .addReg(SrcReg, getKillRegState(KillSrc))
1061 .addImm(0);
1062 } else {
1063 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
1064 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32))
1065 .addReg(SrcReg, getKillRegState(KillSrc))
1066 .addImm(0);
1067 }
1068
1069 return;
1070 }
1071
1072 if (RC == &AMDGPU::AGPR_32RegClass) {
1073 if (AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
1074 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1075 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
1076 .addReg(SrcReg, getKillRegState(KillSrc));
1077 return;
1078 }
1079
1080 if (AMDGPU::AGPR_32RegClass.contains(SrcReg) && ST.hasGFX90AInsts()) {
1081 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_MOV_B32), DestReg)
1082 .addReg(SrcReg, getKillRegState(KillSrc));
1083 return;
1084 }
1085
1086 // FIXME: Pass should maintain scavenger to avoid scan through the block on
1087 // every AGPR spill.
1088 RegScavenger RS;
1089 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1090 indirectCopyToAGPR(*this, MBB, MI, DL, DestReg, SrcReg, KillSrc, RS, Overlap);
1091 return;
1092 }
1093
1094 if (Size == 16) {
1095 assert(AMDGPU::VGPR_16RegClass.contains(SrcReg) ||
1096 AMDGPU::SReg_LO16RegClass.contains(SrcReg) ||
1097 AMDGPU::AGPR_LO16RegClass.contains(SrcReg));
1098
1099 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1100 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1101 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1102 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1103 bool DstLow = !AMDGPU::isHi16Reg(DestReg, RI);
1104 bool SrcLow = !AMDGPU::isHi16Reg(SrcReg, RI);
1105 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1106 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1107
1108 if (IsSGPRDst) {
1109 if (!IsSGPRSrc) {
1110 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1111 return;
1112 }
1113
1114 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), NewDestReg)
1115 .addReg(NewSrcReg, getKillRegState(KillSrc));
1116 return;
1117 }
1118
1119 if (IsAGPRDst || IsAGPRSrc) {
1120 if (!DstLow || !SrcLow) {
1121 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1122 "Cannot use hi16 subreg with an AGPR!");
1123 }
1124
1125 copyPhysReg(MBB, MI, DL, NewDestReg, NewSrcReg, KillSrc);
1126 return;
1127 }
1128
1129 if (ST.useRealTrue16Insts()) {
1130 if (IsSGPRSrc) {
1131 assert(SrcLow);
1132 SrcReg = NewSrcReg;
1133 }
1134 // Use the smaller instruction encoding if possible.
1135 if (AMDGPU::VGPR_16_Lo128RegClass.contains(DestReg) &&
1136 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.contains(SrcReg))) {
1137 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e32), DestReg)
1138 .addReg(SrcReg);
1139 } else {
1140 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e64), DestReg)
1141 .addImm(0) // src0_modifiers
1142 .addReg(SrcReg)
1143 .addImm(0); // op_sel
1144 }
1145 return;
1146 }
1147
1148 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1149 if (!DstLow || !SrcLow) {
1150 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1151 "Cannot use hi16 subreg on VI!");
1152 }
1153
1154 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), NewDestReg)
1155 .addReg(NewSrcReg, getKillRegState(KillSrc));
1156 return;
1157 }
1158
1159 auto MIB = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_sdwa), NewDestReg)
1160 .addImm(0) // src0_modifiers
1161 .addReg(NewSrcReg)
1162 .addImm(0) // clamp
1169 // First implicit operand is $exec.
1170 MIB->tieOperands(0, MIB->getNumOperands() - 1);
1171 return;
1172 }
1173
1174 // Returns true if Dst and Src are in Opc's HwMode-resolved destination and
1175 // source operand classes.
1176 auto CanCopyWith = [&](unsigned Opc, MCRegister Dst, MCRegister Src,
1177 unsigned SrcOp = 1) {
1178 const MCInstrDesc &Desc = get(Opc);
1179 const TargetRegisterClass *DstOpRC = getRegClass(Desc, 0);
1180 const TargetRegisterClass *SrcOpRC = getRegClass(Desc, SrcOp);
1181 return DstOpRC && SrcOpRC && DstOpRC->contains(Dst) &&
1182 SrcOpRC->contains(Src);
1183 };
1184
1185 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1186 if (ST.hasVMovB64Inst() &&
1187 CanCopyWith(AMDGPU::V_MOV_B64_e32, DestReg, SrcReg)) {
1188 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_e32), DestReg)
1189 .addReg(SrcReg, getKillRegState(KillSrc));
1190 return;
1191 }
1192 if (ST.hasPkMovB32() &&
1193 CanCopyWith(AMDGPU::V_PK_MOV_B32, DestReg, SrcReg, /*SrcOp=*/2)) {
1194 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestReg)
1196 .addReg(SrcReg)
1198 .addReg(SrcReg)
1199 .addImm(0) // op_sel_lo
1200 .addImm(0) // op_sel_hi
1201 .addImm(0) // neg_lo
1202 .addImm(0) // neg_hi
1203 .addImm(0) // clamp
1204 .addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
1205 return;
1206 }
1207 }
1208
1209 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1210 if (RI.isSGPRClass(RC)) {
1211 if (!RI.isSGPRClass(SrcRC)) {
1212 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1213 return;
1214 }
1215 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1216 expandSGPRCopy(*this, MBB, MI, DL, DestReg, SrcReg, CanKillSuperReg, RC,
1217 Forward);
1218 return;
1219 }
1220
1221 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1222 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1223 if (RI.isAGPRClass(RC)) {
1224 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1225 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1226 else if (RI.hasVGPRs(SrcRC) ||
1227 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1228 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1229 else
1230 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1231 } else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1232 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1233 } else if (RI.isVGPRClass(RC)) {
1234 if (ST.hasVMovB64Inst())
1235 WideOpcode = AMDGPU::V_MOV_B64_e32;
1236 else if (ST.hasPkMovB32())
1237 WideOpcode = AMDGPU::V_PK_MOV_B32;
1238 }
1239
1240 const TargetRegisterClass *WideDstRC{}, *WideSrcRC{};
1241 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1242 const MCInstrDesc &Desc = get(WideOpcode);
1243 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1244 WideDstRC = getRegClass(Desc, 0);
1245 WideSrcRC = getRegClass(Desc, SrcOp);
1246 }
1247
1248 // If there is an overlap, we can't kill the super-register on the last
1249 // instruction, since it will also kill the components made live by this def.
1250 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1251 const bool CanKillSuperReg = KillSrc && !Overlap;
1252
1253 // For the cases where we need an intermediate instruction/temporary register
1254 // (destination is an AGPR), we need a scavenger.
1255 //
1256 // FIXME: The pass should maintain this for us so we don't have to re-scan the
1257 // whole block for every handled copy.
1258 std::unique_ptr<RegScavenger> RS;
1259 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1260 RS = std::make_unique<RegScavenger>();
1261
1262 ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, 4);
1263
1264 for (unsigned Idx{}; Idx < SubIndices.size();) {
1265 unsigned NumRegs = 1;
1266 unsigned ThisOpcode = Opcode;
1267 unsigned SubIdx =
1268 Forward ? SubIndices[Idx] : SubIndices[SubIndices.size() - Idx - 1];
1269
1270 if (WideDstRC && WideSrcRC && Idx + 1 < SubIndices.size()) {
1271 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1272 if (!Forward)
1273 --Channel;
1274
1275 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1276 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1277 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1278
1279 if (WideDst && WideSrc && WideDstRC->contains(WideDst) &&
1280 WideSrcRC->contains(WideSrc)) {
1281 SubIdx = WideSubIdx;
1282 NumRegs = 2;
1283 ThisOpcode = WideOpcode;
1284 }
1285 }
1286
1287 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1288 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1289 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
1290
1291 Idx += NumRegs;
1292 bool UseKill = CanKillSuperReg && Idx == SubIndices.size();
1293
1294 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1295 Register ImpUseSuper = SrcReg;
1296 indirectCopyToAGPR(*this, MBB, MI, DL, DestSubReg, SrcSubReg, UseKill,
1297 *RS, Overlap, ImpUseSuper);
1298 } else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1299 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestSubReg)
1301 .addReg(SrcSubReg)
1303 .addReg(SrcSubReg)
1304 .addImm(0) // op_sel_lo
1305 .addImm(0) // op_sel_hi
1306 .addImm(0) // neg_lo
1307 .addImm(0) // neg_hi
1308 .addImm(0) // clamp
1309 .addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1310 } else {
1311 MachineInstrBuilder Builder =
1312 BuildMI(MBB, MI, DL, get(ThisOpcode), DestSubReg).addReg(SrcSubReg);
1313
1314 Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1315 }
1316 }
1317}
1318
1319int SIInstrInfo::commuteOpcode(unsigned Opcode) const {
1320 int32_t NewOpc;
1321
1322 // Try to map original to commuted opcode
1323 NewOpc = AMDGPU::getCommuteRev(Opcode);
1324 if (NewOpc != -1)
1325 // Check if the commuted (REV) opcode exists on the target.
1326 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1327
1328 // Try to map commuted to original opcode
1329 NewOpc = AMDGPU::getCommuteOrig(Opcode);
1330 if (NewOpc != -1)
1331 // Check if the original (non-REV) opcode exists on the target.
1332 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1333
1334 return Opcode;
1335}
1336
1338 const Register Reg,
1339 int64_t &ImmVal) const {
1340 switch (MI.getOpcode()) {
1341 case AMDGPU::V_MOV_B32_e32:
1342 case AMDGPU::S_MOV_B32:
1343 case AMDGPU::S_MOVK_I32:
1344 case AMDGPU::S_MOV_B64:
1345 case AMDGPU::V_MOV_B64_e32:
1346 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1347 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1348 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1349 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1350 case AMDGPU::V_MOV_B64_PSEUDO:
1351 case AMDGPU::V_MOV_B16_t16_e32: {
1352 const MachineOperand &Src0 = MI.getOperand(1);
1353 if (Src0.isImm()) {
1354 ImmVal = Src0.getImm();
1355 return MI.getOperand(0).getReg() == Reg;
1356 }
1357
1358 return false;
1359 }
1360 case AMDGPU::V_MOV_B16_t16_e64: {
1361 const MachineOperand &Src0 = MI.getOperand(2);
1362 if (Src0.isImm() && !MI.getOperand(1).getImm()) {
1363 ImmVal = Src0.getImm();
1364 return MI.getOperand(0).getReg() == Reg;
1365 }
1366
1367 return false;
1368 }
1369 case AMDGPU::S_BREV_B32:
1370 case AMDGPU::V_BFREV_B32_e32:
1371 case AMDGPU::V_BFREV_B32_e64: {
1372 const MachineOperand &Src0 = MI.getOperand(1);
1373 if (Src0.isImm()) {
1374 ImmVal = static_cast<int64_t>(reverseBits<int32_t>(Src0.getImm()));
1375 return MI.getOperand(0).getReg() == Reg;
1376 }
1377
1378 return false;
1379 }
1380 case AMDGPU::S_NOT_B32:
1381 case AMDGPU::V_NOT_B32_e32:
1382 case AMDGPU::V_NOT_B32_e64: {
1383 const MachineOperand &Src0 = MI.getOperand(1);
1384 if (Src0.isImm()) {
1385 ImmVal = static_cast<int64_t>(~static_cast<int32_t>(Src0.getImm()));
1386 return MI.getOperand(0).getReg() == Reg;
1387 }
1388
1389 return false;
1390 }
1391 default:
1392 return false;
1393 }
1394}
1395
1396std::optional<int64_t>
1398 const MachineOperand &Op,
1399 MachineInstr **DefMI) const {
1400 if (DefMI)
1401 *DefMI = nullptr;
1402
1403 if (Op.isImm())
1404 return Op.getImm();
1405
1406 if (!Op.isReg() || !Op.getReg().isVirtual())
1407 return std::nullopt;
1408 MachineInstr *Def = MRI.getUniqueVRegDef(Op.getReg());
1409 if (Def && Def->isMoveImmediate()) {
1410 const MachineOperand &ImmSrc = Def->getOperand(1);
1411 if (ImmSrc.isImm()) {
1412 if (DefMI)
1413 *DefMI = Def;
1414 return extractSubregFromImm(ImmSrc.getImm(), Op.getSubReg());
1415 }
1416 }
1417
1418 return std::nullopt;
1419}
1420
1421std::optional<int64_t>
1427
1429
1430 if (RI.isAGPRClass(DstRC))
1431 return AMDGPU::COPY;
1432 if (RI.getRegSizeInBits(*DstRC) == 16) {
1433 // Assume hi bits are unneeded. Only _e64 true16 instructions are legal
1434 // before RA.
1435 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1436 }
1437 if (RI.getRegSizeInBits(*DstRC) == 32)
1438 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1439 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1440 return AMDGPU::S_MOV_B64;
1441 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1442 return AMDGPU::V_MOV_B64_PSEUDO;
1443 return AMDGPU::COPY;
1444}
1445
1446const MCInstrDesc &
1448 bool IsIndirectSrc) const {
1449 if (IsIndirectSrc) {
1450 if (VecSize <= 32) // 4 bytes
1451 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1452 if (VecSize <= 64) // 8 bytes
1453 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1454 if (VecSize <= 96) // 12 bytes
1455 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1456 if (VecSize <= 128) // 16 bytes
1457 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1458 if (VecSize <= 160) // 20 bytes
1459 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1460 if (VecSize <= 192) // 24 bytes
1461 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1462 if (VecSize <= 224) // 28 bytes
1463 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1464 if (VecSize <= 256) // 32 bytes
1465 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1466 if (VecSize <= 288) // 36 bytes
1467 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1468 if (VecSize <= 320) // 40 bytes
1469 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1470 if (VecSize <= 352) // 44 bytes
1471 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1472 if (VecSize <= 384) // 48 bytes
1473 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1474 if (VecSize <= 512) // 64 bytes
1475 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1476 if (VecSize <= 1024) // 128 bytes
1477 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1478
1479 llvm_unreachable("unsupported size for IndirectRegReadGPRIDX pseudos");
1480 }
1481
1482 if (VecSize <= 32) // 4 bytes
1483 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1484 if (VecSize <= 64) // 8 bytes
1485 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1486 if (VecSize <= 96) // 12 bytes
1487 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1488 if (VecSize <= 128) // 16 bytes
1489 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1490 if (VecSize <= 160) // 20 bytes
1491 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1492 if (VecSize <= 192) // 24 bytes
1493 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1494 if (VecSize <= 224) // 28 bytes
1495 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1496 if (VecSize <= 256) // 32 bytes
1497 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1498 if (VecSize <= 288) // 36 bytes
1499 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1500 if (VecSize <= 320) // 40 bytes
1501 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1502 if (VecSize <= 352) // 44 bytes
1503 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1504 if (VecSize <= 384) // 48 bytes
1505 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1506 if (VecSize <= 512) // 64 bytes
1507 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1508 if (VecSize <= 1024) // 128 bytes
1509 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1510
1511 llvm_unreachable("unsupported size for IndirectRegWriteGPRIDX pseudos");
1512}
1513
1514static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize) {
1515 if (VecSize <= 32) // 4 bytes
1516 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1517 if (VecSize <= 64) // 8 bytes
1518 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1519 if (VecSize <= 96) // 12 bytes
1520 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1521 if (VecSize <= 128) // 16 bytes
1522 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1523 if (VecSize <= 160) // 20 bytes
1524 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1525 if (VecSize <= 192) // 24 bytes
1526 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1527 if (VecSize <= 224) // 28 bytes
1528 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1529 if (VecSize <= 256) // 32 bytes
1530 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1531 if (VecSize <= 288) // 36 bytes
1532 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1533 if (VecSize <= 320) // 40 bytes
1534 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1535 if (VecSize <= 352) // 44 bytes
1536 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1537 if (VecSize <= 384) // 48 bytes
1538 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1539 if (VecSize <= 512) // 64 bytes
1540 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1541 if (VecSize <= 1024) // 128 bytes
1542 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1543
1544 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1545}
1546
1547static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize) {
1548 if (VecSize <= 32) // 4 bytes
1549 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1550 if (VecSize <= 64) // 8 bytes
1551 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1552 if (VecSize <= 96) // 12 bytes
1553 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1554 if (VecSize <= 128) // 16 bytes
1555 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1556 if (VecSize <= 160) // 20 bytes
1557 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1558 if (VecSize <= 192) // 24 bytes
1559 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1560 if (VecSize <= 224) // 28 bytes
1561 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1562 if (VecSize <= 256) // 32 bytes
1563 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1564 if (VecSize <= 288) // 36 bytes
1565 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1566 if (VecSize <= 320) // 40 bytes
1567 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1568 if (VecSize <= 352) // 44 bytes
1569 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1570 if (VecSize <= 384) // 48 bytes
1571 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1572 if (VecSize <= 512) // 64 bytes
1573 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1574 if (VecSize <= 1024) // 128 bytes
1575 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1576
1577 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1578}
1579
1580static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize) {
1581 if (VecSize <= 64) // 8 bytes
1582 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1583 if (VecSize <= 128) // 16 bytes
1584 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1585 if (VecSize <= 256) // 32 bytes
1586 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1587 if (VecSize <= 512) // 64 bytes
1588 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1589 if (VecSize <= 1024) // 128 bytes
1590 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1591
1592 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1593}
1594
1595const MCInstrDesc &
1596SIInstrInfo::getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize,
1597 bool IsSGPR) const {
1598 if (IsSGPR) {
1599 switch (EltSize) {
1600 case 32:
1601 return get(getIndirectSGPRWriteMovRelPseudo32(VecSize));
1602 case 64:
1603 return get(getIndirectSGPRWriteMovRelPseudo64(VecSize));
1604 default:
1605 llvm_unreachable("invalid reg indexing elt size");
1606 }
1607 }
1608
1609 assert(EltSize == 32 && "invalid reg indexing elt size");
1611}
1612
1613static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1614 switch (Size) {
1615 case 4:
1616 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1617 case 8:
1618 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1619 case 12:
1620 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1621 case 16:
1622 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1623 : AMDGPU::SI_SPILL_S128_SAVE;
1624 case 20:
1625 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1626 : AMDGPU::SI_SPILL_S160_SAVE;
1627 case 24:
1628 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1629 : AMDGPU::SI_SPILL_S192_SAVE;
1630 case 28:
1631 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1632 : AMDGPU::SI_SPILL_S224_SAVE;
1633 case 32:
1634 return AMDGPU::SI_SPILL_S256_SAVE;
1635 case 36:
1636 return AMDGPU::SI_SPILL_S288_SAVE;
1637 case 40:
1638 return AMDGPU::SI_SPILL_S320_SAVE;
1639 case 44:
1640 return AMDGPU::SI_SPILL_S352_SAVE;
1641 case 48:
1642 return AMDGPU::SI_SPILL_S384_SAVE;
1643 case 64:
1644 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1645 : AMDGPU::SI_SPILL_S512_SAVE;
1646 case 128:
1647 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1648 : AMDGPU::SI_SPILL_S1024_SAVE;
1649 default:
1650 llvm_unreachable("unknown register size");
1651 }
1652}
1653
1654static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1655 switch (Size) {
1656 case 2:
1657 return AMDGPU::SI_SPILL_V16_SAVE;
1658 case 4:
1659 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1660 case 8:
1661 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1662 case 12:
1663 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1664 case 16:
1665 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1666 : AMDGPU::SI_SPILL_V128_SAVE;
1667 case 20:
1668 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1669 : AMDGPU::SI_SPILL_V160_SAVE;
1670 case 24:
1671 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1672 : AMDGPU::SI_SPILL_V192_SAVE;
1673 case 28:
1674 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1675 : AMDGPU::SI_SPILL_V224_SAVE;
1676 case 32:
1677 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1678 : AMDGPU::SI_SPILL_V256_SAVE;
1679 case 36:
1680 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1681 : AMDGPU::SI_SPILL_V288_SAVE;
1682 case 40:
1683 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1684 : AMDGPU::SI_SPILL_V320_SAVE;
1685 case 44:
1686 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1687 : AMDGPU::SI_SPILL_V352_SAVE;
1688 case 48:
1689 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1690 : AMDGPU::SI_SPILL_V384_SAVE;
1691 case 64:
1692 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1693 : AMDGPU::SI_SPILL_V512_SAVE;
1694 case 128:
1695 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1696 : AMDGPU::SI_SPILL_V1024_SAVE;
1697 default:
1698 llvm_unreachable("unknown register size");
1699 }
1700}
1701
1702static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1703 switch (Size) {
1704 case 4:
1705 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1706 : AMDGPU::SI_SPILL_AV32_SAVE;
1707 case 8:
1708 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1709 : AMDGPU::SI_SPILL_AV64_SAVE;
1710 case 12:
1711 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1712 : AMDGPU::SI_SPILL_AV96_SAVE;
1713 case 16:
1714 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1715 : AMDGPU::SI_SPILL_AV128_SAVE;
1716 case 20:
1717 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1718 : AMDGPU::SI_SPILL_AV160_SAVE;
1719 case 24:
1720 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1721 : AMDGPU::SI_SPILL_AV192_SAVE;
1722 case 28:
1723 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1724 : AMDGPU::SI_SPILL_AV224_SAVE;
1725 case 32:
1726 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1727 : AMDGPU::SI_SPILL_AV256_SAVE;
1728 case 36:
1729 return AMDGPU::SI_SPILL_AV288_SAVE;
1730 case 40:
1731 return AMDGPU::SI_SPILL_AV320_SAVE;
1732 case 44:
1733 return AMDGPU::SI_SPILL_AV352_SAVE;
1734 case 48:
1735 return AMDGPU::SI_SPILL_AV384_SAVE;
1736 case 64:
1737 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1738 : AMDGPU::SI_SPILL_AV512_SAVE;
1739 case 128:
1740 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1741 : AMDGPU::SI_SPILL_AV1024_SAVE;
1742 default:
1743 llvm_unreachable("unknown register size");
1744 }
1745}
1746
1747static unsigned getWWMRegSpillSaveOpcode(unsigned Size,
1748 bool IsVectorSuperClass) {
1749 // Currently, there is only 32-bit WWM register spills needed.
1750 if (Size != 4)
1751 llvm_unreachable("unknown wwm register spill size");
1752
1753 if (IsVectorSuperClass)
1754 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1755
1756 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1757}
1758
1760 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1761 const SIMachineFunctionInfo &MFI, bool NeedsCFI) const {
1762 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1763
1764 // Choose the right opcode if spilling a WWM register.
1766 return getWWMRegSpillSaveOpcode(Size, IsVectorSuperClass);
1767
1768 // TODO: Check if AGPRs are available
1769 if (ST.hasMAIInsts())
1770 return getAVSpillSaveOpcode(Size, NeedsCFI);
1771
1772 return getVGPRSpillSaveOpcode(Size, NeedsCFI);
1773}
1774
1775void SIInstrInfo::storeRegToStackSlotImpl(
1777 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1778 MachineInstr::MIFlag Flags, bool NeedsCFI) const {
1779 MachineFunction *MF = MBB.getParent();
1781 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1782 const DebugLoc &DL = MBB.findDebugLoc(MI);
1783
1784 MachinePointerInfo PtrInfo
1785 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1787 PtrInfo, MachineMemOperand::MOStore, FrameInfo.getObjectSize(FrameIndex),
1788 FrameInfo.getObjectAlign(FrameIndex));
1789 unsigned SpillSize = RI.getSpillSize(*RC);
1790
1792 if (RI.isSGPRClass(RC)) {
1793 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1794 MFI->setHasSpilledSGPRs();
1795 assert(SrcReg != AMDGPU::M0 && "m0 should not be spilled");
1796 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1797 SrcReg != AMDGPU::EXEC && "exec should not be spilled");
1798
1799 // We are only allowed to create one new instruction when spilling
1800 // registers, so we need to use pseudo instruction for spilling SGPRs.
1801 const MCInstrDesc &OpDesc =
1802 get(getSGPRSpillSaveOpcode(SpillSize, NeedsCFI));
1803
1804 // The SGPR spill/restore instructions only work on number sgprs, so we need
1805 // to make sure we are using the correct register class.
1806 if (SrcReg.isVirtual() && SpillSize == 4) {
1807 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1808 }
1809
1810 BuildMI(MBB, MI, DL, OpDesc)
1811 .addReg(SrcReg, getKillRegState(isKill)) // data
1812 .addFrameIndex(FrameIndex) // addr
1813 .addMemOperand(MMO)
1815
1816 return;
1817 }
1818
1819 unsigned Opcode = getVectorRegSpillSaveOpcode(VReg ? VReg : SrcReg, RC,
1820 SpillSize, *MFI, NeedsCFI);
1821 MFI->setHasSpilledVGPRs();
1822
1823 BuildMI(MBB, MI, DL, get(Opcode))
1824 .addReg(SrcReg, getKillRegState(isKill)) // data
1825 .addFrameIndex(FrameIndex) // addr
1826 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1827 .addImm(0) // offset
1828 .addMemOperand(MMO);
1829}
1830
1833 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1834 MachineInstr::MIFlag Flags) const {
1835 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1836 false);
1837}
1838
1841 Register SrcReg, bool isKill,
1842 int FrameIndex,
1843 const TargetRegisterClass *RC) const {
1844 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, Register(),
1845 MachineInstr::NoFlags, true);
1846}
1847
1848static unsigned getSGPRSpillRestoreOpcode(unsigned Size) {
1849 switch (Size) {
1850 case 4:
1851 return AMDGPU::SI_SPILL_S32_RESTORE;
1852 case 8:
1853 return AMDGPU::SI_SPILL_S64_RESTORE;
1854 case 12:
1855 return AMDGPU::SI_SPILL_S96_RESTORE;
1856 case 16:
1857 return AMDGPU::SI_SPILL_S128_RESTORE;
1858 case 20:
1859 return AMDGPU::SI_SPILL_S160_RESTORE;
1860 case 24:
1861 return AMDGPU::SI_SPILL_S192_RESTORE;
1862 case 28:
1863 return AMDGPU::SI_SPILL_S224_RESTORE;
1864 case 32:
1865 return AMDGPU::SI_SPILL_S256_RESTORE;
1866 case 36:
1867 return AMDGPU::SI_SPILL_S288_RESTORE;
1868 case 40:
1869 return AMDGPU::SI_SPILL_S320_RESTORE;
1870 case 44:
1871 return AMDGPU::SI_SPILL_S352_RESTORE;
1872 case 48:
1873 return AMDGPU::SI_SPILL_S384_RESTORE;
1874 case 64:
1875 return AMDGPU::SI_SPILL_S512_RESTORE;
1876 case 128:
1877 return AMDGPU::SI_SPILL_S1024_RESTORE;
1878 default:
1879 llvm_unreachable("unknown register size");
1880 }
1881}
1882
1883static unsigned getVGPRSpillRestoreOpcode(unsigned Size) {
1884 switch (Size) {
1885 case 2:
1886 return AMDGPU::SI_SPILL_V16_RESTORE;
1887 case 4:
1888 return AMDGPU::SI_SPILL_V32_RESTORE;
1889 case 8:
1890 return AMDGPU::SI_SPILL_V64_RESTORE;
1891 case 12:
1892 return AMDGPU::SI_SPILL_V96_RESTORE;
1893 case 16:
1894 return AMDGPU::SI_SPILL_V128_RESTORE;
1895 case 20:
1896 return AMDGPU::SI_SPILL_V160_RESTORE;
1897 case 24:
1898 return AMDGPU::SI_SPILL_V192_RESTORE;
1899 case 28:
1900 return AMDGPU::SI_SPILL_V224_RESTORE;
1901 case 32:
1902 return AMDGPU::SI_SPILL_V256_RESTORE;
1903 case 36:
1904 return AMDGPU::SI_SPILL_V288_RESTORE;
1905 case 40:
1906 return AMDGPU::SI_SPILL_V320_RESTORE;
1907 case 44:
1908 return AMDGPU::SI_SPILL_V352_RESTORE;
1909 case 48:
1910 return AMDGPU::SI_SPILL_V384_RESTORE;
1911 case 64:
1912 return AMDGPU::SI_SPILL_V512_RESTORE;
1913 case 128:
1914 return AMDGPU::SI_SPILL_V1024_RESTORE;
1915 default:
1916 llvm_unreachable("unknown register size");
1917 }
1918}
1919
1920static unsigned getAVSpillRestoreOpcode(unsigned Size) {
1921 switch (Size) {
1922 case 4:
1923 return AMDGPU::SI_SPILL_AV32_RESTORE;
1924 case 8:
1925 return AMDGPU::SI_SPILL_AV64_RESTORE;
1926 case 12:
1927 return AMDGPU::SI_SPILL_AV96_RESTORE;
1928 case 16:
1929 return AMDGPU::SI_SPILL_AV128_RESTORE;
1930 case 20:
1931 return AMDGPU::SI_SPILL_AV160_RESTORE;
1932 case 24:
1933 return AMDGPU::SI_SPILL_AV192_RESTORE;
1934 case 28:
1935 return AMDGPU::SI_SPILL_AV224_RESTORE;
1936 case 32:
1937 return AMDGPU::SI_SPILL_AV256_RESTORE;
1938 case 36:
1939 return AMDGPU::SI_SPILL_AV288_RESTORE;
1940 case 40:
1941 return AMDGPU::SI_SPILL_AV320_RESTORE;
1942 case 44:
1943 return AMDGPU::SI_SPILL_AV352_RESTORE;
1944 case 48:
1945 return AMDGPU::SI_SPILL_AV384_RESTORE;
1946 case 64:
1947 return AMDGPU::SI_SPILL_AV512_RESTORE;
1948 case 128:
1949 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1950 default:
1951 llvm_unreachable("unknown register size");
1952 }
1953}
1954
1955static unsigned getWWMRegSpillRestoreOpcode(unsigned Size,
1956 bool IsVectorSuperClass) {
1957 // Currently, there is only 32-bit WWM register spills needed.
1958 if (Size != 4)
1959 llvm_unreachable("unknown wwm register spill size");
1960
1961 if (IsVectorSuperClass) // TODO: Always use this if there are AGPRs
1962 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1963
1964 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1965}
1966
1968 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1969 const SIMachineFunctionInfo &MFI) const {
1970 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1971
1972 // Choose the right opcode if restoring a WWM register.
1974 return getWWMRegSpillRestoreOpcode(Size, IsVectorSuperClass);
1975
1976 // TODO: Check if AGPRs are available
1977 if (ST.hasMAIInsts())
1979
1980 assert(!RI.isAGPRClass(RC));
1982}
1983
1986 Register DestReg, int FrameIndex,
1987 const TargetRegisterClass *RC,
1988 Register VReg, unsigned SubReg,
1989 MachineInstr::MIFlag Flags) const {
1990 MachineFunction *MF = MBB.getParent();
1992 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1993 const DebugLoc &DL = MBB.findDebugLoc(MI);
1994 unsigned SpillSize = RI.getSpillSize(*RC);
1995
1996 MachinePointerInfo PtrInfo
1997 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1998
2000 PtrInfo, MachineMemOperand::MOLoad, FrameInfo.getObjectSize(FrameIndex),
2001 FrameInfo.getObjectAlign(FrameIndex));
2002
2003 if (RI.isSGPRClass(RC)) {
2004 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
2005 MFI->setHasSpilledSGPRs();
2006 assert(DestReg != AMDGPU::M0 && "m0 should not be reloaded into");
2007 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
2008 DestReg != AMDGPU::EXEC && "exec should not be spilled");
2009
2010 // FIXME: Maybe this should not include a memoperand because it will be
2011 // lowered to non-memory instructions.
2012 const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize));
2013 if (DestReg.isVirtual() && SpillSize == 4) {
2015 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
2016 }
2017
2018 BuildMI(MBB, MI, DL, OpDesc, DestReg)
2019 .addFrameIndex(FrameIndex) // addr
2020 .addMemOperand(MMO)
2022
2023 return;
2024 }
2025
2026 unsigned Opcode = getVectorRegSpillRestoreOpcode(VReg ? VReg : DestReg, RC,
2027 SpillSize, *MFI);
2028 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
2029 .addFrameIndex(FrameIndex) // vaddr
2030 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
2031 .addImm(0) // offset
2032 .addMemOperand(MMO);
2033}
2034
2039
2042 unsigned Quantity) const {
2043 DebugLoc DL = MBB.findDebugLoc(MI);
2044 unsigned MaxSNopCount = 1u << ST.getSNopBits();
2045 while (Quantity > 0) {
2046 unsigned Arg = std::min(Quantity, MaxSNopCount);
2047 Quantity -= Arg;
2048 BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
2049 }
2050}
2051
2055 const DebugLoc &DL) const {
2056 MachineFunction *MF = MBB.getParent();
2057 constexpr unsigned DoorbellIDMask = 0x3ff;
2058 constexpr unsigned ECQueueWaveAbort = 0x400;
2059
2060 MachineBasicBlock *TrapBB = &MBB;
2061 MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock();
2062
2063 if (!MBB.succ_empty() ||
2065 /*SkipPseudoOp=*/false) != MBB.end()) {
2066 MBB.splitAt(MI, /*UpdateLiveIns=*/false);
2067 TrapBB = MF->CreateMachineBasicBlock();
2068 BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB);
2069 MF->push_back(TrapBB);
2070 MBB.addSuccessor(TrapBB);
2071 }
2072 // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this
2073 // will be a nop.
2074 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP))
2075 .addImm(static_cast<unsigned>(GCNSubtarget::TrapID::LLVMAMDHSATrap));
2076 Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2077 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32),
2078 DoorbellReg)
2080 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2081 .addUse(AMDGPU::M0);
2082 Register DoorbellRegMasked =
2083 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2084 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2085 .addUse(DoorbellReg)
2086 .addImm(DoorbellIDMask)
2087 .setOperandDead(3); // implicit-def $scc
2088 Register SetWaveAbortBit =
2089 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2090 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2091 .addUse(DoorbellRegMasked)
2092 .addImm(ECQueueWaveAbort)
2093 .setOperandDead(3); // implicit-def $scc
2094 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2095 .addUse(SetWaveAbortBit);
2096 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG))
2098 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2099 .addUse(AMDGPU::TTMP2);
2100 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB);
2101 TrapBB->addSuccessor(HaltLoopBB);
2102
2103 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5);
2104 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH))
2105 .addMBB(HaltLoopBB);
2106 MF->push_back(HaltLoopBB);
2107 HaltLoopBB->addSuccessor(HaltLoopBB);
2108
2109 return MBB.getNextNode();
2110}
2111
2113 switch (MI.getOpcode()) {
2114 default:
2115 if (MI.isMetaInstruction())
2116 return 0;
2117 return 1; // FIXME: Do wait states equal cycles?
2118
2119 case AMDGPU::S_NOP:
2120 return MI.getOperand(0).getImm() + 1;
2121 // SI_RETURN_TO_EPILOG is a fallthrough to code outside of the function. The
2122 // hazard, even if one exist, won't really be visible. Should we handle it?
2123 }
2124}
2125
2127 MachineBasicBlock &MBB = *MI.getParent();
2128 DebugLoc DL = MBB.findDebugLoc(MI);
2130
2131 switch (MI.getOpcode()) {
2132 default: return TargetInstrInfo::expandPostRAPseudo(MI);
2133 case AMDGPU::S_MOV_B64_term:
2134 // This is only a terminator to get the correct spill code placement during
2135 // register allocation.
2136 MI.setDesc(get(AMDGPU::S_MOV_B64));
2137 break;
2138
2139 case AMDGPU::S_MOV_B32_term:
2140 // This is only a terminator to get the correct spill code placement during
2141 // register allocation.
2142 MI.setDesc(get(AMDGPU::S_MOV_B32));
2143 break;
2144
2145 case AMDGPU::S_XOR_B64_term:
2146 // This is only a terminator to get the correct spill code placement during
2147 // register allocation.
2148 MI.setDesc(get(AMDGPU::S_XOR_B64));
2149 break;
2150
2151 case AMDGPU::S_XOR_B32_term:
2152 // This is only a terminator to get the correct spill code placement during
2153 // register allocation.
2154 MI.setDesc(get(AMDGPU::S_XOR_B32));
2155 break;
2156 case AMDGPU::S_OR_B64_term:
2157 // This is only a terminator to get the correct spill code placement during
2158 // register allocation.
2159 MI.setDesc(get(AMDGPU::S_OR_B64));
2160 break;
2161 case AMDGPU::S_OR_B32_term:
2162 // This is only a terminator to get the correct spill code placement during
2163 // register allocation.
2164 MI.setDesc(get(AMDGPU::S_OR_B32));
2165 break;
2166
2167 case AMDGPU::S_ANDN2_B64_term:
2168 // This is only a terminator to get the correct spill code placement during
2169 // register allocation.
2170 MI.setDesc(get(AMDGPU::S_ANDN2_B64));
2171 break;
2172
2173 case AMDGPU::S_ANDN2_B32_term:
2174 // This is only a terminator to get the correct spill code placement during
2175 // register allocation.
2176 MI.setDesc(get(AMDGPU::S_ANDN2_B32));
2177 break;
2178
2179 case AMDGPU::S_AND_B64_term:
2180 // This is only a terminator to get the correct spill code placement during
2181 // register allocation.
2182 MI.setDesc(get(AMDGPU::S_AND_B64));
2183 break;
2184
2185 case AMDGPU::S_AND_B32_term:
2186 // This is only a terminator to get the correct spill code placement during
2187 // register allocation.
2188 MI.setDesc(get(AMDGPU::S_AND_B32));
2189 break;
2190
2191 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2192 // This is only a terminator to get the correct spill code placement during
2193 // register allocation.
2194 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B64));
2195 break;
2196
2197 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2198 // This is only a terminator to get the correct spill code placement during
2199 // register allocation.
2200 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B32));
2201 break;
2202
2203 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2204 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2205 break;
2206 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2207 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2208 break;
2209
2210 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2211 MI.setDesc(get(AMDGPU::V_WRITELANE_B32));
2212 break;
2213
2214 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2215 MI.setDesc(get(AMDGPU::V_READLANE_B32));
2216 break;
2217 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2218 Register Dst = MI.getOperand(0).getReg();
2219 bool IsAGPR = SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst));
2220 MI.setDesc(
2221 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2222 break;
2223 }
2224 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2225 Register Dst = MI.getOperand(0).getReg();
2226 if (SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst))) {
2227 int64_t Imm = MI.getOperand(1).getImm();
2228
2229 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2230 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2231 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstLo)
2233 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstHi)
2234 .addImm(SignExtend64<32>(Imm >> 32));
2235 MI.eraseFromParent();
2236 break;
2237 }
2238
2239 [[fallthrough]];
2240 }
2241 case AMDGPU::V_MOV_B64_PSEUDO: {
2242 Register Dst = MI.getOperand(0).getReg();
2243 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2244 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2245
2246 const MCInstrDesc &Mov64Desc = get(AMDGPU::V_MOV_B64_e32);
2247 const TargetRegisterClass *Mov64RC = getRegClass(Mov64Desc, /*OpNum=*/0);
2248
2249 const MachineOperand &SrcOp = MI.getOperand(1);
2250 // FIXME: Will this work for 64-bit floating point immediates?
2251 assert(!SrcOp.isFPImm());
2252 if (ST.hasVMovB64Inst() && Mov64RC->contains(Dst)) {
2253 MI.setDesc(Mov64Desc);
2254 if (SrcOp.isReg() || isInlineConstant(MI, 1) ||
2255 (SrcOp.isImm() &&
2256 (isUInt<32>(SrcOp.getImm()) || ST.has64BitLiterals())) ||
2257 (SrcOp.isGlobal() && ST.has64BitLiterals()))
2258 break;
2259 }
2260 if (SrcOp.isGlobal()) {
2261 // The address is unknown until link time, so the PK_MOV inline-constant
2262 // shortcut cannot apply.
2263 const GlobalValue *GV = SrcOp.getGlobal();
2264 int64_t Offset = SrcOp.getOffset();
2265 unsigned BaseFlags, LoReloc, HiReloc;
2266 std::tie(BaseFlags, LoReloc, HiReloc) =
2268
2269 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2270 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2271 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2272 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2273 } else if (SrcOp.isImm()) {
2274 APInt Imm(64, SrcOp.getImm());
2275 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2276 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2277 const MCInstrDesc &PkMovDesc = get(AMDGPU::V_PK_MOV_B32);
2278 const TargetRegisterClass *PkMovRC = getRegClass(PkMovDesc, /*OpNum=*/0);
2279
2280 if (ST.hasPkMovB32() && Lo == Hi && isInlineConstant(Lo) &&
2281 PkMovRC->contains(Dst)) {
2282 BuildMI(MBB, MI, DL, PkMovDesc, Dst)
2284 .addImm(Lo.getSExtValue())
2286 .addImm(Lo.getSExtValue())
2287 .addImm(0) // op_sel_lo
2288 .addImm(0) // op_sel_hi
2289 .addImm(0) // neg_lo
2290 .addImm(0) // neg_hi
2291 .addImm(0); // clamp
2292 } else {
2293 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2294 .addImm(Lo.getSExtValue());
2295 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2296 .addImm(Hi.getSExtValue());
2297 }
2298 } else {
2299 assert(SrcOp.isReg());
2300 if (ST.hasPkMovB32() &&
2301 !RI.isAGPR(MBB.getParent()->getRegInfo(), SrcOp.getReg())) {
2302 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), Dst)
2303 .addImm(SISrcMods::OP_SEL_1) // src0_mod
2304 .addReg(SrcOp.getReg())
2306 .addReg(SrcOp.getReg())
2307 .addImm(0) // op_sel_lo
2308 .addImm(0) // op_sel_hi
2309 .addImm(0) // neg_lo
2310 .addImm(0) // neg_hi
2311 .addImm(0); // clamp
2312 } else {
2313 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2314 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0));
2315 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2316 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1));
2317 }
2318 }
2319 MI.eraseFromParent();
2320 break;
2321 }
2322 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2324 break;
2325 }
2326 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2327 const MachineOperand &SrcOp = MI.getOperand(1);
2328 assert(!SrcOp.isFPImm());
2329
2330 if (ST.has64BitLiterals()) {
2331 MI.setDesc(get(AMDGPU::S_MOV_B64));
2332 break;
2333 }
2334
2335 if (SrcOp.isGlobal()) {
2336 Register Dst = MI.getOperand(0).getReg();
2337 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2338 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2339 const GlobalValue *GV = SrcOp.getGlobal();
2340 int64_t Offset = SrcOp.getOffset();
2341 unsigned BaseFlags, LoReloc, HiReloc;
2342 std::tie(BaseFlags, LoReloc, HiReloc) =
2344
2345 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2346 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2347 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2348 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2349 MI.eraseFromParent();
2350 break;
2351 }
2352
2353 // SrcOp is immediate
2354 APInt Imm(64, SrcOp.getImm());
2355 if (Imm.isIntN(32) || isInlineConstant(Imm)) {
2356 MI.setDesc(get(AMDGPU::S_MOV_B64));
2357 break;
2358 }
2359
2360 Register Dst = MI.getOperand(0).getReg();
2361 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2362 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2363
2364 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2365 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2366 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2367 .addImm(Lo.getSExtValue());
2368 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2369 .addImm(Hi.getSExtValue());
2370 MI.eraseFromParent();
2371 break;
2372 }
2373 case AMDGPU::V_SET_INACTIVE_B32: {
2374 // Lower V_SET_INACTIVE_B32 to V_CNDMASK_B32.
2375 Register DstReg = MI.getOperand(0).getReg();
2376 BuildMI(MBB, MI, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2377 .add(MI.getOperand(3))
2378 .add(MI.getOperand(4))
2379 .add(MI.getOperand(1))
2380 .add(MI.getOperand(2))
2381 .add(MI.getOperand(5));
2382 MI.eraseFromParent();
2383 break;
2384 }
2385 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2386 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2387 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2388 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2389 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2390 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2391 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2392 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2393 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2394 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2395 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2396 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2397 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2398 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2399 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2400 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2401 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2402 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2403 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2404 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2405 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2406 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2407 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2408 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2409 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2410 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2411 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2412 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2413 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2414 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2415 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2416 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2417 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2418 const TargetRegisterClass *EltRC = getOpRegClass(MI, 2);
2419
2420 unsigned Opc;
2421 if (RI.hasVGPRs(EltRC)) {
2422 Opc = AMDGPU::V_MOVRELD_B32_e32;
2423 } else {
2424 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2425 : AMDGPU::S_MOVRELD_B32;
2426 }
2427
2428 const MCInstrDesc &OpDesc = get(Opc);
2429 Register VecReg = MI.getOperand(0).getReg();
2430 bool IsUndef = MI.getOperand(1).isUndef();
2431 unsigned SubReg = MI.getOperand(3).getImm();
2432 assert(VecReg == MI.getOperand(1).getReg());
2433
2435 BuildMI(MBB, MI, DL, OpDesc)
2436 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2437 .add(MI.getOperand(2))
2439 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2440
2441 const int ImpDefIdx =
2442 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2443 const int ImpUseIdx = ImpDefIdx + 1;
2444 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2445 MI.eraseFromParent();
2446 break;
2447 }
2448 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2449 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2450 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2451 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2452 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2453 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2454 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2455 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2456 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2457 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2458 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2459 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2460 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2461 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2462 assert(ST.useVGPRIndexMode());
2463 Register VecReg = MI.getOperand(0).getReg();
2464 bool IsUndef = MI.getOperand(1).isUndef();
2465 MachineOperand &Idx = MI.getOperand(3);
2466 Register SubReg = MI.getOperand(4).getImm();
2467
2468 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2469 .add(Idx)
2471 SetOn->getOperand(3).setIsUndef();
2472
2473 const MCInstrDesc &OpDesc = get(AMDGPU::V_MOV_B32_indirect_write);
2475 BuildMI(MBB, MI, DL, OpDesc)
2476 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2477 .add(MI.getOperand(2))
2479 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2480
2481 const int ImpDefIdx =
2482 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2483 const int ImpUseIdx = ImpDefIdx + 1;
2484 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2485
2486 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2487
2488 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2489
2490 MI.eraseFromParent();
2491 break;
2492 }
2493 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2494 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2495 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2496 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2497 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2498 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2499 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2500 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2501 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2502 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2503 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2504 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2505 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2506 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2507 assert(ST.useVGPRIndexMode());
2508 Register Dst = MI.getOperand(0).getReg();
2509 Register VecReg = MI.getOperand(1).getReg();
2510 bool IsUndef = MI.getOperand(1).isUndef();
2511 Register SubReg = MI.getOperand(3).getImm();
2512
2513 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2514 .add(MI.getOperand(2))
2516 SetOn->getOperand(3).setIsUndef();
2517
2518 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_indirect_read))
2519 .addDef(Dst)
2520 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2521 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2522
2523 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2524
2525 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2526
2527 MI.eraseFromParent();
2528 break;
2529 }
2530 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2531 MachineFunction &MF = *MBB.getParent();
2532 Register Reg = MI.getOperand(0).getReg();
2533 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2534 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2535 MachineOperand OpLo = MI.getOperand(1);
2536 MachineOperand OpHi = MI.getOperand(2);
2537
2538 // Create a bundle so these instructions won't be re-ordered by the
2539 // post-RA scheduler.
2540 MIBundleBuilder Bundler(MBB, MI);
2541 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2542
2543 // What we want here is an offset from the value returned by s_getpc (which
2544 // is the address of the s_add_u32 instruction) to the global variable, but
2545 // since the encoding of $symbol starts 4 bytes after the start of the
2546 // s_add_u32 instruction, we end up with an offset that is 4 bytes too
2547 // small. This requires us to add 4 to the global variable offset in order
2548 // to compute the correct address. Similarly for the s_addc_u32 instruction,
2549 // the encoding of $symbol starts 12 bytes after the start of the s_add_u32
2550 // instruction.
2551
2552 int64_t Adjust = 0;
2553 if (ST.hasGetPCZeroExtension()) {
2554 // Fix up hardware that does not sign-extend the 48-bit PC value by
2555 // inserting: s_sext_i32_i16 reghi, reghi
2556 Bundler.append(
2557 BuildMI(MF, DL, get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2558 Adjust += 4;
2559 }
2560
2561 if (OpLo.isGlobal())
2562 OpLo.setOffset(OpLo.getOffset() + Adjust + 4);
2563 Bundler.append(
2564 BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2565
2566 if (OpHi.isGlobal())
2567 OpHi.setOffset(OpHi.getOffset() + Adjust + 12);
2568 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi)
2569 .addReg(RegHi)
2570 .add(OpHi));
2571
2572 finalizeBundle(MBB, Bundler.begin());
2573
2574 MI.eraseFromParent();
2575 break;
2576 }
2577 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2578 MachineFunction &MF = *MBB.getParent();
2579 Register Reg = MI.getOperand(0).getReg();
2580 MachineOperand Op = MI.getOperand(1);
2581
2582 // Create a bundle so these instructions won't be re-ordered by the
2583 // post-RA scheduler.
2584 MIBundleBuilder Bundler(MBB, MI);
2585 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2586 if (Op.isGlobal())
2587 Op.setOffset(Op.getOffset() + 4);
2588 Bundler.append(
2589 BuildMI(MF, DL, get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(Op));
2590
2591 finalizeBundle(MBB, Bundler.begin());
2592
2593 MI.eraseFromParent();
2594 break;
2595 }
2596 case AMDGPU::ENTER_STRICT_WWM: {
2597 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2598 // Whole Wave Mode is entered.
2599 MI.setDesc(get(LMC.OrSaveExecOpc));
2600 break;
2601 }
2602 case AMDGPU::ENTER_STRICT_WQM: {
2603 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2604 // STRICT_WQM is entered.
2605 BuildMI(MBB, MI, DL, get(LMC.MovOpc), MI.getOperand(0).getReg())
2606 .addReg(LMC.ExecReg);
2607 BuildMI(MBB, MI, DL, get(LMC.WQMOpc), LMC.ExecReg).addReg(LMC.ExecReg);
2608
2609 MI.eraseFromParent();
2610 break;
2611 }
2612 case AMDGPU::EXIT_STRICT_WWM:
2613 case AMDGPU::EXIT_STRICT_WQM: {
2614 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2615 // WWM/STICT_WQM is exited.
2616 MI.setDesc(get(LMC.MovOpc));
2617 break;
2618 }
2619 case AMDGPU::SI_RETURN: {
2620 const MachineFunction *MF = MBB.getParent();
2621 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2622 const SIRegisterInfo *TRI = ST.getRegisterInfo();
2623 // Hiding the return address use with SI_RETURN may lead to extra kills in
2624 // the function and missing live-ins. We are fine in practice because callee
2625 // saved register handling ensures the register value is restored before
2626 // RET, but we need the undef flag here to appease the MachineVerifier
2627 // liveness checks.
2629 BuildMI(MBB, MI, DL, get(AMDGPU::S_SETPC_B64_return))
2630 .addReg(TRI->getReturnAddressReg(*MF), RegState::Undef);
2631
2632 MIB.copyImplicitOps(MI);
2633 MI.eraseFromParent();
2634 break;
2635 }
2636
2637 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2638 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2639 MI.setDesc(get(AMDGPU::S_MUL_U64));
2640 break;
2641
2642 case AMDGPU::S_GETPC_B64_pseudo:
2643 MI.setDesc(get(AMDGPU::S_GETPC_B64));
2644 if (ST.hasGetPCZeroExtension()) {
2645 Register Dst = MI.getOperand(0).getReg();
2646 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2647 // Fix up hardware that does not sign-extend the 48-bit PC value by
2648 // inserting: s_sext_i32_i16 dsthi, dsthi
2649 BuildMI(MBB, std::next(MI.getIterator()), DL, get(AMDGPU::S_SEXT_I32_I16),
2650 DstHi)
2651 .addReg(DstHi);
2652 }
2653 break;
2654
2655 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2656 assert(ST.hasBF16PackedInsts());
2657 MI.setDesc(get(AMDGPU::V_PK_MAX_NUM_BF16));
2658 MI.addOperand(MachineOperand::CreateImm(0)); // op_sel
2659 MI.addOperand(MachineOperand::CreateImm(0)); // neg_lo
2660 MI.addOperand(MachineOperand::CreateImm(0)); // neg_hi
2661 auto Op0 = getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
2662 Op0->setImm(Op0->getImm() | SISrcMods::OP_SEL_1);
2663 auto Op1 = getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
2664 Op1->setImm(Op1->getImm() | SISrcMods::OP_SEL_1);
2665 break;
2666 }
2667
2668 case AMDGPU::GET_STACK_BASE:
2669 // The stack starts at offset 0 unless we need to reserve some space at the
2670 // bottom.
2671 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*MBB.getParent())) {
2672 // When CWSR is used in dynamic VGPR mode, the trap handler needs to save
2673 // some of the VGPRs. The size of the required scratch space has already
2674 // been computed by prolog epilog insertion.
2675 const SIMachineFunctionInfo *MFI =
2676 MBB.getParent()->getInfo<SIMachineFunctionInfo>();
2677 unsigned VGPRSize = MFI->getScratchReservedForDynamicVGPRs();
2678 Register DestReg = MI.getOperand(0).getReg();
2679 BuildMI(MBB, MI, DL, get(AMDGPU::S_GETREG_B32), DestReg)
2682 // The MicroEngine ID is 0 for the graphics queue, and 1 or 2 for compute
2683 // (3 is unused, so we ignore it). Unfortunately, S_GETREG doesn't set
2684 // SCC, so we need to check for 0 manually.
2685 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)).addImm(0).addReg(DestReg);
2686 // Change the implicif-def of SCC to an explicit use (but first remove
2687 // the dead flag if present).
2688 MI.getOperand(MI.getNumExplicitOperands()).setIsDead(false);
2689 MI.getOperand(MI.getNumExplicitOperands()).setIsUse();
2690 MI.setDesc(get(AMDGPU::S_CMOVK_I32));
2691 MI.addOperand(MachineOperand::CreateImm(VGPRSize));
2692 } else {
2693 MI.setDesc(get(AMDGPU::S_MOV_B32));
2694 MI.addOperand(MachineOperand::CreateImm(0));
2695 MI.removeOperand(
2696 MI.getNumExplicitOperands()); // Drop implicit def of SCC.
2697 }
2698 break;
2699 }
2700
2701 return true;
2702}
2703
2706 unsigned SubIdx, const MachineInstr &Orig,
2707 LaneBitmask UsedLanes) const {
2708
2709 // Try shrinking the instruction to remat only the part needed for current
2710 // context.
2711 // TODO: Handle more cases.
2712 unsigned Opcode = Orig.getOpcode();
2713 switch (Opcode) {
2714 case AMDGPU::S_MOV_B64:
2715 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2716 if (SubIdx != 0)
2717 break;
2718
2719 if (!Orig.getOperand(1).isImm())
2720 break;
2721
2722 // Shrink S_MOV_B64 to S_MOV_B32 when UsedLanes indicates only a single
2723 // 32-bit lane of the 64-bit value is live at the rematerialization point.
2724 if (UsedLanes.all())
2725 break;
2726
2727 // Determine which half of the 64-bit immediate corresponds to the use.
2728 unsigned OrigSubReg = Orig.getOperand(0).getSubReg();
2729 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2730 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2731
2732 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2733 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2734
2735 if (NeedLo && NeedHi)
2736 break;
2737
2738 int64_t Imm64 = Orig.getOperand(1).getImm();
2739 int32_t Imm32 = NeedLo ? Lo_32(Imm64) : Hi_32(Imm64);
2740
2741 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2742
2743 // Emit S_MOV_B32 defining just the needed 32-bit subreg of DestReg.
2744 BuildMI(MBB, I, Orig.getDebugLoc(), get(AMDGPU::S_MOV_B32))
2745 .addReg(DestReg, RegState::Define | RegState::Undef, UseSubReg)
2746 .addImm(Imm32);
2747 return;
2748 }
2749
2750 case AMDGPU::S_LOAD_DWORDX16_IMM:
2751 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2752 if (SubIdx != 0 || UsedLanes.all())
2753 break;
2754
2755 if (I == MBB.end())
2756 break;
2757
2758 if (I->isBundled())
2759 break;
2760
2761 MachineFunction *MF = MBB.getParent();
2763 assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");
2764
2765 // Look for a single use of the register at the insertion point that is also
2766 // a subreg.
2767 Register RegToFind = Orig.getOperand(0).getReg();
2768 MachineOperand *UseMO = MRI.getOneNonDBGUse(RegToFind);
2769 if (!UseMO ||
2770 UseMO != I->findRegisterUseOperand(RegToFind, /*TRI=*/nullptr) ||
2771 UseMO->getSubReg() == AMDGPU::NoSubRegister)
2772 break;
2773
2774 unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
2775 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());
2776
2777 unsigned NewOpcode = -1;
2778 if (SubregSize == 256)
2779 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2780 else if (SubregSize == 128)
2781 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2782 else
2783 break;
2784
2785 const MCInstrDesc &TID = get(NewOpcode);
2786 const TargetRegisterClass *NewRC =
2787 RI.getAllocatableClass(getRegClass(TID, 0));
2788 MRI.setRegClass(DestReg, NewRC);
2789
2790 UseMO->setReg(DestReg);
2791 UseMO->setSubReg(AMDGPU::NoSubRegister);
2792
2793 // Use a smaller load with the desired size, possibly with updated offset.
2794 MachineInstr *MI = MF->CloneMachineInstr(&Orig);
2795 MI->setDesc(TID);
2796 MI->getOperand(0).setReg(DestReg);
2797 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2798 if (Offset) {
2799 MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
2800 int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
2801 OffsetMO->setImm(FinalOffset);
2802 }
2804 for (const MachineMemOperand *MemOp : Orig.memoperands())
2805 NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
2806 SubregSize / 8));
2807 MI->setMemRefs(*MF, NewMMOs);
2808
2809 MBB.insert(I, MI);
2810 return;
2811 }
2812
2813 default:
2814 break;
2815 }
2816
2817 TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
2818}
2819
2820std::pair<MachineInstr*, MachineInstr*>
2822 assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2823
2824 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2826 ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
2827 MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
2828 return std::pair(&MI, nullptr);
2829 }
2830
2831 MachineBasicBlock &MBB = *MI.getParent();
2832 DebugLoc DL = MBB.findDebugLoc(MI);
2833 MachineFunction *MF = MBB.getParent();
2835 Register Dst = MI.getOperand(0).getReg();
2836 unsigned Part = 0;
2837 MachineInstr *Split[2];
2838
2839 for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2840 auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
2841 if (Dst.isPhysical()) {
2842 MovDPP.addDef(RI.getSubReg(Dst, Sub));
2843 } else {
2844 assert(MRI.isSSA());
2845 auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2846 MovDPP.addDef(Tmp);
2847 }
2848
2849 for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
2850 const MachineOperand &SrcOp = MI.getOperand(I);
2851 assert(!SrcOp.isFPImm());
2852 if (SrcOp.isImm()) {
2853 APInt Imm(64, SrcOp.getImm());
2854 Imm.ashrInPlace(Part * 32);
2855 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2856 } else {
2857 assert(SrcOp.isReg());
2858 Register Src = SrcOp.getReg();
2859 if (Src.isPhysical())
2860 MovDPP.addReg(RI.getSubReg(Src, Sub));
2861 else
2862 MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
2863 }
2864 }
2865
2866 for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
2867 MovDPP.addImm(MO.getImm());
2868
2869 Split[Part] = MovDPP;
2870 ++Part;
2871 }
2872
2873 if (Dst.isVirtual())
2874 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
2875 .addReg(Split[0]->getOperand(0).getReg())
2876 .addImm(AMDGPU::sub0)
2877 .addReg(Split[1]->getOperand(0).getReg())
2878 .addImm(AMDGPU::sub1);
2879
2880 MI.eraseFromParent();
2881 return std::pair(Split[0], Split[1]);
2882}
2883
2884std::optional<DestSourcePair>
2886 if (MI.getOpcode() == AMDGPU::WWM_COPY)
2887 return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
2888
2889 return std::nullopt;
2890}
2891
2893 AMDGPU::OpName Src0OpName,
2894 MachineOperand &Src1,
2895 AMDGPU::OpName Src1OpName) const {
2896 MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
2897 if (!Src0Mods)
2898 return false;
2899
2900 MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
2901 assert(Src1Mods &&
2902 "All commutable instructions have both src0 and src1 modifiers");
2903
2904 int Src0ModsVal = Src0Mods->getImm();
2905 int Src1ModsVal = Src1Mods->getImm();
2906
2907 Src1Mods->setImm(Src0ModsVal);
2908 Src0Mods->setImm(Src1ModsVal);
2909 return true;
2910}
2911
2913 MachineOperand &RegOp,
2914 MachineOperand &NonRegOp) {
2915 Register Reg = RegOp.getReg();
2916 unsigned SubReg = RegOp.getSubReg();
2917 bool IsKill = RegOp.isKill();
2918 bool IsDead = RegOp.isDead();
2919 bool IsUndef = RegOp.isUndef();
2920 bool IsDebug = RegOp.isDebug();
2921
2922 if (NonRegOp.isImm())
2923 RegOp.ChangeToImmediate(NonRegOp.getImm());
2924 else if (NonRegOp.isFI())
2925 RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
2926 else if (NonRegOp.isGlobal()) {
2927 RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
2928 NonRegOp.getTargetFlags());
2929 } else
2930 return nullptr;
2931
2932 // Make sure we don't reinterpret a subreg index in the target flags.
2933 RegOp.setTargetFlags(NonRegOp.getTargetFlags());
2934
2935 NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
2936 NonRegOp.setSubReg(SubReg);
2937
2938 return &MI;
2939}
2940
2942 MachineOperand &NonRegOp1,
2943 MachineOperand &NonRegOp2) {
2944 unsigned TargetFlags = NonRegOp1.getTargetFlags();
2945 int64_t NonRegVal = NonRegOp1.getImm();
2946
2947 NonRegOp1.setImm(NonRegOp2.getImm());
2948 NonRegOp2.setImm(NonRegVal);
2949 NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
2950 NonRegOp2.setTargetFlags(TargetFlags);
2951 return &MI;
2952}
2953
2954// GFX950 v_pk_{add,mul}_f32 must not have opsel[1:0] == 2'b10, i.e. OP_SEL_0 on
2955// src1 but not on src0, and v_pk_fma_f32 must not have OP_SEL_0 on src1 or
2956// src2.
2958 bool CheckSwappedSrc = false) {
2959 unsigned Opc = MI.getOpcode();
2960 if (!TII.getSubtarget().hasPkF32InvalidOpSel() ||
2961 (Opc != AMDGPU::V_PK_ADD_F32 && Opc != AMDGPU::V_PK_MUL_F32 &&
2962 Opc != AMDGPU::V_PK_FMA_F32))
2963 return true;
2964
2965 auto Mods = [&](AMDGPU::OpName Name) {
2966 const MachineOperand *Op = TII.getNamedOperand(MI, Name);
2967 return Op ? static_cast<unsigned>(Op->getImm()) : 0u;
2968 };
2969 unsigned Src0Mods = Mods(AMDGPU::OpName::src0_modifiers);
2970 unsigned Src1Mods = Mods(AMDGPU::OpName::src1_modifiers);
2971 unsigned Src2Mods = Mods(AMDGPU::OpName::src2_modifiers);
2972
2973 if (CheckSwappedSrc)
2974 std::swap(Src0Mods, Src1Mods);
2975
2976 if (Opc == AMDGPU::V_PK_FMA_F32)
2977 return !((Src1Mods | Src2Mods) & SISrcMods::OP_SEL_0);
2978 return (Src0Mods & SISrcMods::OP_SEL_0) || !(Src1Mods & SISrcMods::OP_SEL_0);
2979}
2980
2981bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
2982 unsigned OpIdx1) const {
2983 const MCInstrDesc &InstDesc = MI.getDesc();
2984 const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
2985 const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];
2986
2987 unsigned Opc = MI.getOpcode();
2988 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2989 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
2990
2991 // Swapping src0 and src1 swaps their modifiers; refuse a swap that would
2992 // leave an invalid GFX950 packed FP32 op_sel.
2993 bool IsSrc01Swap = ((int)OpIdx0 == Src0Idx && (int)OpIdx1 == Src1Idx) ||
2994 ((int)OpIdx0 == Src1Idx && (int)OpIdx1 == Src0Idx);
2995 if (IsSrc01Swap && !isLegalPkF32OpSel(*this, MI, true))
2996 return false;
2997
2998 const MachineOperand &MO0 = MI.getOperand(OpIdx0);
2999 const MachineOperand &MO1 = MI.getOperand(OpIdx1);
3000
3001 // Swap doesn't breach constant bus or literal limits, but it may move a
3002 // constant out of src0. Allow that for immediates where the destination
3003 // operand can hold them, e.g. VOP3 sources on targets with VOP3 literal
3004 // support. Other non-register operands stay in src0.
3005 if (isVALU(MI, /*AllowLDSDMA=*/false)) {
3006 if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
3007 (!MO0.isImm() || !isImmOperandLegal(MI, OpIdx1, MO0)))
3008 return false;
3009 if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
3010 (!MO1.isImm() || !isImmOperandLegal(MI, OpIdx0, MO1)))
3011 return false;
3012 }
3013
3014 if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
3015 if (OpInfo1.RegClass == -1)
3016 return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
3017 return isLegalRegOperand(MI, OpIdx1, MO0) &&
3018 (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
3019 }
3020 if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
3021 if (OpInfo0.RegClass == -1)
3022 return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
3023 return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
3024 isLegalRegOperand(MI, OpIdx0, MO1);
3025 }
3026
3027 // No need to check 64-bit literals since swapping does not bring new
3028 // 64-bit literals into current instruction to fold to 32-bit
3029
3030 return isImmOperandLegal(MI, OpIdx1, MO0);
3031}
3032
3034 if (!isDPP(MI))
3035 return false;
3036 const MachineOperand *DppCtrl = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
3037 return !DppCtrl || DppCtrl->getImm() != AMDGPU::DPP::QUAD_PERM_ID;
3038}
3039
3041 unsigned Src0Idx,
3042 unsigned Src1Idx) const {
3043 assert(!NewMI && "this should never be used");
3044
3046 return nullptr;
3047
3048 unsigned Opc = MI.getOpcode();
3049 int CommutedOpcode = commuteOpcode(Opc);
3050 if (CommutedOpcode == -1)
3051 return nullptr;
3052
3053 if (Src0Idx > Src1Idx)
3054 std::swap(Src0Idx, Src1Idx);
3055
3056 assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
3057 static_cast<int>(Src0Idx) &&
3058 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
3059 static_cast<int>(Src1Idx) &&
3060 "inconsistency with findCommutedOpIndices");
3061
3062 if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
3063 return nullptr;
3064
3065 MachineInstr *CommutedMI = nullptr;
3066 MachineOperand &Src0 = MI.getOperand(Src0Idx);
3067 MachineOperand &Src1 = MI.getOperand(Src1Idx);
3068 if (Src0.isReg() && Src1.isReg()) {
3069 // Be sure to copy the source modifiers to the right place.
3070 CommutedMI =
3071 TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
3072 } else if (Src0.isReg() && !Src1.isReg()) {
3073 CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
3074 } else if (!Src0.isReg() && Src1.isReg()) {
3075 CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
3076 } else if (Src0.isImm() && Src1.isImm()) {
3077 CommutedMI = swapImmOperands(MI, Src0, Src1);
3078 } else {
3079 // FIXME: Found two non registers to commute. This does happen.
3080 return nullptr;
3081 }
3082
3083 if (CommutedMI) {
3084 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
3085 Src1, AMDGPU::OpName::src1_modifiers);
3086
3087 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
3088 AMDGPU::OpName::src1_sel);
3089
3090 CommutedMI->setDesc(get(CommutedOpcode));
3091 }
3092
3093 return CommutedMI;
3094}
3095
3096// This needs to be implemented because the source modifiers may be inserted
3097// between the true commutable operands, and the base
3098// TargetInstrInfo::commuteInstruction uses it.
3100 unsigned &SrcOpIdx0,
3101 unsigned &SrcOpIdx1) const {
3103 return false;
3104
3105 return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
3106}
3107
3109 unsigned &SrcOpIdx0,
3110 unsigned &SrcOpIdx1) const {
3111 if (!Desc.isCommutable())
3112 return false;
3113
3114 unsigned Opc = Desc.getOpcode();
3115 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
3116 if (Src0Idx == -1)
3117 return false;
3118
3119 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
3120 if (Src1Idx == -1)
3121 return false;
3122
3123 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3124}
3125
3127 int64_t BrOffset) const {
3128 // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
3129 // because its dest block is unanalyzable.
3130 assert(isSOPP(BranchOp) || isSOPK(BranchOp));
3131
3132 // Convert to dwords.
3133 BrOffset /= 4;
3134
3135 // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
3136 // from the next instruction.
3137 BrOffset -= 1;
3138
3139 return isIntN(BranchOffsetBits, BrOffset);
3140}
3141
3144 return MI.getOperand(0).getMBB();
3145}
3146
3148 for (const MachineInstr &MI : MBB->terminators()) {
3149 if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
3150 MI.getOpcode() == AMDGPU::SI_LOOP ||
3151 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3152 return true;
3153 }
3154 return false;
3155}
3156
3158 MachineBasicBlock &DestBB,
3159 MachineBasicBlock &RestoreBB,
3160 const DebugLoc &DL, int64_t BrOffset,
3161 RegScavenger *RS) const {
3162 assert(MBB.empty() &&
3163 "new block should be inserted for expanding unconditional branch");
3164 assert(MBB.pred_size() == 1);
3165 assert(RestoreBB.empty() &&
3166 "restore block should be inserted for restoring clobbered registers");
3167
3168 MachineFunction *MF = MBB.getParent();
3171 auto I = MBB.end();
3172 auto &MCCtx = MF->getContext();
3173
3174 if (ST.useAddPCI64Inst()) {
3175 MCSymbol *Offset =
3176 MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
3177 auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
3179 MCSymbol *PostAddPCLabel =
3180 MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
3181 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3182 auto *OffsetExpr = MCBinaryExpr::createSub(
3183 MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
3184 MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
3185 Offset->setVariableValue(OffsetExpr);
3186 return;
3187 }
3188
3189 assert(RS && "RegScavenger required for long branching");
3190
3191 // FIXME: Virtual register workaround for RegScavenger not working with empty
3192 // blocks.
3193 Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3194
3195 // Note: as this is used after hazard recognizer we need to apply some hazard
3196 // workarounds directly.
3197 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3198 ST.hasVALUReadSGPRHazard();
3199 auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
3200 if (FlushSGPRWrites)
3201 BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
3203 };
3204
3205 // We need to compute the offset relative to the instruction immediately after
3206 // s_getpc_b64. Insert pc arithmetic code before last terminator.
3207 MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
3208 ApplyHazardWorkarounds();
3209
3210 MCSymbol *PostGetPCLabel =
3211 MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
3212 GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);
3213
3214 MCSymbol *OffsetLo =
3215 MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
3216 MCSymbol *OffsetHi =
3217 MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
3218 BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
3219 .addReg(PCReg, RegState::Define, AMDGPU::sub0)
3220 .addReg(PCReg, {}, AMDGPU::sub0)
3221 .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
3222 BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
3223 .addReg(PCReg, RegState::Define, AMDGPU::sub1)
3224 .addReg(PCReg, {}, AMDGPU::sub1)
3225 .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
3226 ApplyHazardWorkarounds();
3227
3228 // Insert the indirect branch after the other terminator.
3229 BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
3230 .addReg(PCReg);
3231
3232 // If a spill is needed for the pc register pair, we need to insert a spill
3233 // restore block right before the destination block, and insert a short branch
3234 // into the old destination block's fallthrough predecessor.
3235 // e.g.:
3236 //
3237 // s_cbranch_scc0 skip_long_branch:
3238 //
3239 // long_branch_bb:
3240 // spill s[8:9]
3241 // s_getpc_b64 s[8:9]
3242 // s_add_u32 s8, s8, restore_bb
3243 // s_addc_u32 s9, s9, 0
3244 // s_setpc_b64 s[8:9]
3245 //
3246 // skip_long_branch:
3247 // foo;
3248 //
3249 // .....
3250 //
3251 // dest_bb_fallthrough_predecessor:
3252 // bar;
3253 // s_branch dest_bb
3254 //
3255 // restore_bb:
3256 // restore s[8:9]
3257 // fallthrough dest_bb
3258 ///
3259 // dest_bb:
3260 // buzz;
3261
3262 Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
3263 Register Scav;
3264
3265 // If we've previously reserved a register for long branches
3266 // avoid running the scavenger and just use those registers
3267 if (LongBranchReservedReg) {
3268 RS->enterBasicBlock(MBB);
3269 Scav = LongBranchReservedReg;
3270 } else {
3271 RS->enterBasicBlockEnd(MBB);
3272 Scav = RS->scavengeRegisterBackwards(
3273 AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
3274 /* RestoreAfter */ false, 0, /* AllowSpill */ false);
3275 }
3276 if (Scav) {
3277 RS->setRegUsed(Scav);
3278 MRI.replaceRegWith(PCReg, Scav);
3279 MRI.clearVirtRegs();
3280 } else {
3281 // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
3282 // SGPR spill.
3283 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
3284 const SIRegisterInfo *TRI = ST.getRegisterInfo();
3285 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3286 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3287 MRI.clearVirtRegs();
3288 }
3289
3290 MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
3291 // Now, the distance could be defined.
3293 MCSymbolRefExpr::create(DestLabel, MCCtx),
3294 MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
3295 // Add offset assignments.
3296 auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
3297 OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
3298 auto *ShAmt = MCConstantExpr::create(32, MCCtx);
3299 OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
3300}
3301
3302unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
3303 switch (Cond) {
3304 case SIInstrInfo::SCC_TRUE:
3305 return AMDGPU::S_CBRANCH_SCC1;
3306 case SIInstrInfo::SCC_FALSE:
3307 return AMDGPU::S_CBRANCH_SCC0;
3308 case SIInstrInfo::VCCNZ:
3309 return AMDGPU::S_CBRANCH_VCCNZ;
3310 case SIInstrInfo::VCCZ:
3311 return AMDGPU::S_CBRANCH_VCCZ;
3312 case SIInstrInfo::EXECNZ:
3313 return AMDGPU::S_CBRANCH_EXECNZ;
3314 case SIInstrInfo::EXECZ:
3315 return AMDGPU::S_CBRANCH_EXECZ;
3316 default:
3317 llvm_unreachable("invalid branch predicate");
3318 }
3319}
3320
3321SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
3322 switch (Opcode) {
3323 case AMDGPU::S_CBRANCH_SCC0:
3324 return SCC_FALSE;
3325 case AMDGPU::S_CBRANCH_SCC1:
3326 return SCC_TRUE;
3327 case AMDGPU::S_CBRANCH_VCCNZ:
3328 return VCCNZ;
3329 case AMDGPU::S_CBRANCH_VCCZ:
3330 return VCCZ;
3331 case AMDGPU::S_CBRANCH_EXECNZ:
3332 return EXECNZ;
3333 case AMDGPU::S_CBRANCH_EXECZ:
3334 return EXECZ;
3335 default:
3336 return INVALID_BR;
3337 }
3338}
3339
3343 MachineBasicBlock *&FBB,
3345 bool AllowModify) const {
3346 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3347 // Unconditional Branch
3348 TBB = I->getOperand(0).getMBB();
3349 return false;
3350 }
3351
3352 BranchPredicate Pred = getBranchPredicate(I->getOpcode());
3353 if (Pred == INVALID_BR)
3354 return true;
3355
3356 MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
3357 Cond.push_back(MachineOperand::CreateImm(Pred));
3358 Cond.push_back(I->getOperand(1)); // Save the branch register.
3359
3360 ++I;
3361
3362 if (I == MBB.end()) {
3363 // Conditional branch followed by fall-through.
3364 TBB = CondBB;
3365 return false;
3366 }
3367
3368 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3369 TBB = CondBB;
3370 FBB = I->getOperand(0).getMBB();
3371 return false;
3372 }
3373
3374 return true;
3375}
3376
3378 MachineBasicBlock *&FBB,
3380 bool AllowModify) const {
3381 MachineBasicBlock::iterator I = MBB.getFirstTerminator();
3382 auto E = MBB.end();
3383 if (I == E)
3384 return false;
3385
3386 // Skip over the instructions that are artificially terminators for special
3387 // exec management.
3388 while (I != E && !I->isBranch() && !I->isReturn()) {
3389 switch (I->getOpcode()) {
3390 case AMDGPU::S_MOV_B64_term:
3391 case AMDGPU::S_XOR_B64_term:
3392 case AMDGPU::S_OR_B64_term:
3393 case AMDGPU::S_ANDN2_B64_term:
3394 case AMDGPU::S_AND_B64_term:
3395 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3396 case AMDGPU::S_MOV_B32_term:
3397 case AMDGPU::S_XOR_B32_term:
3398 case AMDGPU::S_OR_B32_term:
3399 case AMDGPU::S_ANDN2_B32_term:
3400 case AMDGPU::S_AND_B32_term:
3401 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3402 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3403 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3404 break;
3405 case AMDGPU::SI_IF:
3406 case AMDGPU::SI_ELSE:
3407 case AMDGPU::SI_KILL_I1_TERMINATOR:
3408 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3409 // FIXME: It's messy that these need to be considered here at all.
3410 return true;
3411 default:
3412 llvm_unreachable("unexpected non-branch terminator inst");
3413 }
3414
3415 ++I;
3416 }
3417
3418 if (I == E)
3419 return false;
3420
3421 return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
3422}
3423
3425 int *BytesRemoved) const {
3426 unsigned Count = 0;
3427 unsigned RemovedSize = 0;
3428 for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
3429 // Skip over artificial terminators when removing instructions.
3430 if (MI.isBranch() || MI.isReturn()) {
3431 RemovedSize += getInstSizeInBytes(MI);
3432 MI.eraseFromParent();
3433 ++Count;
3434 }
3435 }
3436
3437 if (BytesRemoved)
3438 *BytesRemoved = RemovedSize;
3439
3440 return Count;
3441}
3442
3443// Copy the flags onto the implicit condition register operand.
3445 const MachineOperand &OrigCond) {
3446 CondReg.setIsUndef(OrigCond.isUndef());
3447 CondReg.setIsKill(OrigCond.isKill());
3448}
3449
3452 MachineBasicBlock *FBB,
3454 const DebugLoc &DL,
3455 int *BytesAdded) const {
3456 if (!FBB && Cond.empty()) {
3457 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3458 .addMBB(TBB);
3459 if (BytesAdded)
3460 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3461 return 1;
3462 }
3463
3464 assert(TBB && Cond[0].isImm());
3465
3466 unsigned Opcode
3467 = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));
3468
3469 if (!FBB) {
3470 MachineInstr *CondBr =
3471 BuildMI(&MBB, DL, get(Opcode))
3472 .addMBB(TBB);
3473
3474 // Copy the flags onto the implicit condition register operand.
3475 preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
3476 fixImplicitOperands(*CondBr);
3477
3478 if (BytesAdded)
3479 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3480 return 1;
3481 }
3482
3483 assert(TBB && FBB);
3484
3485 MachineInstr *CondBr =
3486 BuildMI(&MBB, DL, get(Opcode))
3487 .addMBB(TBB);
3488 fixImplicitOperands(*CondBr);
3489 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3490 .addMBB(FBB);
3491
3492 MachineOperand &CondReg = CondBr->getOperand(1);
3493 CondReg.setIsUndef(Cond[1].isUndef());
3494 CondReg.setIsKill(Cond[1].isKill());
3495
3496 if (BytesAdded)
3497 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3498
3499 return 2;
3500}
3501
3504 if (Cond.size() != 2) {
3505 return true;
3506 }
3507
3508 if (Cond[0].isImm()) {
3509 Cond[0].setImm(-Cond[0].getImm());
3510 return false;
3511 }
3512
3513 return true;
3514}
3515
3516namespace {
3517class AMDGPUPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
3518private:
3519 /// The compare instruction for loop control
3520 const MachineInstr *CmpInst = nullptr;
3521 /// The normalized condition used by createTripCountGreaterCondition()
3523
3524public:
3525 AMDGPUPipelinerLoopInfo(MachineInstr *CmpInst,
3527 : CmpInst(CmpInst), Cond(Cond.begin(), Cond.end()) {}
3528
3529 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
3530 return CmpInst && MI == CmpInst;
3531 }
3532
3533 std::optional<bool> createTripCountGreaterCondition(
3534 int TC, MachineBasicBlock &MBB,
3535 SmallVectorImpl<MachineOperand> &CondParam) override {
3536 CondParam = this->Cond;
3537 return {};
3538 }
3539
3540 void adjustTripCount(int TripCountAdjust) override {}
3541
3542 void setPreheader(MachineBasicBlock *NewPreheader) override {}
3543};
3544} // namespace
3545
3546std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3548 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
3550 // Unanalyzable terminator.
3551 if (analyzeBranch(*LoopBB, TBB, FBB, Cond, /*AllowModify=*/false))
3552 return nullptr;
3553
3554 // Infinite loops are not supported.
3555 if (TBB == LoopBB && FBB == LoopBB)
3556 return nullptr;
3557
3558 // Must be conditional branch.
3559 if (FBB == nullptr)
3560 return nullptr;
3561
3562 assert((TBB == LoopBB || FBB == LoopBB) &&
3563 "The Loop must be a single-basic-block loop");
3564
3565 // Divergent (VCC/EXEC) back-edge is not supported.
3566 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3567 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3568 return nullptr;
3569
3570 // Calls and inline assembly are not supported.
3571 for (const MachineInstr &MI : *LoopBB)
3572 if (MI.isCall() || MI.isInlineAsm())
3573 return nullptr;
3574
3575 // Normalization for createTripCountGreaterCondition(): make Cond mean
3576 // "exit the loop" so the expander emits correct prolog guard branches.
3577 if (TBB == LoopBB)
3579
3580 auto Instructions = make_range(
3582 LoopBB->rend());
3583 auto CmpI = llvm::find_if(Instructions, [&](const MachineInstr &MI) {
3584 return MI.modifiesRegister(Cond[1].getReg(), &RI);
3585 });
3586
3587 if (CmpI == Instructions.end() || CmpI->isPHI())
3588 return nullptr;
3589 MachineInstr *CmpInst = &*CmpI;
3590
3591 return std::make_unique<AMDGPUPipelinerLoopInfo>(CmpInst, Cond);
3592}
3593
3596 Register DstReg, Register TrueReg,
3597 Register FalseReg,
3598 SelectExpansion &Exp) const {
3599 switch (Cond[0].getImm()) {
3600 case VCCNZ:
3601 case VCCZ: {
3602 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3603 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3604 if (MRI.getRegClass(FalseReg) != RC)
3605 return false;
3606
3607 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3608 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts; // ???
3609
3610 // Limit to equal cost for branch vs. N v_cndmask_b32s.
3611 return RI.hasVGPRs(RC) && NumInsts <= 6;
3612 }
3613 case SCC_TRUE:
3614 case SCC_FALSE: {
3615 // FIXME: We could insert for VGPRs if we could replace the original compare
3616 // with a vector one.
3617 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3618 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3619 if (MRI.getRegClass(FalseReg) != RC)
3620 return false;
3621
3622 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3623
3624 // Multiples of 8 can do s_cselect_b64
3625 if (NumInsts % 2 == 0)
3626 NumInsts /= 2;
3627
3628 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts; // ???
3629 return RI.isSGPRClass(RC);
3630 }
3631 default:
3632 return false;
3633 }
3634}
3635
3639 Register TrueReg, Register FalseReg) const {
3640 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3641 if (Pred == VCCZ || Pred == SCC_FALSE) {
3642 Pred = static_cast<BranchPredicate>(-Pred);
3643 std::swap(TrueReg, FalseReg);
3644 }
3645
3646 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3647 const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
3648 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3649
3650 if (DstSize == 32) {
3652 if (Pred == SCC_TRUE) {
3653 Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
3654 .addReg(TrueReg)
3655 .addReg(FalseReg);
3656 } else {
3657 // Instruction's operands are backwards from what is expected.
3658 Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
3659 .addReg(FalseReg)
3660 .addReg(TrueReg);
3661 }
3662
3663 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3664 return;
3665 }
3666
3667 if (DstSize == 64 && Pred == SCC_TRUE) {
3669 BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
3670 .addReg(TrueReg)
3671 .addReg(FalseReg);
3672
3673 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3674 return;
3675 }
3676
3677 static const int16_t Sub0_15[] = {
3678 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3679 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3680 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3681 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3682 };
3683
3684 static const int16_t Sub0_15_64[] = {
3685 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3686 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3687 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3688 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3689 };
3690
3691 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3692 const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
3693 const int16_t *SubIndices = Sub0_15;
3694 int NElts = DstSize / 32;
3695
3696 // 64-bit select is only available for SALU.
3697 // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
3698 if (Pred == SCC_TRUE) {
3699 if (NElts % 2) {
3700 SelOp = AMDGPU::S_CSELECT_B32;
3701 EltRC = &AMDGPU::SGPR_32RegClass;
3702 } else {
3703 SelOp = AMDGPU::S_CSELECT_B64;
3704 EltRC = &AMDGPU::SGPR_64RegClass;
3705 SubIndices = Sub0_15_64;
3706 NElts /= 2;
3707 }
3708 }
3709
3711 MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);
3712
3713 I = MIB->getIterator();
3714
3716 for (int Idx = 0; Idx != NElts; ++Idx) {
3717 Register DstElt = MRI.createVirtualRegister(EltRC);
3718 Regs.push_back(DstElt);
3719
3720 unsigned SubIdx = SubIndices[Idx];
3721
3723 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3724 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3725 .addReg(FalseReg, {}, SubIdx)
3726 .addReg(TrueReg, {}, SubIdx);
3727 } else {
3728 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3729 .addReg(TrueReg, {}, SubIdx)
3730 .addReg(FalseReg, {}, SubIdx);
3731 }
3732
3733 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3735
3736 MIB.addReg(DstElt)
3737 .addImm(SubIdx);
3738 }
3739}
3740
3742
3743 if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
3744 return true;
3745
3746 switch (MI.getOpcode()) {
3747 case AMDGPU::S_ENDPGM:
3748 case AMDGPU::S_ENDPGM_SAVED:
3749 case AMDGPU::S_TRAP:
3750 case AMDGPU::S_GETREG_B32:
3751 case AMDGPU::S_SETREG_B32:
3752 case AMDGPU::S_SETREG_B32_mode:
3753 case AMDGPU::S_SETREG_IMM32_B32:
3754 case AMDGPU::S_SETREG_IMM32_B32_mode:
3755 case AMDGPU::S_SENDMSG:
3756 case AMDGPU::S_SENDMSGHALT:
3757 case AMDGPU::S_SENDMSG_RTN_B32:
3758 case AMDGPU::S_SENDMSG_RTN_B64:
3759 case AMDGPU::S_BARRIER_WAIT:
3760 case AMDGPU::S_BARRIER_SIGNAL_M0:
3761 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3762 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3763 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3764 return true;
3765 default:
3766 return false;
3767 }
3768}
3769
3771 switch (MI.getOpcode()) {
3772 case AMDGPU::V_MOV_B16_t16_e32:
3773 case AMDGPU::V_MOV_B16_t16_e64:
3774 case AMDGPU::V_MOV_B32_e32:
3775 case AMDGPU::V_MOV_B32_e64:
3776 case AMDGPU::V_MOV_B64_PSEUDO:
3777 case AMDGPU::V_MOV_B64_e32:
3778 case AMDGPU::V_MOV_B64_e64:
3779 case AMDGPU::S_MOV_B32:
3780 case AMDGPU::S_MOV_B64:
3781 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3782 case AMDGPU::COPY:
3783 case AMDGPU::WWM_COPY:
3784 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3785 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3786 case AMDGPU::V_ACCVGPR_MOV_B32:
3787 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3788 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3789 return true;
3790 default:
3791 return false;
3792 }
3793}
3794
3796 switch (MI.getOpcode()) {
3797 case AMDGPU::V_MOV_B16_t16_e32:
3798 case AMDGPU::V_MOV_B16_t16_e64:
3799 return 2;
3800 case AMDGPU::V_MOV_B32_e32:
3801 case AMDGPU::V_MOV_B32_e64:
3802 case AMDGPU::V_MOV_B64_PSEUDO:
3803 case AMDGPU::V_MOV_B64_e32:
3804 case AMDGPU::V_MOV_B64_e64:
3805 case AMDGPU::S_MOV_B32:
3806 case AMDGPU::S_MOV_B64:
3807 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3808 case AMDGPU::COPY:
3809 case AMDGPU::WWM_COPY:
3810 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3811 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3812 case AMDGPU::V_ACCVGPR_MOV_B32:
3813 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3814 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3815 return 1;
3816 default:
3817 llvm_unreachable("MI is not a foldable copy");
3818 }
3819}
3820
3821static constexpr AMDGPU::OpName ModifierOpNames[] = {
3822 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3823 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3824 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3825
3827 unsigned Opc = MI.getOpcode();
3828 for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
3829 int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
3830 if (Idx >= 0)
3831 MI.removeOperand(Idx);
3832 }
3833}
3834
3836 const MCInstrDesc &NewDesc) const {
3837 MI.setDesc(NewDesc);
3838
3839 // Remove any leftover implicit operands from mutating the instruction. e.g.
3840 // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
3841 // anymore.
3842 const MCInstrDesc &Desc = MI.getDesc();
3843 unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
3844 Desc.implicit_defs().size();
3845
3846 for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
3847 MI.removeOperand(I);
3848}
3849
3850std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
3851 unsigned SubRegIndex) {
3852 switch (SubRegIndex) {
3853 case AMDGPU::NoSubRegister:
3854 return Imm;
3855 case AMDGPU::sub0:
3856 return SignExtend64<32>(Imm);
3857 case AMDGPU::sub1:
3858 return SignExtend64<32>(Imm >> 32);
3859 case AMDGPU::lo16:
3860 return SignExtend64<16>(Imm);
3861 case AMDGPU::hi16:
3862 return SignExtend64<16>(Imm >> 16);
3863 case AMDGPU::sub1_lo16:
3864 return SignExtend64<16>(Imm >> 32);
3865 case AMDGPU::sub1_hi16:
3866 return SignExtend64<16>(Imm >> 48);
3867 default:
3868 return std::nullopt;
3869 }
3870
3871 llvm_unreachable("covered subregister switch");
3872}
3873
3874static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
3875 switch (Opc) {
3876 case AMDGPU::V_MAC_F16_e32:
3877 case AMDGPU::V_MAC_F16_e64:
3878 case AMDGPU::V_MAD_F16_e64:
3879 return AMDGPU::V_MADAK_F16;
3880 case AMDGPU::V_MAC_F32_e32:
3881 case AMDGPU::V_MAC_F32_e64:
3882 case AMDGPU::V_MAD_F32_e64:
3883 return AMDGPU::V_MADAK_F32;
3884 case AMDGPU::V_FMAC_F32_e32:
3885 case AMDGPU::V_FMAC_F32_e64:
3886 case AMDGPU::V_FMA_F32_e64:
3887 return AMDGPU::V_FMAAK_F32;
3888 case AMDGPU::V_FMAC_F16_e32:
3889 case AMDGPU::V_FMAC_F16_e64:
3890 case AMDGPU::V_FMAC_F16_t16_e64:
3891 case AMDGPU::V_FMAC_F16_fake16_e64:
3892 case AMDGPU::V_FMAC_F16_t16_e32:
3893 case AMDGPU::V_FMAC_F16_fake16_e32:
3894 case AMDGPU::V_FMA_F16_e64:
3895 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3896 ? AMDGPU::V_FMAAK_F16_t16
3897 : AMDGPU::V_FMAAK_F16_fake16
3898 : AMDGPU::V_FMAAK_F16;
3899 case AMDGPU::V_FMAC_F64_e32:
3900 case AMDGPU::V_FMAC_F64_e64:
3901 case AMDGPU::V_FMA_F64_e64:
3902 return AMDGPU::V_FMAAK_F64;
3903 default:
3904 llvm_unreachable("invalid instruction");
3905 }
3906}
3907
3908static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
3909 switch (Opc) {
3910 case AMDGPU::V_MAC_F16_e32:
3911 case AMDGPU::V_MAC_F16_e64:
3912 case AMDGPU::V_MAD_F16_e64:
3913 return AMDGPU::V_MADMK_F16;
3914 case AMDGPU::V_MAC_F32_e32:
3915 case AMDGPU::V_MAC_F32_e64:
3916 case AMDGPU::V_MAD_F32_e64:
3917 return AMDGPU::V_MADMK_F32;
3918 case AMDGPU::V_FMAC_F32_e32:
3919 case AMDGPU::V_FMAC_F32_e64:
3920 case AMDGPU::V_FMA_F32_e64:
3921 return AMDGPU::V_FMAMK_F32;
3922 case AMDGPU::V_FMAC_F16_e32:
3923 case AMDGPU::V_FMAC_F16_e64:
3924 case AMDGPU::V_FMAC_F16_t16_e64:
3925 case AMDGPU::V_FMAC_F16_fake16_e64:
3926 case AMDGPU::V_FMAC_F16_t16_e32:
3927 case AMDGPU::V_FMAC_F16_fake16_e32:
3928 case AMDGPU::V_FMA_F16_e64:
3929 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3930 ? AMDGPU::V_FMAMK_F16_t16
3931 : AMDGPU::V_FMAMK_F16_fake16
3932 : AMDGPU::V_FMAMK_F16;
3933 case AMDGPU::V_FMAC_F64_e32:
3934 case AMDGPU::V_FMAC_F64_e64:
3935 case AMDGPU::V_FMA_F64_e64:
3936 return AMDGPU::V_FMAMK_F64;
3937 default:
3938 llvm_unreachable("invalid instruction");
3939 }
3940}
3941
3943 Register Reg, MachineRegisterInfo *MRI) const {
3944 int64_t Imm;
3945 if (!getConstValDefinedInReg(DefMI, Reg, Imm))
3946 return false;
3947
3948 const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);
3949
3950 assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");
3951
3952 unsigned Opc = UseMI.getOpcode();
3953 if (Opc == AMDGPU::COPY) {
3954 assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");
3955
3956 Register DstReg = UseMI.getOperand(0).getReg();
3957 Register UseSubReg = UseMI.getOperand(1).getSubReg();
3958
3959 const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);
3960
3961 if (HasMultipleUses) {
3962 // TODO: This should fold in more cases with multiple use, but we need to
3963 // more carefully consider what those uses are.
3964 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));
3965
3966 // Avoid breaking up a 64-bit inline immediate into a subregister extract.
3967 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3968 return false;
3969
3970 // Most of the time folding a 32-bit inline constant is free (though this
3971 // might not be true if we can't later fold it into a real user).
3972 //
3973 // FIXME: This isInlineConstant check is imprecise if
3974 // getConstValDefinedInReg handled the tricky non-mov cases.
3975 if (ImmDefSize == 32 &&
3977 return false;
3978 }
3979
3980 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3981 RI.getSubRegIdxSize(UseSubReg) == 16;
3982
3983 if (Is16Bit) {
3984 if (RI.hasVGPRs(DstRC))
3985 return false; // Do not clobber vgpr_hi16
3986
3987 if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
3988 return false;
3989 }
3990
3991 MachineFunction *MF = UseMI.getMF();
3992
3993 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3994 MCRegister MovDstPhysReg =
3995 DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();
3996
3997 std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);
3998
3999 // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
4000 for (unsigned MovOp :
4001 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
4002 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
4003 const MCInstrDesc &MovDesc = get(MovOp);
4004
4005 const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
4006 if (Is16Bit) {
4007 // We just need to find a correctly sized register class, so the
4008 // subregister index compatibility doesn't matter since we're statically
4009 // extracting the immediate value.
4010 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
4011 if (!MovDstRC)
4012 continue;
4013
4014 if (MovDstPhysReg) {
4015 // FIXME: We probably should not do this. If there is a live value in
4016 // the high half of the register, it will be corrupted.
4017 MovDstPhysReg =
4018 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
4019 if (!MovDstPhysReg)
4020 continue;
4021 }
4022 }
4023
4024 // Result class isn't the right size, try the next instruction.
4025 if (MovDstPhysReg) {
4026 if (!MovDstRC->contains(MovDstPhysReg))
4027 return false;
4028 } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
4029 // TODO: This will be overly conservative in the case of 16-bit virtual
4030 // SGPRs. We could hack up the virtual register uses to use a compatible
4031 // 32-bit class.
4032 continue;
4033 }
4034
4035 const MCOperandInfo &OpInfo = MovDesc.operands()[1];
4036
4037 // Ensure the interpreted immediate value is a valid operand in the new
4038 // mov.
4039 //
4040 // FIXME: isImmOperandLegal should have form that doesn't require existing
4041 // MachineInstr or MachineOperand
4042 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4043 !isInlineConstant(*SubRegImm, OpInfo.OperandType))
4044 break;
4045
4046 NewOpc = MovOp;
4047 break;
4048 }
4049
4050 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4051 return false;
4052
4053 if (Is16Bit) {
4054 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4055 if (MovDstPhysReg)
4056 UseMI.getOperand(0).setReg(MovDstPhysReg);
4057 assert(UseMI.getOperand(1).getReg().isVirtual());
4058 }
4059
4060 const MCInstrDesc &NewMCID = get(NewOpc);
4061 UseMI.setDesc(NewMCID);
4062 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4063 UseMI.addImplicitDefUseOperands(*MF);
4064 return true;
4065 }
4066
4067 if (HasMultipleUses)
4068 return false;
4069
4070 if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
4071 Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4072 Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
4073 Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
4074 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4075 Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
4076 Opc == AMDGPU::V_FMAC_F64_e64) {
4077 // Don't fold if we are using source or output modifiers. The new VOP2
4078 // instructions don't have them.
4080 return false;
4081
4082 // If this is a free constant, there's no reason to do this.
4083 // TODO: We could fold this here instead of letting SIFoldOperands do it
4084 // later.
4085 int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4086
4087 // Any src operand can be used for the legality check.
4088 if (isInlineConstant(UseMI, Src0Idx, Imm))
4089 return false;
4090
4091 MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);
4092
4093 MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
4094 MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);
4095
4096 auto CopyRegOperandToNarrowerRC =
4097 [MRI, this](MachineInstr &MI, unsigned OpNo,
4098 const TargetRegisterClass *NewRC) -> void {
4099 if (!MI.getOperand(OpNo).isReg())
4100 return;
4101 Register Reg = MI.getOperand(OpNo).getReg();
4102 const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
4103 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4104 return;
4105 Register Tmp = MRI->createVirtualRegister(NewRC);
4106 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
4107 get(AMDGPU::COPY), Tmp)
4108 .addReg(Reg);
4109 MI.getOperand(OpNo).setReg(Tmp);
4110 };
4111
4112 // Multiplied part is the constant: Use v_madmk_{f16, f32}.
4113 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4114 (Src1->isReg() && Src1->getReg() == Reg)) {
4115 MachineOperand *RegSrc =
4116 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4117 if (!RegSrc->isReg())
4118 return false;
4119 if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
4120 ST.getConstantBusLimit(Opc) < 2)
4121 return false;
4122
4123 if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
4124 return false;
4125
4126 // If src2 is also a literal constant then we have to choose which one to
4127 // fold. In general it is better to choose madak so that the other literal
4128 // can be materialized in an sgpr instead of a vgpr:
4129 // s_mov_b32 s0, literal
4130 // v_madak_f32 v0, s0, v0, literal
4131 // Instead of:
4132 // v_mov_b32 v1, literal
4133 // v_madmk_f32 v0, v0, literal, v1
4134 MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
4135 if (Def && Def->isMoveImmediate() &&
4136 !isInlineConstant(Def->getOperand(1)))
4137 return false;
4138
4139 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4140 if (pseudoToMCOpcode(NewOpc) == -1)
4141 return false;
4142
4143 const std::optional<int64_t> SubRegImm = extractSubregFromImm(
4144 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4145
4146 // FIXME: This would be a lot easier if we could return a new instruction
4147 // instead of having to modify in place.
4148
4149 Register SrcReg = RegSrc->getReg();
4150 unsigned SrcSubReg = RegSrc->getSubReg();
4151 Src0->setReg(SrcReg);
4152 Src0->setSubReg(SrcSubReg);
4153 Src0->setIsKill(RegSrc->isKill());
4154
4155 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4156 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4157 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4158 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4159 UseMI.untieRegOperand(
4160 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4161
4162 Src1->ChangeToImmediate(*SubRegImm);
4163
4165 UseMI.setDesc(get(NewOpc));
4166
4167 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4168 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4169 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4170 Register Tmp = MRI->createVirtualRegister(NewRC);
4171 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4172 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4173 UseMI.getOperand(0).getReg())
4174 .addReg(Tmp);
4175 UseMI.getOperand(0).setReg(Tmp);
4176 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4177 CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
4178 }
4179
4180 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4181 if (DeleteDef)
4182 DefMI.eraseFromParent();
4183
4184 return true;
4185 }
4186
4187 // Added part is the constant: Use v_madak_{f16, f32}.
4188 if (Src2->isReg() && Src2->getReg() == Reg) {
4189 if (ST.getConstantBusLimit(Opc) < 2) {
4190 // Not allowed to use constant bus for another operand.
4191 // We can however allow an inline immediate as src0.
4192 bool Src0Inlined = false;
4193 if (Src0->isReg()) {
4194 // Try to inline constant if possible.
4195 // If the Def moves immediate and the use is single
4196 // We are saving VGPR here.
4197 MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
4198 if (Def && Def->isMoveImmediate() &&
4199 isInlineConstant(Def->getOperand(1)) &&
4200 MRI->hasOneNonDBGUse(Src0->getReg())) {
4201 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4202 Src0Inlined = true;
4203 } else if (ST.getConstantBusLimit(Opc) <= 1 &&
4204 RI.isSGPRReg(*MRI, Src0->getReg())) {
4205 return false;
4206 }
4207 // VGPR is okay as Src0 - fallthrough
4208 }
4209
4210 if (Src1->isReg() && !Src0Inlined) {
4211 // We have one slot for inlinable constant so far - try to fill it
4212 MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
4213 if (Def && Def->isMoveImmediate() &&
4214 isInlineConstant(Def->getOperand(1)) &&
4215 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
4216 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4217 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
4218 return false;
4219 // VGPR is okay as Src1 - fallthrough
4220 }
4221 }
4222
4223 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4224 if (pseudoToMCOpcode(NewOpc) == -1)
4225 return false;
4226
4227 // FIXME: This would be a lot easier if we could return a new instruction
4228 // instead of having to modify in place.
4229
4230 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4231 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4232 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4233 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4234 UseMI.untieRegOperand(
4235 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4236
4237 const std::optional<int64_t> SubRegImm =
4238 extractSubregFromImm(Imm, Src2->getSubReg());
4239
4240 // ChangingToImmediate adds Src2 back to the instruction.
4241 Src2->ChangeToImmediate(*SubRegImm);
4242
4243 // These come before src2.
4245 UseMI.setDesc(get(NewOpc));
4246
4247 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4248 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4249 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4250 Register Tmp = MRI->createVirtualRegister(NewRC);
4251 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4252 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4253 UseMI.getOperand(0).getReg())
4254 .addReg(Tmp);
4255 UseMI.getOperand(0).setReg(Tmp);
4256 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4257 CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
4258 }
4259
4260 // It might happen that UseMI was commuted
4261 // and we now have SGPR as SRC1. If so 2 inlined
4262 // constant and SGPR are illegal.
4264
4265 int NewSrc0Idx =
4266 AMDGPU::getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4267 if (!isOperandLegal(UseMI, NewSrc0Idx))
4268 legalizeOpWithMove(UseMI, NewSrc0Idx);
4269
4270 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4271 if (DeleteDef)
4272 DefMI.eraseFromParent();
4273
4274 return true;
4275 }
4276 }
4277
4278 return false;
4279}
4280
4281static bool
4284 if (BaseOps1.size() != BaseOps2.size())
4285 return false;
4286 for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
4287 if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
4288 return false;
4289 }
4290 return true;
4291}
4292
4293static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
4294 LocationSize WidthB, int OffsetB) {
4295 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4296 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4297 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4298 return LowWidth.hasValue() &&
4299 LowOffset + (int)LowWidth.getValue() <= HighOffset;
4300}
4301
4302bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
4303 const MachineInstr &MIb) const {
4304 SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
4305 int64_t Offset0, Offset1;
4306 LocationSize Dummy0 = LocationSize::precise(0);
4307 LocationSize Dummy1 = LocationSize::precise(0);
4308 bool Offset0IsScalable, Offset1IsScalable;
4309 if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
4310 Dummy0) ||
4311 !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
4312 Dummy1))
4313 return false;
4314
4315 if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
4316 return false;
4317
4318 if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
4319 // FIXME: Handle ds_read2 / ds_write2.
4320 return false;
4321 }
4322 LocationSize Width0 = MIa.memoperands().front()->getSize();
4323 LocationSize Width1 = MIb.memoperands().front()->getSize();
4324 return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
4325}
4326
4328 const MachineInstr &MIb) const {
4329 assert(MIa.mayLoadOrStore() &&
4330 "MIa must load from or modify a memory location");
4331 assert(MIb.mayLoadOrStore() &&
4332 "MIb must load from or modify a memory location");
4333
4335 return false;
4336
4337 // XXX - Can we relax this between address spaces?
4338 if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
4339 return false;
4340
4341 if (isLDSDMA(MIa) || isLDSDMA(MIb))
4342 return false;
4343
4344 if (MIa.isBundle() || MIb.isBundle())
4345 return false;
4346
4347 // TODO: Should we check the address space from the MachineMemOperand? That
4348 // would allow us to distinguish objects we know don't alias based on the
4349 // underlying address space, even if it was lowered to a different one,
4350 // e.g. private accesses lowered to use MUBUF instructions on a scratch
4351 // buffer.
4352 if (isDS(MIa)) {
4353 if (isDS(MIb))
4354 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4355
4356 return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
4357 }
4358
4359 if (isMUBUF(MIa) || isMTBUF(MIa)) {
4360 if (isMUBUF(MIb) || isMTBUF(MIb))
4361 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4362
4363 if (isFLAT(MIb))
4364 return isFLATScratch(MIb);
4365
4366 return !isSMRD(MIb);
4367 }
4368
4369 if (isSMRD(MIa)) {
4370 if (isSMRD(MIb))
4371 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4372
4373 if (isFLAT(MIb))
4374 return isFLATScratch(MIb);
4375
4376 return !isMUBUF(MIb) && !isMTBUF(MIb);
4377 }
4378
4379 if (isFLAT(MIa)) {
4380 if (isFLAT(MIb)) {
4381 if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
4382 (isFLATGlobal(MIa) && isFLATScratch(MIb)))
4383 return true;
4384
4385 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4386 }
4387
4388 return false;
4389 }
4390
4391 return false;
4392}
4393
4394static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
4395 switch (Opc) {
4396 case AMDGPU::V_MAC_F16_e32:
4397 case AMDGPU::V_MAC_F16_e64:
4398 return AMDGPU::V_MAD_F16_e64;
4399 case AMDGPU::V_MAC_F32_e32:
4400 case AMDGPU::V_MAC_F32_e64:
4401 return AMDGPU::V_MAD_F32_e64;
4402 case AMDGPU::V_MAC_LEGACY_F32_e32:
4403 case AMDGPU::V_MAC_LEGACY_F32_e64:
4404 return AMDGPU::V_MAD_LEGACY_F32_e64;
4405 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4406 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4407 return AMDGPU::V_FMA_LEGACY_F32_e64;
4408 case AMDGPU::V_FMAC_F16_e32:
4409 case AMDGPU::V_FMAC_F16_e64:
4410 case AMDGPU::V_FMAC_F16_t16_e64:
4411 case AMDGPU::V_FMAC_F16_fake16_e64:
4412 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4413 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4414 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4415 : AMDGPU::V_FMA_F16_gfx9_e64;
4416 case AMDGPU::V_FMAC_F32_e32:
4417 case AMDGPU::V_FMAC_F32_e64:
4418 return AMDGPU::V_FMA_F32_e64;
4419 case AMDGPU::V_FMAC_F64_e32:
4420 case AMDGPU::V_FMAC_F64_e64:
4421 return AMDGPU::V_FMA_F64_e64;
4422 default:
4423 llvm_unreachable("invalid instruction");
4424 }
4425}
4426
4427/// Helper struct for the implementation of 3-address conversion to communicate
4428/// updates made to instruction operands.
4430 /// Other instruction whose def is no longer used by the converted
4431 /// instruction.
4433};
4434
4436 LiveIntervals *LIS) const {
4437 MachineBasicBlock &MBB = *MI.getParent();
4438 MachineInstr *CandidateMI = &MI;
4439
4440 if (MI.isBundle()) {
4441 // This is a temporary placeholder for bundle handling that enables us to
4442 // exercise the relevant code paths in the two-address instruction pass.
4443 if (MI.getBundleSize() != 1)
4444 return nullptr;
4445 CandidateMI = MI.getNextNode();
4446 }
4447
4449 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4450 if (!NewMI)
4451 return nullptr;
4452
4453 if (MI.isBundle()) {
4454 CandidateMI->eraseFromBundle();
4455
4456 for (MachineOperand &MO : MI.all_defs()) {
4457 if (MO.isTied())
4458 MI.untieRegOperand(MO.getOperandNo());
4459 }
4460 } else {
4461 if (LIS) {
4462 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
4463 // SlotIndex of defs needs to be updated when converting to early-clobber
4464 MachineOperand &Def = NewMI->getOperand(0);
4465 if (Def.isEarlyClobber() && Def.isReg() &&
4466 LIS->hasInterval(Def.getReg())) {
4467 SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
4468 SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
4469 auto &LI = LIS->getInterval(Def.getReg());
4470 auto UpdateDefIndex = [&](LiveRange &LR) {
4471 auto *S = LR.find(OldIndex);
4472 if (S != LR.end() && S->start == OldIndex) {
4473 assert(S->valno && S->valno->def == OldIndex);
4474 S->start = NewIndex;
4475 S->valno->def = NewIndex;
4476 }
4477 };
4478 UpdateDefIndex(LI);
4479 for (auto &SR : LI.subranges())
4480 UpdateDefIndex(SR);
4481 }
4482
4483 // A use tied to an early-clobber def is read at the early-clobber slot.
4484 // The three-address instruction has no tied operands, so the use is now
4485 // read at the register slot.
4486 const MachineOperand &OldDef = MI.getOperand(0);
4487 if (OldDef.isEarlyClobber()) {
4488 assert(OldDef.isTied() &&
4489 "expected a tied def in the two-address form");
4491 MI.getOperand(MI.findTiedOperandIdx(OldDef.getOperandNo()))
4492 .getReg();
4493 SlotIndex Idx = LIS->getInstructionIndex(*NewMI);
4494 SlotIndex OldEnd = Idx.getRegSlot(true);
4495 SlotIndex NewEnd = Idx.getRegSlot();
4496 auto UpdateUseIndex = [&](LiveRange &LR) {
4497 LiveRange::Segment *S = LR.getSegmentContaining(Idx);
4498 if (S && S->end == OldEnd)
4499 S->end = NewEnd;
4500 };
4501 LiveInterval &LI = LIS->getInterval(UseReg);
4502 UpdateUseIndex(LI);
4503 for (LiveInterval::SubRange &SR : LI.subranges())
4504 UpdateUseIndex(SR);
4505 }
4506 }
4507 }
4508
4509 if (U.RemoveMIUse) {
4510 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4511 // The only user is the instruction which will be killed.
4512 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4513
4514 if (MRI.hasOneNonDBGUse(DefReg)) {
4515 // We cannot just remove the DefMI here, calling pass will crash.
4516 U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
4517 U.RemoveMIUse->getOperand(0).setIsDead(true);
4518 for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
4519 U.RemoveMIUse->removeOperand(I);
4520 }
4521
4522 if (MI.isBundle()) {
4523 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4524 if (!VRI.Reads && !VRI.Writes) {
4525 for (MachineOperand &MO : MI.all_uses()) {
4526 if (MO.isReg() && MO.getReg() == DefReg) {
4527 assert(MO.getSubReg() == 0 &&
4528 "tied sub-registers in bundles currently not supported");
4529 MI.removeOperand(MO.getOperandNo());
4530 break;
4531 }
4532 }
4533
4534 if (LIS)
4535 LIS->shrinkToUses(&LIS->getInterval(DefReg));
4536 }
4537 } else if (LIS) {
4538 LiveInterval &DefLI = LIS->getInterval(DefReg);
4539
4540 // We cannot delete the original instruction here, so hack out the use
4541 // in the original instruction with a dummy register so we can use
4542 // shrinkToUses to deal with any multi-use edge cases. Other targets do
4543 // not have the complexity of deleting a use to consider here.
4544 Register DummyReg = MRI.cloneVirtualRegister(DefReg);
4545 for (MachineOperand &MIOp : MI.uses()) {
4546 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4547 MIOp.setIsUndef(true);
4548 MIOp.setReg(DummyReg);
4549 }
4550 }
4551
4552 if (MI.isBundle()) {
4553 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4554 if (!VRI.Reads && !VRI.Writes) {
4555 for (MachineOperand &MIOp : MI.uses()) {
4556 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4557 MIOp.setIsUndef(true);
4558 MIOp.setReg(DummyReg);
4559 }
4560 }
4561 }
4562
4563 MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
4564 false, /*isUndef=*/true));
4565 }
4566
4567 LIS->shrinkToUses(&DefLI);
4568 }
4569 }
4570
4571 return MI.isBundle() ? &MI : NewMI;
4572}
4573
4575SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
4576 ThreeAddressUpdates &U) const {
4577 MachineBasicBlock &MBB = *MI.getParent();
4578 unsigned Opc = MI.getOpcode();
4579
4580 // Handle MFMA.
4581 int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
4582 if (NewMFMAOpc != -1) {
4584 BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
4585 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4586 MIB.add(MI.getOperand(I));
4587 return MIB;
4588 }
4589
4590 if (SIInstrInfo::isWMMA(MI)) {
4591 unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
4592 MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4593 .setMIFlags(MI.getFlags());
4594 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4595 MIB->addOperand(MI.getOperand(I));
4596 return MIB;
4597 }
4598
4599 assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4600 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4601 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4602 "present pre-RA");
4603
4604 // Handle MAC/FMAC.
4605 bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
4606 bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4607 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4608 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4609 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4610 bool Src0Literal = false;
4611
4612 switch (Opc) {
4613 default:
4614 return nullptr;
4615 case AMDGPU::V_MAC_F16_e64:
4616 case AMDGPU::V_FMAC_F16_e64:
4617 case AMDGPU::V_FMAC_F16_t16_e64:
4618 case AMDGPU::V_FMAC_F16_fake16_e64:
4619 case AMDGPU::V_MAC_F32_e64:
4620 case AMDGPU::V_MAC_LEGACY_F32_e64:
4621 case AMDGPU::V_FMAC_F32_e64:
4622 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4623 case AMDGPU::V_FMAC_F64_e64:
4624 break;
4625 case AMDGPU::V_MAC_F16_e32:
4626 case AMDGPU::V_FMAC_F16_e32:
4627 case AMDGPU::V_MAC_F32_e32:
4628 case AMDGPU::V_MAC_LEGACY_F32_e32:
4629 case AMDGPU::V_FMAC_F32_e32:
4630 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4631 case AMDGPU::V_FMAC_F64_e32: {
4632 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
4633 AMDGPU::OpName::src0);
4634 const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
4635 if (!Src0->isReg() && !Src0->isImm())
4636 return nullptr;
4637
4638 if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
4639 Src0Literal = true;
4640
4641 break;
4642 }
4643 }
4644
4645 MachineInstrBuilder MIB;
4646 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
4647 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
4648 const MachineOperand *Src0Mods =
4649 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
4650 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4651 const MachineOperand *Src1Mods =
4652 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
4653 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4654 const MachineOperand *Src2Mods =
4655 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
4656 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
4657 const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
4658 const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);
4659
4660 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4661 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4662 // If we have an SGPR input, we will violate the constant bus restriction.
4663 (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
4664 !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
4665 MachineInstr *DefMI = nullptr;
4666 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4667 std::optional<int64_t> ImmOpt;
4668 int64_t Imm;
4669
4670 if (!Src0Literal &&
4671 (ImmOpt = getImmOrMaterializedImm(MRI, *Src2, &DefMI))) {
4672 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4673 if (pseudoToMCOpcode(NewOpc) != -1) {
4674 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4675 .add(*Dst)
4676 .add(*Src0)
4677 .add(*Src1)
4678 .addImm(*ImmOpt)
4679 .setMIFlags(MI.getFlags());
4680 U.RemoveMIUse = DefMI;
4681 return MIB;
4682 }
4683 }
4684 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4685 if (!Src0Literal &&
4686 (ImmOpt = getImmOrMaterializedImm(MRI, *Src1, &DefMI))) {
4687 if (pseudoToMCOpcode(NewOpc) != -1) {
4688 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4689 .add(*Dst)
4690 .add(*Src0)
4691 .addImm(*ImmOpt)
4692 .add(*Src2)
4693 .setMIFlags(MI.getFlags());
4694 U.RemoveMIUse = DefMI;
4695 return MIB;
4696 }
4697 }
4698 if ((ImmOpt = getImmOrMaterializedImm(MRI, *Src0, &DefMI))) {
4699 Imm = *ImmOpt;
4700 if (pseudoToMCOpcode(NewOpc) != -1 &&
4702 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4703 Src1)) {
4704 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4705 .add(*Dst)
4706 .add(*Src1)
4707 .addImm(Imm)
4708 .add(*Src2)
4709 .setMIFlags(MI.getFlags());
4710 U.RemoveMIUse = DefMI;
4711 return MIB;
4712 }
4713 }
4714 }
4715
4716 // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
4717 // if VOP3 does not allow a literal operand.
4718 if (Src0Literal && !ST.hasVOP3Literal())
4719 return nullptr;
4720
4721 unsigned NewOpc = getNewFMAInst(ST, Opc);
4722
4723 if (pseudoToMCOpcode(NewOpc) == -1)
4724 return nullptr;
4725
4726 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4727 .add(*Dst)
4728 .addImm(Src0Mods ? Src0Mods->getImm() : 0)
4729 .add(*Src0)
4730 .addImm(Src1Mods ? Src1Mods->getImm() : 0)
4731 .add(*Src1)
4732 .addImm(Src2Mods ? Src2Mods->getImm() : 0)
4733 .add(*Src2)
4734 .addImm(Clamp ? Clamp->getImm() : 0)
4735 .addImm(Omod ? Omod->getImm() : 0)
4736 .setMIFlags(MI.getFlags());
4737 if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
4738 MIB.addImm(OpSel ? OpSel->getImm() : 0);
4739 return MIB;
4740}
4741
4742// It's not generally safe to move VALU instructions across these since it will
4743// start using the register as a base index rather than directly.
4744// XXX - Why isn't hasSideEffects sufficient for these?
4746 switch (MI.getOpcode()) {
4747 case AMDGPU::S_SET_GPR_IDX_ON:
4748 case AMDGPU::S_SET_GPR_IDX_MODE:
4749 case AMDGPU::S_SET_GPR_IDX_OFF:
4750 return true;
4751 default:
4752 return false;
4753 }
4754}
4755
4757 const MachineBasicBlock *MBB,
4758 const MachineFunction &MF) const {
4759 // Skipping the check for SP writes in the base implementation. The reason it
4760 // was added was apparently due to compile time concerns.
4761 //
4762 // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
4763 // but is probably avoidable.
4764
4765 // Copied from base implementation.
4766 // Terminators and labels can't be scheduled around.
4767 if (MI.isTerminator() || MI.isPosition())
4768 return true;
4769
4770 // INLINEASM_BR can jump to another block
4771 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4772 return true;
4773
4774 if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
4775 return true;
4776
4777 // Target-independent instructions do not have an implicit-use of EXEC, even
4778 // when they operate on VGPRs. Treating EXEC modifications as scheduling
4779 // boundaries prevents incorrect movements of such instructions.
4780 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4781 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4782 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4783 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4784 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4786}
4787
4789 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4790 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4791 Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
4792}
4793
4795 // Instructions that access scratch use FLAT encoding or BUF encodings.
4796 if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
4797 return false;
4798
4799 // SCRATCH instructions always access scratch.
4800 if (isFLATScratch(MI))
4801 return true;
4802
4803 // If FLAT_SCRATCH registers are not initialized, we can never access scratch
4804 // via the aperture.
4805 if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
4806 return false;
4807
4808 // If there are no memory operands then conservatively assume the flat
4809 // operation may access scratch.
4810 if (MI.memoperands_empty())
4811 return true;
4812
4813 // See if any memory operand specifies an address space that involves scratch.
4814 return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
4815 unsigned AS = Memop->getAddrSpace();
4816 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4817 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4818 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4819 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4820 }
4821 return AS == AMDGPUAS::PRIVATE_ADDRESS;
4822 });
4823}
4824
4826 assert(isFLAT(MI));
4827
4828 // All flat instructions use the VMEM counter except prefetch.
4829 if (!usesVM_CNT(MI))
4830 return false;
4831
4832 // If there are no memory operands then conservatively assume the flat
4833 // operation may access VMEM.
4834 if (MI.memoperands_empty())
4835 return true;
4836
4837 // See if any memory operand specifies an address space that involves VMEM.
4838 // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
4839 // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
4840 // (GDS) address space is not supported by flat operations. Therefore, simply
4841 // return true unless only the LDS address space is found.
4842 for (const MachineMemOperand *Memop : MI.memoperands()) {
4843 unsigned AS = Memop->getAddrSpace();
4845 if (AS != AMDGPUAS::LOCAL_ADDRESS)
4846 return true;
4847 }
4848
4849 return false;
4850}
4851
4853 bool TgSplit) const {
4854 assert(isFLAT(MI));
4855
4856 // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
4857 if (!usesLGKM_CNT(MI))
4858 return false;
4859
4860 // If in tgsplit mode then there can be no use of LDS.
4861 if (TgSplit)
4862 return false;
4863
4864 // If there are no memory operands then conservatively assume the flat
4865 // operation may access LDS.
4866 if (MI.memoperands_empty())
4867 return true;
4868
4869 // See if any memory operand specifies an address space that involves LDS.
4870 for (const MachineMemOperand *Memop : MI.memoperands()) {
4871 unsigned AS = Memop->getAddrSpace();
4873 return true;
4874 }
4875
4876 return false;
4877}
4878
4880 if (!isAsync(MI))
4882 if (usesTENSOR_CNT(MI))
4884 if (!usesASYNC_CNT(MI))
4886
4887 // TODO: Declare the stage of each async instruction in TableGen alongside
4888 // its definition, instead of listing opcodes here.
4889 switch (MI.getOpcode()) {
4890 // Keep in sync with FLATInstructions.td.
4891 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B8:
4892 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B8_SADDR:
4893 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B32:
4894 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B32_SADDR:
4895 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B64:
4896 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B64_SADDR:
4897 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B128:
4898 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B128_SADDR:
4900 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B8:
4901 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B8_SADDR:
4902 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B32:
4903 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B32_SADDR:
4904 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B64:
4905 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B64_SADDR:
4906 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B128:
4907 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B128_SADDR:
4909 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B8:
4910 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B8_SADDR:
4911 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B32:
4912 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B32_SADDR:
4913 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B64:
4914 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B64_SADDR:
4915 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B128:
4916 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B128_SADDR:
4918 default:
4919 llvm_unreachable("Async opcode has no associated async stage");
4920 }
4921}
4922
4924 // Skip the full operand and register alias search modifiesRegister
4925 // does. There's only a handful of instructions that touch this, it's only an
4926 // implicit def, and doesn't alias any other registers.
4927 return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
4928}
4929
4931 unsigned Opcode = MI.getOpcode();
4932
4933 if (MI.mayStore() && isSMRD(MI))
4934 return true; // scalar store or atomic
4935
4936 // This will terminate the function when other lanes may need to continue.
4937 if (MI.isReturn())
4938 return true;
4939
4940 // These instructions cause shader I/O that may cause hardware lockups
4941 // when executed with an empty EXEC mask.
4942 //
4943 // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
4944 // EXEC = 0, but checking for that case here seems not worth it
4945 // given the typical code patterns.
4946 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4947 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4948 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4949 Opcode == AMDGPU::S_SETHALT)
4950 return true;
4951
4952 if (MI.isCall() || MI.isInlineAsm())
4953 return true; // conservative assumption
4954
4955 // V_PERM_PK16 must issue with EXEC != 0 so its follower (or an inserted
4956 // V_NOP) actually runs on the VALU pipe. Returning true here keeps the
4957 // s_cbranch_execz that skips this region when EXEC is empty.
4958 if (ST.hasVPermPk16Hazard() && isVPermPk16(Opcode))
4959 return true;
4960
4961 // Assume that barrier interactions are only intended with active lanes.
4962 if (isBarrier(Opcode))
4963 return true;
4964
4965 // A mode change is a scalar operation that influences vector instructions.
4967 return true;
4968
4969 // These are like SALU instructions in terms of effects, so it's questionable
4970 // whether we should return true for those.
4971 //
4972 // However, executing them with EXEC = 0 causes them to operate on undefined
4973 // data, which we avoid by returning true here.
4974 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4975 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4976 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4977 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4978 return true;
4979
4980 return false;
4981}
4982
4984 const MachineInstr &MI) const {
4985 if (MI.isMetaInstruction())
4986 return false;
4987
4988 // This won't read exec if this is an SGPR->SGPR copy.
4989 if (MI.isCopyLike()) {
4990 if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
4991 return true;
4992
4993 // Make sure this isn't copying exec as a normal operand
4994 return MI.readsRegister(AMDGPU::EXEC, &RI);
4995 }
4996
4997 // Make a conservative assumption about the callee.
4998 if (MI.isCall())
4999 return true;
5000
5001 // Be conservative with any unhandled generic opcodes.
5002 if (!isTargetSpecificOpcode(MI.getOpcode()))
5003 return true;
5004
5005 return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
5006}
5007
5009 switch (Imm.getBitWidth()) {
5010 case 1: // This likely will be a condition code mask.
5011 return true;
5012
5013 case 32:
5014 return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
5015 ST.hasInv2PiInlineImm());
5016 case 64:
5017 return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
5018 ST.hasInv2PiInlineImm());
5019 case 16:
5020 return ST.has16BitInsts() &&
5021 AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
5022 ST.hasInv2PiInlineImm());
5023 default:
5024 llvm_unreachable("invalid bitwidth");
5025 }
5026}
5027
5029 APInt IntImm = Imm.bitcastToAPInt();
5030 int64_t IntImmVal = IntImm.getSExtValue();
5031 bool HasInv2Pi = ST.hasInv2PiInlineImm();
5032 switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
5033 default:
5034 llvm_unreachable("invalid fltSemantics");
5037 return isInlineConstant(IntImm);
5039 return ST.has16BitInsts() &&
5040 AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
5042 return ST.has16BitInsts() &&
5043 AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
5044 }
5045}
5046
5047bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
5048 // MachineOperand provides no way to tell the true operand size, since it only
5049 // records a 64-bit value. We need to know the size to determine if a 32-bit
5050 // floating point immediate bit pattern is legal for an integer immediate. It
5051 // would be for any 32-bit integer operand, but would not be for a 64-bit one.
5052 switch (OperandType) {
5062 int32_t Trunc = static_cast<int32_t>(Imm);
5063 return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
5064 }
5072 return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
5075 // We would expect inline immediates to not be concerned with an integer/fp
5076 // distinction. However, in the case of 16-bit integer operations, the
5077 // "floating point" values appear to not work. It seems read the low 16-bits
5078 // of 32-bit immediates, which happens to always work for the integer
5079 // values.
5080 //
5081 // See llvm bugzilla 46302.
5082 //
5083 // TODO: Theoretically we could use op-sel to use the high bits of the
5084 // 32-bit FP values.
5093 return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
5098 return false;
5101 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
5102 // A few special case instructions have 16-bit operands on subtargets
5103 // where 16-bit instructions are not legal.
5104 // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
5105 // constants in these cases
5106 int16_t Trunc = static_cast<int16_t>(Imm);
5107 return ST.has16BitInsts() &&
5108 AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
5109 }
5110
5111 return false;
5112 }
5115 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
5116 int16_t Trunc = static_cast<int16_t>(Imm);
5117 return ST.has16BitInsts() &&
5118 AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
5119 }
5120 return false;
5121 }
5126 return false;
5128 return isLegalAV64PseudoImm(Imm);
5131 // Always embedded in the instruction for free.
5132 return true;
5142 // Just ignore anything else.
5143 return false;
5144 default:
5145 llvm_unreachable("invalid operand type");
5146 }
5147}
5148
5149static bool compareMachineOp(const MachineOperand &Op0,
5150 const MachineOperand &Op1) {
5151 if (Op0.getType() != Op1.getType())
5152 return false;
5153
5154 switch (Op0.getType()) {
5156 return Op0.getReg() == Op1.getReg();
5158 return Op0.getImm() == Op1.getImm();
5159 default:
5160 llvm_unreachable("Didn't expect to be comparing these operand types");
5161 }
5162}
5163
5165 const MCOperandInfo &OpInfo) const {
5166 if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
5167 return true;
5168
5169 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5170 return false;
5171
5172 if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
5173 return true;
5174
5175 return ST.hasVOP3Literal();
5176}
5177
5178bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5179 int64_t ImmVal) const {
5180 const unsigned Opc = InstDesc.getOpcode();
5181 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
5182 if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
5183 OpNo == static_cast<unsigned>(Src1Idx))
5184 return false;
5185
5186 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5187 if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
5188 if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5189 OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
5190 AMDGPU::OpName::src2))
5191 return false;
5192
5193 if (ST.hasBF16InlineConstFromUpperFP32() && isVOP1(Opc)) {
5194 if ((OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_BF16 ||
5195 OpInfo.OperandType == AMDGPU::OPERAND_REG_INLINE_C_BF16) &&
5196 isInlineConstant(ImmVal, OpInfo.OperandType))
5197 return false;
5198 }
5199
5200 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5201 }
5202
5203 return isLiteralOperandLegal(InstDesc, OpInfo);
5204}
5205
5206bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5207 const MachineOperand &MO) const {
5208 if (MO.isImm())
5209 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
5210
5211 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
5212 "unexpected imm-like operand kind");
5213 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5214 return isLiteralOperandLegal(InstDesc, OpInfo);
5215}
5216
5218 // 2 32-bit inline constants packed into one.
5219 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
5220 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
5221}
5222
5223bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
5224 // GFX90A does not have V_MUL_LEGACY_F32_e32.
5225 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5226 return false;
5227
5228 int Op32 = AMDGPU::getVOPe32(Opcode);
5229 if (Op32 == -1)
5230 return false;
5231
5232 return pseudoToMCOpcode(Op32) != -1;
5233}
5234
5235/// Return true if \p MI is a VALU comparison, i.e. an instruction that writes
5236/// a lane mask with one bit per lane, and zeroes the bits of lanes that were
5237/// inactive when it executed.
5238///
5239/// TODO: Also handle the sdst result of V_ADD_CO_U32 and V_SUB_CO_U32 and
5240/// V_DIV_SCALE_F32.
5241static bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI) {
5242 if (TII.isVOPC(MI))
5243 return true;
5244 int Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5245 return Op32 != -1 && TII.isVOPC(Op32);
5246}
5247
5249 const MachineRegisterInfo &MRI,
5250 unsigned Depth) const {
5251 assert(MRI.isSSA() && "isMaskedByExec requires SSA form");
5253 const MachineBasicBlock *MBB = Use.getParent();
5254
5255 // EXEC itself is trivially masked by EXEC.
5256 if (Reg == LMC.ExecReg)
5257 return true;
5258
5259 // Maximum depth of the def-use walk.
5260 constexpr unsigned MaxDepth = 6;
5261 if (Depth >= MaxDepth || !Reg.isVirtual())
5262 return false;
5263
5264 // Only look at definitions that can execute under the same EXEC mask as the
5265 // use.
5266 const MachineInstr *Def = MRI.getVRegDef(Reg);
5267 if (!Def || Def->getParent() != MBB)
5268 return false;
5269
5270 if (isVCmp(*this, *Def))
5271 return true;
5272
5273 // Recurse into an operand, which must be a whole register to say anything
5274 // about the whole lane mask.
5275 auto Recurse = [&](unsigned OpIdx) {
5276 const MachineOperand &MO = Def->getOperand(OpIdx);
5277 return MO.isReg() && !MO.getSubReg() &&
5278 isMaskedByExec(MO.getReg(), Use, MRI, Depth + 1);
5279 };
5280
5281 unsigned Opc = Def->getOpcode();
5282 if (Opc == AMDGPU::COPY && Recurse(1))
5283 return true;
5284 if (Opc == LMC.AndOpc && (Recurse(1) || Recurse(2)))
5285 return true;
5286 if (Opc == LMC.AndN2Opc && Recurse(1))
5287 return true;
5288 if ((Opc == LMC.OrOpc || Opc == LMC.XorOpc) && Recurse(1) && Recurse(2))
5289 return true;
5290 // TODO: Sometimes we encounter "reg = S_CSELECT -1, 0". If Reg has no other
5291 // uses this could be optimized to "reg = S_CSELECT $exec, 0".
5292
5293 return false;
5294}
5295
5296bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
5297 // The src0_modifier operand is present on all instructions
5298 // that have modifiers.
5299
5300 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
5301}
5302
5304 AMDGPU::OpName OpName) const {
5305 const MachineOperand *Mods = getNamedOperand(MI, OpName);
5306 return Mods && Mods->getImm();
5307}
5308
5310 return any_of(ModifierOpNames,
5311 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
5312}
5313
5315 const MachineRegisterInfo &MRI) const {
5316 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5317 // Can't shrink instruction with three operands.
5318 if (Src2) {
5319 switch (MI.getOpcode()) {
5320 default: return false;
5321
5322 case AMDGPU::V_ADDC_U32_e64:
5323 case AMDGPU::V_SUBB_U32_e64:
5324 case AMDGPU::V_SUBBREV_U32_e64: {
5325 const MachineOperand *Src1
5326 = getNamedOperand(MI, AMDGPU::OpName::src1);
5327 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
5328 return false;
5329 // Additional verification is needed for sdst/src2.
5330 return true;
5331 }
5332 case AMDGPU::V_MAC_F16_e64:
5333 case AMDGPU::V_MAC_F32_e64:
5334 case AMDGPU::V_MAC_LEGACY_F32_e64:
5335 case AMDGPU::V_FMAC_F16_e64:
5336 case AMDGPU::V_FMAC_F16_t16_e64:
5337 case AMDGPU::V_FMAC_F16_fake16_e64:
5338 case AMDGPU::V_FMAC_F32_e64:
5339 case AMDGPU::V_FMAC_F64_e64:
5340 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5341 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
5342 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
5343 return false;
5344 break;
5345
5346 case AMDGPU::V_CNDMASK_B32_e64:
5347 break;
5348 }
5349 }
5350
5351 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
5352 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5353 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
5354 return false;
5355
5356 // Make sure src0 isn't using any modifiers.
5357 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
5358 return false;
5359
5360 // Can it be shrunk to a valid 32 bit opcode?
5361 if (!hasVALU32BitEncoding(MI.getOpcode()))
5362 return false;
5363
5364 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
5365 if (Src0 && Src0->isImm()) {
5366 unsigned Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5367 if (!isImmOperandLegal(
5368 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5369 *Src0))
5370 return false;
5371 }
5372
5373 // Check output modifiers
5374 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
5375 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
5376 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
5377 // TODO: Can we avoid checking bound_ctrl/fi here?
5378 // They are only used by permlane*_swap special case.
5379 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
5380 !hasModifiersSet(MI, AMDGPU::OpName::fi);
5381}
5382
5383// Set VCC operand with all flags from \p Orig, except for setting it as
5384// implicit.
5386 const MachineOperand &Orig) {
5387
5388 for (MachineOperand &Use : MI.implicit_operands()) {
5389 if (Use.isUse() &&
5390 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
5391 Use.setIsUndef(Orig.isUndef());
5392 Use.setIsKill(Orig.isKill());
5393 return;
5394 }
5395 }
5396}
5397
5399 unsigned Op32) const {
5400 MachineBasicBlock *MBB = MI.getParent();
5401
5402 const MCInstrDesc &Op32Desc = get(Op32);
5403 MachineInstrBuilder Inst32 =
5404 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
5405 .setMIFlags(MI.getFlags());
5406
5407 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
5408 // For VOPC instructions, this is replaced by an implicit def of vcc.
5409
5410 // We assume the defs of the shrunk opcode are in the same order, and the
5411 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
5412 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
5413 Inst32.add(MI.getOperand(I));
5414
5415 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5416
5417 int Idx = MI.getNumExplicitDefs();
5418 for (const MachineOperand &Use : MI.explicit_uses()) {
5419 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
5421 continue;
5422
5423 if (&Use == Src2) {
5424 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5425 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
5426 // replaced with an implicit read of vcc or vcc_lo. The implicit read
5427 // of vcc was already added during the initial BuildMI, but we
5428 // 1) may need to change vcc to vcc_lo to preserve the original register
5429 // 2) have to preserve the original flags.
5430 copyFlagsToImplicitVCC(*Inst32, *Src2);
5431 continue;
5432 }
5433 }
5434
5435 Inst32.add(Use);
5436 }
5437
5438 // FIXME: Losing implicit operands
5439 fixImplicitOperands(*Inst32);
5440
5441 // The explicit carry/result def is dropped in favor of an implicit VCC def;
5442 // preserve the dead flag.
5443 const MachineOperand *OldSDst = getNamedOperand(MI, AMDGPU::OpName::sdst);
5444 if (OldSDst && OldSDst->isDead()) {
5445 if (MachineOperand *NewVCC =
5446 Inst32->findRegisterDefOperand(RI.getVCC(), &RI))
5447 NewVCC->setIsDead();
5448 }
5449
5450 return Inst32;
5451}
5452
5454 // Null is free
5455 Register Reg = RegOp.getReg();
5456 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5457 return false;
5458
5459 // SGPRs use the constant bus
5460
5461 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
5462 // physical register operands should also count, except for exec.
5463 if (RegOp.isImplicit())
5464 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5465
5466 // SGPRs use the constant bus
5467 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5468 AMDGPU::SReg_64RegClass.contains(Reg);
5469}
5470
5472 const MachineRegisterInfo &MRI) const {
5473 Register Reg = RegOp.getReg();
5474 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5475 : physRegUsesConstantBus(RegOp);
5476}
5477
5479 const MachineOperand &MO,
5480 const MCOperandInfo &OpInfo) const {
5481 // Literal constants use the constant bus.
5482 if (!MO.isReg())
5483 return !isInlineConstant(MO, OpInfo);
5484
5485 Register Reg = MO.getReg();
5486 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5488}
5489
5491 for (const MachineOperand &MO : MI.implicit_operands()) {
5492 // We only care about reads.
5493 if (MO.isDef())
5494 continue;
5495
5496 switch (MO.getReg()) {
5497 case AMDGPU::VCC:
5498 case AMDGPU::VCC_LO:
5499 case AMDGPU::VCC_HI:
5500 case AMDGPU::M0:
5501 case AMDGPU::FLAT_SCR:
5502 return MO.getReg();
5503
5504 default:
5505 break;
5506 }
5507 }
5508
5509 return Register();
5510}
5511
5512static bool shouldReadExec(const MachineInstr &MI) {
5513 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5514 switch (MI.getOpcode()) {
5515 case AMDGPU::V_READLANE_B32:
5516 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5517 case AMDGPU::V_WRITELANE_B32:
5518 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5519 return false;
5520 }
5521
5522 return true;
5523 }
5524
5525 if (MI.isPreISelOpcode() ||
5526 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5529 return false;
5530
5531 return true;
5532}
5533
5534static bool isRegOrFI(const MachineOperand &MO) {
5535 return MO.isReg() || MO.isFI();
5536}
5537
5538static bool isSubRegOf(const SIRegisterInfo &TRI,
5539 const MachineOperand &SuperVec,
5540 const MachineOperand &SubReg) {
5541 if (SubReg.getReg().isPhysical())
5542 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5543
5544 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5545 SubReg.getReg() == SuperVec.getReg();
5546}
5547
5548// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5549bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5550 const MachineRegisterInfo &MRI,
5551 StringRef &ErrInfo) const {
5552 Register DstReg = MI.getOperand(0).getReg();
5553 Register SrcReg = MI.getOperand(1).getReg();
5554 // This is a check for copy from vector register to SGPR
5555 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5556 ErrInfo = "illegal copy from vector register to SGPR";
5557 return false;
5558 }
5559 return true;
5560}
5561
5563 StringRef &ErrInfo) const {
5564 uint32_t Opcode = MI.getOpcode();
5565 const MachineFunction *MF = MI.getMF();
5566 const MachineRegisterInfo &MRI = MF->getRegInfo();
5567
5568 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5569 // Find a better property to recognize the point where instruction selection
5570 // is just done.
5571 // We can only enforce this check after SIFixSGPRCopies pass so that the
5572 // illegal copies are legalized and thereafter we don't expect a pass
5573 // inserting similar copies.
5574 if (!MRI.isSSA() && MI.isCopy())
5575 return verifyCopy(MI, MRI, ErrInfo);
5576
5577 if (SIInstrInfo::isGenericOpcode(Opcode))
5578 return true;
5579
5580 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5581 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5582 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5583 int Src3Idx = -1;
5584 if (Src0Idx == -1) {
5585 // VOPD V_DUAL_* instructions use different operand names.
5586 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5587 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5588 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5589 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5590 }
5591
5592 // Make sure the number of operands is correct.
5593 const MCInstrDesc &Desc = get(Opcode);
5594 if (!Desc.isVariadic() &&
5595 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5596 ErrInfo = "Instruction has wrong number of operands.";
5597 return false;
5598 }
5599
5600 if (MI.isInlineAsm()) {
5601 // Verify register classes for inlineasm constraints.
5602 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5603 I != E; ++I) {
5604 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5605 if (!RC)
5606 continue;
5607
5608 const MachineOperand &Op = MI.getOperand(I);
5609 if (!Op.isReg())
5610 continue;
5611
5612 Register Reg = Op.getReg();
5613 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5614 ErrInfo = "inlineasm operand has incorrect register class.";
5615 return false;
5616 }
5617 }
5618
5619 return true;
5620 }
5621
5622 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5623 ErrInfo = "missing memory operand from image instruction.";
5624 return false;
5625 }
5626
5627 // Make sure the register classes are correct.
5628 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5629 const MachineOperand &MO = MI.getOperand(i);
5630 if (MO.isFPImm()) {
5631 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5632 "all fp values to integers.";
5633 return false;
5634 }
5635
5636 const MCOperandInfo &OpInfo = Desc.operands()[i];
5637
5638 switch (OpInfo.OperandType) {
5640 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5641 ErrInfo = "Illegal immediate value for operand.";
5642 return false;
5643 }
5644 break;
5658 break;
5672 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5673 ErrInfo = "Illegal immediate value for operand.";
5674 return false;
5675 }
5676 break;
5677 }
5682 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5683 !isInlineConstant(MI, i) &&
5685 OpInfo.OperandType ==
5687 ErrInfo = "illegal 64-bit immediate value for operand.";
5688 return false;
5689 }
5690 break;
5693 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5694 ErrInfo = "Expected inline constant for operand.";
5695 return false;
5696 }
5697 break;
5700 break;
5705 // Check if this operand is an immediate.
5706 // FrameIndex operands will be replaced by immediates, so they are
5707 // allowed.
5708 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5709 ErrInfo = "Expected immediate, but got non-immediate";
5710 return false;
5711 }
5712 break;
5716 break;
5717 default:
5718 if (OpInfo.isGenericType())
5719 continue;
5720 break;
5721 }
5722 }
5723
5724 // Verify SDWA
5725 if (isSDWA(MI)) {
5726 if (!ST.hasSDWA()) {
5727 ErrInfo = "SDWA is not supported on this target";
5728 return false;
5729 }
5730
5731 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5732 AMDGPU::OpName::dst_sel}) {
5733 const MachineOperand *MO = getNamedOperand(MI, Op);
5734 if (!MO)
5735 continue;
5736 int64_t Imm = MO->getImm();
5738 ErrInfo = "Invalid SDWA selection";
5739 return false;
5740 }
5741 }
5742
5743 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5744
5745 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5746 if (OpIdx == -1)
5747 continue;
5748 const MachineOperand &MO = MI.getOperand(OpIdx);
5749
5750 if (!ST.hasSDWAScalar()) {
5751 // Only VGPRS on VI
5752 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5753 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5754 return false;
5755 }
5756 } else {
5757 // No immediates on GFX9
5758 if (!MO.isReg()) {
5759 ErrInfo =
5760 "Only reg allowed as operands in SDWA instructions on GFX9+";
5761 return false;
5762 }
5763 }
5764 }
5765
5766 if (!ST.hasSDWAOmod()) {
5767 // No omod allowed on VI
5768 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5769 if (OMod != nullptr &&
5770 (!OMod->isImm() || OMod->getImm() != 0)) {
5771 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5772 return false;
5773 }
5774 }
5775
5776 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5777 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5778 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5779 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5780 const MachineOperand *Src0ModsMO =
5781 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5782 unsigned Mods = Src0ModsMO->getImm();
5783 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5784 Mods & SISrcMods::SEXT) {
5785 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5786 return false;
5787 }
5788 }
5789
5790 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5791 if (isVOPC(BasicOpcode)) {
5792 if (!ST.hasSDWASdst() && DstIdx != -1) {
5793 // Only vcc allowed as dst on VI for VOPC
5794 const MachineOperand &Dst = MI.getOperand(DstIdx);
5795 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5796 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5797 return false;
5798 }
5799 } else if (!ST.hasSDWAOutModsVOPC()) {
5800 // No clamp allowed on GFX9 for VOPC
5801 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5802 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5803 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5804 return false;
5805 }
5806
5807 // No omod allowed on GFX9 for VOPC
5808 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5809 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5810 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5811 return false;
5812 }
5813 }
5814 }
5815
5816 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5817 if (DstUnused && DstUnused->isImm() &&
5818 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5819 const MachineOperand &Dst = MI.getOperand(DstIdx);
5820 if (!Dst.isReg() || !Dst.isTied()) {
5821 ErrInfo = "Dst register should have tied register";
5822 return false;
5823 }
5824
5825 const MachineOperand &TiedMO =
5826 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5827 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5828 ErrInfo =
5829 "Dst register should be tied to implicit use of preserved register";
5830 return false;
5831 }
5832 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5833 ErrInfo = "Dst register should use same physical register as preserved";
5834 return false;
5835 }
5836 }
5837 }
5838
5839 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5840 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5841 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5842 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5843 return false;
5844 }
5845 if (Src1MO.isImm()) {
5846 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5847 return false;
5848 }
5849 }
5850
5851 // Verify MIMG / VIMAGE / VSAMPLE
5852 if (isImage(Opcode) && !MI.mayStore()) {
5853 // Ensure that the return type used is large enough for all the options
5854 // being used TFE/LWE require an extra result register.
5855 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5856 if (DMask) {
5857 uint64_t DMaskImm = DMask->getImm();
5858 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5859 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5860 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5861 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5862
5863 // Adjust for packed 16 bit values
5864 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5865 RegCount = divideCeil(RegCount, 2);
5866
5867 // Adjust if using LWE or TFE
5868 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5869 RegCount += 1;
5870
5871 const uint32_t DstIdx =
5872 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5873 const MachineOperand &Dst = MI.getOperand(DstIdx);
5874 if (Dst.isReg()) {
5875 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5876 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5877 if (RegCount > DstSize) {
5878 ErrInfo = "Image instruction returns too many registers for dst "
5879 "register class";
5880 return false;
5881 }
5882 }
5883 }
5884 }
5885
5886 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5887 if (isVALU(MI, /*AllowLDSDMA=*/false) &&
5888 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5889 unsigned ConstantBusCount = 0;
5890 bool UsesLiteral = false;
5891 const MachineOperand *LiteralVal = nullptr;
5892
5893 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5894 if (ImmIdx != -1) {
5895 ++ConstantBusCount;
5896 UsesLiteral = true;
5897 LiteralVal = &MI.getOperand(ImmIdx);
5898 }
5899
5900 SmallVector<Register, 2> SGPRsUsed;
5901 Register SGPRUsed;
5902
5903 // Only look at the true operands. Only a real operand can use the constant
5904 // bus, and we don't want to check pseudo-operands like the source modifier
5905 // flags.
5906 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5907 if (OpIdx == -1)
5908 continue;
5909 const MachineOperand &MO = MI.getOperand(OpIdx);
5910 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5911 if (MO.isReg()) {
5912 SGPRUsed = MO.getReg();
5913 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5914 ++ConstantBusCount;
5915 SGPRsUsed.push_back(SGPRUsed);
5916 }
5917 } else if (!MO.isFI()) { // Treat FI like a register.
5918 if (!UsesLiteral) {
5919 ++ConstantBusCount;
5920 UsesLiteral = true;
5921 LiteralVal = &MO;
5922 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5923 assert(isVOP2(MI) || isVOP3(MI));
5924 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5925 return false;
5926 }
5927 }
5928 }
5929 }
5930
5931 SGPRUsed = findImplicitSGPRRead(MI);
5932 if (SGPRUsed) {
5933 // Implicit uses may safely overlap true operands
5934 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5935 return !RI.regsOverlap(SGPRUsed, SGPR);
5936 })) {
5937 ++ConstantBusCount;
5938 SGPRsUsed.push_back(SGPRUsed);
5939 }
5940 }
5941
5942 // v_writelane_b32 is an exception from constant bus restriction:
5943 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5944 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5945 Opcode != AMDGPU::V_WRITELANE_B32) {
5946 ErrInfo = "VOP* instruction violates constant bus restriction";
5947 return false;
5948 }
5949
5950 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5951 ErrInfo = "VOP3 instruction uses literal";
5952 return false;
5953 }
5954 }
5955
5956 // Special case for writelane - this can break the multiple constant bus rule,
5957 // but still can't use more than one SGPR register
5958 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5959 unsigned SGPRCount = 0;
5960 Register SGPRUsed;
5961
5962 for (int OpIdx : {Src0Idx, Src1Idx}) {
5963 if (OpIdx == -1)
5964 break;
5965
5966 const MachineOperand &MO = MI.getOperand(OpIdx);
5967
5968 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5969 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5970 if (MO.getReg() != SGPRUsed)
5971 ++SGPRCount;
5972 SGPRUsed = MO.getReg();
5973 }
5974 }
5975 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5976 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5977 return false;
5978 }
5979 }
5980 }
5981
5982 if (Opcode == AMDGPU::ASYNCMARK || Opcode == AMDGPU::WAIT_ASYNCMARK) {
5983 int64_t Mask = MI.getOperand(MI.getNumExplicitOperands() - 1).getImm();
5984 if (!AMDGPU::isValidAsyncStageMask(Mask)) {
5985 ErrInfo = "invalid asyncmark stage mask";
5986 return false;
5987 }
5988 }
5989
5990 // Verify misc. restrictions on specific instructions.
5991 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5992 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5993 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5994 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5995 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
5996 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5997 if (!compareMachineOp(Src0, Src1) &&
5998 !compareMachineOp(Src0, Src2)) {
5999 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
6000 return false;
6001 }
6002 }
6003 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
6004 SISrcMods::ABS) ||
6005 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
6006 SISrcMods::ABS) ||
6007 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
6008 SISrcMods::ABS)) {
6009 ErrInfo = "ABS not allowed in VOP3B instructions";
6010 return false;
6011 }
6012 }
6013
6014 if (isSOP2(MI) || isSOPC(MI)) {
6015 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
6016 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
6017
6018 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
6019 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
6020 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
6021 !Src0.isIdenticalTo(Src1)) {
6022 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
6023 return false;
6024 }
6025 }
6026
6027 if (isSOPK(MI)) {
6028 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
6029 if (Desc.isBranch()) {
6030 if (!Op->isMBB()) {
6031 ErrInfo = "invalid branch target for SOPK instruction";
6032 return false;
6033 }
6034 } else {
6035 uint64_t Imm = Op->getImm();
6036 if (sopkIsZext(Opcode)) {
6037 if (!isUInt<16>(Imm)) {
6038 ErrInfo = "invalid immediate for SOPK instruction";
6039 return false;
6040 }
6041 } else {
6042 if (!isInt<16>(Imm)) {
6043 ErrInfo = "invalid immediate for SOPK instruction";
6044 return false;
6045 }
6046 }
6047 }
6048 }
6049
6050 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
6051 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
6052 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
6053 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
6054 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
6055 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
6056
6057 const unsigned StaticNumOps =
6058 Desc.getNumOperands() + Desc.implicit_uses().size();
6059 const unsigned NumImplicitOps = IsDst ? 2 : 1;
6060
6061 // Require additional implicit operands. This allows a fixup done by the
6062 // post RA scheduler where the main implicit operand is killed and
6063 // implicit-defs are added for sub-registers that remain live after this
6064 // instruction.
6065 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
6066 ErrInfo = "missing implicit register operands";
6067 return false;
6068 }
6069
6070 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
6071 if (IsDst) {
6072 if (!Dst->isUse()) {
6073 ErrInfo = "v_movreld_b32 vdst should be a use operand";
6074 return false;
6075 }
6076
6077 unsigned UseOpIdx;
6078 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
6079 UseOpIdx != StaticNumOps + 1) {
6080 ErrInfo = "movrel implicit operands should be tied";
6081 return false;
6082 }
6083 }
6084
6085 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
6086 const MachineOperand &ImpUse
6087 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
6088 if (!ImpUse.isReg() || !ImpUse.isUse() ||
6089 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
6090 ErrInfo = "src0 should be subreg of implicit vector use";
6091 return false;
6092 }
6093 }
6094
6095 // Make sure we aren't losing exec uses in the td files. This mostly requires
6096 // being careful when using let Uses to try to add other use registers.
6097 if (shouldReadExec(MI)) {
6098 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
6099 ErrInfo = "VALU instruction does not implicitly read exec mask";
6100 return false;
6101 }
6102 }
6103
6104 if (isSMRD(MI)) {
6105 if (MI.mayStore() &&
6106 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
6107 // The register offset form of scalar stores may only use m0 as the
6108 // soffset register.
6109 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
6110 if (Soff && Soff->getReg() != AMDGPU::M0) {
6111 ErrInfo = "scalar stores must use m0 as offset register";
6112 return false;
6113 }
6114 }
6115 }
6116
6117 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
6118 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
6119 if (Offset->getImm() != 0) {
6120 ErrInfo = "subtarget does not support offsets in flat instructions";
6121 return false;
6122 }
6123 }
6124
6125 if (isDS(MI) && !ST.hasGDS()) {
6126 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
6127 if (GDSOp && GDSOp->getImm() != 0) {
6128 ErrInfo = "GDS is not supported on this subtarget";
6129 return false;
6130 }
6131 }
6132
6133 if (isImage(MI)) {
6134 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
6135 if (DimOp) {
6136 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
6137 AMDGPU::OpName::vaddr0);
6138 AMDGPU::OpName RSrcOpName =
6139 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
6140 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
6141 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
6142 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
6143 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
6144 const AMDGPU::MIMGDimInfo *Dim =
6146
6147 if (!Dim) {
6148 ErrInfo = "dim is out of range";
6149 return false;
6150 }
6151
6152 bool IsA16 = false;
6153 if (ST.hasR128A16()) {
6154 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
6155 IsA16 = R128A16->getImm() != 0;
6156 } else if (ST.hasA16()) {
6157 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
6158 IsA16 = A16->getImm() != 0;
6159 }
6160
6161 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
6162
6163 unsigned AddrWords =
6164 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
6165
6166 unsigned VAddrWords;
6167 if (IsNSA) {
6168 VAddrWords = RsrcIdx - VAddr0Idx;
6169 if (ST.hasPartialNSAEncoding() &&
6170 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
6171 unsigned LastVAddrIdx = RsrcIdx - 1;
6172 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
6173 }
6174 } else {
6175 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
6176 if (AddrWords > 12)
6177 AddrWords = 16;
6178 }
6179
6180 if (VAddrWords != AddrWords) {
6181 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
6182 << " but got " << VAddrWords << "\n");
6183 ErrInfo = "bad vaddr size";
6184 return false;
6185 }
6186 }
6187 }
6188
6189 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
6190 if (DppCt) {
6191 using namespace AMDGPU::DPP;
6192
6193 unsigned DC = DppCt->getImm();
6194 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6195 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6196 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6197 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6198 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6199 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6200 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6201 ErrInfo = "Invalid dpp_ctrl value";
6202 return false;
6203 }
6204 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6205 !ST.hasDPPWavefrontShifts()) {
6206 ErrInfo = "Invalid dpp_ctrl value: "
6207 "wavefront shifts are not supported on GFX10+";
6208 return false;
6209 }
6210 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6211 !ST.hasDPPBroadcasts()) {
6212 ErrInfo = "Invalid dpp_ctrl value: "
6213 "broadcasts are not supported on GFX10+";
6214 return false;
6215 }
6216 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6217 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
6218 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6219 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6220 !ST.hasGFX90AInsts()) {
6221 ErrInfo = "Invalid dpp_ctrl value: "
6222 "row_newbroadcast/row_share is not supported before "
6223 "GFX90A/GFX10";
6224 return false;
6225 }
6226 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6227 ErrInfo = "Invalid dpp_ctrl value: "
6228 "row_share and row_xmask are not supported before GFX10";
6229 return false;
6230 }
6231 }
6232
6233 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6235 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6236 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
6237 ErrInfo = "Invalid dpp_ctrl value: "
6238 "DP ALU dpp only support row_newbcast";
6239 return false;
6240 }
6241 }
6242
6243 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
6244 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
6245 AMDGPU::OpName DataName =
6246 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6247 const MachineOperand *Data = getNamedOperand(MI, DataName);
6248 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
6249 if (Data && !Data->isReg())
6250 Data = nullptr;
6251
6252 if (!ST.hasGFX90AInsts()) {
6253 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6254 (Data && RI.isAGPR(MRI, Data->getReg())) ||
6255 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
6256 ErrInfo = "Invalid register class: "
6257 "agpr loads and stores not supported on this GPU";
6258 return false;
6259 }
6260 }
6261 }
6262
6263 if (ST.needsAlignedVGPRs()) {
6264 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
6266 if (!Op)
6267 return true;
6268 Register Reg = Op->getReg();
6269 if (Reg.isPhysical())
6270 return !(RI.getHWRegIndex(Reg) & 1);
6271 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
6272 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6273 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
6274 };
6275
6276 if (isMIMG(MI)) {
6277 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6278 ErrInfo = "Subtarget requires even aligned vector registers "
6279 "for vaddr operand of image instructions";
6280 return false;
6281 }
6282 }
6283 }
6284
6285 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6286 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
6287 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6288 ErrInfo = "Invalid register class: "
6289 "v_accvgpr_write with an SGPR is not supported on this GPU";
6290 return false;
6291 }
6292 }
6293
6294 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6295 const MachineOperand &SrcOp = MI.getOperand(1);
6296 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
6297 ErrInfo = "pseudo expects only physical SGPRs";
6298 return false;
6299 }
6300 }
6301
6302 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
6303 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
6304 if (!ST.hasScaleOffset()) {
6305 ErrInfo = "Subtarget does not support offset scaling";
6306 return false;
6307 }
6308 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
6309 ErrInfo = "Instruction does not support offset scaling";
6310 return false;
6311 }
6312 }
6313 }
6314
6315 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6316 if (AMDGPU::isSingleSGPRReadInst(Opcode)) {
6317 for (unsigned I = 0; I < 3; ++I) {
6319 return false;
6320 }
6321 }
6322
6323 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
6324 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
6325 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
6326 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6327 &AMDGPU::SReg_64RegClass) ||
6328 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6329 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
6330 return false;
6331 }
6332 }
6333
6334 // GFX950 v_pk_{add,mul,fma}_f32 must not have an invalid op_sel.
6335 if (!isLegalPkF32OpSel(*this, MI)) {
6336 ErrInfo = "GFX950 v_pk_{add,mul,fma}_f32 has an invalid op_sel.";
6337 return false;
6338 }
6339
6340 return true;
6341}
6342
6344 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
6345 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6346 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
6347 ? AMDGPU::COPY
6348 : AMDGPU::V_MOV_B32_e32;
6349 }
6350 return getVALUOp(MI.getOpcode());
6351}
6352
6353// It is more readable to list mapped opcodes on the same line.
6354// clang-format off
6355
6356unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
6357 switch (Opc) {
6358 default: return AMDGPU::INSTRUCTION_LIST_END;
6359 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
6360 case AMDGPU::COPY: return AMDGPU::COPY;
6361 case AMDGPU::PHI: return AMDGPU::PHI;
6362 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
6363 case AMDGPU::WQM: return AMDGPU::WQM;
6364 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
6365 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
6366 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
6367 case AMDGPU::S_ADD_I32:
6368 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6369 case AMDGPU::S_ADDC_U32:
6370 return AMDGPU::V_ADDC_U32_e32;
6371 case AMDGPU::S_SUB_I32:
6372 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6373 // FIXME: These are not consistently handled, and selected when the carry is
6374 // used.
6375 case AMDGPU::S_ADD_U32:
6376 return AMDGPU::V_ADD_CO_U32_e32;
6377 case AMDGPU::S_SUB_U32:
6378 return AMDGPU::V_SUB_CO_U32_e32;
6379 case AMDGPU::S_ADD_U64_PSEUDO:
6380 return AMDGPU::V_ADD_U64_PSEUDO;
6381 case AMDGPU::S_SUB_U64_PSEUDO:
6382 return AMDGPU::V_SUB_U64_PSEUDO;
6383 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
6384 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
6385 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
6386 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
6387 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
6388 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
6389 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
6390 case AMDGPU::S_XNOR_B32:
6391 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6392 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
6393 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
6394 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
6395 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
6396 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
6397 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
6398 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
6399 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
6400 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
6401 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
6402 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
6403 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
6404 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
6405 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
6406 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
6407 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
6408 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
6409 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
6410 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
6411 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
6412 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
6413 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
6414 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
6415 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
6416 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
6417 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
6418 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
6419 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
6420 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
6421 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
6422 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
6423 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
6424 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
6425 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
6426 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
6427 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
6428 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
6429 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
6430 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
6431 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
6432 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
6433 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
6434 case AMDGPU::S_CVT_F32_F16:
6435 case AMDGPU::S_CVT_HI_F32_F16:
6436 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6437 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6438 case AMDGPU::S_CVT_F16_F32:
6439 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6440 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6441 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
6442 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
6443 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
6444 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
6445 case AMDGPU::S_CEIL_F16:
6446 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6447 : AMDGPU::V_CEIL_F16_fake16_e64;
6448 case AMDGPU::S_FLOOR_F16:
6449 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6450 : AMDGPU::V_FLOOR_F16_fake16_e64;
6451 case AMDGPU::S_TRUNC_F16:
6452 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6453 : AMDGPU::V_TRUNC_F16_fake16_e64;
6454 case AMDGPU::S_RNDNE_F16:
6455 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6456 : AMDGPU::V_RNDNE_F16_fake16_e64;
6457 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6458 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6459 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6460 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6461 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6462 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6463 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6464 case AMDGPU::S_ADD_F16:
6465 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6466 : AMDGPU::V_ADD_F16_fake16_e64;
6467 case AMDGPU::S_SUB_F16:
6468 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6469 : AMDGPU::V_SUB_F16_fake16_e64;
6470 case AMDGPU::S_MIN_F16:
6471 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6472 : AMDGPU::V_MIN_F16_fake16_e64;
6473 case AMDGPU::S_MAX_F16:
6474 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6475 : AMDGPU::V_MAX_F16_fake16_e64;
6476 case AMDGPU::S_MINIMUM_F16:
6477 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6478 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6479 case AMDGPU::S_MAXIMUM_F16:
6480 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6481 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6482 case AMDGPU::S_MUL_F16:
6483 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6484 : AMDGPU::V_MUL_F16_fake16_e64;
6485 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6486 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6487 case AMDGPU::S_FMAC_F16:
6488 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6489 : AMDGPU::V_FMAC_F16_fake16_e64;
6490 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6491 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6492 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6493 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6494 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6495 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6496 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6497 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6498 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6499 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6500 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6501 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6502 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6503 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6504 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6505 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6506 case AMDGPU::S_CMP_LT_F16:
6507 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6508 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6509 case AMDGPU::S_CMP_EQ_F16:
6510 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6511 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6512 case AMDGPU::S_CMP_LE_F16:
6513 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6514 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6515 case AMDGPU::S_CMP_GT_F16:
6516 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6517 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6518 case AMDGPU::S_CMP_LG_F16:
6519 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6520 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6521 case AMDGPU::S_CMP_GE_F16:
6522 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6523 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6524 case AMDGPU::S_CMP_O_F16:
6525 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6526 : AMDGPU::V_CMP_O_F16_fake16_e64;
6527 case AMDGPU::S_CMP_U_F16:
6528 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6529 : AMDGPU::V_CMP_U_F16_fake16_e64;
6530 case AMDGPU::S_CMP_NGE_F16:
6531 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6532 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6533 case AMDGPU::S_CMP_NLG_F16:
6534 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6535 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6536 case AMDGPU::S_CMP_NGT_F16:
6537 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6538 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6539 case AMDGPU::S_CMP_NLE_F16:
6540 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6541 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6542 case AMDGPU::S_CMP_NEQ_F16:
6543 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6544 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6545 case AMDGPU::S_CMP_NLT_F16:
6546 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6547 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6548 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6549 case AMDGPU::V_S_EXP_F16_e64:
6550 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6551 : AMDGPU::V_EXP_F16_fake16_e64;
6552 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6553 case AMDGPU::V_S_LOG_F16_e64:
6554 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6555 : AMDGPU::V_LOG_F16_fake16_e64;
6556 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6557 case AMDGPU::V_S_RCP_F16_e64:
6558 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6559 : AMDGPU::V_RCP_F16_fake16_e64;
6560 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6561 case AMDGPU::V_S_RSQ_F16_e64:
6562 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6563 : AMDGPU::V_RSQ_F16_fake16_e64;
6564 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6565 case AMDGPU::V_S_SQRT_F16_e64:
6566 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6567 : AMDGPU::V_SQRT_F16_fake16_e64;
6568 }
6570 "Unexpected scalar opcode without corresponding vector one!");
6571}
6572
6573// clang-format on
6574
6578 const DebugLoc &DL, Register Reg,
6579 bool IsSCCLive,
6580 SlotIndexes *Indexes) const {
6581 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6582 const SIInstrInfo *TII = ST.getInstrInfo();
6584 if (IsSCCLive) {
6585 // Insert two move instructions, one to save the original value of EXEC and
6586 // the other to turn on all bits in EXEC. This is required as we can't use
6587 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6588 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6590 auto FlipExecMI =
6591 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6592 if (Indexes) {
6593 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6594 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6595 }
6596 } else {
6597 auto SaveExec =
6598 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6599 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6600 if (Indexes)
6601 Indexes->insertMachineInstrInMaps(*SaveExec);
6602 }
6603}
6604
6607 const DebugLoc &DL, Register Reg,
6608 SlotIndexes *Indexes) const {
6610 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6611 .addReg(Reg, RegState::Kill);
6612 if (Indexes)
6613 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6614}
6615
6619 "Not a whole wave func");
6620 MachineBasicBlock &MBB = *MF.begin();
6621 for (MachineInstr &MI : MBB)
6622 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6623 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6624 return &MI;
6625
6626 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6627}
6628
6630 unsigned OpNo) const {
6631 const MCInstrDesc &Desc = get(MI.getOpcode());
6632 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6633 Desc.operands()[OpNo].RegClass == -1) {
6634 Register Reg = MI.getOperand(OpNo).getReg();
6635
6636 if (Reg.isVirtual()) {
6637 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6638 return MRI.getRegClass(Reg);
6639 }
6640 return RI.getPhysRegBaseClass(Reg);
6641 }
6642
6643 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6644 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6645}
6646
6647// Convert VOP3 operand index to source number.
6648static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx) {
6649 constexpr AMDGPU::OpName OpNames[] = {
6650 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6651
6652 for (auto [I, OpName] : enumerate(OpNames)) {
6653 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6654 if (static_cast<unsigned>(SrcIdx) == OpIdx)
6655 return I;
6656 }
6657
6658 return UINT_MAX;
6659}
6660
6663 MachineBasicBlock *MBB = MI.getParent();
6664 MachineOperand &MO = MI.getOperand(OpIdx);
6665 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6666 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6667 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6668 unsigned Size = RI.getRegSizeInBits(*RC);
6669 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6670 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6671 : AMDGPU::V_MOV_B32_e32;
6672 if (MO.isReg())
6673 Opcode = AMDGPU::COPY;
6674 else if (RI.isSGPRClass(RC))
6675 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6676
6677 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6678 Register Reg = MRI.createVirtualRegister(VRC);
6679 DebugLoc DL = MBB->findDebugLoc(I);
6680
6681 if (Size == 128 && AMDGPU::isPackedSingleSGPR64BitInst(MI.getOpcode()) &&
6683 // Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
6684 // sources behave like OPSEL is set replicating low 64-bits into high. VGPR
6685 // sources in turn read actual 4 registers. To move operand from an SGPR to
6686 // a VGPR we need to replicate low half.
6687 // We also do not select immediates for these instructions so it always has
6688 // to be an SGPR register here.
6689 // Operands which are not legal as per isLegalSingleSGPRReadInstOperand()
6690 // sent here specifically to fix a non-splat SGPR and shall perform a full
6691 // copy.
6692
6693 const TargetRegisterClass *VRC64 = RI.getVGPRClassForBitWidth(64);
6694 Register Low64 = MRI.createVirtualRegister(VRC64);
6695 assert(MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()));
6696 BuildMI(*MBB, I, DL, get(TargetOpcode::COPY), Low64)
6697 .addReg(MO.getReg(), {}, AMDGPU::sub0_sub1);
6698 BuildMI(*MBB, I, DL, get(TargetOpcode::REG_SEQUENCE), Reg)
6699 .addReg(Low64)
6700 .addImm(AMDGPU::sub0_sub1)
6701 .addReg(Low64)
6702 .addImm(AMDGPU::sub2_sub3);
6703 } else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6704 BuildMI(*MBB, I, DL, get(Opcode), Reg)
6705 .addImm(0) // src0_modifiers
6706 .add(MO)
6707 .addImm(0); // op_sel
6708 } else {
6709 BuildMI(*MBB, I, DL, get(Opcode), Reg).add(MO);
6710 }
6711
6712 MO.ChangeToRegister(Reg, false);
6713}
6714
6717 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6718 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6719 if (!SuperReg.getReg().isVirtual())
6720 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6721
6722 MachineBasicBlock *MBB = MI->getParent();
6723 const DebugLoc &DL = MI->getDebugLoc();
6724 Register SubReg = MRI.createVirtualRegister(SubRC);
6725
6726 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6727 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6728 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6729 return SubReg;
6730}
6731
6734 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6735 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6736 if (Op.isImm()) {
6737 if (SubIdx == AMDGPU::sub0)
6738 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6739 if (SubIdx == AMDGPU::sub1)
6740 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6741
6742 llvm_unreachable("Unhandled register index for immediate");
6743 }
6744
6745 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6746 SubIdx, SubRC);
6747 return MachineOperand::CreateReg(SubReg, false);
6748}
6749
6750// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6751void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6752 assert(Inst.getNumExplicitOperands() == 3);
6753 MachineOperand Op1 = Inst.getOperand(1);
6754 Inst.removeOperand(1);
6755 Inst.addOperand(Op1);
6756}
6757
6759 const MCOperandInfo &OpInfo,
6760 const MachineOperand &MO) const {
6761 if (!MO.isReg())
6762 return false;
6763
6764 Register Reg = MO.getReg();
6765
6766 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6767 if (Reg.isPhysical())
6768 return DRC->contains(Reg);
6769
6770 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6771
6772 if (MO.getSubReg()) {
6773 const TargetRegisterClass *SuperRC =
6774 RI.getLargestLegalSuperClass(RC, MRI.getMF());
6775 if (!SuperRC)
6776 return false;
6777 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6778 }
6779
6780 return RI.getCommonSubClass(DRC, RC) != nullptr;
6781}
6782
6784 const MachineOperand &MO) const {
6785 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6786 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6787 unsigned Opc = MI.getOpcode();
6788
6789 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6790 if (MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
6791 AMDGPU::isSingleSGPRReadInst(MI.getOpcode()) &&
6793 &MO))
6794 return false;
6795
6796 if (!isLegalRegOperand(MRI, OpInfo, MO))
6797 return false;
6798
6799 // check Accumulate GPR operand
6800 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6801 if (IsAGPR && !ST.hasMAIInsts())
6802 return false;
6803 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6804 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6805 return false;
6806 // Atomics should have both vdst and vdata either vgpr or agpr.
6807 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6808 const int DataIdx = AMDGPU::getNamedOperandIdx(
6809 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6810 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6811 MI.getOperand(DataIdx).isReg() &&
6812 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6813 return false;
6814 if ((int)OpIdx == DataIdx) {
6815 if (VDstIdx != -1 &&
6816 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6817 return false;
6818 // DS instructions with 2 src operands also must have tied RC.
6819 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6820 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6821 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6822 return false;
6823 }
6824
6825 // Check V_ACCVGPR_WRITE_B32_e64
6826 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6827 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6828 RI.isSGPRReg(MRI, MO.getReg()))
6829 return false;
6830
6831 if (ST.hasFlatScratchHiInB64InstHazard() &&
6832 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6833 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6834 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6835 64)
6836 return false;
6837 }
6838 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6839 return false;
6840 }
6841 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6842 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6843 return false;
6844
6845 return true;
6846}
6847
6849 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6850 const MachineOperand *MO) const {
6851 constexpr unsigned NumOps = 3;
6852 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6853 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6854 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6855 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6856
6857 assert(SrcN < NumOps);
6858
6859 if (!MO) {
6860 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6861 if (SrcIdx == -1)
6862 return true;
6863 MO = &MI.getOperand(SrcIdx);
6864 }
6865
6866 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6867 return true;
6868
6869 int ModsIdx =
6870 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6871 if (ModsIdx == -1)
6872 return false;
6873
6874 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6875 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6876 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6877
6878 return !OpSel && !OpSelHi;
6879}
6880
6881bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
6882 const MachineOperand *MO) const {
6883 const MachineFunction &MF = *MI.getMF();
6884 const MachineRegisterInfo &MRI = MF.getRegInfo();
6885 const MCInstrDesc &InstDesc = MI.getDesc();
6886 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6887 int64_t RegClass = getOpRegClassID(OpInfo);
6888 const TargetRegisterClass *DefinedRC =
6889 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6890 if (!MO)
6891 MO = &MI.getOperand(OpIdx);
6892
6893 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6894
6895 if (isVALU(MI, /*AllowLDSDMA=*/false) && !IsInlineConst &&
6896 usesConstantBus(MRI, *MO, OpInfo)) {
6897 const MachineOperand *UsedLiteral = nullptr;
6898
6899 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6900 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6901
6902 // TODO: Be more permissive with frame indexes.
6903 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6904 if (!LiteralLimit--)
6905 return false;
6906
6907 UsedLiteral = MO;
6908 }
6909
6911 if (MO->isReg())
6912 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6913
6914 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6915 if (i == OpIdx)
6916 continue;
6917 const MachineOperand &Op = MI.getOperand(i);
6918 if (Op.isReg()) {
6919 if (Op.isUse()) {
6920 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6921 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6922 if (--ConstantBusLimit <= 0)
6923 return false;
6924 }
6925 }
6926 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6927 !isInlineConstant(Op, InstDesc.operands()[i])) {
6928 // The same literal may be used multiple times.
6929 if (!UsedLiteral)
6930 UsedLiteral = &Op;
6931 else if (UsedLiteral->isIdenticalTo(Op))
6932 continue;
6933
6934 if (!LiteralLimit--)
6935 return false;
6936 if (--ConstantBusLimit <= 0)
6937 return false;
6938 }
6939 }
6940 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6941 // There can be at most one literal operand, but it can be repeated.
6942 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6943 if (i == OpIdx)
6944 continue;
6945 const MachineOperand &Op = MI.getOperand(i);
6946 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6947 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6948 !Op.isIdenticalTo(*MO))
6949 return false;
6950
6951 // Do not fold a non-inlineable and non-register operand into an
6952 // instruction that already has a frame index. The frame index handling
6953 // code could not handle well when a frame index co-exists with another
6954 // non-register operand, unless that operand is an inlineable immediate.
6955 if (Op.isFI())
6956 return false;
6957 }
6958 }
6959
6960 if (MO->isReg()) {
6961 if (!DefinedRC)
6962 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6963 return isLegalRegOperand(MI, OpIdx, *MO);
6964 }
6965
6966 if (MO->isImm()) {
6967 uint64_t Imm = MO->getImm();
6968 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6969 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6970 bool Is64BitOp = Is64BitFPOp ||
6971 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6972 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6973 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6974 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6975 if (Is64BitOp &&
6976 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6977 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6978 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6979 return false;
6980
6981 // FIXME: We can use sign extended 64-bit literals, but only for signed
6982 // operands. At the moment we do not know if an operand is signed.
6983 // Such operand will be encoded as its low 32 bits and then either
6984 // correctly sign extended or incorrectly zero extended by HW.
6985 // If 64-bit literals are supported and the literal will be encoded
6986 // as full 64 bit we still can use it.
6987 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6988 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
6989 return false;
6990 }
6991 }
6992
6993 // Handle non-register types that are treated like immediates.
6994 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
6995
6996 if (!DefinedRC) {
6997 // This operand expects an immediate.
6998 return true;
6999 }
7000
7001 return isImmOperandLegal(MI, OpIdx, *MO);
7002}
7003
7005 bool IsGFX950Only = ST.hasGFX950Insts();
7006 bool IsGFX940Only = ST.hasGFX940Insts();
7007
7008 if (!IsGFX950Only && !IsGFX940Only)
7009 return false;
7010
7011 if (!isVALU(MI, /*AllowLDSDMA=*/false))
7012 return false;
7013
7014 // V_COS, V_EXP, V_RCP, etc.
7015 if (isTRANS(MI))
7016 return true;
7017
7018 // DOT2, DOT2C, DOT4, etc.
7019 if (isDOT(MI))
7020 return true;
7021
7022 // MFMA, SMFMA
7023 if (isMFMA(MI))
7024 return true;
7025
7026 unsigned Opcode = MI.getOpcode();
7027 switch (Opcode) {
7028 case AMDGPU::V_CVT_PK_BF8_F32_e64:
7029 case AMDGPU::V_CVT_PK_FP8_F32_e64:
7030 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
7031 case AMDGPU::V_MQSAD_U32_U8_e64:
7032 case AMDGPU::V_PK_ADD_F16:
7033 case AMDGPU::V_PK_ADD_F32:
7034 case AMDGPU::V_PK_ADD_I16:
7035 case AMDGPU::V_PK_ADD_U16:
7036 case AMDGPU::V_PK_ASHRREV_I16:
7037 case AMDGPU::V_PK_FMA_F16:
7038 case AMDGPU::V_PK_FMA_F32:
7039 case AMDGPU::V_PK_FMAC_F16_e32:
7040 case AMDGPU::V_PK_FMAC_F16_e64:
7041 case AMDGPU::V_PK_LSHLREV_B16:
7042 case AMDGPU::V_PK_LSHRREV_B16:
7043 case AMDGPU::V_PK_MAD_I16:
7044 case AMDGPU::V_PK_MAD_U16:
7045 case AMDGPU::V_PK_MAX_F16:
7046 case AMDGPU::V_PK_MAX_I16:
7047 case AMDGPU::V_PK_MAX_U16:
7048 case AMDGPU::V_PK_MIN_F16:
7049 case AMDGPU::V_PK_MIN_I16:
7050 case AMDGPU::V_PK_MIN_U16:
7051 case AMDGPU::V_PK_MOV_B32:
7052 case AMDGPU::V_PK_MUL_F16:
7053 case AMDGPU::V_PK_MUL_F32:
7054 case AMDGPU::V_PK_MUL_LO_U16:
7055 case AMDGPU::V_PK_SUB_I16:
7056 case AMDGPU::V_PK_SUB_U16:
7057 case AMDGPU::V_QSAD_PK_U16_U8_e64:
7058 return true;
7059 default:
7060 return false;
7061 }
7062}
7063
7065 MachineInstr &MI) const {
7066 unsigned Opc = MI.getOpcode();
7067 const MCInstrDesc &InstrDesc = get(Opc);
7068
7069 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
7070 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7071
7072 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
7073 MachineOperand &Src1 = MI.getOperand(Src1Idx);
7074
7075 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
7076 // we need to only have one constant bus use before GFX10.
7077 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
7078 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
7079 RI.isSGPRReg(MRI, Src0.getReg()))
7080 legalizeOpWithMove(MI, Src0Idx);
7081
7082 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
7083 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
7084 // src0/src1 with V_READFIRSTLANE.
7085 if (Opc == AMDGPU::V_WRITELANE_B32) {
7086 const DebugLoc &DL = MI.getDebugLoc();
7087 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
7088 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7089 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7090 .add(Src0);
7091 Src0.ChangeToRegister(Reg, false);
7092 }
7093 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
7094 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7095 const DebugLoc &DL = MI.getDebugLoc();
7096 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7097 .add(Src1);
7098 Src1.ChangeToRegister(Reg, false);
7099 }
7100 return;
7101 }
7102
7103 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
7104 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
7105 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
7106 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
7107 legalizeOpWithMove(MI, Src2Idx);
7108 }
7109
7110 // VOP2 src0 instructions support all operand types, so we don't need to check
7111 // their legality. If src1 is already legal, we don't need to do anything.
7112 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
7113 return;
7114
7115 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
7116 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
7117 // select is uniform.
7118 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
7119 RI.isVGPR(MRI, Src1.getReg())) {
7120 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7121 const DebugLoc &DL = MI.getDebugLoc();
7122 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7123 .add(Src1);
7124 Src1.ChangeToRegister(Reg, false);
7125 return;
7126 }
7127
7128 // We do not use commuteInstruction here because it is too aggressive and will
7129 // commute if it is possible. We only want to commute here if it improves
7130 // legality. This can be called a fairly large number of times so don't waste
7131 // compile time pointlessly swapping and checking legality again.
7132 if (HasImplicitSGPR || !MI.isCommutable()) {
7133 legalizeOpWithMove(MI, Src1Idx);
7134 return;
7135 }
7136
7137 // If src0 can be used as src1, commuting will make the operands legal.
7138 // Otherwise we have to give up and insert a move.
7139 //
7140 // TODO: Other immediate-like operand kinds could be commuted if there was a
7141 // MachineOperand::ChangeTo* for them.
7142 if ((!Src1.isImm() && !Src1.isReg()) ||
7143 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
7144 legalizeOpWithMove(MI, Src1Idx);
7145 return;
7146 }
7147
7148 int CommutedOpc = commuteOpcode(MI);
7149 if (CommutedOpc == -1) {
7150 legalizeOpWithMove(MI, Src1Idx);
7151 return;
7152 }
7153
7154 MI.setDesc(get(CommutedOpc));
7155
7156 Register Src0Reg = Src0.getReg();
7157 unsigned Src0SubReg = Src0.getSubReg();
7158 bool Src0Kill = Src0.isKill();
7159
7160 if (Src1.isImm())
7161 Src0.ChangeToImmediate(Src1.getImm());
7162 else if (Src1.isReg()) {
7163 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
7164 Src0.setSubReg(Src1.getSubReg());
7165 } else
7166 llvm_unreachable("Should only have register or immediate operands");
7167
7168 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
7169 Src1.setSubReg(Src0SubReg);
7171}
7172
7173// Legalize VOP3 operands. All operand types are supported for any operand
7174// but only one literal constant and only starting from GFX10.
7176 MachineInstr &MI) const {
7177 unsigned Opc = MI.getOpcode();
7178
7179 int VOP3Idx[3] = {
7180 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
7181 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
7182 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
7183 };
7184
7185 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7186 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7187 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7188 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7189 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7190 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7191 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7192 // src1 and src2 must be scalar
7193 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
7194 const DebugLoc &DL = MI.getDebugLoc();
7195 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
7196 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7197 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7198 .add(Src1);
7199 Src1.ChangeToRegister(Reg, false);
7200 }
7201 if (VOP3Idx[2] != -1) {
7202 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
7203 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
7204 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7205 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7206 .add(Src2);
7207 Src2.ChangeToRegister(Reg, false);
7208 }
7209 }
7210 }
7211
7212 // Find the one SGPR operand we are allowed to use.
7213 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
7214 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7215 SmallDenseSet<unsigned> SGPRsUsed;
7216 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
7217 if (SGPRReg) {
7218 SGPRsUsed.insert(SGPRReg);
7219 --ConstantBusLimit;
7220 }
7221
7222 for (int Idx : VOP3Idx) {
7223 if (Idx == -1)
7224 break;
7225 MachineOperand &MO = MI.getOperand(Idx);
7226
7227 if (!MO.isReg()) {
7228 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
7229 continue;
7230
7231 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7232 --LiteralLimit;
7233 --ConstantBusLimit;
7234 continue;
7235 }
7236
7237 --LiteralLimit;
7238 --ConstantBusLimit;
7239 legalizeOpWithMove(MI, Idx);
7240 continue;
7241 }
7242
7243 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
7244 continue; // VGPRs are legal
7245
7246 // We can use one SGPR in each VOP3 instruction prior to GFX10
7247 // and two starting from GFX10.
7248 if (SGPRsUsed.count(MO.getReg()))
7249 continue;
7250 if (ConstantBusLimit > 0) {
7251 SGPRsUsed.insert(MO.getReg());
7252 --ConstantBusLimit;
7253 continue;
7254 }
7255
7256 // If we make it this far, then the operand is not legal and we must
7257 // legalize it.
7258 legalizeOpWithMove(MI, Idx);
7259 }
7260
7261 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
7262 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
7263 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
7264 Opc == AMDGPU::V_FMAC_F16_t16_e64) &&
7265 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
7266 legalizeOpWithMove(MI, VOP3Idx[2]);
7267
7268 // Fix the register class of single-sgpr-read instructions on gfx12+. See
7269 // SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
7271 for (unsigned I = 0; I < 3; ++I) {
7272 if (!isLegalSingleSGPRReadInstOperand(MRI, MI, /*SrcN=*/I))
7273 legalizeOpWithMove(MI, VOP3Idx[I]);
7274 }
7275 }
7276}
7277
7280 const TargetRegisterClass *DstRC /*=nullptr*/) const {
7281 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
7282 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
7283 if (DstRC)
7284 SRC = RI.getCommonSubClass(SRC, DstRC);
7285
7286 Register DstReg = MRI.createVirtualRegister(SRC);
7287 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7288
7289 if (RI.hasAGPRs(VRC)) {
7290 VRC = RI.getEquivalentVGPRClass(VRC);
7291 Register NewSrcReg = MRI.createVirtualRegister(VRC);
7292 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7293 get(TargetOpcode::COPY), NewSrcReg)
7294 .addReg(SrcReg);
7295 SrcReg = NewSrcReg;
7296 }
7297
7298 if (SubRegs == 1) {
7299 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7300 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7301 .addReg(SrcReg);
7302 return DstReg;
7303 }
7304
7306 for (unsigned i = 0; i < SubRegs; ++i) {
7307 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7308 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7309 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7310 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7311 SRegs.push_back(SGPR);
7312 }
7313
7315 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7316 get(AMDGPU::REG_SEQUENCE), DstReg);
7317 for (unsigned i = 0; i < SubRegs; ++i) {
7318 MIB.addReg(SRegs[i]);
7319 MIB.addImm(RI.getSubRegFromChannel(i));
7320 }
7321 return DstReg;
7322}
7323
7325 MachineInstr &MI) const {
7326
7327 // If the pointer is store in VGPRs, then we need to move them to
7328 // SGPRs using v_readfirstlane. This is safe because we only select
7329 // loads with uniform pointers to SMRD instruction so we know the
7330 // pointer value is uniform.
7331 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
7332 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
7333 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
7334 SBase->setReg(SGPR);
7335 }
7336 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
7337 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
7338 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
7339 SOff->setReg(SGPR);
7340 }
7341}
7342
7344 unsigned Opc = Inst.getOpcode();
7345 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
7346 if (OldSAddrIdx < 0)
7347 return false;
7348
7349 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
7350
7351 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
7352 if (NewOpc < 0)
7354 if (NewOpc < 0)
7355 return false;
7356
7358 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
7359 if (RI.isSGPRReg(MRI, SAddr.getReg()))
7360 return false;
7361
7362 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7363 if (NewVAddrIdx < 0)
7364 return false;
7365
7366 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
7367
7368 // Check vaddr, it shall be zero or absent.
7369 MachineInstr *VAddrDef = nullptr;
7370 if (OldVAddrIdx >= 0) {
7371 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
7372 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
7373 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
7374 !VAddrDef->getOperand(1).isImm() ||
7375 VAddrDef->getOperand(1).getImm() != 0)
7376 return false;
7377 }
7378
7379 const MCInstrDesc &NewDesc = get(NewOpc);
7380 Inst.setDesc(NewDesc);
7381
7382 // Callers expect iterator to be valid after this call, so modify the
7383 // instruction in place.
7384 if (OldVAddrIdx == NewVAddrIdx) {
7385 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
7386 // Clear use list from the old vaddr holding a zero register.
7387 MRI.removeRegOperandFromUseList(&NewVAddr);
7388 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7389 Inst.removeOperand(OldSAddrIdx);
7390 // Update the use list with the pointer we have just moved from vaddr to
7391 // saddr position. Otherwise new vaddr will be missing from the use list.
7392 MRI.removeRegOperandFromUseList(&NewVAddr);
7393 MRI.addRegOperandToUseList(&NewVAddr);
7394 } else {
7395 assert(OldSAddrIdx == NewVAddrIdx);
7396
7397 if (OldVAddrIdx >= 0) {
7398 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7399 AMDGPU::OpName::vdst_in);
7400
7401 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
7402 // it asserts. Untie the operands for now and retie them afterwards.
7403 if (NewVDstIn != -1) {
7404 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
7405 Inst.untieRegOperand(OldVDstIn);
7406 }
7407
7408 Inst.removeOperand(OldVAddrIdx);
7409
7410 if (NewVDstIn != -1) {
7411 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7412 Inst.tieOperands(NewVDst, NewVDstIn);
7413 }
7414 }
7415 }
7416
7417 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
7418 VAddrDef->eraseFromParent();
7419
7420 return true;
7421}
7422
7423// FIXME: Remove this when SelectionDAG is obsoleted.
7425 MachineInstr &MI) const {
7426 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
7427 return;
7428
7429 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
7430 // thinks they are uniform, so a readfirstlane should be valid.
7431 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
7432 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
7433 return;
7434
7436 return;
7437
7438 const TargetRegisterClass *DeclaredRC =
7439 getRegClass(MI.getDesc(), SAddr->getOperandNo());
7440
7441 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
7442 SAddr->setReg(ToSGPR);
7443}
7444
7447 const TargetRegisterClass *DstRC,
7450 const DebugLoc &DL) const {
7451 Register OpReg = Op.getReg();
7452 unsigned OpSubReg = Op.getSubReg();
7453
7454 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
7455 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7456
7457 // Check if operand is already the correct register class.
7458 if (DstRC == OpRC)
7459 return;
7460
7461 Register DstReg = MRI.createVirtualRegister(DstRC);
7462 auto Copy = BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg)
7463 .addReg(OpReg, {}, OpSubReg);
7464 Op.setReg(DstReg);
7465 Op.setSubReg(AMDGPU::NoSubRegister);
7466
7467 MachineInstr *Def = MRI.getVRegDef(OpReg);
7468 if (!Def)
7469 return;
7470
7471 // Try to eliminate the copy if it is copying an immediate value.
7472 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7473 foldImmediate(*Copy, *Def, OpReg, &MRI);
7474
7475 bool ImpDef = Def->isImplicitDef();
7476 while (!ImpDef && Def && Def->isCopy()) {
7477 if (Def->getOperand(1).getReg().isPhysical())
7478 break;
7479 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7480 ImpDef = Def && Def->isImplicitDef();
7481 }
7482 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7483 !ImpDef)
7484 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7485}
7486
7487// Emit the actual waterfall loop, executing the wrapped instruction for each
7488// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7489// iteration, in the worst case we execute 64 (once per lane).
7492 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7493 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7494 MachineFunction &MF = *LoopBB.getParent();
7496 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7498 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7499
7500 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7501 // available. Otherwise, use the previous pattern of v_cmp_eq,
7502 // s_and_saveexec, and s_xor.
7503 bool UseNewExecInstructions =
7504 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7505
7507 Register CondReg;
7508
7509 Register PhiExec;
7510 Register NewExec;
7511
7512 if (UseNewExecInstructions) {
7513 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7514 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7515 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7516 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7517 .addReg(LMC.ExecReg);
7518
7519 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7520 .addReg(InitExec)
7521 .addMBB(&PredBB)
7522 .addReg(NewExec)
7523 .addMBB(&BodyBB);
7524 }
7525
7526 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7527 // involves a trade-off between register pressure and latency:
7528 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7529 // register pressure because arguments and results of all
7530 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7531 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7532 // increase latency by placing v_readfirstlane instructions
7533 // immediately before v_cmpx instruction that directly depend on it.
7534 ///
7535 // Emitting interleaved v_cmpx and v_readfirstlane requires
7536 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7537 // v_cmpx needs to be treated as terminator until after register allocation
7538 // (spill placement) and instruction reordering.
7539 //
7540 // Current implementation defers v_cmpx and leaves other instruction
7541 // scheduling decisions to later passes, where register pressure is known or
7542 // easier to approximate.
7543 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7544 // v_cmpx instructions are inserted at the end of LoopBB.
7545 // After the first v_cmpx is emitted, I is updated to point to it
7546 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7547 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7548 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7549 unsigned NumSubRegs = RegSize / 32;
7550 Register VScalarOp = ScalarOp->getReg();
7551
7552 const TargetRegisterClass *RFLSrcRC =
7553 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7554
7555 if (NumSubRegs == 1) {
7556 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7557 if (const TargetRegisterClass *Common =
7558 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7559 Common != VScalarOpRC) {
7560 Register VRReg = MRI.createVirtualRegister(Common);
7561 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7562 VScalarOp = VRReg;
7563 }
7564 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7565
7566 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7567 .addReg(VScalarOp);
7568
7569 if (UseNewExecInstructions) {
7570 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7571 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7572 .addReg(CurReg)
7573 .addReg(VScalarOp);
7574 if (I == LoopBB.end())
7575 I = CmpxMI.getInstr()->getIterator();
7576 } else {
7577 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7578
7579 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7580 .addReg(CurReg)
7581 .addReg(VScalarOp);
7582
7583 // Combine the comparison results with AND.
7584 if (!CondReg) { // First.
7585 CondReg = NewCondReg;
7586 } else { // If not the first, we create an AND.
7587 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7588 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7589 .addReg(CondReg)
7590 .addReg(NewCondReg)
7591 .setOperandDead(3);
7592 CondReg = AndReg;
7593 }
7594 }
7595
7596 // Update ScalarOp operand to use the SGPR ScalarOp.
7597 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7598 ScalarOp->setReg(CurReg);
7599 else {
7600 // Insert into the same block of use
7601 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7602 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7603 .addReg(CurReg);
7604 ScalarOp->setReg(PhySGPRs[Idx]);
7605 }
7606 } else {
7607 SmallVector<Register, 8> ReadlanePieces;
7608 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7609 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7610 "Unhandled register size");
7611
7612 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7613 Register CurRegLo =
7614 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7615 Register CurRegHi =
7616 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7617
7618 // Read the next variant <- also loop target.
7619 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7620 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7621
7622 // Read the next variant <- also loop target.
7623 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7624 .addReg(VScalarOp, VScalarOpUndef,
7625 TRI->getSubRegFromChannel(Idx + 1));
7626
7627 ReadlanePieces.push_back(CurRegLo);
7628 ReadlanePieces.push_back(CurRegHi);
7629
7630 // Comparison is to be done as 64-bit.
7631 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7632 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7633 .addReg(CurRegLo)
7634 .addImm(AMDGPU::sub0)
7635 .addReg(CurRegHi)
7636 .addImm(AMDGPU::sub1);
7637
7638 unsigned SubReg =
7639 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7640
7641 if (UseNewExecInstructions) {
7642 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7643 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7644 .addReg(CurReg)
7645 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7646 if (I == LoopBB.end())
7647 I = CmpxMI.getInstr()->getIterator();
7648 } else {
7649 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7650 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7651 .addReg(CurReg)
7652 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7653
7654 // Combine the comparison results with AND.
7655 if (!CondReg) { // First.
7656 CondReg = NewCondReg;
7657 } else { // If not the first, we create an AND.
7658 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7659 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7660 .addReg(CondReg)
7661 .addReg(NewCondReg)
7662 .setOperandDead(3);
7663 CondReg = AndReg;
7664 }
7665 }
7666 } // End for loop.
7667
7668 const auto *SScalarOpRC =
7669 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7670 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7671
7672 // Build scalar ScalarOp.
7673 auto Merge =
7674 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7675 unsigned Channel = 0;
7676 for (Register Piece : ReadlanePieces) {
7677 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7678 }
7679
7680 // Update ScalarOp operand to use the SGPR ScalarOp.
7681 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7682 ScalarOp->setReg(SScalarOp);
7683 else {
7684 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7685 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7686 .addReg(SScalarOp);
7687 ScalarOp->setReg(PhySGPRs[Idx]);
7688 }
7689 }
7690 }
7691
7692 // AndSaveExecOpc modifies EXEC but can't be isTerminator=1: terminators
7693 // that define virtual registers aren't supported.
7694 Register SaveExec;
7695 if (!UseNewExecInstructions) {
7696 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7697 MRI.setSimpleHint(SaveExec, CondReg);
7698
7699 // Update EXEC to matching lanes, saving original to SaveExec.
7700 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7701 .addReg(CondReg)
7702 .setOperandDead(3);
7703 }
7704
7705 // The original instruction is here; we insert the terminators after it.
7706 I = BodyBB.end();
7707
7708 if (UseNewExecInstructions) {
7709 // Compute the remaining lanes into a plain virtual register and write EXEC
7710 // from a terminator, so spill code for NewExec is placed before EXEC
7711 // changes. SIOptimizeExecMasking opportunistically folds the pair back
7712 // into S_ANDN2_WREXEC after register allocation.
7713 MRI.setSimpleHint(NewExec, PhiExec);
7714 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2Opc), NewExec)
7715 .addReg(PhiExec)
7716 .addReg(LMC.ExecReg)
7717 .setOperandDead(3);
7718 BuildMI(BodyBB, I, DL, TII.get(LMC.MovTermOpc), LMC.ExecReg)
7719 .addReg(NewExec);
7720 } else {
7721 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7722 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7723 .addReg(LMC.ExecReg)
7724 .addReg(SaveExec)
7725 .setOperandDead(3);
7726 }
7727
7728 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7729}
7730
7731// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7732// with SGPRs by iterating over all unique values across all lanes.
7733// Returns the loop basic block that now contains \p MI.
7734static MachineBasicBlock *
7738 MachineBasicBlock::iterator Begin = nullptr,
7740 ArrayRef<Register> PhySGPRs = {}) {
7741 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7742 "Physical SGPRs must be empty or match the number of scalar operands");
7744 MachineFunction &MF = *MBB.getParent();
7746 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7748 if (!Begin.isValid())
7749 Begin = &MI;
7750 if (!End.isValid()) {
7751 End = &MI;
7752 ++End;
7753 }
7754 const DebugLoc &DL = MI.getDebugLoc();
7756 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7757
7758 // Save SCC. Waterfall Loop may overwrite SCC.
7759 Register SaveSCCReg;
7760
7761 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7762 // rather than unlimited scan everywhere
7763 bool SCCNotDead =
7764 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7765 std::numeric_limits<unsigned>::max()) !=
7767 if (SCCNotDead) {
7768 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7769 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7770 .addImm(1)
7771 .addImm(0);
7772 }
7773
7774 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7775
7776 // Save the EXEC mask
7777 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7778
7779 // To insert the loop we need to split the block. Move everything after this
7780 // point to a new block, and insert a new empty block between the two.
7783 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7785 ++MBBI;
7786
7787 MF.insert(MBBI, LoopBB);
7788 MF.insert(MBBI, BodyBB);
7789 MF.insert(MBBI, RemainderBB);
7790
7791 LoopBB->addSuccessor(BodyBB);
7792 BodyBB->addSuccessor(LoopBB);
7793 BodyBB->addSuccessor(RemainderBB);
7794
7795 // Move Begin to MI to the BodyBB, and the remainder of the block to
7796 // RemainderBB.
7797 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7798 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7799 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7800
7801 MBB.addSuccessor(LoopBB);
7802
7803 // Update dominators. We know that MBB immediately dominates LoopBB, that
7804 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7805 // RemainderBB. RemainderBB immediately dominates all of the successors
7806 // transferred to it from MBB that MBB used to properly dominate.
7807 if (MDT) {
7808 MDT->addNewBlock(LoopBB, &MBB);
7809 MDT->addNewBlock(BodyBB, LoopBB);
7810 MDT->addNewBlock(RemainderBB, BodyBB);
7811 for (auto &Succ : RemainderBB->successors()) {
7812 if (MDT->properlyDominates(&MBB, Succ)) {
7813 MDT->changeImmediateDominator(Succ, RemainderBB);
7814 }
7815 }
7816 }
7817
7818 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7819 PhySGPRs);
7820
7821 MachineBasicBlock::iterator First = RemainderBB->begin();
7822 // Restore SCC
7823 if (SCCNotDead) {
7824 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7825 .addReg(SaveSCCReg)
7826 .addImm(0);
7827 }
7828
7829 // Restore the EXEC mask
7830 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7831 .addReg(SaveExec);
7832 return BodyBB;
7833}
7834
7835// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7836static std::tuple<unsigned, unsigned>
7838 MachineBasicBlock &MBB = *MI.getParent();
7839 MachineFunction &MF = *MBB.getParent();
7841
7842 // Extract the ptr from the resource descriptor.
7843 unsigned RsrcPtr =
7844 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7845 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7846
7847 // Create an empty resource descriptor
7848 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7849 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7850 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7851 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7852 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7853
7854 // Zero64 = 0
7855 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7856 .addImm(0);
7857
7858 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7859 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7860 .addImm(Lo_32(RsrcDataFormat));
7861
7862 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7863 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7864 .addImm(Hi_32(RsrcDataFormat));
7865
7866 // NewSRsrc = {Zero64, SRsrcFormat}
7867 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7868 .addReg(Zero64)
7869 .addImm(AMDGPU::sub0_sub1)
7870 .addReg(SRsrcFormatLo)
7871 .addImm(AMDGPU::sub2)
7872 .addReg(SRsrcFormatHi)
7873 .addImm(AMDGPU::sub3);
7874
7875 return std::tuple(RsrcPtr, NewSRsrc);
7876}
7877
7880 MachineDominatorTree *MDT) const {
7881 MachineFunction &MF = *MI.getMF();
7883 MachineBasicBlock *CreatedBB = nullptr;
7884
7885 // Legalize True16
7886 if (ST.useRealTrue16Insts())
7888
7889 // Legalize VOP2
7890 if (isVOP2(MI) || isVOPC(MI)) {
7892 return CreatedBB;
7893 }
7894
7895 // Legalize VOP3
7896 if (isVOP3(MI)) {
7898 return CreatedBB;
7899 }
7900
7901 // Legalize SMRD
7902 if (isSMRD(MI)) {
7904 return CreatedBB;
7905 }
7906
7907 // Legalize FLAT
7908 if (isFLAT(MI)) {
7910 return CreatedBB;
7911 }
7912
7913 // Legalize PHI
7914 // The register class of the operands must be the same type as the register
7915 // class of the output.
7916 if (MI.getOpcode() == AMDGPU::PHI) {
7917 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7918 assert(!RI.isSGPRClass(VRC));
7919
7920 // Update all the operands so they have the same type.
7921 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7922 MachineOperand &Op = MI.getOperand(I);
7923 if (!Op.isReg() || !Op.getReg().isVirtual())
7924 continue;
7925
7926 // MI is a PHI instruction.
7927 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7929
7930 // Avoid creating no-op copies with the same src and dst reg class. These
7931 // confuse some of the machine passes.
7932 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7933 }
7934 }
7935
7936 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7937 // VGPR dest type and SGPR sources, insert copies so all operands are
7938 // VGPRs. This seems to help operand folding / the register coalescer.
7939 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7940 MachineBasicBlock *MBB = MI.getParent();
7941 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7942 if (RI.hasVGPRs(DstRC)) {
7943 // Update all the operands so they are VGPR register classes. These may
7944 // not be the same register class because REG_SEQUENCE supports mixing
7945 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7946 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7947 MachineOperand &Op = MI.getOperand(I);
7948 if (!Op.isReg() || !Op.getReg().isVirtual())
7949 continue;
7950
7951 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7952 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7953 if (VRC == OpRC)
7954 continue;
7955
7956 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7957 }
7958 }
7959
7960 return CreatedBB;
7961 }
7962
7963 // Legalize INSERT_SUBREG
7964 // src0 must have the same register class as dst
7965 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7966 Register Dst = MI.getOperand(0).getReg();
7967 Register Src0 = MI.getOperand(1).getReg();
7968 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7969 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7970 if (DstRC != Src0RC) {
7971 MachineBasicBlock *MBB = MI.getParent();
7972 MachineOperand &Op = MI.getOperand(1);
7973 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7974 }
7975 return CreatedBB;
7976 }
7977
7978 // Legalize SI_INIT_M0
7979 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7980 MachineOperand &Src = MI.getOperand(0);
7981 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7982 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7983 return CreatedBB;
7984 }
7985
7986 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
7987 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7988 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7989 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7990 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7991 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7992 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7993 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7994 MachineOperand &Src = MI.getOperand(1);
7995 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7996 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7997 return CreatedBB;
7998 }
7999
8000 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
8001 //
8002 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
8003 // scratch memory access. In both cases, the legalization never involves
8004 // conversion to the addr64 form.
8006 (isMUBUF(MI) || isMTBUF(MI)))) {
8007 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
8008 ? AMDGPU::OpName::rsrc
8009 : AMDGPU::OpName::srsrc;
8010 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
8011 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
8012 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
8013
8014 AMDGPU::OpName SampOpName =
8015 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
8016 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
8017 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
8018 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
8019
8020 return CreatedBB;
8021 }
8022
8023 // Legalize SI_CALL
8024 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
8025 MachineOperand *Dest = &MI.getOperand(0);
8026 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
8027 createWaterFallForSiCall(&MI, MDT, {Dest});
8028 }
8029 }
8030
8031 // Legalize s_sleep_var.
8032 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
8033 const DebugLoc &DL = MI.getDebugLoc();
8034 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8035 int Src0Idx =
8036 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
8037 MachineOperand &Src0 = MI.getOperand(Src0Idx);
8038 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
8039 .add(Src0);
8040 Src0.ChangeToRegister(Reg, false);
8041 return nullptr;
8042 }
8043
8044 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
8045 // operands are scalar.
8046 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
8047 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
8048 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
8049 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
8050 for (MachineOperand &Src : MI.explicit_operands()) {
8051 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
8052 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
8053 }
8054 return CreatedBB;
8055 }
8056
8057 // Legalize MUBUF instructions.
8058 bool isSoffsetLegal = true;
8059 int SoffsetIdx =
8060 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
8061 if (SoffsetIdx != -1) {
8062 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
8063 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
8064 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
8065 isSoffsetLegal = false;
8066 }
8067 }
8068
8069 bool isRsrcLegal = true;
8070 int RsrcIdx =
8071 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
8072 if (RsrcIdx != -1) {
8073 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
8074 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
8075 isRsrcLegal = false;
8076 }
8077
8078 // The operands are legal.
8079 if (isRsrcLegal && isSoffsetLegal)
8080 return CreatedBB;
8081
8082 if (!isRsrcLegal) {
8083 // Legalize a VGPR Rsrc
8084 //
8085 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
8086 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
8087 // a zero-value SRsrc.
8088 //
8089 // If the instruction is _OFFSET (both idxen and offen disabled), and we
8090 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
8091 // above.
8092 //
8093 // Otherwise we are on non-ADDR64 hardware, and/or we have
8094 // idxen/offen/bothen and we fall back to a waterfall loop.
8095
8096 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
8097 MachineBasicBlock &MBB = *MI.getParent();
8098
8099 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
8100 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
8101 // This is already an ADDR64 instruction so we need to add the pointer
8102 // extracted from the resource descriptor to the current value of VAddr.
8103 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8104 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8105 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8106
8107 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
8108 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
8109 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
8110
8111 unsigned RsrcPtr, NewSRsrc;
8112 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
8113
8114 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
8115 const DebugLoc &DL = MI.getDebugLoc();
8116 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
8117 .addDef(CondReg0)
8118 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8119 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
8120 .addImm(0);
8121
8122 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
8123 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
8124 .addDef(CondReg1, RegState::Dead)
8125 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8126 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
8127 .addReg(CondReg0)
8128 .addImm(0);
8129
8130 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8131 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
8132 .addReg(NewVAddrLo)
8133 .addImm(AMDGPU::sub0)
8134 .addReg(NewVAddrHi)
8135 .addImm(AMDGPU::sub1);
8136
8137 VAddr->setReg(NewVAddr);
8138 Rsrc->setReg(NewSRsrc);
8139 } else if (!VAddr && ST.hasAddr64()) {
8140 // This instructions is the _OFFSET variant, so we need to convert it to
8141 // ADDR64.
8142 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
8143 "FIXME: Need to emit flat atomics here");
8144
8145 unsigned RsrcPtr, NewSRsrc;
8146 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
8147
8148 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8149 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
8150 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
8151 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8152 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
8153
8154 // Atomics with return have an additional tied operand and are
8155 // missing some of the special bits.
8156 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
8157 MachineInstr *Addr64;
8158
8159 if (!VDataIn) {
8160 // Regular buffer load / store.
8162 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
8163 .add(*VData)
8164 .addReg(NewVAddr)
8165 .addReg(NewSRsrc)
8166 .add(*SOffset)
8167 .add(*Offset);
8168
8169 if (const MachineOperand *CPol =
8170 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
8171 MIB.addImm(CPol->getImm());
8172 }
8173
8174 if (const MachineOperand *TFE =
8175 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
8176 MIB.addImm(TFE->getImm());
8177 }
8178
8179 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
8180
8181 MIB.cloneMemRefs(MI);
8182 Addr64 = MIB;
8183 } else {
8184 // Atomics with return.
8185 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
8186 .add(*VData)
8187 .add(*VDataIn)
8188 .addReg(NewVAddr)
8189 .addReg(NewSRsrc)
8190 .add(*SOffset)
8191 .add(*Offset)
8192 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
8193 .cloneMemRefs(MI);
8194 }
8195
8196 MI.removeFromParent();
8197
8198 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8199 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
8200 NewVAddr)
8201 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8202 .addImm(AMDGPU::sub0)
8203 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8204 .addImm(AMDGPU::sub1);
8205 } else {
8206 // Legalize a VGPR Rsrc and soffset together.
8207 if (!isSoffsetLegal) {
8208 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8209 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
8210 return CreatedBB;
8211 }
8212 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
8213 return CreatedBB;
8214 }
8215 }
8216
8217 // Legalize a VGPR soffset.
8218 if (!isSoffsetLegal) {
8219 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8220 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
8221 return CreatedBB;
8222 }
8223 return CreatedBB;
8224}
8225
8227 if (InSet.insert(MI).second)
8228 InstrList.push_back(MI);
8229 // Add MBUF instructiosn to deferred list.
8230 int RsrcIdx =
8231 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
8232 if (RsrcIdx != -1) {
8233 DeferredList.insert(MI);
8234 }
8235}
8236
8238 return DeferredList.contains(MI);
8239}
8240
8241// Legalize size mismatches between 16bit and 32bit registers in v2s copy
8242// lowering (change sgpr to vgpr).
8243// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
8244// size. Need to legalize the size of the operands during the vgpr lowering
8245// chain. This can be removed after we have sgpr16 in place
8247 MachineRegisterInfo &MRI) const {
8248 if (!ST.useRealTrue16Insts())
8249 return;
8250
8251 unsigned Opcode = MI.getOpcode();
8252 MachineBasicBlock *MBB = MI.getParent();
8253 // Legalize operands and check for size mismatch
8254 if (OpIdx >= MI.getNumExplicitOperands() ||
8255 OpIdx >= get(Opcode).getNumOperands() ||
8256 get(Opcode).operands()[OpIdx].RegClass == -1)
8257 return;
8258
8259 MachineOperand &Op = MI.getOperand(OpIdx);
8260 if (!Op.isReg() || !Op.getReg().isVirtual() || Op.isDef())
8261 return;
8262
8263 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
8264 if (!RI.isVGPRClass(CurrRC))
8265 return;
8266
8267 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
8268 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
8269 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8270 // Default to the lo16 only if the subregister is not specified.
8271 if (Op.getSubReg() == AMDGPU::NoSubRegister)
8272 Op.setSubReg(AMDGPU::lo16);
8273 return;
8274 }
8275
8276 const TargetRegisterClass *CurrSRC =
8277 RI.getSubRegisterClass(CurrRC, Op.getSubReg());
8278 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8279 const DebugLoc &DL = MI.getDebugLoc();
8280 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8281 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8282 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
8283 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
8284 .addReg(Op.getReg(), {}, Op.getSubReg())
8285 .addImm(AMDGPU::lo16)
8286 .addReg(Undef)
8287 .addImm(AMDGPU::hi16);
8288 Op.setReg(NewDstReg);
8289 Op.setSubReg(AMDGPU::NoSubRegister);
8290 }
8291}
8293 MachineRegisterInfo &MRI) const {
8294 for (unsigned OpIdx = 0; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
8296}
8297
8301 ArrayRef<Register> PhySGPRs) const {
8302 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8303 "This only handle waterfall for SI_CALL_ISEL");
8304 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
8305 // following copies, we also need to move copies from and to physical
8306 // registers into the loop block.
8307 // Also move the copies to physical registers into the loop block
8308 MachineBasicBlock &MBB = *MI->getParent();
8310 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8311 --Start;
8313 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8314 ++End;
8315
8316 // Also include following copies of the return value
8317 ++End;
8318 while (End != MBB.end() && End->isCopy() &&
8319 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8320 ++End;
8321
8322 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
8323}
8324
8326 MachineDominatorTree *MDT) const {
8328 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
8329 while (!Worklist.empty()) {
8330 MachineInstr &Inst = *Worklist.top();
8331 Worklist.erase_top();
8332 // Skip MachineInstr in the deferred list.
8333 if (Worklist.isDeferred(&Inst))
8334 continue;
8335 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8336 }
8337
8338 // Deferred list of instructions will be processed once
8339 // all the MachineInstr in the worklist are done.
8340 for (MachineInstr *Inst : Worklist.getDeferredList()) {
8341 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8342 assert(Worklist.empty() &&
8343 "Deferred MachineInstr are not supposed to re-populate worklist");
8344 }
8345
8346 for (auto &Entry : WaterFalls) {
8347 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8348 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
8349 Entry.second.SGPRs);
8350 }
8351
8352 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8353 if (Entry.second)
8354 Entry.first->eraseFromParent();
8355}
8357 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
8358 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
8359 // hope for the best.
8360 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
8361 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
8362 if (SubRegIndices.size() <= 1) {
8363 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8364 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8365 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8366 .add(Inst.getOperand(1));
8367 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
8368 DstReg)
8369 .addReg(NewDst);
8370 } else {
8372 for (int16_t Indice : SubRegIndices) {
8373 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8374 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8375 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8376 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
8377
8378 DstRegs.push_back(NewDst);
8379 }
8381 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8382 get(AMDGPU::REG_SEQUENCE), DstReg);
8383 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
8384 MIB.addReg(DstRegs[i]);
8385 MIB.addImm(RI.getSubRegFromChannel(i));
8386 }
8387 }
8388}
8389
8391 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
8394 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8395 if (DstReg == AMDGPU::M0) {
8397 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8398 return;
8399 }
8400 Register SrcReg = Inst.getOperand(1).getReg();
8403 // Only search current block since phyreg's def & use cannot cross
8404 // blocks when MF.NoPhi = false.
8405 while (++I != E) {
8406 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
8407 // and record the operand for later waterfall loop generation.
8408 if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8409 MachineInstr *UseMI = &*I;
8410 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
8411 if (UseMI->getOperand(i).isReg() &&
8412 UseMI->getOperand(i).getReg() == DstReg) {
8413 MachineOperand *MO = &UseMI->getOperand(i);
8414 MO->setReg(SrcReg);
8415 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
8416 V2SCopyInfo.MOs.push_back(MO);
8417 V2SCopyInfo.SGPRs.push_back(DstReg);
8418 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8419 }
8420 }
8421 } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8422 I->getOperand(0).isReg() &&
8423 I->getOperand(0).getReg() == DstReg) {
8425 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8426 } else if (I->readsRegister(DstReg, &RI)) {
8427 // COPY cannot be erased if other type of inst uses it.
8428 V2SPhyCopiesToErase[&Inst] = false;
8429 }
8430 if (I->findRegisterDefOperand(DstReg, &RI))
8431 break;
8432 }
8433}
8434
8436 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
8438 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8439
8441 if (!MBB)
8442 return;
8443 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
8444 unsigned Opcode = Inst.getOpcode();
8445 unsigned NewOpcode = getVALUOp(Inst);
8446 const DebugLoc &DL = Inst.getDebugLoc();
8447
8448 // Handle some special cases
8449 switch (Opcode) {
8450 default:
8451 break;
8452 case AMDGPU::S_ADD_I32:
8453 case AMDGPU::S_SUB_I32: {
8454 // FIXME: The u32 versions currently selected use the carry.
8455 bool Changed;
8456 MachineBasicBlock *CreatedBBTmp = nullptr;
8457 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8458 if (Changed)
8459 return;
8460
8461 // Default handling
8462 break;
8463 }
8464
8465 case AMDGPU::S_MUL_U64:
8466 if (ST.useVMulU64Inst()) {
8467 NewOpcode = AMDGPU::V_MUL_U64_e64;
8468 break;
8469 }
8470 // Split s_mul_u64 in 32-bit vector multiplications.
8471 splitScalarSMulU64(Worklist, Inst, MDT);
8472 Inst.eraseFromParent();
8473 return;
8474
8475 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8476 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8477 // This is a special case of s_mul_u64 where all the operands are either
8478 // zero extended or sign extended.
8479 splitScalarSMulPseudo(Worklist, Inst, MDT);
8480 Inst.eraseFromParent();
8481 return;
8482
8483 case AMDGPU::S_AND_B64:
8484 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8485 Inst.eraseFromParent();
8486 return;
8487
8488 case AMDGPU::S_OR_B64:
8489 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8490 Inst.eraseFromParent();
8491 return;
8492
8493 case AMDGPU::S_XOR_B64:
8494 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8495 Inst.eraseFromParent();
8496 return;
8497
8498 case AMDGPU::S_NAND_B64:
8499 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8500 Inst.eraseFromParent();
8501 return;
8502
8503 case AMDGPU::S_NOR_B64:
8504 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8505 Inst.eraseFromParent();
8506 return;
8507
8508 case AMDGPU::S_XNOR_B64:
8509 if (ST.hasDLInsts())
8510 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8511 else
8512 splitScalar64BitXnor(Worklist, Inst, MDT);
8513 Inst.eraseFromParent();
8514 return;
8515
8516 case AMDGPU::S_ANDN2_B64:
8517 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8518 Inst.eraseFromParent();
8519 return;
8520
8521 case AMDGPU::S_ORN2_B64:
8522 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8523 Inst.eraseFromParent();
8524 return;
8525
8526 case AMDGPU::S_BREV_B64:
8527 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8528 Inst.eraseFromParent();
8529 return;
8530
8531 case AMDGPU::S_NOT_B64:
8532 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8533 Inst.eraseFromParent();
8534 return;
8535
8536 case AMDGPU::S_BCNT1_I32_B64:
8537 splitScalar64BitBCNT(Worklist, Inst);
8538 Inst.eraseFromParent();
8539 return;
8540
8541 case AMDGPU::S_BFE_I64:
8542 splitScalar64BitBFE(Worklist, Inst);
8543 Inst.eraseFromParent();
8544 return;
8545
8546 case AMDGPU::S_FLBIT_I32_B64:
8547 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8548 Inst.eraseFromParent();
8549 return;
8550 case AMDGPU::S_FF1_I32_B64:
8551 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8552 Inst.eraseFromParent();
8553 return;
8554
8555 case AMDGPU::S_LSHL_B32:
8556 if (ST.hasOnlyRevVALUShifts()) {
8557 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8558 swapOperands(Inst);
8559 }
8560 break;
8561 case AMDGPU::S_ASHR_I32:
8562 if (ST.hasOnlyRevVALUShifts()) {
8563 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8564 swapOperands(Inst);
8565 }
8566 break;
8567 case AMDGPU::S_LSHR_B32:
8568 if (ST.hasOnlyRevVALUShifts()) {
8569 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8570 swapOperands(Inst);
8571 }
8572 break;
8573 case AMDGPU::S_LSHL_B64:
8574 if (ST.hasOnlyRevVALUShifts()) {
8575 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8576 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8577 : AMDGPU::V_LSHLREV_B64_e64;
8578 swapOperands(Inst);
8579 }
8580 break;
8581 case AMDGPU::S_ASHR_I64:
8582 if (ST.hasOnlyRevVALUShifts()) {
8583 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8584 swapOperands(Inst);
8585 }
8586 break;
8587 case AMDGPU::S_LSHR_B64:
8588 if (ST.hasOnlyRevVALUShifts()) {
8589 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8590 swapOperands(Inst);
8591 }
8592 break;
8593
8594 case AMDGPU::S_ABS_I32:
8595 lowerScalarAbs(Worklist, Inst);
8596 Inst.eraseFromParent();
8597 return;
8598
8599 case AMDGPU::S_ABSDIFF_I32:
8600 lowerScalarAbsDiff(Worklist, Inst);
8601 Inst.eraseFromParent();
8602 return;
8603
8604 case AMDGPU::S_CBRANCH_SCC0:
8605 case AMDGPU::S_CBRANCH_SCC1: {
8606 // Clear unused bits of vcc
8607 Register CondReg = Inst.getOperand(1).getReg();
8608 bool IsSCC = CondReg == AMDGPU::SCC;
8610 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8611 .addReg(LMC.ExecReg)
8612 .addReg(IsSCC ? LMC.VccReg : CondReg)
8613 .setOperandDead(3); // implicit-def $scc
8614 Inst.removeOperand(1);
8615 } break;
8616
8617 case AMDGPU::S_BFE_U64:
8618 case AMDGPU::S_BFM_B64:
8619 llvm_unreachable("Moving this op to VALU not implemented");
8620
8621 case AMDGPU::S_PACK_LL_B32_B16:
8622 case AMDGPU::S_PACK_LH_B32_B16:
8623 case AMDGPU::S_PACK_HL_B32_B16:
8624 case AMDGPU::S_PACK_HH_B32_B16:
8625 movePackToVALU(Worklist, MRI, Inst);
8626 Inst.eraseFromParent();
8627 return;
8628
8629 case AMDGPU::S_XNOR_B32:
8630 lowerScalarXnor(Worklist, Inst);
8631 Inst.eraseFromParent();
8632 return;
8633
8634 case AMDGPU::S_NAND_B32:
8635 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8636 Inst.eraseFromParent();
8637 return;
8638
8639 case AMDGPU::S_NOR_B32:
8640 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8641 Inst.eraseFromParent();
8642 return;
8643
8644 case AMDGPU::S_ANDN2_B32:
8645 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8646 Inst.eraseFromParent();
8647 return;
8648
8649 case AMDGPU::S_ORN2_B32:
8650 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8651 Inst.eraseFromParent();
8652 return;
8653
8654 // TODO: remove as soon as everything is ready
8655 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8656 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8657 // can only be selected from the uniform SDNode.
8658 case AMDGPU::S_ADD_CO_PSEUDO:
8659 case AMDGPU::S_SUB_CO_PSEUDO: {
8660 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8661 ? AMDGPU::V_ADDC_U32_e64
8662 : AMDGPU::V_SUBB_U32_e64;
8663 const auto *CarryRC = RI.getWaveMaskRegClass();
8664
8665 Register CarryInReg = Inst.getOperand(4).getReg();
8666 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8667 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8668 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8669 .addReg(CarryInReg);
8670 }
8671
8672 Register CarryOutReg = Inst.getOperand(1).getReg();
8673
8674 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8675 MRI.getRegClass(Inst.getOperand(0).getReg())));
8676 MachineInstr *CarryOp =
8677 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8678 .addReg(CarryOutReg, RegState::Define)
8679 .add(Inst.getOperand(2))
8680 .add(Inst.getOperand(3))
8681 .addReg(CarryInReg)
8682 .addImm(0);
8683 legalizeOperands(*CarryOp);
8684 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8685 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8686 Inst.eraseFromParent();
8687 }
8688 return;
8689 case AMDGPU::S_UADDO_PSEUDO:
8690 case AMDGPU::S_USUBO_PSEUDO: {
8691 MachineOperand &Dest0 = Inst.getOperand(0);
8692 MachineOperand &Dest1 = Inst.getOperand(1);
8693 MachineOperand &Src0 = Inst.getOperand(2);
8694 MachineOperand &Src1 = Inst.getOperand(3);
8695
8696 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8697 ? AMDGPU::V_ADD_CO_U32_e64
8698 : AMDGPU::V_SUB_CO_U32_e64;
8699 const TargetRegisterClass *NewRC =
8700 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8701 Register DestReg = MRI.createVirtualRegister(NewRC);
8702 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8703 .addReg(Dest1.getReg(), RegState::Define)
8704 .add(Src0)
8705 .add(Src1)
8706 .addImm(0); // clamp bit
8707
8708 legalizeOperands(*NewInstr, MDT);
8709 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8710 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8711 Inst.eraseFromParent();
8712 }
8713 return;
8714 case AMDGPU::S_LSHL1_ADD_U32:
8715 case AMDGPU::S_LSHL2_ADD_U32:
8716 case AMDGPU::S_LSHL3_ADD_U32:
8717 case AMDGPU::S_LSHL4_ADD_U32: {
8718 MachineOperand &Dest = Inst.getOperand(0);
8719 MachineOperand &Src0 = Inst.getOperand(1);
8720 MachineOperand &Src1 = Inst.getOperand(2);
8721 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8722 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8723 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8724 : 4);
8725
8726 const TargetRegisterClass *NewRC =
8727 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8728 Register DestReg = MRI.createVirtualRegister(NewRC);
8729 MachineInstr *NewInstr =
8730 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8731 .add(Src0)
8732 .addImm(ShiftAmt)
8733 .add(Src1);
8734
8735 legalizeOperands(*NewInstr, MDT);
8736 MRI.replaceRegWith(Dest.getReg(), DestReg);
8737 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8738 Inst.eraseFromParent();
8739 }
8740 return;
8741 case AMDGPU::S_CSELECT_B32:
8742 case AMDGPU::S_CSELECT_B64:
8743 lowerSelect(Worklist, Inst, MDT);
8744 Inst.eraseFromParent();
8745 return;
8746 case AMDGPU::S_CMP_EQ_I32:
8747 case AMDGPU::S_CMP_LG_I32:
8748 case AMDGPU::S_CMP_GT_I32:
8749 case AMDGPU::S_CMP_GE_I32:
8750 case AMDGPU::S_CMP_LT_I32:
8751 case AMDGPU::S_CMP_LE_I32:
8752 case AMDGPU::S_CMP_EQ_U32:
8753 case AMDGPU::S_CMP_LG_U32:
8754 case AMDGPU::S_CMP_GT_U32:
8755 case AMDGPU::S_CMP_GE_U32:
8756 case AMDGPU::S_CMP_LT_U32:
8757 case AMDGPU::S_CMP_LE_U32:
8758 case AMDGPU::S_CMP_EQ_U64:
8759 case AMDGPU::S_CMP_LG_U64:
8760 case AMDGPU::S_CMP_LT_F32:
8761 case AMDGPU::S_CMP_EQ_F32:
8762 case AMDGPU::S_CMP_LE_F32:
8763 case AMDGPU::S_CMP_GT_F32:
8764 case AMDGPU::S_CMP_LG_F32:
8765 case AMDGPU::S_CMP_GE_F32:
8766 case AMDGPU::S_CMP_O_F32:
8767 case AMDGPU::S_CMP_U_F32:
8768 case AMDGPU::S_CMP_NGE_F32:
8769 case AMDGPU::S_CMP_NLG_F32:
8770 case AMDGPU::S_CMP_NGT_F32:
8771 case AMDGPU::S_CMP_NLE_F32:
8772 case AMDGPU::S_CMP_NEQ_F32:
8773 case AMDGPU::S_CMP_NLT_F32: {
8774 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8775 auto NewInstr =
8776 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8777 .setMIFlags(Inst.getFlags());
8778 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8779 0) {
8780 NewInstr
8781 .addImm(0) // src0_modifiers
8782 .add(Inst.getOperand(0)) // src0
8783 .addImm(0) // src1_modifiers
8784 .add(Inst.getOperand(1)) // src1
8785 .addImm(0); // clamp
8786 } else {
8787 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8788 }
8789 legalizeOperands(*NewInstr, MDT);
8790 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8791 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8792 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8793 Inst.eraseFromParent();
8794 return;
8795 }
8796 case AMDGPU::S_CMP_LT_F16:
8797 case AMDGPU::S_CMP_EQ_F16:
8798 case AMDGPU::S_CMP_LE_F16:
8799 case AMDGPU::S_CMP_GT_F16:
8800 case AMDGPU::S_CMP_LG_F16:
8801 case AMDGPU::S_CMP_GE_F16:
8802 case AMDGPU::S_CMP_O_F16:
8803 case AMDGPU::S_CMP_U_F16:
8804 case AMDGPU::S_CMP_NGE_F16:
8805 case AMDGPU::S_CMP_NLG_F16:
8806 case AMDGPU::S_CMP_NGT_F16:
8807 case AMDGPU::S_CMP_NLE_F16:
8808 case AMDGPU::S_CMP_NEQ_F16:
8809 case AMDGPU::S_CMP_NLT_F16: {
8810 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8811 auto NewInstr =
8812 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8813 .setMIFlags(Inst.getFlags());
8814 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8815 NewInstr
8816 .addImm(0) // src0_modifiers
8817 .add(Inst.getOperand(0)) // src0
8818 .addImm(0) // src1_modifiers
8819 .add(Inst.getOperand(1)) // src1
8820 .addImm(0); // clamp
8821 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8822 NewInstr.addImm(0); // op_sel0
8823 } else {
8824 NewInstr
8825 .add(Inst.getOperand(0))
8826 .add(Inst.getOperand(1));
8827 }
8828 legalizeOperands(*NewInstr, MDT);
8829 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8830 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8831 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8832 Inst.eraseFromParent();
8833 return;
8834 }
8835 case AMDGPU::S_CVT_HI_F32_F16: {
8836 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8837 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8838 if (ST.useRealTrue16Insts()) {
8839 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8840 .add(Inst.getOperand(1));
8841 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8842 .addImm(0) // src0_modifiers
8843 .addReg(TmpReg, {}, AMDGPU::hi16)
8844 .addImm(0) // clamp
8845 .addImm(0) // omod
8846 .addImm(0); // op_sel0
8847 } else {
8848 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8849 .addImm(16)
8850 .add(Inst.getOperand(1));
8851 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8852 .addImm(0) // src0_modifiers
8853 .addReg(TmpReg)
8854 .addImm(0) // clamp
8855 .addImm(0); // omod
8856 }
8857
8858 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8859 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8860 Inst.eraseFromParent();
8861 return;
8862 }
8863 case AMDGPU::S_MINIMUM_F32:
8864 case AMDGPU::S_MAXIMUM_F32: {
8865 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8866 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8867 .addImm(0) // src0_modifiers
8868 .add(Inst.getOperand(1))
8869 .addImm(0) // src1_modifiers
8870 .add(Inst.getOperand(2))
8871 .addImm(0) // clamp
8872 .addImm(0); // omod
8873 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8874
8875 legalizeOperands(*NewInstr, MDT);
8876 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8877 Inst.eraseFromParent();
8878 return;
8879 }
8880 case AMDGPU::S_MINIMUM_F16:
8881 case AMDGPU::S_MAXIMUM_F16: {
8882 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8883 ? &AMDGPU::VGPR_16RegClass
8884 : &AMDGPU::VGPR_32RegClass);
8885 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8886 .addImm(0) // src0_modifiers
8887 .add(Inst.getOperand(1))
8888 .addImm(0) // src1_modifiers
8889 .add(Inst.getOperand(2))
8890 .addImm(0) // clamp
8891 .addImm(0) // omod
8892 .addImm(0); // opsel0
8893 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8894 legalizeOperands(*NewInstr, MDT);
8895 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8896 Inst.eraseFromParent();
8897 return;
8898 }
8899 case AMDGPU::V_S_EXP_F16_e64:
8900 case AMDGPU::V_S_LOG_F16_e64:
8901 case AMDGPU::V_S_RCP_F16_e64:
8902 case AMDGPU::V_S_RSQ_F16_e64:
8903 case AMDGPU::V_S_SQRT_F16_e64: {
8904 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8905 ? &AMDGPU::VGPR_16RegClass
8906 : &AMDGPU::VGPR_32RegClass);
8907 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8908 .add(Inst.getOperand(1)) // src0_modifiers
8909 .add(Inst.getOperand(2))
8910 .add(Inst.getOperand(3)) // clamp
8911 .add(Inst.getOperand(4)) // omod
8912 .setMIFlags(Inst.getFlags());
8913 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8914 NewInstr.addImm(0); // opsel0
8915 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8916 legalizeOperands(*NewInstr, MDT);
8917 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8918 Inst.eraseFromParent();
8919 return;
8920 }
8921 }
8922
8923 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8924 // We cannot move this instruction to the VALU, so we should try to
8925 // legalize its operands instead.
8926 legalizeOperands(Inst, MDT);
8927 return;
8928 }
8929 // Handle converting generic instructions like COPY-to-SGPR into
8930 // COPY-to-VGPR.
8931 if (NewOpcode == Opcode) {
8932 Register DstReg = Inst.getOperand(0).getReg();
8933 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8934
8935 if (Inst.isCopy() && DstReg.isPhysical() &&
8936 Inst.getOperand(1).getReg().isVirtual()) {
8937 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8938 V2SPhyCopiesToErase);
8939 return;
8940 }
8941
8942 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8943 Register NewDstReg = Inst.getOperand(1).getReg();
8944 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8945 if (const TargetRegisterClass *CommonRC =
8946 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8947 // Instead of creating a copy where src and dst are the same register
8948 // class, we just replace all uses of dst with src. These kinds of
8949 // copies interfere with the heuristics MachineSink uses to decide
8950 // whether or not to split a critical edge. Since the pass assumes
8951 // that copies will end up as machine instructions and not be
8952 // eliminated.
8953 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8954 unsigned SrcSubReg = Inst.getOperand(1).getSubReg();
8955 bool IsUndef = Inst.getOperand(1).isUndef();
8956 for (MachineOperand &UseMO :
8957 make_early_inc_range(MRI.use_operands(DstReg))) {
8958 UseMO.setSubReg(
8959 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8960 UseMO.setReg(NewDstReg);
8961 if (IsUndef)
8962 UseMO.setIsUndef();
8963 }
8964
8965 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8966 llvm_unreachable("failed to constrain register");
8967
8968 Inst.eraseFromParent();
8969
8970 for (MachineOperand &UseMO :
8971 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8972 MachineInstr &UseMI = *UseMO.getParent();
8973
8974 // Legalize t16 operands since replaceReg is called after
8975 // addUsersToVALU.
8977
8978 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
8979 if (const TargetRegisterClass *OpRC =
8980 getRegClass(UseMI.getDesc(), OpIdx))
8981 MRI.constrainRegClass(NewDstReg, OpRC);
8982 }
8983
8984 return;
8985 }
8986 }
8987
8988 // If this is a v2s copy between 16bit and 32bit reg,
8989 // replace vgpr copy to reg_sequence/extract_subreg
8990 // This can be remove after we have sgpr16 in place
8991 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
8992 Inst.getOperand(1).getReg().isVirtual() &&
8993 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
8994 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
8995 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8996 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8997 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8998 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8999 get(AMDGPU::IMPLICIT_DEF), Undef);
9000 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
9001 get(AMDGPU::REG_SEQUENCE), NewDstReg)
9002 .addReg(Inst.getOperand(1).getReg())
9003 .addImm(AMDGPU::lo16)
9004 .addReg(Undef)
9005 .addImm(AMDGPU::hi16);
9006 Inst.eraseFromParent();
9007 MRI.replaceRegWith(DstReg, NewDstReg);
9008 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9009 return;
9010 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
9011 AMDGPU::lo16)) {
9012 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
9013 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9014 MRI.replaceRegWith(DstReg, NewDstReg);
9015 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9016 return;
9017 }
9018 }
9019
9020 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9021 MRI.replaceRegWith(DstReg, NewDstReg);
9022 legalizeOperands(Inst, MDT);
9023 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9024 return;
9025 }
9026
9027 // Use the new VALU Opcode.
9028 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
9029 .setMIFlags(Inst.getFlags());
9030 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
9031 // Intersperse VOP3 modifiers among the SALU operands.
9032 NewInstr->addOperand(Inst.getOperand(0));
9033 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9034 AMDGPU::OpName::src0_modifiers) >= 0)
9035 NewInstr.addImm(0);
9036 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
9037 const MachineOperand &Src = Inst.getOperand(1);
9038 NewInstr->addOperand(Src);
9039 }
9040
9041 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
9042 // We are converting these to a BFE, so we need to add the missing
9043 // operands for the size and offset.
9044 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
9045 NewInstr.addImm(0);
9046 NewInstr.addImm(Size);
9047 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
9048 // The VALU version adds the second operand to the result, so insert an
9049 // extra 0 operand.
9050 NewInstr.addImm(0);
9051 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
9052 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
9053 // If we need to move this to VGPRs, we need to unpack the second
9054 // operand back into the 2 separate ones for bit offset and width.
9055 assert(OffsetWidthOp.isImm() &&
9056 "Scalar BFE is only implemented for constant width and offset");
9057 uint32_t Imm = OffsetWidthOp.getImm();
9058
9059 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9060 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9061 NewInstr.addImm(Offset);
9062 NewInstr.addImm(BitWidth);
9063 } else {
9064 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9065 AMDGPU::OpName::src1_modifiers) >= 0)
9066 NewInstr.addImm(0);
9067 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
9068 NewInstr->addOperand(Inst.getOperand(2));
9069 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9070 AMDGPU::OpName::src2_modifiers) >= 0)
9071 NewInstr.addImm(0);
9072 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
9073 NewInstr->addOperand(Inst.getOperand(3));
9074 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
9075 NewInstr.addImm(0);
9076 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
9077 NewInstr.addImm(0);
9078 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
9079 NewInstr.addImm(0);
9080 }
9081 } else {
9082 // Just copy the SALU operands.
9083 for (const MachineOperand &Op : Inst.explicit_operands())
9084 NewInstr->addOperand(Op);
9085 }
9086
9087 // Remove any references to SCC. Vector instructions can't read from it, and
9088 // We're just about to add the implicit use / defs of VCC, and we don't want
9089 // both.
9090 bool DeadSCCDef = false;
9091 for (MachineOperand &Op : Inst.implicit_operands()) {
9092 if (Op.getReg() == AMDGPU::SCC) {
9093 // Only propagate through live-def of SCC.
9094 if (Op.isDef()) {
9095 if (Op.isDead())
9096 DeadSCCDef = true;
9097 else
9098 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
9099 continue;
9100 }
9101
9102 addSCCDefsToVALUWorklist(NewInstr, Worklist);
9103 }
9104 }
9105 Inst.eraseFromParent();
9106 Register NewDstReg;
9107 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
9108 Register DstReg = NewInstr->getOperand(0).getReg();
9109 assert(DstReg.isVirtual());
9110 // Update the destination register class.
9111 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
9112 assert(NewDstRC);
9113 NewDstReg = MRI.createVirtualRegister(NewDstRC);
9114 MRI.replaceRegWith(DstReg, NewDstReg);
9115 }
9116 fixImplicitOperands(*NewInstr);
9117
9118 if (DeadSCCDef) {
9119 // A scalar op with a dead SCC def lowers to a VALU op whose VCC def will
9120 // also be dead.
9121 if (MachineOperand *VCCDef =
9122 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
9123 VCCDef->setIsDead();
9124 }
9125
9126 // Legalize the operands
9127 legalizeOperands(*NewInstr, MDT);
9128 if (NewDstReg)
9129 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9130}
9131
9132// Add/sub require special handling to deal with carry outs.
9133std::pair<bool, MachineBasicBlock *>
9134SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
9135 MachineDominatorTree *MDT) const {
9136 if (ST.hasAddNoCarryInsts()) {
9137 // Assume there is no user of scc since we don't select this in that case.
9138 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
9139 // is used.
9140
9141 MachineBasicBlock &MBB = *Inst.getParent();
9142 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9143
9144 Register OldDstReg = Inst.getOperand(0).getReg();
9145 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9146
9147 unsigned Opc = Inst.getOpcode();
9148 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
9149
9150 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
9151 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9152
9153 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
9154 Inst.removeOperand(3);
9155
9156 Inst.setDesc(get(NewOpc));
9157 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
9158 Inst.addImplicitDefUseOperands(*MBB.getParent());
9159 MRI.replaceRegWith(OldDstReg, ResultReg);
9160 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
9161
9162 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9163 return std::pair(true, NewBB);
9164 }
9165
9166 return std::pair(false, nullptr);
9167}
9168
9169void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
9170 MachineDominatorTree *MDT) const {
9171
9172 MachineBasicBlock &MBB = *Inst.getParent();
9173 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9174 MachineBasicBlock::iterator MII = Inst;
9175 const DebugLoc &DL = Inst.getDebugLoc();
9176
9177 MachineOperand &Dest = Inst.getOperand(0);
9178 MachineOperand &Src0 = Inst.getOperand(1);
9179 MachineOperand &Src1 = Inst.getOperand(2);
9180 MachineOperand &Cond = Inst.getOperand(3);
9181
9182 Register CondReg = Cond.getReg();
9183 bool IsSCC = (CondReg == AMDGPU::SCC);
9184
9185 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
9186 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
9187 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
9188 // output directly into the V_CNDMASK.
9189 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
9190 (Src1.getImm() == 0)) {
9191 for (MachineOperand &UseMO :
9193 MachineInstr &UseMI = *UseMO.getParent();
9194 switch (UseMI.getOpcode()) {
9195 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9196 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9197 case AMDGPU::V_CNDMASK_B16_t16_e32:
9198 case AMDGPU::V_CNDMASK_B16_t16_e64:
9199 case AMDGPU::V_CNDMASK_B32_e32:
9200 case AMDGPU::V_CNDMASK_B32_e64:
9201 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9202 if (UseMO.isImplicit() ||
9203 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
9204 UseMO.setReg(CondReg);
9205 }
9206 }
9207 if (MRI.use_nodbg_empty(Dest.getReg()))
9208 return;
9209 }
9210
9211 Register NewCondReg = CondReg;
9212 if (IsSCC) {
9213 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
9214 NewCondReg = MRI.createVirtualRegister(TC);
9215
9216 // Now look for the closest SCC def if it is a copy
9217 // replacing the CondReg with the COPY source register
9218 bool CopyFound = false;
9219 for (MachineInstr &CandI :
9221 Inst.getParent()->rend())) {
9222 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
9223 -1) {
9224 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9225 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
9226 .addReg(CandI.getOperand(1).getReg());
9227 CopyFound = true;
9228 }
9229 break;
9230 }
9231 }
9232 if (!CopyFound) {
9233 // SCC def is not a copy
9234 // Insert a trivial select instead of creating a copy, because a copy from
9235 // SCC would semantically mean just copying a single bit, but we may need
9236 // the result to be a vector condition mask that needs preserving.
9237 unsigned Opcode =
9238 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9239 auto NewSelect =
9240 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
9241 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
9242 }
9243 }
9244
9245 Register NewDestReg = MRI.createVirtualRegister(
9246 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
9247 MachineInstr *NewInst;
9248 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
9249 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9250 .addImm(0)
9251 .add(Src1) // False
9252 .addImm(0)
9253 .add(Src0) // True
9254 .addReg(NewCondReg);
9255 } else {
9256 NewInst =
9257 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
9258 .add(Src1) // False
9259 .add(Src0) // True
9260 .addReg(NewCondReg);
9261 }
9262 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
9263 legalizeOperands(*NewInst, MDT);
9264 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9265}
9266
9267void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
9268 MachineInstr &Inst) const {
9269 MachineBasicBlock &MBB = *Inst.getParent();
9270 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9271 MachineBasicBlock::iterator MII = Inst;
9272 const DebugLoc &DL = Inst.getDebugLoc();
9273
9274 MachineOperand &Dest = Inst.getOperand(0);
9275 MachineOperand &Src = Inst.getOperand(1);
9276 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9277 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9278
9279 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9280 unsigned SubOp =
9281 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9282
9283 MachineInstrBuilder Sub =
9284 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(Src.getReg());
9285 if (HasCarryOut)
9286 Sub.setOperandDead(3); // Dead vcc
9287
9288 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9289 .addReg(Src.getReg())
9290 .addReg(TmpReg);
9291
9292 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9293 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9294}
9295
9296void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
9297 MachineInstr &Inst) const {
9298 MachineBasicBlock &MBB = *Inst.getParent();
9299 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9300 MachineBasicBlock::iterator MII = Inst;
9301 const DebugLoc &DL = Inst.getDebugLoc();
9302
9303 MachineOperand &Dest = Inst.getOperand(0);
9304 MachineOperand &Src1 = Inst.getOperand(1);
9305 MachineOperand &Src2 = Inst.getOperand(2);
9306 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9307 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9308 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9309
9310 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9311 unsigned SubOp =
9312 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9313
9314 MachineInstrBuilder Sub1 = BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
9315 .addReg(Src1.getReg())
9316 .addReg(Src2.getReg());
9317
9318 MachineInstrBuilder Sub2 =
9319 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
9320
9321 if (HasCarryOut) {
9322 Sub1.setOperandDead(3); // Dead vcc
9323 Sub2.setOperandDead(3); // Dead vcc
9324 }
9325
9326 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9327 .addReg(SubResultReg)
9328 .addReg(TmpReg);
9329
9330 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9331 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9332}
9333
9334void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
9335 MachineInstr &Inst) const {
9336 MachineBasicBlock &MBB = *Inst.getParent();
9337 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9338 MachineBasicBlock::iterator MII = Inst;
9339 const DebugLoc &DL = Inst.getDebugLoc();
9340
9341 MachineOperand &Dest = Inst.getOperand(0);
9342 MachineOperand &Src0 = Inst.getOperand(1);
9343 MachineOperand &Src1 = Inst.getOperand(2);
9344
9345 if (ST.hasDLInsts()) {
9346 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9347 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
9348 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
9349
9350 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
9351 .add(Src0)
9352 .add(Src1);
9353
9354 MRI.replaceRegWith(Dest.getReg(), NewDest);
9355 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9356 } else {
9357 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
9358 // invert either source and then perform the XOR. If either source is a
9359 // scalar register, then we can leave the inversion on the scalar unit to
9360 // achieve a better distribution of scalar and vector instructions.
9361 bool Src0IsSGPR = Src0.isReg() &&
9362 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
9363 bool Src1IsSGPR = Src1.isReg() &&
9364 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
9365 MachineInstr *Xor;
9366 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9367 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9368
9369 // Build a pair of scalar instructions and add them to the work list.
9370 // The next iteration over the work list will lower these to the vector
9371 // unit as necessary.
9372 if (Src0IsSGPR) {
9373 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
9374 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9375 .addReg(Temp)
9376 .add(Src1);
9377 } else if (Src1IsSGPR) {
9378 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
9379 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9380 .add(Src0)
9381 .addReg(Temp);
9382 } else {
9383 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
9384 .add(Src0)
9385 .add(Src1);
9386 MachineInstr *Not =
9387 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
9388 Worklist.insert(Not);
9389 }
9390
9391 MRI.replaceRegWith(Dest.getReg(), NewDest);
9392
9393 Worklist.insert(Xor);
9394
9395 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9396 }
9397}
9398
9399void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
9400 MachineInstr &Inst,
9401 unsigned Opcode) const {
9402 MachineBasicBlock &MBB = *Inst.getParent();
9403 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9404 MachineBasicBlock::iterator MII = Inst;
9405 const DebugLoc &DL = Inst.getDebugLoc();
9406
9407 MachineOperand &Dest = Inst.getOperand(0);
9408 MachineOperand &Src0 = Inst.getOperand(1);
9409 MachineOperand &Src1 = Inst.getOperand(2);
9410
9411 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9412 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9413
9414 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
9415 .add(Src0)
9416 .add(Src1);
9417
9418 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
9419 .addReg(Interm);
9420
9421 Worklist.insert(&Op);
9422 Worklist.insert(&Not);
9423
9424 MRI.replaceRegWith(Dest.getReg(), NewDest);
9425 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9426}
9427
9428void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
9429 MachineInstr &Inst,
9430 unsigned Opcode) const {
9431 MachineBasicBlock &MBB = *Inst.getParent();
9432 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9433 MachineBasicBlock::iterator MII = Inst;
9434 const DebugLoc &DL = Inst.getDebugLoc();
9435
9436 MachineOperand &Dest = Inst.getOperand(0);
9437 MachineOperand &Src0 = Inst.getOperand(1);
9438 MachineOperand &Src1 = Inst.getOperand(2);
9439
9440 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9441 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9442
9443 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
9444 .add(Src1);
9445
9446 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
9447 .add(Src0)
9448 .addReg(Interm);
9449
9450 Worklist.insert(&Not);
9451 Worklist.insert(&Op);
9452
9453 MRI.replaceRegWith(Dest.getReg(), NewDest);
9454 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9455}
9456
9457void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
9458 MachineInstr &Inst, unsigned Opcode,
9459 bool Swap) const {
9460 MachineBasicBlock &MBB = *Inst.getParent();
9461 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9462
9463 MachineOperand &Dest = Inst.getOperand(0);
9464 MachineOperand &Src0 = Inst.getOperand(1);
9465 const DebugLoc &DL = Inst.getDebugLoc();
9466
9467 MachineBasicBlock::iterator MII = Inst;
9468
9469 const MCInstrDesc &InstDesc = get(Opcode);
9470 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9471 MRI.getRegClass(Src0.getReg()) :
9472 &AMDGPU::SGPR_32RegClass;
9473
9474 const TargetRegisterClass *Src0SubRC =
9475 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9476
9477 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9478 AMDGPU::sub0, Src0SubRC);
9479
9480 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9481 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9482 const TargetRegisterClass *NewDestSubRC =
9483 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9484
9485 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9486 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
9487
9488 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9489 AMDGPU::sub1, Src0SubRC);
9490
9491 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9492 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
9493
9494 if (Swap)
9495 std::swap(DestSub0, DestSub1);
9496
9497 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9498 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9499 .addReg(DestSub0)
9500 .addImm(AMDGPU::sub0)
9501 .addReg(DestSub1)
9502 .addImm(AMDGPU::sub1);
9503
9504 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9505
9506 Worklist.insert(&LoHalf);
9507 Worklist.insert(&HiHalf);
9508
9509 // We don't need to legalizeOperands here because for a single operand, src0
9510 // will support any kind of input.
9511
9512 // Move all users of this moved value.
9513 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9514}
9515
9516// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9517// split the s_mul_u64 in 32-bit vector multiplications.
9518void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9519 MachineInstr &Inst,
9520 MachineDominatorTree *MDT) const {
9521 MachineBasicBlock &MBB = *Inst.getParent();
9522 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9523
9524 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9525 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9526 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9527
9528 MachineOperand &Dest = Inst.getOperand(0);
9529 MachineOperand &Src0 = Inst.getOperand(1);
9530 MachineOperand &Src1 = Inst.getOperand(2);
9531 const DebugLoc &DL = Inst.getDebugLoc();
9532 MachineBasicBlock::iterator MII = Inst;
9533
9534 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9535 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9536 const TargetRegisterClass *Src0SubRC =
9537 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9538 if (RI.isSGPRClass(Src0SubRC))
9539 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9540 const TargetRegisterClass *Src1SubRC =
9541 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9542 if (RI.isSGPRClass(Src1SubRC))
9543 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9544
9545 // First, we extract the low 32-bit and high 32-bit values from each of the
9546 // operands.
9547 MachineOperand Op0L =
9548 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9549 MachineOperand Op1L =
9550 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9551 MachineOperand Op0H =
9552 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9553 MachineOperand Op1H =
9554 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9555
9556 // The multilication is done as follows:
9557 //
9558 // Op1H Op1L
9559 // * Op0H Op0L
9560 // --------------------
9561 // Op1H*Op0L Op1L*Op0L
9562 // + Op1H*Op0H Op1L*Op0H
9563 // -----------------------------------------
9564 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9565 //
9566 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9567 // value and that would overflow.
9568 // The low 32-bit value is Op1L*Op0L.
9569 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9570
9571 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9572 MachineInstr *Op1L_Op0H =
9573 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9574 .add(Op1L)
9575 .add(Op0H);
9576
9577 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9578 MachineInstr *Op1H_Op0L =
9579 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9580 .add(Op1H)
9581 .add(Op0L);
9582
9583 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9584 MachineInstr *Carry =
9585 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9586 .add(Op1L)
9587 .add(Op0L);
9588
9589 MachineInstr *LoHalf =
9590 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9591 .add(Op1L)
9592 .add(Op0L);
9593
9594 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9595 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9596 .addReg(Op1L_Op0H_Reg)
9597 .addReg(Op1H_Op0L_Reg);
9598
9599 MachineInstr *HiHalf =
9600 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9601 .addReg(AddReg)
9602 .addReg(CarryReg);
9603
9604 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9605 .addReg(DestSub0)
9606 .addImm(AMDGPU::sub0)
9607 .addReg(DestSub1)
9608 .addImm(AMDGPU::sub1);
9609
9610 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9611
9612 // Try to legalize the operands in case we need to swap the order to keep it
9613 // valid.
9614 legalizeOperands(*Op1L_Op0H, MDT);
9615 legalizeOperands(*Op1H_Op0L, MDT);
9616 legalizeOperands(*Carry, MDT);
9617 legalizeOperands(*LoHalf, MDT);
9618 legalizeOperands(*Add, MDT);
9619 legalizeOperands(*HiHalf, MDT);
9620
9621 // Move all users of this moved value.
9622 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9623}
9624
9625// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9626// multiplications.
9627void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9628 MachineInstr &Inst,
9629 MachineDominatorTree *MDT) const {
9630 MachineBasicBlock &MBB = *Inst.getParent();
9631 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9632
9633 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9634 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9635 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9636
9637 MachineOperand &Dest = Inst.getOperand(0);
9638 MachineOperand &Src0 = Inst.getOperand(1);
9639 MachineOperand &Src1 = Inst.getOperand(2);
9640 const DebugLoc &DL = Inst.getDebugLoc();
9641 MachineBasicBlock::iterator MII = Inst;
9642
9643 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9644 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9645 const TargetRegisterClass *Src0SubRC =
9646 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9647 if (RI.isSGPRClass(Src0SubRC))
9648 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9649 const TargetRegisterClass *Src1SubRC =
9650 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9651 if (RI.isSGPRClass(Src1SubRC))
9652 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9653
9654 // First, we extract the low 32-bit and high 32-bit values from each of the
9655 // operands.
9656 MachineOperand Op0L =
9657 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9658 MachineOperand Op1L =
9659 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9660
9661 unsigned Opc = Inst.getOpcode();
9662 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9663 ? AMDGPU::V_MUL_HI_U32_e64
9664 : AMDGPU::V_MUL_HI_I32_e64;
9665 MachineInstr *HiHalf =
9666 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9667
9668 MachineInstr *LoHalf =
9669 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9670 .add(Op1L)
9671 .add(Op0L);
9672
9673 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9674 .addReg(DestSub0)
9675 .addImm(AMDGPU::sub0)
9676 .addReg(DestSub1)
9677 .addImm(AMDGPU::sub1);
9678
9679 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9680
9681 // Try to legalize the operands in case we need to swap the order to keep it
9682 // valid.
9683 legalizeOperands(*HiHalf, MDT);
9684 legalizeOperands(*LoHalf, MDT);
9685
9686 // Move all users of this moved value.
9687 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9688}
9689
9690void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9691 MachineInstr &Inst, unsigned Opcode,
9692 MachineDominatorTree *MDT) const {
9693 MachineBasicBlock &MBB = *Inst.getParent();
9694 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9695
9696 MachineOperand &Dest = Inst.getOperand(0);
9697 MachineOperand &Src0 = Inst.getOperand(1);
9698 MachineOperand &Src1 = Inst.getOperand(2);
9699 const DebugLoc &DL = Inst.getDebugLoc();
9700
9701 MachineBasicBlock::iterator MII = Inst;
9702
9703 const MCInstrDesc &InstDesc = get(Opcode);
9704 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9705 MRI.getRegClass(Src0.getReg()) :
9706 &AMDGPU::SGPR_32RegClass;
9707
9708 const TargetRegisterClass *Src0SubRC =
9709 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9710 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9711 MRI.getRegClass(Src1.getReg()) :
9712 &AMDGPU::SGPR_32RegClass;
9713
9714 const TargetRegisterClass *Src1SubRC =
9715 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9716
9717 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9718 AMDGPU::sub0, Src0SubRC);
9719 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9720 AMDGPU::sub0, Src1SubRC);
9721 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9722 AMDGPU::sub1, Src0SubRC);
9723 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9724 AMDGPU::sub1, Src1SubRC);
9725
9726 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9727 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9728 const TargetRegisterClass *NewDestSubRC =
9729 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9730
9731 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9732 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9733 .add(SrcReg0Sub0)
9734 .add(SrcReg1Sub0);
9735
9736 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9737 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9738 .add(SrcReg0Sub1)
9739 .add(SrcReg1Sub1);
9740
9741 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9742 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9743 .addReg(DestSub0)
9744 .addImm(AMDGPU::sub0)
9745 .addReg(DestSub1)
9746 .addImm(AMDGPU::sub1);
9747
9748 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9749
9750 Worklist.insert(&LoHalf);
9751 Worklist.insert(&HiHalf);
9752
9753 // Move all users of this moved value.
9754 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9755}
9756
9757void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9758 MachineInstr &Inst,
9759 MachineDominatorTree *MDT) const {
9760 MachineBasicBlock &MBB = *Inst.getParent();
9761 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9762
9763 MachineOperand &Dest = Inst.getOperand(0);
9764 MachineOperand &Src0 = Inst.getOperand(1);
9765 MachineOperand &Src1 = Inst.getOperand(2);
9766 const DebugLoc &DL = Inst.getDebugLoc();
9767
9768 MachineBasicBlock::iterator MII = Inst;
9769
9770 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9771
9772 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9773
9774 MachineOperand* Op0;
9775 MachineOperand* Op1;
9776
9777 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9778 Op0 = &Src0;
9779 Op1 = &Src1;
9780 } else {
9781 Op0 = &Src1;
9782 Op1 = &Src0;
9783 }
9784
9785 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9786 .add(*Op0);
9787
9788 Register NewDest = MRI.createVirtualRegister(DestRC);
9789
9790 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9791 .addReg(Interm)
9792 .add(*Op1);
9793
9794 MRI.replaceRegWith(Dest.getReg(), NewDest);
9795
9796 Worklist.insert(&Xor);
9797}
9798
9799void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9800 MachineInstr &Inst) const {
9801 MachineBasicBlock &MBB = *Inst.getParent();
9802 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9803
9804 MachineBasicBlock::iterator MII = Inst;
9805 const DebugLoc &DL = Inst.getDebugLoc();
9806
9807 MachineOperand &Dest = Inst.getOperand(0);
9808 MachineOperand &Src = Inst.getOperand(1);
9809
9810 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9811 const TargetRegisterClass *SrcRC = Src.isReg() ?
9812 MRI.getRegClass(Src.getReg()) :
9813 &AMDGPU::SGPR_32RegClass;
9814
9815 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9816 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9817
9818 const TargetRegisterClass *SrcSubRC =
9819 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9820
9821 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9822 AMDGPU::sub0, SrcSubRC);
9823 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9824 AMDGPU::sub1, SrcSubRC);
9825
9826 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9827
9828 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9829
9830 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9831
9832 // We don't need to legalize operands here. src0 for either instruction can be
9833 // an SGPR, and the second input is unused or determined here.
9834 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9835}
9836
9837void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9838 MachineInstr &Inst) const {
9839 MachineBasicBlock &MBB = *Inst.getParent();
9840 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9841 MachineBasicBlock::iterator MII = Inst;
9842 const DebugLoc &DL = Inst.getDebugLoc();
9843
9844 MachineOperand &Dest = Inst.getOperand(0);
9845 uint32_t Imm = Inst.getOperand(2).getImm();
9846 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9847 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9848
9849 (void) Offset;
9850
9851 // Only sext_inreg cases handled.
9852 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9853 Offset == 0 && "Not implemented");
9854
9855 if (BitWidth < 32) {
9856 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9857 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9858 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9859
9860 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9861 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9862 .addImm(0)
9863 .addImm(BitWidth);
9864
9865 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9866 .addImm(31)
9867 .addReg(MidRegLo);
9868
9869 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9870 .addReg(MidRegLo)
9871 .addImm(AMDGPU::sub0)
9872 .addReg(MidRegHi)
9873 .addImm(AMDGPU::sub1);
9874
9875 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9876 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9877 return;
9878 }
9879
9880 MachineOperand &Src = Inst.getOperand(1);
9881 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9882 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9883
9884 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9885 .addImm(31)
9886 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9887
9888 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9889 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9890 .addImm(AMDGPU::sub0)
9891 .addReg(TmpReg)
9892 .addImm(AMDGPU::sub1);
9893
9894 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9895 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9896}
9897
9898void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9899 MachineInstr &Inst, unsigned Opcode,
9900 MachineDominatorTree *MDT) const {
9901 // (S_FLBIT_I32_B64 hi:lo) ->
9902 // -> (umin (V_FFBH_U32_e32 hi), (or (V_FFBH_U32_e32 lo), 32))
9903 // (S_FF1_I32_B64 hi:lo) ->
9904 // ->(umin (or (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9905
9906 MachineBasicBlock &MBB = *Inst.getParent();
9907 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9908 MachineBasicBlock::iterator MII = Inst;
9909 const DebugLoc &DL = Inst.getDebugLoc();
9910
9911 MachineOperand &Dest = Inst.getOperand(0);
9912 MachineOperand &Src = Inst.getOperand(1);
9913
9914 const MCInstrDesc &InstDesc = get(Opcode);
9915
9916 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9917
9918 const TargetRegisterClass *SrcRC =
9919 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9920 const TargetRegisterClass *SrcSubRC =
9921 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9922
9923 MachineOperand SrcRegSub0 =
9924 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9925 MachineOperand SrcRegSub1 =
9926 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9927
9928 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9929 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9930 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9931 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9932
9933 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9934
9935 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9936
9937 BuildMI(MBB, MII, DL, get(AMDGPU::V_OR_B32_e32), MidReg3)
9938 .addImm(32)
9939 .addReg(IsCtlz ? MidReg1 : MidReg2);
9940
9941 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9942 .addReg(MidReg3)
9943 .addReg(IsCtlz ? MidReg2 : MidReg1);
9944
9945 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9946
9947 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9948}
9949
9950void SIInstrInfo::addUsersToMoveToVALUWorklist(
9952 SIInstrWorklist &Worklist) const {
9953 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9954 MachineInstr &UseMI = *MO.getParent();
9955
9956 unsigned OpNo = 0;
9957
9958 switch (UseMI.getOpcode()) {
9959 case AMDGPU::COPY:
9960 case AMDGPU::WQM:
9961 case AMDGPU::SOFT_WQM:
9962 case AMDGPU::STRICT_WWM:
9963 case AMDGPU::STRICT_WQM:
9964 case AMDGPU::REG_SEQUENCE:
9965 case AMDGPU::PHI:
9966 case AMDGPU::INSERT_SUBREG:
9967 break;
9968 default:
9969 OpNo = MO.getOperandNo();
9970 break;
9971 }
9972
9973 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9974 MRI.constrainRegClass(DstReg, OpRC);
9975
9976 if (!RI.hasVectorRegisters(OpRC))
9977 Worklist.insert(&UseMI);
9978 else
9979 // Legalization could change user list.
9981 }
9982}
9983
9984void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
9986 MachineInstr &Inst) const {
9987 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9988 MachineBasicBlock *MBB = Inst.getParent();
9989 MachineOperand &Src0 = Inst.getOperand(1);
9990 MachineOperand &Src1 = Inst.getOperand(2);
9991 const DebugLoc &DL = Inst.getDebugLoc();
9992
9993 if (ST.useRealTrue16Insts()) {
9994 Register SrcReg0, SrcReg1;
9995 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
9996 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9997 BuildMI(*MBB, Inst, DL,
9998 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9999 .add(Src0);
10000 } else {
10001 SrcReg0 = Src0.getReg();
10002 }
10003
10004 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
10005 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10006 BuildMI(*MBB, Inst, DL,
10007 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
10008 .add(Src1);
10009 } else {
10010 SrcReg1 = Src1.getReg();
10011 }
10012
10013 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
10014 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
10015
10016 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
10017 switch (Inst.getOpcode()) {
10018 case AMDGPU::S_PACK_LL_B32_B16:
10019 NewMI
10020 .addReg(SrcReg0, {},
10021 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10022 .addImm(AMDGPU::lo16)
10023 .addReg(SrcReg1, {},
10024 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10025 .addImm(AMDGPU::hi16);
10026 break;
10027 case AMDGPU::S_PACK_LH_B32_B16:
10028 NewMI
10029 .addReg(SrcReg0, {},
10030 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10031 .addImm(AMDGPU::lo16)
10032 .addReg(SrcReg1, {}, AMDGPU::hi16)
10033 .addImm(AMDGPU::hi16);
10034 break;
10035 case AMDGPU::S_PACK_HL_B32_B16:
10036 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10037 .addImm(AMDGPU::lo16)
10038 .addReg(SrcReg1, {},
10039 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10040 .addImm(AMDGPU::hi16);
10041 break;
10042 case AMDGPU::S_PACK_HH_B32_B16:
10043 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10044 .addImm(AMDGPU::lo16)
10045 .addReg(SrcReg1, {}, AMDGPU::hi16)
10046 .addImm(AMDGPU::hi16);
10047 break;
10048 default:
10049 llvm_unreachable("unhandled s_pack_* instruction");
10050 }
10051
10052 MachineOperand &Dest = Inst.getOperand(0);
10053 MRI.replaceRegWith(Dest.getReg(), ResultReg);
10054 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10055 return;
10056 }
10057
10058 switch (Inst.getOpcode()) {
10059 case AMDGPU::S_PACK_LL_B32_B16: {
10060 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10061 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10062
10063 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
10064 // 0.
10065 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10066 .addImm(0xffff);
10067
10068 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
10069 .addReg(ImmReg)
10070 .add(Src0);
10071
10072 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
10073 .add(Src1)
10074 .addImm(16)
10075 .addReg(TmpReg);
10076 break;
10077 }
10078 case AMDGPU::S_PACK_LH_B32_B16: {
10079 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10080 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10081 .addImm(0xffff);
10082 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
10083 .addReg(ImmReg)
10084 .add(Src0)
10085 .add(Src1);
10086 break;
10087 }
10088 case AMDGPU::S_PACK_HL_B32_B16: {
10089 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10090 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
10091 .addImm(16)
10092 .add(Src0);
10093 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
10094 .add(Src1)
10095 .addImm(16)
10096 .addReg(TmpReg);
10097 break;
10098 }
10099 case AMDGPU::S_PACK_HH_B32_B16: {
10100 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10101 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10102 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
10103 .addImm(16)
10104 .add(Src0);
10105 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10106 .addImm(0xffff0000);
10107 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
10108 .add(Src1)
10109 .addReg(ImmReg)
10110 .addReg(TmpReg);
10111 break;
10112 }
10113 default:
10114 llvm_unreachable("unhandled s_pack_* instruction");
10115 }
10116
10117 MachineOperand &Dest = Inst.getOperand(0);
10118 MRI.replaceRegWith(Dest.getReg(), ResultReg);
10119 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10120}
10121
10122void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
10123 MachineInstr &SCCDefInst,
10124 SIInstrWorklist &Worklist,
10125 Register NewCond) const {
10126
10127 // Ensure that def inst defines SCC, which is still live.
10128 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
10129 !Op.isDead() && Op.getParent() == &SCCDefInst);
10130 SmallVector<MachineInstr *, 4> CopyToDelete;
10131 // This assumes that all the users of SCC are in the same block
10132 // as the SCC def.
10133 for (MachineInstr &MI : // Skip the def inst itself.
10134 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
10135 SCCDefInst.getParent()->end())) {
10136 // Check if SCC is used first.
10137 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
10138 if (SCCIdx != -1) {
10139 if (MI.isCopy()) {
10140 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10141 Register DestReg = MI.getOperand(0).getReg();
10142
10143 MRI.replaceRegWith(DestReg, NewCond);
10144 CopyToDelete.push_back(&MI);
10145 } else {
10146
10147 if (NewCond.isValid())
10148 MI.getOperand(SCCIdx).setReg(NewCond);
10149
10150 Worklist.insert(&MI);
10151 }
10152 }
10153 // Exit if we find another SCC def.
10154 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
10155 break;
10156 }
10157 for (auto &Copy : CopyToDelete)
10158 Copy->eraseFromParent();
10159}
10160
10161// Instructions that use SCC may be converted to VALU instructions. When that
10162// happens, the SCC register is changed to VCC_LO. The instruction that defines
10163// SCC must be changed to an instruction that defines VCC. This function makes
10164// sure that the instruction that defines SCC is added to the moveToVALU
10165// worklist.
10166void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
10167 SIInstrWorklist &Worklist) const {
10168 // Look for a preceding instruction that either defines VCC or SCC. If VCC
10169 // then there is nothing to do because the defining instruction has been
10170 // converted to a VALU already. If SCC then that instruction needs to be
10171 // converted to a VALU.
10172 for (MachineInstr &MI :
10173 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
10174 SCCUseInst->getParent()->rend())) {
10175 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
10176 break;
10177 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
10178 Worklist.insert(&MI);
10179 break;
10180 }
10181 }
10182}
10183
10184const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
10185 const MachineInstr &Inst) const {
10186 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
10187
10188 switch (Inst.getOpcode()) {
10189 // For target instructions, getOpRegClass just returns the virtual register
10190 // class associated with the operand, so we need to find an equivalent VGPR
10191 // register class in order to move the instruction to the VALU.
10192 case AMDGPU::COPY:
10193 case AMDGPU::PHI:
10194 case AMDGPU::REG_SEQUENCE:
10195 case AMDGPU::INSERT_SUBREG:
10196 case AMDGPU::WQM:
10197 case AMDGPU::SOFT_WQM:
10198 case AMDGPU::STRICT_WWM:
10199 case AMDGPU::STRICT_WQM: {
10200 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
10201 if (RI.isAGPRClass(SrcRC)) {
10202 if (RI.isAGPRClass(NewDstRC))
10203 return nullptr;
10204
10205 switch (Inst.getOpcode()) {
10206 case AMDGPU::PHI:
10207 case AMDGPU::REG_SEQUENCE:
10208 case AMDGPU::INSERT_SUBREG:
10209 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10210 break;
10211 default:
10212 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10213 }
10214
10215 if (!NewDstRC)
10216 return nullptr;
10217 } else {
10218 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10219 return nullptr;
10220
10221 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10222 if (!NewDstRC)
10223 return nullptr;
10224 }
10225
10226 return NewDstRC;
10227 }
10228 default:
10229 return NewDstRC;
10230 }
10231}
10232
10233// Find the one SGPR operand we are allowed to use.
10234Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
10235 int OpIndices[3]) const {
10236 const MCInstrDesc &Desc = MI.getDesc();
10237
10238 // Find the one SGPR operand we are allowed to use.
10239 //
10240 // First we need to consider the instruction's operand requirements before
10241 // legalizing. Some operands are required to be SGPRs, such as implicit uses
10242 // of VCC, but we are still bound by the constant bus requirement to only use
10243 // one.
10244 //
10245 // If the operand's class is an SGPR, we can never move it.
10246
10247 Register SGPRReg = findImplicitSGPRRead(MI);
10248 if (SGPRReg)
10249 return SGPRReg;
10250
10251 Register UsedSGPRs[3] = {Register()};
10252 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10253
10254 for (unsigned i = 0; i < 3; ++i) {
10255 int Idx = OpIndices[i];
10256 if (Idx == -1)
10257 break;
10258
10259 const MachineOperand &MO = MI.getOperand(Idx);
10260 if (!MO.isReg())
10261 continue;
10262
10263 // Is this operand statically required to be an SGPR based on the operand
10264 // constraints?
10265 const TargetRegisterClass *OpRC =
10266 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
10267 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10268 if (IsRequiredSGPR)
10269 return MO.getReg();
10270
10271 // If this could be a VGPR or an SGPR, Check the dynamic register class.
10272 Register Reg = MO.getReg();
10273 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
10274 if (RI.isSGPRClass(RegRC))
10275 UsedSGPRs[i] = Reg;
10276 }
10277
10278 // We don't have a required SGPR operand, so we have a bit more freedom in
10279 // selecting operands to move.
10280
10281 // Try to select the most used SGPR. If an SGPR is equal to one of the
10282 // others, we choose that.
10283 //
10284 // e.g.
10285 // V_FMA_F32 v0, s0, s0, s0 -> No moves
10286 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
10287
10288 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
10289 // prefer those.
10290
10291 if (UsedSGPRs[0]) {
10292 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10293 SGPRReg = UsedSGPRs[0];
10294 }
10295
10296 if (!SGPRReg && UsedSGPRs[1]) {
10297 if (UsedSGPRs[1] == UsedSGPRs[2])
10298 SGPRReg = UsedSGPRs[1];
10299 }
10300
10301 return SGPRReg;
10302}
10303
10305 AMDGPU::OpName OperandName) const {
10306 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10307 return nullptr;
10308
10309 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
10310 if (Idx == -1)
10311 return nullptr;
10312
10313 return &MI.getOperand(Idx);
10314}
10315
10317 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
10318 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
10321 return (Format << 44) |
10322 (1ULL << 56) | // RESOURCE_LEVEL = 1
10323 (3ULL << 60); // OOB_SELECT = 3
10324 }
10325
10326 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
10327 if (ST.isAmdHsaOS()) {
10328 // Set ATC = 1. GFX9 doesn't have this bit.
10329 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10330 RsrcDataFormat |= (1ULL << 56);
10331
10332 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
10333 // BTW, it disables TC L2 and therefore decreases performance.
10334 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
10335 RsrcDataFormat |= (2ULL << 59);
10336 }
10337
10338 return RsrcDataFormat;
10339}
10340
10342 uint64_t Rsrc23 = getDefaultRsrcDataFormat() |
10344 0xffffffff; // Size;
10345
10346 // GFX9 doesn't have ELEMENT_SIZE.
10347 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
10348 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
10349 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
10350 }
10351
10352 // IndexStride = 64 / 32.
10353 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10354 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
10355
10356 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
10357 // Clear them unless we want a huge stride.
10358 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
10359 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
10360 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
10361
10362 return Rsrc23;
10363}
10364
10366 unsigned Opc = MI.getOpcode();
10367
10368 return isSMRD(Opc);
10369}
10370
10372 return get(Opc).mayLoad() &&
10373 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
10374}
10375
10377 TypeSize &MemBytes) const {
10378 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
10379 if (!Addr || !Addr->isFI())
10380 return Register();
10381
10382 assert(!MI.memoperands_empty() &&
10383 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
10384
10385 FrameIndex = Addr->getIndex();
10386
10387 int VDataIdx =
10388 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
10389 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
10390 return MI.getOperand(VDataIdx).getReg();
10391}
10392
10394 TypeSize &MemBytes) const {
10395 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
10396 assert(Addr && Addr->isFI());
10397 FrameIndex = Addr->getIndex();
10398
10399 int DataIdx =
10400 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
10401 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
10402 return MI.getOperand(DataIdx).getReg();
10403}
10404
10406 int &FrameIndex,
10407 TypeSize &MemBytes) const {
10408 if (!MI.mayLoad())
10409 return Register();
10410
10411 if (isMUBUF(MI) || isVGPRSpill(MI))
10412 return isStackAccess(MI, FrameIndex, MemBytes);
10413
10414 if (isSGPRSpill(MI))
10415 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10416
10417 return Register();
10418}
10419
10421 int &FrameIndex,
10422 TypeSize &MemBytes) const {
10423 if (!MI.mayStore())
10424 return Register();
10425
10426 if (isMUBUF(MI) || isVGPRSpill(MI))
10427 return isStackAccess(MI, FrameIndex, MemBytes);
10428
10429 if (isSGPRSpill(MI))
10430 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10431
10432 return Register();
10433}
10434
10436 unsigned Opc = MI.getOpcode();
10438 unsigned DescSize = Desc.getSize();
10439
10440 // If we have a definitive size, we can use it. Otherwise we need to inspect
10441 // the operands to know the size.
10442 if (isFixedSize(MI)) {
10443 unsigned Size = DescSize;
10444
10445 // If we hit the buggy offset, an extra nop will be inserted in MC so
10446 // estimate the worst case.
10447 if (MI.isBranch() && ST.hasOffset3fBug())
10448 Size += 4;
10449
10450 return Size;
10451 }
10452
10453 // Instructions may have a 32-bit literal encoded after them. Check
10454 // operands that could ever be literals.
10455 if (isVALU(MI, /*AllowLDSDMA=*/false) || isSALU(MI)) {
10456 if (isDPP(MI))
10457 return DescSize;
10458 bool HasLiteral = false;
10459 unsigned LiteralSize = 4;
10460 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
10461 const MachineOperand &Op = MI.getOperand(I);
10462 const MCOperandInfo &OpInfo = Desc.operands()[I];
10463 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
10464 HasLiteral = true;
10465 if (ST.has64BitLiterals()) {
10466 switch (OpInfo.OperandType) {
10467 default:
10468 break;
10471 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
10472 LiteralSize = 8;
10473 break;
10476 // A 32-bit literal is only valid when the value fits in BOTH signed
10477 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
10478 // emitter's getLit64Encoding logic. This is because of the lack of
10479 // abilility to tell signedness of the literal, therefore we need to
10480 // be conservative and assume values outside this range require a
10481 // 64-bit literal encoding (8 bytes).
10482 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
10483 !isUInt<32>(Op.getImm()))
10484 LiteralSize = 8;
10485 break;
10486 }
10487 }
10488 break;
10489 }
10490 }
10491 return HasLiteral ? DescSize + LiteralSize : DescSize;
10492 }
10493
10494 // Check whether we have extra NSA words.
10495 if (isMIMG(MI)) {
10496 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
10497 if (VAddr0Idx < 0)
10498 return 8;
10499
10500 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
10501 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10502 }
10503
10504 switch (Opc) {
10505 case TargetOpcode::BUNDLE:
10506 return getInstBundleSize(MI);
10507 case TargetOpcode::INLINEASM:
10508 case TargetOpcode::INLINEASM_BR: {
10509 const MachineFunction *MF = MI.getMF();
10510 const char *AsmStr = MI.getOperand(0).getSymbolName();
10511 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10512 }
10513 default:
10514 if (MI.isMetaInstruction())
10515 return 0;
10516
10517 // If D16 Pseudo inst, get correct MC code size
10518 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10519 if (D16Info) {
10520 // Assume d16_lo/hi inst are always in same size
10521 unsigned LoInstOpcode = D16Info->LoOp;
10522 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10523 DescSize = Desc.getSize();
10524 }
10525
10526 // If FMA Pseudo inst, get correct MC code size
10527 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10528 // All potential lowerings are the same size; arbitrarily pick one.
10529 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10530 DescSize = Desc.getSize();
10531 }
10532
10533 return DescSize;
10534 }
10535}
10536
10539 if (MI.isBranch() && ST.hasOffset3fBug())
10540 return InstSizeVerifyMode::NoVerify;
10541 return InstSizeVerifyMode::ExactSize;
10542}
10543
10546 static const std::pair<int, const char *> TargetIndices[] = {
10547 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10548 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10549 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10550 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10551 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10552 return ArrayRef(TargetIndices);
10553}
10554
10555/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10556/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10559 const ScheduleDAG *DAG) const {
10560 return new GCNHazardRecognizer(DAG->MF);
10561}
10562
10563/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10564/// pass.
10571
10572// Called during:
10573// - pre-RA scheduling and post-RA scheduling
10576 const ScheduleDAGMI *DAG) const {
10577 // Borrowed from Arm Target
10578 // We would like to restrict this hazard recognizer to only
10579 // post-RA scheduling; we can tell that we're post-RA because we don't
10580 // track VRegLiveness.
10581 if (!DAG->hasVRegLiveness())
10582 return new GCNHazardRecognizer(DAG->MF);
10584}
10585
10586std::pair<unsigned, unsigned>
10588 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10589}
10590
10593 static const std::pair<unsigned, const char *> TargetFlags[] = {
10594 {MO_GOTPCREL, "amdgpu-gotprel"},
10595 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10596 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10597 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10598 {MO_REL32_LO, "amdgpu-rel32-lo"},
10599 {MO_REL32_HI, "amdgpu-rel32-hi"},
10600 {MO_REL64, "amdgpu-rel64"},
10601 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10602 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10603 {MO_ABS64, "amdgpu-abs64"},
10604 };
10605
10606 return ArrayRef(TargetFlags);
10607}
10608
10611 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10612 {
10613 {MONoClobber, "amdgpu-noclobber"},
10614 {MOLastUse, "amdgpu-last-use"},
10615 {MOCooperative, "amdgpu-cooperative"},
10616 {MOThreadPrivate, "amdgpu-thread-private"},
10617 {MOCFSB0, "amdgpu-cfs0"},
10618 {MOCFSB1, "amdgpu-cfs1"},
10619 };
10620
10621 return ArrayRef(TargetFlags);
10622}
10623
10625 const MachineFunction &MF) const {
10627 assert(SrcReg.isVirtual());
10628 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10629 return AMDGPU::WWM_COPY;
10630
10631 return AMDGPU::COPY;
10632}
10633
10635 uint32_t Opcode = MI.getOpcode();
10636 // Check if it is SGPR spill or wwm-register spill Opcode.
10637 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10638 return true;
10639
10640 const MachineFunction *MF = MI.getMF();
10641 const MachineRegisterInfo &MRI = MF->getRegInfo();
10643
10644 // See if this is Liverange split instruction inserted for SGPR or
10645 // wwm-register. The implicit def inserted for wwm-registers should also be
10646 // included as they can appear at the bb begin.
10647 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10648 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10649 return false;
10650
10651 Register Reg = MI.getOperand(0).getReg();
10652 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10653 return IsLRSplitInst;
10654
10655 return MFI->isWWMReg(Reg);
10656}
10657
10659 Register Reg) const {
10660 // We need to handle instructions which may be inserted during register
10661 // allocation to handle the prolog. The initial prolog instruction may have
10662 // been separated from the start of the block by spills and copies inserted
10663 // needed by the prolog. However, the insertions for scalar registers can
10664 // always be placed at the BB top as they are independent of the exec mask
10665 // value.
10666 bool IsNullOrVectorRegister = true;
10667 if (Reg) {
10668 const MachineFunction *MF = MI.getMF();
10669 const MachineRegisterInfo &MRI = MF->getRegInfo();
10670 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10671 }
10672
10673 return IsNullOrVectorRegister &&
10674 (canAddToBBProlog(MI) ||
10675 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10676 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10677}
10678
10682 const DebugLoc &DL,
10683 Register DestReg) const {
10684 if (ST.hasAddNoCarryInsts())
10685 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10686
10687 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10688 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10689 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10690
10691 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10692 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10693}
10694
10697 const DebugLoc &DL,
10698 Register DestReg,
10699 RegScavenger &RS) const {
10700 if (ST.hasAddNoCarryInsts())
10701 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10702
10703 // If available, prefer to use vcc.
10704 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10705 ? Register(RI.getVCC())
10706 : RS.scavengeRegisterBackwards(
10707 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10708 0, /* AllowSpill */ false);
10709
10710 // TODO: Users need to deal with this.
10711 if (!UnusedCarry.isValid())
10712 return MachineInstrBuilder();
10713
10714 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10715 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10716}
10717
10718bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10719 switch (Opcode) {
10720 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10721 case AMDGPU::SI_KILL_I1_TERMINATOR:
10722 return true;
10723 default:
10724 return false;
10725 }
10726}
10727
10729 switch (Opcode) {
10730 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10731 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10732 case AMDGPU::SI_KILL_I1_PSEUDO:
10733 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10734 default:
10735 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10736 }
10737}
10738
10740 return Imm <= getMaxMUBUFImmOffset(ST);
10741}
10742
10744 // GFX12 field is non-negative 24-bit signed byte offset.
10745 const unsigned OffsetBits =
10746 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10747 return (1 << OffsetBits) - 1;
10748}
10749
10751 if (!ST.isWave32())
10752 return;
10753
10754 if (MI.isInlineAsm())
10755 return;
10756
10757 if (MI.getNumOperands() < MI.getDesc().getNumOperands())
10758 return;
10759
10760 for (auto &Op : MI.implicit_operands()) {
10761 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10762 Op.setReg(AMDGPU::VCC_LO);
10763 }
10764}
10765
10767 if (!isSMRD(MI))
10768 return false;
10769
10770 // Check that it is using a buffer resource.
10771 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10772 if (Idx == -1) // e.g. s_memtime
10773 return false;
10774
10775 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10776 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10777}
10778
10779// Given Imm, split it into the values to put into the SOffset and ImmOffset
10780// fields in an MUBUF instruction. Return false if it is not possible (due to a
10781// hardware bug needing a workaround).
10782//
10783// The required alignment ensures that individual address components remain
10784// aligned if they are aligned to begin with. It also ensures that additional
10785// offsets within the given alignment can be added to the resulting ImmOffset.
10787 uint32_t &ImmOffset, Align Alignment) const {
10788 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10789 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10790 uint32_t Overflow = 0;
10791
10792 if (Imm > MaxImm) {
10793 if (Imm <= MaxImm + 64) {
10794 // Use an SOffset inline constant for 4..64
10795 Overflow = Imm - MaxImm;
10796 Imm = MaxImm;
10797 } else {
10798 // Try to keep the same value in SOffset for adjacent loads, so that
10799 // the corresponding register contents can be re-used.
10800 //
10801 // Load values with all low-bits (except for alignment bits) set into
10802 // SOffset, so that a larger range of values can be covered using
10803 // s_movk_i32.
10804 //
10805 // Atomic operations fail to work correctly when individual address
10806 // components are unaligned, even if their sum is aligned.
10807 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10808 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10809 Imm = Low;
10810 Overflow = High - Alignment.value();
10811 }
10812 }
10813
10814 if (Overflow > 0) {
10815 // There is a hardware bug in SI and CI which prevents address clamping in
10816 // MUBUF instructions from working correctly with SOffsets. The immediate
10817 // offset is unaffected.
10818 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10819 return false;
10820
10821 // It is not possible to set immediate in SOffset field on some targets.
10822 if (ST.hasRestrictedSOffset())
10823 return false;
10824 }
10825
10826 ImmOffset = Imm;
10827 SOffset = Overflow;
10828 return true;
10829}
10830
10831// Depending on the used address space and instructions, some immediate offsets
10832// are allowed and some are not.
10833// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10834// scratch instruction offsets can also be negative. On GFX12, offsets can be
10835// negative for all variants.
10836//
10837// There are several bugs related to these offsets:
10838// On gfx10.1, flat instructions that go into the global address space cannot
10839// use an offset.
10840//
10841// For scratch instructions, the address can be either an SGPR or a VGPR.
10842// The following offsets can be used, depending on the architecture (x means
10843// cannot be used):
10844// +----------------------------+------+------+
10845// | Address-Mode | SGPR | VGPR |
10846// +----------------------------+------+------+
10847// | gfx9 | | |
10848// | negative, 4-aligned offset | x | ok |
10849// | negative, unaligned offset | x | ok |
10850// +----------------------------+------+------+
10851// | gfx10 | | |
10852// | negative, 4-aligned offset | ok | ok |
10853// | negative, unaligned offset | ok | x |
10854// +----------------------------+------+------+
10855// | gfx10.3 | | |
10856// | negative, 4-aligned offset | ok | ok |
10857// | negative, unaligned offset | ok | ok |
10858// +----------------------------+------+------+
10859//
10860// This function ignores the addressing mode, so if an offset cannot be used in
10861// one addressing mode, it is considered illegal.
10862bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10863 AMDGPU::FlatAddrSpace FlatVariant) const {
10864 // TODO: Should 0 be special cased?
10865 if (!ST.hasFlatInstOffsets())
10866 return false;
10867
10869 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10870 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10871 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10872 return false;
10873
10874 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10875 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10876 (Offset % 4) != 0) {
10877 return false;
10878 }
10879
10880 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10881 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10882 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10883}
10884
10885// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10886std::pair<int64_t, int64_t>
10887SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10888 AMDGPU::FlatAddrSpace FlatVariant) const {
10889 int64_t RemainderOffset = COffsetVal;
10890 int64_t ImmField = 0;
10891
10892 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10893 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10894
10895 if (AllowNegative) {
10896 // Use signed division by a power of two to truncate towards 0.
10897 int64_t D = 1LL << NumBits;
10898 RemainderOffset = (COffsetVal / D) * D;
10899 ImmField = COffsetVal - RemainderOffset;
10900
10901 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10902 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10903 (ImmField % 4) != 0) {
10904 // Make ImmField a multiple of 4
10905 RemainderOffset += ImmField % 4;
10906 ImmField -= ImmField % 4;
10907 }
10908 } else if (COffsetVal >= 0) {
10909 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10910 RemainderOffset = COffsetVal - ImmField;
10911 }
10912
10913 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10914 assert(RemainderOffset + ImmField == COffsetVal);
10915 return {ImmField, RemainderOffset};
10916}
10917
10919 AMDGPU::FlatAddrSpace FlatVariant) const {
10920 if (ST.hasNegativeScratchOffsetBug() &&
10922 return false;
10923
10924 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10925}
10926
10927static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10928 switch (ST.getGeneration()) {
10929 default:
10930 break;
10933 return SIEncodingFamily::SI;
10935 // The GFX80 encoding family only contains buffer instructions with unpacked
10936 // D16 data; pseudoToMCOpcode falls back on VI for everything else.
10937 // TODO: remove this when we discard GFX80 encoding.
10938 return ST.hasUnpackedD16VMem() ? SIEncodingFamily::GFX80
10941 return SIEncodingFamily::VI;
10945 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10948 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10952 }
10953 llvm_unreachable("Unknown subtarget generation!");
10954}
10955
10956bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10957 switch(MCOp) {
10958 // These opcodes use indirect register addressing so
10959 // they need special handling by codegen (currently missing).
10960 // Therefore it is too risky to allow these opcodes
10961 // to be selected by dpp combiner or sdwa peepholer.
10962 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10963 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10964 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10965 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10966 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10967 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10968 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10969 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10970 return true;
10971 default:
10972 return false;
10973 }
10974}
10975
10976#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10977 case OPCODE##_dpp: \
10978 case OPCODE##_e32: \
10979 case OPCODE##_e64:
10980
10981static bool isRenamedInGFX9(int Opcode) {
10982 switch (Opcode) {
10983 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
10984 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
10985 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
10986 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
10987 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
10988 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
10989 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
10990 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
10991 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
10992 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10993 case AMDGPU::V_FMA_F16_gfx9_e64:
10994 case AMDGPU::V_INTERP_P2_F16:
10995 case AMDGPU::V_MAD_F16_e64:
10996 case AMDGPU::V_MAD_U16_e64:
10997 case AMDGPU::V_MAD_I16_e64:
10998 case AMDGPU::V_MAD_U16_gfx9_e64:
10999 case AMDGPU::V_MAD_I16_gfx9_e64:
11000 return true;
11001 default:
11002 return false;
11003 }
11004}
11005
11006int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
11007 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
11008 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
11009
11010 unsigned Gen = subtargetEncodingFamily(ST);
11011
11012 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
11014
11015 if (SIInstrFlags::isSDWA(get(Opcode))) {
11016 switch (ST.getGeneration()) {
11017 default:
11019 break;
11022 break;
11025 break;
11026 }
11027 }
11028
11029 if (isMAI(Opcode)) {
11030 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
11031 if (MFMAOp != -1)
11032 Opcode = MFMAOp;
11033 }
11034
11035 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
11036
11037 // Only buffer instructions with unpacked D16 data have a GFX80 encoding.
11038 // Anything else on such a subtarget uses the plain VI encoding.
11039 // TODO: remove this when we discard GFX80 encoding.
11040 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && Gen == SIEncodingFamily::GFX80)
11042
11043 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
11045
11046 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
11048
11049 // -1 means that Opcode is already a native instruction.
11050 if (MCOp == -1)
11051 return Opcode;
11052
11053 if (ST.hasGFX90AInsts()) {
11054 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
11055 if (ST.hasGFX940Insts())
11057 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11059 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11061 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
11062 MCOp = NMCOp;
11063 }
11064
11065 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
11066 // encoding in the given subtarget generation.
11067 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
11068 return -1;
11069
11070 if (isAsmOnlyOpcode(MCOp))
11071 return -1;
11072
11073 return MCOp;
11074}
11075
11076static
11078 assert(RegOpnd.isReg());
11079 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
11080 getRegSubRegPair(RegOpnd);
11081}
11082
11085 assert(MI.isRegSequence());
11086 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
11087 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
11088 auto &RegOp = MI.getOperand(1 + 2 * I);
11089 return getRegOrUndef(RegOp);
11090 }
11092}
11093
11094// Try to find the definition of reg:subreg in subreg-manipulation pseudos
11095// Following a subreg of reg:subreg isn't supported
11098 if (!RSR.SubReg)
11099 return false;
11100 switch (MI.getOpcode()) {
11101 default: break;
11102 case AMDGPU::REG_SEQUENCE:
11103 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
11104 return true;
11105 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
11106 case AMDGPU::INSERT_SUBREG:
11107 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
11108 // inserted the subreg we're looking for
11109 RSR = getRegOrUndef(MI.getOperand(2));
11110 else { // the subreg in the rest of the reg
11111 auto R1 = getRegOrUndef(MI.getOperand(1));
11112 if (R1.SubReg) // subreg of subreg isn't supported
11113 return false;
11114 RSR.Reg = R1.Reg;
11115 }
11116 return true;
11117 }
11118 return false;
11119}
11120
11122 const MachineRegisterInfo &MRI) {
11123 assert(MRI.isSSA());
11124 if (!P.Reg.isVirtual())
11125 return nullptr;
11126
11127 auto RSR = P;
11128 auto *DefInst = MRI.getVRegDef(RSR.Reg);
11129 while (auto *MI = DefInst) {
11130 DefInst = nullptr;
11131 switch (MI->getOpcode()) {
11132 case AMDGPU::COPY:
11133 case AMDGPU::V_MOV_B32_e32: {
11134 auto &Op1 = MI->getOperand(1);
11135 if (Op1.isReg() && Op1.getReg().isVirtual()) {
11136 if (Op1.isUndef())
11137 return nullptr;
11138 RSR = getRegSubRegPair(Op1);
11139 DefInst = MRI.getVRegDef(RSR.Reg);
11140 }
11141 break;
11142 }
11143 default:
11144 if (followSubRegDef(*MI, RSR)) {
11145 if (!RSR.Reg)
11146 return nullptr;
11147 DefInst = MRI.getVRegDef(RSR.Reg);
11148 }
11149 }
11150 if (!DefInst)
11151 return MI;
11152 }
11153 return nullptr;
11154}
11155
11157 Register VReg,
11158 const MachineInstr &DefMI,
11159 const MachineInstr &UseMI) {
11160 assert(MRI.isSSA() && "Must be run on SSA");
11161
11162 auto *TRI = MRI.getTargetRegisterInfo();
11163 auto *DefBB = DefMI.getParent();
11164
11165 // Don't bother searching between blocks, although it is possible this block
11166 // doesn't modify exec.
11167 if (UseMI.getParent() != DefBB)
11168 return true;
11169
11170 const int MaxInstScan = 20;
11171 int NumInst = 0;
11172
11173 // Stop scan at the use.
11174 auto E = UseMI.getIterator();
11175 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
11176 if (I->isDebugInstr())
11177 continue;
11178
11179 if (++NumInst > MaxInstScan)
11180 return true;
11181
11182 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
11183 return true;
11184 }
11185
11186 return false;
11187}
11188
11190 Register VReg,
11191 const MachineInstr &DefMI) {
11192 assert(MRI.isSSA() && "Must be run on SSA");
11193
11194 auto *TRI = MRI.getTargetRegisterInfo();
11195 auto *DefBB = DefMI.getParent();
11196
11197 const int MaxUseScan = 10;
11198 int NumUse = 0;
11199
11200 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
11201 auto &UseInst = *Use.getParent();
11202 // Don't bother searching between blocks, although it is possible this block
11203 // doesn't modify exec.
11204 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11205 return true;
11206
11207 if (++NumUse > MaxUseScan)
11208 return true;
11209 }
11210
11211 if (NumUse == 0)
11212 return false;
11213
11214 const int MaxInstScan = 20;
11215 int NumInst = 0;
11216
11217 // Stop scan when we have seen all the uses.
11218 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
11219 assert(I != DefBB->end());
11220
11221 if (I->isDebugInstr())
11222 continue;
11223
11224 if (++NumInst > MaxInstScan)
11225 return true;
11226
11227 for (const MachineOperand &Op : I->operands()) {
11228 // We don't check reg masks here as they're used only on calls:
11229 // 1. EXEC is only considered const within one BB
11230 // 2. Call should be a terminator instruction if present in a BB
11231
11232 if (!Op.isReg())
11233 continue;
11234
11235 Register Reg = Op.getReg();
11236 if (Op.isUse()) {
11237 if (Reg == VReg && --NumUse == 0)
11238 return false;
11239 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
11240 return true;
11241 }
11242 }
11243}
11244
11247 const DebugLoc &DL, Register Src, Register Dst) const {
11248 auto Cur = MBB.begin();
11249 if (Cur != MBB.end())
11250 do {
11251 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
11252 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
11253 ++Cur;
11254 } while (Cur != MBB.end() && Cur != LastPHIIt);
11255
11256 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
11257 Dst);
11258}
11259
11262 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
11263 if (InsPt != MBB.end() &&
11264 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11265 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11266 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11267 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
11268 InsPt++;
11269 return BuildMI(MBB, InsPt, DL,
11270 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
11271 .addReg(Src, {}, SrcSubReg)
11272 .addReg(AMDGPU::EXEC, RegState::Implicit);
11273 }
11274 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
11275 Dst);
11276}
11277
11278bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
11279
11281 const MachineInstr &SecondMI) const {
11282 for (const auto &Use : SecondMI.all_uses()) {
11283 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
11284 return true;
11285 }
11286 return false;
11287}
11288
11289/// If OpX is multicycle, anti-dependencies are not allowed.
11290/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
11291/// purpose.
11293 const MachineInstr &OpX) const {
11295}
11296
11299 ArrayRef<unsigned> Ops, int FrameIndex,
11300 MachineInstr *&CopyMI, LiveIntervals *LIS,
11301 VirtRegMap *VRM) const {
11302 // This is a bit of a hack (copied from AArch64). Consider this instruction:
11303 //
11304 // %0:sreg_32 = COPY $m0
11305 //
11306 // We explicitly chose SReg_32 for the virtual register so such a copy might
11307 // be eliminated by RegisterCoalescer. However, that may not be possible, and
11308 // %0 may even spill. We can't spill $m0 normally (it would require copying to
11309 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
11310 // TargetInstrInfo::foldMemoryOperand() is going to try.
11311 // A similar issue also exists with spilling and reloading $exec registers.
11312 //
11313 // To prevent that, constrain the %0 register class here.
11314 if (isFullCopyInstr(MI)) {
11315 Register DstReg = MI.getOperand(0).getReg();
11316 Register SrcReg = MI.getOperand(1).getReg();
11317 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
11318 (DstReg.isVirtual() != SrcReg.isVirtual())) {
11320 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
11321 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
11322 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
11323 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11324 return nullptr;
11325 }
11326 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
11327 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11328 return nullptr;
11329 }
11330 }
11331 }
11332
11333 return nullptr;
11334}
11335
11337 const MachineInstr &MI,
11338 unsigned *PredCost) const {
11339 if (MI.isBundle()) {
11341 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
11342 unsigned Lat = 0, Count = 0;
11343 for (++I; I != E && I->isBundledWithPred(); ++I) {
11344 ++Count;
11345 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
11346 }
11347 return Lat + Count - 1;
11348 }
11349
11350 return SchedModel.computeInstrLatency(&MI);
11351}
11352
11354 if (!ST.hasGFX1250VALUBlockingCycles())
11355 return 0;
11357}
11358
11359unsigned
11361 if (const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(MI.getOpcode()))
11362 return Entry->GFX1250BlockingCycles;
11363 return 0;
11364}
11365
11366const MachineOperand &
11368 if (const MachineOperand *CallAddrOp =
11369 getNamedOperand(MI, AMDGPU::OpName::src0))
11370 return *CallAddrOp;
11372}
11373
11376 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11377 unsigned Opcode = MI.getOpcode();
11378
11379 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
11380 Register Dst = MI.getOperand(0).getReg();
11381 Register Src = MI.getOperand(1).getReg();
11382 LLT DstTy = MRI.getType(Dst);
11383 LLT SrcTy = MRI.getType(Src);
11384 unsigned DstAS = DstTy.getAddressSpace();
11385 unsigned SrcAS = SrcTy.getAddressSpace();
11386 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
11387 DstAS == AMDGPUAS::FLAT_ADDRESS &&
11388 ST.hasGloballyAddressableScratch()
11391 };
11392
11393 // If the target supports globally addressable scratch, the mapping from
11394 // scratch memory to the flat aperture changes therefore an address space cast
11395 // is no longer uniform.
11396 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11397 return HandleAddrSpaceCast(MI);
11398
11399 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
11400 auto IID = GI->getIntrinsicID();
11405
11406 switch (IID) {
11407 case Intrinsic::amdgcn_if:
11408 case Intrinsic::amdgcn_else:
11409 // FIXME: Uniform if second result
11410 break;
11411 }
11412
11414 }
11415
11416 // Loads from the private and flat address spaces are divergent, because
11417 // threads can execute the load instruction with the same inputs and get
11418 // different results.
11419 //
11420 // All other loads are not divergent, because if threads issue loads with the
11421 // same arguments, they will always get the same result.
11422 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11423 Opcode == AMDGPU::G_SEXTLOAD) {
11424 if (MI.memoperands_empty())
11425 return ValueUniformity::NeverUniform; // conservative assumption
11426
11427 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11428 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11429 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11430 })) {
11431 // At least one MMO in a non-global address space.
11433 }
11435 }
11436
11437 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11438 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11439 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11440 AMDGPU::isGenericAtomic(Opcode)) {
11442 }
11443
11444 // Result is computed from uniform SP and uniform wave-wide max size.
11445 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11447
11448 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11450
11452}
11453
11455 if (!Formatter)
11456 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11457 return Formatter.get();
11458}
11459
11461
11462 if (isNeverUniform(MI))
11464
11465 unsigned opcode = MI.getOpcode();
11466 if (opcode == AMDGPU::V_READLANE_B32 ||
11467 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11468 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11470
11471 // If any of defs is divergent, report as NeverUniform. isUniformReg will
11472 // calculate in more detail for each def from its reg class, if available.
11473 if (MI.isInlineAsm()) {
11474 for (const MachineOperand &MO : MI.operands()) {
11475 if (!MO.isReg() || !MO.isDef())
11476 continue;
11477 const TargetRegisterClass *RC =
11478 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
11479 if (!RC || !RI.isSGPRClass(RC))
11481 }
11482 }
11483
11484 if (isCopyInstr(MI)) {
11485 const MachineOperand &srcOp = MI.getOperand(1);
11486 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
11487 const TargetRegisterClass *regClass =
11488 RI.getPhysRegBaseClass(srcOp.getReg());
11489 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
11491 }
11493 }
11494
11495 // GMIR handling
11496 if (MI.isPreISelOpcode())
11498
11499 // Atomics are divergent because they are executed sequentially: when an
11500 // atomic operation refers to the same address in each thread, then each
11501 // thread after the first sees the value written by the previous thread as
11502 // original value.
11503
11504 if (isAtomic(MI))
11506
11507 // Loads from the private and flat address spaces are divergent, because
11508 // threads can execute the load instruction with the same inputs and get
11509 // different results.
11510 if (isFLAT(MI) && MI.mayLoad()) {
11511 if (MI.memoperands_empty())
11512 return ValueUniformity::NeverUniform; // conservative assumption
11513
11514 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11515 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11516 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11517 })) {
11518 // At least one MMO in a non-global address space.
11520 }
11521
11523 }
11524
11525 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11526 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11527
11528 // FIXME: It's conceptually broken to report this for an instruction, and not
11529 // a specific def operand. For inline asm in particular, there could be mixed
11530 // uniform and divergent results.
11531 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11532 const MachineOperand &SrcOp = MI.getOperand(I);
11533 if (!SrcOp.isReg())
11534 continue;
11535
11536 Register Reg = SrcOp.getReg();
11537 if (!Reg || !SrcOp.readsReg())
11538 continue;
11539
11540 // If RegBank is null, this is unassigned or an unallocatable special
11541 // register, which are all scalars.
11542 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11543 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11545 }
11546
11547 // TODO: Uniformity check condtions above can be rearranged for more
11548 // redability
11549
11550 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11551 // currently turned into no-op COPYs by SelectionDAG ISel and are
11552 // therefore no longer recognizable.
11553
11555}
11556
11558 switch (MF.getFunction().getCallingConv()) {
11560 return 1;
11562 return 2;
11564 return 3;
11568 const Function &F = MF.getFunction();
11569 F.getContext().diagnose(DiagnosticInfoUnsupported(
11570 F, "ds_ordered_count unsupported for this calling conv"));
11571 [[fallthrough]];
11572 }
11575 case CallingConv::C:
11576 case CallingConv::Fast:
11577 default:
11578 // Assume other calling conventions are various compute callable functions
11579 return 0;
11580 }
11581}
11582
11584 Register &SrcReg2, int64_t &CmpMask,
11585 int64_t &CmpValue) const {
11586 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11587 return false;
11588
11589 switch (MI.getOpcode()) {
11590 default:
11591 break;
11592 case AMDGPU::S_CMP_EQ_U32:
11593 case AMDGPU::S_CMP_EQ_I32:
11594 case AMDGPU::S_CMP_LG_U32:
11595 case AMDGPU::S_CMP_LG_I32:
11596 case AMDGPU::S_CMP_LT_U32:
11597 case AMDGPU::S_CMP_LT_I32:
11598 case AMDGPU::S_CMP_GT_U32:
11599 case AMDGPU::S_CMP_GT_I32:
11600 case AMDGPU::S_CMP_LE_U32:
11601 case AMDGPU::S_CMP_LE_I32:
11602 case AMDGPU::S_CMP_GE_U32:
11603 case AMDGPU::S_CMP_GE_I32:
11604 case AMDGPU::S_CMP_EQ_U64:
11605 case AMDGPU::S_CMP_LG_U64:
11606 SrcReg = MI.getOperand(0).getReg();
11607 if (MI.getOperand(1).isReg()) {
11608 if (MI.getOperand(1).getSubReg())
11609 return false;
11610 SrcReg2 = MI.getOperand(1).getReg();
11611 CmpValue = 0;
11612 } else if (MI.getOperand(1).isImm()) {
11613 SrcReg2 = Register();
11614 CmpValue = MI.getOperand(1).getImm();
11615 } else {
11616 return false;
11617 }
11618 CmpMask = ~0;
11619 return true;
11620 case AMDGPU::S_CMPK_EQ_U32:
11621 case AMDGPU::S_CMPK_EQ_I32:
11622 case AMDGPU::S_CMPK_LG_U32:
11623 case AMDGPU::S_CMPK_LG_I32:
11624 case AMDGPU::S_CMPK_LT_U32:
11625 case AMDGPU::S_CMPK_LT_I32:
11626 case AMDGPU::S_CMPK_GT_U32:
11627 case AMDGPU::S_CMPK_GT_I32:
11628 case AMDGPU::S_CMPK_LE_U32:
11629 case AMDGPU::S_CMPK_LE_I32:
11630 case AMDGPU::S_CMPK_GE_U32:
11631 case AMDGPU::S_CMPK_GE_I32:
11632 SrcReg = MI.getOperand(0).getReg();
11633 SrcReg2 = Register();
11634 CmpValue = MI.getOperand(1).getImm();
11635 CmpMask = ~0;
11636 return true;
11637 }
11638
11639 return false;
11640}
11641
11643 for (MachineBasicBlock *S : MBB->successors()) {
11644 if (S->isLiveIn(AMDGPU::SCC))
11645 return false;
11646 }
11647 return true;
11648}
11649
11650// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11651// (incoming SCC) = !(SCC defined by SCCDef).
11652// Return true if all uses can be re-written, false otherwise.
11653bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11654 MachineBasicBlock *MBB = SCCDef->getParent();
11655 SmallVector<MachineInstr *> InvertInstr;
11656 bool SCCIsDead = false;
11657
11658 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11659 constexpr unsigned ScanLimit = 12;
11660 unsigned Count = 0;
11661 for (MachineInstr &MI : instructionsWithoutDebug(
11662 std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11663 if (++Count > ScanLimit)
11664 return false;
11665 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11666 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11667 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11668 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11669 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11670 InvertInstr.push_back(&MI);
11671 else
11672 return false;
11673 }
11674 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11675 SCCIsDead = true;
11676 break;
11677 }
11678 }
11679 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11680 SCCIsDead = true;
11681
11682 // SCC may have more uses. Can't invert all of them.
11683 if (!SCCIsDead)
11684 return false;
11685
11686 // Invert uses
11687 for (MachineInstr *MI : InvertInstr) {
11688 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11689 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11690 swapOperands(*MI);
11691 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11692 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11693 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11694 ? AMDGPU::S_CBRANCH_SCC1
11695 : AMDGPU::S_CBRANCH_SCC0));
11696 } else {
11697 llvm_unreachable("SCC used but no inversion handling");
11698 }
11699 }
11700 return true;
11701}
11702
11703// SCC is already valid after SCCValid.
11704// SCCRedefine will redefine SCC to the same value already available after
11705// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11706// update kill/dead flags if necessary.
11707bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11708 bool NeedInversion) const {
11709 MachineInstr *KillsSCC = nullptr;
11710 if (SCCValid->getParent() != SCCRedefine->getParent())
11711 return false;
11712 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11713 SCCRedefine->getIterator())) {
11714 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11715 return false;
11716 if (MI.killsRegister(AMDGPU::SCC, &RI))
11717 KillsSCC = &MI;
11718 }
11719 if (NeedInversion && !invertSCCUse(SCCRedefine))
11720 return false;
11721 if (MachineOperand *SccDef =
11722 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11723 SccDef->setIsDead(false);
11724 if (KillsSCC)
11725 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11726 SCCRedefine->eraseFromParent();
11727 return true;
11728}
11729
11730/// If \p Sel is an S_CSELECT* of two different constants A and B, return them,
11731/// truncated to the width of the select.
11732static std::optional<std::pair<int64_t, int64_t>>
11734 const MachineInstr &Sel) {
11735 unsigned Opc = Sel.getOpcode();
11736 if (Opc != AMDGPU::S_CSELECT_B32 && Opc != AMDGPU::S_CSELECT_B64)
11737 return {};
11738 std::optional<int64_t> A =
11739 TII.getImmOrMaterializedImm(MRI, Sel.getOperand(1));
11740 if (!A)
11741 return {};
11742 std::optional<int64_t> B =
11743 TII.getImmOrMaterializedImm(MRI, Sel.getOperand(2));
11744 if (!B)
11745 return {};
11746 if (Opc == AMDGPU::S_CSELECT_B32) {
11747 A = Lo_32(*A);
11748 B = Lo_32(*B);
11749 }
11750 if (*A == *B)
11751 return {};
11752 return std::pair(*A, *B);
11753}
11754
11755static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11756 unsigned &NewDefOpc) {
11757 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11758 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11759 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11760 Def.getOpcode() != AMDGPU::S_ADD_U32)
11761 return false;
11762 const MachineOperand &AddSrc1 = Def.getOperand(1);
11763 const MachineOperand &AddSrc2 = Def.getOperand(2);
11764 const MachineRegisterInfo &MRI = Def.getMF()->getRegInfo();
11765 const SIInstrInfo *TII = static_cast<const SIInstrInfo *>(
11766 Def.getMF()->getSubtarget().getInstrInfo());
11767
11768 auto Imm1 = TII->getImmOrMaterializedImm(MRI, AddSrc1);
11769 auto Imm2 = TII->getImmOrMaterializedImm(MRI, AddSrc2);
11770 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11771 return false;
11772
11773 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11774 const MachineOperand *SccDef =
11775 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11776 if (!SccDef->isDead())
11777 return false;
11778 NewDefOpc = AMDGPU::S_ADD_U32;
11779 }
11780 NeedInversion = !NeedInversion;
11781 return true;
11782}
11783
11785 Register SrcReg2, int64_t CmpMask,
11786 int64_t CmpValue,
11787 const MachineRegisterInfo *MRI) const {
11788 if (!SrcReg || SrcReg.isPhysical())
11789 return false;
11790
11791 if (SrcReg2) {
11792 auto ImmOpt = getImmOrMaterializedImm(*MRI, SrcReg2);
11793 if (!ImmOpt)
11794 return false;
11795 CmpValue = *ImmOpt;
11796 }
11797
11798 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11799 this](bool NeedInversion) -> bool {
11800 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11801 if (!Def)
11802 return false;
11803
11804 unsigned NewDefOpc = Def->getOpcode();
11805 if (auto Consts = getSelectConstants(*this, *MRI, *Def)) {
11806 // sX = S_CSELECT* A, B with A != B, so sX == A exactly when SCC was set.
11807 // Comparing sX with A or B recomputes SCC or its inverse:
11808 //
11809 // s_cmp_eq_* sX, A => SCC s_cmp_lg_* sX, A => !SCC
11810 // s_cmp_eq_* sX, B => !SCC s_cmp_lg_* sX, B => SCC
11811 auto [A, B] = *Consts;
11812 int64_t C = Def->getOpcode() == AMDGPU::S_CSELECT_B32 ? Lo_32(CmpValue)
11813 : CmpValue;
11814 if (C == A)
11815 NeedInversion = !NeedInversion;
11816 else if (C != B)
11817 return false;
11818 } else {
11819 // For S_OP that set SCC = DST!=0, do the transformation
11820 //
11821 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11822 //
11823 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11824 // do the transformation:
11825 //
11826 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11827 if (CmpValue != 0 ||
11828 (!setsSCCIfResultIsNonZero(*Def) &&
11829 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc)))
11830 return false;
11831 }
11832
11833 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11834 return false;
11835
11836 if (NewDefOpc != Def->getOpcode())
11837 Def->setDesc(get(NewDefOpc));
11838
11839 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11840 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11841 // 64-bit select then delete s_or_b32 in the sequence:
11842 // sX = s_cselect_b64 A, B (A != B, one of them 0)
11843 // sLo = copy sX.sub0
11844 // sHi = copy sX.sub1
11845 // sY = s_or_b32 sLo, sHi
11846 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11847 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11848 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11849 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11850 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11851 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11852 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11853 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11854 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11855 Def2->getOperand(1).isReg() &&
11856 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11857 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11858 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11859 if (MachineInstr *Select =
11860 MRI->getVRegDef(Def1->getOperand(1).getReg())) {
11861 if (auto Consts = getSelectConstants(*this, *MRI, *Select)) {
11862 auto [A, B] = *Consts;
11863 if (A == 0 || B == 0)
11864 optimizeSCC(Select, Def, /*NeedInversion=*/A == 0);
11865 }
11866 }
11867 }
11868 }
11869 }
11870 return true;
11871 };
11872
11873 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11874 this](int64_t ExpectedValue, unsigned SrcSize,
11875 bool IsReversible, bool IsSigned) -> bool {
11876 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11877 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11878 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11879 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11880 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11881 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11882 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11883 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11884 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11885 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11886 //
11887 // Signed ge/gt are not used for the sign bit.
11888 //
11889 // If result of the AND is unused except in the compare:
11890 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11891 //
11892 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11893 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11894 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11895 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11896 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11897 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11898
11899 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11900 if (!Def)
11901 return false;
11902
11903 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11904 Def->getOpcode() != AMDGPU::S_AND_B64)
11905 return false;
11906
11907 int64_t Mask;
11908 const auto isMask = [&Mask, SrcSize, MRI,
11909 this](const MachineOperand *MO) -> bool {
11910 auto ImmOpt = this->getImmOrMaterializedImm(*MRI, *MO);
11911 if (!ImmOpt)
11912 return false;
11913 Mask = *ImmOpt;
11914 Mask &= maxUIntN(SrcSize);
11915 return isPowerOf2_64(Mask);
11916 };
11917
11918 MachineOperand *SrcOp = &Def->getOperand(1);
11919 if (isMask(SrcOp))
11920 SrcOp = &Def->getOperand(2);
11921 else if (isMask(&Def->getOperand(2)))
11922 SrcOp = &Def->getOperand(1);
11923 else
11924 return false;
11925
11926 // A valid Mask is required to have a single bit set, hence a non-zero and
11927 // power-of-two value. This verifies that we will not do 64-bit shift below.
11928 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11929 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11930 if (IsSigned && BitNo == SrcSize - 1)
11931 return false;
11932
11933 ExpectedValue <<= BitNo;
11934
11935 bool IsReversedCC = false;
11936 if (CmpValue != ExpectedValue) {
11937 if (!IsReversible)
11938 return false;
11939 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11940 if (!IsReversedCC)
11941 return false;
11942 }
11943
11944 Register DefReg = Def->getOperand(0).getReg();
11945 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11946 return false;
11947
11948 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11949 return false;
11950
11951 if (!MRI->use_nodbg_empty(DefReg)) {
11952 assert(!IsReversedCC);
11953 return true;
11954 }
11955
11956 // Replace AND with unused result with a S_BITCMP.
11957 MachineBasicBlock *MBB = Def->getParent();
11958
11959 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11960 : AMDGPU::S_BITCMP1_B32
11961 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11962 : AMDGPU::S_BITCMP1_B64;
11963
11964 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11965 .add(*SrcOp)
11966 .addImm(BitNo);
11967 Def->eraseFromParent();
11968
11969 return true;
11970 };
11971
11972 switch (CmpInstr.getOpcode()) {
11973 default:
11974 break;
11975 case AMDGPU::S_CMP_EQ_U32:
11976 case AMDGPU::S_CMP_EQ_I32:
11977 case AMDGPU::S_CMPK_EQ_U32:
11978 case AMDGPU::S_CMPK_EQ_I32:
11979 return optimizeCmpAnd(1, 32, true, false) ||
11980 optimizeCmpSelect(/*NeedInversion=*/true);
11981 case AMDGPU::S_CMP_GE_U32:
11982 case AMDGPU::S_CMPK_GE_U32:
11983 return optimizeCmpAnd(1, 32, false, false);
11984 case AMDGPU::S_CMP_GE_I32:
11985 case AMDGPU::S_CMPK_GE_I32:
11986 return optimizeCmpAnd(1, 32, false, true);
11987 case AMDGPU::S_CMP_EQ_U64:
11988 return optimizeCmpAnd(1, 64, true, false) ||
11989 optimizeCmpSelect(/*NeedInversion=*/true);
11990 case AMDGPU::S_CMP_LG_U32:
11991 case AMDGPU::S_CMP_LG_I32:
11992 case AMDGPU::S_CMPK_LG_U32:
11993 case AMDGPU::S_CMPK_LG_I32:
11994 return optimizeCmpAnd(0, 32, true, false) ||
11995 optimizeCmpSelect(/*NeedInversion=*/false);
11996 case AMDGPU::S_CMP_GT_U32:
11997 case AMDGPU::S_CMPK_GT_U32:
11998 return optimizeCmpAnd(0, 32, false, false);
11999 case AMDGPU::S_CMP_GT_I32:
12000 case AMDGPU::S_CMPK_GT_I32:
12001 return optimizeCmpAnd(0, 32, false, true);
12002 case AMDGPU::S_CMP_LG_U64:
12003 return optimizeCmpAnd(0, 64, true, false) ||
12004 optimizeCmpSelect(/*NeedInversion=*/false);
12005 }
12006
12007 return false;
12008}
12009
12011 AMDGPU::OpName OpName) const {
12012 if (!ST.needsAlignedVGPRs())
12013 return;
12014
12015 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
12016 if (OpNo < 0)
12017 return;
12018 MachineOperand &Op = MI.getOperand(OpNo);
12019 if (getOpSize(MI, OpNo) > 4)
12020 return;
12021
12022 // Add implicit aligned super-reg to force alignment on the data operand.
12023 const DebugLoc &DL = MI.getDebugLoc();
12024 MachineBasicBlock *BB = MI.getParent();
12026 Register DataReg = Op.getReg();
12027 bool IsAGPR = RI.isAGPR(MRI, DataReg);
12028 Register Undef = MRI.createVirtualRegister(
12029 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
12030 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
12031 Register NewVR =
12032 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
12033 : &AMDGPU::VReg_64_Align2RegClass);
12034 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
12035 .addReg(DataReg, {}, Op.getSubReg())
12036 .addImm(AMDGPU::sub0)
12037 .addReg(Undef)
12038 .addImm(AMDGPU::sub1);
12039 Op.setReg(NewVR);
12040 Op.setSubReg(AMDGPU::sub0);
12041 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
12042}
12043
12045 if (!SchedModel.hasInstrSchedModel())
12046 return 0;
12047
12048 // The repeat rate is the throughput-limiting resource occupancy: the largest
12049 // number of cycles any written processor resource is held.
12050 const MCSchedClassDesc *SCDesc = SchedModel.resolveSchedClass(&MI);
12051 unsigned RepeatRate = 0;
12053 PI = SchedModel.getWriteProcResBegin(SCDesc),
12054 PE = SchedModel.getWriteProcResEnd(SCDesc);
12055 PI != PE; ++PI) {
12056 RepeatRate = std::max(RepeatRate, (unsigned)PI->ReleaseAtCycle);
12057 }
12058
12059 return RepeatRate;
12060}
12061
12063 if (isIGLP(*MI))
12064 return false;
12065
12067}
12068
12070 if (!isWMMA(MI) && !isSWMMAC(MI))
12071 return false;
12072
12073 if (ST.hasGFX1250Insts())
12074 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
12075
12076 return true;
12077}
12078
12080 unsigned Opcode = MI.getOpcode();
12081
12082 if (AMDGPU::isGFX12Plus(ST))
12083 return isDOT(MI) || isXDLWMMA(MI);
12084
12085 if (!isMAI(MI) || isDGEMM(Opcode) ||
12086 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
12087 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
12088 return false;
12089
12090 if (!ST.hasGFX940Insts())
12091 return true;
12092
12093 return AMDGPU::getMAIIsGFX940XDL(Opcode);
12094}
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Shared AMDGPU asyncmark stage definitions.
uint64_t uint64_t
uint64_t Imm
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
AMDGPU Register Bank Select
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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...
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static bool isUndef(const MachineInstr &MI)
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t High
uint64_t IntrinsicInst * II
#define P(N)
R600 Clause Merge
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
This file declares the machine register scavenger class.
static cl::opt< bool > Fix16BitCopies("amdgpu-fix-16-bit-physreg-copies", cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"), cl::init(true), cl::ReallyHidden)
static void expandSGPRCopy(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RC, bool Forward)
static std::optional< std::pair< int64_t, int64_t > > getSelectConstants(const SIInstrInfo &TII, const MachineRegisterInfo &MRI, const MachineInstr &Sel)
If Sel is an S_CSELECT* of two different constants A and B, return them, truncated to the width of th...
static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc)
static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize)
static bool compareMachineOp(const MachineOperand &Op0, const MachineOperand &Op1)
static bool isStride64(unsigned Opc)
static MachineBasicBlock * generateWaterFallLoop(const SIInstrInfo &TII, MachineInstr &MI, ArrayRef< MachineOperand * > ScalarOps, MachineDominatorTree *MDT, MachineBasicBlock::iterator Begin=nullptr, MachineBasicBlock::iterator End=nullptr, ArrayRef< Register > PhySGPRs={})
#define GENERATE_RENAMED_GFX9_CASES(OPCODE)
static std::tuple< unsigned, unsigned > extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc)
static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx)
static bool followSubRegDef(MachineInstr &MI, TargetInstrInfo::RegSubRegPair &RSR)
static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize)
static MachineInstr * swapImmOperands(MachineInstr &MI, MachineOperand &NonRegOp1, MachineOperand &NonRegOp2)
static void copyFlagsToImplicitVCC(MachineInstr &MI, const MachineOperand &Orig)
static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, LocationSize WidthB, int OffsetB)
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, RegScavenger &RS, bool RegsOverlap, Register ImpUseSuperReg=Register())
Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908.
static unsigned getWWMRegSpillSaveOpcode(unsigned Size, bool IsVectorSuperClass)
static bool memOpsHaveSameBaseOperands(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getWWMRegSpillRestoreOpcode(unsigned Size, bool IsVectorSuperClass)
static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion, unsigned &NewDefOpc)
static bool isSCCDeadOnExit(MachineBasicBlock *MBB)
static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize)
static unsigned subtargetEncodingFamily(const GCNSubtarget &ST)
static void preserveCondRegFlags(MachineOperand &CondReg, const MachineOperand &OrigCond)
static Register findImplicitSGPRRead(const MachineInstr &MI)
static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc)
static cl::opt< unsigned > BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16), cl::desc("Restrict range of branch instructions (DEBUG)"))
static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getSGPRSpillRestoreOpcode(unsigned Size)
static bool isRegOrFI(const MachineOperand &MO)
static bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI)
Return true if MI is a VALU comparison, i.e.
static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static constexpr AMDGPU::OpName ModifierOpNames[]
static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const char *Msg="illegal VGPR to SGPR copy")
static MachineInstr * swapRegAndNonRegOperand(MachineInstr &MI, MachineOperand &RegOp, MachineOperand &NonRegOp)
static bool isLegalPkF32OpSel(const SIInstrInfo &TII, const MachineInstr &MI, bool CheckSwappedSrc=false)
static bool shouldReadExec(const MachineInstr &MI)
static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc)
static bool isRenamedInGFX9(int Opcode)
static TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd)
static std::tuple< unsigned, unsigned, unsigned > splitGlobalAddressRelocFlags(const GCNSubtarget &ST, const MachineOperand &SrcOp)
static bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
static bool nodesHaveSameOperandValue(SDNode *N0, SDNode *N1, AMDGPU::OpName OpName)
Returns true if both nodes have the same value for the given operand Op, or if both nodes do not have...
static unsigned getNumOperandsNoGlue(SDNode *Node)
static bool canRemat(const MachineInstr &MI)
static unsigned getAVSpillRestoreOpcode(unsigned Size)
static void emitLoadScalarOpsFromVGPRLoop(const SIInstrInfo &TII, MachineRegisterInfo &MRI, MachineBasicBlock &PredBB, MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={})
static unsigned getVGPRSpillRestoreOpcode(unsigned Size)
Interface definition for SIInstrInfo.
bool IsDead
const char * Msg
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:479
#define LLVM_DEBUG(...)
Definition Debug.h:119
static const LaneMaskConstants & get(const GCNSubtarget &ST)
static LLVM_ABI Semantics SemanticsToEnum(const llvm::fltSemantics &Sem)
Definition APFloat.cpp:185
Class for arbitrary precision integers.
Definition APInt.h:78
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
This class is the base class for the comparison instructions.
Definition InstrTypes.h:728
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A debug info location.
Definition DebugLoc.h:126
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:856
Diagnostic information for unsupported feature in backend.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:273
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:352
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
CycleRef getParentCycle(CycleRef C) const
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
Itinerary data supplied by a subtarget to be used by a target.
constexpr unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
A live range for subregisters.
LiveInterval - This class represents the liveness of a register, or stack slot.
iterator_range< subrange_iterator > subranges()
bool hasInterval(Register Reg) const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
LLVM_ABI bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
This class represents the liveness of a register, stack slot, etc.
bool hasValue() const
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:347
static const MCBinaryExpr * createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:417
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
unsigned getOpcode() const
Return the opcode number for this descriptor.
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition MCInstrDesc.h:88
uint8_t OperandType
Information about the type of the operand.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition MCInstrDesc.h:94
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void setVariableValue(const MCExpr *Value)
Definition MCSymbol.cpp:51
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
MIRFormater - Interface to format MIR operand based on target.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
void push_back(MachineInstr *MI)
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
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.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
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
@ LQR_Dead
Register is known to be fully dead.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isImmutableObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an immutable object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
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)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
bool isCopy() const
const MachineBasicBlock * getParent() const
LLVM_ABI void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
bool isBundle() const
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromBundle()
Unlink 'this' from its basic block and delete it.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mop_range explicit_operands()
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just after the instruction itself.
LLVM_ABI void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo)
Clear all kill flags affecting Reg.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
const GlobalValue * getGlobal() const
LLVM_ABI void ChangeToFrameIndex(int Idx, unsigned TargetFlags=0)
Replace this operand with a frame index.
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
LLVM_ABI void ChangeToGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
ChangeToGA - Replace this operand with a new global address operand.
void setIsKill(bool Val=true)
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
void setOffset(int64_t Offset)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
bool isEarlyClobber() const
Register getReg() const
getReg - Returns the register number.
bool isTargetIndex() const
isTargetIndex - Tests if this is a MO_TargetIndex operand.
void setTargetFlags(unsigned F)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
const MachineFunction & getMF() const
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
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
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
bool isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
unsigned getGFX1250BlockingCyclesTable(const MachineInstr &MI) const
GFX1250 blocking-cycles table lookup with no occupancy subtarget gate.
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const final
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
static bool isDOT(const MachineInstr &MI)
std::unique_ptr< PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
static bool usesTENSOR_CNT(const MachineInstr &MI)
bool hasModifiers(unsigned Opcode) const
Return true if this instruction has any modifiers.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
static bool isSWMMAC(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
bool isWave32() const
bool isHighLatencyDef(int Opc) const override
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const
Legalize the OpIndex operand of this instruction by inserting a MOV.
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isVOPC(const MachineInstr &MI)
void removeModOperands(MachineInstr &MI) const
unsigned getRepeatRate(const MachineInstr &MI) const
Get the repeat rate for a VALU instruction from the scheduling model.
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool isLegalSingleSGPRReadInstOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for a single-SGPR-read instruction.
bool isXDL(const MachineInstr &MI) const
Register isStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
static bool isVIMAGE(const MachineInstr &MI)
void enforceOperandRCAlignment(MachineInstr &MI, AMDGPU::OpName OpName) const
static bool isSOP2(const MachineInstr &MI)
static bool isGWS(const MachineInstr &MI)
bool hasRAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI) const
bool isLegalAV64PseudoImm(uint64_t Imm) const
Check if this immediate value can be used for AV_MOV_B64_IMM_PSEUDO.
bool isNeverCoissue(MachineInstr &MI) const
static bool isBUF(const MachineInstr &MI)
bool isNonCommutableDPP(const MachineInstr &MI) const
void handleCopyToPhysHelper(SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst, MachineRegisterInfo &MRI, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
bool hasModifiersSet(const MachineInstr &MI, AMDGPU::OpName OpName) const
bool isLegalToSwap(const MachineInstr &MI, unsigned fromIdx, unsigned toIdx) const
static bool isFLATGlobal(const MachineInstr &MI)
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isGlobalMemoryObject(const MachineInstr *MI) const override
bool canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, SelectExpansion &Exp) const override
static bool isVSAMPLE(const MachineInstr &MI)
bool isBufferSMRD(const MachineInstr &MI) const
static bool isKillTerminator(unsigned Opcode)
bool isVOPDAntidependencyAllowed(const MachineInstr &MI) const
If OpX is multicycle, anti-dependencies are not allowed.
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
void insertScratchExecCopy(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, bool IsSCCLive, SlotIndexes *Indexes=nullptr) const
bool hasVALU32BitEncoding(unsigned Opcode) const
Return true if this 64-bit VALU instruction has a 32-bit encoding.
unsigned getBlockingCycles(const MachineInstr &MI) const
unsigned getMovOpcode(const TargetRegisterClass *DstRC) const
Register isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
unsigned buildExtractSubReg(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const
Legalize operands in MI by either commuting it or inserting a copy of src1.
static bool isVPermPk16(unsigned Opcode)
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const final
static bool isTRANS(const MachineInstr &MI)
static bool isImage(const MachineInstr &MI)
static bool isSOPK(const MachineInstr &MI)
const TargetRegisterClass * getOpRegClass(const MachineInstr &MI, unsigned OpNo) const
Return the correct register class for OpNo.
MachineBasicBlock * insertSimulatedTrap(MachineRegisterInfo &MRI, MachineBasicBlock &MBB, MachineInstr &MI, const DebugLoc &DL) const
Build instructions that simulate the behavior of a s_trap 2 instructions for hardware (namely,...
static unsigned getNonSoftWaitcntOpcode(unsigned Opcode)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static bool isFoldableCopy(const MachineInstr &MI)
static bool isMUBUF(const MachineInstr &MI)
bool expandPostRAPseudo(MachineInstr &MI) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
void createWaterFallForSiCall(MachineInstr *MI, MachineDominatorTree *MDT, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={}) const
Wrapper function for generating waterfall for instruction MI This function take into consideration of...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
AMDGPU::AsyncStages getAsyncStage(const MachineInstr &MI) const
static bool isSegmentSpecificFLAT(const MachineInstr &MI)
bool isReMaterializableImpl(const MachineInstr &MI) const override
static bool isVOP3(const MCInstrDesc &Desc)
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool physRegUsesConstantBus(const MachineOperand &Reg) const
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
bool mayAccessVMEMThroughFlat(const MachineInstr &MI) const
static bool isDPP(const MachineInstr &MI)
bool analyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
static bool isMFMA(const MachineInstr &MI)
bool isLowLatencyInstruction(const MachineInstr &MI) const
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is a instruction that moves/copies value from one register to ano...
void mutateAndCleanupImplicit(MachineInstr &MI, const MCInstrDesc &NewDesc) const
ValueUniformity getGenericValueUniformity(const MachineInstr &MI) const
static bool isMAI(const MCInstrDesc &Desc)
static bool isSrc1DPPRevOpcode(const GCNSubtarget &ST, uint32_t Opcode)
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const override
static bool usesLGKM_CNT(const MachineInstr &MI)
void legalizeOperandsVALUt16(MachineInstr &Inst, MachineRegisterInfo &MRI) const
Fix operands in Inst to fix 16bit SALU to VALU lowering.
bool isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo, const MachineOperand &MO) const
bool canShrink(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
const MachineOperand & getCalleeOperand(const MachineInstr &MI) const override
bool isAsmOnlyOpcode(int MCOp) const
Check if this instruction should only be used by assembler.
bool isAlwaysGDS(uint32_t Opcode) const
static bool isVGPRSpill(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
This is used by the post-RA scheduler (SchedulePostRAList.cpp).
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
unsigned getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr &MI, unsigned *PredCost=nullptr) const override
unsigned getVectorRegSpillSaveOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI, bool NeedsCFI) const
int64_t getNamedImmOperand(const MachineInstr &MI, AMDGPU::OpName OperandName) const
Get required immediate operand.
ArrayRef< std::pair< int, const char * > > getSerializableTargetIndices() const override
bool regUsesConstantBus(const MachineOperand &Reg, const MachineRegisterInfo &MRI) const
static bool isMIMG(const MachineInstr &MI)
MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isLegalRegOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO (a register operand) is a legal register for the given operand description or operand ind...
static unsigned getNumWaitStates(const MachineInstr &MI)
Return the number of wait states that result from executing this instruction.
unsigned getVALUOp(const MachineInstr &MI) const
static bool modifiesModeRegister(const MachineInstr &MI)
Return true if the instruction modifies the mode register.q.
Register readlaneVGPRToSGPR(Register SrcReg, MachineInstr &UseMI, MachineRegisterInfo &MRI, const TargetRegisterClass *DstRC=nullptr) const
Copy a value from a VGPR (SrcReg) to SGPR.
bool hasDivergentBranch(const MachineBasicBlock *MBB) const
Return whether the block terminate with divergent branch.
std::pair< int64_t, int64_t > splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Split COffsetVal into {immediate offset field, remainder offset} values.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void fixImplicitOperands(MachineInstr &MI) const
bool moveFlatAddrToVGPR(MachineInstr &Inst) const
Change SADDR form of a FLAT Inst to its VADDR form if saddr operand was moved to VGPR.
static bool usesASYNC_CNT(const MachineInstr &MI)
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool isMaskedByExec(Register Reg, const MachineInstr &Use, const MachineRegisterInfo &MRI, unsigned Depth=0) const
Return true if Reg is a lane mask that already has 0 in every bit corresponding to a lane that is ina...
void createReadFirstLaneFromCopyToPhysReg(MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const
bool swapSourceModifiers(MachineInstr &MI, MachineOperand &Src0, AMDGPU::OpName Src0OpName, MachineOperand &Src1, AMDGPU::OpName Src1OpName) const
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
bool isAsync(const MachineInstr &MI) const
bool memOpsHaveSameBase(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2) const
Return true if the memory operations described by BaseOps1 and BaseOps2 (as returned by getMemOperand...
bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const
This function is used to determine if an instruction can be safely executed under EXEC = 0 without ha...
bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg, int64_t &ImmVal) const override
static bool isAtomic(const MachineInstr &MI)
bool isLiteralOperandLegal(const MCInstrDesc &InstDesc, const MCOperandInfo &OpInfo) const
static bool isWWMRegSpillOpcode(uint32_t Opcode)
static bool sopkIsZext(unsigned Opcode)
static bool isSGPRSpill(const MachineInstr &MI)
static bool isWMMA(const MachineInstr &MI)
ArrayRef< std::pair< MachineMemOperand::Flags, const char * > > getSerializableMachineMemOperandTargetFlags() const override
bool mayReadEXEC(const MachineRegisterInfo &MRI, const MachineInstr &MI) const
Returns true if the instruction could potentially depend on the value of exec.
void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
std::pair< MachineInstr *, MachineInstr * > expandMovDPP64(MachineInstr &MI) const
static bool isSOPC(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
bool isBarrier(unsigned Opcode) const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx0, unsigned OpIdx1) const override
bool mayAccessLDSThroughFlat(const MachineInstr &MI, bool TgSplit) const
int pseudoToMCOpcode(int Opcode) const
Return a target-specific opcode if Opcode is a pseudo instruction.
const MCInstrDesc & getMCOpcodeFromPseudo(unsigned Opcode) const
Return the descriptor of the target-specific machine instruction that corresponds to the specified ps...
static bool usesVM_CNT(const MachineInstr &MI)
MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const override
static bool isFixedSize(const MachineInstr &MI)
bool isSafeToSink(MachineInstr &MI, MachineBasicBlock *SuccToSinkTo, MachineCycleInfo *CI) const override
LLVM_READONLY int commuteOpcode(unsigned Opc) const
ValueUniformity getValueUniformity(const MachineInstr &MI) const final
uint64_t getScratchRsrcWords23() const
LLVM_READONLY MachineOperand * getNamedOperand(MachineInstr &MI, AMDGPU::OpName OperandName) const
Returns the operand named Op.
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveIntervals *LIS) const override
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx, const MachineOperand *MO=nullptr) const
Check if MO is a legal operand if it was the OpIdx Operand for MI.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool allowNegativeFlatOffset(AMDGPU::FlatAddrSpace FlatVariant) const
Returns true if negative offsets are allowed for the given FlatVariant.
void moveToVALUImpl(SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
static bool isLDSDMA(const MachineInstr &MI)
static bool isVOP1(const MachineInstr &MI)
SIInstrInfo(const GCNSubtarget &ST)
std::optional< int64_t > getImmOrMaterializedImm(const MachineRegisterInfo &MRI, const MachineOperand &Op, MachineInstr **DefMI=nullptr) const
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool hasAnyModifiersSet(const MachineInstr &MI) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
void setHasSpilledVGPRs(bool Spill=true)
bool isWWMReg(Register Reg) const
bool checkFlag(Register Reg, uint8_t Flag) const
void setHasSpilledSGPRs(bool Spill=true)
unsigned getScratchReservedForDynamicVGPRs() const
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
static unsigned getSubRegFromChannel(uint64_t Channel, uint64_t NumRegs=1)
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:70
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndexes pass.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:295
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
int64_t getImm() const
Register getReg() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Object returned by analyzeLoopForPipelining.
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:352
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:210
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:188
self_iterator getIterator()
Definition ilist_node.h:123
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
constexpr bool isValidAsyncStageMask(int64_t Mask)
AsyncStages
Bit mask of the async stages tracked by the asyncmark / wait_asyncmark intrinsics.
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi, bool *IsBF16)
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
@ OPERAND_REG_IMM_V2FP64
Definition SIDefines.h:441
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:459
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:426
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:434
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:450
@ OPERAND_REG_IMM_NOINLINE_FP16
Definition SIDefines.h:432
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:447
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:452
@ OPERAND_REG_IMM_V2INT64
Definition SIDefines.h:437
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:436
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:430
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:425
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:433
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:431
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:435
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:446
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:444
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:438
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:429
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:453
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:464
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:465
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:439
@ OPERAND_SDWA_VOPC_DST
Definition SIDefines.h:476
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:428
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:449
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:445
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:451
@ OPERAND_INLINE_C_AV64_PSEUDO
Definition SIDefines.h:470
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:440
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:466
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:448
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:427
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:456
LLVM_READONLY int32_t getBasicFromSDWAOp(uint32_t Opcode)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
@ TI_SCRATCH_RSRC_DWORD1
Definition AMDGPU.h:667
@ TI_SCRATCH_RSRC_DWORD3
Definition AMDGPU.h:669
@ TI_SCRATCH_RSRC_DWORD0
Definition AMDGPU.h:666
@ TI_SCRATCH_RSRC_DWORD2
Definition AMDGPU.h:668
@ TI_CONSTDATA_START
Definition AMDGPU.h:665
bool isSingleSGPRReadInst(unsigned Opc)
Packed instructions that read a single SGPR for SGPR operands, except for 64-bit elements which read ...
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
const uint64_t RSRC_INDEX_STRIDE_SHIFT
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition CallingConv.h:41
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ OPERAND_GENERIC_4
Definition MCInstrDesc.h:71
@ OPERAND_GENERIC_2
Definition MCInstrDesc.h:69
@ OPERAND_GENERIC_1
Definition MCInstrDesc.h:68
@ OPERAND_GENERIC_3
Definition MCInstrDesc.h:70
@ OPERAND_IMMEDIATE
Definition MCInstrDesc.h:61
@ OPERAND_GENERIC_0
Definition MCInstrDesc.h:67
@ OPERAND_GENERIC_5
Definition MCInstrDesc.h:72
Not(const Pred &P) -> Not< Pred >
constexpr bool isSDWA(const T &...O)
Definition SIDefines.h:249
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
Definition Threading.h:280
@ Offset
Definition DWP.cpp:577
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
constexpr uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
Definition MathExtras.h:208
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
static const MachineMemOperand::Flags MOCFSB1
Definition SIInstrInfo.h:75
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:546
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
Op::Description Desc
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg)
Return the SubReg component from REG_SEQUENCE.
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:49
constexpr bool has_single_bit(T Value) noexcept
Definition bit.h:149
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
MachineInstr * getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, const MachineRegisterInfo &MRI)
Return the defining instruction for a given reg:subreg pair skipping copy like instructions and subre...
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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
LLVM_ABI VirtRegInfo AnalyzeVirtRegInBundle(MachineInstr &MI, Register Reg, SmallVectorImpl< std::pair< MachineInstr *, unsigned > > *Ops=nullptr)
AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses a virtual register.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
Definition SIInstrInfo.h:57
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
Definition SIInstrInfo.h:45
constexpr unsigned BitWidth
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition SIInstrInfo.h:53
constexpr T reverseBits(T Val)
Reverse the bits in Val.
Definition MathExtras.h:119
static const MachineMemOperand::Flags MOCFSB0
Use two MMO flags to encode the 2-bit cache fill size field for GFX13+.
Definition SIInstrInfo.h:72
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:572
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320
constexpr RegState getUndefRegState(bool B)
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
Definition Uniformity.h:18
@ AlwaysUniform
The result value is always uniform.
Definition Uniformity.h:23
@ NeverUniform
The result value can never be assumed to be uniform.
Definition Uniformity.h:26
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
Definition SIInstrInfo.h:68
bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI)
Return false if EXEC is not changed between the def of VReg at DefMI and all its uses.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr bool all() const
Definition LaneBitmask.h:54
This represents a simple continuous liveness interval for a value.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:124
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Utility to store machine instructions worklist.
Definition SIInstrInfo.h:79
MachineInstr * top() const
Definition SIInstrInfo.h:84
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
void insert(MachineInstr *MI)
A pair composed of a register and a sub-register index.
VirtRegInfo - Information about a virtual register used by a set of operands.
bool Reads
Reads - One of the operands read the virtual register.
bool Writes
Writes - One of the operands writes the virtual register.