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"
37#include <tuple>
38
39using namespace llvm;
40
41#define DEBUG_TYPE "si-instr-info"
42
43#define GET_INSTRINFO_CTOR_DTOR
44#include "AMDGPUGenInstrInfo.inc"
45
46namespace llvm::AMDGPU {
47#define GET_ImageDimIntrinsicTable_IMPL
48#define GET_RsrcIntrinsics_IMPL
49#define GET_GFX1250BlockingCyclesTable_DECL
50#define GET_GFX1250BlockingCyclesTable_IMPL
51
56
57#include "AMDGPUGenSearchableTables.inc"
58} // namespace llvm::AMDGPU
59
60// Must be at least 4 to be able to branch over minimum unconditional branch
61// code. This is only for making it possible to write reasonably small tests for
62// long branches.
64BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16),
65 cl::desc("Restrict range of branch instructions (DEBUG)"));
66
68 "amdgpu-fix-16-bit-physreg-copies",
69 cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"),
70 cl::init(true),
72
74 : AMDGPUGenInstrInfo(ST, RI, AMDGPU::ADJCALLSTACKUP,
75 AMDGPU::ADJCALLSTACKDOWN),
76 RI(ST), ST(ST) {
77 SchedModel.init(&ST);
78}
79
80//===----------------------------------------------------------------------===//
81// TargetInstrInfo callbacks
82//===----------------------------------------------------------------------===//
83
84static unsigned getNumOperandsNoGlue(SDNode *Node) {
85 unsigned N = Node->getNumOperands();
86 while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
87 --N;
88 return N;
89}
90
91/// Returns true if both nodes have the same value for the given
92/// operand \p Op, or if both nodes do not have this operand.
94 AMDGPU::OpName OpName) {
95 unsigned Opc0 = N0->getMachineOpcode();
96 unsigned Opc1 = N1->getMachineOpcode();
97
98 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName);
99 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName);
100
101 if (Op0Idx == -1 && Op1Idx == -1)
102 return true;
103
104
105 if ((Op0Idx == -1 && Op1Idx != -1) ||
106 (Op1Idx == -1 && Op0Idx != -1))
107 return false;
108
109 // getNamedOperandIdx returns the index for the MachineInstr's operands,
110 // which includes the result as the first operand. We are indexing into the
111 // MachineSDNode's operands, so we need to skip the result operand to get
112 // the real index.
113 --Op0Idx;
114 --Op1Idx;
115
116 return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx);
117}
118
119static bool canRemat(const MachineInstr &MI) {
120
124 return true;
125
126 if (SIInstrInfo::isSMRD(MI)) {
127 return !MI.memoperands_empty() &&
128 llvm::all_of(MI.memoperands(), [](const MachineMemOperand *MMO) {
129 return MMO->isLoad() && MMO->isInvariant();
130 });
131 }
132
133 return false;
134}
135
136// Split relocation flags for 64-bit global-address materialization into a
137// common base and the hi/lo relocation variants.
138static std::tuple<unsigned, unsigned, unsigned>
140 const MachineOperand &SrcOp) {
141 const unsigned BaseFlags = SrcOp.getTargetFlags() & ~SIInstrInfo::MO_MASK;
142 const unsigned Reloc = SrcOp.getTargetFlags() & SIInstrInfo::MO_MASK;
143
144 // Infer the relocation type from the existing flags on the global operand.
145 // The relocation type should have been determined earlier in the pipeline.
146 unsigned LoReloc, HiReloc;
147 switch (Reloc) {
151 LoReloc = SIInstrInfo::MO_REL32_LO;
152 HiReloc = SIInstrInfo::MO_REL32_HI;
153 break;
158 break;
161 // For 64-bit GOT-relative, use the 64-bit relocation.
164 break;
168 LoReloc = SIInstrInfo::MO_ABS32_LO;
169 HiReloc = SIInstrInfo::MO_ABS32_HI;
170 break;
171 default:
172 llvm_unreachable("unknown relocation type for global address");
173 break;
174 }
175
176 return {BaseFlags, LoReloc, HiReloc};
177}
178
180 const MachineInstr &MI) const {
181
182 if (canRemat(MI)) {
183 // Normally VALU use of exec would block the rematerialization, but that
184 // is OK in this case to have an implicit exec read as all VALU do.
185 // We really want all of the generic logic for this except for this.
186
187 // Another potential implicit use is mode register. The core logic of
188 // the RA will not attempt rematerialization if mode is set anywhere
189 // in the function, otherwise it is safe since mode is not changed.
190
191 // There is difference to generic method which does not allow
192 // rematerialization if there are virtual register uses. We allow this,
193 // therefore this method includes SOP instructions as well.
194 if (!MI.hasImplicitDef() &&
195 MI.getNumImplicitOperands() == MI.getDesc().implicit_uses().size() &&
196 !MI.mayRaiseFPException())
197 return true;
198 }
199
200 // Everything below copied from TargetInstrInfo::isReMaterializableImpl. The
201 // only difference is that we allow operations that perform read-modify-write
202 // on sub-registers.
203
204 // Remat clients assume operand 0 is the defined register.
205 if (!MI.getNumOperands() || !MI.getOperand(0).isReg())
206 return false;
207 Register DefReg = MI.getOperand(0).getReg();
208
209 const MachineFunction &MF = *MI.getMF();
210
211 // A load from a fixed stack slot can be rematerialized. This may be
212 // redundant with subsequent checks, but it's target-independent,
213 // simple, and a common case.
214 int FrameIdx = 0;
215 if (isLoadFromStackSlot(MI, FrameIdx) &&
217 return true;
218
219 // Avoid instructions obviously unsafe for remat.
220 if (MI.isNotDuplicable() || MI.mayStore() || MI.mayRaiseFPException() ||
221 MI.hasUnmodeledSideEffects())
222 return false;
223
224 // Don't remat inline asm. We have no idea how expensive it is
225 // even if it's side effect free.
226 if (MI.isInlineAsm())
227 return false;
228
229 // Avoid instructions which load from potentially varying memory.
230 if (MI.mayLoad() && !MI.isDereferenceableInvariantLoad())
231 return false;
232
233 const MachineRegisterInfo &MRI = MF.getRegInfo();
234
235 // If any of the registers accessed are non-constant, conservatively assume
236 // the instruction is not rematerializable.
237 for (const MachineOperand &MO : MI.operands()) {
238 if (!MO.isReg())
239 continue;
240 Register Reg = MO.getReg();
241 if (Reg == 0)
242 continue;
243
244 // Check for a well-behaved physical register.
245 if (Reg.isPhysical()) {
246 if (MO.isUse()) {
247 // If the physreg has no defs anywhere, it's just an ambient register
248 // and we can freely move its uses. Alternatively, if it's allocatable,
249 // it could get allocated to something with a def during allocation.
250 if (!MRI.isConstantPhysReg(Reg))
251 return false;
252 } else {
253 // A physreg def. We can't remat it.
254 return false;
255 }
256 continue;
257 }
258
259 // Only allow one virtual-register def. There may be multiple defs of the
260 // same virtual register, though.
261 if (MO.isDef() && Reg != DefReg)
262 return false;
263 }
264
265 return true;
266}
267
269 switch (Opcode) {
270 // v_subrev_u16 (gfx9)
271 case AMDGPU::V_SUBREV_U16_e32:
272 case AMDGPU::V_SUBREV_U16_e64:
273 // v_subrev_u32 (gfx9) / v_subrev_nc_u32 (gfx10+)
274 case AMDGPU::V_SUBREV_U32_e32:
275 case AMDGPU::V_SUBREV_U32_e64:
276 // v_subrev_co_u32
277 case AMDGPU::V_SUBREV_CO_U32_e32:
278 case AMDGPU::V_SUBREV_CO_U32_e64:
279 // v_subbrev_u32 (gfx9) / v_subrev_co_ci_u32 (gfx10+)
280 case AMDGPU::V_SUBBREV_U32_e32:
281 case AMDGPU::V_SUBBREV_U32_e64:
282 return true;
283 // REV shift opcodes worked this way before GFX11, verified on hardware
284 case AMDGPU::V_ASHRREV_I16_e32:
285 case AMDGPU::V_ASHRREV_I16_e64:
286 case AMDGPU::V_ASHRREV_I32_e32:
287 case AMDGPU::V_ASHRREV_I32_e64:
288 case AMDGPU::V_ASHRREV_I64_e64:
289 case AMDGPU::V_LSHLREV_B16_e32:
290 case AMDGPU::V_LSHLREV_B16_e64:
291 case AMDGPU::V_LSHLREV_B32_e32:
292 case AMDGPU::V_LSHLREV_B32_e64:
293 case AMDGPU::V_LSHLREV_B64_e64:
294 case AMDGPU::V_LSHRREV_B16_e32:
295 case AMDGPU::V_LSHRREV_B16_e64:
296 case AMDGPU::V_LSHRREV_B32_e32:
297 case AMDGPU::V_LSHRREV_B32_e64:
298 case AMDGPU::V_LSHRREV_B64_e64:
299 return !ST.hasGFX11Insts();
300 default:
301 return false;
302 }
303}
304
305// Returns true if the result of a VALU instruction depends on exec.
306bool SIInstrInfo::resultDependsOnExec(const MachineInstr &MI) const {
307 assert(isVALU(MI, /*AllowLDSDMA=*/true));
308
309 // If it is convergent it depends on EXEC.
310 if (MI.isConvergent())
311 return true;
312
313 // If it defines an SGPR it depends on EXEC, unless it's dead.
314 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
315 for (const MachineOperand &Def : MI.defs()) {
316 if (Def.isDead())
317 continue;
318
319 Register Reg = Def.getReg();
320 if (Reg && RI.isSGPRReg(MRI, Reg))
321 return true;
322 }
323
324 return false;
325}
326
327bool SIInstrInfo::isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const {
328 const MachineOperand &MO = MI.getOperand(OpIdx);
329 // Any implicit use of exec by VALU is not a real register read.
330 return MO.getReg() == AMDGPU::EXEC && MO.isImplicit() &&
331 isVALU(MI, /*AllowLDSDMA=*/true) && !resultDependsOnExec(MI);
332}
333
335 MachineBasicBlock *SuccToSinkTo,
336 MachineCycleInfo *CI) const {
337 // Allow sinking if MI edits lane mask (divergent i1 in sgpr).
338 if (MI.getOpcode() == AMDGPU::SI_IF_BREAK)
339 return true;
340
341 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
342 // Check if sinking of MI would create temporal divergent use.
343 for (auto Op : MI.uses()) {
344 if (Op.isReg() && Op.getReg().isVirtual() &&
345 RI.isSGPRClass(MRI.getRegClass(Op.getReg()))) {
346 MachineInstr *SgprDef = MRI.getVRegDef(Op.getReg());
347 if (!SgprDef)
348 continue;
349
350 // SgprDef defined inside cycle
351 CycleRef FromCycle = CI->getCycle(SgprDef->getParent());
352 if (!FromCycle)
353 continue;
354
355 CycleRef ToCycle = CI->getCycle(SuccToSinkTo);
356 // Check if there is a FromCycle that contains SgprDef's basic block but
357 // does not contain SuccToSinkTo and also has divergent exit condition.
358 while (FromCycle && !(ToCycle && CI->contains(FromCycle, ToCycle))) {
360 CI->getExitingBlocks(FromCycle, ExitingBlocks);
361
362 // FromCycle has divergent exit condition.
363 for (MachineBasicBlock *ExitingBlock : ExitingBlocks) {
364 if (hasDivergentBranch(ExitingBlock))
365 return false;
366 }
367
368 FromCycle = CI->getParentCycle(FromCycle);
369 }
370 }
371 }
372
373 return true;
374}
375
377 int64_t &Offset0,
378 int64_t &Offset1) const {
379 if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode())
380 return false;
381
382 unsigned Opc0 = Load0->getMachineOpcode();
383 unsigned Opc1 = Load1->getMachineOpcode();
384
385 // Make sure both are actually loads.
386 if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad())
387 return false;
388
389 // A mayLoad instruction without a def is not a load. Likely a prefetch.
390 if (!get(Opc0).getNumDefs() || !get(Opc1).getNumDefs())
391 return false;
392
393 if (isDS(Opc0) && isDS(Opc1)) {
394
395 // FIXME: Handle this case:
396 if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1))
397 return false;
398
399 // Check base reg.
400 if (Load0->getOperand(0) != Load1->getOperand(0))
401 return false;
402
403 // Skip read2 / write2 variants for simplicity.
404 // TODO: We should report true if the used offsets are adjacent (excluded
405 // st64 versions).
406 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
407 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
408 if (Offset0Idx == -1 || Offset1Idx == -1)
409 return false;
410
411 // XXX - be careful of dataless loads
412 // getNamedOperandIdx returns the index for MachineInstrs. Since they
413 // include the output in the operand list, but SDNodes don't, we need to
414 // subtract the index by one.
415 Offset0Idx -= get(Opc0).NumDefs;
416 Offset1Idx -= get(Opc1).NumDefs;
417 Offset0 = Load0->getConstantOperandVal(Offset0Idx);
418 Offset1 = Load1->getConstantOperandVal(Offset1Idx);
419 return true;
420 }
421
422 if (isSMRD(Opc0) && isSMRD(Opc1)) {
423 // Skip time and cache invalidation instructions.
424 if (!AMDGPU::hasNamedOperand(Opc0, AMDGPU::OpName::sbase) ||
425 !AMDGPU::hasNamedOperand(Opc1, AMDGPU::OpName::sbase))
426 return false;
427
428 unsigned NumOps = getNumOperandsNoGlue(Load0);
429 if (NumOps != getNumOperandsNoGlue(Load1))
430 return false;
431
432 // Check base reg.
433 if (Load0->getOperand(0) != Load1->getOperand(0))
434 return false;
435
436 // Match register offsets, if both register and immediate offsets present.
437 assert(NumOps == 4 || NumOps == 5);
438 if (NumOps == 5 && Load0->getOperand(1) != Load1->getOperand(1))
439 return false;
440
441 const ConstantSDNode *Load0Offset =
443 const ConstantSDNode *Load1Offset =
445
446 if (!Load0Offset || !Load1Offset)
447 return false;
448
449 Offset0 = Load0Offset->getZExtValue();
450 Offset1 = Load1Offset->getZExtValue();
451 return true;
452 }
453
454 // MUBUF and MTBUF can access the same addresses.
455 if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) {
456
457 // MUBUF and MTBUF have vaddr at different indices.
458 if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) ||
459 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) ||
460 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc))
461 return false;
462
463 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
464 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
465
466 if (OffIdx0 == -1 || OffIdx1 == -1)
467 return false;
468
469 // getNamedOperandIdx returns the index for MachineInstrs. Since they
470 // include the output in the operand list, but SDNodes don't, we need to
471 // subtract the index by one.
472 OffIdx0 -= get(Opc0).NumDefs;
473 OffIdx1 -= get(Opc1).NumDefs;
474
475 SDValue Off0 = Load0->getOperand(OffIdx0);
476 SDValue Off1 = Load1->getOperand(OffIdx1);
477
478 // The offset might be a FrameIndexSDNode.
479 if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1))
480 return false;
481
482 Offset0 = Off0->getAsZExtVal();
483 Offset1 = Off1->getAsZExtVal();
484 return true;
485 }
486
487 return false;
488}
489
490static bool isStride64(unsigned Opc) {
491 switch (Opc) {
492 case AMDGPU::DS_READ2ST64_B32:
493 case AMDGPU::DS_READ2ST64_B64:
494 case AMDGPU::DS_WRITE2ST64_B32:
495 case AMDGPU::DS_WRITE2ST64_B64:
496 return true;
497 default:
498 return false;
499 }
500}
501
504 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const {
505 if (!LdSt.mayLoadOrStore())
506 return false;
507
508 unsigned Opc = LdSt.getOpcode();
509 OffsetIsScalable = false;
510 const MachineOperand *BaseOp, *OffsetOp;
511 int DataOpIdx;
512
513 if (isDS(LdSt)) {
514 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr);
515 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
516 if (OffsetOp) {
517 // Normal, single offset LDS instruction.
518 if (!BaseOp) {
519 // DS_CONSUME/DS_APPEND use M0 for the base address.
520 // TODO: find the implicit use operand for M0 and use that as BaseOp?
521 return false;
522 }
523 BaseOps.push_back(BaseOp);
524 Offset = OffsetOp->getImm();
525 // Get appropriate operand, and compute width accordingly.
526 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
527 if (DataOpIdx == -1)
528 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
529 if (Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
530 Width = LocationSize::precise(64);
531 else
532 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
533 } else {
534 // The 2 offset instructions use offset0 and offset1 instead. We can treat
535 // these as a load with a single offset if the 2 offsets are consecutive.
536 // We will use this for some partially aligned loads.
537 const MachineOperand *Offset0Op =
538 getNamedOperand(LdSt, AMDGPU::OpName::offset0);
539 const MachineOperand *Offset1Op =
540 getNamedOperand(LdSt, AMDGPU::OpName::offset1);
541
542 unsigned Offset0 = Offset0Op->getImm() & 0xff;
543 unsigned Offset1 = Offset1Op->getImm() & 0xff;
544 if (Offset0 + 1 != Offset1)
545 return false;
546
547 // Each of these offsets is in element sized units, so we need to convert
548 // to bytes of the individual reads.
549
550 unsigned EltSize;
551 if (LdSt.mayLoad())
552 EltSize = RI.getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16;
553 else {
554 assert(LdSt.mayStore());
555 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
556 EltSize = RI.getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8;
557 }
558
559 if (isStride64(Opc))
560 EltSize *= 64;
561
562 BaseOps.push_back(BaseOp);
563 Offset = EltSize * Offset0;
564 // Get appropriate operand(s), and compute width accordingly.
565 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
566 if (DataOpIdx == -1) {
567 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
568 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
569 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
570 Width = LocationSize::precise(
571 Width.getValue() + TypeSize::getFixed(getOpSize(LdSt, DataOpIdx)));
572 } else {
573 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
574 }
575 }
576 return true;
577 }
578
579 if (isMUBUF(LdSt) || isMTBUF(LdSt)) {
580 const MachineOperand *RSrc = getNamedOperand(LdSt, AMDGPU::OpName::srsrc);
581 if (!RSrc) // e.g. BUFFER_WBINVL1_VOL
582 return false;
583 BaseOps.push_back(RSrc);
584 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
585 if (BaseOp && !BaseOp->isFI())
586 BaseOps.push_back(BaseOp);
587 const MachineOperand *OffsetImm =
588 getNamedOperand(LdSt, AMDGPU::OpName::offset);
589 Offset = OffsetImm->getImm();
590 const MachineOperand *SOffset =
591 getNamedOperand(LdSt, AMDGPU::OpName::soffset);
592 if (SOffset) {
593 if (SOffset->isReg())
594 BaseOps.push_back(SOffset);
595 else
596 Offset += SOffset->getImm();
597 }
598 // Get appropriate operand, and compute width accordingly.
599 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
600 if (DataOpIdx == -1)
601 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
602 if (DataOpIdx == -1) // LDS DMA
603 return false;
604 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
605 return true;
606 }
607
608 if (isImage(LdSt)) {
609 auto RsrcOpName =
610 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
611 int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RsrcOpName);
612 BaseOps.push_back(&LdSt.getOperand(SRsrcIdx));
613 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
614 if (VAddr0Idx >= 0) {
615 // GFX10 possible NSA encoding.
616 for (int I = VAddr0Idx; I < SRsrcIdx; ++I)
617 BaseOps.push_back(&LdSt.getOperand(I));
618 } else {
619 BaseOps.push_back(getNamedOperand(LdSt, AMDGPU::OpName::vaddr));
620 }
621 Offset = 0;
622 // Get appropriate operand, and compute width accordingly.
623 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
624 if (DataOpIdx == -1)
625 return false; // no return sampler
626 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
627 return true;
628 }
629
630 if (isSMRD(LdSt)) {
631 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::sbase);
632 if (!BaseOp) // e.g. S_MEMTIME
633 return false;
634 BaseOps.push_back(BaseOp);
635 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
636 Offset = OffsetOp ? OffsetOp->getImm() : 0;
637 // Get appropriate operand, and compute width accordingly.
638 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
639 if (DataOpIdx == -1)
640 return false;
641 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
642 return true;
643 }
644
645 if (isFLAT(LdSt)) {
646 // Instructions have either vaddr or saddr or both or none.
647 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
648 if (BaseOp)
649 BaseOps.push_back(BaseOp);
650 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr);
651 if (BaseOp)
652 BaseOps.push_back(BaseOp);
653 Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm();
654 // Get appropriate operand, and compute width accordingly.
655 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
656 if (DataOpIdx == -1)
657 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
658 if (DataOpIdx == -1) // LDS DMA
659 return false;
660 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
661 return true;
662 }
663
664 return false;
665}
666
667static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
669 const MachineInstr &MI2,
671 // Only examine the first "base" operand of each instruction, on the
672 // assumption that it represents the real base address of the memory access.
673 // Other operands are typically offsets or indices from this base address.
674 if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
675 return true;
676
677 if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
678 return false;
679
680 auto *MO1 = *MI1.memoperands_begin();
681 auto *MO2 = *MI2.memoperands_begin();
682 if (MO1->getAddrSpace() != MO2->getAddrSpace())
683 return false;
684
685 const auto *Base1 = MO1->getValue();
686 const auto *Base2 = MO2->getValue();
687 if (!Base1 || !Base2)
688 return false;
689 Base1 = getUnderlyingObject(Base1);
690 Base2 = getUnderlyingObject(Base2);
691
692 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
693 return false;
694
695 return Base1 == Base2;
696}
697
700 ArrayRef<const MachineOperand *> BaseOps2) const {
701 // Accesses without base operands (e.g. scratch addressed only by an
702 // immediate offset) share the same implicit base.
703 if (BaseOps1.empty() || BaseOps2.empty())
704 return BaseOps1.empty() && BaseOps2.empty();
705 return memOpsHaveSameBasePtr(*BaseOps1.front()->getParent(), BaseOps1,
706 *BaseOps2.front()->getParent(), BaseOps2);
707}
708
710 int64_t Offset1, bool OffsetIsScalable1,
712 int64_t Offset2, bool OffsetIsScalable2,
713 unsigned ClusterSize,
714 unsigned NumBytes) const {
715 // If the mem ops (to be clustered) do not have the same base ptr, then they
716 // should not be clustered
717 if (!memOpsHaveSameBase(BaseOps1, BaseOps2))
718 return false;
719
720 // Both lists are empty or neither is, so BaseOps1 alone decides whether
721 // there is an instruction to read the budget from.
722 assert(BaseOps1.empty() == BaseOps2.empty());
723 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;
724 if (!BaseOps1.empty()) {
725 const MachineFunction *MF = BaseOps1.front()->getParent()->getMF();
726 MaxMemoryClusterDWords =
727 MF->getInfo<SIMachineFunctionInfo>()->getMaxMemoryClusterDWords();
728 }
729
730 // In order to avoid register pressure, on an average, the number of DWORDS
731 // loaded together by all clustered mem ops should not exceed
732 // MaxMemoryClusterDWords. This is an empirical value based on certain
733 // observations and performance related experiments.
734 // The good thing about this heuristic is - it avoids clustering of too many
735 // sub-word loads, and also avoids clustering of wide loads. Below is the
736 // brief summary of how the heuristic behaves for various `LoadSize` when
737 // MaxMemoryClusterDWords is 8.
738 //
739 // (1) 1 <= LoadSize <= 4: cluster at max 8 mem ops
740 // (2) 5 <= LoadSize <= 8: cluster at max 4 mem ops
741 // (3) 9 <= LoadSize <= 12: cluster at max 2 mem ops
742 // (4) 13 <= LoadSize <= 16: cluster at max 2 mem ops
743 // (5) LoadSize >= 17: do not cluster
744 const unsigned LoadSize = NumBytes / ClusterSize;
745 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
746 return NumDWords <= MaxMemoryClusterDWords;
747}
748
749// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
750// the first 16 loads will be interleaved with the stores, and the next 16 will
751// be clustered as expected. It should really split into 2 16 store batches.
752//
753// Loads are clustered until this returns false, rather than trying to schedule
754// groups of stores. This also means we have to deal with saying different
755// address space loads should be clustered, and ones which might cause bank
756// conflicts.
757//
758// This might be deprecated so it might not be worth that much effort to fix.
760 int64_t Offset0, int64_t Offset1,
761 unsigned NumLoads) const {
762 assert(Offset1 > Offset0 &&
763 "Second offset should be larger than first offset!");
764 // If we have less than 16 loads in a row, and the offsets are within 64
765 // bytes, then schedule together.
766
767 // A cacheline is 64 bytes (for global memory).
768 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
769}
770
773 const DebugLoc &DL, MCRegister DestReg,
774 MCRegister SrcReg, bool KillSrc,
775 const char *Msg = "illegal VGPR to SGPR copy") {
776 MachineFunction *MF = MBB.getParent();
777
780
781 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg)
782 .addReg(SrcReg, getKillRegState(KillSrc));
783}
784
785/// Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908. It is not
786/// possible to have a direct copy in these cases on GFX908, so an intermediate
787/// VGPR copy is required.
790 const DebugLoc &DL, MCRegister DestReg,
791 MCRegister SrcReg, bool KillSrc,
792 RegScavenger &RS, bool RegsOverlap,
793 Register ImpUseSuperReg = Register()) {
794 assert((TII.getSubtarget().hasMAIInsts() &&
795 !TII.getSubtarget().hasGFX90AInsts()) &&
796 "Expected GFX908 subtarget.");
797
798 assert((AMDGPU::SReg_32RegClass.contains(SrcReg) ||
799 AMDGPU::AGPR_32RegClass.contains(SrcReg)) &&
800 "Source register of the copy should be either an SGPR or an AGPR.");
801
802 assert(AMDGPU::AGPR_32RegClass.contains(DestReg) &&
803 "Destination register of the copy should be an AGPR.");
804
805 const SIRegisterInfo &RI = TII.getRegisterInfo();
806
807 // First try to find defining accvgpr_write to avoid temporary registers.
808 // In the case of copies of overlapping AGPRs, we conservatively do not
809 // reuse previous accvgpr_writes. Otherwise, we may incorrectly pick up
810 // an accvgpr_write used for this same copy due to implicit-defs
811 if (!RegsOverlap) {
812 for (auto Def = MI, E = MBB.begin(); Def != E; ) {
813 --Def;
814
815 if (!Def->modifiesRegister(SrcReg, &RI))
816 continue;
817
818 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
819 Def->getOperand(0).getReg() != SrcReg)
820 break;
821
822 MachineOperand &DefOp = Def->getOperand(1);
823 assert(DefOp.isReg() || DefOp.isImm());
824
825 if (DefOp.isReg()) {
826 bool SafeToPropagate = true;
827 // Check that register source operand is not clobbered before MI.
828 // Immediate operands are always safe to propagate.
829 for (auto I = Def; I != MI && SafeToPropagate; ++I)
830 if (I->modifiesRegister(DefOp.getReg(), &RI))
831 SafeToPropagate = false;
832
833 if (!SafeToPropagate)
834 break;
835
836 for (auto I = Def; I != MI; ++I)
837 I->clearRegisterKills(DefOp.getReg(), &RI);
838 }
839
840 MachineInstrBuilder Builder =
841 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64),
842 DestReg)
843 .add(DefOp);
844
845 if (ImpUseSuperReg) {
846 Builder.addReg(ImpUseSuperReg,
848 }
849
850 return;
851 }
852 }
853
854 RS.enterBasicBlockEnd(MBB);
855 RS.backward(std::next(MI));
856
857 // Ideally we want to have three registers for a long reg_sequence copy
858 // to hide 2 waitstates between v_mov_b32 and accvgpr_write.
859 unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass,
860 *MBB.getParent());
861
862 // Registers in the sequence are allocated contiguously so we can just
863 // use register number to pick one of three round-robin temps.
864 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
865 Register Tmp =
866 MBB.getParent()->getInfo<SIMachineFunctionInfo>()->getVGPRForAGPRCopy();
867 assert(MBB.getParent()->getRegInfo().isReserved(Tmp) &&
868 "VGPR used for an intermediate copy should have been reserved.");
869
870 // Only loop through if there are any free registers left. We don't want to
871 // spill.
872 while (RegNo--) {
873 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI,
874 /* RestoreAfter */ false, 0,
875 /* AllowSpill */ false);
876 if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs)
877 break;
878 Tmp = Tmp2;
879 RS.setRegUsed(Tmp);
880 }
881
882 // Insert copy to temporary VGPR.
883 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
884 if (AMDGPU::AGPR_32RegClass.contains(SrcReg)) {
885 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
886 } else {
887 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
888 }
889
890 MachineInstrBuilder UseBuilder = BuildMI(MBB, MI, DL, TII.get(TmpCopyOp), Tmp)
891 .addReg(SrcReg, getKillRegState(KillSrc));
892 if (ImpUseSuperReg) {
893 UseBuilder.addReg(ImpUseSuperReg,
895 }
896
897 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
898 .addReg(Tmp, RegState::Kill);
899}
900
903 MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
904 const TargetRegisterClass *RC, bool Forward) {
905 const SIRegisterInfo &RI = TII.getRegisterInfo();
906 ArrayRef<int16_t> BaseIndices = RI.getRegSplitParts(RC, 4);
908 MachineInstr *FirstMI = nullptr, *LastMI = nullptr;
909
910 for (unsigned Idx = 0; Idx < BaseIndices.size(); ++Idx) {
911 int16_t SubIdx = BaseIndices[Idx];
912 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
913 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
914 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
915 unsigned Opcode = AMDGPU::S_MOV_B32;
916
917 // Is SGPR aligned? If so try to combine with next.
918 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
919 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
920 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.size())) {
921 // Can use SGPR64 copy
922 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
923 SubIdx = RI.getSubRegFromChannel(Channel, 2);
924 DestSubReg = RI.getSubReg(DestReg, SubIdx);
925 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
926 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
927 Opcode = AMDGPU::S_MOV_B64;
928 Idx++;
929 }
930
931 LastMI = BuildMI(MBB, I, DL, TII.get(Opcode), DestSubReg)
932 .addReg(SrcSubReg)
933 .addReg(SrcReg, RegState::Implicit);
934
935 if (!FirstMI)
936 FirstMI = LastMI;
937
938 if (!Forward)
939 I--;
940 }
941
942 assert(FirstMI && LastMI);
943 if (!Forward)
944 std::swap(FirstMI, LastMI);
945
946 if (KillSrc)
947 LastMI->addRegisterKilled(SrcReg, &RI);
948}
949
952 const DebugLoc &DL, Register DestReg,
953 Register SrcReg, bool KillSrc, bool RenamableDest,
954 bool RenamableSrc) const {
955 const TargetRegisterClass *RC = RI.getPhysRegBaseClass(DestReg);
956 unsigned Size = RI.getRegSizeInBits(*RC);
957 const TargetRegisterClass *SrcRC = RI.getPhysRegBaseClass(SrcReg);
958 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
959
960 // The rest of copyPhysReg assumes Src and Dst size are the same size.
961 // TODO-GFX11_16BIT If all true 16 bit instruction patterns are completed can
962 // we remove Fix16BitCopies and this code block?
963 if (Fix16BitCopies) {
964 if (((Size == 16) != (SrcSize == 16))) {
965 // Non-VGPR Src and Dst will later be expanded back to 32 bits.
966 assert(ST.useRealTrue16Insts());
967 Register &RegToFix = (Size == 32) ? DestReg : SrcReg;
968 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
969 RegToFix = SubReg;
970
971 if (DestReg == SrcReg) {
972 // Identity copy. Insert empty bundle since ExpandPostRA expects an
973 // instruction here.
974 BuildMI(MBB, MI, DL, get(AMDGPU::BUNDLE));
975 return;
976 }
977 RC = RI.getPhysRegBaseClass(DestReg);
978 Size = RI.getRegSizeInBits(*RC);
979 SrcRC = RI.getPhysRegBaseClass(SrcReg);
980 SrcSize = RI.getRegSizeInBits(*SrcRC);
981 }
982 }
983
984 if (RC == &AMDGPU::VGPR_32RegClass) {
985 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
986 AMDGPU::SReg_32RegClass.contains(SrcReg) ||
987 AMDGPU::AGPR_32RegClass.contains(SrcReg));
988 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
989 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
990 BuildMI(MBB, MI, DL, get(Opc), DestReg)
991 .addReg(SrcReg, getKillRegState(KillSrc));
992 return;
993 }
994
995 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
996 RC == &AMDGPU::SReg_32RegClass) {
997 if (SrcReg == AMDGPU::SCC) {
998 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg)
999 .addImm(1)
1000 .addImm(0);
1001 return;
1002 }
1003
1004 if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) {
1005 if (DestReg == AMDGPU::VCC_LO) {
1006 // FIXME: Hack until VReg_1 removed.
1007 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
1008 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
1009 .addImm(0)
1010 .addReg(SrcReg, getKillRegState(KillSrc));
1011 return;
1012 }
1013
1014 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1015 return;
1016 }
1017
1018 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
1019 .addReg(SrcReg, getKillRegState(KillSrc));
1020 return;
1021 }
1022
1023 if (RC == &AMDGPU::SReg_64RegClass) {
1024 if (SrcReg == AMDGPU::SCC) {
1025 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B64), DestReg)
1026 .addImm(1)
1027 .addImm(0);
1028 return;
1029 }
1030
1031 if (!AMDGPU::SReg_64_EncodableRegClass.contains(SrcReg)) {
1032 if (DestReg == AMDGPU::VCC) {
1033 // FIXME: Hack until VReg_1 removed.
1034 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
1035 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
1036 .addImm(0)
1037 .addReg(SrcReg, getKillRegState(KillSrc));
1038 return;
1039 }
1040
1041 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1042 return;
1043 }
1044
1045 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
1046 .addReg(SrcReg, getKillRegState(KillSrc));
1047 return;
1048 }
1049
1050 if (DestReg == AMDGPU::SCC) {
1051 // Copying 64-bit or 32-bit sources to SCC barely makes sense,
1052 // but SelectionDAG emits such copies for i1 sources.
1053 if (AMDGPU::SReg_64RegClass.contains(SrcReg)) {
1054 // This copy can only be produced by patterns
1055 // with explicit SCC, which are known to be enabled
1056 // only for subtargets with S_CMP_LG_U64 present.
1057 assert(ST.hasScalarCompareEq64());
1058 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U64))
1059 .addReg(SrcReg, getKillRegState(KillSrc))
1060 .addImm(0);
1061 } else {
1062 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
1063 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32))
1064 .addReg(SrcReg, getKillRegState(KillSrc))
1065 .addImm(0);
1066 }
1067
1068 return;
1069 }
1070
1071 if (RC == &AMDGPU::AGPR_32RegClass) {
1072 if (AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
1073 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1074 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
1075 .addReg(SrcReg, getKillRegState(KillSrc));
1076 return;
1077 }
1078
1079 if (AMDGPU::AGPR_32RegClass.contains(SrcReg) && ST.hasGFX90AInsts()) {
1080 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_MOV_B32), DestReg)
1081 .addReg(SrcReg, getKillRegState(KillSrc));
1082 return;
1083 }
1084
1085 // FIXME: Pass should maintain scavenger to avoid scan through the block on
1086 // every AGPR spill.
1087 RegScavenger RS;
1088 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1089 indirectCopyToAGPR(*this, MBB, MI, DL, DestReg, SrcReg, KillSrc, RS, Overlap);
1090 return;
1091 }
1092
1093 if (Size == 16) {
1094 assert(AMDGPU::VGPR_16RegClass.contains(SrcReg) ||
1095 AMDGPU::SReg_LO16RegClass.contains(SrcReg) ||
1096 AMDGPU::AGPR_LO16RegClass.contains(SrcReg));
1097
1098 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1099 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1100 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1101 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1102 bool DstLow = !AMDGPU::isHi16Reg(DestReg, RI);
1103 bool SrcLow = !AMDGPU::isHi16Reg(SrcReg, RI);
1104 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1105 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1106
1107 if (IsSGPRDst) {
1108 if (!IsSGPRSrc) {
1109 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1110 return;
1111 }
1112
1113 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), NewDestReg)
1114 .addReg(NewSrcReg, getKillRegState(KillSrc));
1115 return;
1116 }
1117
1118 if (IsAGPRDst || IsAGPRSrc) {
1119 if (!DstLow || !SrcLow) {
1120 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1121 "Cannot use hi16 subreg with an AGPR!");
1122 }
1123
1124 copyPhysReg(MBB, MI, DL, NewDestReg, NewSrcReg, KillSrc);
1125 return;
1126 }
1127
1128 if (ST.useRealTrue16Insts()) {
1129 if (IsSGPRSrc) {
1130 assert(SrcLow);
1131 SrcReg = NewSrcReg;
1132 }
1133 // Use the smaller instruction encoding if possible.
1134 if (AMDGPU::VGPR_16_Lo128RegClass.contains(DestReg) &&
1135 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.contains(SrcReg))) {
1136 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e32), DestReg)
1137 .addReg(SrcReg);
1138 } else {
1139 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e64), DestReg)
1140 .addImm(0) // src0_modifiers
1141 .addReg(SrcReg)
1142 .addImm(0); // op_sel
1143 }
1144 return;
1145 }
1146
1147 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1148 if (!DstLow || !SrcLow) {
1149 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1150 "Cannot use hi16 subreg on VI!");
1151 }
1152
1153 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), NewDestReg)
1154 .addReg(NewSrcReg, getKillRegState(KillSrc));
1155 return;
1156 }
1157
1158 auto MIB = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_sdwa), NewDestReg)
1159 .addImm(0) // src0_modifiers
1160 .addReg(NewSrcReg)
1161 .addImm(0) // clamp
1168 // First implicit operand is $exec.
1169 MIB->tieOperands(0, MIB->getNumOperands() - 1);
1170 return;
1171 }
1172
1173 // Returns true if Dst and Src are in Opc's HwMode-resolved destination and
1174 // source operand classes.
1175 auto CanCopyWith = [&](unsigned Opc, MCRegister Dst, MCRegister Src,
1176 unsigned SrcOp = 1) {
1177 const MCInstrDesc &Desc = get(Opc);
1178 const TargetRegisterClass *DstOpRC = getRegClass(Desc, 0);
1179 const TargetRegisterClass *SrcOpRC = getRegClass(Desc, SrcOp);
1180 return DstOpRC && SrcOpRC && DstOpRC->contains(Dst) &&
1181 SrcOpRC->contains(Src);
1182 };
1183
1184 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1185 if (ST.hasVMovB64Inst() &&
1186 CanCopyWith(AMDGPU::V_MOV_B64_e32, DestReg, SrcReg)) {
1187 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_e32), DestReg)
1188 .addReg(SrcReg, getKillRegState(KillSrc));
1189 return;
1190 }
1191 if (ST.hasPkMovB32() &&
1192 CanCopyWith(AMDGPU::V_PK_MOV_B32, DestReg, SrcReg, /*SrcOp=*/2)) {
1193 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestReg)
1195 .addReg(SrcReg)
1197 .addReg(SrcReg)
1198 .addImm(0) // op_sel_lo
1199 .addImm(0) // op_sel_hi
1200 .addImm(0) // neg_lo
1201 .addImm(0) // neg_hi
1202 .addImm(0) // clamp
1203 .addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
1204 return;
1205 }
1206 }
1207
1208 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1209 if (RI.isSGPRClass(RC)) {
1210 if (!RI.isSGPRClass(SrcRC)) {
1211 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1212 return;
1213 }
1214 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1215 expandSGPRCopy(*this, MBB, MI, DL, DestReg, SrcReg, CanKillSuperReg, RC,
1216 Forward);
1217 return;
1218 }
1219
1220 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1221 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1222 if (RI.isAGPRClass(RC)) {
1223 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1224 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1225 else if (RI.hasVGPRs(SrcRC) ||
1226 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1227 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1228 else
1229 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1230 } else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1231 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1232 } else if (RI.isVGPRClass(RC)) {
1233 if (ST.hasVMovB64Inst())
1234 WideOpcode = AMDGPU::V_MOV_B64_e32;
1235 else if (ST.hasPkMovB32())
1236 WideOpcode = AMDGPU::V_PK_MOV_B32;
1237 }
1238
1239 const TargetRegisterClass *WideDstRC{}, *WideSrcRC{};
1240 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1241 const MCInstrDesc &Desc = get(WideOpcode);
1242 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1243 WideDstRC = getRegClass(Desc, 0);
1244 WideSrcRC = getRegClass(Desc, SrcOp);
1245 }
1246
1247 // If there is an overlap, we can't kill the super-register on the last
1248 // instruction, since it will also kill the components made live by this def.
1249 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1250 const bool CanKillSuperReg = KillSrc && !Overlap;
1251
1252 // For the cases where we need an intermediate instruction/temporary register
1253 // (destination is an AGPR), we need a scavenger.
1254 //
1255 // FIXME: The pass should maintain this for us so we don't have to re-scan the
1256 // whole block for every handled copy.
1257 std::unique_ptr<RegScavenger> RS;
1258 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1259 RS = std::make_unique<RegScavenger>();
1260
1261 ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, 4);
1262
1263 for (unsigned Idx{}; Idx < SubIndices.size();) {
1264 unsigned NumRegs = 1;
1265 unsigned ThisOpcode = Opcode;
1266 unsigned SubIdx =
1267 Forward ? SubIndices[Idx] : SubIndices[SubIndices.size() - Idx - 1];
1268
1269 if (WideDstRC && WideSrcRC && Idx + 1 < SubIndices.size()) {
1270 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1271 if (!Forward)
1272 --Channel;
1273
1274 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1275 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1276 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1277
1278 if (WideDst && WideSrc && WideDstRC->contains(WideDst) &&
1279 WideSrcRC->contains(WideSrc)) {
1280 SubIdx = WideSubIdx;
1281 NumRegs = 2;
1282 ThisOpcode = WideOpcode;
1283 }
1284 }
1285
1286 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1287 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1288 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
1289
1290 Idx += NumRegs;
1291 bool UseKill = CanKillSuperReg && Idx == SubIndices.size();
1292
1293 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1294 Register ImpUseSuper = SrcReg;
1295 indirectCopyToAGPR(*this, MBB, MI, DL, DestSubReg, SrcSubReg, UseKill,
1296 *RS, Overlap, ImpUseSuper);
1297 } else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1298 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestSubReg)
1300 .addReg(SrcSubReg)
1302 .addReg(SrcSubReg)
1303 .addImm(0) // op_sel_lo
1304 .addImm(0) // op_sel_hi
1305 .addImm(0) // neg_lo
1306 .addImm(0) // neg_hi
1307 .addImm(0) // clamp
1308 .addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1309 } else {
1310 MachineInstrBuilder Builder =
1311 BuildMI(MBB, MI, DL, get(ThisOpcode), DestSubReg).addReg(SrcSubReg);
1312
1313 Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1314 }
1315 }
1316}
1317
1318int SIInstrInfo::commuteOpcode(unsigned Opcode) const {
1319 int32_t NewOpc;
1320
1321 // Try to map original to commuted opcode
1322 NewOpc = AMDGPU::getCommuteRev(Opcode);
1323 if (NewOpc != -1)
1324 // Check if the commuted (REV) opcode exists on the target.
1325 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1326
1327 // Try to map commuted to original opcode
1328 NewOpc = AMDGPU::getCommuteOrig(Opcode);
1329 if (NewOpc != -1)
1330 // Check if the original (non-REV) opcode exists on the target.
1331 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1332
1333 return Opcode;
1334}
1335
1337 const Register Reg,
1338 int64_t &ImmVal) const {
1339 switch (MI.getOpcode()) {
1340 case AMDGPU::V_MOV_B32_e32:
1341 case AMDGPU::S_MOV_B32:
1342 case AMDGPU::S_MOVK_I32:
1343 case AMDGPU::S_MOV_B64:
1344 case AMDGPU::V_MOV_B64_e32:
1345 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1346 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1347 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1348 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1349 case AMDGPU::V_MOV_B64_PSEUDO:
1350 case AMDGPU::V_MOV_B16_t16_e32: {
1351 const MachineOperand &Src0 = MI.getOperand(1);
1352 if (Src0.isImm()) {
1353 ImmVal = Src0.getImm();
1354 return MI.getOperand(0).getReg() == Reg;
1355 }
1356
1357 return false;
1358 }
1359 case AMDGPU::V_MOV_B16_t16_e64: {
1360 const MachineOperand &Src0 = MI.getOperand(2);
1361 if (Src0.isImm() && !MI.getOperand(1).getImm()) {
1362 ImmVal = Src0.getImm();
1363 return MI.getOperand(0).getReg() == Reg;
1364 }
1365
1366 return false;
1367 }
1368 case AMDGPU::S_BREV_B32:
1369 case AMDGPU::V_BFREV_B32_e32:
1370 case AMDGPU::V_BFREV_B32_e64: {
1371 const MachineOperand &Src0 = MI.getOperand(1);
1372 if (Src0.isImm()) {
1373 ImmVal = static_cast<int64_t>(reverseBits<int32_t>(Src0.getImm()));
1374 return MI.getOperand(0).getReg() == Reg;
1375 }
1376
1377 return false;
1378 }
1379 case AMDGPU::S_NOT_B32:
1380 case AMDGPU::V_NOT_B32_e32:
1381 case AMDGPU::V_NOT_B32_e64: {
1382 const MachineOperand &Src0 = MI.getOperand(1);
1383 if (Src0.isImm()) {
1384 ImmVal = static_cast<int64_t>(~static_cast<int32_t>(Src0.getImm()));
1385 return MI.getOperand(0).getReg() == Reg;
1386 }
1387
1388 return false;
1389 }
1390 default:
1391 return false;
1392 }
1393}
1394
1395std::optional<int64_t>
1397 const MachineOperand &Op,
1398 MachineInstr **DefMI) const {
1399 if (DefMI)
1400 *DefMI = nullptr;
1401
1402 if (Op.isImm())
1403 return Op.getImm();
1404
1405 if (!Op.isReg() || !Op.getReg().isVirtual())
1406 return std::nullopt;
1407 MachineInstr *Def = MRI.getUniqueVRegDef(Op.getReg());
1408 if (Def && Def->isMoveImmediate()) {
1409 const MachineOperand &ImmSrc = Def->getOperand(1);
1410 if (ImmSrc.isImm()) {
1411 if (DefMI)
1412 *DefMI = Def;
1413 return extractSubregFromImm(ImmSrc.getImm(), Op.getSubReg());
1414 }
1415 }
1416
1417 return std::nullopt;
1418}
1419
1420std::optional<int64_t>
1426
1428
1429 if (RI.isAGPRClass(DstRC))
1430 return AMDGPU::COPY;
1431 if (RI.getRegSizeInBits(*DstRC) == 16) {
1432 // Assume hi bits are unneeded. Only _e64 true16 instructions are legal
1433 // before RA.
1434 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1435 }
1436 if (RI.getRegSizeInBits(*DstRC) == 32)
1437 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1438 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1439 return AMDGPU::S_MOV_B64;
1440 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1441 return AMDGPU::V_MOV_B64_PSEUDO;
1442 return AMDGPU::COPY;
1443}
1444
1445const MCInstrDesc &
1447 bool IsIndirectSrc) const {
1448 if (IsIndirectSrc) {
1449 if (VecSize <= 32) // 4 bytes
1450 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1451 if (VecSize <= 64) // 8 bytes
1452 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1453 if (VecSize <= 96) // 12 bytes
1454 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1455 if (VecSize <= 128) // 16 bytes
1456 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1457 if (VecSize <= 160) // 20 bytes
1458 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1459 if (VecSize <= 192) // 24 bytes
1460 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1461 if (VecSize <= 224) // 28 bytes
1462 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1463 if (VecSize <= 256) // 32 bytes
1464 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1465 if (VecSize <= 288) // 36 bytes
1466 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1467 if (VecSize <= 320) // 40 bytes
1468 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1469 if (VecSize <= 352) // 44 bytes
1470 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1471 if (VecSize <= 384) // 48 bytes
1472 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1473 if (VecSize <= 512) // 64 bytes
1474 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1475 if (VecSize <= 1024) // 128 bytes
1476 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1477
1478 llvm_unreachable("unsupported size for IndirectRegReadGPRIDX pseudos");
1479 }
1480
1481 if (VecSize <= 32) // 4 bytes
1482 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1483 if (VecSize <= 64) // 8 bytes
1484 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1485 if (VecSize <= 96) // 12 bytes
1486 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1487 if (VecSize <= 128) // 16 bytes
1488 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1489 if (VecSize <= 160) // 20 bytes
1490 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1491 if (VecSize <= 192) // 24 bytes
1492 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1493 if (VecSize <= 224) // 28 bytes
1494 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1495 if (VecSize <= 256) // 32 bytes
1496 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1497 if (VecSize <= 288) // 36 bytes
1498 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1499 if (VecSize <= 320) // 40 bytes
1500 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1501 if (VecSize <= 352) // 44 bytes
1502 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1503 if (VecSize <= 384) // 48 bytes
1504 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1505 if (VecSize <= 512) // 64 bytes
1506 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1507 if (VecSize <= 1024) // 128 bytes
1508 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1509
1510 llvm_unreachable("unsupported size for IndirectRegWriteGPRIDX pseudos");
1511}
1512
1513static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize) {
1514 if (VecSize <= 32) // 4 bytes
1515 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1516 if (VecSize <= 64) // 8 bytes
1517 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1518 if (VecSize <= 96) // 12 bytes
1519 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1520 if (VecSize <= 128) // 16 bytes
1521 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1522 if (VecSize <= 160) // 20 bytes
1523 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1524 if (VecSize <= 192) // 24 bytes
1525 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1526 if (VecSize <= 224) // 28 bytes
1527 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1528 if (VecSize <= 256) // 32 bytes
1529 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1530 if (VecSize <= 288) // 36 bytes
1531 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1532 if (VecSize <= 320) // 40 bytes
1533 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1534 if (VecSize <= 352) // 44 bytes
1535 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1536 if (VecSize <= 384) // 48 bytes
1537 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1538 if (VecSize <= 512) // 64 bytes
1539 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1540 if (VecSize <= 1024) // 128 bytes
1541 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1542
1543 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1544}
1545
1546static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize) {
1547 if (VecSize <= 32) // 4 bytes
1548 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1549 if (VecSize <= 64) // 8 bytes
1550 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1551 if (VecSize <= 96) // 12 bytes
1552 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1553 if (VecSize <= 128) // 16 bytes
1554 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1555 if (VecSize <= 160) // 20 bytes
1556 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1557 if (VecSize <= 192) // 24 bytes
1558 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1559 if (VecSize <= 224) // 28 bytes
1560 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1561 if (VecSize <= 256) // 32 bytes
1562 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1563 if (VecSize <= 288) // 36 bytes
1564 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1565 if (VecSize <= 320) // 40 bytes
1566 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1567 if (VecSize <= 352) // 44 bytes
1568 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1569 if (VecSize <= 384) // 48 bytes
1570 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1571 if (VecSize <= 512) // 64 bytes
1572 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1573 if (VecSize <= 1024) // 128 bytes
1574 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1575
1576 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1577}
1578
1579static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize) {
1580 if (VecSize <= 64) // 8 bytes
1581 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1582 if (VecSize <= 128) // 16 bytes
1583 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1584 if (VecSize <= 256) // 32 bytes
1585 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1586 if (VecSize <= 512) // 64 bytes
1587 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1588 if (VecSize <= 1024) // 128 bytes
1589 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1590
1591 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1592}
1593
1594const MCInstrDesc &
1595SIInstrInfo::getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize,
1596 bool IsSGPR) const {
1597 if (IsSGPR) {
1598 switch (EltSize) {
1599 case 32:
1600 return get(getIndirectSGPRWriteMovRelPseudo32(VecSize));
1601 case 64:
1602 return get(getIndirectSGPRWriteMovRelPseudo64(VecSize));
1603 default:
1604 llvm_unreachable("invalid reg indexing elt size");
1605 }
1606 }
1607
1608 assert(EltSize == 32 && "invalid reg indexing elt size");
1610}
1611
1612static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1613 switch (Size) {
1614 case 4:
1615 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1616 case 8:
1617 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1618 case 12:
1619 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1620 case 16:
1621 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1622 : AMDGPU::SI_SPILL_S128_SAVE;
1623 case 20:
1624 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1625 : AMDGPU::SI_SPILL_S160_SAVE;
1626 case 24:
1627 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1628 : AMDGPU::SI_SPILL_S192_SAVE;
1629 case 28:
1630 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1631 : AMDGPU::SI_SPILL_S224_SAVE;
1632 case 32:
1633 return AMDGPU::SI_SPILL_S256_SAVE;
1634 case 36:
1635 return AMDGPU::SI_SPILL_S288_SAVE;
1636 case 40:
1637 return AMDGPU::SI_SPILL_S320_SAVE;
1638 case 44:
1639 return AMDGPU::SI_SPILL_S352_SAVE;
1640 case 48:
1641 return AMDGPU::SI_SPILL_S384_SAVE;
1642 case 64:
1643 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1644 : AMDGPU::SI_SPILL_S512_SAVE;
1645 case 128:
1646 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1647 : AMDGPU::SI_SPILL_S1024_SAVE;
1648 default:
1649 llvm_unreachable("unknown register size");
1650 }
1651}
1652
1653static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1654 switch (Size) {
1655 case 2:
1656 return AMDGPU::SI_SPILL_V16_SAVE;
1657 case 4:
1658 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1659 case 8:
1660 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1661 case 12:
1662 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1663 case 16:
1664 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1665 : AMDGPU::SI_SPILL_V128_SAVE;
1666 case 20:
1667 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1668 : AMDGPU::SI_SPILL_V160_SAVE;
1669 case 24:
1670 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1671 : AMDGPU::SI_SPILL_V192_SAVE;
1672 case 28:
1673 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1674 : AMDGPU::SI_SPILL_V224_SAVE;
1675 case 32:
1676 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1677 : AMDGPU::SI_SPILL_V256_SAVE;
1678 case 36:
1679 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1680 : AMDGPU::SI_SPILL_V288_SAVE;
1681 case 40:
1682 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1683 : AMDGPU::SI_SPILL_V320_SAVE;
1684 case 44:
1685 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1686 : AMDGPU::SI_SPILL_V352_SAVE;
1687 case 48:
1688 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1689 : AMDGPU::SI_SPILL_V384_SAVE;
1690 case 64:
1691 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1692 : AMDGPU::SI_SPILL_V512_SAVE;
1693 case 128:
1694 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1695 : AMDGPU::SI_SPILL_V1024_SAVE;
1696 default:
1697 llvm_unreachable("unknown register size");
1698 }
1699}
1700
1701static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1702 switch (Size) {
1703 case 4:
1704 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1705 : AMDGPU::SI_SPILL_AV32_SAVE;
1706 case 8:
1707 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1708 : AMDGPU::SI_SPILL_AV64_SAVE;
1709 case 12:
1710 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1711 : AMDGPU::SI_SPILL_AV96_SAVE;
1712 case 16:
1713 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1714 : AMDGPU::SI_SPILL_AV128_SAVE;
1715 case 20:
1716 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1717 : AMDGPU::SI_SPILL_AV160_SAVE;
1718 case 24:
1719 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1720 : AMDGPU::SI_SPILL_AV192_SAVE;
1721 case 28:
1722 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1723 : AMDGPU::SI_SPILL_AV224_SAVE;
1724 case 32:
1725 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1726 : AMDGPU::SI_SPILL_AV256_SAVE;
1727 case 36:
1728 return AMDGPU::SI_SPILL_AV288_SAVE;
1729 case 40:
1730 return AMDGPU::SI_SPILL_AV320_SAVE;
1731 case 44:
1732 return AMDGPU::SI_SPILL_AV352_SAVE;
1733 case 48:
1734 return AMDGPU::SI_SPILL_AV384_SAVE;
1735 case 64:
1736 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1737 : AMDGPU::SI_SPILL_AV512_SAVE;
1738 case 128:
1739 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1740 : AMDGPU::SI_SPILL_AV1024_SAVE;
1741 default:
1742 llvm_unreachable("unknown register size");
1743 }
1744}
1745
1746static unsigned getWWMRegSpillSaveOpcode(unsigned Size,
1747 bool IsVectorSuperClass) {
1748 // Currently, there is only 32-bit WWM register spills needed.
1749 if (Size != 4)
1750 llvm_unreachable("unknown wwm register spill size");
1751
1752 if (IsVectorSuperClass)
1753 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1754
1755 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1756}
1757
1759 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1760 const SIMachineFunctionInfo &MFI, bool NeedsCFI) const {
1761 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1762
1763 // Choose the right opcode if spilling a WWM register.
1765 return getWWMRegSpillSaveOpcode(Size, IsVectorSuperClass);
1766
1767 // TODO: Check if AGPRs are available
1768 if (ST.hasMAIInsts())
1769 return getAVSpillSaveOpcode(Size, NeedsCFI);
1770
1771 return getVGPRSpillSaveOpcode(Size, NeedsCFI);
1772}
1773
1774void SIInstrInfo::storeRegToStackSlotImpl(
1776 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1777 MachineInstr::MIFlag Flags, bool NeedsCFI) const {
1778 MachineFunction *MF = MBB.getParent();
1780 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1781 const DebugLoc &DL = MBB.findDebugLoc(MI);
1782
1783 MachinePointerInfo PtrInfo
1784 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1786 PtrInfo, MachineMemOperand::MOStore, FrameInfo.getObjectSize(FrameIndex),
1787 FrameInfo.getObjectAlign(FrameIndex));
1788 unsigned SpillSize = RI.getSpillSize(*RC);
1789
1791 if (RI.isSGPRClass(RC)) {
1792 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1793 MFI->setHasSpilledSGPRs();
1794 assert(SrcReg != AMDGPU::M0 && "m0 should not be spilled");
1795 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1796 SrcReg != AMDGPU::EXEC && "exec should not be spilled");
1797
1798 // We are only allowed to create one new instruction when spilling
1799 // registers, so we need to use pseudo instruction for spilling SGPRs.
1800 const MCInstrDesc &OpDesc =
1801 get(getSGPRSpillSaveOpcode(SpillSize, NeedsCFI));
1802
1803 // The SGPR spill/restore instructions only work on number sgprs, so we need
1804 // to make sure we are using the correct register class.
1805 if (SrcReg.isVirtual() && SpillSize == 4) {
1806 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1807 }
1808
1809 BuildMI(MBB, MI, DL, OpDesc)
1810 .addReg(SrcReg, getKillRegState(isKill)) // data
1811 .addFrameIndex(FrameIndex) // addr
1812 .addMemOperand(MMO)
1814
1815 return;
1816 }
1817
1818 unsigned Opcode = getVectorRegSpillSaveOpcode(VReg ? VReg : SrcReg, RC,
1819 SpillSize, *MFI, NeedsCFI);
1820 MFI->setHasSpilledVGPRs();
1821
1822 BuildMI(MBB, MI, DL, get(Opcode))
1823 .addReg(SrcReg, getKillRegState(isKill)) // data
1824 .addFrameIndex(FrameIndex) // addr
1825 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1826 .addImm(0) // offset
1827 .addMemOperand(MMO);
1828}
1829
1832 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1833 MachineInstr::MIFlag Flags) const {
1834 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1835 false);
1836}
1837
1840 Register SrcReg, bool isKill,
1841 int FrameIndex,
1842 const TargetRegisterClass *RC) const {
1843 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, Register(),
1844 MachineInstr::NoFlags, true);
1845}
1846
1847static unsigned getSGPRSpillRestoreOpcode(unsigned Size) {
1848 switch (Size) {
1849 case 4:
1850 return AMDGPU::SI_SPILL_S32_RESTORE;
1851 case 8:
1852 return AMDGPU::SI_SPILL_S64_RESTORE;
1853 case 12:
1854 return AMDGPU::SI_SPILL_S96_RESTORE;
1855 case 16:
1856 return AMDGPU::SI_SPILL_S128_RESTORE;
1857 case 20:
1858 return AMDGPU::SI_SPILL_S160_RESTORE;
1859 case 24:
1860 return AMDGPU::SI_SPILL_S192_RESTORE;
1861 case 28:
1862 return AMDGPU::SI_SPILL_S224_RESTORE;
1863 case 32:
1864 return AMDGPU::SI_SPILL_S256_RESTORE;
1865 case 36:
1866 return AMDGPU::SI_SPILL_S288_RESTORE;
1867 case 40:
1868 return AMDGPU::SI_SPILL_S320_RESTORE;
1869 case 44:
1870 return AMDGPU::SI_SPILL_S352_RESTORE;
1871 case 48:
1872 return AMDGPU::SI_SPILL_S384_RESTORE;
1873 case 64:
1874 return AMDGPU::SI_SPILL_S512_RESTORE;
1875 case 128:
1876 return AMDGPU::SI_SPILL_S1024_RESTORE;
1877 default:
1878 llvm_unreachable("unknown register size");
1879 }
1880}
1881
1882static unsigned getVGPRSpillRestoreOpcode(unsigned Size) {
1883 switch (Size) {
1884 case 2:
1885 return AMDGPU::SI_SPILL_V16_RESTORE;
1886 case 4:
1887 return AMDGPU::SI_SPILL_V32_RESTORE;
1888 case 8:
1889 return AMDGPU::SI_SPILL_V64_RESTORE;
1890 case 12:
1891 return AMDGPU::SI_SPILL_V96_RESTORE;
1892 case 16:
1893 return AMDGPU::SI_SPILL_V128_RESTORE;
1894 case 20:
1895 return AMDGPU::SI_SPILL_V160_RESTORE;
1896 case 24:
1897 return AMDGPU::SI_SPILL_V192_RESTORE;
1898 case 28:
1899 return AMDGPU::SI_SPILL_V224_RESTORE;
1900 case 32:
1901 return AMDGPU::SI_SPILL_V256_RESTORE;
1902 case 36:
1903 return AMDGPU::SI_SPILL_V288_RESTORE;
1904 case 40:
1905 return AMDGPU::SI_SPILL_V320_RESTORE;
1906 case 44:
1907 return AMDGPU::SI_SPILL_V352_RESTORE;
1908 case 48:
1909 return AMDGPU::SI_SPILL_V384_RESTORE;
1910 case 64:
1911 return AMDGPU::SI_SPILL_V512_RESTORE;
1912 case 128:
1913 return AMDGPU::SI_SPILL_V1024_RESTORE;
1914 default:
1915 llvm_unreachable("unknown register size");
1916 }
1917}
1918
1919static unsigned getAVSpillRestoreOpcode(unsigned Size) {
1920 switch (Size) {
1921 case 4:
1922 return AMDGPU::SI_SPILL_AV32_RESTORE;
1923 case 8:
1924 return AMDGPU::SI_SPILL_AV64_RESTORE;
1925 case 12:
1926 return AMDGPU::SI_SPILL_AV96_RESTORE;
1927 case 16:
1928 return AMDGPU::SI_SPILL_AV128_RESTORE;
1929 case 20:
1930 return AMDGPU::SI_SPILL_AV160_RESTORE;
1931 case 24:
1932 return AMDGPU::SI_SPILL_AV192_RESTORE;
1933 case 28:
1934 return AMDGPU::SI_SPILL_AV224_RESTORE;
1935 case 32:
1936 return AMDGPU::SI_SPILL_AV256_RESTORE;
1937 case 36:
1938 return AMDGPU::SI_SPILL_AV288_RESTORE;
1939 case 40:
1940 return AMDGPU::SI_SPILL_AV320_RESTORE;
1941 case 44:
1942 return AMDGPU::SI_SPILL_AV352_RESTORE;
1943 case 48:
1944 return AMDGPU::SI_SPILL_AV384_RESTORE;
1945 case 64:
1946 return AMDGPU::SI_SPILL_AV512_RESTORE;
1947 case 128:
1948 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1949 default:
1950 llvm_unreachable("unknown register size");
1951 }
1952}
1953
1954static unsigned getWWMRegSpillRestoreOpcode(unsigned Size,
1955 bool IsVectorSuperClass) {
1956 // Currently, there is only 32-bit WWM register spills needed.
1957 if (Size != 4)
1958 llvm_unreachable("unknown wwm register spill size");
1959
1960 if (IsVectorSuperClass) // TODO: Always use this if there are AGPRs
1961 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1962
1963 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1964}
1965
1967 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1968 const SIMachineFunctionInfo &MFI) const {
1969 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1970
1971 // Choose the right opcode if restoring a WWM register.
1973 return getWWMRegSpillRestoreOpcode(Size, IsVectorSuperClass);
1974
1975 // TODO: Check if AGPRs are available
1976 if (ST.hasMAIInsts())
1978
1979 assert(!RI.isAGPRClass(RC));
1981}
1982
1985 Register DestReg, int FrameIndex,
1986 const TargetRegisterClass *RC,
1987 Register VReg, unsigned SubReg,
1988 MachineInstr::MIFlag Flags) const {
1989 MachineFunction *MF = MBB.getParent();
1991 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1992 const DebugLoc &DL = MBB.findDebugLoc(MI);
1993 unsigned SpillSize = RI.getSpillSize(*RC);
1994
1995 MachinePointerInfo PtrInfo
1996 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1997
1999 PtrInfo, MachineMemOperand::MOLoad, FrameInfo.getObjectSize(FrameIndex),
2000 FrameInfo.getObjectAlign(FrameIndex));
2001
2002 if (RI.isSGPRClass(RC)) {
2003 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
2004 MFI->setHasSpilledSGPRs();
2005 assert(DestReg != AMDGPU::M0 && "m0 should not be reloaded into");
2006 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
2007 DestReg != AMDGPU::EXEC && "exec should not be spilled");
2008
2009 // FIXME: Maybe this should not include a memoperand because it will be
2010 // lowered to non-memory instructions.
2011 const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize));
2012 if (DestReg.isVirtual() && SpillSize == 4) {
2014 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
2015 }
2016
2017 BuildMI(MBB, MI, DL, OpDesc, DestReg)
2018 .addFrameIndex(FrameIndex) // addr
2019 .addMemOperand(MMO)
2021
2022 return;
2023 }
2024
2025 unsigned Opcode = getVectorRegSpillRestoreOpcode(VReg ? VReg : DestReg, RC,
2026 SpillSize, *MFI);
2027 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
2028 .addFrameIndex(FrameIndex) // vaddr
2029 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
2030 .addImm(0) // offset
2031 .addMemOperand(MMO);
2032}
2033
2038
2041 unsigned Quantity) const {
2042 DebugLoc DL = MBB.findDebugLoc(MI);
2043 unsigned MaxSNopCount = 1u << ST.getSNopBits();
2044 while (Quantity > 0) {
2045 unsigned Arg = std::min(Quantity, MaxSNopCount);
2046 Quantity -= Arg;
2047 BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
2048 }
2049}
2050
2054 const DebugLoc &DL) const {
2055 MachineFunction *MF = MBB.getParent();
2056 constexpr unsigned DoorbellIDMask = 0x3ff;
2057 constexpr unsigned ECQueueWaveAbort = 0x400;
2058
2059 MachineBasicBlock *TrapBB = &MBB;
2060 MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock();
2061
2062 if (!MBB.succ_empty() ||
2064 /*SkipPseudoOp=*/false) != MBB.end()) {
2065 MBB.splitAt(MI, /*UpdateLiveIns=*/false);
2066 TrapBB = MF->CreateMachineBasicBlock();
2067 BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB);
2068 MF->push_back(TrapBB);
2069 MBB.addSuccessor(TrapBB);
2070 }
2071 // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this
2072 // will be a nop.
2073 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP))
2074 .addImm(static_cast<unsigned>(GCNSubtarget::TrapID::LLVMAMDHSATrap));
2075 Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2076 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32),
2077 DoorbellReg)
2079 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2080 .addUse(AMDGPU::M0);
2081 Register DoorbellRegMasked =
2082 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2083 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2084 .addUse(DoorbellReg)
2085 .addImm(DoorbellIDMask)
2086 .setOperandDead(3); // implicit-def $scc
2087 Register SetWaveAbortBit =
2088 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2089 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2090 .addUse(DoorbellRegMasked)
2091 .addImm(ECQueueWaveAbort)
2092 .setOperandDead(3); // implicit-def $scc
2093 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2094 .addUse(SetWaveAbortBit);
2095 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG))
2097 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2098 .addUse(AMDGPU::TTMP2);
2099 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB);
2100 TrapBB->addSuccessor(HaltLoopBB);
2101
2102 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5);
2103 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH))
2104 .addMBB(HaltLoopBB);
2105 MF->push_back(HaltLoopBB);
2106 HaltLoopBB->addSuccessor(HaltLoopBB);
2107
2108 return MBB.getNextNode();
2109}
2110
2112 switch (MI.getOpcode()) {
2113 default:
2114 if (MI.isMetaInstruction())
2115 return 0;
2116 return 1; // FIXME: Do wait states equal cycles?
2117
2118 case AMDGPU::S_NOP:
2119 return MI.getOperand(0).getImm() + 1;
2120 // SI_RETURN_TO_EPILOG is a fallthrough to code outside of the function. The
2121 // hazard, even if one exist, won't really be visible. Should we handle it?
2122 }
2123}
2124
2126 MachineBasicBlock &MBB = *MI.getParent();
2127 DebugLoc DL = MBB.findDebugLoc(MI);
2129
2130 switch (MI.getOpcode()) {
2131 default: return TargetInstrInfo::expandPostRAPseudo(MI);
2132 case AMDGPU::S_MOV_B64_term:
2133 // This is only a terminator to get the correct spill code placement during
2134 // register allocation.
2135 MI.setDesc(get(AMDGPU::S_MOV_B64));
2136 break;
2137
2138 case AMDGPU::S_MOV_B32_term:
2139 // This is only a terminator to get the correct spill code placement during
2140 // register allocation.
2141 MI.setDesc(get(AMDGPU::S_MOV_B32));
2142 break;
2143
2144 case AMDGPU::S_XOR_B64_term:
2145 // This is only a terminator to get the correct spill code placement during
2146 // register allocation.
2147 MI.setDesc(get(AMDGPU::S_XOR_B64));
2148 break;
2149
2150 case AMDGPU::S_XOR_B32_term:
2151 // This is only a terminator to get the correct spill code placement during
2152 // register allocation.
2153 MI.setDesc(get(AMDGPU::S_XOR_B32));
2154 break;
2155 case AMDGPU::S_OR_B64_term:
2156 // This is only a terminator to get the correct spill code placement during
2157 // register allocation.
2158 MI.setDesc(get(AMDGPU::S_OR_B64));
2159 break;
2160 case AMDGPU::S_OR_B32_term:
2161 // This is only a terminator to get the correct spill code placement during
2162 // register allocation.
2163 MI.setDesc(get(AMDGPU::S_OR_B32));
2164 break;
2165
2166 case AMDGPU::S_ANDN2_B64_term:
2167 // This is only a terminator to get the correct spill code placement during
2168 // register allocation.
2169 MI.setDesc(get(AMDGPU::S_ANDN2_B64));
2170 break;
2171
2172 case AMDGPU::S_ANDN2_B32_term:
2173 // This is only a terminator to get the correct spill code placement during
2174 // register allocation.
2175 MI.setDesc(get(AMDGPU::S_ANDN2_B32));
2176 break;
2177
2178 case AMDGPU::S_AND_B64_term:
2179 // This is only a terminator to get the correct spill code placement during
2180 // register allocation.
2181 MI.setDesc(get(AMDGPU::S_AND_B64));
2182 break;
2183
2184 case AMDGPU::S_AND_B32_term:
2185 // This is only a terminator to get the correct spill code placement during
2186 // register allocation.
2187 MI.setDesc(get(AMDGPU::S_AND_B32));
2188 break;
2189
2190 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2191 // This is only a terminator to get the correct spill code placement during
2192 // register allocation.
2193 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B64));
2194 break;
2195
2196 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2197 // This is only a terminator to get the correct spill code placement during
2198 // register allocation.
2199 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B32));
2200 break;
2201
2202 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2203 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2204 break;
2205 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2206 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2207 break;
2208
2209 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2210 MI.setDesc(get(AMDGPU::V_WRITELANE_B32));
2211 break;
2212
2213 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2214 MI.setDesc(get(AMDGPU::V_READLANE_B32));
2215 break;
2216 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2217 Register Dst = MI.getOperand(0).getReg();
2218 bool IsAGPR = SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst));
2219 MI.setDesc(
2220 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2221 break;
2222 }
2223 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2224 Register Dst = MI.getOperand(0).getReg();
2225 if (SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst))) {
2226 int64_t Imm = MI.getOperand(1).getImm();
2227
2228 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2229 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2230 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstLo)
2232 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstHi)
2233 .addImm(SignExtend64<32>(Imm >> 32));
2234 MI.eraseFromParent();
2235 break;
2236 }
2237
2238 [[fallthrough]];
2239 }
2240 case AMDGPU::V_MOV_B64_PSEUDO: {
2241 Register Dst = MI.getOperand(0).getReg();
2242 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2243 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2244
2245 const MCInstrDesc &Mov64Desc = get(AMDGPU::V_MOV_B64_e32);
2246 const TargetRegisterClass *Mov64RC = getRegClass(Mov64Desc, /*OpNum=*/0);
2247
2248 const MachineOperand &SrcOp = MI.getOperand(1);
2249 // FIXME: Will this work for 64-bit floating point immediates?
2250 assert(!SrcOp.isFPImm());
2251 if (ST.hasVMovB64Inst() && Mov64RC->contains(Dst)) {
2252 MI.setDesc(Mov64Desc);
2253 if (SrcOp.isReg() || isInlineConstant(MI, 1) ||
2254 (SrcOp.isImm() &&
2255 (isUInt<32>(SrcOp.getImm()) || ST.has64BitLiterals())) ||
2256 (SrcOp.isGlobal() && ST.has64BitLiterals()))
2257 break;
2258 }
2259 if (SrcOp.isGlobal()) {
2260 // The address is unknown until link time, so the PK_MOV inline-constant
2261 // shortcut cannot apply.
2262 const GlobalValue *GV = SrcOp.getGlobal();
2263 int64_t Offset = SrcOp.getOffset();
2264 unsigned BaseFlags, LoReloc, HiReloc;
2265 std::tie(BaseFlags, LoReloc, HiReloc) =
2267
2268 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2269 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2270 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2271 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2272 } else if (SrcOp.isImm()) {
2273 APInt Imm(64, SrcOp.getImm());
2274 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2275 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2276 const MCInstrDesc &PkMovDesc = get(AMDGPU::V_PK_MOV_B32);
2277 const TargetRegisterClass *PkMovRC = getRegClass(PkMovDesc, /*OpNum=*/0);
2278
2279 if (ST.hasPkMovB32() && Lo == Hi && isInlineConstant(Lo) &&
2280 PkMovRC->contains(Dst)) {
2281 BuildMI(MBB, MI, DL, PkMovDesc, Dst)
2283 .addImm(Lo.getSExtValue())
2285 .addImm(Lo.getSExtValue())
2286 .addImm(0) // op_sel_lo
2287 .addImm(0) // op_sel_hi
2288 .addImm(0) // neg_lo
2289 .addImm(0) // neg_hi
2290 .addImm(0); // clamp
2291 } else {
2292 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2293 .addImm(Lo.getSExtValue());
2294 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2295 .addImm(Hi.getSExtValue());
2296 }
2297 } else {
2298 assert(SrcOp.isReg());
2299 if (ST.hasPkMovB32() &&
2300 !RI.isAGPR(MBB.getParent()->getRegInfo(), SrcOp.getReg())) {
2301 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), Dst)
2302 .addImm(SISrcMods::OP_SEL_1) // src0_mod
2303 .addReg(SrcOp.getReg())
2305 .addReg(SrcOp.getReg())
2306 .addImm(0) // op_sel_lo
2307 .addImm(0) // op_sel_hi
2308 .addImm(0) // neg_lo
2309 .addImm(0) // neg_hi
2310 .addImm(0); // clamp
2311 } else {
2312 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2313 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0));
2314 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2315 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1));
2316 }
2317 }
2318 MI.eraseFromParent();
2319 break;
2320 }
2321 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2323 break;
2324 }
2325 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2326 const MachineOperand &SrcOp = MI.getOperand(1);
2327 assert(!SrcOp.isFPImm());
2328
2329 if (ST.has64BitLiterals()) {
2330 MI.setDesc(get(AMDGPU::S_MOV_B64));
2331 break;
2332 }
2333
2334 if (SrcOp.isGlobal()) {
2335 Register Dst = MI.getOperand(0).getReg();
2336 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2337 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2338 const GlobalValue *GV = SrcOp.getGlobal();
2339 int64_t Offset = SrcOp.getOffset();
2340 unsigned BaseFlags, LoReloc, HiReloc;
2341 std::tie(BaseFlags, LoReloc, HiReloc) =
2343
2344 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2345 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2346 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2347 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2348 MI.eraseFromParent();
2349 break;
2350 }
2351
2352 // SrcOp is immediate
2353 APInt Imm(64, SrcOp.getImm());
2354 if (Imm.isIntN(32) || isInlineConstant(Imm)) {
2355 MI.setDesc(get(AMDGPU::S_MOV_B64));
2356 break;
2357 }
2358
2359 Register Dst = MI.getOperand(0).getReg();
2360 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2361 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2362
2363 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2364 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2365 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2366 .addImm(Lo.getSExtValue());
2367 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2368 .addImm(Hi.getSExtValue());
2369 MI.eraseFromParent();
2370 break;
2371 }
2372 case AMDGPU::V_SET_INACTIVE_B32: {
2373 // Lower V_SET_INACTIVE_B32 to V_CNDMASK_B32.
2374 Register DstReg = MI.getOperand(0).getReg();
2375 BuildMI(MBB, MI, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2376 .add(MI.getOperand(3))
2377 .add(MI.getOperand(4))
2378 .add(MI.getOperand(1))
2379 .add(MI.getOperand(2))
2380 .add(MI.getOperand(5));
2381 MI.eraseFromParent();
2382 break;
2383 }
2384 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2385 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2386 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2387 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2388 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2389 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2390 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2391 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2392 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2393 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2394 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2395 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2396 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2397 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2398 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2399 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2400 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2401 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2402 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2403 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2404 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2405 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2406 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2407 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2408 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2409 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2410 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2411 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2412 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2413 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2414 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2415 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2416 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2417 const TargetRegisterClass *EltRC = getOpRegClass(MI, 2);
2418
2419 unsigned Opc;
2420 if (RI.hasVGPRs(EltRC)) {
2421 Opc = AMDGPU::V_MOVRELD_B32_e32;
2422 } else {
2423 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2424 : AMDGPU::S_MOVRELD_B32;
2425 }
2426
2427 const MCInstrDesc &OpDesc = get(Opc);
2428 Register VecReg = MI.getOperand(0).getReg();
2429 bool IsUndef = MI.getOperand(1).isUndef();
2430 unsigned SubReg = MI.getOperand(3).getImm();
2431 assert(VecReg == MI.getOperand(1).getReg());
2432
2434 BuildMI(MBB, MI, DL, OpDesc)
2435 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2436 .add(MI.getOperand(2))
2438 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2439
2440 const int ImpDefIdx =
2441 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2442 const int ImpUseIdx = ImpDefIdx + 1;
2443 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2444 MI.eraseFromParent();
2445 break;
2446 }
2447 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2448 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2449 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2450 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2451 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2452 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2453 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2454 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2455 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2456 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2457 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2458 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2459 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2460 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2461 assert(ST.useVGPRIndexMode());
2462 Register VecReg = MI.getOperand(0).getReg();
2463 bool IsUndef = MI.getOperand(1).isUndef();
2464 MachineOperand &Idx = MI.getOperand(3);
2465 Register SubReg = MI.getOperand(4).getImm();
2466
2467 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2468 .add(Idx)
2470 SetOn->getOperand(3).setIsUndef();
2471
2472 const MCInstrDesc &OpDesc = get(AMDGPU::V_MOV_B32_indirect_write);
2474 BuildMI(MBB, MI, DL, OpDesc)
2475 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2476 .add(MI.getOperand(2))
2478 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2479
2480 const int ImpDefIdx =
2481 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2482 const int ImpUseIdx = ImpDefIdx + 1;
2483 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2484
2485 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2486
2487 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2488
2489 MI.eraseFromParent();
2490 break;
2491 }
2492 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2493 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2494 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2495 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2496 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2497 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2498 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2499 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2500 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2501 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2502 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2503 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2504 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2505 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2506 assert(ST.useVGPRIndexMode());
2507 Register Dst = MI.getOperand(0).getReg();
2508 Register VecReg = MI.getOperand(1).getReg();
2509 bool IsUndef = MI.getOperand(1).isUndef();
2510 Register SubReg = MI.getOperand(3).getImm();
2511
2512 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2513 .add(MI.getOperand(2))
2515 SetOn->getOperand(3).setIsUndef();
2516
2517 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_indirect_read))
2518 .addDef(Dst)
2519 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2520 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2521
2522 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2523
2524 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2525
2526 MI.eraseFromParent();
2527 break;
2528 }
2529 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2530 MachineFunction &MF = *MBB.getParent();
2531 Register Reg = MI.getOperand(0).getReg();
2532 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2533 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2534 MachineOperand OpLo = MI.getOperand(1);
2535 MachineOperand OpHi = MI.getOperand(2);
2536
2537 // Create a bundle so these instructions won't be re-ordered by the
2538 // post-RA scheduler.
2539 MIBundleBuilder Bundler(MBB, MI);
2540 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2541
2542 // What we want here is an offset from the value returned by s_getpc (which
2543 // is the address of the s_add_u32 instruction) to the global variable, but
2544 // since the encoding of $symbol starts 4 bytes after the start of the
2545 // s_add_u32 instruction, we end up with an offset that is 4 bytes too
2546 // small. This requires us to add 4 to the global variable offset in order
2547 // to compute the correct address. Similarly for the s_addc_u32 instruction,
2548 // the encoding of $symbol starts 12 bytes after the start of the s_add_u32
2549 // instruction.
2550
2551 int64_t Adjust = 0;
2552 if (ST.hasGetPCZeroExtension()) {
2553 // Fix up hardware that does not sign-extend the 48-bit PC value by
2554 // inserting: s_sext_i32_i16 reghi, reghi
2555 Bundler.append(
2556 BuildMI(MF, DL, get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2557 Adjust += 4;
2558 }
2559
2560 if (OpLo.isGlobal())
2561 OpLo.setOffset(OpLo.getOffset() + Adjust + 4);
2562 Bundler.append(
2563 BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2564
2565 if (OpHi.isGlobal())
2566 OpHi.setOffset(OpHi.getOffset() + Adjust + 12);
2567 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi)
2568 .addReg(RegHi)
2569 .add(OpHi));
2570
2571 finalizeBundle(MBB, Bundler.begin());
2572
2573 MI.eraseFromParent();
2574 break;
2575 }
2576 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2577 MachineFunction &MF = *MBB.getParent();
2578 Register Reg = MI.getOperand(0).getReg();
2579 MachineOperand Op = MI.getOperand(1);
2580
2581 // Create a bundle so these instructions won't be re-ordered by the
2582 // post-RA scheduler.
2583 MIBundleBuilder Bundler(MBB, MI);
2584 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2585 if (Op.isGlobal())
2586 Op.setOffset(Op.getOffset() + 4);
2587 Bundler.append(
2588 BuildMI(MF, DL, get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(Op));
2589
2590 finalizeBundle(MBB, Bundler.begin());
2591
2592 MI.eraseFromParent();
2593 break;
2594 }
2595 case AMDGPU::ENTER_STRICT_WWM: {
2596 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2597 // Whole Wave Mode is entered.
2598 MI.setDesc(get(LMC.OrSaveExecOpc));
2599 break;
2600 }
2601 case AMDGPU::ENTER_STRICT_WQM: {
2602 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2603 // STRICT_WQM is entered.
2604 BuildMI(MBB, MI, DL, get(LMC.MovOpc), MI.getOperand(0).getReg())
2605 .addReg(LMC.ExecReg);
2606 BuildMI(MBB, MI, DL, get(LMC.WQMOpc), LMC.ExecReg).addReg(LMC.ExecReg);
2607
2608 MI.eraseFromParent();
2609 break;
2610 }
2611 case AMDGPU::EXIT_STRICT_WWM:
2612 case AMDGPU::EXIT_STRICT_WQM: {
2613 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2614 // WWM/STICT_WQM is exited.
2615 MI.setDesc(get(LMC.MovOpc));
2616 break;
2617 }
2618 case AMDGPU::SI_RETURN: {
2619 const MachineFunction *MF = MBB.getParent();
2620 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2621 const SIRegisterInfo *TRI = ST.getRegisterInfo();
2622 // Hiding the return address use with SI_RETURN may lead to extra kills in
2623 // the function and missing live-ins. We are fine in practice because callee
2624 // saved register handling ensures the register value is restored before
2625 // RET, but we need the undef flag here to appease the MachineVerifier
2626 // liveness checks.
2628 BuildMI(MBB, MI, DL, get(AMDGPU::S_SETPC_B64_return))
2629 .addReg(TRI->getReturnAddressReg(*MF), RegState::Undef);
2630
2631 MIB.copyImplicitOps(MI);
2632 MI.eraseFromParent();
2633 break;
2634 }
2635
2636 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2637 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2638 MI.setDesc(get(AMDGPU::S_MUL_U64));
2639 break;
2640
2641 case AMDGPU::S_GETPC_B64_pseudo:
2642 MI.setDesc(get(AMDGPU::S_GETPC_B64));
2643 if (ST.hasGetPCZeroExtension()) {
2644 Register Dst = MI.getOperand(0).getReg();
2645 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2646 // Fix up hardware that does not sign-extend the 48-bit PC value by
2647 // inserting: s_sext_i32_i16 dsthi, dsthi
2648 BuildMI(MBB, std::next(MI.getIterator()), DL, get(AMDGPU::S_SEXT_I32_I16),
2649 DstHi)
2650 .addReg(DstHi);
2651 }
2652 break;
2653
2654 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2655 assert(ST.hasBF16PackedInsts());
2656 MI.setDesc(get(AMDGPU::V_PK_MAX_NUM_BF16));
2657 MI.addOperand(MachineOperand::CreateImm(0)); // op_sel
2658 MI.addOperand(MachineOperand::CreateImm(0)); // neg_lo
2659 MI.addOperand(MachineOperand::CreateImm(0)); // neg_hi
2660 auto Op0 = getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
2661 Op0->setImm(Op0->getImm() | SISrcMods::OP_SEL_1);
2662 auto Op1 = getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
2663 Op1->setImm(Op1->getImm() | SISrcMods::OP_SEL_1);
2664 break;
2665 }
2666
2667 case AMDGPU::GET_STACK_BASE:
2668 // The stack starts at offset 0 unless we need to reserve some space at the
2669 // bottom.
2670 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*MBB.getParent())) {
2671 // When CWSR is used in dynamic VGPR mode, the trap handler needs to save
2672 // some of the VGPRs. The size of the required scratch space has already
2673 // been computed by prolog epilog insertion.
2674 const SIMachineFunctionInfo *MFI =
2675 MBB.getParent()->getInfo<SIMachineFunctionInfo>();
2676 unsigned VGPRSize = MFI->getScratchReservedForDynamicVGPRs();
2677 Register DestReg = MI.getOperand(0).getReg();
2678 BuildMI(MBB, MI, DL, get(AMDGPU::S_GETREG_B32), DestReg)
2681 // The MicroEngine ID is 0 for the graphics queue, and 1 or 2 for compute
2682 // (3 is unused, so we ignore it). Unfortunately, S_GETREG doesn't set
2683 // SCC, so we need to check for 0 manually.
2684 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)).addImm(0).addReg(DestReg);
2685 // Change the implicif-def of SCC to an explicit use (but first remove
2686 // the dead flag if present).
2687 MI.getOperand(MI.getNumExplicitOperands()).setIsDead(false);
2688 MI.getOperand(MI.getNumExplicitOperands()).setIsUse();
2689 MI.setDesc(get(AMDGPU::S_CMOVK_I32));
2690 MI.addOperand(MachineOperand::CreateImm(VGPRSize));
2691 } else {
2692 MI.setDesc(get(AMDGPU::S_MOV_B32));
2693 MI.addOperand(MachineOperand::CreateImm(0));
2694 MI.removeOperand(
2695 MI.getNumExplicitOperands()); // Drop implicit def of SCC.
2696 }
2697 break;
2698 }
2699
2700 return true;
2701}
2702
2705 unsigned SubIdx, const MachineInstr &Orig,
2706 LaneBitmask UsedLanes) const {
2707
2708 // Try shrinking the instruction to remat only the part needed for current
2709 // context.
2710 // TODO: Handle more cases.
2711 unsigned Opcode = Orig.getOpcode();
2712 switch (Opcode) {
2713 case AMDGPU::S_MOV_B64:
2714 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2715 if (SubIdx != 0)
2716 break;
2717
2718 if (!Orig.getOperand(1).isImm())
2719 break;
2720
2721 // Shrink S_MOV_B64 to S_MOV_B32 when UsedLanes indicates only a single
2722 // 32-bit lane of the 64-bit value is live at the rematerialization point.
2723 if (UsedLanes.all())
2724 break;
2725
2726 // Determine which half of the 64-bit immediate corresponds to the use.
2727 unsigned OrigSubReg = Orig.getOperand(0).getSubReg();
2728 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2729 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2730
2731 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2732 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2733
2734 if (NeedLo && NeedHi)
2735 break;
2736
2737 int64_t Imm64 = Orig.getOperand(1).getImm();
2738 int32_t Imm32 = NeedLo ? Lo_32(Imm64) : Hi_32(Imm64);
2739
2740 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2741
2742 // Emit S_MOV_B32 defining just the needed 32-bit subreg of DestReg.
2743 BuildMI(MBB, I, Orig.getDebugLoc(), get(AMDGPU::S_MOV_B32))
2744 .addReg(DestReg, RegState::Define | RegState::Undef, UseSubReg)
2745 .addImm(Imm32);
2746 return;
2747 }
2748
2749 case AMDGPU::S_LOAD_DWORDX16_IMM:
2750 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2751 if (SubIdx != 0 || UsedLanes.all())
2752 break;
2753
2754 if (I == MBB.end())
2755 break;
2756
2757 if (I->isBundled())
2758 break;
2759
2760 MachineFunction *MF = MBB.getParent();
2762 assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");
2763
2764 // Look for a single use of the register at the insertion point that is also
2765 // a subreg.
2766 Register RegToFind = Orig.getOperand(0).getReg();
2767 MachineOperand *UseMO = MRI.getOneNonDBGUse(RegToFind);
2768 if (!UseMO ||
2769 UseMO != I->findRegisterUseOperand(RegToFind, /*TRI=*/nullptr) ||
2770 UseMO->getSubReg() == AMDGPU::NoSubRegister)
2771 break;
2772
2773 unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
2774 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());
2775
2776 unsigned NewOpcode = -1;
2777 if (SubregSize == 256)
2778 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2779 else if (SubregSize == 128)
2780 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2781 else
2782 break;
2783
2784 const MCInstrDesc &TID = get(NewOpcode);
2785 const TargetRegisterClass *NewRC =
2786 RI.getAllocatableClass(getRegClass(TID, 0));
2787 MRI.setRegClass(DestReg, NewRC);
2788
2789 UseMO->setReg(DestReg);
2790 UseMO->setSubReg(AMDGPU::NoSubRegister);
2791
2792 // Use a smaller load with the desired size, possibly with updated offset.
2793 MachineInstr *MI = MF->CloneMachineInstr(&Orig);
2794 MI->setDesc(TID);
2795 MI->getOperand(0).setReg(DestReg);
2796 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2797 if (Offset) {
2798 MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
2799 int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
2800 OffsetMO->setImm(FinalOffset);
2801 }
2803 for (const MachineMemOperand *MemOp : Orig.memoperands())
2804 NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
2805 SubregSize / 8));
2806 MI->setMemRefs(*MF, NewMMOs);
2807
2808 MBB.insert(I, MI);
2809 return;
2810 }
2811
2812 default:
2813 break;
2814 }
2815
2816 TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
2817}
2818
2819std::pair<MachineInstr*, MachineInstr*>
2821 assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2822
2823 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2825 ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
2826 MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
2827 return std::pair(&MI, nullptr);
2828 }
2829
2830 MachineBasicBlock &MBB = *MI.getParent();
2831 DebugLoc DL = MBB.findDebugLoc(MI);
2832 MachineFunction *MF = MBB.getParent();
2834 Register Dst = MI.getOperand(0).getReg();
2835 unsigned Part = 0;
2836 MachineInstr *Split[2];
2837
2838 for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2839 auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
2840 if (Dst.isPhysical()) {
2841 MovDPP.addDef(RI.getSubReg(Dst, Sub));
2842 } else {
2843 assert(MRI.isSSA());
2844 auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2845 MovDPP.addDef(Tmp);
2846 }
2847
2848 for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
2849 const MachineOperand &SrcOp = MI.getOperand(I);
2850 assert(!SrcOp.isFPImm());
2851 if (SrcOp.isImm()) {
2852 APInt Imm(64, SrcOp.getImm());
2853 Imm.ashrInPlace(Part * 32);
2854 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2855 } else {
2856 assert(SrcOp.isReg());
2857 Register Src = SrcOp.getReg();
2858 if (Src.isPhysical())
2859 MovDPP.addReg(RI.getSubReg(Src, Sub));
2860 else
2861 MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
2862 }
2863 }
2864
2865 for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
2866 MovDPP.addImm(MO.getImm());
2867
2868 Split[Part] = MovDPP;
2869 ++Part;
2870 }
2871
2872 if (Dst.isVirtual())
2873 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
2874 .addReg(Split[0]->getOperand(0).getReg())
2875 .addImm(AMDGPU::sub0)
2876 .addReg(Split[1]->getOperand(0).getReg())
2877 .addImm(AMDGPU::sub1);
2878
2879 MI.eraseFromParent();
2880 return std::pair(Split[0], Split[1]);
2881}
2882
2883std::optional<DestSourcePair>
2885 if (MI.getOpcode() == AMDGPU::WWM_COPY)
2886 return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
2887
2888 return std::nullopt;
2889}
2890
2892 AMDGPU::OpName Src0OpName,
2893 MachineOperand &Src1,
2894 AMDGPU::OpName Src1OpName) const {
2895 MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
2896 if (!Src0Mods)
2897 return false;
2898
2899 MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
2900 assert(Src1Mods &&
2901 "All commutable instructions have both src0 and src1 modifiers");
2902
2903 int Src0ModsVal = Src0Mods->getImm();
2904 int Src1ModsVal = Src1Mods->getImm();
2905
2906 Src1Mods->setImm(Src0ModsVal);
2907 Src0Mods->setImm(Src1ModsVal);
2908 return true;
2909}
2910
2912 MachineOperand &RegOp,
2913 MachineOperand &NonRegOp) {
2914 Register Reg = RegOp.getReg();
2915 unsigned SubReg = RegOp.getSubReg();
2916 bool IsKill = RegOp.isKill();
2917 bool IsDead = RegOp.isDead();
2918 bool IsUndef = RegOp.isUndef();
2919 bool IsDebug = RegOp.isDebug();
2920
2921 if (NonRegOp.isImm())
2922 RegOp.ChangeToImmediate(NonRegOp.getImm());
2923 else if (NonRegOp.isFI())
2924 RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
2925 else if (NonRegOp.isGlobal()) {
2926 RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
2927 NonRegOp.getTargetFlags());
2928 } else
2929 return nullptr;
2930
2931 // Make sure we don't reinterpret a subreg index in the target flags.
2932 RegOp.setTargetFlags(NonRegOp.getTargetFlags());
2933
2934 NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
2935 NonRegOp.setSubReg(SubReg);
2936
2937 return &MI;
2938}
2939
2941 MachineOperand &NonRegOp1,
2942 MachineOperand &NonRegOp2) {
2943 unsigned TargetFlags = NonRegOp1.getTargetFlags();
2944 int64_t NonRegVal = NonRegOp1.getImm();
2945
2946 NonRegOp1.setImm(NonRegOp2.getImm());
2947 NonRegOp2.setImm(NonRegVal);
2948 NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
2949 NonRegOp2.setTargetFlags(TargetFlags);
2950 return &MI;
2951}
2952
2953bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
2954 unsigned OpIdx1) const {
2955 const MCInstrDesc &InstDesc = MI.getDesc();
2956 const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
2957 const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];
2958
2959 unsigned Opc = MI.getOpcode();
2960 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2961
2962 const MachineOperand &MO0 = MI.getOperand(OpIdx0);
2963 const MachineOperand &MO1 = MI.getOperand(OpIdx1);
2964
2965 // Swap doesn't breach constant bus or literal limits, but it may move a
2966 // constant out of src0. Allow that for immediates where the destination
2967 // operand can hold them, e.g. VOP3 sources on targets with VOP3 literal
2968 // support. Other non-register operands stay in src0.
2969 if (isVALU(MI, /*AllowLDSDMA=*/false)) {
2970 if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
2971 (!MO0.isImm() || !isImmOperandLegal(MI, OpIdx1, MO0)))
2972 return false;
2973 if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
2974 (!MO1.isImm() || !isImmOperandLegal(MI, OpIdx0, MO1)))
2975 return false;
2976 }
2977
2978 if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
2979 if (OpInfo1.RegClass == -1)
2980 return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
2981 return isLegalRegOperand(MI, OpIdx1, MO0) &&
2982 (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
2983 }
2984 if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
2985 if (OpInfo0.RegClass == -1)
2986 return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
2987 return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
2988 isLegalRegOperand(MI, OpIdx0, MO1);
2989 }
2990
2991 // No need to check 64-bit literals since swapping does not bring new
2992 // 64-bit literals into current instruction to fold to 32-bit
2993
2994 return isImmOperandLegal(MI, OpIdx1, MO0);
2995}
2996
2998 if (!isDPP(MI))
2999 return false;
3000 const MachineOperand *DppCtrl = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
3001 return !DppCtrl || DppCtrl->getImm() != AMDGPU::DPP::QUAD_PERM_ID;
3002}
3003
3005 unsigned Src0Idx,
3006 unsigned Src1Idx) const {
3007 assert(!NewMI && "this should never be used");
3008
3010 return nullptr;
3011
3012 unsigned Opc = MI.getOpcode();
3013 int CommutedOpcode = commuteOpcode(Opc);
3014 if (CommutedOpcode == -1)
3015 return nullptr;
3016
3017 if (Src0Idx > Src1Idx)
3018 std::swap(Src0Idx, Src1Idx);
3019
3020 assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
3021 static_cast<int>(Src0Idx) &&
3022 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
3023 static_cast<int>(Src1Idx) &&
3024 "inconsistency with findCommutedOpIndices");
3025
3026 if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
3027 return nullptr;
3028
3029 MachineInstr *CommutedMI = nullptr;
3030 MachineOperand &Src0 = MI.getOperand(Src0Idx);
3031 MachineOperand &Src1 = MI.getOperand(Src1Idx);
3032 if (Src0.isReg() && Src1.isReg()) {
3033 // Be sure to copy the source modifiers to the right place.
3034 CommutedMI =
3035 TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
3036 } else if (Src0.isReg() && !Src1.isReg()) {
3037 CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
3038 } else if (!Src0.isReg() && Src1.isReg()) {
3039 CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
3040 } else if (Src0.isImm() && Src1.isImm()) {
3041 CommutedMI = swapImmOperands(MI, Src0, Src1);
3042 } else {
3043 // FIXME: Found two non registers to commute. This does happen.
3044 return nullptr;
3045 }
3046
3047 if (CommutedMI) {
3048 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
3049 Src1, AMDGPU::OpName::src1_modifiers);
3050
3051 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
3052 AMDGPU::OpName::src1_sel);
3053
3054 CommutedMI->setDesc(get(CommutedOpcode));
3055 }
3056
3057 return CommutedMI;
3058}
3059
3060// This needs to be implemented because the source modifiers may be inserted
3061// between the true commutable operands, and the base
3062// TargetInstrInfo::commuteInstruction uses it.
3064 unsigned &SrcOpIdx0,
3065 unsigned &SrcOpIdx1) const {
3067 return false;
3068
3069 return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
3070}
3071
3073 unsigned &SrcOpIdx0,
3074 unsigned &SrcOpIdx1) const {
3075 if (!Desc.isCommutable())
3076 return false;
3077
3078 unsigned Opc = Desc.getOpcode();
3079 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
3080 if (Src0Idx == -1)
3081 return false;
3082
3083 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
3084 if (Src1Idx == -1)
3085 return false;
3086
3087 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3088}
3089
3091 int64_t BrOffset) const {
3092 // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
3093 // because its dest block is unanalyzable.
3094 assert(isSOPP(BranchOp) || isSOPK(BranchOp));
3095
3096 // Convert to dwords.
3097 BrOffset /= 4;
3098
3099 // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
3100 // from the next instruction.
3101 BrOffset -= 1;
3102
3103 return isIntN(BranchOffsetBits, BrOffset);
3104}
3105
3108 return MI.getOperand(0).getMBB();
3109}
3110
3112 for (const MachineInstr &MI : MBB->terminators()) {
3113 if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
3114 MI.getOpcode() == AMDGPU::SI_LOOP ||
3115 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3116 return true;
3117 }
3118 return false;
3119}
3120
3122 MachineBasicBlock &DestBB,
3123 MachineBasicBlock &RestoreBB,
3124 const DebugLoc &DL, int64_t BrOffset,
3125 RegScavenger *RS) const {
3126 assert(MBB.empty() &&
3127 "new block should be inserted for expanding unconditional branch");
3128 assert(MBB.pred_size() == 1);
3129 assert(RestoreBB.empty() &&
3130 "restore block should be inserted for restoring clobbered registers");
3131
3132 MachineFunction *MF = MBB.getParent();
3135 auto I = MBB.end();
3136 auto &MCCtx = MF->getContext();
3137
3138 if (ST.useAddPCI64Inst()) {
3139 MCSymbol *Offset =
3140 MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
3141 auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
3143 MCSymbol *PostAddPCLabel =
3144 MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
3145 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3146 auto *OffsetExpr = MCBinaryExpr::createSub(
3147 MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
3148 MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
3149 Offset->setVariableValue(OffsetExpr);
3150 return;
3151 }
3152
3153 assert(RS && "RegScavenger required for long branching");
3154
3155 // FIXME: Virtual register workaround for RegScavenger not working with empty
3156 // blocks.
3157 Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3158
3159 // Note: as this is used after hazard recognizer we need to apply some hazard
3160 // workarounds directly.
3161 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3162 ST.hasVALUReadSGPRHazard();
3163 auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
3164 if (FlushSGPRWrites)
3165 BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
3167 };
3168
3169 // We need to compute the offset relative to the instruction immediately after
3170 // s_getpc_b64. Insert pc arithmetic code before last terminator.
3171 MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
3172 ApplyHazardWorkarounds();
3173
3174 MCSymbol *PostGetPCLabel =
3175 MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
3176 GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);
3177
3178 MCSymbol *OffsetLo =
3179 MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
3180 MCSymbol *OffsetHi =
3181 MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
3182 BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
3183 .addReg(PCReg, RegState::Define, AMDGPU::sub0)
3184 .addReg(PCReg, {}, AMDGPU::sub0)
3185 .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
3186 BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
3187 .addReg(PCReg, RegState::Define, AMDGPU::sub1)
3188 .addReg(PCReg, {}, AMDGPU::sub1)
3189 .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
3190 ApplyHazardWorkarounds();
3191
3192 // Insert the indirect branch after the other terminator.
3193 BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
3194 .addReg(PCReg);
3195
3196 // If a spill is needed for the pc register pair, we need to insert a spill
3197 // restore block right before the destination block, and insert a short branch
3198 // into the old destination block's fallthrough predecessor.
3199 // e.g.:
3200 //
3201 // s_cbranch_scc0 skip_long_branch:
3202 //
3203 // long_branch_bb:
3204 // spill s[8:9]
3205 // s_getpc_b64 s[8:9]
3206 // s_add_u32 s8, s8, restore_bb
3207 // s_addc_u32 s9, s9, 0
3208 // s_setpc_b64 s[8:9]
3209 //
3210 // skip_long_branch:
3211 // foo;
3212 //
3213 // .....
3214 //
3215 // dest_bb_fallthrough_predecessor:
3216 // bar;
3217 // s_branch dest_bb
3218 //
3219 // restore_bb:
3220 // restore s[8:9]
3221 // fallthrough dest_bb
3222 ///
3223 // dest_bb:
3224 // buzz;
3225
3226 Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
3227 Register Scav;
3228
3229 // If we've previously reserved a register for long branches
3230 // avoid running the scavenger and just use those registers
3231 if (LongBranchReservedReg) {
3232 RS->enterBasicBlock(MBB);
3233 Scav = LongBranchReservedReg;
3234 } else {
3235 RS->enterBasicBlockEnd(MBB);
3236 Scav = RS->scavengeRegisterBackwards(
3237 AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
3238 /* RestoreAfter */ false, 0, /* AllowSpill */ false);
3239 }
3240 if (Scav) {
3241 RS->setRegUsed(Scav);
3242 MRI.replaceRegWith(PCReg, Scav);
3243 MRI.clearVirtRegs();
3244 } else {
3245 // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
3246 // SGPR spill.
3247 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
3248 const SIRegisterInfo *TRI = ST.getRegisterInfo();
3249 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3250 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3251 MRI.clearVirtRegs();
3252 }
3253
3254 MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
3255 // Now, the distance could be defined.
3257 MCSymbolRefExpr::create(DestLabel, MCCtx),
3258 MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
3259 // Add offset assignments.
3260 auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
3261 OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
3262 auto *ShAmt = MCConstantExpr::create(32, MCCtx);
3263 OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
3264}
3265
3266unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
3267 switch (Cond) {
3268 case SIInstrInfo::SCC_TRUE:
3269 return AMDGPU::S_CBRANCH_SCC1;
3270 case SIInstrInfo::SCC_FALSE:
3271 return AMDGPU::S_CBRANCH_SCC0;
3272 case SIInstrInfo::VCCNZ:
3273 return AMDGPU::S_CBRANCH_VCCNZ;
3274 case SIInstrInfo::VCCZ:
3275 return AMDGPU::S_CBRANCH_VCCZ;
3276 case SIInstrInfo::EXECNZ:
3277 return AMDGPU::S_CBRANCH_EXECNZ;
3278 case SIInstrInfo::EXECZ:
3279 return AMDGPU::S_CBRANCH_EXECZ;
3280 default:
3281 llvm_unreachable("invalid branch predicate");
3282 }
3283}
3284
3285SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
3286 switch (Opcode) {
3287 case AMDGPU::S_CBRANCH_SCC0:
3288 return SCC_FALSE;
3289 case AMDGPU::S_CBRANCH_SCC1:
3290 return SCC_TRUE;
3291 case AMDGPU::S_CBRANCH_VCCNZ:
3292 return VCCNZ;
3293 case AMDGPU::S_CBRANCH_VCCZ:
3294 return VCCZ;
3295 case AMDGPU::S_CBRANCH_EXECNZ:
3296 return EXECNZ;
3297 case AMDGPU::S_CBRANCH_EXECZ:
3298 return EXECZ;
3299 default:
3300 return INVALID_BR;
3301 }
3302}
3303
3307 MachineBasicBlock *&FBB,
3309 bool AllowModify) const {
3310 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3311 // Unconditional Branch
3312 TBB = I->getOperand(0).getMBB();
3313 return false;
3314 }
3315
3316 BranchPredicate Pred = getBranchPredicate(I->getOpcode());
3317 if (Pred == INVALID_BR)
3318 return true;
3319
3320 MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
3321 Cond.push_back(MachineOperand::CreateImm(Pred));
3322 Cond.push_back(I->getOperand(1)); // Save the branch register.
3323
3324 ++I;
3325
3326 if (I == MBB.end()) {
3327 // Conditional branch followed by fall-through.
3328 TBB = CondBB;
3329 return false;
3330 }
3331
3332 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3333 TBB = CondBB;
3334 FBB = I->getOperand(0).getMBB();
3335 return false;
3336 }
3337
3338 return true;
3339}
3340
3342 MachineBasicBlock *&FBB,
3344 bool AllowModify) const {
3345 MachineBasicBlock::iterator I = MBB.getFirstTerminator();
3346 auto E = MBB.end();
3347 if (I == E)
3348 return false;
3349
3350 // Skip over the instructions that are artificially terminators for special
3351 // exec management.
3352 while (I != E && !I->isBranch() && !I->isReturn()) {
3353 switch (I->getOpcode()) {
3354 case AMDGPU::S_MOV_B64_term:
3355 case AMDGPU::S_XOR_B64_term:
3356 case AMDGPU::S_OR_B64_term:
3357 case AMDGPU::S_ANDN2_B64_term:
3358 case AMDGPU::S_AND_B64_term:
3359 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3360 case AMDGPU::S_MOV_B32_term:
3361 case AMDGPU::S_XOR_B32_term:
3362 case AMDGPU::S_OR_B32_term:
3363 case AMDGPU::S_ANDN2_B32_term:
3364 case AMDGPU::S_AND_B32_term:
3365 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3366 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3367 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3368 break;
3369 case AMDGPU::SI_IF:
3370 case AMDGPU::SI_ELSE:
3371 case AMDGPU::SI_KILL_I1_TERMINATOR:
3372 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3373 // FIXME: It's messy that these need to be considered here at all.
3374 return true;
3375 default:
3376 llvm_unreachable("unexpected non-branch terminator inst");
3377 }
3378
3379 ++I;
3380 }
3381
3382 if (I == E)
3383 return false;
3384
3385 return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
3386}
3387
3389 int *BytesRemoved) const {
3390 unsigned Count = 0;
3391 unsigned RemovedSize = 0;
3392 for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
3393 // Skip over artificial terminators when removing instructions.
3394 if (MI.isBranch() || MI.isReturn()) {
3395 RemovedSize += getInstSizeInBytes(MI);
3396 MI.eraseFromParent();
3397 ++Count;
3398 }
3399 }
3400
3401 if (BytesRemoved)
3402 *BytesRemoved = RemovedSize;
3403
3404 return Count;
3405}
3406
3407// Copy the flags onto the implicit condition register operand.
3409 const MachineOperand &OrigCond) {
3410 CondReg.setIsUndef(OrigCond.isUndef());
3411 CondReg.setIsKill(OrigCond.isKill());
3412}
3413
3416 MachineBasicBlock *FBB,
3418 const DebugLoc &DL,
3419 int *BytesAdded) const {
3420 if (!FBB && Cond.empty()) {
3421 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3422 .addMBB(TBB);
3423 if (BytesAdded)
3424 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3425 return 1;
3426 }
3427
3428 assert(TBB && Cond[0].isImm());
3429
3430 unsigned Opcode
3431 = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));
3432
3433 if (!FBB) {
3434 MachineInstr *CondBr =
3435 BuildMI(&MBB, DL, get(Opcode))
3436 .addMBB(TBB);
3437
3438 // Copy the flags onto the implicit condition register operand.
3439 preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
3440 fixImplicitOperands(*CondBr);
3441
3442 if (BytesAdded)
3443 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3444 return 1;
3445 }
3446
3447 assert(TBB && FBB);
3448
3449 MachineInstr *CondBr =
3450 BuildMI(&MBB, DL, get(Opcode))
3451 .addMBB(TBB);
3452 fixImplicitOperands(*CondBr);
3453 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3454 .addMBB(FBB);
3455
3456 MachineOperand &CondReg = CondBr->getOperand(1);
3457 CondReg.setIsUndef(Cond[1].isUndef());
3458 CondReg.setIsKill(Cond[1].isKill());
3459
3460 if (BytesAdded)
3461 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3462
3463 return 2;
3464}
3465
3468 if (Cond.size() != 2) {
3469 return true;
3470 }
3471
3472 if (Cond[0].isImm()) {
3473 Cond[0].setImm(-Cond[0].getImm());
3474 return false;
3475 }
3476
3477 return true;
3478}
3479
3480namespace {
3481class AMDGPUPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
3482private:
3483 /// The compare instruction for loop control
3484 const MachineInstr *CmpInst = nullptr;
3485 /// The normalized condition used by createTripCountGreaterCondition()
3487
3488public:
3489 AMDGPUPipelinerLoopInfo(MachineInstr *CmpInst,
3491 : CmpInst(CmpInst), Cond(Cond.begin(), Cond.end()) {}
3492
3493 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
3494 return CmpInst && MI == CmpInst;
3495 }
3496
3497 std::optional<bool> createTripCountGreaterCondition(
3498 int TC, MachineBasicBlock &MBB,
3499 SmallVectorImpl<MachineOperand> &CondParam) override {
3500 CondParam = this->Cond;
3501 return {};
3502 }
3503
3504 void adjustTripCount(int TripCountAdjust) override {}
3505
3506 void setPreheader(MachineBasicBlock *NewPreheader) override {}
3507};
3508} // namespace
3509
3510std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3512 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
3514 // Unanalyzable terminator.
3515 if (analyzeBranch(*LoopBB, TBB, FBB, Cond, /*AllowModify=*/false))
3516 return nullptr;
3517
3518 // Infinite loops are not supported.
3519 if (TBB == LoopBB && FBB == LoopBB)
3520 return nullptr;
3521
3522 // Must be conditional branch.
3523 if (FBB == nullptr)
3524 return nullptr;
3525
3526 assert((TBB == LoopBB || FBB == LoopBB) &&
3527 "The Loop must be a single-basic-block loop");
3528
3529 // Divergent (VCC/EXEC) back-edge is not supported.
3530 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3531 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3532 return nullptr;
3533
3534 // Calls and inline assembly are not supported.
3535 for (const MachineInstr &MI : *LoopBB)
3536 if (MI.isCall() || MI.isInlineAsm())
3537 return nullptr;
3538
3539 // Normalization for createTripCountGreaterCondition(): make Cond mean
3540 // "exit the loop" so the expander emits correct prolog guard branches.
3541 if (TBB == LoopBB)
3543
3544 auto Instructions = make_range(
3546 LoopBB->rend());
3547 auto CmpI = llvm::find_if(Instructions, [&](const MachineInstr &MI) {
3548 return MI.modifiesRegister(Cond[1].getReg(), &RI);
3549 });
3550
3551 if (CmpI == Instructions.end() || CmpI->isPHI())
3552 return nullptr;
3553 MachineInstr *CmpInst = &*CmpI;
3554
3555 return std::make_unique<AMDGPUPipelinerLoopInfo>(CmpInst, Cond);
3556}
3557
3560 Register DstReg, Register TrueReg,
3561 Register FalseReg,
3562 SelectExpansion &Exp) const {
3563 switch (Cond[0].getImm()) {
3564 case VCCNZ:
3565 case VCCZ: {
3566 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3567 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3568 if (MRI.getRegClass(FalseReg) != RC)
3569 return false;
3570
3571 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3572 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts; // ???
3573
3574 // Limit to equal cost for branch vs. N v_cndmask_b32s.
3575 return RI.hasVGPRs(RC) && NumInsts <= 6;
3576 }
3577 case SCC_TRUE:
3578 case SCC_FALSE: {
3579 // FIXME: We could insert for VGPRs if we could replace the original compare
3580 // with a vector one.
3581 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3582 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3583 if (MRI.getRegClass(FalseReg) != RC)
3584 return false;
3585
3586 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3587
3588 // Multiples of 8 can do s_cselect_b64
3589 if (NumInsts % 2 == 0)
3590 NumInsts /= 2;
3591
3592 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts; // ???
3593 return RI.isSGPRClass(RC);
3594 }
3595 default:
3596 return false;
3597 }
3598}
3599
3603 Register TrueReg, Register FalseReg) const {
3604 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3605 if (Pred == VCCZ || Pred == SCC_FALSE) {
3606 Pred = static_cast<BranchPredicate>(-Pred);
3607 std::swap(TrueReg, FalseReg);
3608 }
3609
3610 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3611 const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
3612 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3613
3614 if (DstSize == 32) {
3616 if (Pred == SCC_TRUE) {
3617 Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
3618 .addReg(TrueReg)
3619 .addReg(FalseReg);
3620 } else {
3621 // Instruction's operands are backwards from what is expected.
3622 Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
3623 .addReg(FalseReg)
3624 .addReg(TrueReg);
3625 }
3626
3627 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3628 return;
3629 }
3630
3631 if (DstSize == 64 && Pred == SCC_TRUE) {
3633 BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
3634 .addReg(TrueReg)
3635 .addReg(FalseReg);
3636
3637 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3638 return;
3639 }
3640
3641 static const int16_t Sub0_15[] = {
3642 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3643 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3644 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3645 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3646 };
3647
3648 static const int16_t Sub0_15_64[] = {
3649 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3650 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3651 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3652 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3653 };
3654
3655 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3656 const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
3657 const int16_t *SubIndices = Sub0_15;
3658 int NElts = DstSize / 32;
3659
3660 // 64-bit select is only available for SALU.
3661 // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
3662 if (Pred == SCC_TRUE) {
3663 if (NElts % 2) {
3664 SelOp = AMDGPU::S_CSELECT_B32;
3665 EltRC = &AMDGPU::SGPR_32RegClass;
3666 } else {
3667 SelOp = AMDGPU::S_CSELECT_B64;
3668 EltRC = &AMDGPU::SGPR_64RegClass;
3669 SubIndices = Sub0_15_64;
3670 NElts /= 2;
3671 }
3672 }
3673
3675 MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);
3676
3677 I = MIB->getIterator();
3678
3680 for (int Idx = 0; Idx != NElts; ++Idx) {
3681 Register DstElt = MRI.createVirtualRegister(EltRC);
3682 Regs.push_back(DstElt);
3683
3684 unsigned SubIdx = SubIndices[Idx];
3685
3687 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3688 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3689 .addReg(FalseReg, {}, SubIdx)
3690 .addReg(TrueReg, {}, SubIdx);
3691 } else {
3692 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3693 .addReg(TrueReg, {}, SubIdx)
3694 .addReg(FalseReg, {}, SubIdx);
3695 }
3696
3697 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3699
3700 MIB.addReg(DstElt)
3701 .addImm(SubIdx);
3702 }
3703}
3704
3706
3707 if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
3708 return true;
3709
3710 switch (MI.getOpcode()) {
3711 case AMDGPU::S_ENDPGM:
3712 case AMDGPU::S_ENDPGM_SAVED:
3713 case AMDGPU::S_TRAP:
3714 case AMDGPU::S_GETREG_B32:
3715 case AMDGPU::S_SETREG_B32:
3716 case AMDGPU::S_SETREG_B32_mode:
3717 case AMDGPU::S_SETREG_IMM32_B32:
3718 case AMDGPU::S_SETREG_IMM32_B32_mode:
3719 case AMDGPU::S_SENDMSG:
3720 case AMDGPU::S_SENDMSGHALT:
3721 case AMDGPU::S_SENDMSG_RTN_B32:
3722 case AMDGPU::S_SENDMSG_RTN_B64:
3723 case AMDGPU::S_BARRIER_WAIT:
3724 case AMDGPU::S_BARRIER_SIGNAL_M0:
3725 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3726 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3727 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3728 return true;
3729 default:
3730 return false;
3731 }
3732}
3733
3735 switch (MI.getOpcode()) {
3736 case AMDGPU::V_MOV_B16_t16_e32:
3737 case AMDGPU::V_MOV_B16_t16_e64:
3738 case AMDGPU::V_MOV_B32_e32:
3739 case AMDGPU::V_MOV_B32_e64:
3740 case AMDGPU::V_MOV_B64_PSEUDO:
3741 case AMDGPU::V_MOV_B64_e32:
3742 case AMDGPU::V_MOV_B64_e64:
3743 case AMDGPU::S_MOV_B32:
3744 case AMDGPU::S_MOV_B64:
3745 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3746 case AMDGPU::COPY:
3747 case AMDGPU::WWM_COPY:
3748 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3749 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3750 case AMDGPU::V_ACCVGPR_MOV_B32:
3751 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3752 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3753 return true;
3754 default:
3755 return false;
3756 }
3757}
3758
3760 switch (MI.getOpcode()) {
3761 case AMDGPU::V_MOV_B16_t16_e32:
3762 case AMDGPU::V_MOV_B16_t16_e64:
3763 return 2;
3764 case AMDGPU::V_MOV_B32_e32:
3765 case AMDGPU::V_MOV_B32_e64:
3766 case AMDGPU::V_MOV_B64_PSEUDO:
3767 case AMDGPU::V_MOV_B64_e32:
3768 case AMDGPU::V_MOV_B64_e64:
3769 case AMDGPU::S_MOV_B32:
3770 case AMDGPU::S_MOV_B64:
3771 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3772 case AMDGPU::COPY:
3773 case AMDGPU::WWM_COPY:
3774 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3775 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3776 case AMDGPU::V_ACCVGPR_MOV_B32:
3777 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3778 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3779 return 1;
3780 default:
3781 llvm_unreachable("MI is not a foldable copy");
3782 }
3783}
3784
3785static constexpr AMDGPU::OpName ModifierOpNames[] = {
3786 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3787 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3788 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3789
3791 unsigned Opc = MI.getOpcode();
3792 for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
3793 int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
3794 if (Idx >= 0)
3795 MI.removeOperand(Idx);
3796 }
3797}
3798
3800 const MCInstrDesc &NewDesc) const {
3801 MI.setDesc(NewDesc);
3802
3803 // Remove any leftover implicit operands from mutating the instruction. e.g.
3804 // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
3805 // anymore.
3806 const MCInstrDesc &Desc = MI.getDesc();
3807 unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
3808 Desc.implicit_defs().size();
3809
3810 for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
3811 MI.removeOperand(I);
3812}
3813
3814std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
3815 unsigned SubRegIndex) {
3816 switch (SubRegIndex) {
3817 case AMDGPU::NoSubRegister:
3818 return Imm;
3819 case AMDGPU::sub0:
3820 return SignExtend64<32>(Imm);
3821 case AMDGPU::sub1:
3822 return SignExtend64<32>(Imm >> 32);
3823 case AMDGPU::lo16:
3824 return SignExtend64<16>(Imm);
3825 case AMDGPU::hi16:
3826 return SignExtend64<16>(Imm >> 16);
3827 case AMDGPU::sub1_lo16:
3828 return SignExtend64<16>(Imm >> 32);
3829 case AMDGPU::sub1_hi16:
3830 return SignExtend64<16>(Imm >> 48);
3831 default:
3832 return std::nullopt;
3833 }
3834
3835 llvm_unreachable("covered subregister switch");
3836}
3837
3838static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
3839 switch (Opc) {
3840 case AMDGPU::V_MAC_F16_e32:
3841 case AMDGPU::V_MAC_F16_e64:
3842 case AMDGPU::V_MAD_F16_e64:
3843 return AMDGPU::V_MADAK_F16;
3844 case AMDGPU::V_MAC_F32_e32:
3845 case AMDGPU::V_MAC_F32_e64:
3846 case AMDGPU::V_MAD_F32_e64:
3847 return AMDGPU::V_MADAK_F32;
3848 case AMDGPU::V_FMAC_F32_e32:
3849 case AMDGPU::V_FMAC_F32_e64:
3850 case AMDGPU::V_FMA_F32_e64:
3851 return AMDGPU::V_FMAAK_F32;
3852 case AMDGPU::V_FMAC_F16_e32:
3853 case AMDGPU::V_FMAC_F16_e64:
3854 case AMDGPU::V_FMAC_F16_t16_e64:
3855 case AMDGPU::V_FMAC_F16_fake16_e64:
3856 case AMDGPU::V_FMAC_F16_t16_e32:
3857 case AMDGPU::V_FMAC_F16_fake16_e32:
3858 case AMDGPU::V_FMA_F16_e64:
3859 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3860 ? AMDGPU::V_FMAAK_F16_t16
3861 : AMDGPU::V_FMAAK_F16_fake16
3862 : AMDGPU::V_FMAAK_F16;
3863 case AMDGPU::V_FMAC_F64_e32:
3864 case AMDGPU::V_FMAC_F64_e64:
3865 case AMDGPU::V_FMA_F64_e64:
3866 return AMDGPU::V_FMAAK_F64;
3867 default:
3868 llvm_unreachable("invalid instruction");
3869 }
3870}
3871
3872static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
3873 switch (Opc) {
3874 case AMDGPU::V_MAC_F16_e32:
3875 case AMDGPU::V_MAC_F16_e64:
3876 case AMDGPU::V_MAD_F16_e64:
3877 return AMDGPU::V_MADMK_F16;
3878 case AMDGPU::V_MAC_F32_e32:
3879 case AMDGPU::V_MAC_F32_e64:
3880 case AMDGPU::V_MAD_F32_e64:
3881 return AMDGPU::V_MADMK_F32;
3882 case AMDGPU::V_FMAC_F32_e32:
3883 case AMDGPU::V_FMAC_F32_e64:
3884 case AMDGPU::V_FMA_F32_e64:
3885 return AMDGPU::V_FMAMK_F32;
3886 case AMDGPU::V_FMAC_F16_e32:
3887 case AMDGPU::V_FMAC_F16_e64:
3888 case AMDGPU::V_FMAC_F16_t16_e64:
3889 case AMDGPU::V_FMAC_F16_fake16_e64:
3890 case AMDGPU::V_FMAC_F16_t16_e32:
3891 case AMDGPU::V_FMAC_F16_fake16_e32:
3892 case AMDGPU::V_FMA_F16_e64:
3893 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3894 ? AMDGPU::V_FMAMK_F16_t16
3895 : AMDGPU::V_FMAMK_F16_fake16
3896 : AMDGPU::V_FMAMK_F16;
3897 case AMDGPU::V_FMAC_F64_e32:
3898 case AMDGPU::V_FMAC_F64_e64:
3899 case AMDGPU::V_FMA_F64_e64:
3900 return AMDGPU::V_FMAMK_F64;
3901 default:
3902 llvm_unreachable("invalid instruction");
3903 }
3904}
3905
3907 Register Reg, MachineRegisterInfo *MRI) const {
3908 int64_t Imm;
3909 if (!getConstValDefinedInReg(DefMI, Reg, Imm))
3910 return false;
3911
3912 const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);
3913
3914 assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");
3915
3916 unsigned Opc = UseMI.getOpcode();
3917 if (Opc == AMDGPU::COPY) {
3918 assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");
3919
3920 Register DstReg = UseMI.getOperand(0).getReg();
3921 Register UseSubReg = UseMI.getOperand(1).getSubReg();
3922
3923 const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);
3924
3925 if (HasMultipleUses) {
3926 // TODO: This should fold in more cases with multiple use, but we need to
3927 // more carefully consider what those uses are.
3928 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));
3929
3930 // Avoid breaking up a 64-bit inline immediate into a subregister extract.
3931 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3932 return false;
3933
3934 // Most of the time folding a 32-bit inline constant is free (though this
3935 // might not be true if we can't later fold it into a real user).
3936 //
3937 // FIXME: This isInlineConstant check is imprecise if
3938 // getConstValDefinedInReg handled the tricky non-mov cases.
3939 if (ImmDefSize == 32 &&
3941 return false;
3942 }
3943
3944 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3945 RI.getSubRegIdxSize(UseSubReg) == 16;
3946
3947 if (Is16Bit) {
3948 if (RI.hasVGPRs(DstRC))
3949 return false; // Do not clobber vgpr_hi16
3950
3951 if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
3952 return false;
3953 }
3954
3955 MachineFunction *MF = UseMI.getMF();
3956
3957 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3958 MCRegister MovDstPhysReg =
3959 DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();
3960
3961 std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);
3962
3963 // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
3964 for (unsigned MovOp :
3965 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3966 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3967 const MCInstrDesc &MovDesc = get(MovOp);
3968
3969 const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
3970 if (Is16Bit) {
3971 // We just need to find a correctly sized register class, so the
3972 // subregister index compatibility doesn't matter since we're statically
3973 // extracting the immediate value.
3974 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3975 if (!MovDstRC)
3976 continue;
3977
3978 if (MovDstPhysReg) {
3979 // FIXME: We probably should not do this. If there is a live value in
3980 // the high half of the register, it will be corrupted.
3981 MovDstPhysReg =
3982 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3983 if (!MovDstPhysReg)
3984 continue;
3985 }
3986 }
3987
3988 // Result class isn't the right size, try the next instruction.
3989 if (MovDstPhysReg) {
3990 if (!MovDstRC->contains(MovDstPhysReg))
3991 return false;
3992 } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
3993 // TODO: This will be overly conservative in the case of 16-bit virtual
3994 // SGPRs. We could hack up the virtual register uses to use a compatible
3995 // 32-bit class.
3996 continue;
3997 }
3998
3999 const MCOperandInfo &OpInfo = MovDesc.operands()[1];
4000
4001 // Ensure the interpreted immediate value is a valid operand in the new
4002 // mov.
4003 //
4004 // FIXME: isImmOperandLegal should have form that doesn't require existing
4005 // MachineInstr or MachineOperand
4006 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4007 !isInlineConstant(*SubRegImm, OpInfo.OperandType))
4008 break;
4009
4010 NewOpc = MovOp;
4011 break;
4012 }
4013
4014 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4015 return false;
4016
4017 if (Is16Bit) {
4018 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4019 if (MovDstPhysReg)
4020 UseMI.getOperand(0).setReg(MovDstPhysReg);
4021 assert(UseMI.getOperand(1).getReg().isVirtual());
4022 }
4023
4024 const MCInstrDesc &NewMCID = get(NewOpc);
4025 UseMI.setDesc(NewMCID);
4026 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4027 UseMI.addImplicitDefUseOperands(*MF);
4028 return true;
4029 }
4030
4031 if (HasMultipleUses)
4032 return false;
4033
4034 if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
4035 Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4036 Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
4037 Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
4038 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4039 Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
4040 Opc == AMDGPU::V_FMAC_F64_e64) {
4041 // Don't fold if we are using source or output modifiers. The new VOP2
4042 // instructions don't have them.
4044 return false;
4045
4046 // If this is a free constant, there's no reason to do this.
4047 // TODO: We could fold this here instead of letting SIFoldOperands do it
4048 // later.
4049 int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4050
4051 // Any src operand can be used for the legality check.
4052 if (isInlineConstant(UseMI, Src0Idx, Imm))
4053 return false;
4054
4055 MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);
4056
4057 MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
4058 MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);
4059
4060 auto CopyRegOperandToNarrowerRC =
4061 [MRI, this](MachineInstr &MI, unsigned OpNo,
4062 const TargetRegisterClass *NewRC) -> void {
4063 if (!MI.getOperand(OpNo).isReg())
4064 return;
4065 Register Reg = MI.getOperand(OpNo).getReg();
4066 const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
4067 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4068 return;
4069 Register Tmp = MRI->createVirtualRegister(NewRC);
4070 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
4071 get(AMDGPU::COPY), Tmp)
4072 .addReg(Reg);
4073 MI.getOperand(OpNo).setReg(Tmp);
4074 };
4075
4076 // Multiplied part is the constant: Use v_madmk_{f16, f32}.
4077 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4078 (Src1->isReg() && Src1->getReg() == Reg)) {
4079 MachineOperand *RegSrc =
4080 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4081 if (!RegSrc->isReg())
4082 return false;
4083 if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
4084 ST.getConstantBusLimit(Opc) < 2)
4085 return false;
4086
4087 if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
4088 return false;
4089
4090 // If src2 is also a literal constant then we have to choose which one to
4091 // fold. In general it is better to choose madak so that the other literal
4092 // can be materialized in an sgpr instead of a vgpr:
4093 // s_mov_b32 s0, literal
4094 // v_madak_f32 v0, s0, v0, literal
4095 // Instead of:
4096 // v_mov_b32 v1, literal
4097 // v_madmk_f32 v0, v0, literal, v1
4098 MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
4099 if (Def && Def->isMoveImmediate() &&
4100 !isInlineConstant(Def->getOperand(1)))
4101 return false;
4102
4103 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4104 if (pseudoToMCOpcode(NewOpc) == -1)
4105 return false;
4106
4107 const std::optional<int64_t> SubRegImm = extractSubregFromImm(
4108 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4109
4110 // FIXME: This would be a lot easier if we could return a new instruction
4111 // instead of having to modify in place.
4112
4113 Register SrcReg = RegSrc->getReg();
4114 unsigned SrcSubReg = RegSrc->getSubReg();
4115 Src0->setReg(SrcReg);
4116 Src0->setSubReg(SrcSubReg);
4117 Src0->setIsKill(RegSrc->isKill());
4118
4119 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4120 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4121 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4122 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4123 UseMI.untieRegOperand(
4124 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4125
4126 Src1->ChangeToImmediate(*SubRegImm);
4127
4129 UseMI.setDesc(get(NewOpc));
4130
4131 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4132 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4133 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4134 Register Tmp = MRI->createVirtualRegister(NewRC);
4135 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4136 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4137 UseMI.getOperand(0).getReg())
4138 .addReg(Tmp);
4139 UseMI.getOperand(0).setReg(Tmp);
4140 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4141 CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
4142 }
4143
4144 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4145 if (DeleteDef)
4146 DefMI.eraseFromParent();
4147
4148 return true;
4149 }
4150
4151 // Added part is the constant: Use v_madak_{f16, f32}.
4152 if (Src2->isReg() && Src2->getReg() == Reg) {
4153 if (ST.getConstantBusLimit(Opc) < 2) {
4154 // Not allowed to use constant bus for another operand.
4155 // We can however allow an inline immediate as src0.
4156 bool Src0Inlined = false;
4157 if (Src0->isReg()) {
4158 // Try to inline constant if possible.
4159 // If the Def moves immediate and the use is single
4160 // We are saving VGPR here.
4161 MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
4162 if (Def && Def->isMoveImmediate() &&
4163 isInlineConstant(Def->getOperand(1)) &&
4164 MRI->hasOneNonDBGUse(Src0->getReg())) {
4165 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4166 Src0Inlined = true;
4167 } else if (ST.getConstantBusLimit(Opc) <= 1 &&
4168 RI.isSGPRReg(*MRI, Src0->getReg())) {
4169 return false;
4170 }
4171 // VGPR is okay as Src0 - fallthrough
4172 }
4173
4174 if (Src1->isReg() && !Src0Inlined) {
4175 // We have one slot for inlinable constant so far - try to fill it
4176 MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
4177 if (Def && Def->isMoveImmediate() &&
4178 isInlineConstant(Def->getOperand(1)) &&
4179 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
4180 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4181 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
4182 return false;
4183 // VGPR is okay as Src1 - fallthrough
4184 }
4185 }
4186
4187 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4188 if (pseudoToMCOpcode(NewOpc) == -1)
4189 return false;
4190
4191 // FIXME: This would be a lot easier if we could return a new instruction
4192 // instead of having to modify in place.
4193
4194 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4195 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4196 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4197 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4198 UseMI.untieRegOperand(
4199 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4200
4201 const std::optional<int64_t> SubRegImm =
4202 extractSubregFromImm(Imm, Src2->getSubReg());
4203
4204 // ChangingToImmediate adds Src2 back to the instruction.
4205 Src2->ChangeToImmediate(*SubRegImm);
4206
4207 // These come before src2.
4209 UseMI.setDesc(get(NewOpc));
4210
4211 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4212 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4213 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4214 Register Tmp = MRI->createVirtualRegister(NewRC);
4215 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4216 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4217 UseMI.getOperand(0).getReg())
4218 .addReg(Tmp);
4219 UseMI.getOperand(0).setReg(Tmp);
4220 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4221 CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
4222 }
4223
4224 // It might happen that UseMI was commuted
4225 // and we now have SGPR as SRC1. If so 2 inlined
4226 // constant and SGPR are illegal.
4228
4229 int NewSrc0Idx =
4230 AMDGPU::getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4231 if (!isOperandLegal(UseMI, NewSrc0Idx))
4232 legalizeOpWithMove(UseMI, NewSrc0Idx);
4233
4234 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4235 if (DeleteDef)
4236 DefMI.eraseFromParent();
4237
4238 return true;
4239 }
4240 }
4241
4242 return false;
4243}
4244
4245static bool
4248 if (BaseOps1.size() != BaseOps2.size())
4249 return false;
4250 for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
4251 if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
4252 return false;
4253 }
4254 return true;
4255}
4256
4257static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
4258 LocationSize WidthB, int OffsetB) {
4259 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4260 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4261 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4262 return LowWidth.hasValue() &&
4263 LowOffset + (int)LowWidth.getValue() <= HighOffset;
4264}
4265
4266bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
4267 const MachineInstr &MIb) const {
4268 SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
4269 int64_t Offset0, Offset1;
4270 LocationSize Dummy0 = LocationSize::precise(0);
4271 LocationSize Dummy1 = LocationSize::precise(0);
4272 bool Offset0IsScalable, Offset1IsScalable;
4273 if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
4274 Dummy0) ||
4275 !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
4276 Dummy1))
4277 return false;
4278
4279 if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
4280 return false;
4281
4282 if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
4283 // FIXME: Handle ds_read2 / ds_write2.
4284 return false;
4285 }
4286 LocationSize Width0 = MIa.memoperands().front()->getSize();
4287 LocationSize Width1 = MIb.memoperands().front()->getSize();
4288 return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
4289}
4290
4292 const MachineInstr &MIb) const {
4293 assert(MIa.mayLoadOrStore() &&
4294 "MIa must load from or modify a memory location");
4295 assert(MIb.mayLoadOrStore() &&
4296 "MIb must load from or modify a memory location");
4297
4299 return false;
4300
4301 // XXX - Can we relax this between address spaces?
4302 if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
4303 return false;
4304
4305 if (isLDSDMA(MIa) || isLDSDMA(MIb))
4306 return false;
4307
4308 if (MIa.isBundle() || MIb.isBundle())
4309 return false;
4310
4311 // TODO: Should we check the address space from the MachineMemOperand? That
4312 // would allow us to distinguish objects we know don't alias based on the
4313 // underlying address space, even if it was lowered to a different one,
4314 // e.g. private accesses lowered to use MUBUF instructions on a scratch
4315 // buffer.
4316 if (isDS(MIa)) {
4317 if (isDS(MIb))
4318 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4319
4320 return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
4321 }
4322
4323 if (isMUBUF(MIa) || isMTBUF(MIa)) {
4324 if (isMUBUF(MIb) || isMTBUF(MIb))
4325 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4326
4327 if (isFLAT(MIb))
4328 return isFLATScratch(MIb);
4329
4330 return !isSMRD(MIb);
4331 }
4332
4333 if (isSMRD(MIa)) {
4334 if (isSMRD(MIb))
4335 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4336
4337 if (isFLAT(MIb))
4338 return isFLATScratch(MIb);
4339
4340 return !isMUBUF(MIb) && !isMTBUF(MIb);
4341 }
4342
4343 if (isFLAT(MIa)) {
4344 if (isFLAT(MIb)) {
4345 if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
4346 (isFLATGlobal(MIa) && isFLATScratch(MIb)))
4347 return true;
4348
4349 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4350 }
4351
4352 return false;
4353 }
4354
4355 return false;
4356}
4357
4358static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
4359 switch (Opc) {
4360 case AMDGPU::V_MAC_F16_e32:
4361 case AMDGPU::V_MAC_F16_e64:
4362 return AMDGPU::V_MAD_F16_e64;
4363 case AMDGPU::V_MAC_F32_e32:
4364 case AMDGPU::V_MAC_F32_e64:
4365 return AMDGPU::V_MAD_F32_e64;
4366 case AMDGPU::V_MAC_LEGACY_F32_e32:
4367 case AMDGPU::V_MAC_LEGACY_F32_e64:
4368 return AMDGPU::V_MAD_LEGACY_F32_e64;
4369 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4370 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4371 return AMDGPU::V_FMA_LEGACY_F32_e64;
4372 case AMDGPU::V_FMAC_F16_e32:
4373 case AMDGPU::V_FMAC_F16_e64:
4374 case AMDGPU::V_FMAC_F16_t16_e64:
4375 case AMDGPU::V_FMAC_F16_fake16_e64:
4376 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4377 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4378 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4379 : AMDGPU::V_FMA_F16_gfx9_e64;
4380 case AMDGPU::V_FMAC_F32_e32:
4381 case AMDGPU::V_FMAC_F32_e64:
4382 return AMDGPU::V_FMA_F32_e64;
4383 case AMDGPU::V_FMAC_F64_e32:
4384 case AMDGPU::V_FMAC_F64_e64:
4385 return AMDGPU::V_FMA_F64_e64;
4386 default:
4387 llvm_unreachable("invalid instruction");
4388 }
4389}
4390
4391/// Helper struct for the implementation of 3-address conversion to communicate
4392/// updates made to instruction operands.
4394 /// Other instruction whose def is no longer used by the converted
4395 /// instruction.
4397};
4398
4400 LiveIntervals *LIS) const {
4401 MachineBasicBlock &MBB = *MI.getParent();
4402 MachineInstr *CandidateMI = &MI;
4403
4404 if (MI.isBundle()) {
4405 // This is a temporary placeholder for bundle handling that enables us to
4406 // exercise the relevant code paths in the two-address instruction pass.
4407 if (MI.getBundleSize() != 1)
4408 return nullptr;
4409 CandidateMI = MI.getNextNode();
4410 }
4411
4413 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4414 if (!NewMI)
4415 return nullptr;
4416
4417 if (MI.isBundle()) {
4418 CandidateMI->eraseFromBundle();
4419
4420 for (MachineOperand &MO : MI.all_defs()) {
4421 if (MO.isTied())
4422 MI.untieRegOperand(MO.getOperandNo());
4423 }
4424 } else {
4425 if (LIS) {
4426 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
4427 // SlotIndex of defs needs to be updated when converting to early-clobber
4428 MachineOperand &Def = NewMI->getOperand(0);
4429 if (Def.isEarlyClobber() && Def.isReg() &&
4430 LIS->hasInterval(Def.getReg())) {
4431 SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
4432 SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
4433 auto &LI = LIS->getInterval(Def.getReg());
4434 auto UpdateDefIndex = [&](LiveRange &LR) {
4435 auto *S = LR.find(OldIndex);
4436 if (S != LR.end() && S->start == OldIndex) {
4437 assert(S->valno && S->valno->def == OldIndex);
4438 S->start = NewIndex;
4439 S->valno->def = NewIndex;
4440 }
4441 };
4442 UpdateDefIndex(LI);
4443 for (auto &SR : LI.subranges())
4444 UpdateDefIndex(SR);
4445 }
4446 }
4447 }
4448
4449 if (U.RemoveMIUse) {
4450 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4451 // The only user is the instruction which will be killed.
4452 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4453
4454 if (MRI.hasOneNonDBGUse(DefReg)) {
4455 // We cannot just remove the DefMI here, calling pass will crash.
4456 U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
4457 U.RemoveMIUse->getOperand(0).setIsDead(true);
4458 for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
4459 U.RemoveMIUse->removeOperand(I);
4460 }
4461
4462 if (MI.isBundle()) {
4463 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4464 if (!VRI.Reads && !VRI.Writes) {
4465 for (MachineOperand &MO : MI.all_uses()) {
4466 if (MO.isReg() && MO.getReg() == DefReg) {
4467 assert(MO.getSubReg() == 0 &&
4468 "tied sub-registers in bundles currently not supported");
4469 MI.removeOperand(MO.getOperandNo());
4470 break;
4471 }
4472 }
4473
4474 if (LIS)
4475 LIS->shrinkToUses(&LIS->getInterval(DefReg));
4476 }
4477 } else if (LIS) {
4478 LiveInterval &DefLI = LIS->getInterval(DefReg);
4479
4480 // We cannot delete the original instruction here, so hack out the use
4481 // in the original instruction with a dummy register so we can use
4482 // shrinkToUses to deal with any multi-use edge cases. Other targets do
4483 // not have the complexity of deleting a use to consider here.
4484 Register DummyReg = MRI.cloneVirtualRegister(DefReg);
4485 for (MachineOperand &MIOp : MI.uses()) {
4486 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4487 MIOp.setIsUndef(true);
4488 MIOp.setReg(DummyReg);
4489 }
4490 }
4491
4492 if (MI.isBundle()) {
4493 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4494 if (!VRI.Reads && !VRI.Writes) {
4495 for (MachineOperand &MIOp : MI.uses()) {
4496 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4497 MIOp.setIsUndef(true);
4498 MIOp.setReg(DummyReg);
4499 }
4500 }
4501 }
4502
4503 MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
4504 false, /*isUndef=*/true));
4505 }
4506
4507 LIS->shrinkToUses(&DefLI);
4508 }
4509 }
4510
4511 return MI.isBundle() ? &MI : NewMI;
4512}
4513
4515SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
4516 ThreeAddressUpdates &U) const {
4517 MachineBasicBlock &MBB = *MI.getParent();
4518 unsigned Opc = MI.getOpcode();
4519
4520 // Handle MFMA.
4521 int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
4522 if (NewMFMAOpc != -1) {
4524 BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
4525 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4526 MIB.add(MI.getOperand(I));
4527 return MIB;
4528 }
4529
4530 if (SIInstrInfo::isWMMA(MI)) {
4531 unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
4532 MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4533 .setMIFlags(MI.getFlags());
4534 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4535 MIB->addOperand(MI.getOperand(I));
4536 return MIB;
4537 }
4538
4539 assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4540 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4541 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4542 "present pre-RA");
4543
4544 // Handle MAC/FMAC.
4545 bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
4546 bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4547 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4548 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4549 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4550 bool Src0Literal = false;
4551
4552 switch (Opc) {
4553 default:
4554 return nullptr;
4555 case AMDGPU::V_MAC_F16_e64:
4556 case AMDGPU::V_FMAC_F16_e64:
4557 case AMDGPU::V_FMAC_F16_t16_e64:
4558 case AMDGPU::V_FMAC_F16_fake16_e64:
4559 case AMDGPU::V_MAC_F32_e64:
4560 case AMDGPU::V_MAC_LEGACY_F32_e64:
4561 case AMDGPU::V_FMAC_F32_e64:
4562 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4563 case AMDGPU::V_FMAC_F64_e64:
4564 break;
4565 case AMDGPU::V_MAC_F16_e32:
4566 case AMDGPU::V_FMAC_F16_e32:
4567 case AMDGPU::V_MAC_F32_e32:
4568 case AMDGPU::V_MAC_LEGACY_F32_e32:
4569 case AMDGPU::V_FMAC_F32_e32:
4570 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4571 case AMDGPU::V_FMAC_F64_e32: {
4572 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
4573 AMDGPU::OpName::src0);
4574 const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
4575 if (!Src0->isReg() && !Src0->isImm())
4576 return nullptr;
4577
4578 if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
4579 Src0Literal = true;
4580
4581 break;
4582 }
4583 }
4584
4585 MachineInstrBuilder MIB;
4586 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
4587 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
4588 const MachineOperand *Src0Mods =
4589 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
4590 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4591 const MachineOperand *Src1Mods =
4592 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
4593 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4594 const MachineOperand *Src2Mods =
4595 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
4596 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
4597 const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
4598 const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);
4599
4600 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4601 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4602 // If we have an SGPR input, we will violate the constant bus restriction.
4603 (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
4604 !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
4605 MachineInstr *DefMI = nullptr;
4606 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4607 std::optional<int64_t> ImmOpt;
4608 int64_t Imm;
4609
4610 if (!Src0Literal &&
4611 (ImmOpt = getImmOrMaterializedImm(MRI, *Src2, &DefMI))) {
4612 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4613 if (pseudoToMCOpcode(NewOpc) != -1) {
4614 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4615 .add(*Dst)
4616 .add(*Src0)
4617 .add(*Src1)
4618 .addImm(*ImmOpt)
4619 .setMIFlags(MI.getFlags());
4620 U.RemoveMIUse = DefMI;
4621 return MIB;
4622 }
4623 }
4624 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4625 if (!Src0Literal &&
4626 (ImmOpt = getImmOrMaterializedImm(MRI, *Src1, &DefMI))) {
4627 if (pseudoToMCOpcode(NewOpc) != -1) {
4628 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4629 .add(*Dst)
4630 .add(*Src0)
4631 .addImm(*ImmOpt)
4632 .add(*Src2)
4633 .setMIFlags(MI.getFlags());
4634 U.RemoveMIUse = DefMI;
4635 return MIB;
4636 }
4637 }
4638 if ((ImmOpt = getImmOrMaterializedImm(MRI, *Src0, &DefMI))) {
4639 Imm = *ImmOpt;
4640 if (pseudoToMCOpcode(NewOpc) != -1 &&
4642 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4643 Src1)) {
4644 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4645 .add(*Dst)
4646 .add(*Src1)
4647 .addImm(Imm)
4648 .add(*Src2)
4649 .setMIFlags(MI.getFlags());
4650 U.RemoveMIUse = DefMI;
4651 return MIB;
4652 }
4653 }
4654 }
4655
4656 // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
4657 // if VOP3 does not allow a literal operand.
4658 if (Src0Literal && !ST.hasVOP3Literal())
4659 return nullptr;
4660
4661 unsigned NewOpc = getNewFMAInst(ST, Opc);
4662
4663 if (pseudoToMCOpcode(NewOpc) == -1)
4664 return nullptr;
4665
4666 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4667 .add(*Dst)
4668 .addImm(Src0Mods ? Src0Mods->getImm() : 0)
4669 .add(*Src0)
4670 .addImm(Src1Mods ? Src1Mods->getImm() : 0)
4671 .add(*Src1)
4672 .addImm(Src2Mods ? Src2Mods->getImm() : 0)
4673 .add(*Src2)
4674 .addImm(Clamp ? Clamp->getImm() : 0)
4675 .addImm(Omod ? Omod->getImm() : 0)
4676 .setMIFlags(MI.getFlags());
4677 if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
4678 MIB.addImm(OpSel ? OpSel->getImm() : 0);
4679 return MIB;
4680}
4681
4682// It's not generally safe to move VALU instructions across these since it will
4683// start using the register as a base index rather than directly.
4684// XXX - Why isn't hasSideEffects sufficient for these?
4686 switch (MI.getOpcode()) {
4687 case AMDGPU::S_SET_GPR_IDX_ON:
4688 case AMDGPU::S_SET_GPR_IDX_MODE:
4689 case AMDGPU::S_SET_GPR_IDX_OFF:
4690 return true;
4691 default:
4692 return false;
4693 }
4694}
4695
4697 const MachineBasicBlock *MBB,
4698 const MachineFunction &MF) const {
4699 // Skipping the check for SP writes in the base implementation. The reason it
4700 // was added was apparently due to compile time concerns.
4701 //
4702 // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
4703 // but is probably avoidable.
4704
4705 // Copied from base implementation.
4706 // Terminators and labels can't be scheduled around.
4707 if (MI.isTerminator() || MI.isPosition())
4708 return true;
4709
4710 // INLINEASM_BR can jump to another block
4711 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4712 return true;
4713
4714 if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
4715 return true;
4716
4717 // Target-independent instructions do not have an implicit-use of EXEC, even
4718 // when they operate on VGPRs. Treating EXEC modifications as scheduling
4719 // boundaries prevents incorrect movements of such instructions.
4720 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4721 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4722 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4723 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4724 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4726}
4727
4729 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4730 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4731 Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
4732}
4733
4735 // Instructions that access scratch use FLAT encoding or BUF encodings.
4736 if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
4737 return false;
4738
4739 // SCRATCH instructions always access scratch.
4740 if (isFLATScratch(MI))
4741 return true;
4742
4743 // If FLAT_SCRATCH registers are not initialized, we can never access scratch
4744 // via the aperture.
4745 if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
4746 return false;
4747
4748 // If there are no memory operands then conservatively assume the flat
4749 // operation may access scratch.
4750 if (MI.memoperands_empty())
4751 return true;
4752
4753 // See if any memory operand specifies an address space that involves scratch.
4754 return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
4755 unsigned AS = Memop->getAddrSpace();
4756 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4757 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4758 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4759 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4760 }
4761 return AS == AMDGPUAS::PRIVATE_ADDRESS;
4762 });
4763}
4764
4766 assert(isFLAT(MI));
4767
4768 // All flat instructions use the VMEM counter except prefetch.
4769 if (!usesVM_CNT(MI))
4770 return false;
4771
4772 // If there are no memory operands then conservatively assume the flat
4773 // operation may access VMEM.
4774 if (MI.memoperands_empty())
4775 return true;
4776
4777 // See if any memory operand specifies an address space that involves VMEM.
4778 // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
4779 // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
4780 // (GDS) address space is not supported by flat operations. Therefore, simply
4781 // return true unless only the LDS address space is found.
4782 for (const MachineMemOperand *Memop : MI.memoperands()) {
4783 unsigned AS = Memop->getAddrSpace();
4785 if (AS != AMDGPUAS::LOCAL_ADDRESS)
4786 return true;
4787 }
4788
4789 return false;
4790}
4791
4793 bool TgSplit) const {
4794 assert(isFLAT(MI));
4795
4796 // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
4797 if (!usesLGKM_CNT(MI))
4798 return false;
4799
4800 // If in tgsplit mode then there can be no use of LDS.
4801 if (TgSplit)
4802 return false;
4803
4804 // If there are no memory operands then conservatively assume the flat
4805 // operation may access LDS.
4806 if (MI.memoperands_empty())
4807 return true;
4808
4809 // See if any memory operand specifies an address space that involves LDS.
4810 for (const MachineMemOperand *Memop : MI.memoperands()) {
4811 unsigned AS = Memop->getAddrSpace();
4813 return true;
4814 }
4815
4816 return false;
4817}
4818
4820 // Skip the full operand and register alias search modifiesRegister
4821 // does. There's only a handful of instructions that touch this, it's only an
4822 // implicit def, and doesn't alias any other registers.
4823 return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
4824}
4825
4827 unsigned Opcode = MI.getOpcode();
4828
4829 if (MI.mayStore() && isSMRD(MI))
4830 return true; // scalar store or atomic
4831
4832 // This will terminate the function when other lanes may need to continue.
4833 if (MI.isReturn())
4834 return true;
4835
4836 // These instructions cause shader I/O that may cause hardware lockups
4837 // when executed with an empty EXEC mask.
4838 //
4839 // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
4840 // EXEC = 0, but checking for that case here seems not worth it
4841 // given the typical code patterns.
4842 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4843 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4844 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4845 Opcode == AMDGPU::S_SETHALT)
4846 return true;
4847
4848 if (MI.isCall() || MI.isInlineAsm())
4849 return true; // conservative assumption
4850
4851 // V_PERM_PK16 must issue with EXEC != 0 so its follower (or an inserted
4852 // V_NOP) actually runs on the VALU pipe. Returning true here keeps the
4853 // s_cbranch_execz that skips this region when EXEC is empty.
4854 if (ST.hasVPermPk16Hazard() && isVPermPk16(Opcode))
4855 return true;
4856
4857 // Assume that barrier interactions are only intended with active lanes.
4858 if (isBarrier(Opcode))
4859 return true;
4860
4861 // A mode change is a scalar operation that influences vector instructions.
4863 return true;
4864
4865 // These are like SALU instructions in terms of effects, so it's questionable
4866 // whether we should return true for those.
4867 //
4868 // However, executing them with EXEC = 0 causes them to operate on undefined
4869 // data, which we avoid by returning true here.
4870 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4871 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4872 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4873 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4874 return true;
4875
4876 return false;
4877}
4878
4880 const MachineInstr &MI) const {
4881 if (MI.isMetaInstruction())
4882 return false;
4883
4884 // This won't read exec if this is an SGPR->SGPR copy.
4885 if (MI.isCopyLike()) {
4886 if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
4887 return true;
4888
4889 // Make sure this isn't copying exec as a normal operand
4890 return MI.readsRegister(AMDGPU::EXEC, &RI);
4891 }
4892
4893 // Make a conservative assumption about the callee.
4894 if (MI.isCall())
4895 return true;
4896
4897 // Be conservative with any unhandled generic opcodes.
4898 if (!isTargetSpecificOpcode(MI.getOpcode()))
4899 return true;
4900
4901 return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
4902}
4903
4905 switch (Imm.getBitWidth()) {
4906 case 1: // This likely will be a condition code mask.
4907 return true;
4908
4909 case 32:
4910 return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
4911 ST.hasInv2PiInlineImm());
4912 case 64:
4913 return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
4914 ST.hasInv2PiInlineImm());
4915 case 16:
4916 return ST.has16BitInsts() &&
4917 AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
4918 ST.hasInv2PiInlineImm());
4919 default:
4920 llvm_unreachable("invalid bitwidth");
4921 }
4922}
4923
4925 APInt IntImm = Imm.bitcastToAPInt();
4926 int64_t IntImmVal = IntImm.getSExtValue();
4927 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4928 switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
4929 default:
4930 llvm_unreachable("invalid fltSemantics");
4933 return isInlineConstant(IntImm);
4935 return ST.has16BitInsts() &&
4936 AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
4938 return ST.has16BitInsts() &&
4939 AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
4940 }
4941}
4942
4943bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
4944 // MachineOperand provides no way to tell the true operand size, since it only
4945 // records a 64-bit value. We need to know the size to determine if a 32-bit
4946 // floating point immediate bit pattern is legal for an integer immediate. It
4947 // would be for any 32-bit integer operand, but would not be for a 64-bit one.
4948 switch (OperandType) {
4958 int32_t Trunc = static_cast<int32_t>(Imm);
4959 return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
4960 }
4968 return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
4971 // We would expect inline immediates to not be concerned with an integer/fp
4972 // distinction. However, in the case of 16-bit integer operations, the
4973 // "floating point" values appear to not work. It seems read the low 16-bits
4974 // of 32-bit immediates, which happens to always work for the integer
4975 // values.
4976 //
4977 // See llvm bugzilla 46302.
4978 //
4979 // TODO: Theoretically we could use op-sel to use the high bits of the
4980 // 32-bit FP values.
4989 return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
4994 return false;
4997 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
4998 // A few special case instructions have 16-bit operands on subtargets
4999 // where 16-bit instructions are not legal.
5000 // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
5001 // constants in these cases
5002 int16_t Trunc = static_cast<int16_t>(Imm);
5003 return ST.has16BitInsts() &&
5004 AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
5005 }
5006
5007 return false;
5008 }
5011 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
5012 int16_t Trunc = static_cast<int16_t>(Imm);
5013 return ST.has16BitInsts() &&
5014 AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
5015 }
5016 return false;
5017 }
5022 return false;
5024 return isLegalAV64PseudoImm(Imm);
5027 // Always embedded in the instruction for free.
5028 return true;
5038 // Just ignore anything else.
5039 return false;
5040 default:
5041 llvm_unreachable("invalid operand type");
5042 }
5043}
5044
5045static bool compareMachineOp(const MachineOperand &Op0,
5046 const MachineOperand &Op1) {
5047 if (Op0.getType() != Op1.getType())
5048 return false;
5049
5050 switch (Op0.getType()) {
5052 return Op0.getReg() == Op1.getReg();
5054 return Op0.getImm() == Op1.getImm();
5055 default:
5056 llvm_unreachable("Didn't expect to be comparing these operand types");
5057 }
5058}
5059
5061 const MCOperandInfo &OpInfo) const {
5062 if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
5063 return true;
5064
5065 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5066 return false;
5067
5068 if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
5069 return true;
5070
5071 return ST.hasVOP3Literal();
5072}
5073
5074bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5075 int64_t ImmVal) const {
5076 const unsigned Opc = InstDesc.getOpcode();
5077 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
5078 if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
5079 OpNo == static_cast<unsigned>(Src1Idx))
5080 return false;
5081
5082 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5083 if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
5084 if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5085 OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
5086 AMDGPU::OpName::src2))
5087 return false;
5088
5089 if (ST.hasBF16InlineConstFromUpperFP32() && isVOP1(Opc)) {
5090 if ((OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_BF16 ||
5091 OpInfo.OperandType == AMDGPU::OPERAND_REG_INLINE_C_BF16) &&
5092 isInlineConstant(ImmVal, OpInfo.OperandType))
5093 return false;
5094 }
5095
5096 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5097 }
5098
5099 return isLiteralOperandLegal(InstDesc, OpInfo);
5100}
5101
5102bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5103 const MachineOperand &MO) const {
5104 if (MO.isImm())
5105 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
5106
5107 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
5108 "unexpected imm-like operand kind");
5109 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5110 return isLiteralOperandLegal(InstDesc, OpInfo);
5111}
5112
5114 // 2 32-bit inline constants packed into one.
5115 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
5116 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
5117}
5118
5119bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
5120 // GFX90A does not have V_MUL_LEGACY_F32_e32.
5121 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5122 return false;
5123
5124 int Op32 = AMDGPU::getVOPe32(Opcode);
5125 if (Op32 == -1)
5126 return false;
5127
5128 return pseudoToMCOpcode(Op32) != -1;
5129}
5130
5131/// Return true if \p MI is a VALU comparison, i.e. an instruction that writes
5132/// a lane mask with one bit per lane, and zeroes the bits of lanes that were
5133/// inactive when it executed.
5134///
5135/// TODO: Also handle the sdst result of V_ADD_CO_U32 and V_SUB_CO_U32 and
5136/// V_DIV_SCALE_F32.
5137static bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI) {
5138 if (TII.isVOPC(MI))
5139 return true;
5140 int Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5141 return Op32 != -1 && TII.isVOPC(Op32);
5142}
5143
5145 const MachineRegisterInfo &MRI,
5146 unsigned Depth) const {
5147 assert(MRI.isSSA() && "isMaskedByExec requires SSA form");
5149 const MachineBasicBlock *MBB = Use.getParent();
5150
5151 // EXEC itself is trivially masked by EXEC.
5152 if (Reg == LMC.ExecReg)
5153 return true;
5154
5155 // Maximum depth of the def-use walk.
5156 constexpr unsigned MaxDepth = 6;
5157 if (Depth >= MaxDepth || !Reg.isVirtual())
5158 return false;
5159
5160 // Only look at definitions that can execute under the same EXEC mask as the
5161 // use.
5162 const MachineInstr *Def = MRI.getVRegDef(Reg);
5163 if (!Def || Def->getParent() != MBB)
5164 return false;
5165
5166 if (isVCmp(*this, *Def))
5167 return true;
5168
5169 // Recurse into an operand, which must be a whole register to say anything
5170 // about the whole lane mask.
5171 auto Recurse = [&](unsigned OpIdx) {
5172 const MachineOperand &MO = Def->getOperand(OpIdx);
5173 return MO.isReg() && !MO.getSubReg() &&
5174 isMaskedByExec(MO.getReg(), Use, MRI, Depth + 1);
5175 };
5176
5177 unsigned Opc = Def->getOpcode();
5178 if (Opc == AMDGPU::COPY && Recurse(1))
5179 return true;
5180 if (Opc == LMC.AndOpc && (Recurse(1) || Recurse(2)))
5181 return true;
5182 if (Opc == LMC.AndN2Opc && Recurse(1))
5183 return true;
5184 if ((Opc == LMC.OrOpc || Opc == LMC.XorOpc) && Recurse(1) && Recurse(2))
5185 return true;
5186 // TODO: Sometimes we encounter "reg = S_CSELECT -1, 0". If Reg has no other
5187 // uses this could be optimized to "reg = S_CSELECT $exec, 0".
5188
5189 return false;
5190}
5191
5192bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
5193 // The src0_modifier operand is present on all instructions
5194 // that have modifiers.
5195
5196 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
5197}
5198
5200 AMDGPU::OpName OpName) const {
5201 const MachineOperand *Mods = getNamedOperand(MI, OpName);
5202 return Mods && Mods->getImm();
5203}
5204
5206 return any_of(ModifierOpNames,
5207 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
5208}
5209
5211 const MachineRegisterInfo &MRI) const {
5212 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5213 // Can't shrink instruction with three operands.
5214 if (Src2) {
5215 switch (MI.getOpcode()) {
5216 default: return false;
5217
5218 case AMDGPU::V_ADDC_U32_e64:
5219 case AMDGPU::V_SUBB_U32_e64:
5220 case AMDGPU::V_SUBBREV_U32_e64: {
5221 const MachineOperand *Src1
5222 = getNamedOperand(MI, AMDGPU::OpName::src1);
5223 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
5224 return false;
5225 // Additional verification is needed for sdst/src2.
5226 return true;
5227 }
5228 case AMDGPU::V_MAC_F16_e64:
5229 case AMDGPU::V_MAC_F32_e64:
5230 case AMDGPU::V_MAC_LEGACY_F32_e64:
5231 case AMDGPU::V_FMAC_F16_e64:
5232 case AMDGPU::V_FMAC_F16_t16_e64:
5233 case AMDGPU::V_FMAC_F16_fake16_e64:
5234 case AMDGPU::V_FMAC_F32_e64:
5235 case AMDGPU::V_FMAC_F64_e64:
5236 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5237 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
5238 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
5239 return false;
5240 break;
5241
5242 case AMDGPU::V_CNDMASK_B32_e64:
5243 break;
5244 }
5245 }
5246
5247 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
5248 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5249 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
5250 return false;
5251
5252 // Make sure src0 isn't using any modifiers.
5253 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
5254 return false;
5255
5256 // Can it be shrunk to a valid 32 bit opcode?
5257 if (!hasVALU32BitEncoding(MI.getOpcode()))
5258 return false;
5259
5260 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
5261 if (Src0 && Src0->isImm()) {
5262 unsigned Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5263 if (!isImmOperandLegal(
5264 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5265 *Src0))
5266 return false;
5267 }
5268
5269 // Check output modifiers
5270 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
5271 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
5272 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
5273 // TODO: Can we avoid checking bound_ctrl/fi here?
5274 // They are only used by permlane*_swap special case.
5275 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
5276 !hasModifiersSet(MI, AMDGPU::OpName::fi);
5277}
5278
5279// Set VCC operand with all flags from \p Orig, except for setting it as
5280// implicit.
5282 const MachineOperand &Orig) {
5283
5284 for (MachineOperand &Use : MI.implicit_operands()) {
5285 if (Use.isUse() &&
5286 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
5287 Use.setIsUndef(Orig.isUndef());
5288 Use.setIsKill(Orig.isKill());
5289 return;
5290 }
5291 }
5292}
5293
5295 unsigned Op32) const {
5296 MachineBasicBlock *MBB = MI.getParent();
5297
5298 const MCInstrDesc &Op32Desc = get(Op32);
5299 MachineInstrBuilder Inst32 =
5300 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
5301 .setMIFlags(MI.getFlags());
5302
5303 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
5304 // For VOPC instructions, this is replaced by an implicit def of vcc.
5305
5306 // We assume the defs of the shrunk opcode are in the same order, and the
5307 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
5308 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
5309 Inst32.add(MI.getOperand(I));
5310
5311 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5312
5313 int Idx = MI.getNumExplicitDefs();
5314 for (const MachineOperand &Use : MI.explicit_uses()) {
5315 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
5317 continue;
5318
5319 if (&Use == Src2) {
5320 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5321 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
5322 // replaced with an implicit read of vcc or vcc_lo. The implicit read
5323 // of vcc was already added during the initial BuildMI, but we
5324 // 1) may need to change vcc to vcc_lo to preserve the original register
5325 // 2) have to preserve the original flags.
5326 copyFlagsToImplicitVCC(*Inst32, *Src2);
5327 continue;
5328 }
5329 }
5330
5331 Inst32.add(Use);
5332 }
5333
5334 // FIXME: Losing implicit operands
5335 fixImplicitOperands(*Inst32);
5336
5337 // The explicit carry/result def is dropped in favor of an implicit VCC def;
5338 // preserve the dead flag.
5339 const MachineOperand *OldSDst = getNamedOperand(MI, AMDGPU::OpName::sdst);
5340 if (OldSDst && OldSDst->isDead()) {
5341 if (MachineOperand *NewVCC =
5342 Inst32->findRegisterDefOperand(RI.getVCC(), &RI))
5343 NewVCC->setIsDead();
5344 }
5345
5346 return Inst32;
5347}
5348
5350 // Null is free
5351 Register Reg = RegOp.getReg();
5352 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5353 return false;
5354
5355 // SGPRs use the constant bus
5356
5357 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
5358 // physical register operands should also count, except for exec.
5359 if (RegOp.isImplicit())
5360 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5361
5362 // SGPRs use the constant bus
5363 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5364 AMDGPU::SReg_64RegClass.contains(Reg);
5365}
5366
5368 const MachineRegisterInfo &MRI) const {
5369 Register Reg = RegOp.getReg();
5370 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5371 : physRegUsesConstantBus(RegOp);
5372}
5373
5375 const MachineOperand &MO,
5376 const MCOperandInfo &OpInfo) const {
5377 // Literal constants use the constant bus.
5378 if (!MO.isReg())
5379 return !isInlineConstant(MO, OpInfo);
5380
5381 Register Reg = MO.getReg();
5382 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5384}
5385
5387 for (const MachineOperand &MO : MI.implicit_operands()) {
5388 // We only care about reads.
5389 if (MO.isDef())
5390 continue;
5391
5392 switch (MO.getReg()) {
5393 case AMDGPU::VCC:
5394 case AMDGPU::VCC_LO:
5395 case AMDGPU::VCC_HI:
5396 case AMDGPU::M0:
5397 case AMDGPU::FLAT_SCR:
5398 return MO.getReg();
5399
5400 default:
5401 break;
5402 }
5403 }
5404
5405 return Register();
5406}
5407
5408static bool shouldReadExec(const MachineInstr &MI) {
5409 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5410 switch (MI.getOpcode()) {
5411 case AMDGPU::V_READLANE_B32:
5412 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5413 case AMDGPU::V_WRITELANE_B32:
5414 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5415 return false;
5416 }
5417
5418 return true;
5419 }
5420
5421 if (MI.isPreISelOpcode() ||
5422 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5425 return false;
5426
5427 return true;
5428}
5429
5430static bool isRegOrFI(const MachineOperand &MO) {
5431 return MO.isReg() || MO.isFI();
5432}
5433
5434static bool isSubRegOf(const SIRegisterInfo &TRI,
5435 const MachineOperand &SuperVec,
5436 const MachineOperand &SubReg) {
5437 if (SubReg.getReg().isPhysical())
5438 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5439
5440 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5441 SubReg.getReg() == SuperVec.getReg();
5442}
5443
5444// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5445bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5446 const MachineRegisterInfo &MRI,
5447 StringRef &ErrInfo) const {
5448 Register DstReg = MI.getOperand(0).getReg();
5449 Register SrcReg = MI.getOperand(1).getReg();
5450 // This is a check for copy from vector register to SGPR
5451 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5452 ErrInfo = "illegal copy from vector register to SGPR";
5453 return false;
5454 }
5455 return true;
5456}
5457
5459 StringRef &ErrInfo) const {
5460 uint32_t Opcode = MI.getOpcode();
5461 const MachineFunction *MF = MI.getMF();
5462 const MachineRegisterInfo &MRI = MF->getRegInfo();
5463
5464 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5465 // Find a better property to recognize the point where instruction selection
5466 // is just done.
5467 // We can only enforce this check after SIFixSGPRCopies pass so that the
5468 // illegal copies are legalized and thereafter we don't expect a pass
5469 // inserting similar copies.
5470 if (!MRI.isSSA() && MI.isCopy())
5471 return verifyCopy(MI, MRI, ErrInfo);
5472
5473 if (SIInstrInfo::isGenericOpcode(Opcode))
5474 return true;
5475
5476 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5477 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5478 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5479 int Src3Idx = -1;
5480 if (Src0Idx == -1) {
5481 // VOPD V_DUAL_* instructions use different operand names.
5482 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5483 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5484 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5485 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5486 }
5487
5488 // Make sure the number of operands is correct.
5489 const MCInstrDesc &Desc = get(Opcode);
5490 if (!Desc.isVariadic() &&
5491 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5492 ErrInfo = "Instruction has wrong number of operands.";
5493 return false;
5494 }
5495
5496 if (MI.isInlineAsm()) {
5497 // Verify register classes for inlineasm constraints.
5498 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5499 I != E; ++I) {
5500 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5501 if (!RC)
5502 continue;
5503
5504 const MachineOperand &Op = MI.getOperand(I);
5505 if (!Op.isReg())
5506 continue;
5507
5508 Register Reg = Op.getReg();
5509 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5510 ErrInfo = "inlineasm operand has incorrect register class.";
5511 return false;
5512 }
5513 }
5514
5515 return true;
5516 }
5517
5518 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5519 ErrInfo = "missing memory operand from image instruction.";
5520 return false;
5521 }
5522
5523 // Make sure the register classes are correct.
5524 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5525 const MachineOperand &MO = MI.getOperand(i);
5526 if (MO.isFPImm()) {
5527 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5528 "all fp values to integers.";
5529 return false;
5530 }
5531
5532 const MCOperandInfo &OpInfo = Desc.operands()[i];
5533
5534 switch (OpInfo.OperandType) {
5536 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5537 ErrInfo = "Illegal immediate value for operand.";
5538 return false;
5539 }
5540 break;
5554 break;
5568 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5569 ErrInfo = "Illegal immediate value for operand.";
5570 return false;
5571 }
5572 break;
5573 }
5578 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5579 !isInlineConstant(MI, i) &&
5581 OpInfo.OperandType ==
5583 ErrInfo = "illegal 64-bit immediate value for operand.";
5584 return false;
5585 }
5586 break;
5589 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5590 ErrInfo = "Expected inline constant for operand.";
5591 return false;
5592 }
5593 break;
5596 break;
5601 // Check if this operand is an immediate.
5602 // FrameIndex operands will be replaced by immediates, so they are
5603 // allowed.
5604 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5605 ErrInfo = "Expected immediate, but got non-immediate";
5606 return false;
5607 }
5608 break;
5612 break;
5613 default:
5614 if (OpInfo.isGenericType())
5615 continue;
5616 break;
5617 }
5618 }
5619
5620 // Verify SDWA
5621 if (isSDWA(MI)) {
5622 if (!ST.hasSDWA()) {
5623 ErrInfo = "SDWA is not supported on this target";
5624 return false;
5625 }
5626
5627 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5628 AMDGPU::OpName::dst_sel}) {
5629 const MachineOperand *MO = getNamedOperand(MI, Op);
5630 if (!MO)
5631 continue;
5632 int64_t Imm = MO->getImm();
5634 ErrInfo = "Invalid SDWA selection";
5635 return false;
5636 }
5637 }
5638
5639 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5640
5641 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5642 if (OpIdx == -1)
5643 continue;
5644 const MachineOperand &MO = MI.getOperand(OpIdx);
5645
5646 if (!ST.hasSDWAScalar()) {
5647 // Only VGPRS on VI
5648 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5649 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5650 return false;
5651 }
5652 } else {
5653 // No immediates on GFX9
5654 if (!MO.isReg()) {
5655 ErrInfo =
5656 "Only reg allowed as operands in SDWA instructions on GFX9+";
5657 return false;
5658 }
5659 }
5660 }
5661
5662 if (!ST.hasSDWAOmod()) {
5663 // No omod allowed on VI
5664 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5665 if (OMod != nullptr &&
5666 (!OMod->isImm() || OMod->getImm() != 0)) {
5667 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5668 return false;
5669 }
5670 }
5671
5672 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5673 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5674 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5675 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5676 const MachineOperand *Src0ModsMO =
5677 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5678 unsigned Mods = Src0ModsMO->getImm();
5679 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5680 Mods & SISrcMods::SEXT) {
5681 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5682 return false;
5683 }
5684 }
5685
5686 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5687 if (isVOPC(BasicOpcode)) {
5688 if (!ST.hasSDWASdst() && DstIdx != -1) {
5689 // Only vcc allowed as dst on VI for VOPC
5690 const MachineOperand &Dst = MI.getOperand(DstIdx);
5691 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5692 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5693 return false;
5694 }
5695 } else if (!ST.hasSDWAOutModsVOPC()) {
5696 // No clamp allowed on GFX9 for VOPC
5697 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5698 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5699 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5700 return false;
5701 }
5702
5703 // No omod allowed on GFX9 for VOPC
5704 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5705 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5706 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5707 return false;
5708 }
5709 }
5710 }
5711
5712 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5713 if (DstUnused && DstUnused->isImm() &&
5714 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5715 const MachineOperand &Dst = MI.getOperand(DstIdx);
5716 if (!Dst.isReg() || !Dst.isTied()) {
5717 ErrInfo = "Dst register should have tied register";
5718 return false;
5719 }
5720
5721 const MachineOperand &TiedMO =
5722 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5723 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5724 ErrInfo =
5725 "Dst register should be tied to implicit use of preserved register";
5726 return false;
5727 }
5728 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5729 ErrInfo = "Dst register should use same physical register as preserved";
5730 return false;
5731 }
5732 }
5733 }
5734
5735 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5736 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5737 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5738 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5739 return false;
5740 }
5741 if (Src1MO.isImm()) {
5742 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5743 return false;
5744 }
5745 }
5746
5747 // Verify MIMG / VIMAGE / VSAMPLE
5748 if (isImage(Opcode) && !MI.mayStore()) {
5749 // Ensure that the return type used is large enough for all the options
5750 // being used TFE/LWE require an extra result register.
5751 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5752 if (DMask) {
5753 uint64_t DMaskImm = DMask->getImm();
5754 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5755 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5756 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5757 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5758
5759 // Adjust for packed 16 bit values
5760 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5761 RegCount = divideCeil(RegCount, 2);
5762
5763 // Adjust if using LWE or TFE
5764 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5765 RegCount += 1;
5766
5767 const uint32_t DstIdx =
5768 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5769 const MachineOperand &Dst = MI.getOperand(DstIdx);
5770 if (Dst.isReg()) {
5771 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5772 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5773 if (RegCount > DstSize) {
5774 ErrInfo = "Image instruction returns too many registers for dst "
5775 "register class";
5776 return false;
5777 }
5778 }
5779 }
5780 }
5781
5782 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5783 if (isVALU(MI, /*AllowLDSDMA=*/false) &&
5784 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5785 unsigned ConstantBusCount = 0;
5786 bool UsesLiteral = false;
5787 const MachineOperand *LiteralVal = nullptr;
5788
5789 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5790 if (ImmIdx != -1) {
5791 ++ConstantBusCount;
5792 UsesLiteral = true;
5793 LiteralVal = &MI.getOperand(ImmIdx);
5794 }
5795
5796 SmallVector<Register, 2> SGPRsUsed;
5797 Register SGPRUsed;
5798
5799 // Only look at the true operands. Only a real operand can use the constant
5800 // bus, and we don't want to check pseudo-operands like the source modifier
5801 // flags.
5802 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5803 if (OpIdx == -1)
5804 continue;
5805 const MachineOperand &MO = MI.getOperand(OpIdx);
5806 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5807 if (MO.isReg()) {
5808 SGPRUsed = MO.getReg();
5809 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5810 ++ConstantBusCount;
5811 SGPRsUsed.push_back(SGPRUsed);
5812 }
5813 } else if (!MO.isFI()) { // Treat FI like a register.
5814 if (!UsesLiteral) {
5815 ++ConstantBusCount;
5816 UsesLiteral = true;
5817 LiteralVal = &MO;
5818 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5819 assert(isVOP2(MI) || isVOP3(MI));
5820 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5821 return false;
5822 }
5823 }
5824 }
5825 }
5826
5827 SGPRUsed = findImplicitSGPRRead(MI);
5828 if (SGPRUsed) {
5829 // Implicit uses may safely overlap true operands
5830 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5831 return !RI.regsOverlap(SGPRUsed, SGPR);
5832 })) {
5833 ++ConstantBusCount;
5834 SGPRsUsed.push_back(SGPRUsed);
5835 }
5836 }
5837
5838 // v_writelane_b32 is an exception from constant bus restriction:
5839 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5840 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5841 Opcode != AMDGPU::V_WRITELANE_B32) {
5842 ErrInfo = "VOP* instruction violates constant bus restriction";
5843 return false;
5844 }
5845
5846 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5847 ErrInfo = "VOP3 instruction uses literal";
5848 return false;
5849 }
5850 }
5851
5852 // Special case for writelane - this can break the multiple constant bus rule,
5853 // but still can't use more than one SGPR register
5854 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5855 unsigned SGPRCount = 0;
5856 Register SGPRUsed;
5857
5858 for (int OpIdx : {Src0Idx, Src1Idx}) {
5859 if (OpIdx == -1)
5860 break;
5861
5862 const MachineOperand &MO = MI.getOperand(OpIdx);
5863
5864 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5865 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5866 if (MO.getReg() != SGPRUsed)
5867 ++SGPRCount;
5868 SGPRUsed = MO.getReg();
5869 }
5870 }
5871 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5872 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5873 return false;
5874 }
5875 }
5876 }
5877
5878 // Verify misc. restrictions on specific instructions.
5879 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5880 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5881 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5882 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5883 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
5884 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5885 if (!compareMachineOp(Src0, Src1) &&
5886 !compareMachineOp(Src0, Src2)) {
5887 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
5888 return false;
5889 }
5890 }
5891 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
5892 SISrcMods::ABS) ||
5893 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
5894 SISrcMods::ABS) ||
5895 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
5896 SISrcMods::ABS)) {
5897 ErrInfo = "ABS not allowed in VOP3B instructions";
5898 return false;
5899 }
5900 }
5901
5902 if (isSOP2(MI) || isSOPC(MI)) {
5903 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5904 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5905
5906 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
5907 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
5908 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
5909 !Src0.isIdenticalTo(Src1)) {
5910 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
5911 return false;
5912 }
5913 }
5914
5915 if (isSOPK(MI)) {
5916 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
5917 if (Desc.isBranch()) {
5918 if (!Op->isMBB()) {
5919 ErrInfo = "invalid branch target for SOPK instruction";
5920 return false;
5921 }
5922 } else {
5923 uint64_t Imm = Op->getImm();
5924 if (sopkIsZext(Opcode)) {
5925 if (!isUInt<16>(Imm)) {
5926 ErrInfo = "invalid immediate for SOPK instruction";
5927 return false;
5928 }
5929 } else {
5930 if (!isInt<16>(Imm)) {
5931 ErrInfo = "invalid immediate for SOPK instruction";
5932 return false;
5933 }
5934 }
5935 }
5936 }
5937
5938 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5939 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5940 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5941 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5942 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5943 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5944
5945 const unsigned StaticNumOps =
5946 Desc.getNumOperands() + Desc.implicit_uses().size();
5947 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5948
5949 // Require additional implicit operands. This allows a fixup done by the
5950 // post RA scheduler where the main implicit operand is killed and
5951 // implicit-defs are added for sub-registers that remain live after this
5952 // instruction.
5953 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5954 ErrInfo = "missing implicit register operands";
5955 return false;
5956 }
5957
5958 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5959 if (IsDst) {
5960 if (!Dst->isUse()) {
5961 ErrInfo = "v_movreld_b32 vdst should be a use operand";
5962 return false;
5963 }
5964
5965 unsigned UseOpIdx;
5966 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5967 UseOpIdx != StaticNumOps + 1) {
5968 ErrInfo = "movrel implicit operands should be tied";
5969 return false;
5970 }
5971 }
5972
5973 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5974 const MachineOperand &ImpUse
5975 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5976 if (!ImpUse.isReg() || !ImpUse.isUse() ||
5977 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5978 ErrInfo = "src0 should be subreg of implicit vector use";
5979 return false;
5980 }
5981 }
5982
5983 // Make sure we aren't losing exec uses in the td files. This mostly requires
5984 // being careful when using let Uses to try to add other use registers.
5985 if (shouldReadExec(MI)) {
5986 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5987 ErrInfo = "VALU instruction does not implicitly read exec mask";
5988 return false;
5989 }
5990 }
5991
5992 if (isSMRD(MI)) {
5993 if (MI.mayStore() &&
5994 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
5995 // The register offset form of scalar stores may only use m0 as the
5996 // soffset register.
5997 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
5998 if (Soff && Soff->getReg() != AMDGPU::M0) {
5999 ErrInfo = "scalar stores must use m0 as offset register";
6000 return false;
6001 }
6002 }
6003 }
6004
6005 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
6006 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
6007 if (Offset->getImm() != 0) {
6008 ErrInfo = "subtarget does not support offsets in flat instructions";
6009 return false;
6010 }
6011 }
6012
6013 if (isDS(MI) && !ST.hasGDS()) {
6014 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
6015 if (GDSOp && GDSOp->getImm() != 0) {
6016 ErrInfo = "GDS is not supported on this subtarget";
6017 return false;
6018 }
6019 }
6020
6021 if (isImage(MI)) {
6022 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
6023 if (DimOp) {
6024 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
6025 AMDGPU::OpName::vaddr0);
6026 AMDGPU::OpName RSrcOpName =
6027 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
6028 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
6029 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
6030 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
6031 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
6032 const AMDGPU::MIMGDimInfo *Dim =
6034
6035 if (!Dim) {
6036 ErrInfo = "dim is out of range";
6037 return false;
6038 }
6039
6040 bool IsA16 = false;
6041 if (ST.hasR128A16()) {
6042 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
6043 IsA16 = R128A16->getImm() != 0;
6044 } else if (ST.hasA16()) {
6045 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
6046 IsA16 = A16->getImm() != 0;
6047 }
6048
6049 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
6050
6051 unsigned AddrWords =
6052 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
6053
6054 unsigned VAddrWords;
6055 if (IsNSA) {
6056 VAddrWords = RsrcIdx - VAddr0Idx;
6057 if (ST.hasPartialNSAEncoding() &&
6058 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
6059 unsigned LastVAddrIdx = RsrcIdx - 1;
6060 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
6061 }
6062 } else {
6063 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
6064 if (AddrWords > 12)
6065 AddrWords = 16;
6066 }
6067
6068 if (VAddrWords != AddrWords) {
6069 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
6070 << " but got " << VAddrWords << "\n");
6071 ErrInfo = "bad vaddr size";
6072 return false;
6073 }
6074 }
6075 }
6076
6077 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
6078 if (DppCt) {
6079 using namespace AMDGPU::DPP;
6080
6081 unsigned DC = DppCt->getImm();
6082 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6083 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6084 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6085 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6086 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6087 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6088 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6089 ErrInfo = "Invalid dpp_ctrl value";
6090 return false;
6091 }
6092 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6093 !ST.hasDPPWavefrontShifts()) {
6094 ErrInfo = "Invalid dpp_ctrl value: "
6095 "wavefront shifts are not supported on GFX10+";
6096 return false;
6097 }
6098 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6099 !ST.hasDPPBroadcasts()) {
6100 ErrInfo = "Invalid dpp_ctrl value: "
6101 "broadcasts are not supported on GFX10+";
6102 return false;
6103 }
6104 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6105 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
6106 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6107 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6108 !ST.hasGFX90AInsts()) {
6109 ErrInfo = "Invalid dpp_ctrl value: "
6110 "row_newbroadcast/row_share is not supported before "
6111 "GFX90A/GFX10";
6112 return false;
6113 }
6114 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6115 ErrInfo = "Invalid dpp_ctrl value: "
6116 "row_share and row_xmask are not supported before GFX10";
6117 return false;
6118 }
6119 }
6120
6121 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6123 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6124 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
6125 ErrInfo = "Invalid dpp_ctrl value: "
6126 "DP ALU dpp only support row_newbcast";
6127 return false;
6128 }
6129 }
6130
6131 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
6132 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
6133 AMDGPU::OpName DataName =
6134 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6135 const MachineOperand *Data = getNamedOperand(MI, DataName);
6136 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
6137 if (Data && !Data->isReg())
6138 Data = nullptr;
6139
6140 if (!ST.hasGFX90AInsts()) {
6141 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6142 (Data && RI.isAGPR(MRI, Data->getReg())) ||
6143 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
6144 ErrInfo = "Invalid register class: "
6145 "agpr loads and stores not supported on this GPU";
6146 return false;
6147 }
6148 }
6149 }
6150
6151 if (ST.needsAlignedVGPRs()) {
6152 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
6154 if (!Op)
6155 return true;
6156 Register Reg = Op->getReg();
6157 if (Reg.isPhysical())
6158 return !(RI.getHWRegIndex(Reg) & 1);
6159 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
6160 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6161 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
6162 };
6163
6164 if (isMIMG(MI)) {
6165 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6166 ErrInfo = "Subtarget requires even aligned vector registers "
6167 "for vaddr operand of image instructions";
6168 return false;
6169 }
6170 }
6171 }
6172
6173 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6174 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
6175 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6176 ErrInfo = "Invalid register class: "
6177 "v_accvgpr_write with an SGPR is not supported on this GPU";
6178 return false;
6179 }
6180 }
6181
6182 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6183 const MachineOperand &SrcOp = MI.getOperand(1);
6184 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
6185 ErrInfo = "pseudo expects only physical SGPRs";
6186 return false;
6187 }
6188 }
6189
6190 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
6191 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
6192 if (!ST.hasScaleOffset()) {
6193 ErrInfo = "Subtarget does not support offset scaling";
6194 return false;
6195 }
6196 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
6197 ErrInfo = "Instruction does not support offset scaling";
6198 return false;
6199 }
6200 }
6201 }
6202
6203 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6204 if (AMDGPU::isSingleSGPRReadInst(Opcode)) {
6205 for (unsigned I = 0; I < 3; ++I) {
6207 return false;
6208 }
6209 }
6210
6211 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
6212 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
6213 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
6214 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6215 &AMDGPU::SReg_64RegClass) ||
6216 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6217 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
6218 return false;
6219 }
6220 }
6221
6222 return true;
6223}
6224
6226 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
6227 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6228 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
6229 ? AMDGPU::COPY
6230 : AMDGPU::V_MOV_B32_e32;
6231 }
6232 return getVALUOp(MI.getOpcode());
6233}
6234
6235// It is more readable to list mapped opcodes on the same line.
6236// clang-format off
6237
6238unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
6239 switch (Opc) {
6240 default: return AMDGPU::INSTRUCTION_LIST_END;
6241 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
6242 case AMDGPU::COPY: return AMDGPU::COPY;
6243 case AMDGPU::PHI: return AMDGPU::PHI;
6244 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
6245 case AMDGPU::WQM: return AMDGPU::WQM;
6246 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
6247 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
6248 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
6249 case AMDGPU::S_ADD_I32:
6250 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6251 case AMDGPU::S_ADDC_U32:
6252 return AMDGPU::V_ADDC_U32_e32;
6253 case AMDGPU::S_SUB_I32:
6254 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6255 // FIXME: These are not consistently handled, and selected when the carry is
6256 // used.
6257 case AMDGPU::S_ADD_U32:
6258 return AMDGPU::V_ADD_CO_U32_e32;
6259 case AMDGPU::S_SUB_U32:
6260 return AMDGPU::V_SUB_CO_U32_e32;
6261 case AMDGPU::S_ADD_U64_PSEUDO:
6262 return AMDGPU::V_ADD_U64_PSEUDO;
6263 case AMDGPU::S_SUB_U64_PSEUDO:
6264 return AMDGPU::V_SUB_U64_PSEUDO;
6265 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
6266 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
6267 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
6268 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
6269 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
6270 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
6271 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
6272 case AMDGPU::S_XNOR_B32:
6273 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6274 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
6275 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
6276 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
6277 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
6278 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
6279 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
6280 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
6281 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
6282 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
6283 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
6284 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
6285 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
6286 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
6287 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
6288 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
6289 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
6290 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
6291 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
6292 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
6293 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
6294 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
6295 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
6296 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
6297 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
6298 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
6299 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
6300 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
6301 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
6302 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
6303 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
6304 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
6305 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
6306 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
6307 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
6308 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
6309 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
6310 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
6311 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
6312 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
6313 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
6314 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
6315 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
6316 case AMDGPU::S_CVT_F32_F16:
6317 case AMDGPU::S_CVT_HI_F32_F16:
6318 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6319 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6320 case AMDGPU::S_CVT_F16_F32:
6321 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6322 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6323 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
6324 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
6325 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
6326 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
6327 case AMDGPU::S_CEIL_F16:
6328 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6329 : AMDGPU::V_CEIL_F16_fake16_e64;
6330 case AMDGPU::S_FLOOR_F16:
6331 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6332 : AMDGPU::V_FLOOR_F16_fake16_e64;
6333 case AMDGPU::S_TRUNC_F16:
6334 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6335 : AMDGPU::V_TRUNC_F16_fake16_e64;
6336 case AMDGPU::S_RNDNE_F16:
6337 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6338 : AMDGPU::V_RNDNE_F16_fake16_e64;
6339 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6340 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6341 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6342 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6343 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6344 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6345 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6346 case AMDGPU::S_ADD_F16:
6347 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6348 : AMDGPU::V_ADD_F16_fake16_e64;
6349 case AMDGPU::S_SUB_F16:
6350 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6351 : AMDGPU::V_SUB_F16_fake16_e64;
6352 case AMDGPU::S_MIN_F16:
6353 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6354 : AMDGPU::V_MIN_F16_fake16_e64;
6355 case AMDGPU::S_MAX_F16:
6356 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6357 : AMDGPU::V_MAX_F16_fake16_e64;
6358 case AMDGPU::S_MINIMUM_F16:
6359 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6360 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6361 case AMDGPU::S_MAXIMUM_F16:
6362 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6363 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6364 case AMDGPU::S_MUL_F16:
6365 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6366 : AMDGPU::V_MUL_F16_fake16_e64;
6367 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6368 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6369 case AMDGPU::S_FMAC_F16:
6370 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6371 : AMDGPU::V_FMAC_F16_fake16_e64;
6372 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6373 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6374 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6375 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6376 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6377 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6378 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6379 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6380 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6381 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6382 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6383 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6384 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6385 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6386 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6387 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6388 case AMDGPU::S_CMP_LT_F16:
6389 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6390 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6391 case AMDGPU::S_CMP_EQ_F16:
6392 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6393 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6394 case AMDGPU::S_CMP_LE_F16:
6395 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6396 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6397 case AMDGPU::S_CMP_GT_F16:
6398 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6399 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6400 case AMDGPU::S_CMP_LG_F16:
6401 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6402 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6403 case AMDGPU::S_CMP_GE_F16:
6404 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6405 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6406 case AMDGPU::S_CMP_O_F16:
6407 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6408 : AMDGPU::V_CMP_O_F16_fake16_e64;
6409 case AMDGPU::S_CMP_U_F16:
6410 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6411 : AMDGPU::V_CMP_U_F16_fake16_e64;
6412 case AMDGPU::S_CMP_NGE_F16:
6413 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6414 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6415 case AMDGPU::S_CMP_NLG_F16:
6416 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6417 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6418 case AMDGPU::S_CMP_NGT_F16:
6419 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6420 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6421 case AMDGPU::S_CMP_NLE_F16:
6422 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6423 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6424 case AMDGPU::S_CMP_NEQ_F16:
6425 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6426 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6427 case AMDGPU::S_CMP_NLT_F16:
6428 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6429 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6430 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6431 case AMDGPU::V_S_EXP_F16_e64:
6432 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6433 : AMDGPU::V_EXP_F16_fake16_e64;
6434 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6435 case AMDGPU::V_S_LOG_F16_e64:
6436 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6437 : AMDGPU::V_LOG_F16_fake16_e64;
6438 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6439 case AMDGPU::V_S_RCP_F16_e64:
6440 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6441 : AMDGPU::V_RCP_F16_fake16_e64;
6442 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6443 case AMDGPU::V_S_RSQ_F16_e64:
6444 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6445 : AMDGPU::V_RSQ_F16_fake16_e64;
6446 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6447 case AMDGPU::V_S_SQRT_F16_e64:
6448 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6449 : AMDGPU::V_SQRT_F16_fake16_e64;
6450 }
6452 "Unexpected scalar opcode without corresponding vector one!");
6453}
6454
6455// clang-format on
6456
6460 const DebugLoc &DL, Register Reg,
6461 bool IsSCCLive,
6462 SlotIndexes *Indexes) const {
6463 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6464 const SIInstrInfo *TII = ST.getInstrInfo();
6466 if (IsSCCLive) {
6467 // Insert two move instructions, one to save the original value of EXEC and
6468 // the other to turn on all bits in EXEC. This is required as we can't use
6469 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6470 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6472 auto FlipExecMI =
6473 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6474 if (Indexes) {
6475 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6476 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6477 }
6478 } else {
6479 auto SaveExec =
6480 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6481 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6482 if (Indexes)
6483 Indexes->insertMachineInstrInMaps(*SaveExec);
6484 }
6485}
6486
6489 const DebugLoc &DL, Register Reg,
6490 SlotIndexes *Indexes) const {
6492 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6493 .addReg(Reg, RegState::Kill);
6494 if (Indexes)
6495 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6496}
6497
6501 "Not a whole wave func");
6502 MachineBasicBlock &MBB = *MF.begin();
6503 for (MachineInstr &MI : MBB)
6504 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6505 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6506 return &MI;
6507
6508 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6509}
6510
6512 unsigned OpNo) const {
6513 const MCInstrDesc &Desc = get(MI.getOpcode());
6514 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6515 Desc.operands()[OpNo].RegClass == -1) {
6516 Register Reg = MI.getOperand(OpNo).getReg();
6517
6518 if (Reg.isVirtual()) {
6519 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6520 return MRI.getRegClass(Reg);
6521 }
6522 return RI.getPhysRegBaseClass(Reg);
6523 }
6524
6525 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6526 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6527}
6528
6529// Convert VOP3 operand index to source number.
6530static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx) {
6531 constexpr AMDGPU::OpName OpNames[] = {
6532 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6533
6534 for (auto [I, OpName] : enumerate(OpNames)) {
6535 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6536 if (static_cast<unsigned>(SrcIdx) == OpIdx)
6537 return I;
6538 }
6539
6540 return UINT_MAX;
6541}
6542
6545 MachineBasicBlock *MBB = MI.getParent();
6546 MachineOperand &MO = MI.getOperand(OpIdx);
6547 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6548 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6549 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6550 unsigned Size = RI.getRegSizeInBits(*RC);
6551 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6552 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6553 : AMDGPU::V_MOV_B32_e32;
6554 if (MO.isReg())
6555 Opcode = AMDGPU::COPY;
6556 else if (RI.isSGPRClass(RC))
6557 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6558
6559 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6560 Register Reg = MRI.createVirtualRegister(VRC);
6561 DebugLoc DL = MBB->findDebugLoc(I);
6562
6563 if (Size == 128 && AMDGPU::isPackedSingleSGPR64BitInst(MI.getOpcode()) &&
6565 // Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
6566 // sources behave like OPSEL is set replicating low 64-bits into high. VGPR
6567 // sources in turn read actual 4 registers. To move operand from an SGPR to
6568 // a VGPR we need to replicate low half.
6569 // We also do not select immediates for these instructions so it always has
6570 // to be an SGPR register here.
6571 // Operands which are not legal as per isLegalSingleSGPRReadInstOperand()
6572 // sent here specifically to fix a non-splat SGPR and shall perform a full
6573 // copy.
6574
6575 const TargetRegisterClass *VRC64 = RI.getVGPRClassForBitWidth(64);
6576 Register Low64 = MRI.createVirtualRegister(VRC64);
6577 assert(MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()));
6578 BuildMI(*MBB, I, DL, get(TargetOpcode::COPY), Low64)
6579 .addReg(MO.getReg(), {}, AMDGPU::sub0_sub1);
6580 BuildMI(*MBB, I, DL, get(TargetOpcode::REG_SEQUENCE), Reg)
6581 .addReg(Low64)
6582 .addImm(AMDGPU::sub0_sub1)
6583 .addReg(Low64)
6584 .addImm(AMDGPU::sub2_sub3);
6585 } else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6586 BuildMI(*MBB, I, DL, get(Opcode), Reg)
6587 .addImm(0) // src0_modifiers
6588 .add(MO)
6589 .addImm(0); // op_sel
6590 } else {
6591 BuildMI(*MBB, I, DL, get(Opcode), Reg).add(MO);
6592 }
6593
6594 MO.ChangeToRegister(Reg, false);
6595}
6596
6599 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6600 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6601 if (!SuperReg.getReg().isVirtual())
6602 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6603
6604 MachineBasicBlock *MBB = MI->getParent();
6605 const DebugLoc &DL = MI->getDebugLoc();
6606 Register SubReg = MRI.createVirtualRegister(SubRC);
6607
6608 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6609 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6610 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6611 return SubReg;
6612}
6613
6616 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6617 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6618 if (Op.isImm()) {
6619 if (SubIdx == AMDGPU::sub0)
6620 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6621 if (SubIdx == AMDGPU::sub1)
6622 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6623
6624 llvm_unreachable("Unhandled register index for immediate");
6625 }
6626
6627 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6628 SubIdx, SubRC);
6629 return MachineOperand::CreateReg(SubReg, false);
6630}
6631
6632// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6633void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6634 assert(Inst.getNumExplicitOperands() == 3);
6635 MachineOperand Op1 = Inst.getOperand(1);
6636 Inst.removeOperand(1);
6637 Inst.addOperand(Op1);
6638}
6639
6641 const MCOperandInfo &OpInfo,
6642 const MachineOperand &MO) const {
6643 if (!MO.isReg())
6644 return false;
6645
6646 Register Reg = MO.getReg();
6647
6648 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6649 if (Reg.isPhysical())
6650 return DRC->contains(Reg);
6651
6652 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6653
6654 if (MO.getSubReg()) {
6655 const TargetRegisterClass *SuperRC =
6656 RI.getLargestLegalSuperClass(RC, MRI.getMF());
6657 if (!SuperRC)
6658 return false;
6659 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6660 }
6661
6662 return RI.getCommonSubClass(DRC, RC) != nullptr;
6663}
6664
6666 const MachineOperand &MO) const {
6667 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6668 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6669 unsigned Opc = MI.getOpcode();
6670
6671 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6672 if (MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
6673 AMDGPU::isSingleSGPRReadInst(MI.getOpcode()) &&
6675 &MO))
6676 return false;
6677
6678 if (!isLegalRegOperand(MRI, OpInfo, MO))
6679 return false;
6680
6681 // check Accumulate GPR operand
6682 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6683 if (IsAGPR && !ST.hasMAIInsts())
6684 return false;
6685 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6686 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6687 return false;
6688 // Atomics should have both vdst and vdata either vgpr or agpr.
6689 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6690 const int DataIdx = AMDGPU::getNamedOperandIdx(
6691 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6692 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6693 MI.getOperand(DataIdx).isReg() &&
6694 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6695 return false;
6696 if ((int)OpIdx == DataIdx) {
6697 if (VDstIdx != -1 &&
6698 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6699 return false;
6700 // DS instructions with 2 src operands also must have tied RC.
6701 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6702 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6703 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6704 return false;
6705 }
6706
6707 // Check V_ACCVGPR_WRITE_B32_e64
6708 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6709 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6710 RI.isSGPRReg(MRI, MO.getReg()))
6711 return false;
6712
6713 if (ST.hasFlatScratchHiInB64InstHazard() &&
6714 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6715 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6716 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6717 64)
6718 return false;
6719 }
6720 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6721 return false;
6722 }
6723 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6724 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6725 return false;
6726
6727 return true;
6728}
6729
6731 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6732 const MachineOperand *MO) const {
6733 constexpr unsigned NumOps = 3;
6734 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6735 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6736 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6737 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6738
6739 assert(SrcN < NumOps);
6740
6741 if (!MO) {
6742 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6743 if (SrcIdx == -1)
6744 return true;
6745 MO = &MI.getOperand(SrcIdx);
6746 }
6747
6748 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6749 return true;
6750
6751 int ModsIdx =
6752 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6753 if (ModsIdx == -1)
6754 return false;
6755
6756 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6757 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6758 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6759
6760 return !OpSel && !OpSelHi;
6761}
6762
6763// Check if V_PK_FMA_F32 does not have the invalid opsel conditions.
6765 if (!ST.hasPkF32InvalidOpSel() || MI.getOpcode() != AMDGPU::V_PK_FMA_F32)
6766 return true;
6767
6768 const MachineOperand *Src1Mods =
6769 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
6770 const MachineOperand *Src2Mods =
6771 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
6772
6773 auto HasOpSel0 = [](const MachineOperand *Mods) {
6774 return Mods->getImm() & SISrcMods::OP_SEL_0;
6775 };
6776
6777 // Illegal iff opsel[2:1] == 2'b01, 2'b10, or 2'b11
6778 return !HasOpSel0(Src1Mods) && !HasOpSel0(Src2Mods);
6779}
6780
6782 MachineRegisterInfo &MRI) const {
6783 assert(MI.getOpcode() == AMDGPU::V_PK_FMA_F32);
6784
6785 MachineBasicBlock &MBB = *MI.getParent();
6786 const DebugLoc &DL = MI.getDebugLoc();
6787
6788 MachineOperand *Srcs[3] = {getNamedOperand(MI, AMDGPU::OpName::src0),
6789 getNamedOperand(MI, AMDGPU::OpName::src1),
6790 getNamedOperand(MI, AMDGPU::OpName::src2)};
6791 const unsigned Mods[3] = {
6792 static_cast<unsigned>(
6793 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm()),
6794 static_cast<unsigned>(
6795 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm()),
6796 static_cast<unsigned>(
6797 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm())};
6798
6799 // extract op_sel / op_sel_hi
6800 bool OpSel[3][2];
6801 for (unsigned I = 0; I != 3; ++I) {
6802 OpSel[I][0] = Mods[I] & SISrcMods::OP_SEL_0;
6803 OpSel[I][1] = Mods[I] & SISrcMods::OP_SEL_1;
6804 }
6805
6806 // The packed op can read only one SGPR on the constant bus (limit is 1 on
6807 // gfx9), so all its SGPR sources are the same pair. Each scalar lane can also
6808 // read only one SGPR, but op_sel may make a lane read different halves of
6809 // that pair, e.g.
6810 // v_pk_fma_f32 v[0:1], s[0:1], 0, s[0:1] op_sel:[0,0,1] op_sel_hi:[1,1,0]
6811 // => v_fma_f32 v0, s0, 0, s1 / v_fma_f32 v1, s1, 0, s0
6812 // If so, copy the pair to a VGPR once before extracting the lanes, rather
6813 // than moving a scalar into a VGPR per lane.
6814 SmallVector<unsigned, 3> SGPRSrcs;
6815 bool DivergentSGPRs = false;
6816 for (unsigned I = 0; I != 3; ++I) {
6817 if (!Srcs[I]->isReg() || !RI.isSGPRReg(MRI, Srcs[I]->getReg()))
6818 continue;
6819 if (!SGPRSrcs.empty()) {
6820 unsigned First = SGPRSrcs.front();
6821 assert(Srcs[I]->getReg() == Srcs[First]->getReg() &&
6822 Srcs[I]->getSubReg() == Srcs[First]->getSubReg() &&
6823 "constant bus limit allows only one SGPR source");
6824 DivergentSGPRs |=
6825 OpSel[I][0] != OpSel[First][0] || OpSel[I][1] != OpSel[First][1];
6826 }
6827 SGPRSrcs.push_back(I);
6828 }
6829
6830 if (DivergentSGPRs) {
6831 unsigned First = SGPRSrcs.front();
6832 legalizeOpWithMove(MI, MI.getOperandNo(Srcs[First]));
6833 for (unsigned I : ArrayRef(SGPRSrcs).drop_front())
6834 Srcs[I]->ChangeToRegister(Srcs[First]->getReg(), /*isDef=*/false);
6835 }
6836
6837 // Extract the low or high lane of a packed VOP3P source operand.
6838 auto ExtractLane = [&](MachineOperand &Op, bool UseSub1) -> MachineOperand {
6839 unsigned SubIdx = (Op.isReg() && UseSub1) ? AMDGPU::sub1 : AMDGPU::sub0;
6840 const TargetRegisterClass *RC =
6841 Op.isReg() ? MRI.getRegClass(Op.getReg()) : nullptr;
6842 const TargetRegisterClass *SubRC = !Op.isReg() ? nullptr
6843 : RI.isVGPR(MRI, Op.getReg())
6844 ? RI.getVGPRClassForBitWidth(32)
6845 : RI.getSGPRClassForBitWidth(32);
6846 return buildExtractSubRegOrImm(MI, MRI, Op, RC, SubIdx, SubRC);
6847 };
6848
6849 // neg_lo/neg_hi on the packed operand become a plain NEG modifier.
6850 auto LaneMods = [](unsigned Mods, bool Hi) -> unsigned {
6851 if (Hi)
6852 return (Mods & SISrcMods::NEG_HI) ? static_cast<unsigned>(SISrcMods::NEG)
6853 : 0u;
6854 return Mods & SISrcMods::NEG;
6855 };
6856
6857 auto BuildLane = [&](Register Dst, bool Hi) {
6858 MachineOperand L0 = ExtractLane(*Srcs[0], OpSel[0][Hi]);
6859 MachineOperand L1 = ExtractLane(*Srcs[1], OpSel[1][Hi]);
6860 MachineOperand L2 = ExtractLane(*Srcs[2], OpSel[2][Hi]);
6861 BuildMI(MBB, MI, DL, get(AMDGPU::V_FMA_F32_e64), Dst)
6862 .addImm(LaneMods(Mods[0], Hi))
6863 .add(L0)
6864 .addImm(LaneMods(Mods[1], Hi))
6865 .add(L1)
6866 .addImm(LaneMods(Mods[2], Hi))
6867 .add(L2)
6868 .addImm(0) // clamp
6869 .addImm(0); // omod
6870 };
6871
6872 const TargetRegisterClass *VGPR32 = RI.getVGPRClassForBitWidth(32);
6873 Register Lo = MRI.createVirtualRegister(VGPR32);
6874 Register Hi = MRI.createVirtualRegister(VGPR32);
6875 BuildLane(Lo, false);
6876 BuildLane(Hi, true);
6877
6878 Register Dst = getNamedOperand(MI, AMDGPU::OpName::vdst)->getReg();
6879 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
6880 .addReg(Lo)
6881 .addImm(AMDGPU::sub0)
6882 .addReg(Hi)
6883 .addImm(AMDGPU::sub1);
6884
6885 MI.eraseFromParent();
6886}
6887
6888bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
6889 const MachineOperand *MO) const {
6890 const MachineFunction &MF = *MI.getMF();
6891 const MachineRegisterInfo &MRI = MF.getRegInfo();
6892 const MCInstrDesc &InstDesc = MI.getDesc();
6893 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6894 int64_t RegClass = getOpRegClassID(OpInfo);
6895 const TargetRegisterClass *DefinedRC =
6896 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6897 if (!MO)
6898 MO = &MI.getOperand(OpIdx);
6899
6900 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6901
6902 if (isVALU(MI, /*AllowLDSDMA=*/false) && !IsInlineConst &&
6903 usesConstantBus(MRI, *MO, OpInfo)) {
6904 const MachineOperand *UsedLiteral = nullptr;
6905
6906 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6907 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6908
6909 // TODO: Be more permissive with frame indexes.
6910 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6911 if (!LiteralLimit--)
6912 return false;
6913
6914 UsedLiteral = MO;
6915 }
6916
6918 if (MO->isReg())
6919 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6920
6921 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6922 if (i == OpIdx)
6923 continue;
6924 const MachineOperand &Op = MI.getOperand(i);
6925 if (Op.isReg()) {
6926 if (Op.isUse()) {
6927 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6928 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6929 if (--ConstantBusLimit <= 0)
6930 return false;
6931 }
6932 }
6933 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6934 !isInlineConstant(Op, InstDesc.operands()[i])) {
6935 // The same literal may be used multiple times.
6936 if (!UsedLiteral)
6937 UsedLiteral = &Op;
6938 else if (UsedLiteral->isIdenticalTo(Op))
6939 continue;
6940
6941 if (!LiteralLimit--)
6942 return false;
6943 if (--ConstantBusLimit <= 0)
6944 return false;
6945 }
6946 }
6947 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6948 // There can be at most one literal operand, but it can be repeated.
6949 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6950 if (i == OpIdx)
6951 continue;
6952 const MachineOperand &Op = MI.getOperand(i);
6953 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6954 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6955 !Op.isIdenticalTo(*MO))
6956 return false;
6957
6958 // Do not fold a non-inlineable and non-register operand into an
6959 // instruction that already has a frame index. The frame index handling
6960 // code could not handle well when a frame index co-exists with another
6961 // non-register operand, unless that operand is an inlineable immediate.
6962 if (Op.isFI())
6963 return false;
6964 }
6965 }
6966
6967 if (MO->isReg()) {
6968 if (!DefinedRC)
6969 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6970 return isLegalRegOperand(MI, OpIdx, *MO);
6971 }
6972
6973 if (MO->isImm()) {
6974 uint64_t Imm = MO->getImm();
6975 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6976 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6977 bool Is64BitOp = Is64BitFPOp ||
6978 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6979 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6980 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6981 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6982 if (Is64BitOp &&
6983 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6984 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6985 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6986 return false;
6987
6988 // FIXME: We can use sign extended 64-bit literals, but only for signed
6989 // operands. At the moment we do not know if an operand is signed.
6990 // Such operand will be encoded as its low 32 bits and then either
6991 // correctly sign extended or incorrectly zero extended by HW.
6992 // If 64-bit literals are supported and the literal will be encoded
6993 // as full 64 bit we still can use it.
6994 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6995 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
6996 return false;
6997 }
6998 }
6999
7000 // Handle non-register types that are treated like immediates.
7001 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
7002
7003 if (!DefinedRC) {
7004 // This operand expects an immediate.
7005 return true;
7006 }
7007
7008 return isImmOperandLegal(MI, OpIdx, *MO);
7009}
7010
7012 bool IsGFX950Only = ST.hasGFX950Insts();
7013 bool IsGFX940Only = ST.hasGFX940Insts();
7014
7015 if (!IsGFX950Only && !IsGFX940Only)
7016 return false;
7017
7018 if (!isVALU(MI, /*AllowLDSDMA=*/false))
7019 return false;
7020
7021 // V_COS, V_EXP, V_RCP, etc.
7022 if (isTRANS(MI))
7023 return true;
7024
7025 // DOT2, DOT2C, DOT4, etc.
7026 if (isDOT(MI))
7027 return true;
7028
7029 // MFMA, SMFMA
7030 if (isMFMA(MI))
7031 return true;
7032
7033 unsigned Opcode = MI.getOpcode();
7034 switch (Opcode) {
7035 case AMDGPU::V_CVT_PK_BF8_F32_e64:
7036 case AMDGPU::V_CVT_PK_FP8_F32_e64:
7037 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
7038 case AMDGPU::V_MQSAD_U32_U8_e64:
7039 case AMDGPU::V_PK_ADD_F16:
7040 case AMDGPU::V_PK_ADD_F32:
7041 case AMDGPU::V_PK_ADD_I16:
7042 case AMDGPU::V_PK_ADD_U16:
7043 case AMDGPU::V_PK_ASHRREV_I16:
7044 case AMDGPU::V_PK_FMA_F16:
7045 case AMDGPU::V_PK_FMA_F32:
7046 case AMDGPU::V_PK_FMAC_F16_e32:
7047 case AMDGPU::V_PK_FMAC_F16_e64:
7048 case AMDGPU::V_PK_LSHLREV_B16:
7049 case AMDGPU::V_PK_LSHRREV_B16:
7050 case AMDGPU::V_PK_MAD_I16:
7051 case AMDGPU::V_PK_MAD_U16:
7052 case AMDGPU::V_PK_MAX_F16:
7053 case AMDGPU::V_PK_MAX_I16:
7054 case AMDGPU::V_PK_MAX_U16:
7055 case AMDGPU::V_PK_MIN_F16:
7056 case AMDGPU::V_PK_MIN_I16:
7057 case AMDGPU::V_PK_MIN_U16:
7058 case AMDGPU::V_PK_MOV_B32:
7059 case AMDGPU::V_PK_MUL_F16:
7060 case AMDGPU::V_PK_MUL_F32:
7061 case AMDGPU::V_PK_MUL_LO_U16:
7062 case AMDGPU::V_PK_SUB_I16:
7063 case AMDGPU::V_PK_SUB_U16:
7064 case AMDGPU::V_QSAD_PK_U16_U8_e64:
7065 return true;
7066 default:
7067 return false;
7068 }
7069}
7070
7072 MachineInstr &MI) const {
7073 unsigned Opc = MI.getOpcode();
7074 const MCInstrDesc &InstrDesc = get(Opc);
7075
7076 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
7077 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7078
7079 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
7080 MachineOperand &Src1 = MI.getOperand(Src1Idx);
7081
7082 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
7083 // we need to only have one constant bus use before GFX10.
7084 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
7085 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
7086 RI.isSGPRReg(MRI, Src0.getReg()))
7087 legalizeOpWithMove(MI, Src0Idx);
7088
7089 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
7090 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
7091 // src0/src1 with V_READFIRSTLANE.
7092 if (Opc == AMDGPU::V_WRITELANE_B32) {
7093 const DebugLoc &DL = MI.getDebugLoc();
7094 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
7095 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7096 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7097 .add(Src0);
7098 Src0.ChangeToRegister(Reg, false);
7099 }
7100 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
7101 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7102 const DebugLoc &DL = MI.getDebugLoc();
7103 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7104 .add(Src1);
7105 Src1.ChangeToRegister(Reg, false);
7106 }
7107 return;
7108 }
7109
7110 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
7111 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
7112 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
7113 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
7114 legalizeOpWithMove(MI, Src2Idx);
7115 }
7116
7117 // VOP2 src0 instructions support all operand types, so we don't need to check
7118 // their legality. If src1 is already legal, we don't need to do anything.
7119 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
7120 return;
7121
7122 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
7123 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
7124 // select is uniform.
7125 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
7126 RI.isVGPR(MRI, Src1.getReg())) {
7127 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7128 const DebugLoc &DL = MI.getDebugLoc();
7129 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7130 .add(Src1);
7131 Src1.ChangeToRegister(Reg, false);
7132 return;
7133 }
7134
7135 // We do not use commuteInstruction here because it is too aggressive and will
7136 // commute if it is possible. We only want to commute here if it improves
7137 // legality. This can be called a fairly large number of times so don't waste
7138 // compile time pointlessly swapping and checking legality again.
7139 if (HasImplicitSGPR || !MI.isCommutable()) {
7140 legalizeOpWithMove(MI, Src1Idx);
7141 return;
7142 }
7143
7144 // If src0 can be used as src1, commuting will make the operands legal.
7145 // Otherwise we have to give up and insert a move.
7146 //
7147 // TODO: Other immediate-like operand kinds could be commuted if there was a
7148 // MachineOperand::ChangeTo* for them.
7149 if ((!Src1.isImm() && !Src1.isReg()) ||
7150 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
7151 legalizeOpWithMove(MI, Src1Idx);
7152 return;
7153 }
7154
7155 int CommutedOpc = commuteOpcode(MI);
7156 if (CommutedOpc == -1) {
7157 legalizeOpWithMove(MI, Src1Idx);
7158 return;
7159 }
7160
7161 MI.setDesc(get(CommutedOpc));
7162
7163 Register Src0Reg = Src0.getReg();
7164 unsigned Src0SubReg = Src0.getSubReg();
7165 bool Src0Kill = Src0.isKill();
7166
7167 if (Src1.isImm())
7168 Src0.ChangeToImmediate(Src1.getImm());
7169 else if (Src1.isReg()) {
7170 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
7171 Src0.setSubReg(Src1.getSubReg());
7172 } else
7173 llvm_unreachable("Should only have register or immediate operands");
7174
7175 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
7176 Src1.setSubReg(Src0SubReg);
7178}
7179
7180// Legalize VOP3 operands. All operand types are supported for any operand
7181// but only one literal constant and only starting from GFX10.
7183 MachineInstr &MI) const {
7184 unsigned Opc = MI.getOpcode();
7185
7186 int VOP3Idx[3] = {
7187 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
7188 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
7189 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
7190 };
7191
7192 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7193 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7194 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7195 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7196 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7197 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7198 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7199 // src1 and src2 must be scalar
7200 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
7201 const DebugLoc &DL = MI.getDebugLoc();
7202 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
7203 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7204 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7205 .add(Src1);
7206 Src1.ChangeToRegister(Reg, false);
7207 }
7208 if (VOP3Idx[2] != -1) {
7209 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
7210 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
7211 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7212 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7213 .add(Src2);
7214 Src2.ChangeToRegister(Reg, false);
7215 }
7216 }
7217 }
7218
7219 // Find the one SGPR operand we are allowed to use.
7220 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
7221 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7222 SmallDenseSet<unsigned> SGPRsUsed;
7223 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
7224 if (SGPRReg) {
7225 SGPRsUsed.insert(SGPRReg);
7226 --ConstantBusLimit;
7227 }
7228
7229 for (int Idx : VOP3Idx) {
7230 if (Idx == -1)
7231 break;
7232 MachineOperand &MO = MI.getOperand(Idx);
7233
7234 if (!MO.isReg()) {
7235 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
7236 continue;
7237
7238 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7239 --LiteralLimit;
7240 --ConstantBusLimit;
7241 continue;
7242 }
7243
7244 --LiteralLimit;
7245 --ConstantBusLimit;
7246 legalizeOpWithMove(MI, Idx);
7247 continue;
7248 }
7249
7250 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
7251 continue; // VGPRs are legal
7252
7253 // We can use one SGPR in each VOP3 instruction prior to GFX10
7254 // and two starting from GFX10.
7255 if (SGPRsUsed.count(MO.getReg()))
7256 continue;
7257 if (ConstantBusLimit > 0) {
7258 SGPRsUsed.insert(MO.getReg());
7259 --ConstantBusLimit;
7260 continue;
7261 }
7262
7263 // If we make it this far, then the operand is not legal and we must
7264 // legalize it.
7265 legalizeOpWithMove(MI, Idx);
7266 }
7267
7268 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
7269 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
7270 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
7271 Opc == AMDGPU::V_FMAC_F16_t16_e64) &&
7272 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
7273 legalizeOpWithMove(MI, VOP3Idx[2]);
7274
7275 // Fix the register class of single-sgpr-read instructions on gfx12+. See
7276 // SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
7278 for (unsigned I = 0; I < 3; ++I) {
7279 if (!isLegalSingleSGPRReadInstOperand(MRI, MI, /*SrcN=*/I))
7280 legalizeOpWithMove(MI, VOP3Idx[I]);
7281 }
7282 }
7283}
7284
7287 const TargetRegisterClass *DstRC /*=nullptr*/) const {
7288 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
7289 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
7290 if (DstRC)
7291 SRC = RI.getCommonSubClass(SRC, DstRC);
7292
7293 Register DstReg = MRI.createVirtualRegister(SRC);
7294 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7295
7296 if (RI.hasAGPRs(VRC)) {
7297 VRC = RI.getEquivalentVGPRClass(VRC);
7298 Register NewSrcReg = MRI.createVirtualRegister(VRC);
7299 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7300 get(TargetOpcode::COPY), NewSrcReg)
7301 .addReg(SrcReg);
7302 SrcReg = NewSrcReg;
7303 }
7304
7305 if (SubRegs == 1) {
7306 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7307 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7308 .addReg(SrcReg);
7309 return DstReg;
7310 }
7311
7313 for (unsigned i = 0; i < SubRegs; ++i) {
7314 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7315 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7316 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7317 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7318 SRegs.push_back(SGPR);
7319 }
7320
7322 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7323 get(AMDGPU::REG_SEQUENCE), DstReg);
7324 for (unsigned i = 0; i < SubRegs; ++i) {
7325 MIB.addReg(SRegs[i]);
7326 MIB.addImm(RI.getSubRegFromChannel(i));
7327 }
7328 return DstReg;
7329}
7330
7332 MachineInstr &MI) const {
7333
7334 // If the pointer is store in VGPRs, then we need to move them to
7335 // SGPRs using v_readfirstlane. This is safe because we only select
7336 // loads with uniform pointers to SMRD instruction so we know the
7337 // pointer value is uniform.
7338 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
7339 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
7340 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
7341 SBase->setReg(SGPR);
7342 }
7343 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
7344 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
7345 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
7346 SOff->setReg(SGPR);
7347 }
7348}
7349
7351 unsigned Opc = Inst.getOpcode();
7352 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
7353 if (OldSAddrIdx < 0)
7354 return false;
7355
7356 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
7357
7358 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
7359 if (NewOpc < 0)
7361 if (NewOpc < 0)
7362 return false;
7363
7365 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
7366 if (RI.isSGPRReg(MRI, SAddr.getReg()))
7367 return false;
7368
7369 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7370 if (NewVAddrIdx < 0)
7371 return false;
7372
7373 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
7374
7375 // Check vaddr, it shall be zero or absent.
7376 MachineInstr *VAddrDef = nullptr;
7377 if (OldVAddrIdx >= 0) {
7378 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
7379 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
7380 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
7381 !VAddrDef->getOperand(1).isImm() ||
7382 VAddrDef->getOperand(1).getImm() != 0)
7383 return false;
7384 }
7385
7386 const MCInstrDesc &NewDesc = get(NewOpc);
7387 Inst.setDesc(NewDesc);
7388
7389 // Callers expect iterator to be valid after this call, so modify the
7390 // instruction in place.
7391 if (OldVAddrIdx == NewVAddrIdx) {
7392 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
7393 // Clear use list from the old vaddr holding a zero register.
7394 MRI.removeRegOperandFromUseList(&NewVAddr);
7395 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7396 Inst.removeOperand(OldSAddrIdx);
7397 // Update the use list with the pointer we have just moved from vaddr to
7398 // saddr position. Otherwise new vaddr will be missing from the use list.
7399 MRI.removeRegOperandFromUseList(&NewVAddr);
7400 MRI.addRegOperandToUseList(&NewVAddr);
7401 } else {
7402 assert(OldSAddrIdx == NewVAddrIdx);
7403
7404 if (OldVAddrIdx >= 0) {
7405 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7406 AMDGPU::OpName::vdst_in);
7407
7408 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
7409 // it asserts. Untie the operands for now and retie them afterwards.
7410 if (NewVDstIn != -1) {
7411 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
7412 Inst.untieRegOperand(OldVDstIn);
7413 }
7414
7415 Inst.removeOperand(OldVAddrIdx);
7416
7417 if (NewVDstIn != -1) {
7418 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7419 Inst.tieOperands(NewVDst, NewVDstIn);
7420 }
7421 }
7422 }
7423
7424 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
7425 VAddrDef->eraseFromParent();
7426
7427 return true;
7428}
7429
7430// FIXME: Remove this when SelectionDAG is obsoleted.
7432 MachineInstr &MI) const {
7433 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
7434 return;
7435
7436 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
7437 // thinks they are uniform, so a readfirstlane should be valid.
7438 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
7439 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
7440 return;
7441
7443 return;
7444
7445 const TargetRegisterClass *DeclaredRC =
7446 getRegClass(MI.getDesc(), SAddr->getOperandNo());
7447
7448 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
7449 SAddr->setReg(ToSGPR);
7450}
7451
7454 const TargetRegisterClass *DstRC,
7457 const DebugLoc &DL) const {
7458 Register OpReg = Op.getReg();
7459 unsigned OpSubReg = Op.getSubReg();
7460
7461 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
7462 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7463
7464 // Check if operand is already the correct register class.
7465 if (DstRC == OpRC)
7466 return;
7467
7468 Register DstReg = MRI.createVirtualRegister(DstRC);
7469 auto Copy = BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg)
7470 .addReg(OpReg, {}, OpSubReg);
7471 Op.setReg(DstReg);
7472 Op.setSubReg(AMDGPU::NoSubRegister);
7473
7474 MachineInstr *Def = MRI.getVRegDef(OpReg);
7475 if (!Def)
7476 return;
7477
7478 // Try to eliminate the copy if it is copying an immediate value.
7479 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7480 foldImmediate(*Copy, *Def, OpReg, &MRI);
7481
7482 bool ImpDef = Def->isImplicitDef();
7483 while (!ImpDef && Def && Def->isCopy()) {
7484 if (Def->getOperand(1).getReg().isPhysical())
7485 break;
7486 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7487 ImpDef = Def && Def->isImplicitDef();
7488 }
7489 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7490 !ImpDef)
7491 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7492}
7493
7494// Emit the actual waterfall loop, executing the wrapped instruction for each
7495// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7496// iteration, in the worst case we execute 64 (once per lane).
7499 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7500 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7501 MachineFunction &MF = *LoopBB.getParent();
7503 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7505 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7506
7507 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7508 // available. Otherwise, use the previous pattern of v_cmp_eq,
7509 // s_and_saveexec, and s_xor.
7510 bool UseNewExecInstructions =
7511 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7512
7514 Register CondReg;
7515
7516 Register PhiExec;
7517 Register NewExec;
7518
7519 if (UseNewExecInstructions) {
7520 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7521 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7522 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7523 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7524 .addReg(LMC.ExecReg);
7525
7526 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7527 .addReg(InitExec)
7528 .addMBB(&PredBB)
7529 .addReg(NewExec)
7530 .addMBB(&BodyBB);
7531 }
7532
7533 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7534 // involves a trade-off between register pressure and latency:
7535 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7536 // register pressure because arguments and results of all
7537 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7538 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7539 // increase latency by placing v_readfirstlane instructions
7540 // immediately before v_cmpx instruction that directly depend on it.
7541 ///
7542 // Emitting interleaved v_cmpx and v_readfirstlane requires
7543 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7544 // v_cmpx needs to be treated as terminator until after register allocation
7545 // (spill placement) and instruction reordering.
7546 //
7547 // Current implementation defers v_cmpx and leaves other instruction
7548 // scheduling decisions to later passes, where register pressure is known or
7549 // easier to approximate.
7550 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7551 // v_cmpx instructions are inserted at the end of LoopBB.
7552 // After the first v_cmpx is emitted, I is updated to point to it
7553 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7554 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7555 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7556 unsigned NumSubRegs = RegSize / 32;
7557 Register VScalarOp = ScalarOp->getReg();
7558
7559 const TargetRegisterClass *RFLSrcRC =
7560 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7561
7562 if (NumSubRegs == 1) {
7563 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7564 if (const TargetRegisterClass *Common =
7565 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7566 Common != VScalarOpRC) {
7567 Register VRReg = MRI.createVirtualRegister(Common);
7568 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7569 VScalarOp = VRReg;
7570 }
7571 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7572
7573 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7574 .addReg(VScalarOp);
7575
7576 if (UseNewExecInstructions) {
7577 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7578 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7579 .addReg(CurReg)
7580 .addReg(VScalarOp);
7581 if (I == LoopBB.end())
7582 I = CmpxMI.getInstr()->getIterator();
7583 } else {
7584 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7585
7586 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7587 .addReg(CurReg)
7588 .addReg(VScalarOp);
7589
7590 // Combine the comparison results with AND.
7591 if (!CondReg) { // First.
7592 CondReg = NewCondReg;
7593 } else { // If not the first, we create an AND.
7594 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7595 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7596 .addReg(CondReg)
7597 .addReg(NewCondReg)
7598 .setOperandDead(3);
7599 CondReg = AndReg;
7600 }
7601 }
7602
7603 // Update ScalarOp operand to use the SGPR ScalarOp.
7604 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7605 ScalarOp->setReg(CurReg);
7606 else {
7607 // Insert into the same block of use
7608 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7609 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7610 .addReg(CurReg);
7611 ScalarOp->setReg(PhySGPRs[Idx]);
7612 }
7613 } else {
7614 SmallVector<Register, 8> ReadlanePieces;
7615 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7616 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7617 "Unhandled register size");
7618
7619 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7620 Register CurRegLo =
7621 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7622 Register CurRegHi =
7623 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7624
7625 // Read the next variant <- also loop target.
7626 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7627 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7628
7629 // Read the next variant <- also loop target.
7630 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7631 .addReg(VScalarOp, VScalarOpUndef,
7632 TRI->getSubRegFromChannel(Idx + 1));
7633
7634 ReadlanePieces.push_back(CurRegLo);
7635 ReadlanePieces.push_back(CurRegHi);
7636
7637 // Comparison is to be done as 64-bit.
7638 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7639 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7640 .addReg(CurRegLo)
7641 .addImm(AMDGPU::sub0)
7642 .addReg(CurRegHi)
7643 .addImm(AMDGPU::sub1);
7644
7645 unsigned SubReg =
7646 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7647
7648 if (UseNewExecInstructions) {
7649 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7650 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7651 .addReg(CurReg)
7652 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7653 if (I == LoopBB.end())
7654 I = CmpxMI.getInstr()->getIterator();
7655 } else {
7656 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7657 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7658 .addReg(CurReg)
7659 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7660
7661 // Combine the comparison results with AND.
7662 if (!CondReg) { // First.
7663 CondReg = NewCondReg;
7664 } else { // If not the first, we create an AND.
7665 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7666 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7667 .addReg(CondReg)
7668 .addReg(NewCondReg)
7669 .setOperandDead(3);
7670 CondReg = AndReg;
7671 }
7672 }
7673 } // End for loop.
7674
7675 const auto *SScalarOpRC =
7676 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7677 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7678
7679 // Build scalar ScalarOp.
7680 auto Merge =
7681 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7682 unsigned Channel = 0;
7683 for (Register Piece : ReadlanePieces) {
7684 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7685 }
7686
7687 // Update ScalarOp operand to use the SGPR ScalarOp.
7688 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7689 ScalarOp->setReg(SScalarOp);
7690 else {
7691 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7692 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7693 .addReg(SScalarOp);
7694 ScalarOp->setReg(PhySGPRs[Idx]);
7695 }
7696 }
7697 }
7698
7699 // AndSaveExecOpc modifies EXEC but can't be isTerminator=1: terminators
7700 // that define virtual registers aren't supported.
7701 Register SaveExec;
7702 if (!UseNewExecInstructions) {
7703 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7704 MRI.setSimpleHint(SaveExec, CondReg);
7705
7706 // Update EXEC to matching lanes, saving original to SaveExec.
7707 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7708 .addReg(CondReg)
7709 .setOperandDead(3);
7710 }
7711
7712 // The original instruction is here; we insert the terminators after it.
7713 I = BodyBB.end();
7714
7715 if (UseNewExecInstructions) {
7716 // Compute the remaining lanes into a plain virtual register and write EXEC
7717 // from a terminator, so spill code for NewExec is placed before EXEC
7718 // changes. SIOptimizeExecMasking opportunistically folds the pair back
7719 // into S_ANDN2_WREXEC after register allocation.
7720 MRI.setSimpleHint(NewExec, PhiExec);
7721 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2Opc), NewExec)
7722 .addReg(PhiExec)
7723 .addReg(LMC.ExecReg)
7724 .setOperandDead(3);
7725 BuildMI(BodyBB, I, DL, TII.get(LMC.MovTermOpc), LMC.ExecReg)
7726 .addReg(NewExec);
7727 } else {
7728 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7729 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7730 .addReg(LMC.ExecReg)
7731 .addReg(SaveExec)
7732 .setOperandDead(3);
7733 }
7734
7735 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7736}
7737
7738// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7739// with SGPRs by iterating over all unique values across all lanes.
7740// Returns the loop basic block that now contains \p MI.
7741static MachineBasicBlock *
7745 MachineBasicBlock::iterator Begin = nullptr,
7747 ArrayRef<Register> PhySGPRs = {}) {
7748 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7749 "Physical SGPRs must be empty or match the number of scalar operands");
7751 MachineFunction &MF = *MBB.getParent();
7753 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7755 if (!Begin.isValid())
7756 Begin = &MI;
7757 if (!End.isValid()) {
7758 End = &MI;
7759 ++End;
7760 }
7761 const DebugLoc &DL = MI.getDebugLoc();
7763 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7764
7765 // Save SCC. Waterfall Loop may overwrite SCC.
7766 Register SaveSCCReg;
7767
7768 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7769 // rather than unlimited scan everywhere
7770 bool SCCNotDead =
7771 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7772 std::numeric_limits<unsigned>::max()) !=
7774 if (SCCNotDead) {
7775 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7776 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7777 .addImm(1)
7778 .addImm(0);
7779 }
7780
7781 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7782
7783 // Save the EXEC mask
7784 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7785
7786 // Killed uses in the instruction we are waterfalling around will be
7787 // incorrect due to the added control-flow.
7789 ++AfterMI;
7790 for (auto I = Begin; I != AfterMI; I++) {
7791 for (auto &MO : I->all_uses())
7792 MRI.clearKillFlags(MO.getReg());
7793 }
7794
7795 // To insert the loop we need to split the block. Move everything after this
7796 // point to a new block, and insert a new empty block between the two.
7799 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7801 ++MBBI;
7802
7803 MF.insert(MBBI, LoopBB);
7804 MF.insert(MBBI, BodyBB);
7805 MF.insert(MBBI, RemainderBB);
7806
7807 LoopBB->addSuccessor(BodyBB);
7808 BodyBB->addSuccessor(LoopBB);
7809 BodyBB->addSuccessor(RemainderBB);
7810
7811 // Move Begin to MI to the BodyBB, and the remainder of the block to
7812 // RemainderBB.
7813 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7814 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7815 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7816
7817 MBB.addSuccessor(LoopBB);
7818
7819 // Update dominators. We know that MBB immediately dominates LoopBB, that
7820 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7821 // RemainderBB. RemainderBB immediately dominates all of the successors
7822 // transferred to it from MBB that MBB used to properly dominate.
7823 if (MDT) {
7824 MDT->addNewBlock(LoopBB, &MBB);
7825 MDT->addNewBlock(BodyBB, LoopBB);
7826 MDT->addNewBlock(RemainderBB, BodyBB);
7827 for (auto &Succ : RemainderBB->successors()) {
7828 if (MDT->properlyDominates(&MBB, Succ)) {
7829 MDT->changeImmediateDominator(Succ, RemainderBB);
7830 }
7831 }
7832 }
7833
7834 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7835 PhySGPRs);
7836
7837 MachineBasicBlock::iterator First = RemainderBB->begin();
7838 // Restore SCC
7839 if (SCCNotDead) {
7840 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7841 .addReg(SaveSCCReg)
7842 .addImm(0);
7843 }
7844
7845 // Restore the EXEC mask
7846 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7847 .addReg(SaveExec);
7848 return BodyBB;
7849}
7850
7851// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7852static std::tuple<unsigned, unsigned>
7854 MachineBasicBlock &MBB = *MI.getParent();
7855 MachineFunction &MF = *MBB.getParent();
7857
7858 // Extract the ptr from the resource descriptor.
7859 unsigned RsrcPtr =
7860 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7861 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7862
7863 // Create an empty resource descriptor
7864 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7865 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7866 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7867 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7868 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7869
7870 // Zero64 = 0
7871 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7872 .addImm(0);
7873
7874 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7875 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7876 .addImm(Lo_32(RsrcDataFormat));
7877
7878 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7879 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7880 .addImm(Hi_32(RsrcDataFormat));
7881
7882 // NewSRsrc = {Zero64, SRsrcFormat}
7883 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7884 .addReg(Zero64)
7885 .addImm(AMDGPU::sub0_sub1)
7886 .addReg(SRsrcFormatLo)
7887 .addImm(AMDGPU::sub2)
7888 .addReg(SRsrcFormatHi)
7889 .addImm(AMDGPU::sub3);
7890
7891 return std::tuple(RsrcPtr, NewSRsrc);
7892}
7893
7896 MachineDominatorTree *MDT) const {
7897 MachineFunction &MF = *MI.getMF();
7899 MachineBasicBlock *CreatedBB = nullptr;
7900
7901 // Legalize True16
7902 if (ST.useRealTrue16Insts())
7904
7905 // Legalize VOP2
7906 if (isVOP2(MI) || isVOPC(MI)) {
7908 return CreatedBB;
7909 }
7910
7911 // Legalize VOP3
7912 if (isVOP3(MI)) {
7914 return CreatedBB;
7915 }
7916
7917 // Legalize SMRD
7918 if (isSMRD(MI)) {
7920 return CreatedBB;
7921 }
7922
7923 // Legalize FLAT
7924 if (isFLAT(MI)) {
7926 return CreatedBB;
7927 }
7928
7929 // Legalize PHI
7930 // The register class of the operands must be the same type as the register
7931 // class of the output.
7932 if (MI.getOpcode() == AMDGPU::PHI) {
7933 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7934 assert(!RI.isSGPRClass(VRC));
7935
7936 // Update all the operands so they have the same type.
7937 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7938 MachineOperand &Op = MI.getOperand(I);
7939 if (!Op.isReg() || !Op.getReg().isVirtual())
7940 continue;
7941
7942 // MI is a PHI instruction.
7943 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7945
7946 // Avoid creating no-op copies with the same src and dst reg class. These
7947 // confuse some of the machine passes.
7948 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7949 }
7950 }
7951
7952 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7953 // VGPR dest type and SGPR sources, insert copies so all operands are
7954 // VGPRs. This seems to help operand folding / the register coalescer.
7955 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7956 MachineBasicBlock *MBB = MI.getParent();
7957 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7958 if (RI.hasVGPRs(DstRC)) {
7959 // Update all the operands so they are VGPR register classes. These may
7960 // not be the same register class because REG_SEQUENCE supports mixing
7961 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7962 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7963 MachineOperand &Op = MI.getOperand(I);
7964 if (!Op.isReg() || !Op.getReg().isVirtual())
7965 continue;
7966
7967 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7968 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7969 if (VRC == OpRC)
7970 continue;
7971
7972 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7973 }
7974 }
7975
7976 return CreatedBB;
7977 }
7978
7979 // Legalize INSERT_SUBREG
7980 // src0 must have the same register class as dst
7981 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7982 Register Dst = MI.getOperand(0).getReg();
7983 Register Src0 = MI.getOperand(1).getReg();
7984 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7985 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7986 if (DstRC != Src0RC) {
7987 MachineBasicBlock *MBB = MI.getParent();
7988 MachineOperand &Op = MI.getOperand(1);
7989 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7990 }
7991 return CreatedBB;
7992 }
7993
7994 // Legalize SI_INIT_M0
7995 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7996 MachineOperand &Src = MI.getOperand(0);
7997 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7998 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7999 return CreatedBB;
8000 }
8001
8002 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
8003 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
8004 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
8005 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
8006 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
8007 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
8008 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
8009 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
8010 MachineOperand &Src = MI.getOperand(1);
8011 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
8012 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
8013 return CreatedBB;
8014 }
8015
8016 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
8017 //
8018 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
8019 // scratch memory access. In both cases, the legalization never involves
8020 // conversion to the addr64 form.
8022 (isMUBUF(MI) || isMTBUF(MI)))) {
8023 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
8024 ? AMDGPU::OpName::rsrc
8025 : AMDGPU::OpName::srsrc;
8026 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
8027 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
8028 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
8029
8030 AMDGPU::OpName SampOpName =
8031 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
8032 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
8033 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
8034 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
8035
8036 return CreatedBB;
8037 }
8038
8039 // Legalize SI_CALL
8040 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
8041 MachineOperand *Dest = &MI.getOperand(0);
8042 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
8043 createWaterFallForSiCall(&MI, MDT, {Dest});
8044 }
8045 }
8046
8047 // Legalize s_sleep_var.
8048 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
8049 const DebugLoc &DL = MI.getDebugLoc();
8050 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8051 int Src0Idx =
8052 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
8053 MachineOperand &Src0 = MI.getOperand(Src0Idx);
8054 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
8055 .add(Src0);
8056 Src0.ChangeToRegister(Reg, false);
8057 return nullptr;
8058 }
8059
8060 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
8061 // operands are scalar.
8062 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
8063 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
8064 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
8065 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
8066 for (MachineOperand &Src : MI.explicit_operands()) {
8067 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
8068 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
8069 }
8070 return CreatedBB;
8071 }
8072
8073 // Legalize MUBUF instructions.
8074 bool isSoffsetLegal = true;
8075 int SoffsetIdx =
8076 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
8077 if (SoffsetIdx != -1) {
8078 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
8079 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
8080 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
8081 isSoffsetLegal = false;
8082 }
8083 }
8084
8085 bool isRsrcLegal = true;
8086 int RsrcIdx =
8087 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
8088 if (RsrcIdx != -1) {
8089 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
8090 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
8091 isRsrcLegal = false;
8092 }
8093
8094 // The operands are legal.
8095 if (isRsrcLegal && isSoffsetLegal)
8096 return CreatedBB;
8097
8098 if (!isRsrcLegal) {
8099 // Legalize a VGPR Rsrc
8100 //
8101 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
8102 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
8103 // a zero-value SRsrc.
8104 //
8105 // If the instruction is _OFFSET (both idxen and offen disabled), and we
8106 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
8107 // above.
8108 //
8109 // Otherwise we are on non-ADDR64 hardware, and/or we have
8110 // idxen/offen/bothen and we fall back to a waterfall loop.
8111
8112 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
8113 MachineBasicBlock &MBB = *MI.getParent();
8114
8115 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
8116 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
8117 // This is already an ADDR64 instruction so we need to add the pointer
8118 // extracted from the resource descriptor to the current value of VAddr.
8119 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8120 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8121 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8122
8123 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
8124 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
8125 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
8126
8127 unsigned RsrcPtr, NewSRsrc;
8128 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
8129
8130 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
8131 const DebugLoc &DL = MI.getDebugLoc();
8132 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
8133 .addDef(CondReg0)
8134 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8135 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
8136 .addImm(0);
8137
8138 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
8139 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
8140 .addDef(CondReg1, RegState::Dead)
8141 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8142 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
8143 .addReg(CondReg0)
8144 .addImm(0);
8145
8146 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8147 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
8148 .addReg(NewVAddrLo)
8149 .addImm(AMDGPU::sub0)
8150 .addReg(NewVAddrHi)
8151 .addImm(AMDGPU::sub1);
8152
8153 VAddr->setReg(NewVAddr);
8154 Rsrc->setReg(NewSRsrc);
8155 } else if (!VAddr && ST.hasAddr64()) {
8156 // This instructions is the _OFFSET variant, so we need to convert it to
8157 // ADDR64.
8158 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
8159 "FIXME: Need to emit flat atomics here");
8160
8161 unsigned RsrcPtr, NewSRsrc;
8162 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
8163
8164 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8165 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
8166 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
8167 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8168 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
8169
8170 // Atomics with return have an additional tied operand and are
8171 // missing some of the special bits.
8172 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
8173 MachineInstr *Addr64;
8174
8175 if (!VDataIn) {
8176 // Regular buffer load / store.
8178 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
8179 .add(*VData)
8180 .addReg(NewVAddr)
8181 .addReg(NewSRsrc)
8182 .add(*SOffset)
8183 .add(*Offset);
8184
8185 if (const MachineOperand *CPol =
8186 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
8187 MIB.addImm(CPol->getImm());
8188 }
8189
8190 if (const MachineOperand *TFE =
8191 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
8192 MIB.addImm(TFE->getImm());
8193 }
8194
8195 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
8196
8197 MIB.cloneMemRefs(MI);
8198 Addr64 = MIB;
8199 } else {
8200 // Atomics with return.
8201 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
8202 .add(*VData)
8203 .add(*VDataIn)
8204 .addReg(NewVAddr)
8205 .addReg(NewSRsrc)
8206 .add(*SOffset)
8207 .add(*Offset)
8208 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
8209 .cloneMemRefs(MI);
8210 }
8211
8212 MI.removeFromParent();
8213
8214 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8215 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
8216 NewVAddr)
8217 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8218 .addImm(AMDGPU::sub0)
8219 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8220 .addImm(AMDGPU::sub1);
8221 } else {
8222 // Legalize a VGPR Rsrc and soffset together.
8223 if (!isSoffsetLegal) {
8224 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8225 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
8226 return CreatedBB;
8227 }
8228 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
8229 return CreatedBB;
8230 }
8231 }
8232
8233 // Legalize a VGPR soffset.
8234 if (!isSoffsetLegal) {
8235 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8236 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
8237 return CreatedBB;
8238 }
8239 return CreatedBB;
8240}
8241
8243 if (InSet.insert(MI).second)
8244 InstrList.push_back(MI);
8245 // Add MBUF instructiosn to deferred list.
8246 int RsrcIdx =
8247 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
8248 if (RsrcIdx != -1) {
8249 DeferredList.insert(MI);
8250 }
8251}
8252
8254 return DeferredList.contains(MI);
8255}
8256
8257// Legalize size mismatches between 16bit and 32bit registers in v2s copy
8258// lowering (change sgpr to vgpr).
8259// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
8260// size. Need to legalize the size of the operands during the vgpr lowering
8261// chain. This can be removed after we have sgpr16 in place
8263 MachineRegisterInfo &MRI) const {
8264 if (!ST.useRealTrue16Insts())
8265 return;
8266
8267 unsigned Opcode = MI.getOpcode();
8268 MachineBasicBlock *MBB = MI.getParent();
8269 // Legalize operands and check for size mismatch
8270 if (OpIdx >= MI.getNumExplicitOperands() ||
8271 OpIdx >= get(Opcode).getNumOperands() ||
8272 get(Opcode).operands()[OpIdx].RegClass == -1)
8273 return;
8274
8275 MachineOperand &Op = MI.getOperand(OpIdx);
8276 if (!Op.isReg() || !Op.getReg().isVirtual() || Op.isDef())
8277 return;
8278
8279 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
8280 if (!RI.isVGPRClass(CurrRC))
8281 return;
8282
8283 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
8284 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
8285 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8286 // Default to the lo16 only if the subregister is not specified.
8287 if (Op.getSubReg() == AMDGPU::NoSubRegister)
8288 Op.setSubReg(AMDGPU::lo16);
8289 return;
8290 }
8291
8292 const TargetRegisterClass *CurrSRC =
8293 RI.getSubRegisterClass(CurrRC, Op.getSubReg());
8294 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8295 const DebugLoc &DL = MI.getDebugLoc();
8296 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8297 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8298 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
8299 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
8300 .addReg(Op.getReg(), {}, Op.getSubReg())
8301 .addImm(AMDGPU::lo16)
8302 .addReg(Undef)
8303 .addImm(AMDGPU::hi16);
8304 Op.setReg(NewDstReg);
8305 Op.setSubReg(AMDGPU::NoSubRegister);
8306 }
8307}
8309 MachineRegisterInfo &MRI) const {
8310 for (unsigned OpIdx = 0; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
8312}
8313
8317 ArrayRef<Register> PhySGPRs) const {
8318 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8319 "This only handle waterfall for SI_CALL_ISEL");
8320 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
8321 // following copies, we also need to move copies from and to physical
8322 // registers into the loop block.
8323 // Also move the copies to physical registers into the loop block
8324 MachineBasicBlock &MBB = *MI->getParent();
8326 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8327 --Start;
8329 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8330 ++End;
8331
8332 // Also include following copies of the return value
8333 ++End;
8334 while (End != MBB.end() && End->isCopy() &&
8335 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8336 ++End;
8337
8338 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
8339}
8340
8342 MachineDominatorTree *MDT) const {
8344 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
8345 while (!Worklist.empty()) {
8346 MachineInstr &Inst = *Worklist.top();
8347 Worklist.erase_top();
8348 // Skip MachineInstr in the deferred list.
8349 if (Worklist.isDeferred(&Inst))
8350 continue;
8351 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8352 }
8353
8354 // Deferred list of instructions will be processed once
8355 // all the MachineInstr in the worklist are done.
8356 for (MachineInstr *Inst : Worklist.getDeferredList()) {
8357 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8358 assert(Worklist.empty() &&
8359 "Deferred MachineInstr are not supposed to re-populate worklist");
8360 }
8361
8362 for (auto &Entry : WaterFalls) {
8363 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8364 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
8365 Entry.second.SGPRs);
8366 }
8367
8368 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8369 if (Entry.second)
8370 Entry.first->eraseFromParent();
8371}
8373 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
8374 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
8375 // hope for the best.
8376 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
8377 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
8378 if (SubRegIndices.size() <= 1) {
8379 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8380 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8381 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8382 .add(Inst.getOperand(1));
8383 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
8384 DstReg)
8385 .addReg(NewDst);
8386 } else {
8388 for (int16_t Indice : SubRegIndices) {
8389 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8390 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8391 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8392 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
8393
8394 DstRegs.push_back(NewDst);
8395 }
8397 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8398 get(AMDGPU::REG_SEQUENCE), DstReg);
8399 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
8400 MIB.addReg(DstRegs[i]);
8401 MIB.addImm(RI.getSubRegFromChannel(i));
8402 }
8403 }
8404}
8405
8407 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
8410 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8411 if (DstReg == AMDGPU::M0) {
8413 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8414 return;
8415 }
8416 Register SrcReg = Inst.getOperand(1).getReg();
8419 // Only search current block since phyreg's def & use cannot cross
8420 // blocks when MF.NoPhi = false.
8421 while (++I != E) {
8422 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
8423 // and record the operand for later waterfall loop generation.
8424 if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8425 MachineInstr *UseMI = &*I;
8426 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
8427 if (UseMI->getOperand(i).isReg() &&
8428 UseMI->getOperand(i).getReg() == DstReg) {
8429 MachineOperand *MO = &UseMI->getOperand(i);
8430 MO->setReg(SrcReg);
8431 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
8432 V2SCopyInfo.MOs.push_back(MO);
8433 V2SCopyInfo.SGPRs.push_back(DstReg);
8434 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8435 }
8436 }
8437 } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8438 I->getOperand(0).isReg() &&
8439 I->getOperand(0).getReg() == DstReg) {
8441 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8442 } else if (I->readsRegister(DstReg, &RI)) {
8443 // COPY cannot be erased if other type of inst uses it.
8444 V2SPhyCopiesToErase[&Inst] = false;
8445 }
8446 if (I->findRegisterDefOperand(DstReg, &RI))
8447 break;
8448 }
8449}
8450
8452 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
8454 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8455
8457 if (!MBB)
8458 return;
8459 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
8460 unsigned Opcode = Inst.getOpcode();
8461 unsigned NewOpcode = getVALUOp(Inst);
8462 const DebugLoc &DL = Inst.getDebugLoc();
8463
8464 // Handle some special cases
8465 switch (Opcode) {
8466 default:
8467 break;
8468 case AMDGPU::S_ADD_I32:
8469 case AMDGPU::S_SUB_I32: {
8470 // FIXME: The u32 versions currently selected use the carry.
8471 bool Changed;
8472 MachineBasicBlock *CreatedBBTmp = nullptr;
8473 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8474 if (Changed)
8475 return;
8476
8477 // Default handling
8478 break;
8479 }
8480
8481 case AMDGPU::S_MUL_U64:
8482 if (ST.useVMulU64Inst()) {
8483 NewOpcode = AMDGPU::V_MUL_U64_e64;
8484 break;
8485 }
8486 // Split s_mul_u64 in 32-bit vector multiplications.
8487 splitScalarSMulU64(Worklist, Inst, MDT);
8488 Inst.eraseFromParent();
8489 return;
8490
8491 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8492 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8493 // This is a special case of s_mul_u64 where all the operands are either
8494 // zero extended or sign extended.
8495 splitScalarSMulPseudo(Worklist, Inst, MDT);
8496 Inst.eraseFromParent();
8497 return;
8498
8499 case AMDGPU::S_AND_B64:
8500 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8501 Inst.eraseFromParent();
8502 return;
8503
8504 case AMDGPU::S_OR_B64:
8505 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8506 Inst.eraseFromParent();
8507 return;
8508
8509 case AMDGPU::S_XOR_B64:
8510 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8511 Inst.eraseFromParent();
8512 return;
8513
8514 case AMDGPU::S_NAND_B64:
8515 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8516 Inst.eraseFromParent();
8517 return;
8518
8519 case AMDGPU::S_NOR_B64:
8520 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8521 Inst.eraseFromParent();
8522 return;
8523
8524 case AMDGPU::S_XNOR_B64:
8525 if (ST.hasDLInsts())
8526 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8527 else
8528 splitScalar64BitXnor(Worklist, Inst, MDT);
8529 Inst.eraseFromParent();
8530 return;
8531
8532 case AMDGPU::S_ANDN2_B64:
8533 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8534 Inst.eraseFromParent();
8535 return;
8536
8537 case AMDGPU::S_ORN2_B64:
8538 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8539 Inst.eraseFromParent();
8540 return;
8541
8542 case AMDGPU::S_BREV_B64:
8543 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8544 Inst.eraseFromParent();
8545 return;
8546
8547 case AMDGPU::S_NOT_B64:
8548 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8549 Inst.eraseFromParent();
8550 return;
8551
8552 case AMDGPU::S_BCNT1_I32_B64:
8553 splitScalar64BitBCNT(Worklist, Inst);
8554 Inst.eraseFromParent();
8555 return;
8556
8557 case AMDGPU::S_BFE_I64:
8558 splitScalar64BitBFE(Worklist, Inst);
8559 Inst.eraseFromParent();
8560 return;
8561
8562 case AMDGPU::S_FLBIT_I32_B64:
8563 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8564 Inst.eraseFromParent();
8565 return;
8566 case AMDGPU::S_FF1_I32_B64:
8567 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8568 Inst.eraseFromParent();
8569 return;
8570
8571 case AMDGPU::S_LSHL_B32:
8572 if (ST.hasOnlyRevVALUShifts()) {
8573 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8574 swapOperands(Inst);
8575 }
8576 break;
8577 case AMDGPU::S_ASHR_I32:
8578 if (ST.hasOnlyRevVALUShifts()) {
8579 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8580 swapOperands(Inst);
8581 }
8582 break;
8583 case AMDGPU::S_LSHR_B32:
8584 if (ST.hasOnlyRevVALUShifts()) {
8585 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8586 swapOperands(Inst);
8587 }
8588 break;
8589 case AMDGPU::S_LSHL_B64:
8590 if (ST.hasOnlyRevVALUShifts()) {
8591 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8592 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8593 : AMDGPU::V_LSHLREV_B64_e64;
8594 swapOperands(Inst);
8595 }
8596 break;
8597 case AMDGPU::S_ASHR_I64:
8598 if (ST.hasOnlyRevVALUShifts()) {
8599 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8600 swapOperands(Inst);
8601 }
8602 break;
8603 case AMDGPU::S_LSHR_B64:
8604 if (ST.hasOnlyRevVALUShifts()) {
8605 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8606 swapOperands(Inst);
8607 }
8608 break;
8609
8610 case AMDGPU::S_ABS_I32:
8611 lowerScalarAbs(Worklist, Inst);
8612 Inst.eraseFromParent();
8613 return;
8614
8615 case AMDGPU::S_ABSDIFF_I32:
8616 lowerScalarAbsDiff(Worklist, Inst);
8617 Inst.eraseFromParent();
8618 return;
8619
8620 case AMDGPU::S_CBRANCH_SCC0:
8621 case AMDGPU::S_CBRANCH_SCC1: {
8622 // Clear unused bits of vcc
8623 Register CondReg = Inst.getOperand(1).getReg();
8624 bool IsSCC = CondReg == AMDGPU::SCC;
8626 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8627 .addReg(LMC.ExecReg)
8628 .addReg(IsSCC ? LMC.VccReg : CondReg)
8629 .setOperandDead(3); // implicit-def $scc
8630 Inst.removeOperand(1);
8631 } break;
8632
8633 case AMDGPU::S_BFE_U64:
8634 case AMDGPU::S_BFM_B64:
8635 llvm_unreachable("Moving this op to VALU not implemented");
8636
8637 case AMDGPU::S_PACK_LL_B32_B16:
8638 case AMDGPU::S_PACK_LH_B32_B16:
8639 case AMDGPU::S_PACK_HL_B32_B16:
8640 case AMDGPU::S_PACK_HH_B32_B16:
8641 movePackToVALU(Worklist, MRI, Inst);
8642 Inst.eraseFromParent();
8643 return;
8644
8645 case AMDGPU::S_XNOR_B32:
8646 lowerScalarXnor(Worklist, Inst);
8647 Inst.eraseFromParent();
8648 return;
8649
8650 case AMDGPU::S_NAND_B32:
8651 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8652 Inst.eraseFromParent();
8653 return;
8654
8655 case AMDGPU::S_NOR_B32:
8656 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8657 Inst.eraseFromParent();
8658 return;
8659
8660 case AMDGPU::S_ANDN2_B32:
8661 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8662 Inst.eraseFromParent();
8663 return;
8664
8665 case AMDGPU::S_ORN2_B32:
8666 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8667 Inst.eraseFromParent();
8668 return;
8669
8670 // TODO: remove as soon as everything is ready
8671 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8672 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8673 // can only be selected from the uniform SDNode.
8674 case AMDGPU::S_ADD_CO_PSEUDO:
8675 case AMDGPU::S_SUB_CO_PSEUDO: {
8676 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8677 ? AMDGPU::V_ADDC_U32_e64
8678 : AMDGPU::V_SUBB_U32_e64;
8679 const auto *CarryRC = RI.getWaveMaskRegClass();
8680
8681 Register CarryInReg = Inst.getOperand(4).getReg();
8682 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8683 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8684 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8685 .addReg(CarryInReg);
8686 }
8687
8688 Register CarryOutReg = Inst.getOperand(1).getReg();
8689
8690 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8691 MRI.getRegClass(Inst.getOperand(0).getReg())));
8692 MachineInstr *CarryOp =
8693 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8694 .addReg(CarryOutReg, RegState::Define)
8695 .add(Inst.getOperand(2))
8696 .add(Inst.getOperand(3))
8697 .addReg(CarryInReg)
8698 .addImm(0);
8699 legalizeOperands(*CarryOp);
8700 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8701 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8702 Inst.eraseFromParent();
8703 }
8704 return;
8705 case AMDGPU::S_UADDO_PSEUDO:
8706 case AMDGPU::S_USUBO_PSEUDO: {
8707 MachineOperand &Dest0 = Inst.getOperand(0);
8708 MachineOperand &Dest1 = Inst.getOperand(1);
8709 MachineOperand &Src0 = Inst.getOperand(2);
8710 MachineOperand &Src1 = Inst.getOperand(3);
8711
8712 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8713 ? AMDGPU::V_ADD_CO_U32_e64
8714 : AMDGPU::V_SUB_CO_U32_e64;
8715 const TargetRegisterClass *NewRC =
8716 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8717 Register DestReg = MRI.createVirtualRegister(NewRC);
8718 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8719 .addReg(Dest1.getReg(), RegState::Define)
8720 .add(Src0)
8721 .add(Src1)
8722 .addImm(0); // clamp bit
8723
8724 legalizeOperands(*NewInstr, MDT);
8725 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8726 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8727 Inst.eraseFromParent();
8728 }
8729 return;
8730 case AMDGPU::S_LSHL1_ADD_U32:
8731 case AMDGPU::S_LSHL2_ADD_U32:
8732 case AMDGPU::S_LSHL3_ADD_U32:
8733 case AMDGPU::S_LSHL4_ADD_U32: {
8734 MachineOperand &Dest = Inst.getOperand(0);
8735 MachineOperand &Src0 = Inst.getOperand(1);
8736 MachineOperand &Src1 = Inst.getOperand(2);
8737 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8738 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8739 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8740 : 4);
8741
8742 const TargetRegisterClass *NewRC =
8743 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8744 Register DestReg = MRI.createVirtualRegister(NewRC);
8745 MachineInstr *NewInstr =
8746 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8747 .add(Src0)
8748 .addImm(ShiftAmt)
8749 .add(Src1);
8750
8751 legalizeOperands(*NewInstr, MDT);
8752 MRI.replaceRegWith(Dest.getReg(), DestReg);
8753 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8754 Inst.eraseFromParent();
8755 }
8756 return;
8757 case AMDGPU::S_CSELECT_B32:
8758 case AMDGPU::S_CSELECT_B64:
8759 lowerSelect(Worklist, Inst, MDT);
8760 Inst.eraseFromParent();
8761 return;
8762 case AMDGPU::S_CMP_EQ_I32:
8763 case AMDGPU::S_CMP_LG_I32:
8764 case AMDGPU::S_CMP_GT_I32:
8765 case AMDGPU::S_CMP_GE_I32:
8766 case AMDGPU::S_CMP_LT_I32:
8767 case AMDGPU::S_CMP_LE_I32:
8768 case AMDGPU::S_CMP_EQ_U32:
8769 case AMDGPU::S_CMP_LG_U32:
8770 case AMDGPU::S_CMP_GT_U32:
8771 case AMDGPU::S_CMP_GE_U32:
8772 case AMDGPU::S_CMP_LT_U32:
8773 case AMDGPU::S_CMP_LE_U32:
8774 case AMDGPU::S_CMP_EQ_U64:
8775 case AMDGPU::S_CMP_LG_U64:
8776 case AMDGPU::S_CMP_LT_F32:
8777 case AMDGPU::S_CMP_EQ_F32:
8778 case AMDGPU::S_CMP_LE_F32:
8779 case AMDGPU::S_CMP_GT_F32:
8780 case AMDGPU::S_CMP_LG_F32:
8781 case AMDGPU::S_CMP_GE_F32:
8782 case AMDGPU::S_CMP_O_F32:
8783 case AMDGPU::S_CMP_U_F32:
8784 case AMDGPU::S_CMP_NGE_F32:
8785 case AMDGPU::S_CMP_NLG_F32:
8786 case AMDGPU::S_CMP_NGT_F32:
8787 case AMDGPU::S_CMP_NLE_F32:
8788 case AMDGPU::S_CMP_NEQ_F32:
8789 case AMDGPU::S_CMP_NLT_F32: {
8790 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8791 auto NewInstr =
8792 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8793 .setMIFlags(Inst.getFlags());
8794 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8795 0) {
8796 NewInstr
8797 .addImm(0) // src0_modifiers
8798 .add(Inst.getOperand(0)) // src0
8799 .addImm(0) // src1_modifiers
8800 .add(Inst.getOperand(1)) // src1
8801 .addImm(0); // clamp
8802 } else {
8803 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8804 }
8805 legalizeOperands(*NewInstr, MDT);
8806 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8807 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8808 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8809 Inst.eraseFromParent();
8810 return;
8811 }
8812 case AMDGPU::S_CMP_LT_F16:
8813 case AMDGPU::S_CMP_EQ_F16:
8814 case AMDGPU::S_CMP_LE_F16:
8815 case AMDGPU::S_CMP_GT_F16:
8816 case AMDGPU::S_CMP_LG_F16:
8817 case AMDGPU::S_CMP_GE_F16:
8818 case AMDGPU::S_CMP_O_F16:
8819 case AMDGPU::S_CMP_U_F16:
8820 case AMDGPU::S_CMP_NGE_F16:
8821 case AMDGPU::S_CMP_NLG_F16:
8822 case AMDGPU::S_CMP_NGT_F16:
8823 case AMDGPU::S_CMP_NLE_F16:
8824 case AMDGPU::S_CMP_NEQ_F16:
8825 case AMDGPU::S_CMP_NLT_F16: {
8826 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8827 auto NewInstr =
8828 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8829 .setMIFlags(Inst.getFlags());
8830 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8831 NewInstr
8832 .addImm(0) // src0_modifiers
8833 .add(Inst.getOperand(0)) // src0
8834 .addImm(0) // src1_modifiers
8835 .add(Inst.getOperand(1)) // src1
8836 .addImm(0); // clamp
8837 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8838 NewInstr.addImm(0); // op_sel0
8839 } else {
8840 NewInstr
8841 .add(Inst.getOperand(0))
8842 .add(Inst.getOperand(1));
8843 }
8844 legalizeOperands(*NewInstr, MDT);
8845 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8846 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8847 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8848 Inst.eraseFromParent();
8849 return;
8850 }
8851 case AMDGPU::S_CVT_HI_F32_F16: {
8852 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8853 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8854 if (ST.useRealTrue16Insts()) {
8855 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8856 .add(Inst.getOperand(1));
8857 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8858 .addImm(0) // src0_modifiers
8859 .addReg(TmpReg, {}, AMDGPU::hi16)
8860 .addImm(0) // clamp
8861 .addImm(0) // omod
8862 .addImm(0); // op_sel0
8863 } else {
8864 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8865 .addImm(16)
8866 .add(Inst.getOperand(1));
8867 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8868 .addImm(0) // src0_modifiers
8869 .addReg(TmpReg)
8870 .addImm(0) // clamp
8871 .addImm(0); // omod
8872 }
8873
8874 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8875 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8876 Inst.eraseFromParent();
8877 return;
8878 }
8879 case AMDGPU::S_MINIMUM_F32:
8880 case AMDGPU::S_MAXIMUM_F32: {
8881 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8882 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8883 .addImm(0) // src0_modifiers
8884 .add(Inst.getOperand(1))
8885 .addImm(0) // src1_modifiers
8886 .add(Inst.getOperand(2))
8887 .addImm(0) // clamp
8888 .addImm(0); // omod
8889 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8890
8891 legalizeOperands(*NewInstr, MDT);
8892 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8893 Inst.eraseFromParent();
8894 return;
8895 }
8896 case AMDGPU::S_MINIMUM_F16:
8897 case AMDGPU::S_MAXIMUM_F16: {
8898 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8899 ? &AMDGPU::VGPR_16RegClass
8900 : &AMDGPU::VGPR_32RegClass);
8901 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8902 .addImm(0) // src0_modifiers
8903 .add(Inst.getOperand(1))
8904 .addImm(0) // src1_modifiers
8905 .add(Inst.getOperand(2))
8906 .addImm(0) // clamp
8907 .addImm(0) // omod
8908 .addImm(0); // opsel0
8909 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8910 legalizeOperands(*NewInstr, MDT);
8911 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8912 Inst.eraseFromParent();
8913 return;
8914 }
8915 case AMDGPU::V_S_EXP_F16_e64:
8916 case AMDGPU::V_S_LOG_F16_e64:
8917 case AMDGPU::V_S_RCP_F16_e64:
8918 case AMDGPU::V_S_RSQ_F16_e64:
8919 case AMDGPU::V_S_SQRT_F16_e64: {
8920 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8921 ? &AMDGPU::VGPR_16RegClass
8922 : &AMDGPU::VGPR_32RegClass);
8923 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8924 .add(Inst.getOperand(1)) // src0_modifiers
8925 .add(Inst.getOperand(2))
8926 .add(Inst.getOperand(3)) // clamp
8927 .add(Inst.getOperand(4)) // omod
8928 .setMIFlags(Inst.getFlags());
8929 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8930 NewInstr.addImm(0); // opsel0
8931 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8932 legalizeOperands(*NewInstr, MDT);
8933 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8934 Inst.eraseFromParent();
8935 return;
8936 }
8937 }
8938
8939 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8940 // We cannot move this instruction to the VALU, so we should try to
8941 // legalize its operands instead.
8942 legalizeOperands(Inst, MDT);
8943 return;
8944 }
8945 // Handle converting generic instructions like COPY-to-SGPR into
8946 // COPY-to-VGPR.
8947 if (NewOpcode == Opcode) {
8948 Register DstReg = Inst.getOperand(0).getReg();
8949 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8950
8951 if (Inst.isCopy() && DstReg.isPhysical() &&
8952 Inst.getOperand(1).getReg().isVirtual()) {
8953 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8954 V2SPhyCopiesToErase);
8955 return;
8956 }
8957
8958 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8959 Register NewDstReg = Inst.getOperand(1).getReg();
8960 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8961 if (const TargetRegisterClass *CommonRC =
8962 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8963 // Instead of creating a copy where src and dst are the same register
8964 // class, we just replace all uses of dst with src. These kinds of
8965 // copies interfere with the heuristics MachineSink uses to decide
8966 // whether or not to split a critical edge. Since the pass assumes
8967 // that copies will end up as machine instructions and not be
8968 // eliminated.
8969 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8970 unsigned SrcSubReg = Inst.getOperand(1).getSubReg();
8971 bool IsUndef = Inst.getOperand(1).isUndef();
8972 for (MachineOperand &UseMO :
8973 make_early_inc_range(MRI.use_operands(DstReg))) {
8974 UseMO.setSubReg(
8975 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8976 UseMO.setReg(NewDstReg);
8977 if (IsUndef)
8978 UseMO.setIsUndef();
8979 }
8980 MRI.clearKillFlags(NewDstReg);
8981
8982 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8983 llvm_unreachable("failed to constrain register");
8984
8985 Inst.eraseFromParent();
8986
8987 for (MachineOperand &UseMO :
8988 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8989 MachineInstr &UseMI = *UseMO.getParent();
8990
8991 // Legalize t16 operands since replaceReg is called after
8992 // addUsersToVALU.
8994
8995 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
8996 if (const TargetRegisterClass *OpRC =
8997 getRegClass(UseMI.getDesc(), OpIdx))
8998 MRI.constrainRegClass(NewDstReg, OpRC);
8999 }
9000
9001 return;
9002 }
9003 }
9004
9005 // If this is a v2s copy between 16bit and 32bit reg,
9006 // replace vgpr copy to reg_sequence/extract_subreg
9007 // This can be remove after we have sgpr16 in place
9008 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
9009 Inst.getOperand(1).getReg().isVirtual() &&
9010 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
9011 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
9012 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
9013 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9014 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
9015 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
9016 get(AMDGPU::IMPLICIT_DEF), Undef);
9017 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
9018 get(AMDGPU::REG_SEQUENCE), NewDstReg)
9019 .addReg(Inst.getOperand(1).getReg())
9020 .addImm(AMDGPU::lo16)
9021 .addReg(Undef)
9022 .addImm(AMDGPU::hi16);
9023 Inst.eraseFromParent();
9024 MRI.replaceRegWith(DstReg, NewDstReg);
9025 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9026 return;
9027 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
9028 AMDGPU::lo16)) {
9029 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
9030 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9031 MRI.replaceRegWith(DstReg, NewDstReg);
9032 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9033 return;
9034 }
9035 }
9036
9037 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9038 MRI.replaceRegWith(DstReg, NewDstReg);
9039 legalizeOperands(Inst, MDT);
9040 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9041 return;
9042 }
9043
9044 // Use the new VALU Opcode.
9045 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
9046 .setMIFlags(Inst.getFlags());
9047 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
9048 // Intersperse VOP3 modifiers among the SALU operands.
9049 NewInstr->addOperand(Inst.getOperand(0));
9050 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9051 AMDGPU::OpName::src0_modifiers) >= 0)
9052 NewInstr.addImm(0);
9053 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
9054 const MachineOperand &Src = Inst.getOperand(1);
9055 NewInstr->addOperand(Src);
9056 }
9057
9058 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
9059 // We are converting these to a BFE, so we need to add the missing
9060 // operands for the size and offset.
9061 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
9062 NewInstr.addImm(0);
9063 NewInstr.addImm(Size);
9064 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
9065 // The VALU version adds the second operand to the result, so insert an
9066 // extra 0 operand.
9067 NewInstr.addImm(0);
9068 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
9069 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
9070 // If we need to move this to VGPRs, we need to unpack the second
9071 // operand back into the 2 separate ones for bit offset and width.
9072 assert(OffsetWidthOp.isImm() &&
9073 "Scalar BFE is only implemented for constant width and offset");
9074 uint32_t Imm = OffsetWidthOp.getImm();
9075
9076 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9077 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9078 NewInstr.addImm(Offset);
9079 NewInstr.addImm(BitWidth);
9080 } else {
9081 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9082 AMDGPU::OpName::src1_modifiers) >= 0)
9083 NewInstr.addImm(0);
9084 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
9085 NewInstr->addOperand(Inst.getOperand(2));
9086 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9087 AMDGPU::OpName::src2_modifiers) >= 0)
9088 NewInstr.addImm(0);
9089 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
9090 NewInstr->addOperand(Inst.getOperand(3));
9091 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
9092 NewInstr.addImm(0);
9093 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
9094 NewInstr.addImm(0);
9095 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
9096 NewInstr.addImm(0);
9097 }
9098 } else {
9099 // Just copy the SALU operands.
9100 for (const MachineOperand &Op : Inst.explicit_operands())
9101 NewInstr->addOperand(Op);
9102 }
9103
9104 // Remove any references to SCC. Vector instructions can't read from it, and
9105 // We're just about to add the implicit use / defs of VCC, and we don't want
9106 // both.
9107 bool DeadSCCDef = false;
9108 for (MachineOperand &Op : Inst.implicit_operands()) {
9109 if (Op.getReg() == AMDGPU::SCC) {
9110 // Only propagate through live-def of SCC.
9111 if (Op.isDef()) {
9112 if (Op.isDead())
9113 DeadSCCDef = true;
9114 else
9115 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
9116 continue;
9117 }
9118
9119 addSCCDefsToVALUWorklist(NewInstr, Worklist);
9120 }
9121 }
9122 Inst.eraseFromParent();
9123 Register NewDstReg;
9124 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
9125 Register DstReg = NewInstr->getOperand(0).getReg();
9126 assert(DstReg.isVirtual());
9127 // Update the destination register class.
9128 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
9129 assert(NewDstRC);
9130 NewDstReg = MRI.createVirtualRegister(NewDstRC);
9131 MRI.replaceRegWith(DstReg, NewDstReg);
9132 }
9133 fixImplicitOperands(*NewInstr);
9134
9135 if (DeadSCCDef) {
9136 // A scalar op with a dead SCC def lowers to a VALU op whose VCC def will
9137 // also be dead.
9138 if (MachineOperand *VCCDef =
9139 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
9140 VCCDef->setIsDead();
9141 }
9142
9143 // Legalize the operands
9144 legalizeOperands(*NewInstr, MDT);
9145 if (NewDstReg)
9146 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9147}
9148
9149// Add/sub require special handling to deal with carry outs.
9150std::pair<bool, MachineBasicBlock *>
9151SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
9152 MachineDominatorTree *MDT) const {
9153 if (ST.hasAddNoCarryInsts()) {
9154 // Assume there is no user of scc since we don't select this in that case.
9155 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
9156 // is used.
9157
9158 MachineBasicBlock &MBB = *Inst.getParent();
9159 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9160
9161 Register OldDstReg = Inst.getOperand(0).getReg();
9162 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9163
9164 unsigned Opc = Inst.getOpcode();
9165 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
9166
9167 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
9168 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9169
9170 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
9171 Inst.removeOperand(3);
9172
9173 Inst.setDesc(get(NewOpc));
9174 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
9175 Inst.addImplicitDefUseOperands(*MBB.getParent());
9176 MRI.replaceRegWith(OldDstReg, ResultReg);
9177 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
9178
9179 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9180 return std::pair(true, NewBB);
9181 }
9182
9183 return std::pair(false, nullptr);
9184}
9185
9186void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
9187 MachineDominatorTree *MDT) const {
9188
9189 MachineBasicBlock &MBB = *Inst.getParent();
9190 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9191 MachineBasicBlock::iterator MII = Inst;
9192 const DebugLoc &DL = Inst.getDebugLoc();
9193
9194 MachineOperand &Dest = Inst.getOperand(0);
9195 MachineOperand &Src0 = Inst.getOperand(1);
9196 MachineOperand &Src1 = Inst.getOperand(2);
9197 MachineOperand &Cond = Inst.getOperand(3);
9198
9199 Register CondReg = Cond.getReg();
9200 bool IsSCC = (CondReg == AMDGPU::SCC);
9201
9202 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
9203 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
9204 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
9205 // output directly into the V_CNDMASK.
9206 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
9207 (Src1.getImm() == 0)) {
9208 for (MachineOperand &UseMO :
9210 MachineInstr &UseMI = *UseMO.getParent();
9211 switch (UseMI.getOpcode()) {
9212 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9213 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9214 case AMDGPU::V_CNDMASK_B16_t16_e32:
9215 case AMDGPU::V_CNDMASK_B16_t16_e64:
9216 case AMDGPU::V_CNDMASK_B32_e32:
9217 case AMDGPU::V_CNDMASK_B32_e64:
9218 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9219 if (UseMO.isImplicit() ||
9220 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
9221 UseMO.setReg(CondReg);
9222 }
9223 }
9224 if (MRI.use_nodbg_empty(Dest.getReg()))
9225 return;
9226 }
9227
9228 Register NewCondReg = CondReg;
9229 if (IsSCC) {
9230 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
9231 NewCondReg = MRI.createVirtualRegister(TC);
9232
9233 // Now look for the closest SCC def if it is a copy
9234 // replacing the CondReg with the COPY source register
9235 bool CopyFound = false;
9236 for (MachineInstr &CandI :
9238 Inst.getParent()->rend())) {
9239 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
9240 -1) {
9241 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9242 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
9243 .addReg(CandI.getOperand(1).getReg());
9244 CopyFound = true;
9245 }
9246 break;
9247 }
9248 }
9249 if (!CopyFound) {
9250 // SCC def is not a copy
9251 // Insert a trivial select instead of creating a copy, because a copy from
9252 // SCC would semantically mean just copying a single bit, but we may need
9253 // the result to be a vector condition mask that needs preserving.
9254 unsigned Opcode =
9255 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9256 auto NewSelect =
9257 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
9258 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
9259 }
9260 }
9261
9262 Register NewDestReg = MRI.createVirtualRegister(
9263 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
9264 MachineInstr *NewInst;
9265 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
9266 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9267 .addImm(0)
9268 .add(Src1) // False
9269 .addImm(0)
9270 .add(Src0) // True
9271 .addReg(NewCondReg);
9272 } else {
9273 NewInst =
9274 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
9275 .add(Src1) // False
9276 .add(Src0) // True
9277 .addReg(NewCondReg);
9278 }
9279 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
9280 legalizeOperands(*NewInst, MDT);
9281 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9282}
9283
9284void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
9285 MachineInstr &Inst) const {
9286 MachineBasicBlock &MBB = *Inst.getParent();
9287 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9288 MachineBasicBlock::iterator MII = Inst;
9289 const DebugLoc &DL = Inst.getDebugLoc();
9290
9291 MachineOperand &Dest = Inst.getOperand(0);
9292 MachineOperand &Src = Inst.getOperand(1);
9293 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9294 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9295
9296 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9297 unsigned SubOp =
9298 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9299
9300 MachineInstrBuilder Sub =
9301 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(Src.getReg());
9302 if (HasCarryOut)
9303 Sub.setOperandDead(3); // Dead vcc
9304
9305 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9306 .addReg(Src.getReg())
9307 .addReg(TmpReg);
9308
9309 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9310 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9311}
9312
9313void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
9314 MachineInstr &Inst) const {
9315 MachineBasicBlock &MBB = *Inst.getParent();
9316 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9317 MachineBasicBlock::iterator MII = Inst;
9318 const DebugLoc &DL = Inst.getDebugLoc();
9319
9320 MachineOperand &Dest = Inst.getOperand(0);
9321 MachineOperand &Src1 = Inst.getOperand(1);
9322 MachineOperand &Src2 = Inst.getOperand(2);
9323 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9324 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9325 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9326
9327 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9328 unsigned SubOp =
9329 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9330
9331 MachineInstrBuilder Sub1 = BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
9332 .addReg(Src1.getReg())
9333 .addReg(Src2.getReg());
9334
9335 MachineInstrBuilder Sub2 =
9336 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
9337
9338 if (HasCarryOut) {
9339 Sub1.setOperandDead(3); // Dead vcc
9340 Sub2.setOperandDead(3); // Dead vcc
9341 }
9342
9343 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9344 .addReg(SubResultReg)
9345 .addReg(TmpReg);
9346
9347 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9348 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9349}
9350
9351void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
9352 MachineInstr &Inst) const {
9353 MachineBasicBlock &MBB = *Inst.getParent();
9354 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9355 MachineBasicBlock::iterator MII = Inst;
9356 const DebugLoc &DL = Inst.getDebugLoc();
9357
9358 MachineOperand &Dest = Inst.getOperand(0);
9359 MachineOperand &Src0 = Inst.getOperand(1);
9360 MachineOperand &Src1 = Inst.getOperand(2);
9361
9362 if (ST.hasDLInsts()) {
9363 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9364 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
9365 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
9366
9367 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
9368 .add(Src0)
9369 .add(Src1);
9370
9371 MRI.replaceRegWith(Dest.getReg(), NewDest);
9372 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9373 } else {
9374 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
9375 // invert either source and then perform the XOR. If either source is a
9376 // scalar register, then we can leave the inversion on the scalar unit to
9377 // achieve a better distribution of scalar and vector instructions.
9378 bool Src0IsSGPR = Src0.isReg() &&
9379 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
9380 bool Src1IsSGPR = Src1.isReg() &&
9381 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
9382 MachineInstr *Xor;
9383 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9384 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9385
9386 // Build a pair of scalar instructions and add them to the work list.
9387 // The next iteration over the work list will lower these to the vector
9388 // unit as necessary.
9389 if (Src0IsSGPR) {
9390 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
9391 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9392 .addReg(Temp)
9393 .add(Src1);
9394 } else if (Src1IsSGPR) {
9395 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
9396 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9397 .add(Src0)
9398 .addReg(Temp);
9399 } else {
9400 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
9401 .add(Src0)
9402 .add(Src1);
9403 MachineInstr *Not =
9404 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
9405 Worklist.insert(Not);
9406 }
9407
9408 MRI.replaceRegWith(Dest.getReg(), NewDest);
9409
9410 Worklist.insert(Xor);
9411
9412 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9413 }
9414}
9415
9416void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
9417 MachineInstr &Inst,
9418 unsigned Opcode) const {
9419 MachineBasicBlock &MBB = *Inst.getParent();
9420 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9421 MachineBasicBlock::iterator MII = Inst;
9422 const DebugLoc &DL = Inst.getDebugLoc();
9423
9424 MachineOperand &Dest = Inst.getOperand(0);
9425 MachineOperand &Src0 = Inst.getOperand(1);
9426 MachineOperand &Src1 = Inst.getOperand(2);
9427
9428 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9429 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9430
9431 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
9432 .add(Src0)
9433 .add(Src1);
9434
9435 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
9436 .addReg(Interm);
9437
9438 Worklist.insert(&Op);
9439 Worklist.insert(&Not);
9440
9441 MRI.replaceRegWith(Dest.getReg(), NewDest);
9442 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9443}
9444
9445void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
9446 MachineInstr &Inst,
9447 unsigned Opcode) const {
9448 MachineBasicBlock &MBB = *Inst.getParent();
9449 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9450 MachineBasicBlock::iterator MII = Inst;
9451 const DebugLoc &DL = Inst.getDebugLoc();
9452
9453 MachineOperand &Dest = Inst.getOperand(0);
9454 MachineOperand &Src0 = Inst.getOperand(1);
9455 MachineOperand &Src1 = Inst.getOperand(2);
9456
9457 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9458 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9459
9460 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
9461 .add(Src1);
9462
9463 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
9464 .add(Src0)
9465 .addReg(Interm);
9466
9467 Worklist.insert(&Not);
9468 Worklist.insert(&Op);
9469
9470 MRI.replaceRegWith(Dest.getReg(), NewDest);
9471 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9472}
9473
9474void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
9475 MachineInstr &Inst, unsigned Opcode,
9476 bool Swap) const {
9477 MachineBasicBlock &MBB = *Inst.getParent();
9478 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9479
9480 MachineOperand &Dest = Inst.getOperand(0);
9481 MachineOperand &Src0 = Inst.getOperand(1);
9482 const DebugLoc &DL = Inst.getDebugLoc();
9483
9484 MachineBasicBlock::iterator MII = Inst;
9485
9486 const MCInstrDesc &InstDesc = get(Opcode);
9487 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9488 MRI.getRegClass(Src0.getReg()) :
9489 &AMDGPU::SGPR_32RegClass;
9490
9491 const TargetRegisterClass *Src0SubRC =
9492 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9493
9494 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9495 AMDGPU::sub0, Src0SubRC);
9496
9497 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9498 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9499 const TargetRegisterClass *NewDestSubRC =
9500 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9501
9502 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9503 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
9504
9505 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9506 AMDGPU::sub1, Src0SubRC);
9507
9508 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9509 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
9510
9511 if (Swap)
9512 std::swap(DestSub0, DestSub1);
9513
9514 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9515 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9516 .addReg(DestSub0)
9517 .addImm(AMDGPU::sub0)
9518 .addReg(DestSub1)
9519 .addImm(AMDGPU::sub1);
9520
9521 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9522
9523 Worklist.insert(&LoHalf);
9524 Worklist.insert(&HiHalf);
9525
9526 // We don't need to legalizeOperands here because for a single operand, src0
9527 // will support any kind of input.
9528
9529 // Move all users of this moved value.
9530 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9531}
9532
9533// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9534// split the s_mul_u64 in 32-bit vector multiplications.
9535void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9536 MachineInstr &Inst,
9537 MachineDominatorTree *MDT) const {
9538 MachineBasicBlock &MBB = *Inst.getParent();
9539 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9540
9541 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9542 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9543 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9544
9545 MachineOperand &Dest = Inst.getOperand(0);
9546 MachineOperand &Src0 = Inst.getOperand(1);
9547 MachineOperand &Src1 = Inst.getOperand(2);
9548 const DebugLoc &DL = Inst.getDebugLoc();
9549 MachineBasicBlock::iterator MII = Inst;
9550
9551 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9552 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9553 const TargetRegisterClass *Src0SubRC =
9554 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9555 if (RI.isSGPRClass(Src0SubRC))
9556 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9557 const TargetRegisterClass *Src1SubRC =
9558 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9559 if (RI.isSGPRClass(Src1SubRC))
9560 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9561
9562 // First, we extract the low 32-bit and high 32-bit values from each of the
9563 // operands.
9564 MachineOperand Op0L =
9565 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9566 MachineOperand Op1L =
9567 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9568 MachineOperand Op0H =
9569 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9570 MachineOperand Op1H =
9571 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9572
9573 // The multilication is done as follows:
9574 //
9575 // Op1H Op1L
9576 // * Op0H Op0L
9577 // --------------------
9578 // Op1H*Op0L Op1L*Op0L
9579 // + Op1H*Op0H Op1L*Op0H
9580 // -----------------------------------------
9581 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9582 //
9583 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9584 // value and that would overflow.
9585 // The low 32-bit value is Op1L*Op0L.
9586 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9587
9588 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9589 MachineInstr *Op1L_Op0H =
9590 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9591 .add(Op1L)
9592 .add(Op0H);
9593
9594 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9595 MachineInstr *Op1H_Op0L =
9596 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9597 .add(Op1H)
9598 .add(Op0L);
9599
9600 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9601 MachineInstr *Carry =
9602 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9603 .add(Op1L)
9604 .add(Op0L);
9605
9606 MachineInstr *LoHalf =
9607 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9608 .add(Op1L)
9609 .add(Op0L);
9610
9611 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9612 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9613 .addReg(Op1L_Op0H_Reg)
9614 .addReg(Op1H_Op0L_Reg);
9615
9616 MachineInstr *HiHalf =
9617 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9618 .addReg(AddReg)
9619 .addReg(CarryReg);
9620
9621 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9622 .addReg(DestSub0)
9623 .addImm(AMDGPU::sub0)
9624 .addReg(DestSub1)
9625 .addImm(AMDGPU::sub1);
9626
9627 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9628
9629 // Try to legalize the operands in case we need to swap the order to keep it
9630 // valid.
9631 legalizeOperands(*Op1L_Op0H, MDT);
9632 legalizeOperands(*Op1H_Op0L, MDT);
9633 legalizeOperands(*Carry, MDT);
9634 legalizeOperands(*LoHalf, MDT);
9635 legalizeOperands(*Add, MDT);
9636 legalizeOperands(*HiHalf, MDT);
9637
9638 // Move all users of this moved value.
9639 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9640}
9641
9642// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9643// multiplications.
9644void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9645 MachineInstr &Inst,
9646 MachineDominatorTree *MDT) const {
9647 MachineBasicBlock &MBB = *Inst.getParent();
9648 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9649
9650 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9651 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9652 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9653
9654 MachineOperand &Dest = Inst.getOperand(0);
9655 MachineOperand &Src0 = Inst.getOperand(1);
9656 MachineOperand &Src1 = Inst.getOperand(2);
9657 const DebugLoc &DL = Inst.getDebugLoc();
9658 MachineBasicBlock::iterator MII = Inst;
9659
9660 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9661 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9662 const TargetRegisterClass *Src0SubRC =
9663 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9664 if (RI.isSGPRClass(Src0SubRC))
9665 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9666 const TargetRegisterClass *Src1SubRC =
9667 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9668 if (RI.isSGPRClass(Src1SubRC))
9669 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9670
9671 // First, we extract the low 32-bit and high 32-bit values from each of the
9672 // operands.
9673 MachineOperand Op0L =
9674 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9675 MachineOperand Op1L =
9676 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9677
9678 unsigned Opc = Inst.getOpcode();
9679 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9680 ? AMDGPU::V_MUL_HI_U32_e64
9681 : AMDGPU::V_MUL_HI_I32_e64;
9682 MachineInstr *HiHalf =
9683 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9684
9685 MachineInstr *LoHalf =
9686 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9687 .add(Op1L)
9688 .add(Op0L);
9689
9690 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9691 .addReg(DestSub0)
9692 .addImm(AMDGPU::sub0)
9693 .addReg(DestSub1)
9694 .addImm(AMDGPU::sub1);
9695
9696 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9697
9698 // Try to legalize the operands in case we need to swap the order to keep it
9699 // valid.
9700 legalizeOperands(*HiHalf, MDT);
9701 legalizeOperands(*LoHalf, MDT);
9702
9703 // Move all users of this moved value.
9704 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9705}
9706
9707void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9708 MachineInstr &Inst, unsigned Opcode,
9709 MachineDominatorTree *MDT) const {
9710 MachineBasicBlock &MBB = *Inst.getParent();
9711 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9712
9713 MachineOperand &Dest = Inst.getOperand(0);
9714 MachineOperand &Src0 = Inst.getOperand(1);
9715 MachineOperand &Src1 = Inst.getOperand(2);
9716 const DebugLoc &DL = Inst.getDebugLoc();
9717
9718 MachineBasicBlock::iterator MII = Inst;
9719
9720 const MCInstrDesc &InstDesc = get(Opcode);
9721 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9722 MRI.getRegClass(Src0.getReg()) :
9723 &AMDGPU::SGPR_32RegClass;
9724
9725 const TargetRegisterClass *Src0SubRC =
9726 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9727 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9728 MRI.getRegClass(Src1.getReg()) :
9729 &AMDGPU::SGPR_32RegClass;
9730
9731 const TargetRegisterClass *Src1SubRC =
9732 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9733
9734 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9735 AMDGPU::sub0, Src0SubRC);
9736 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9737 AMDGPU::sub0, Src1SubRC);
9738 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9739 AMDGPU::sub1, Src0SubRC);
9740 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9741 AMDGPU::sub1, Src1SubRC);
9742
9743 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9744 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9745 const TargetRegisterClass *NewDestSubRC =
9746 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9747
9748 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9749 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9750 .add(SrcReg0Sub0)
9751 .add(SrcReg1Sub0);
9752
9753 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9754 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9755 .add(SrcReg0Sub1)
9756 .add(SrcReg1Sub1);
9757
9758 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9759 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9760 .addReg(DestSub0)
9761 .addImm(AMDGPU::sub0)
9762 .addReg(DestSub1)
9763 .addImm(AMDGPU::sub1);
9764
9765 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9766
9767 Worklist.insert(&LoHalf);
9768 Worklist.insert(&HiHalf);
9769
9770 // Move all users of this moved value.
9771 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9772}
9773
9774void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9775 MachineInstr &Inst,
9776 MachineDominatorTree *MDT) const {
9777 MachineBasicBlock &MBB = *Inst.getParent();
9778 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9779
9780 MachineOperand &Dest = Inst.getOperand(0);
9781 MachineOperand &Src0 = Inst.getOperand(1);
9782 MachineOperand &Src1 = Inst.getOperand(2);
9783 const DebugLoc &DL = Inst.getDebugLoc();
9784
9785 MachineBasicBlock::iterator MII = Inst;
9786
9787 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9788
9789 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9790
9791 MachineOperand* Op0;
9792 MachineOperand* Op1;
9793
9794 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9795 Op0 = &Src0;
9796 Op1 = &Src1;
9797 } else {
9798 Op0 = &Src1;
9799 Op1 = &Src0;
9800 }
9801
9802 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9803 .add(*Op0);
9804
9805 Register NewDest = MRI.createVirtualRegister(DestRC);
9806
9807 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9808 .addReg(Interm)
9809 .add(*Op1);
9810
9811 MRI.replaceRegWith(Dest.getReg(), NewDest);
9812
9813 Worklist.insert(&Xor);
9814}
9815
9816void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9817 MachineInstr &Inst) const {
9818 MachineBasicBlock &MBB = *Inst.getParent();
9819 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9820
9821 MachineBasicBlock::iterator MII = Inst;
9822 const DebugLoc &DL = Inst.getDebugLoc();
9823
9824 MachineOperand &Dest = Inst.getOperand(0);
9825 MachineOperand &Src = Inst.getOperand(1);
9826
9827 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9828 const TargetRegisterClass *SrcRC = Src.isReg() ?
9829 MRI.getRegClass(Src.getReg()) :
9830 &AMDGPU::SGPR_32RegClass;
9831
9832 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9833 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9834
9835 const TargetRegisterClass *SrcSubRC =
9836 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9837
9838 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9839 AMDGPU::sub0, SrcSubRC);
9840 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9841 AMDGPU::sub1, SrcSubRC);
9842
9843 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9844
9845 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9846
9847 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9848
9849 // We don't need to legalize operands here. src0 for either instruction can be
9850 // an SGPR, and the second input is unused or determined here.
9851 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9852}
9853
9854void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9855 MachineInstr &Inst) const {
9856 MachineBasicBlock &MBB = *Inst.getParent();
9857 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9858 MachineBasicBlock::iterator MII = Inst;
9859 const DebugLoc &DL = Inst.getDebugLoc();
9860
9861 MachineOperand &Dest = Inst.getOperand(0);
9862 uint32_t Imm = Inst.getOperand(2).getImm();
9863 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9864 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9865
9866 (void) Offset;
9867
9868 // Only sext_inreg cases handled.
9869 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9870 Offset == 0 && "Not implemented");
9871
9872 if (BitWidth < 32) {
9873 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9874 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9875 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9876
9877 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9878 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9879 .addImm(0)
9880 .addImm(BitWidth);
9881
9882 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9883 .addImm(31)
9884 .addReg(MidRegLo);
9885
9886 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9887 .addReg(MidRegLo)
9888 .addImm(AMDGPU::sub0)
9889 .addReg(MidRegHi)
9890 .addImm(AMDGPU::sub1);
9891
9892 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9893 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9894 return;
9895 }
9896
9897 MachineOperand &Src = Inst.getOperand(1);
9898 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9899 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9900
9901 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9902 .addImm(31)
9903 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9904
9905 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9906 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9907 .addImm(AMDGPU::sub0)
9908 .addReg(TmpReg)
9909 .addImm(AMDGPU::sub1);
9910
9911 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9912 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9913}
9914
9915void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9916 MachineInstr &Inst, unsigned Opcode,
9917 MachineDominatorTree *MDT) const {
9918 // (S_FLBIT_I32_B64 hi:lo) ->
9919 // -> (umin (V_FFBH_U32_e32 hi), (or (V_FFBH_U32_e32 lo), 32))
9920 // (S_FF1_I32_B64 hi:lo) ->
9921 // ->(umin (or (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9922
9923 MachineBasicBlock &MBB = *Inst.getParent();
9924 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9925 MachineBasicBlock::iterator MII = Inst;
9926 const DebugLoc &DL = Inst.getDebugLoc();
9927
9928 MachineOperand &Dest = Inst.getOperand(0);
9929 MachineOperand &Src = Inst.getOperand(1);
9930
9931 const MCInstrDesc &InstDesc = get(Opcode);
9932
9933 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9934
9935 const TargetRegisterClass *SrcRC =
9936 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9937 const TargetRegisterClass *SrcSubRC =
9938 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9939
9940 MachineOperand SrcRegSub0 =
9941 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9942 MachineOperand SrcRegSub1 =
9943 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9944
9945 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9946 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9947 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9948 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9949
9950 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9951
9952 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9953
9954 BuildMI(MBB, MII, DL, get(AMDGPU::V_OR_B32_e32), MidReg3)
9955 .addImm(32)
9956 .addReg(IsCtlz ? MidReg1 : MidReg2);
9957
9958 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9959 .addReg(MidReg3)
9960 .addReg(IsCtlz ? MidReg2 : MidReg1);
9961
9962 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9963
9964 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9965}
9966
9967void SIInstrInfo::addUsersToMoveToVALUWorklist(
9969 SIInstrWorklist &Worklist) const {
9970 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9971 MachineInstr &UseMI = *MO.getParent();
9972
9973 unsigned OpNo = 0;
9974
9975 switch (UseMI.getOpcode()) {
9976 case AMDGPU::COPY:
9977 case AMDGPU::WQM:
9978 case AMDGPU::SOFT_WQM:
9979 case AMDGPU::STRICT_WWM:
9980 case AMDGPU::STRICT_WQM:
9981 case AMDGPU::REG_SEQUENCE:
9982 case AMDGPU::PHI:
9983 case AMDGPU::INSERT_SUBREG:
9984 break;
9985 default:
9986 OpNo = MO.getOperandNo();
9987 break;
9988 }
9989
9990 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9991 MRI.constrainRegClass(DstReg, OpRC);
9992
9993 if (!RI.hasVectorRegisters(OpRC))
9994 Worklist.insert(&UseMI);
9995 else
9996 // Legalization could change user list.
9998 }
9999}
10000
10001void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
10003 MachineInstr &Inst) const {
10004 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10005 MachineBasicBlock *MBB = Inst.getParent();
10006 MachineOperand &Src0 = Inst.getOperand(1);
10007 MachineOperand &Src1 = Inst.getOperand(2);
10008 const DebugLoc &DL = Inst.getDebugLoc();
10009
10010 if (ST.useRealTrue16Insts()) {
10011 Register SrcReg0, SrcReg1;
10012 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
10013 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10014 BuildMI(*MBB, Inst, DL,
10015 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
10016 .add(Src0);
10017 } else {
10018 SrcReg0 = Src0.getReg();
10019 }
10020
10021 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
10022 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10023 BuildMI(*MBB, Inst, DL,
10024 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
10025 .add(Src1);
10026 } else {
10027 SrcReg1 = Src1.getReg();
10028 }
10029
10030 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
10031 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
10032
10033 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
10034 switch (Inst.getOpcode()) {
10035 case AMDGPU::S_PACK_LL_B32_B16:
10036 NewMI
10037 .addReg(SrcReg0, {},
10038 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10039 .addImm(AMDGPU::lo16)
10040 .addReg(SrcReg1, {},
10041 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10042 .addImm(AMDGPU::hi16);
10043 break;
10044 case AMDGPU::S_PACK_LH_B32_B16:
10045 NewMI
10046 .addReg(SrcReg0, {},
10047 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10048 .addImm(AMDGPU::lo16)
10049 .addReg(SrcReg1, {}, AMDGPU::hi16)
10050 .addImm(AMDGPU::hi16);
10051 break;
10052 case AMDGPU::S_PACK_HL_B32_B16:
10053 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10054 .addImm(AMDGPU::lo16)
10055 .addReg(SrcReg1, {},
10056 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10057 .addImm(AMDGPU::hi16);
10058 break;
10059 case AMDGPU::S_PACK_HH_B32_B16:
10060 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10061 .addImm(AMDGPU::lo16)
10062 .addReg(SrcReg1, {}, AMDGPU::hi16)
10063 .addImm(AMDGPU::hi16);
10064 break;
10065 default:
10066 llvm_unreachable("unhandled s_pack_* instruction");
10067 }
10068
10069 MachineOperand &Dest = Inst.getOperand(0);
10070 MRI.replaceRegWith(Dest.getReg(), ResultReg);
10071 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10072 return;
10073 }
10074
10075 switch (Inst.getOpcode()) {
10076 case AMDGPU::S_PACK_LL_B32_B16: {
10077 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10078 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10079
10080 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
10081 // 0.
10082 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10083 .addImm(0xffff);
10084
10085 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
10086 .addReg(ImmReg)
10087 .add(Src0);
10088
10089 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
10090 .add(Src1)
10091 .addImm(16)
10092 .addReg(TmpReg);
10093 break;
10094 }
10095 case AMDGPU::S_PACK_LH_B32_B16: {
10096 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10097 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10098 .addImm(0xffff);
10099 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
10100 .addReg(ImmReg)
10101 .add(Src0)
10102 .add(Src1);
10103 break;
10104 }
10105 case AMDGPU::S_PACK_HL_B32_B16: {
10106 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10107 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
10108 .addImm(16)
10109 .add(Src0);
10110 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
10111 .add(Src1)
10112 .addImm(16)
10113 .addReg(TmpReg);
10114 break;
10115 }
10116 case AMDGPU::S_PACK_HH_B32_B16: {
10117 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10118 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10119 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
10120 .addImm(16)
10121 .add(Src0);
10122 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10123 .addImm(0xffff0000);
10124 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
10125 .add(Src1)
10126 .addReg(ImmReg)
10127 .addReg(TmpReg);
10128 break;
10129 }
10130 default:
10131 llvm_unreachable("unhandled s_pack_* instruction");
10132 }
10133
10134 MachineOperand &Dest = Inst.getOperand(0);
10135 MRI.replaceRegWith(Dest.getReg(), ResultReg);
10136 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10137}
10138
10139void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
10140 MachineInstr &SCCDefInst,
10141 SIInstrWorklist &Worklist,
10142 Register NewCond) const {
10143
10144 // Ensure that def inst defines SCC, which is still live.
10145 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
10146 !Op.isDead() && Op.getParent() == &SCCDefInst);
10147 SmallVector<MachineInstr *, 4> CopyToDelete;
10148 // This assumes that all the users of SCC are in the same block
10149 // as the SCC def.
10150 for (MachineInstr &MI : // Skip the def inst itself.
10151 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
10152 SCCDefInst.getParent()->end())) {
10153 // Check if SCC is used first.
10154 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
10155 if (SCCIdx != -1) {
10156 if (MI.isCopy()) {
10157 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10158 Register DestReg = MI.getOperand(0).getReg();
10159
10160 MRI.replaceRegWith(DestReg, NewCond);
10161 CopyToDelete.push_back(&MI);
10162 } else {
10163
10164 if (NewCond.isValid())
10165 MI.getOperand(SCCIdx).setReg(NewCond);
10166
10167 Worklist.insert(&MI);
10168 }
10169 }
10170 // Exit if we find another SCC def.
10171 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
10172 break;
10173 }
10174 for (auto &Copy : CopyToDelete)
10175 Copy->eraseFromParent();
10176}
10177
10178// Instructions that use SCC may be converted to VALU instructions. When that
10179// happens, the SCC register is changed to VCC_LO. The instruction that defines
10180// SCC must be changed to an instruction that defines VCC. This function makes
10181// sure that the instruction that defines SCC is added to the moveToVALU
10182// worklist.
10183void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
10184 SIInstrWorklist &Worklist) const {
10185 // Look for a preceding instruction that either defines VCC or SCC. If VCC
10186 // then there is nothing to do because the defining instruction has been
10187 // converted to a VALU already. If SCC then that instruction needs to be
10188 // converted to a VALU.
10189 for (MachineInstr &MI :
10190 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
10191 SCCUseInst->getParent()->rend())) {
10192 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
10193 break;
10194 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
10195 Worklist.insert(&MI);
10196 break;
10197 }
10198 }
10199}
10200
10201const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
10202 const MachineInstr &Inst) const {
10203 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
10204
10205 switch (Inst.getOpcode()) {
10206 // For target instructions, getOpRegClass just returns the virtual register
10207 // class associated with the operand, so we need to find an equivalent VGPR
10208 // register class in order to move the instruction to the VALU.
10209 case AMDGPU::COPY:
10210 case AMDGPU::PHI:
10211 case AMDGPU::REG_SEQUENCE:
10212 case AMDGPU::INSERT_SUBREG:
10213 case AMDGPU::WQM:
10214 case AMDGPU::SOFT_WQM:
10215 case AMDGPU::STRICT_WWM:
10216 case AMDGPU::STRICT_WQM: {
10217 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
10218 if (RI.isAGPRClass(SrcRC)) {
10219 if (RI.isAGPRClass(NewDstRC))
10220 return nullptr;
10221
10222 switch (Inst.getOpcode()) {
10223 case AMDGPU::PHI:
10224 case AMDGPU::REG_SEQUENCE:
10225 case AMDGPU::INSERT_SUBREG:
10226 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10227 break;
10228 default:
10229 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10230 }
10231
10232 if (!NewDstRC)
10233 return nullptr;
10234 } else {
10235 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10236 return nullptr;
10237
10238 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10239 if (!NewDstRC)
10240 return nullptr;
10241 }
10242
10243 return NewDstRC;
10244 }
10245 default:
10246 return NewDstRC;
10247 }
10248}
10249
10250// Find the one SGPR operand we are allowed to use.
10251Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
10252 int OpIndices[3]) const {
10253 const MCInstrDesc &Desc = MI.getDesc();
10254
10255 // Find the one SGPR operand we are allowed to use.
10256 //
10257 // First we need to consider the instruction's operand requirements before
10258 // legalizing. Some operands are required to be SGPRs, such as implicit uses
10259 // of VCC, but we are still bound by the constant bus requirement to only use
10260 // one.
10261 //
10262 // If the operand's class is an SGPR, we can never move it.
10263
10264 Register SGPRReg = findImplicitSGPRRead(MI);
10265 if (SGPRReg)
10266 return SGPRReg;
10267
10268 Register UsedSGPRs[3] = {Register()};
10269 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10270
10271 for (unsigned i = 0; i < 3; ++i) {
10272 int Idx = OpIndices[i];
10273 if (Idx == -1)
10274 break;
10275
10276 const MachineOperand &MO = MI.getOperand(Idx);
10277 if (!MO.isReg())
10278 continue;
10279
10280 // Is this operand statically required to be an SGPR based on the operand
10281 // constraints?
10282 const TargetRegisterClass *OpRC =
10283 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
10284 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10285 if (IsRequiredSGPR)
10286 return MO.getReg();
10287
10288 // If this could be a VGPR or an SGPR, Check the dynamic register class.
10289 Register Reg = MO.getReg();
10290 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
10291 if (RI.isSGPRClass(RegRC))
10292 UsedSGPRs[i] = Reg;
10293 }
10294
10295 // We don't have a required SGPR operand, so we have a bit more freedom in
10296 // selecting operands to move.
10297
10298 // Try to select the most used SGPR. If an SGPR is equal to one of the
10299 // others, we choose that.
10300 //
10301 // e.g.
10302 // V_FMA_F32 v0, s0, s0, s0 -> No moves
10303 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
10304
10305 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
10306 // prefer those.
10307
10308 if (UsedSGPRs[0]) {
10309 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10310 SGPRReg = UsedSGPRs[0];
10311 }
10312
10313 if (!SGPRReg && UsedSGPRs[1]) {
10314 if (UsedSGPRs[1] == UsedSGPRs[2])
10315 SGPRReg = UsedSGPRs[1];
10316 }
10317
10318 return SGPRReg;
10319}
10320
10322 AMDGPU::OpName OperandName) const {
10323 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10324 return nullptr;
10325
10326 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
10327 if (Idx == -1)
10328 return nullptr;
10329
10330 return &MI.getOperand(Idx);
10331}
10332
10334 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
10335 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
10338 return (Format << 44) |
10339 (1ULL << 56) | // RESOURCE_LEVEL = 1
10340 (3ULL << 60); // OOB_SELECT = 3
10341 }
10342
10343 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
10344 if (ST.isAmdHsaOS()) {
10345 // Set ATC = 1. GFX9 doesn't have this bit.
10346 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10347 RsrcDataFormat |= (1ULL << 56);
10348
10349 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
10350 // BTW, it disables TC L2 and therefore decreases performance.
10351 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
10352 RsrcDataFormat |= (2ULL << 59);
10353 }
10354
10355 return RsrcDataFormat;
10356}
10357
10359 uint64_t Rsrc23 = getDefaultRsrcDataFormat() |
10361 0xffffffff; // Size;
10362
10363 // GFX9 doesn't have ELEMENT_SIZE.
10364 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
10365 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
10366 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
10367 }
10368
10369 // IndexStride = 64 / 32.
10370 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10371 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
10372
10373 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
10374 // Clear them unless we want a huge stride.
10375 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
10376 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
10377 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
10378
10379 return Rsrc23;
10380}
10381
10383 unsigned Opc = MI.getOpcode();
10384
10385 return isSMRD(Opc);
10386}
10387
10389 return get(Opc).mayLoad() &&
10390 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
10391}
10392
10394 TypeSize &MemBytes) const {
10395 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
10396 if (!Addr || !Addr->isFI())
10397 return Register();
10398
10399 assert(!MI.memoperands_empty() &&
10400 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
10401
10402 FrameIndex = Addr->getIndex();
10403
10404 int VDataIdx =
10405 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
10406 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
10407 return MI.getOperand(VDataIdx).getReg();
10408}
10409
10411 TypeSize &MemBytes) const {
10412 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
10413 assert(Addr && Addr->isFI());
10414 FrameIndex = Addr->getIndex();
10415
10416 int DataIdx =
10417 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
10418 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
10419 return MI.getOperand(DataIdx).getReg();
10420}
10421
10423 int &FrameIndex,
10424 TypeSize &MemBytes) const {
10425 if (!MI.mayLoad())
10426 return Register();
10427
10428 if (isMUBUF(MI) || isVGPRSpill(MI))
10429 return isStackAccess(MI, FrameIndex, MemBytes);
10430
10431 if (isSGPRSpill(MI))
10432 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10433
10434 return Register();
10435}
10436
10438 int &FrameIndex,
10439 TypeSize &MemBytes) const {
10440 if (!MI.mayStore())
10441 return Register();
10442
10443 if (isMUBUF(MI) || isVGPRSpill(MI))
10444 return isStackAccess(MI, FrameIndex, MemBytes);
10445
10446 if (isSGPRSpill(MI))
10447 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10448
10449 return Register();
10450}
10451
10453 unsigned Opc = MI.getOpcode();
10455 unsigned DescSize = Desc.getSize();
10456
10457 // If we have a definitive size, we can use it. Otherwise we need to inspect
10458 // the operands to know the size.
10459 if (isFixedSize(MI)) {
10460 unsigned Size = DescSize;
10461
10462 // If we hit the buggy offset, an extra nop will be inserted in MC so
10463 // estimate the worst case.
10464 if (MI.isBranch() && ST.hasOffset3fBug())
10465 Size += 4;
10466
10467 return Size;
10468 }
10469
10470 // Instructions may have a 32-bit literal encoded after them. Check
10471 // operands that could ever be literals.
10472 if (isVALU(MI, /*AllowLDSDMA=*/false) || isSALU(MI)) {
10473 if (isDPP(MI))
10474 return DescSize;
10475 bool HasLiteral = false;
10476 unsigned LiteralSize = 4;
10477 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
10478 const MachineOperand &Op = MI.getOperand(I);
10479 const MCOperandInfo &OpInfo = Desc.operands()[I];
10480 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
10481 HasLiteral = true;
10482 if (ST.has64BitLiterals()) {
10483 switch (OpInfo.OperandType) {
10484 default:
10485 break;
10488 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
10489 LiteralSize = 8;
10490 break;
10493 // A 32-bit literal is only valid when the value fits in BOTH signed
10494 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
10495 // emitter's getLit64Encoding logic. This is because of the lack of
10496 // abilility to tell signedness of the literal, therefore we need to
10497 // be conservative and assume values outside this range require a
10498 // 64-bit literal encoding (8 bytes).
10499 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
10500 !isUInt<32>(Op.getImm()))
10501 LiteralSize = 8;
10502 break;
10503 }
10504 }
10505 break;
10506 }
10507 }
10508 return HasLiteral ? DescSize + LiteralSize : DescSize;
10509 }
10510
10511 // Check whether we have extra NSA words.
10512 if (isMIMG(MI)) {
10513 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
10514 if (VAddr0Idx < 0)
10515 return 8;
10516
10517 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
10518 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10519 }
10520
10521 switch (Opc) {
10522 case TargetOpcode::BUNDLE:
10523 return getInstBundleSize(MI);
10524 case TargetOpcode::INLINEASM:
10525 case TargetOpcode::INLINEASM_BR: {
10526 const MachineFunction *MF = MI.getMF();
10527 const char *AsmStr = MI.getOperand(0).getSymbolName();
10528 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10529 }
10530 default:
10531 if (MI.isMetaInstruction())
10532 return 0;
10533
10534 // If D16 Pseudo inst, get correct MC code size
10535 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10536 if (D16Info) {
10537 // Assume d16_lo/hi inst are always in same size
10538 unsigned LoInstOpcode = D16Info->LoOp;
10539 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10540 DescSize = Desc.getSize();
10541 }
10542
10543 // If FMA Pseudo inst, get correct MC code size
10544 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10545 // All potential lowerings are the same size; arbitrarily pick one.
10546 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10547 DescSize = Desc.getSize();
10548 }
10549
10550 return DescSize;
10551 }
10552}
10553
10556 if (MI.isBranch() && ST.hasOffset3fBug())
10557 return InstSizeVerifyMode::NoVerify;
10558 return InstSizeVerifyMode::ExactSize;
10559}
10560
10563 static const std::pair<int, const char *> TargetIndices[] = {
10564 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10565 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10566 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10567 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10568 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10569 return ArrayRef(TargetIndices);
10570}
10571
10572/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10573/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10576 const ScheduleDAG *DAG) const {
10577 return new GCNHazardRecognizer(DAG->MF);
10578}
10579
10580/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10581/// pass.
10588
10589// Called during:
10590// - pre-RA scheduling and post-RA scheduling
10593 const ScheduleDAGMI *DAG) const {
10594 // Borrowed from Arm Target
10595 // We would like to restrict this hazard recognizer to only
10596 // post-RA scheduling; we can tell that we're post-RA because we don't
10597 // track VRegLiveness.
10598 if (!DAG->hasVRegLiveness())
10599 return new GCNHazardRecognizer(DAG->MF);
10601}
10602
10603std::pair<unsigned, unsigned>
10605 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10606}
10607
10610 static const std::pair<unsigned, const char *> TargetFlags[] = {
10611 {MO_GOTPCREL, "amdgpu-gotprel"},
10612 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10613 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10614 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10615 {MO_REL32_LO, "amdgpu-rel32-lo"},
10616 {MO_REL32_HI, "amdgpu-rel32-hi"},
10617 {MO_REL64, "amdgpu-rel64"},
10618 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10619 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10620 {MO_ABS64, "amdgpu-abs64"},
10621 };
10622
10623 return ArrayRef(TargetFlags);
10624}
10625
10628 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10629 {
10630 {MONoClobber, "amdgpu-noclobber"},
10631 {MOLastUse, "amdgpu-last-use"},
10632 {MOCooperative, "amdgpu-cooperative"},
10633 {MOThreadPrivate, "amdgpu-thread-private"},
10634 {MOCFSB0, "amdgpu-cfs0"},
10635 {MOCFSB1, "amdgpu-cfs1"},
10636 };
10637
10638 return ArrayRef(TargetFlags);
10639}
10640
10642 const MachineFunction &MF) const {
10644 assert(SrcReg.isVirtual());
10645 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10646 return AMDGPU::WWM_COPY;
10647
10648 return AMDGPU::COPY;
10649}
10650
10652 uint32_t Opcode = MI.getOpcode();
10653 // Check if it is SGPR spill or wwm-register spill Opcode.
10654 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10655 return true;
10656
10657 const MachineFunction *MF = MI.getMF();
10658 const MachineRegisterInfo &MRI = MF->getRegInfo();
10660
10661 // See if this is Liverange split instruction inserted for SGPR or
10662 // wwm-register. The implicit def inserted for wwm-registers should also be
10663 // included as they can appear at the bb begin.
10664 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10665 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10666 return false;
10667
10668 Register Reg = MI.getOperand(0).getReg();
10669 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10670 return IsLRSplitInst;
10671
10672 return MFI->isWWMReg(Reg);
10673}
10674
10676 Register Reg) const {
10677 // We need to handle instructions which may be inserted during register
10678 // allocation to handle the prolog. The initial prolog instruction may have
10679 // been separated from the start of the block by spills and copies inserted
10680 // needed by the prolog. However, the insertions for scalar registers can
10681 // always be placed at the BB top as they are independent of the exec mask
10682 // value.
10683 bool IsNullOrVectorRegister = true;
10684 if (Reg) {
10685 const MachineFunction *MF = MI.getMF();
10686 const MachineRegisterInfo &MRI = MF->getRegInfo();
10687 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10688 }
10689
10690 return IsNullOrVectorRegister &&
10691 (canAddToBBProlog(MI) ||
10692 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10693 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10694}
10695
10699 const DebugLoc &DL,
10700 Register DestReg) const {
10701 if (ST.hasAddNoCarryInsts())
10702 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10703
10704 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10705 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10706 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10707
10708 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10709 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10710}
10711
10714 const DebugLoc &DL,
10715 Register DestReg,
10716 RegScavenger &RS) const {
10717 if (ST.hasAddNoCarryInsts())
10718 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10719
10720 // If available, prefer to use vcc.
10721 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10722 ? Register(RI.getVCC())
10723 : RS.scavengeRegisterBackwards(
10724 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10725 0, /* AllowSpill */ false);
10726
10727 // TODO: Users need to deal with this.
10728 if (!UnusedCarry.isValid())
10729 return MachineInstrBuilder();
10730
10731 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10732 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10733}
10734
10735bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10736 switch (Opcode) {
10737 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10738 case AMDGPU::SI_KILL_I1_TERMINATOR:
10739 return true;
10740 default:
10741 return false;
10742 }
10743}
10744
10746 switch (Opcode) {
10747 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10748 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10749 case AMDGPU::SI_KILL_I1_PSEUDO:
10750 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10751 default:
10752 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10753 }
10754}
10755
10757 return Imm <= getMaxMUBUFImmOffset(ST);
10758}
10759
10761 // GFX12 field is non-negative 24-bit signed byte offset.
10762 const unsigned OffsetBits =
10763 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10764 return (1 << OffsetBits) - 1;
10765}
10766
10768 if (!ST.isWave32())
10769 return;
10770
10771 if (MI.isInlineAsm())
10772 return;
10773
10774 if (MI.getNumOperands() < MI.getDesc().getNumOperands())
10775 return;
10776
10777 for (auto &Op : MI.implicit_operands()) {
10778 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10779 Op.setReg(AMDGPU::VCC_LO);
10780 }
10781}
10782
10784 if (!isSMRD(MI))
10785 return false;
10786
10787 // Check that it is using a buffer resource.
10788 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10789 if (Idx == -1) // e.g. s_memtime
10790 return false;
10791
10792 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10793 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10794}
10795
10796// Given Imm, split it into the values to put into the SOffset and ImmOffset
10797// fields in an MUBUF instruction. Return false if it is not possible (due to a
10798// hardware bug needing a workaround).
10799//
10800// The required alignment ensures that individual address components remain
10801// aligned if they are aligned to begin with. It also ensures that additional
10802// offsets within the given alignment can be added to the resulting ImmOffset.
10804 uint32_t &ImmOffset, Align Alignment) const {
10805 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10806 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10807 uint32_t Overflow = 0;
10808
10809 if (Imm > MaxImm) {
10810 if (Imm <= MaxImm + 64) {
10811 // Use an SOffset inline constant for 4..64
10812 Overflow = Imm - MaxImm;
10813 Imm = MaxImm;
10814 } else {
10815 // Try to keep the same value in SOffset for adjacent loads, so that
10816 // the corresponding register contents can be re-used.
10817 //
10818 // Load values with all low-bits (except for alignment bits) set into
10819 // SOffset, so that a larger range of values can be covered using
10820 // s_movk_i32.
10821 //
10822 // Atomic operations fail to work correctly when individual address
10823 // components are unaligned, even if their sum is aligned.
10824 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10825 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10826 Imm = Low;
10827 Overflow = High - Alignment.value();
10828 }
10829 }
10830
10831 if (Overflow > 0) {
10832 // There is a hardware bug in SI and CI which prevents address clamping in
10833 // MUBUF instructions from working correctly with SOffsets. The immediate
10834 // offset is unaffected.
10835 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10836 return false;
10837
10838 // It is not possible to set immediate in SOffset field on some targets.
10839 if (ST.hasRestrictedSOffset())
10840 return false;
10841 }
10842
10843 ImmOffset = Imm;
10844 SOffset = Overflow;
10845 return true;
10846}
10847
10848// Depending on the used address space and instructions, some immediate offsets
10849// are allowed and some are not.
10850// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10851// scratch instruction offsets can also be negative. On GFX12, offsets can be
10852// negative for all variants.
10853//
10854// There are several bugs related to these offsets:
10855// On gfx10.1, flat instructions that go into the global address space cannot
10856// use an offset.
10857//
10858// For scratch instructions, the address can be either an SGPR or a VGPR.
10859// The following offsets can be used, depending on the architecture (x means
10860// cannot be used):
10861// +----------------------------+------+------+
10862// | Address-Mode | SGPR | VGPR |
10863// +----------------------------+------+------+
10864// | gfx9 | | |
10865// | negative, 4-aligned offset | x | ok |
10866// | negative, unaligned offset | x | ok |
10867// +----------------------------+------+------+
10868// | gfx10 | | |
10869// | negative, 4-aligned offset | ok | ok |
10870// | negative, unaligned offset | ok | x |
10871// +----------------------------+------+------+
10872// | gfx10.3 | | |
10873// | negative, 4-aligned offset | ok | ok |
10874// | negative, unaligned offset | ok | ok |
10875// +----------------------------+------+------+
10876//
10877// This function ignores the addressing mode, so if an offset cannot be used in
10878// one addressing mode, it is considered illegal.
10879bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10880 AMDGPU::FlatAddrSpace FlatVariant) const {
10881 // TODO: Should 0 be special cased?
10882 if (!ST.hasFlatInstOffsets())
10883 return false;
10884
10886 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10887 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10888 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10889 return false;
10890
10891 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10892 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10893 (Offset % 4) != 0) {
10894 return false;
10895 }
10896
10897 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10898 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10899 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10900}
10901
10902// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10903std::pair<int64_t, int64_t>
10904SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10905 AMDGPU::FlatAddrSpace FlatVariant) const {
10906 int64_t RemainderOffset = COffsetVal;
10907 int64_t ImmField = 0;
10908
10909 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10910 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10911
10912 if (AllowNegative) {
10913 // Use signed division by a power of two to truncate towards 0.
10914 int64_t D = 1LL << NumBits;
10915 RemainderOffset = (COffsetVal / D) * D;
10916 ImmField = COffsetVal - RemainderOffset;
10917
10918 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10919 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10920 (ImmField % 4) != 0) {
10921 // Make ImmField a multiple of 4
10922 RemainderOffset += ImmField % 4;
10923 ImmField -= ImmField % 4;
10924 }
10925 } else if (COffsetVal >= 0) {
10926 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10927 RemainderOffset = COffsetVal - ImmField;
10928 }
10929
10930 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10931 assert(RemainderOffset + ImmField == COffsetVal);
10932 return {ImmField, RemainderOffset};
10933}
10934
10936 AMDGPU::FlatAddrSpace FlatVariant) const {
10937 if (ST.hasNegativeScratchOffsetBug() &&
10939 return false;
10940
10941 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10942}
10943
10944static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10945 switch (ST.getGeneration()) {
10946 default:
10947 break;
10950 return SIEncodingFamily::SI;
10952 // The GFX80 encoding family only contains buffer instructions with unpacked
10953 // D16 data; pseudoToMCOpcode falls back on VI for everything else.
10954 // TODO: remove this when we discard GFX80 encoding.
10955 return ST.hasUnpackedD16VMem() ? SIEncodingFamily::GFX80
10958 return SIEncodingFamily::VI;
10962 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10965 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10969 }
10970 llvm_unreachable("Unknown subtarget generation!");
10971}
10972
10973bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10974 switch(MCOp) {
10975 // These opcodes use indirect register addressing so
10976 // they need special handling by codegen (currently missing).
10977 // Therefore it is too risky to allow these opcodes
10978 // to be selected by dpp combiner or sdwa peepholer.
10979 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10980 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10981 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10982 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10983 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10984 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10985 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10986 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10987 return true;
10988 default:
10989 return false;
10990 }
10991}
10992
10993#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10994 case OPCODE##_dpp: \
10995 case OPCODE##_e32: \
10996 case OPCODE##_e64:
10997
10998static bool isRenamedInGFX9(int Opcode) {
10999 switch (Opcode) {
11000 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
11001 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
11002 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
11003 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
11004 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
11005 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
11006 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
11007 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
11008 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
11009 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
11010 case AMDGPU::V_FMA_F16_gfx9_e64:
11011 case AMDGPU::V_INTERP_P2_F16:
11012 case AMDGPU::V_MAD_F16_e64:
11013 case AMDGPU::V_MAD_U16_e64:
11014 case AMDGPU::V_MAD_I16_e64:
11015 case AMDGPU::V_MAD_U16_gfx9_e64:
11016 case AMDGPU::V_MAD_I16_gfx9_e64:
11017 return true;
11018 default:
11019 return false;
11020 }
11021}
11022
11023int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
11024 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
11025 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
11026
11027 unsigned Gen = subtargetEncodingFamily(ST);
11028
11029 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
11031
11032 if (SIInstrFlags::isSDWA(get(Opcode))) {
11033 switch (ST.getGeneration()) {
11034 default:
11036 break;
11039 break;
11042 break;
11043 }
11044 }
11045
11046 if (isMAI(Opcode)) {
11047 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
11048 if (MFMAOp != -1)
11049 Opcode = MFMAOp;
11050 }
11051
11052 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
11053
11054 // Only buffer instructions with unpacked D16 data have a GFX80 encoding.
11055 // Anything else on such a subtarget uses the plain VI encoding.
11056 // TODO: remove this when we discard GFX80 encoding.
11057 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && Gen == SIEncodingFamily::GFX80)
11059
11060 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
11062
11063 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
11065
11066 // -1 means that Opcode is already a native instruction.
11067 if (MCOp == -1)
11068 return Opcode;
11069
11070 if (ST.hasGFX90AInsts()) {
11071 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
11072 if (ST.hasGFX940Insts())
11074 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11076 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11078 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
11079 MCOp = NMCOp;
11080 }
11081
11082 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
11083 // encoding in the given subtarget generation.
11084 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
11085 return -1;
11086
11087 if (isAsmOnlyOpcode(MCOp))
11088 return -1;
11089
11090 return MCOp;
11091}
11092
11093static
11095 assert(RegOpnd.isReg());
11096 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
11097 getRegSubRegPair(RegOpnd);
11098}
11099
11102 assert(MI.isRegSequence());
11103 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
11104 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
11105 auto &RegOp = MI.getOperand(1 + 2 * I);
11106 return getRegOrUndef(RegOp);
11107 }
11109}
11110
11111// Try to find the definition of reg:subreg in subreg-manipulation pseudos
11112// Following a subreg of reg:subreg isn't supported
11115 if (!RSR.SubReg)
11116 return false;
11117 switch (MI.getOpcode()) {
11118 default: break;
11119 case AMDGPU::REG_SEQUENCE:
11120 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
11121 return true;
11122 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
11123 case AMDGPU::INSERT_SUBREG:
11124 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
11125 // inserted the subreg we're looking for
11126 RSR = getRegOrUndef(MI.getOperand(2));
11127 else { // the subreg in the rest of the reg
11128 auto R1 = getRegOrUndef(MI.getOperand(1));
11129 if (R1.SubReg) // subreg of subreg isn't supported
11130 return false;
11131 RSR.Reg = R1.Reg;
11132 }
11133 return true;
11134 }
11135 return false;
11136}
11137
11139 const MachineRegisterInfo &MRI) {
11140 assert(MRI.isSSA());
11141 if (!P.Reg.isVirtual())
11142 return nullptr;
11143
11144 auto RSR = P;
11145 auto *DefInst = MRI.getVRegDef(RSR.Reg);
11146 while (auto *MI = DefInst) {
11147 DefInst = nullptr;
11148 switch (MI->getOpcode()) {
11149 case AMDGPU::COPY:
11150 case AMDGPU::V_MOV_B32_e32: {
11151 auto &Op1 = MI->getOperand(1);
11152 if (Op1.isReg() && Op1.getReg().isVirtual()) {
11153 if (Op1.isUndef())
11154 return nullptr;
11155 RSR = getRegSubRegPair(Op1);
11156 DefInst = MRI.getVRegDef(RSR.Reg);
11157 }
11158 break;
11159 }
11160 default:
11161 if (followSubRegDef(*MI, RSR)) {
11162 if (!RSR.Reg)
11163 return nullptr;
11164 DefInst = MRI.getVRegDef(RSR.Reg);
11165 }
11166 }
11167 if (!DefInst)
11168 return MI;
11169 }
11170 return nullptr;
11171}
11172
11174 Register VReg,
11175 const MachineInstr &DefMI,
11176 const MachineInstr &UseMI) {
11177 assert(MRI.isSSA() && "Must be run on SSA");
11178
11179 auto *TRI = MRI.getTargetRegisterInfo();
11180 auto *DefBB = DefMI.getParent();
11181
11182 // Don't bother searching between blocks, although it is possible this block
11183 // doesn't modify exec.
11184 if (UseMI.getParent() != DefBB)
11185 return true;
11186
11187 const int MaxInstScan = 20;
11188 int NumInst = 0;
11189
11190 // Stop scan at the use.
11191 auto E = UseMI.getIterator();
11192 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
11193 if (I->isDebugInstr())
11194 continue;
11195
11196 if (++NumInst > MaxInstScan)
11197 return true;
11198
11199 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
11200 return true;
11201 }
11202
11203 return false;
11204}
11205
11207 Register VReg,
11208 const MachineInstr &DefMI) {
11209 assert(MRI.isSSA() && "Must be run on SSA");
11210
11211 auto *TRI = MRI.getTargetRegisterInfo();
11212 auto *DefBB = DefMI.getParent();
11213
11214 const int MaxUseScan = 10;
11215 int NumUse = 0;
11216
11217 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
11218 auto &UseInst = *Use.getParent();
11219 // Don't bother searching between blocks, although it is possible this block
11220 // doesn't modify exec.
11221 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11222 return true;
11223
11224 if (++NumUse > MaxUseScan)
11225 return true;
11226 }
11227
11228 if (NumUse == 0)
11229 return false;
11230
11231 const int MaxInstScan = 20;
11232 int NumInst = 0;
11233
11234 // Stop scan when we have seen all the uses.
11235 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
11236 assert(I != DefBB->end());
11237
11238 if (I->isDebugInstr())
11239 continue;
11240
11241 if (++NumInst > MaxInstScan)
11242 return true;
11243
11244 for (const MachineOperand &Op : I->operands()) {
11245 // We don't check reg masks here as they're used only on calls:
11246 // 1. EXEC is only considered const within one BB
11247 // 2. Call should be a terminator instruction if present in a BB
11248
11249 if (!Op.isReg())
11250 continue;
11251
11252 Register Reg = Op.getReg();
11253 if (Op.isUse()) {
11254 if (Reg == VReg && --NumUse == 0)
11255 return false;
11256 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
11257 return true;
11258 }
11259 }
11260}
11261
11264 const DebugLoc &DL, Register Src, Register Dst) const {
11265 auto Cur = MBB.begin();
11266 if (Cur != MBB.end())
11267 do {
11268 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
11269 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
11270 ++Cur;
11271 } while (Cur != MBB.end() && Cur != LastPHIIt);
11272
11273 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
11274 Dst);
11275}
11276
11279 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
11280 if (InsPt != MBB.end() &&
11281 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11282 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11283 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11284 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
11285 InsPt++;
11286 return BuildMI(MBB, InsPt, DL,
11287 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
11288 .addReg(Src, {}, SrcSubReg)
11289 .addReg(AMDGPU::EXEC, RegState::Implicit);
11290 }
11291 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
11292 Dst);
11293}
11294
11295bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
11296
11298 const MachineInstr &SecondMI) const {
11299 for (const auto &Use : SecondMI.all_uses()) {
11300 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
11301 return true;
11302 }
11303 return false;
11304}
11305
11306/// If OpX is multicycle, anti-dependencies are not allowed.
11307/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
11308/// purpose.
11310 const MachineInstr &OpX) const {
11312}
11313
11316 ArrayRef<unsigned> Ops, int FrameIndex,
11317 MachineInstr *&CopyMI, LiveIntervals *LIS,
11318 VirtRegMap *VRM) const {
11319 // This is a bit of a hack (copied from AArch64). Consider this instruction:
11320 //
11321 // %0:sreg_32 = COPY $m0
11322 //
11323 // We explicitly chose SReg_32 for the virtual register so such a copy might
11324 // be eliminated by RegisterCoalescer. However, that may not be possible, and
11325 // %0 may even spill. We can't spill $m0 normally (it would require copying to
11326 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
11327 // TargetInstrInfo::foldMemoryOperand() is going to try.
11328 // A similar issue also exists with spilling and reloading $exec registers.
11329 //
11330 // To prevent that, constrain the %0 register class here.
11331 if (isFullCopyInstr(MI)) {
11332 Register DstReg = MI.getOperand(0).getReg();
11333 Register SrcReg = MI.getOperand(1).getReg();
11334 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
11335 (DstReg.isVirtual() != SrcReg.isVirtual())) {
11337 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
11338 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
11339 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
11340 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11341 return nullptr;
11342 }
11343 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
11344 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11345 return nullptr;
11346 }
11347 }
11348 }
11349
11350 return nullptr;
11351}
11352
11354 const MachineInstr &MI,
11355 unsigned *PredCost) const {
11356 if (MI.isBundle()) {
11358 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
11359 unsigned Lat = 0, Count = 0;
11360 for (++I; I != E && I->isBundledWithPred(); ++I) {
11361 ++Count;
11362 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
11363 }
11364 return Lat + Count - 1;
11365 }
11366
11367 return SchedModel.computeInstrLatency(&MI);
11368}
11369
11371 if (!ST.hasGFX1250VALUBlockingCycles())
11372 return 0;
11374}
11375
11376unsigned
11378 if (const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(MI.getOpcode()))
11379 return Entry->GFX1250BlockingCycles;
11380 return 0;
11381}
11382
11383const MachineOperand &
11385 if (const MachineOperand *CallAddrOp =
11386 getNamedOperand(MI, AMDGPU::OpName::src0))
11387 return *CallAddrOp;
11389}
11390
11393 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11394 unsigned Opcode = MI.getOpcode();
11395
11396 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
11397 Register Dst = MI.getOperand(0).getReg();
11398 Register Src = MI.getOperand(1).getReg();
11399 LLT DstTy = MRI.getType(Dst);
11400 LLT SrcTy = MRI.getType(Src);
11401 unsigned DstAS = DstTy.getAddressSpace();
11402 unsigned SrcAS = SrcTy.getAddressSpace();
11403 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
11404 DstAS == AMDGPUAS::FLAT_ADDRESS &&
11405 ST.hasGloballyAddressableScratch()
11408 };
11409
11410 // If the target supports globally addressable scratch, the mapping from
11411 // scratch memory to the flat aperture changes therefore an address space cast
11412 // is no longer uniform.
11413 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11414 return HandleAddrSpaceCast(MI);
11415
11416 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
11417 auto IID = GI->getIntrinsicID();
11422
11423 switch (IID) {
11424 case Intrinsic::amdgcn_if:
11425 case Intrinsic::amdgcn_else:
11426 // FIXME: Uniform if second result
11427 break;
11428 }
11429
11431 }
11432
11433 // Loads from the private and flat address spaces are divergent, because
11434 // threads can execute the load instruction with the same inputs and get
11435 // different results.
11436 //
11437 // All other loads are not divergent, because if threads issue loads with the
11438 // same arguments, they will always get the same result.
11439 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11440 Opcode == AMDGPU::G_SEXTLOAD) {
11441 if (MI.memoperands_empty())
11442 return ValueUniformity::NeverUniform; // conservative assumption
11443
11444 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11445 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11446 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11447 })) {
11448 // At least one MMO in a non-global address space.
11450 }
11452 }
11453
11454 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11455 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11456 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11457 AMDGPU::isGenericAtomic(Opcode)) {
11459 }
11460
11461 // Result is computed from uniform SP and uniform wave-wide max size.
11462 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11464
11465 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11467
11469}
11470
11472 if (!Formatter)
11473 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11474 return Formatter.get();
11475}
11476
11478
11479 if (isNeverUniform(MI))
11481
11482 unsigned opcode = MI.getOpcode();
11483 if (opcode == AMDGPU::V_READLANE_B32 ||
11484 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11485 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11487
11488 // If any of defs is divergent, report as NeverUniform. isUniformReg will
11489 // calculate in more detail for each def from its reg class, if available.
11490 if (MI.isInlineAsm()) {
11491 for (const MachineOperand &MO : MI.operands()) {
11492 if (!MO.isReg() || !MO.isDef())
11493 continue;
11494 const TargetRegisterClass *RC =
11495 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
11496 if (!RC || !RI.isSGPRClass(RC))
11498 }
11499 }
11500
11501 if (isCopyInstr(MI)) {
11502 const MachineOperand &srcOp = MI.getOperand(1);
11503 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
11504 const TargetRegisterClass *regClass =
11505 RI.getPhysRegBaseClass(srcOp.getReg());
11506 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
11508 }
11510 }
11511
11512 // GMIR handling
11513 if (MI.isPreISelOpcode())
11515
11516 // Atomics are divergent because they are executed sequentially: when an
11517 // atomic operation refers to the same address in each thread, then each
11518 // thread after the first sees the value written by the previous thread as
11519 // original value.
11520
11521 if (isAtomic(MI))
11523
11524 // Loads from the private and flat address spaces are divergent, because
11525 // threads can execute the load instruction with the same inputs and get
11526 // different results.
11527 if (isFLAT(MI) && MI.mayLoad()) {
11528 if (MI.memoperands_empty())
11529 return ValueUniformity::NeverUniform; // conservative assumption
11530
11531 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11532 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11533 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11534 })) {
11535 // At least one MMO in a non-global address space.
11537 }
11538
11540 }
11541
11542 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11543 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11544
11545 // FIXME: It's conceptually broken to report this for an instruction, and not
11546 // a specific def operand. For inline asm in particular, there could be mixed
11547 // uniform and divergent results.
11548 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11549 const MachineOperand &SrcOp = MI.getOperand(I);
11550 if (!SrcOp.isReg())
11551 continue;
11552
11553 Register Reg = SrcOp.getReg();
11554 if (!Reg || !SrcOp.readsReg())
11555 continue;
11556
11557 // If RegBank is null, this is unassigned or an unallocatable special
11558 // register, which are all scalars.
11559 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11560 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11562 }
11563
11564 // TODO: Uniformity check condtions above can be rearranged for more
11565 // redability
11566
11567 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11568 // currently turned into no-op COPYs by SelectionDAG ISel and are
11569 // therefore no longer recognizable.
11570
11572}
11573
11575 switch (MF.getFunction().getCallingConv()) {
11577 return 1;
11579 return 2;
11581 return 3;
11585 const Function &F = MF.getFunction();
11586 F.getContext().diagnose(DiagnosticInfoUnsupported(
11587 F, "ds_ordered_count unsupported for this calling conv"));
11588 [[fallthrough]];
11589 }
11592 case CallingConv::C:
11593 case CallingConv::Fast:
11594 default:
11595 // Assume other calling conventions are various compute callable functions
11596 return 0;
11597 }
11598}
11599
11601 Register &SrcReg2, int64_t &CmpMask,
11602 int64_t &CmpValue) const {
11603 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11604 return false;
11605
11606 switch (MI.getOpcode()) {
11607 default:
11608 break;
11609 case AMDGPU::S_CMP_EQ_U32:
11610 case AMDGPU::S_CMP_EQ_I32:
11611 case AMDGPU::S_CMP_LG_U32:
11612 case AMDGPU::S_CMP_LG_I32:
11613 case AMDGPU::S_CMP_LT_U32:
11614 case AMDGPU::S_CMP_LT_I32:
11615 case AMDGPU::S_CMP_GT_U32:
11616 case AMDGPU::S_CMP_GT_I32:
11617 case AMDGPU::S_CMP_LE_U32:
11618 case AMDGPU::S_CMP_LE_I32:
11619 case AMDGPU::S_CMP_GE_U32:
11620 case AMDGPU::S_CMP_GE_I32:
11621 case AMDGPU::S_CMP_EQ_U64:
11622 case AMDGPU::S_CMP_LG_U64:
11623 SrcReg = MI.getOperand(0).getReg();
11624 if (MI.getOperand(1).isReg()) {
11625 if (MI.getOperand(1).getSubReg())
11626 return false;
11627 SrcReg2 = MI.getOperand(1).getReg();
11628 CmpValue = 0;
11629 } else if (MI.getOperand(1).isImm()) {
11630 SrcReg2 = Register();
11631 CmpValue = MI.getOperand(1).getImm();
11632 } else {
11633 return false;
11634 }
11635 CmpMask = ~0;
11636 return true;
11637 case AMDGPU::S_CMPK_EQ_U32:
11638 case AMDGPU::S_CMPK_EQ_I32:
11639 case AMDGPU::S_CMPK_LG_U32:
11640 case AMDGPU::S_CMPK_LG_I32:
11641 case AMDGPU::S_CMPK_LT_U32:
11642 case AMDGPU::S_CMPK_LT_I32:
11643 case AMDGPU::S_CMPK_GT_U32:
11644 case AMDGPU::S_CMPK_GT_I32:
11645 case AMDGPU::S_CMPK_LE_U32:
11646 case AMDGPU::S_CMPK_LE_I32:
11647 case AMDGPU::S_CMPK_GE_U32:
11648 case AMDGPU::S_CMPK_GE_I32:
11649 SrcReg = MI.getOperand(0).getReg();
11650 SrcReg2 = Register();
11651 CmpValue = MI.getOperand(1).getImm();
11652 CmpMask = ~0;
11653 return true;
11654 }
11655
11656 return false;
11657}
11658
11660 for (MachineBasicBlock *S : MBB->successors()) {
11661 if (S->isLiveIn(AMDGPU::SCC))
11662 return false;
11663 }
11664 return true;
11665}
11666
11667// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11668// (incoming SCC) = !(SCC defined by SCCDef).
11669// Return true if all uses can be re-written, false otherwise.
11670bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11671 MachineBasicBlock *MBB = SCCDef->getParent();
11672 SmallVector<MachineInstr *> InvertInstr;
11673 bool SCCIsDead = false;
11674
11675 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11676 constexpr unsigned ScanLimit = 12;
11677 unsigned Count = 0;
11678 for (MachineInstr &MI : instructionsWithoutDebug(
11679 std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11680 if (++Count > ScanLimit)
11681 return false;
11682 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11683 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11684 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11685 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11686 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11687 InvertInstr.push_back(&MI);
11688 else
11689 return false;
11690 }
11691 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11692 SCCIsDead = true;
11693 break;
11694 }
11695 }
11696 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11697 SCCIsDead = true;
11698
11699 // SCC may have more uses. Can't invert all of them.
11700 if (!SCCIsDead)
11701 return false;
11702
11703 // Invert uses
11704 for (MachineInstr *MI : InvertInstr) {
11705 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11706 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11707 swapOperands(*MI);
11708 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11709 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11710 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11711 ? AMDGPU::S_CBRANCH_SCC1
11712 : AMDGPU::S_CBRANCH_SCC0));
11713 } else {
11714 llvm_unreachable("SCC used but no inversion handling");
11715 }
11716 }
11717 return true;
11718}
11719
11720// SCC is already valid after SCCValid.
11721// SCCRedefine will redefine SCC to the same value already available after
11722// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11723// update kill/dead flags if necessary.
11724bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11725 bool NeedInversion) const {
11726 MachineInstr *KillsSCC = nullptr;
11727 if (SCCValid->getParent() != SCCRedefine->getParent())
11728 return false;
11729 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11730 SCCRedefine->getIterator())) {
11731 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11732 return false;
11733 if (MI.killsRegister(AMDGPU::SCC, &RI))
11734 KillsSCC = &MI;
11735 }
11736 if (NeedInversion && !invertSCCUse(SCCRedefine))
11737 return false;
11738 if (MachineOperand *SccDef =
11739 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11740 SccDef->setIsDead(false);
11741 if (KillsSCC)
11742 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11743 SCCRedefine->eraseFromParent();
11744 return true;
11745}
11746
11747/// If \p Sel is an S_CSELECT* of two different constants A and B, return them,
11748/// truncated to the width of the select.
11749static std::optional<std::pair<int64_t, int64_t>>
11751 const MachineInstr &Sel) {
11752 unsigned Opc = Sel.getOpcode();
11753 if (Opc != AMDGPU::S_CSELECT_B32 && Opc != AMDGPU::S_CSELECT_B64)
11754 return {};
11755 std::optional<int64_t> A =
11756 TII.getImmOrMaterializedImm(MRI, Sel.getOperand(1));
11757 if (!A)
11758 return {};
11759 std::optional<int64_t> B =
11760 TII.getImmOrMaterializedImm(MRI, Sel.getOperand(2));
11761 if (!B)
11762 return {};
11763 if (Opc == AMDGPU::S_CSELECT_B32) {
11764 A = Lo_32(*A);
11765 B = Lo_32(*B);
11766 }
11767 if (*A == *B)
11768 return {};
11769 return std::pair(*A, *B);
11770}
11771
11772static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11773 unsigned &NewDefOpc) {
11774 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11775 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11776 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11777 Def.getOpcode() != AMDGPU::S_ADD_U32)
11778 return false;
11779 const MachineOperand &AddSrc1 = Def.getOperand(1);
11780 const MachineOperand &AddSrc2 = Def.getOperand(2);
11781 const MachineRegisterInfo &MRI = Def.getMF()->getRegInfo();
11782 const SIInstrInfo *TII = static_cast<const SIInstrInfo *>(
11783 Def.getMF()->getSubtarget().getInstrInfo());
11784
11785 auto Imm1 = TII->getImmOrMaterializedImm(MRI, AddSrc1);
11786 auto Imm2 = TII->getImmOrMaterializedImm(MRI, AddSrc2);
11787 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11788 return false;
11789
11790 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11791 const MachineOperand *SccDef =
11792 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11793 if (!SccDef->isDead())
11794 return false;
11795 NewDefOpc = AMDGPU::S_ADD_U32;
11796 }
11797 NeedInversion = !NeedInversion;
11798 return true;
11799}
11800
11802 Register SrcReg2, int64_t CmpMask,
11803 int64_t CmpValue,
11804 const MachineRegisterInfo *MRI) const {
11805 if (!SrcReg || SrcReg.isPhysical())
11806 return false;
11807
11808 if (SrcReg2) {
11809 auto ImmOpt = getImmOrMaterializedImm(*MRI, SrcReg2);
11810 if (!ImmOpt)
11811 return false;
11812 CmpValue = *ImmOpt;
11813 }
11814
11815 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11816 this](bool NeedInversion) -> bool {
11817 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11818 if (!Def)
11819 return false;
11820
11821 unsigned NewDefOpc = Def->getOpcode();
11822 if (auto Consts = getSelectConstants(*this, *MRI, *Def)) {
11823 // sX = S_CSELECT* A, B with A != B, so sX == A exactly when SCC was set.
11824 // Comparing sX with A or B recomputes SCC or its inverse:
11825 //
11826 // s_cmp_eq_* sX, A => SCC s_cmp_lg_* sX, A => !SCC
11827 // s_cmp_eq_* sX, B => !SCC s_cmp_lg_* sX, B => SCC
11828 auto [A, B] = *Consts;
11829 int64_t C = Def->getOpcode() == AMDGPU::S_CSELECT_B32 ? Lo_32(CmpValue)
11830 : CmpValue;
11831 if (C == A)
11832 NeedInversion = !NeedInversion;
11833 else if (C != B)
11834 return false;
11835 } else {
11836 // For S_OP that set SCC = DST!=0, do the transformation
11837 //
11838 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11839 //
11840 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11841 // do the transformation:
11842 //
11843 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11844 if (CmpValue != 0 ||
11845 (!setsSCCIfResultIsNonZero(*Def) &&
11846 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc)))
11847 return false;
11848 }
11849
11850 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11851 return false;
11852
11853 if (NewDefOpc != Def->getOpcode())
11854 Def->setDesc(get(NewDefOpc));
11855
11856 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11857 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11858 // 64-bit select then delete s_or_b32 in the sequence:
11859 // sX = s_cselect_b64 A, B (A != B, one of them 0)
11860 // sLo = copy sX.sub0
11861 // sHi = copy sX.sub1
11862 // sY = s_or_b32 sLo, sHi
11863 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11864 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11865 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11866 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11867 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11868 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11869 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11870 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11871 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11872 Def2->getOperand(1).isReg() &&
11873 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11874 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11875 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11876 if (MachineInstr *Select =
11877 MRI->getVRegDef(Def1->getOperand(1).getReg())) {
11878 if (auto Consts = getSelectConstants(*this, *MRI, *Select)) {
11879 auto [A, B] = *Consts;
11880 if (A == 0 || B == 0)
11881 optimizeSCC(Select, Def, /*NeedInversion=*/A == 0);
11882 }
11883 }
11884 }
11885 }
11886 }
11887 return true;
11888 };
11889
11890 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11891 this](int64_t ExpectedValue, unsigned SrcSize,
11892 bool IsReversible, bool IsSigned) -> bool {
11893 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11894 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11895 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11896 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11897 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11898 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11899 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11900 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11901 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11902 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11903 //
11904 // Signed ge/gt are not used for the sign bit.
11905 //
11906 // If result of the AND is unused except in the compare:
11907 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11908 //
11909 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11910 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11911 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11912 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11913 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11914 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11915
11916 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11917 if (!Def)
11918 return false;
11919
11920 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11921 Def->getOpcode() != AMDGPU::S_AND_B64)
11922 return false;
11923
11924 int64_t Mask;
11925 const auto isMask = [&Mask, SrcSize, MRI,
11926 this](const MachineOperand *MO) -> bool {
11927 auto ImmOpt = this->getImmOrMaterializedImm(*MRI, *MO);
11928 if (!ImmOpt)
11929 return false;
11930 Mask = *ImmOpt;
11931 Mask &= maxUIntN(SrcSize);
11932 return isPowerOf2_64(Mask);
11933 };
11934
11935 MachineOperand *SrcOp = &Def->getOperand(1);
11936 if (isMask(SrcOp))
11937 SrcOp = &Def->getOperand(2);
11938 else if (isMask(&Def->getOperand(2)))
11939 SrcOp = &Def->getOperand(1);
11940 else
11941 return false;
11942
11943 // A valid Mask is required to have a single bit set, hence a non-zero and
11944 // power-of-two value. This verifies that we will not do 64-bit shift below.
11945 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11946 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11947 if (IsSigned && BitNo == SrcSize - 1)
11948 return false;
11949
11950 ExpectedValue <<= BitNo;
11951
11952 bool IsReversedCC = false;
11953 if (CmpValue != ExpectedValue) {
11954 if (!IsReversible)
11955 return false;
11956 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11957 if (!IsReversedCC)
11958 return false;
11959 }
11960
11961 Register DefReg = Def->getOperand(0).getReg();
11962 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11963 return false;
11964
11965 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11966 return false;
11967
11968 if (!MRI->use_nodbg_empty(DefReg)) {
11969 assert(!IsReversedCC);
11970 return true;
11971 }
11972
11973 // Replace AND with unused result with a S_BITCMP.
11974 MachineBasicBlock *MBB = Def->getParent();
11975
11976 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11977 : AMDGPU::S_BITCMP1_B32
11978 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11979 : AMDGPU::S_BITCMP1_B64;
11980
11981 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11982 .add(*SrcOp)
11983 .addImm(BitNo);
11984 Def->eraseFromParent();
11985
11986 return true;
11987 };
11988
11989 switch (CmpInstr.getOpcode()) {
11990 default:
11991 break;
11992 case AMDGPU::S_CMP_EQ_U32:
11993 case AMDGPU::S_CMP_EQ_I32:
11994 case AMDGPU::S_CMPK_EQ_U32:
11995 case AMDGPU::S_CMPK_EQ_I32:
11996 return optimizeCmpAnd(1, 32, true, false) ||
11997 optimizeCmpSelect(/*NeedInversion=*/true);
11998 case AMDGPU::S_CMP_GE_U32:
11999 case AMDGPU::S_CMPK_GE_U32:
12000 return optimizeCmpAnd(1, 32, false, false);
12001 case AMDGPU::S_CMP_GE_I32:
12002 case AMDGPU::S_CMPK_GE_I32:
12003 return optimizeCmpAnd(1, 32, false, true);
12004 case AMDGPU::S_CMP_EQ_U64:
12005 return optimizeCmpAnd(1, 64, true, false) ||
12006 optimizeCmpSelect(/*NeedInversion=*/true);
12007 case AMDGPU::S_CMP_LG_U32:
12008 case AMDGPU::S_CMP_LG_I32:
12009 case AMDGPU::S_CMPK_LG_U32:
12010 case AMDGPU::S_CMPK_LG_I32:
12011 return optimizeCmpAnd(0, 32, true, false) ||
12012 optimizeCmpSelect(/*NeedInversion=*/false);
12013 case AMDGPU::S_CMP_GT_U32:
12014 case AMDGPU::S_CMPK_GT_U32:
12015 return optimizeCmpAnd(0, 32, false, false);
12016 case AMDGPU::S_CMP_GT_I32:
12017 case AMDGPU::S_CMPK_GT_I32:
12018 return optimizeCmpAnd(0, 32, false, true);
12019 case AMDGPU::S_CMP_LG_U64:
12020 return optimizeCmpAnd(0, 64, true, false) ||
12021 optimizeCmpSelect(/*NeedInversion=*/false);
12022 }
12023
12024 return false;
12025}
12026
12028 AMDGPU::OpName OpName) const {
12029 if (!ST.needsAlignedVGPRs())
12030 return;
12031
12032 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
12033 if (OpNo < 0)
12034 return;
12035 MachineOperand &Op = MI.getOperand(OpNo);
12036 if (getOpSize(MI, OpNo) > 4)
12037 return;
12038
12039 // Add implicit aligned super-reg to force alignment on the data operand.
12040 const DebugLoc &DL = MI.getDebugLoc();
12041 MachineBasicBlock *BB = MI.getParent();
12043 Register DataReg = Op.getReg();
12044 bool IsAGPR = RI.isAGPR(MRI, DataReg);
12045 Register Undef = MRI.createVirtualRegister(
12046 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
12047 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
12048 Register NewVR =
12049 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
12050 : &AMDGPU::VReg_64_Align2RegClass);
12051 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
12052 .addReg(DataReg, {}, Op.getSubReg())
12053 .addImm(AMDGPU::sub0)
12054 .addReg(Undef)
12055 .addImm(AMDGPU::sub1);
12056 Op.setReg(NewVR);
12057 Op.setSubReg(AMDGPU::sub0);
12058 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
12059}
12060
12062 if (!SchedModel.hasInstrSchedModel())
12063 return 0;
12064
12065 // The repeat rate is the throughput-limiting resource occupancy: the largest
12066 // number of cycles any written processor resource is held.
12067 const MCSchedClassDesc *SCDesc = SchedModel.resolveSchedClass(&MI);
12068 unsigned RepeatRate = 0;
12070 PI = SchedModel.getWriteProcResBegin(SCDesc),
12071 PE = SchedModel.getWriteProcResEnd(SCDesc);
12072 PI != PE; ++PI) {
12073 RepeatRate = std::max(RepeatRate, (unsigned)PI->ReleaseAtCycle);
12074 }
12075
12076 return RepeatRate;
12077}
12078
12080 if (isIGLP(*MI))
12081 return false;
12082
12084}
12085
12087 if (!isWMMA(MI) && !isSWMMAC(MI))
12088 return false;
12089
12090 if (ST.hasGFX1250Insts())
12091 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
12092
12093 return true;
12094}
12095
12097 unsigned Opcode = MI.getOpcode();
12098
12099 if (AMDGPU::isGFX12Plus(ST))
12100 return isDOT(MI) || isXDLWMMA(MI);
12101
12102 if (!isMAI(MI) || isDGEMM(Opcode) ||
12103 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
12104 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
12105 return false;
12106
12107 if (!ST.hasGFX940Insts())
12108 return true;
12109
12110 return AMDGPU::getMAIIsGFX940XDL(Opcode);
12111}
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!")
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...
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)
static bool isReg(const MCInst &MI, unsigned OpNo)
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 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:480
#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:184
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
LiveInterval - This class represents the liveness of a register, or stack slot.
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:50
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)
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.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
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
void decomposePkFMAF32(MachineInstr &MI, MachineRegisterInfo &MRI) const
Decompose a GFX950 v_pk_fma_f32 with invalid op_sel into two independent scalar V_FMA_F32_e64 instruc...
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isLegalPkFMAF32OpSel(const MachineInstr &MI) const
Check if MI has legal GFX950 v_pk_fma op_sel.
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
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
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.
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 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
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
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:293
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:209
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:187
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)
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:71
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:45
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:53
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:41
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:49
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:68
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:64
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
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:130
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:75
MachineInstr * top() const
Definition SIInstrInfo.h:80
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
Definition SIInstrInfo.h:98
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.