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
1790 MachineRegisterInfo &MRI = MF->getRegInfo();
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) {
2013 MachineRegisterInfo &MRI = MF->getRegInfo();
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)
2752 break;
2753
2754 if (I == MBB.end())
2755 break;
2756
2757 if (I->isBundled())
2758 break;
2759
2760 // Look for a single use of the register that is also a subreg.
2761 Register RegToFind = Orig.getOperand(0).getReg();
2762 MachineOperand *UseMO = nullptr;
2763 for (auto &CandMO : I->operands()) {
2764 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2765 continue;
2766 if (UseMO) {
2767 UseMO = nullptr;
2768 break;
2769 }
2770 UseMO = &CandMO;
2771 }
2772 if (!UseMO || UseMO->getSubReg() == AMDGPU::NoSubRegister)
2773 break;
2774
2775 unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
2776 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());
2777
2778 MachineFunction *MF = MBB.getParent();
2779 MachineRegisterInfo &MRI = MF->getRegInfo();
2780 assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");
2781
2782 unsigned NewOpcode = -1;
2783 if (SubregSize == 256)
2784 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2785 else if (SubregSize == 128)
2786 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2787 else
2788 break;
2789
2790 const MCInstrDesc &TID = get(NewOpcode);
2791 const TargetRegisterClass *NewRC =
2792 RI.getAllocatableClass(getRegClass(TID, 0));
2793 MRI.setRegClass(DestReg, NewRC);
2794
2795 UseMO->setReg(DestReg);
2796 UseMO->setSubReg(AMDGPU::NoSubRegister);
2797
2798 // Use a smaller load with the desired size, possibly with updated offset.
2799 MachineInstr *MI = MF->CloneMachineInstr(&Orig);
2800 MI->setDesc(TID);
2801 MI->getOperand(0).setReg(DestReg);
2802 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2803 if (Offset) {
2804 MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
2805 int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
2806 OffsetMO->setImm(FinalOffset);
2807 }
2809 for (const MachineMemOperand *MemOp : Orig.memoperands())
2810 NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
2811 SubregSize / 8));
2812 MI->setMemRefs(*MF, NewMMOs);
2813
2814 MBB.insert(I, MI);
2815 return;
2816 }
2817
2818 default:
2819 break;
2820 }
2821
2822 TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
2823}
2824
2825std::pair<MachineInstr*, MachineInstr*>
2827 assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2828
2829 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2831 ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
2832 MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
2833 return std::pair(&MI, nullptr);
2834 }
2835
2836 MachineBasicBlock &MBB = *MI.getParent();
2837 DebugLoc DL = MBB.findDebugLoc(MI);
2838 MachineFunction *MF = MBB.getParent();
2839 MachineRegisterInfo &MRI = MF->getRegInfo();
2840 Register Dst = MI.getOperand(0).getReg();
2841 unsigned Part = 0;
2842 MachineInstr *Split[2];
2843
2844 for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2845 auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
2846 if (Dst.isPhysical()) {
2847 MovDPP.addDef(RI.getSubReg(Dst, Sub));
2848 } else {
2849 assert(MRI.isSSA());
2850 auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2851 MovDPP.addDef(Tmp);
2852 }
2853
2854 for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
2855 const MachineOperand &SrcOp = MI.getOperand(I);
2856 assert(!SrcOp.isFPImm());
2857 if (SrcOp.isImm()) {
2858 APInt Imm(64, SrcOp.getImm());
2859 Imm.ashrInPlace(Part * 32);
2860 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2861 } else {
2862 assert(SrcOp.isReg());
2863 Register Src = SrcOp.getReg();
2864 if (Src.isPhysical())
2865 MovDPP.addReg(RI.getSubReg(Src, Sub));
2866 else
2867 MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
2868 }
2869 }
2870
2871 for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
2872 MovDPP.addImm(MO.getImm());
2873
2874 Split[Part] = MovDPP;
2875 ++Part;
2876 }
2877
2878 if (Dst.isVirtual())
2879 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
2880 .addReg(Split[0]->getOperand(0).getReg())
2881 .addImm(AMDGPU::sub0)
2882 .addReg(Split[1]->getOperand(0).getReg())
2883 .addImm(AMDGPU::sub1);
2884
2885 MI.eraseFromParent();
2886 return std::pair(Split[0], Split[1]);
2887}
2888
2889std::optional<DestSourcePair>
2891 if (MI.getOpcode() == AMDGPU::WWM_COPY)
2892 return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
2893
2894 return std::nullopt;
2895}
2896
2898 AMDGPU::OpName Src0OpName,
2899 MachineOperand &Src1,
2900 AMDGPU::OpName Src1OpName) const {
2901 MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
2902 if (!Src0Mods)
2903 return false;
2904
2905 MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
2906 assert(Src1Mods &&
2907 "All commutable instructions have both src0 and src1 modifiers");
2908
2909 int Src0ModsVal = Src0Mods->getImm();
2910 int Src1ModsVal = Src1Mods->getImm();
2911
2912 Src1Mods->setImm(Src0ModsVal);
2913 Src0Mods->setImm(Src1ModsVal);
2914 return true;
2915}
2916
2918 MachineOperand &RegOp,
2919 MachineOperand &NonRegOp) {
2920 Register Reg = RegOp.getReg();
2921 unsigned SubReg = RegOp.getSubReg();
2922 bool IsKill = RegOp.isKill();
2923 bool IsDead = RegOp.isDead();
2924 bool IsUndef = RegOp.isUndef();
2925 bool IsDebug = RegOp.isDebug();
2926
2927 if (NonRegOp.isImm())
2928 RegOp.ChangeToImmediate(NonRegOp.getImm());
2929 else if (NonRegOp.isFI())
2930 RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
2931 else if (NonRegOp.isGlobal()) {
2932 RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
2933 NonRegOp.getTargetFlags());
2934 } else
2935 return nullptr;
2936
2937 // Make sure we don't reinterpret a subreg index in the target flags.
2938 RegOp.setTargetFlags(NonRegOp.getTargetFlags());
2939
2940 NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
2941 NonRegOp.setSubReg(SubReg);
2942
2943 return &MI;
2944}
2945
2947 MachineOperand &NonRegOp1,
2948 MachineOperand &NonRegOp2) {
2949 unsigned TargetFlags = NonRegOp1.getTargetFlags();
2950 int64_t NonRegVal = NonRegOp1.getImm();
2951
2952 NonRegOp1.setImm(NonRegOp2.getImm());
2953 NonRegOp2.setImm(NonRegVal);
2954 NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
2955 NonRegOp2.setTargetFlags(TargetFlags);
2956 return &MI;
2957}
2958
2959bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
2960 unsigned OpIdx1) const {
2961 const MCInstrDesc &InstDesc = MI.getDesc();
2962 const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
2963 const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];
2964
2965 unsigned Opc = MI.getOpcode();
2966 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2967
2968 const MachineOperand &MO0 = MI.getOperand(OpIdx0);
2969 const MachineOperand &MO1 = MI.getOperand(OpIdx1);
2970
2971 // Swap doesn't breach constant bus or literal limits, but it may move a
2972 // constant out of src0. Allow that for immediates where the destination
2973 // operand can hold them, e.g. VOP3 sources on targets with VOP3 literal
2974 // support. Other non-register operands stay in src0.
2975 if (isVALU(MI, /*AllowLDSDMA=*/false)) {
2976 if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
2977 (!MO0.isImm() || !isImmOperandLegal(MI, OpIdx1, MO0)))
2978 return false;
2979 if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
2980 (!MO1.isImm() || !isImmOperandLegal(MI, OpIdx0, MO1)))
2981 return false;
2982 }
2983
2984 if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
2985 if (OpInfo1.RegClass == -1)
2986 return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
2987 return isLegalRegOperand(MI, OpIdx1, MO0) &&
2988 (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
2989 }
2990 if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
2991 if (OpInfo0.RegClass == -1)
2992 return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
2993 return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
2994 isLegalRegOperand(MI, OpIdx0, MO1);
2995 }
2996
2997 // No need to check 64-bit literals since swapping does not bring new
2998 // 64-bit literals into current instruction to fold to 32-bit
2999
3000 return isImmOperandLegal(MI, OpIdx1, MO0);
3001}
3002
3004 if (!isDPP(MI))
3005 return false;
3006 const MachineOperand *DppCtrl = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
3007 return !DppCtrl || DppCtrl->getImm() != AMDGPU::DPP::QUAD_PERM_ID;
3008}
3009
3011 unsigned Src0Idx,
3012 unsigned Src1Idx) const {
3013 assert(!NewMI && "this should never be used");
3014
3016 return nullptr;
3017
3018 unsigned Opc = MI.getOpcode();
3019 int CommutedOpcode = commuteOpcode(Opc);
3020 if (CommutedOpcode == -1)
3021 return nullptr;
3022
3023 if (Src0Idx > Src1Idx)
3024 std::swap(Src0Idx, Src1Idx);
3025
3026 assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
3027 static_cast<int>(Src0Idx) &&
3028 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
3029 static_cast<int>(Src1Idx) &&
3030 "inconsistency with findCommutedOpIndices");
3031
3032 if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
3033 return nullptr;
3034
3035 MachineInstr *CommutedMI = nullptr;
3036 MachineOperand &Src0 = MI.getOperand(Src0Idx);
3037 MachineOperand &Src1 = MI.getOperand(Src1Idx);
3038 if (Src0.isReg() && Src1.isReg()) {
3039 // Be sure to copy the source modifiers to the right place.
3040 CommutedMI =
3041 TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
3042 } else if (Src0.isReg() && !Src1.isReg()) {
3043 CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
3044 } else if (!Src0.isReg() && Src1.isReg()) {
3045 CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
3046 } else if (Src0.isImm() && Src1.isImm()) {
3047 CommutedMI = swapImmOperands(MI, Src0, Src1);
3048 } else {
3049 // FIXME: Found two non registers to commute. This does happen.
3050 return nullptr;
3051 }
3052
3053 if (CommutedMI) {
3054 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
3055 Src1, AMDGPU::OpName::src1_modifiers);
3056
3057 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
3058 AMDGPU::OpName::src1_sel);
3059
3060 CommutedMI->setDesc(get(CommutedOpcode));
3061 }
3062
3063 return CommutedMI;
3064}
3065
3066// This needs to be implemented because the source modifiers may be inserted
3067// between the true commutable operands, and the base
3068// TargetInstrInfo::commuteInstruction uses it.
3070 unsigned &SrcOpIdx0,
3071 unsigned &SrcOpIdx1) const {
3073 return false;
3074
3075 return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
3076}
3077
3079 unsigned &SrcOpIdx0,
3080 unsigned &SrcOpIdx1) const {
3081 if (!Desc.isCommutable())
3082 return false;
3083
3084 unsigned Opc = Desc.getOpcode();
3085 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
3086 if (Src0Idx == -1)
3087 return false;
3088
3089 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
3090 if (Src1Idx == -1)
3091 return false;
3092
3093 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3094}
3095
3097 int64_t BrOffset) const {
3098 // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
3099 // because its dest block is unanalyzable.
3100 assert(isSOPP(BranchOp) || isSOPK(BranchOp));
3101
3102 // Convert to dwords.
3103 BrOffset /= 4;
3104
3105 // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
3106 // from the next instruction.
3107 BrOffset -= 1;
3108
3109 return isIntN(BranchOffsetBits, BrOffset);
3110}
3111
3114 return MI.getOperand(0).getMBB();
3115}
3116
3118 for (const MachineInstr &MI : MBB->terminators()) {
3119 if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
3120 MI.getOpcode() == AMDGPU::SI_LOOP ||
3121 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3122 return true;
3123 }
3124 return false;
3125}
3126
3128 MachineBasicBlock &DestBB,
3129 MachineBasicBlock &RestoreBB,
3130 const DebugLoc &DL, int64_t BrOffset,
3131 RegScavenger *RS) const {
3132 assert(MBB.empty() &&
3133 "new block should be inserted for expanding unconditional branch");
3134 assert(MBB.pred_size() == 1);
3135 assert(RestoreBB.empty() &&
3136 "restore block should be inserted for restoring clobbered registers");
3137
3138 MachineFunction *MF = MBB.getParent();
3139 MachineRegisterInfo &MRI = MF->getRegInfo();
3141 auto I = MBB.end();
3142 auto &MCCtx = MF->getContext();
3143
3144 if (ST.useAddPC64Inst()) {
3145 MCSymbol *Offset =
3146 MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
3147 auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
3149 MCSymbol *PostAddPCLabel =
3150 MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
3151 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3152 auto *OffsetExpr = MCBinaryExpr::createSub(
3153 MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
3154 MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
3155 Offset->setVariableValue(OffsetExpr);
3156 return;
3157 }
3158
3159 assert(RS && "RegScavenger required for long branching");
3160
3161 // FIXME: Virtual register workaround for RegScavenger not working with empty
3162 // blocks.
3163 Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3164
3165 // Note: as this is used after hazard recognizer we need to apply some hazard
3166 // workarounds directly.
3167 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3168 ST.hasVALUReadSGPRHazard();
3169 auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
3170 if (FlushSGPRWrites)
3171 BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
3173 };
3174
3175 // We need to compute the offset relative to the instruction immediately after
3176 // s_getpc_b64. Insert pc arithmetic code before last terminator.
3177 MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
3178 ApplyHazardWorkarounds();
3179
3180 MCSymbol *PostGetPCLabel =
3181 MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
3182 GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);
3183
3184 MCSymbol *OffsetLo =
3185 MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
3186 MCSymbol *OffsetHi =
3187 MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
3188 BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
3189 .addReg(PCReg, RegState::Define, AMDGPU::sub0)
3190 .addReg(PCReg, {}, AMDGPU::sub0)
3191 .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
3192 BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
3193 .addReg(PCReg, RegState::Define, AMDGPU::sub1)
3194 .addReg(PCReg, {}, AMDGPU::sub1)
3195 .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
3196 ApplyHazardWorkarounds();
3197
3198 // Insert the indirect branch after the other terminator.
3199 BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
3200 .addReg(PCReg);
3201
3202 // If a spill is needed for the pc register pair, we need to insert a spill
3203 // restore block right before the destination block, and insert a short branch
3204 // into the old destination block's fallthrough predecessor.
3205 // e.g.:
3206 //
3207 // s_cbranch_scc0 skip_long_branch:
3208 //
3209 // long_branch_bb:
3210 // spill s[8:9]
3211 // s_getpc_b64 s[8:9]
3212 // s_add_u32 s8, s8, restore_bb
3213 // s_addc_u32 s9, s9, 0
3214 // s_setpc_b64 s[8:9]
3215 //
3216 // skip_long_branch:
3217 // foo;
3218 //
3219 // .....
3220 //
3221 // dest_bb_fallthrough_predecessor:
3222 // bar;
3223 // s_branch dest_bb
3224 //
3225 // restore_bb:
3226 // restore s[8:9]
3227 // fallthrough dest_bb
3228 ///
3229 // dest_bb:
3230 // buzz;
3231
3232 Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
3233 Register Scav;
3234
3235 // If we've previously reserved a register for long branches
3236 // avoid running the scavenger and just use those registers
3237 if (LongBranchReservedReg) {
3238 RS->enterBasicBlock(MBB);
3239 Scav = LongBranchReservedReg;
3240 } else {
3241 RS->enterBasicBlockEnd(MBB);
3242 Scav = RS->scavengeRegisterBackwards(
3243 AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
3244 /* RestoreAfter */ false, 0, /* AllowSpill */ false);
3245 }
3246 if (Scav) {
3247 RS->setRegUsed(Scav);
3248 MRI.replaceRegWith(PCReg, Scav);
3249 MRI.clearVirtRegs();
3250 } else {
3251 // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
3252 // SGPR spill.
3253 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
3254 const SIRegisterInfo *TRI = ST.getRegisterInfo();
3255 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3256 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3257 MRI.clearVirtRegs();
3258 }
3259
3260 MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
3261 // Now, the distance could be defined.
3263 MCSymbolRefExpr::create(DestLabel, MCCtx),
3264 MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
3265 // Add offset assignments.
3266 auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
3267 OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
3268 auto *ShAmt = MCConstantExpr::create(32, MCCtx);
3269 OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
3270}
3271
3272unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
3273 switch (Cond) {
3274 case SIInstrInfo::SCC_TRUE:
3275 return AMDGPU::S_CBRANCH_SCC1;
3276 case SIInstrInfo::SCC_FALSE:
3277 return AMDGPU::S_CBRANCH_SCC0;
3278 case SIInstrInfo::VCCNZ:
3279 return AMDGPU::S_CBRANCH_VCCNZ;
3280 case SIInstrInfo::VCCZ:
3281 return AMDGPU::S_CBRANCH_VCCZ;
3282 case SIInstrInfo::EXECNZ:
3283 return AMDGPU::S_CBRANCH_EXECNZ;
3284 case SIInstrInfo::EXECZ:
3285 return AMDGPU::S_CBRANCH_EXECZ;
3286 default:
3287 llvm_unreachable("invalid branch predicate");
3288 }
3289}
3290
3291SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
3292 switch (Opcode) {
3293 case AMDGPU::S_CBRANCH_SCC0:
3294 return SCC_FALSE;
3295 case AMDGPU::S_CBRANCH_SCC1:
3296 return SCC_TRUE;
3297 case AMDGPU::S_CBRANCH_VCCNZ:
3298 return VCCNZ;
3299 case AMDGPU::S_CBRANCH_VCCZ:
3300 return VCCZ;
3301 case AMDGPU::S_CBRANCH_EXECNZ:
3302 return EXECNZ;
3303 case AMDGPU::S_CBRANCH_EXECZ:
3304 return EXECZ;
3305 default:
3306 return INVALID_BR;
3307 }
3308}
3309
3313 MachineBasicBlock *&FBB,
3315 bool AllowModify) const {
3316 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3317 // Unconditional Branch
3318 TBB = I->getOperand(0).getMBB();
3319 return false;
3320 }
3321
3322 BranchPredicate Pred = getBranchPredicate(I->getOpcode());
3323 if (Pred == INVALID_BR)
3324 return true;
3325
3326 MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
3327 Cond.push_back(MachineOperand::CreateImm(Pred));
3328 Cond.push_back(I->getOperand(1)); // Save the branch register.
3329
3330 ++I;
3331
3332 if (I == MBB.end()) {
3333 // Conditional branch followed by fall-through.
3334 TBB = CondBB;
3335 return false;
3336 }
3337
3338 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3339 TBB = CondBB;
3340 FBB = I->getOperand(0).getMBB();
3341 return false;
3342 }
3343
3344 return true;
3345}
3346
3348 MachineBasicBlock *&FBB,
3350 bool AllowModify) const {
3351 MachineBasicBlock::iterator I = MBB.getFirstTerminator();
3352 auto E = MBB.end();
3353 if (I == E)
3354 return false;
3355
3356 // Skip over the instructions that are artificially terminators for special
3357 // exec management.
3358 while (I != E && !I->isBranch() && !I->isReturn()) {
3359 switch (I->getOpcode()) {
3360 case AMDGPU::S_MOV_B64_term:
3361 case AMDGPU::S_XOR_B64_term:
3362 case AMDGPU::S_OR_B64_term:
3363 case AMDGPU::S_ANDN2_B64_term:
3364 case AMDGPU::S_AND_B64_term:
3365 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3366 case AMDGPU::S_MOV_B32_term:
3367 case AMDGPU::S_XOR_B32_term:
3368 case AMDGPU::S_OR_B32_term:
3369 case AMDGPU::S_ANDN2_B32_term:
3370 case AMDGPU::S_AND_B32_term:
3371 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3372 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3373 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3374 break;
3375 case AMDGPU::SI_IF:
3376 case AMDGPU::SI_ELSE:
3377 case AMDGPU::SI_KILL_I1_TERMINATOR:
3378 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3379 // FIXME: It's messy that these need to be considered here at all.
3380 return true;
3381 default:
3382 llvm_unreachable("unexpected non-branch terminator inst");
3383 }
3384
3385 ++I;
3386 }
3387
3388 if (I == E)
3389 return false;
3390
3391 return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
3392}
3393
3395 int *BytesRemoved) const {
3396 unsigned Count = 0;
3397 unsigned RemovedSize = 0;
3398 for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
3399 // Skip over artificial terminators when removing instructions.
3400 if (MI.isBranch() || MI.isReturn()) {
3401 RemovedSize += getInstSizeInBytes(MI);
3402 MI.eraseFromParent();
3403 ++Count;
3404 }
3405 }
3406
3407 if (BytesRemoved)
3408 *BytesRemoved = RemovedSize;
3409
3410 return Count;
3411}
3412
3413// Copy the flags onto the implicit condition register operand.
3415 const MachineOperand &OrigCond) {
3416 CondReg.setIsUndef(OrigCond.isUndef());
3417 CondReg.setIsKill(OrigCond.isKill());
3418}
3419
3422 MachineBasicBlock *FBB,
3424 const DebugLoc &DL,
3425 int *BytesAdded) const {
3426 if (!FBB && Cond.empty()) {
3427 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3428 .addMBB(TBB);
3429 if (BytesAdded)
3430 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3431 return 1;
3432 }
3433
3434 assert(TBB && Cond[0].isImm());
3435
3436 unsigned Opcode
3437 = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));
3438
3439 if (!FBB) {
3440 MachineInstr *CondBr =
3441 BuildMI(&MBB, DL, get(Opcode))
3442 .addMBB(TBB);
3443
3444 // Copy the flags onto the implicit condition register operand.
3445 preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
3446 fixImplicitOperands(*CondBr);
3447
3448 if (BytesAdded)
3449 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3450 return 1;
3451 }
3452
3453 assert(TBB && FBB);
3454
3455 MachineInstr *CondBr =
3456 BuildMI(&MBB, DL, get(Opcode))
3457 .addMBB(TBB);
3458 fixImplicitOperands(*CondBr);
3459 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3460 .addMBB(FBB);
3461
3462 MachineOperand &CondReg = CondBr->getOperand(1);
3463 CondReg.setIsUndef(Cond[1].isUndef());
3464 CondReg.setIsKill(Cond[1].isKill());
3465
3466 if (BytesAdded)
3467 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3468
3469 return 2;
3470}
3471
3474 if (Cond.size() != 2) {
3475 return true;
3476 }
3477
3478 if (Cond[0].isImm()) {
3479 Cond[0].setImm(-Cond[0].getImm());
3480 return false;
3481 }
3482
3483 return true;
3484}
3485
3486namespace {
3487class AMDGPUPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
3488private:
3489 /// The compare instruction for loop control
3490 const MachineInstr *CmpInst = nullptr;
3491 /// The normalized condition used by createTripCountGreaterCondition()
3493
3494public:
3495 AMDGPUPipelinerLoopInfo(MachineInstr *CmpInst,
3497 : CmpInst(CmpInst), Cond(Cond.begin(), Cond.end()) {}
3498
3499 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
3500 return CmpInst && MI == CmpInst;
3501 }
3502
3503 std::optional<bool> createTripCountGreaterCondition(
3504 int TC, MachineBasicBlock &MBB,
3505 SmallVectorImpl<MachineOperand> &CondParam) override {
3506 CondParam = this->Cond;
3507 return {};
3508 }
3509
3510 void adjustTripCount(int TripCountAdjust) override {}
3511
3512 void setPreheader(MachineBasicBlock *NewPreheader) override {}
3513};
3514} // namespace
3515
3516std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3518 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
3520 // Unanalyzable terminator.
3521 if (analyzeBranch(*LoopBB, TBB, FBB, Cond, /*AllowModify=*/false))
3522 return nullptr;
3523
3524 // Infinite loops are not supported.
3525 if (TBB == LoopBB && FBB == LoopBB)
3526 return nullptr;
3527
3528 // Must be conditional branch.
3529 if (FBB == nullptr)
3530 return nullptr;
3531
3532 assert((TBB == LoopBB || FBB == LoopBB) &&
3533 "The Loop must be a single-basic-block loop");
3534
3535 // Divergent (VCC/EXEC) back-edge is not supported.
3536 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3537 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3538 return nullptr;
3539
3540 // Calls and inline assembly are not supported.
3541 for (const MachineInstr &MI : *LoopBB)
3542 if (MI.isCall() || MI.isInlineAsm())
3543 return nullptr;
3544
3545 // Normalization for createTripCountGreaterCondition(): make Cond mean
3546 // "exit the loop" so the expander emits correct prolog guard branches.
3547 if (TBB == LoopBB)
3549
3550 auto Instructions = make_range(
3552 LoopBB->rend());
3553 auto CmpI = llvm::find_if(Instructions, [&](const MachineInstr &MI) {
3554 return MI.modifiesRegister(Cond[1].getReg(), &RI);
3555 });
3556
3557 if (CmpI == Instructions.end() || CmpI->isPHI())
3558 return nullptr;
3559 MachineInstr *CmpInst = &*CmpI;
3560
3561 return std::make_unique<AMDGPUPipelinerLoopInfo>(CmpInst, Cond);
3562}
3563
3566 Register DstReg, Register TrueReg,
3567 Register FalseReg,
3568 SelectExpansion &Exp) const {
3569 switch (Cond[0].getImm()) {
3570 case VCCNZ:
3571 case VCCZ: {
3572 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3573 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3574 if (MRI.getRegClass(FalseReg) != RC)
3575 return false;
3576
3577 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3578 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts; // ???
3579
3580 // Limit to equal cost for branch vs. N v_cndmask_b32s.
3581 return RI.hasVGPRs(RC) && NumInsts <= 6;
3582 }
3583 case SCC_TRUE:
3584 case SCC_FALSE: {
3585 // FIXME: We could insert for VGPRs if we could replace the original compare
3586 // with a vector one.
3587 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3588 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3589 if (MRI.getRegClass(FalseReg) != RC)
3590 return false;
3591
3592 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3593
3594 // Multiples of 8 can do s_cselect_b64
3595 if (NumInsts % 2 == 0)
3596 NumInsts /= 2;
3597
3598 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts; // ???
3599 return RI.isSGPRClass(RC);
3600 }
3601 default:
3602 return false;
3603 }
3604}
3605
3609 Register TrueReg, Register FalseReg) const {
3610 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3611 if (Pred == VCCZ || Pred == SCC_FALSE) {
3612 Pred = static_cast<BranchPredicate>(-Pred);
3613 std::swap(TrueReg, FalseReg);
3614 }
3615
3616 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3617 const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
3618 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3619
3620 if (DstSize == 32) {
3622 if (Pred == SCC_TRUE) {
3623 Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
3624 .addReg(TrueReg)
3625 .addReg(FalseReg);
3626 } else {
3627 // Instruction's operands are backwards from what is expected.
3628 Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
3629 .addReg(FalseReg)
3630 .addReg(TrueReg);
3631 }
3632
3633 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3634 return;
3635 }
3636
3637 if (DstSize == 64 && Pred == SCC_TRUE) {
3639 BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
3640 .addReg(TrueReg)
3641 .addReg(FalseReg);
3642
3643 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3644 return;
3645 }
3646
3647 static const int16_t Sub0_15[] = {
3648 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3649 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3650 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3651 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3652 };
3653
3654 static const int16_t Sub0_15_64[] = {
3655 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3656 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3657 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3658 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3659 };
3660
3661 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3662 const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
3663 const int16_t *SubIndices = Sub0_15;
3664 int NElts = DstSize / 32;
3665
3666 // 64-bit select is only available for SALU.
3667 // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
3668 if (Pred == SCC_TRUE) {
3669 if (NElts % 2) {
3670 SelOp = AMDGPU::S_CSELECT_B32;
3671 EltRC = &AMDGPU::SGPR_32RegClass;
3672 } else {
3673 SelOp = AMDGPU::S_CSELECT_B64;
3674 EltRC = &AMDGPU::SGPR_64RegClass;
3675 SubIndices = Sub0_15_64;
3676 NElts /= 2;
3677 }
3678 }
3679
3681 MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);
3682
3683 I = MIB->getIterator();
3684
3686 for (int Idx = 0; Idx != NElts; ++Idx) {
3687 Register DstElt = MRI.createVirtualRegister(EltRC);
3688 Regs.push_back(DstElt);
3689
3690 unsigned SubIdx = SubIndices[Idx];
3691
3693 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3694 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3695 .addReg(FalseReg, {}, SubIdx)
3696 .addReg(TrueReg, {}, SubIdx);
3697 } else {
3698 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3699 .addReg(TrueReg, {}, SubIdx)
3700 .addReg(FalseReg, {}, SubIdx);
3701 }
3702
3703 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3705
3706 MIB.addReg(DstElt)
3707 .addImm(SubIdx);
3708 }
3709}
3710
3712
3713 if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
3714 return true;
3715
3716 switch (MI.getOpcode()) {
3717 case AMDGPU::S_ENDPGM:
3718 case AMDGPU::S_ENDPGM_SAVED:
3719 case AMDGPU::S_TRAP:
3720 case AMDGPU::S_GETREG_B32:
3721 case AMDGPU::S_SETREG_B32:
3722 case AMDGPU::S_SETREG_B32_mode:
3723 case AMDGPU::S_SETREG_IMM32_B32:
3724 case AMDGPU::S_SETREG_IMM32_B32_mode:
3725 case AMDGPU::S_SENDMSG:
3726 case AMDGPU::S_SENDMSGHALT:
3727 case AMDGPU::S_SENDMSG_RTN_B32:
3728 case AMDGPU::S_SENDMSG_RTN_B64:
3729 case AMDGPU::S_BARRIER_WAIT:
3730 case AMDGPU::S_BARRIER_SIGNAL_M0:
3731 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3732 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3733 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3734 return true;
3735 default:
3736 return false;
3737 }
3738}
3739
3741 switch (MI.getOpcode()) {
3742 case AMDGPU::V_MOV_B16_t16_e32:
3743 case AMDGPU::V_MOV_B16_t16_e64:
3744 case AMDGPU::V_MOV_B32_e32:
3745 case AMDGPU::V_MOV_B32_e64:
3746 case AMDGPU::V_MOV_B64_PSEUDO:
3747 case AMDGPU::V_MOV_B64_e32:
3748 case AMDGPU::V_MOV_B64_e64:
3749 case AMDGPU::S_MOV_B32:
3750 case AMDGPU::S_MOV_B64:
3751 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3752 case AMDGPU::COPY:
3753 case AMDGPU::WWM_COPY:
3754 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3755 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3756 case AMDGPU::V_ACCVGPR_MOV_B32:
3757 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3758 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3759 return true;
3760 default:
3761 return false;
3762 }
3763}
3764
3766 switch (MI.getOpcode()) {
3767 case AMDGPU::V_MOV_B16_t16_e32:
3768 case AMDGPU::V_MOV_B16_t16_e64:
3769 return 2;
3770 case AMDGPU::V_MOV_B32_e32:
3771 case AMDGPU::V_MOV_B32_e64:
3772 case AMDGPU::V_MOV_B64_PSEUDO:
3773 case AMDGPU::V_MOV_B64_e32:
3774 case AMDGPU::V_MOV_B64_e64:
3775 case AMDGPU::S_MOV_B32:
3776 case AMDGPU::S_MOV_B64:
3777 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3778 case AMDGPU::COPY:
3779 case AMDGPU::WWM_COPY:
3780 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3781 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3782 case AMDGPU::V_ACCVGPR_MOV_B32:
3783 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3784 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3785 return 1;
3786 default:
3787 llvm_unreachable("MI is not a foldable copy");
3788 }
3789}
3790
3791static constexpr AMDGPU::OpName ModifierOpNames[] = {
3792 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3793 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3794 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3795
3797 unsigned Opc = MI.getOpcode();
3798 for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
3799 int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
3800 if (Idx >= 0)
3801 MI.removeOperand(Idx);
3802 }
3803}
3804
3806 const MCInstrDesc &NewDesc) const {
3807 MI.setDesc(NewDesc);
3808
3809 // Remove any leftover implicit operands from mutating the instruction. e.g.
3810 // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
3811 // anymore.
3812 const MCInstrDesc &Desc = MI.getDesc();
3813 unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
3814 Desc.implicit_defs().size();
3815
3816 for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
3817 MI.removeOperand(I);
3818}
3819
3820std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
3821 unsigned SubRegIndex) {
3822 switch (SubRegIndex) {
3823 case AMDGPU::NoSubRegister:
3824 return Imm;
3825 case AMDGPU::sub0:
3826 return SignExtend64<32>(Imm);
3827 case AMDGPU::sub1:
3828 return SignExtend64<32>(Imm >> 32);
3829 case AMDGPU::lo16:
3830 return SignExtend64<16>(Imm);
3831 case AMDGPU::hi16:
3832 return SignExtend64<16>(Imm >> 16);
3833 case AMDGPU::sub1_lo16:
3834 return SignExtend64<16>(Imm >> 32);
3835 case AMDGPU::sub1_hi16:
3836 return SignExtend64<16>(Imm >> 48);
3837 default:
3838 return std::nullopt;
3839 }
3840
3841 llvm_unreachable("covered subregister switch");
3842}
3843
3844static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
3845 switch (Opc) {
3846 case AMDGPU::V_MAC_F16_e32:
3847 case AMDGPU::V_MAC_F16_e64:
3848 case AMDGPU::V_MAD_F16_e64:
3849 return AMDGPU::V_MADAK_F16;
3850 case AMDGPU::V_MAC_F32_e32:
3851 case AMDGPU::V_MAC_F32_e64:
3852 case AMDGPU::V_MAD_F32_e64:
3853 return AMDGPU::V_MADAK_F32;
3854 case AMDGPU::V_FMAC_F32_e32:
3855 case AMDGPU::V_FMAC_F32_e64:
3856 case AMDGPU::V_FMA_F32_e64:
3857 return AMDGPU::V_FMAAK_F32;
3858 case AMDGPU::V_FMAC_F16_e32:
3859 case AMDGPU::V_FMAC_F16_e64:
3860 case AMDGPU::V_FMAC_F16_t16_e64:
3861 case AMDGPU::V_FMAC_F16_fake16_e64:
3862 case AMDGPU::V_FMAC_F16_t16_e32:
3863 case AMDGPU::V_FMAC_F16_fake16_e32:
3864 case AMDGPU::V_FMA_F16_e64:
3865 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3866 ? AMDGPU::V_FMAAK_F16_t16
3867 : AMDGPU::V_FMAAK_F16_fake16
3868 : AMDGPU::V_FMAAK_F16;
3869 case AMDGPU::V_FMAC_F64_e32:
3870 case AMDGPU::V_FMAC_F64_e64:
3871 case AMDGPU::V_FMA_F64_e64:
3872 return AMDGPU::V_FMAAK_F64;
3873 default:
3874 llvm_unreachable("invalid instruction");
3875 }
3876}
3877
3878static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
3879 switch (Opc) {
3880 case AMDGPU::V_MAC_F16_e32:
3881 case AMDGPU::V_MAC_F16_e64:
3882 case AMDGPU::V_MAD_F16_e64:
3883 return AMDGPU::V_MADMK_F16;
3884 case AMDGPU::V_MAC_F32_e32:
3885 case AMDGPU::V_MAC_F32_e64:
3886 case AMDGPU::V_MAD_F32_e64:
3887 return AMDGPU::V_MADMK_F32;
3888 case AMDGPU::V_FMAC_F32_e32:
3889 case AMDGPU::V_FMAC_F32_e64:
3890 case AMDGPU::V_FMA_F32_e64:
3891 return AMDGPU::V_FMAMK_F32;
3892 case AMDGPU::V_FMAC_F16_e32:
3893 case AMDGPU::V_FMAC_F16_e64:
3894 case AMDGPU::V_FMAC_F16_t16_e64:
3895 case AMDGPU::V_FMAC_F16_fake16_e64:
3896 case AMDGPU::V_FMAC_F16_t16_e32:
3897 case AMDGPU::V_FMAC_F16_fake16_e32:
3898 case AMDGPU::V_FMA_F16_e64:
3899 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3900 ? AMDGPU::V_FMAMK_F16_t16
3901 : AMDGPU::V_FMAMK_F16_fake16
3902 : AMDGPU::V_FMAMK_F16;
3903 case AMDGPU::V_FMAC_F64_e32:
3904 case AMDGPU::V_FMAC_F64_e64:
3905 case AMDGPU::V_FMA_F64_e64:
3906 return AMDGPU::V_FMAMK_F64;
3907 default:
3908 llvm_unreachable("invalid instruction");
3909 }
3910}
3911
3913 Register Reg, MachineRegisterInfo *MRI) const {
3914 int64_t Imm;
3915 if (!getConstValDefinedInReg(DefMI, Reg, Imm))
3916 return false;
3917
3918 const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);
3919
3920 assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");
3921
3922 unsigned Opc = UseMI.getOpcode();
3923 if (Opc == AMDGPU::COPY) {
3924 assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");
3925
3926 Register DstReg = UseMI.getOperand(0).getReg();
3927 Register UseSubReg = UseMI.getOperand(1).getSubReg();
3928
3929 const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);
3930
3931 if (HasMultipleUses) {
3932 // TODO: This should fold in more cases with multiple use, but we need to
3933 // more carefully consider what those uses are.
3934 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));
3935
3936 // Avoid breaking up a 64-bit inline immediate into a subregister extract.
3937 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3938 return false;
3939
3940 // Most of the time folding a 32-bit inline constant is free (though this
3941 // might not be true if we can't later fold it into a real user).
3942 //
3943 // FIXME: This isInlineConstant check is imprecise if
3944 // getConstValDefinedInReg handled the tricky non-mov cases.
3945 if (ImmDefSize == 32 &&
3947 return false;
3948 }
3949
3950 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3951 RI.getSubRegIdxSize(UseSubReg) == 16;
3952
3953 if (Is16Bit) {
3954 if (RI.hasVGPRs(DstRC))
3955 return false; // Do not clobber vgpr_hi16
3956
3957 if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
3958 return false;
3959 }
3960
3961 MachineFunction *MF = UseMI.getMF();
3962
3963 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3964 MCRegister MovDstPhysReg =
3965 DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();
3966
3967 std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);
3968
3969 // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
3970 for (unsigned MovOp :
3971 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3972 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3973 const MCInstrDesc &MovDesc = get(MovOp);
3974
3975 const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
3976 if (Is16Bit) {
3977 // We just need to find a correctly sized register class, so the
3978 // subregister index compatibility doesn't matter since we're statically
3979 // extracting the immediate value.
3980 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3981 if (!MovDstRC)
3982 continue;
3983
3984 if (MovDstPhysReg) {
3985 // FIXME: We probably should not do this. If there is a live value in
3986 // the high half of the register, it will be corrupted.
3987 MovDstPhysReg =
3988 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3989 if (!MovDstPhysReg)
3990 continue;
3991 }
3992 }
3993
3994 // Result class isn't the right size, try the next instruction.
3995 if (MovDstPhysReg) {
3996 if (!MovDstRC->contains(MovDstPhysReg))
3997 return false;
3998 } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
3999 // TODO: This will be overly conservative in the case of 16-bit virtual
4000 // SGPRs. We could hack up the virtual register uses to use a compatible
4001 // 32-bit class.
4002 continue;
4003 }
4004
4005 const MCOperandInfo &OpInfo = MovDesc.operands()[1];
4006
4007 // Ensure the interpreted immediate value is a valid operand in the new
4008 // mov.
4009 //
4010 // FIXME: isImmOperandLegal should have form that doesn't require existing
4011 // MachineInstr or MachineOperand
4012 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4013 !isInlineConstant(*SubRegImm, OpInfo.OperandType))
4014 break;
4015
4016 NewOpc = MovOp;
4017 break;
4018 }
4019
4020 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4021 return false;
4022
4023 if (Is16Bit) {
4024 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4025 if (MovDstPhysReg)
4026 UseMI.getOperand(0).setReg(MovDstPhysReg);
4027 assert(UseMI.getOperand(1).getReg().isVirtual());
4028 }
4029
4030 const MCInstrDesc &NewMCID = get(NewOpc);
4031 UseMI.setDesc(NewMCID);
4032 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4033 UseMI.addImplicitDefUseOperands(*MF);
4034 return true;
4035 }
4036
4037 if (HasMultipleUses)
4038 return false;
4039
4040 if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
4041 Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4042 Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
4043 Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
4044 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4045 Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
4046 Opc == AMDGPU::V_FMAC_F64_e64) {
4047 // Don't fold if we are using source or output modifiers. The new VOP2
4048 // instructions don't have them.
4050 return false;
4051
4052 // If this is a free constant, there's no reason to do this.
4053 // TODO: We could fold this here instead of letting SIFoldOperands do it
4054 // later.
4055 int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4056
4057 // Any src operand can be used for the legality check.
4058 if (isInlineConstant(UseMI, Src0Idx, Imm))
4059 return false;
4060
4061 MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);
4062
4063 MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
4064 MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);
4065
4066 auto CopyRegOperandToNarrowerRC =
4067 [MRI, this](MachineInstr &MI, unsigned OpNo,
4068 const TargetRegisterClass *NewRC) -> void {
4069 if (!MI.getOperand(OpNo).isReg())
4070 return;
4071 Register Reg = MI.getOperand(OpNo).getReg();
4072 const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
4073 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4074 return;
4075 Register Tmp = MRI->createVirtualRegister(NewRC);
4076 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
4077 get(AMDGPU::COPY), Tmp)
4078 .addReg(Reg);
4079 MI.getOperand(OpNo).setReg(Tmp);
4080 };
4081
4082 // Multiplied part is the constant: Use v_madmk_{f16, f32}.
4083 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4084 (Src1->isReg() && Src1->getReg() == Reg)) {
4085 MachineOperand *RegSrc =
4086 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4087 if (!RegSrc->isReg())
4088 return false;
4089 if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
4090 ST.getConstantBusLimit(Opc) < 2)
4091 return false;
4092
4093 if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
4094 return false;
4095
4096 // If src2 is also a literal constant then we have to choose which one to
4097 // fold. In general it is better to choose madak so that the other literal
4098 // can be materialized in an sgpr instead of a vgpr:
4099 // s_mov_b32 s0, literal
4100 // v_madak_f32 v0, s0, v0, literal
4101 // Instead of:
4102 // v_mov_b32 v1, literal
4103 // v_madmk_f32 v0, v0, literal, v1
4104 MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
4105 if (Def && Def->isMoveImmediate() &&
4106 !isInlineConstant(Def->getOperand(1)))
4107 return false;
4108
4109 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4110 if (pseudoToMCOpcode(NewOpc) == -1)
4111 return false;
4112
4113 const std::optional<int64_t> SubRegImm = extractSubregFromImm(
4114 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4115
4116 // FIXME: This would be a lot easier if we could return a new instruction
4117 // instead of having to modify in place.
4118
4119 Register SrcReg = RegSrc->getReg();
4120 unsigned SrcSubReg = RegSrc->getSubReg();
4121 Src0->setReg(SrcReg);
4122 Src0->setSubReg(SrcSubReg);
4123 Src0->setIsKill(RegSrc->isKill());
4124
4125 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4126 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4127 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4128 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4129 UseMI.untieRegOperand(
4130 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4131
4132 Src1->ChangeToImmediate(*SubRegImm);
4133
4135 UseMI.setDesc(get(NewOpc));
4136
4137 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4138 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4139 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4140 Register Tmp = MRI->createVirtualRegister(NewRC);
4141 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4142 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4143 UseMI.getOperand(0).getReg())
4144 .addReg(Tmp);
4145 UseMI.getOperand(0).setReg(Tmp);
4146 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4147 CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
4148 }
4149
4150 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4151 if (DeleteDef)
4152 DefMI.eraseFromParent();
4153
4154 return true;
4155 }
4156
4157 // Added part is the constant: Use v_madak_{f16, f32}.
4158 if (Src2->isReg() && Src2->getReg() == Reg) {
4159 if (ST.getConstantBusLimit(Opc) < 2) {
4160 // Not allowed to use constant bus for another operand.
4161 // We can however allow an inline immediate as src0.
4162 bool Src0Inlined = false;
4163 if (Src0->isReg()) {
4164 // Try to inline constant if possible.
4165 // If the Def moves immediate and the use is single
4166 // We are saving VGPR here.
4167 MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
4168 if (Def && Def->isMoveImmediate() &&
4169 isInlineConstant(Def->getOperand(1)) &&
4170 MRI->hasOneNonDBGUse(Src0->getReg())) {
4171 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4172 Src0Inlined = true;
4173 } else if (ST.getConstantBusLimit(Opc) <= 1 &&
4174 RI.isSGPRReg(*MRI, Src0->getReg())) {
4175 return false;
4176 }
4177 // VGPR is okay as Src0 - fallthrough
4178 }
4179
4180 if (Src1->isReg() && !Src0Inlined) {
4181 // We have one slot for inlinable constant so far - try to fill it
4182 MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
4183 if (Def && Def->isMoveImmediate() &&
4184 isInlineConstant(Def->getOperand(1)) &&
4185 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
4186 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4187 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
4188 return false;
4189 // VGPR is okay as Src1 - fallthrough
4190 }
4191 }
4192
4193 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4194 if (pseudoToMCOpcode(NewOpc) == -1)
4195 return false;
4196
4197 // FIXME: This would be a lot easier if we could return a new instruction
4198 // instead of having to modify in place.
4199
4200 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4201 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4202 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4203 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4204 UseMI.untieRegOperand(
4205 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4206
4207 const std::optional<int64_t> SubRegImm =
4208 extractSubregFromImm(Imm, Src2->getSubReg());
4209
4210 // ChangingToImmediate adds Src2 back to the instruction.
4211 Src2->ChangeToImmediate(*SubRegImm);
4212
4213 // These come before src2.
4215 UseMI.setDesc(get(NewOpc));
4216
4217 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4218 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4219 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4220 Register Tmp = MRI->createVirtualRegister(NewRC);
4221 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4222 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4223 UseMI.getOperand(0).getReg())
4224 .addReg(Tmp);
4225 UseMI.getOperand(0).setReg(Tmp);
4226 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4227 CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
4228 }
4229
4230 // It might happen that UseMI was commuted
4231 // and we now have SGPR as SRC1. If so 2 inlined
4232 // constant and SGPR are illegal.
4234
4235 int NewSrc0Idx =
4236 AMDGPU::getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4237 if (!isOperandLegal(UseMI, NewSrc0Idx))
4238 legalizeOpWithMove(UseMI, NewSrc0Idx);
4239
4240 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4241 if (DeleteDef)
4242 DefMI.eraseFromParent();
4243
4244 return true;
4245 }
4246 }
4247
4248 return false;
4249}
4250
4251static bool
4254 if (BaseOps1.size() != BaseOps2.size())
4255 return false;
4256 for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
4257 if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
4258 return false;
4259 }
4260 return true;
4261}
4262
4263static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
4264 LocationSize WidthB, int OffsetB) {
4265 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4266 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4267 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4268 return LowWidth.hasValue() &&
4269 LowOffset + (int)LowWidth.getValue() <= HighOffset;
4270}
4271
4272bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
4273 const MachineInstr &MIb) const {
4274 SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
4275 int64_t Offset0, Offset1;
4276 LocationSize Dummy0 = LocationSize::precise(0);
4277 LocationSize Dummy1 = LocationSize::precise(0);
4278 bool Offset0IsScalable, Offset1IsScalable;
4279 if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
4280 Dummy0) ||
4281 !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
4282 Dummy1))
4283 return false;
4284
4285 if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
4286 return false;
4287
4288 if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
4289 // FIXME: Handle ds_read2 / ds_write2.
4290 return false;
4291 }
4292 LocationSize Width0 = MIa.memoperands().front()->getSize();
4293 LocationSize Width1 = MIb.memoperands().front()->getSize();
4294 return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
4295}
4296
4298 const MachineInstr &MIb) const {
4299 assert(MIa.mayLoadOrStore() &&
4300 "MIa must load from or modify a memory location");
4301 assert(MIb.mayLoadOrStore() &&
4302 "MIb must load from or modify a memory location");
4303
4305 return false;
4306
4307 // XXX - Can we relax this between address spaces?
4308 if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
4309 return false;
4310
4311 if (isLDSDMA(MIa) || isLDSDMA(MIb))
4312 return false;
4313
4314 if (MIa.isBundle() || MIb.isBundle())
4315 return false;
4316
4317 // TODO: Should we check the address space from the MachineMemOperand? That
4318 // would allow us to distinguish objects we know don't alias based on the
4319 // underlying address space, even if it was lowered to a different one,
4320 // e.g. private accesses lowered to use MUBUF instructions on a scratch
4321 // buffer.
4322 if (isDS(MIa)) {
4323 if (isDS(MIb))
4324 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4325
4326 return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
4327 }
4328
4329 if (isMUBUF(MIa) || isMTBUF(MIa)) {
4330 if (isMUBUF(MIb) || isMTBUF(MIb))
4331 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4332
4333 if (isFLAT(MIb))
4334 return isFLATScratch(MIb);
4335
4336 return !isSMRD(MIb);
4337 }
4338
4339 if (isSMRD(MIa)) {
4340 if (isSMRD(MIb))
4341 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4342
4343 if (isFLAT(MIb))
4344 return isFLATScratch(MIb);
4345
4346 return !isMUBUF(MIb) && !isMTBUF(MIb);
4347 }
4348
4349 if (isFLAT(MIa)) {
4350 if (isFLAT(MIb)) {
4351 if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
4352 (isFLATGlobal(MIa) && isFLATScratch(MIb)))
4353 return true;
4354
4355 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4356 }
4357
4358 return false;
4359 }
4360
4361 return false;
4362}
4363
4364static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
4365 switch (Opc) {
4366 case AMDGPU::V_MAC_F16_e32:
4367 case AMDGPU::V_MAC_F16_e64:
4368 return AMDGPU::V_MAD_F16_e64;
4369 case AMDGPU::V_MAC_F32_e32:
4370 case AMDGPU::V_MAC_F32_e64:
4371 return AMDGPU::V_MAD_F32_e64;
4372 case AMDGPU::V_MAC_LEGACY_F32_e32:
4373 case AMDGPU::V_MAC_LEGACY_F32_e64:
4374 return AMDGPU::V_MAD_LEGACY_F32_e64;
4375 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4376 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4377 return AMDGPU::V_FMA_LEGACY_F32_e64;
4378 case AMDGPU::V_FMAC_F16_e32:
4379 case AMDGPU::V_FMAC_F16_e64:
4380 case AMDGPU::V_FMAC_F16_t16_e64:
4381 case AMDGPU::V_FMAC_F16_fake16_e64:
4382 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4383 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4384 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4385 : AMDGPU::V_FMA_F16_gfx9_e64;
4386 case AMDGPU::V_FMAC_F32_e32:
4387 case AMDGPU::V_FMAC_F32_e64:
4388 return AMDGPU::V_FMA_F32_e64;
4389 case AMDGPU::V_FMAC_F64_e32:
4390 case AMDGPU::V_FMAC_F64_e64:
4391 return AMDGPU::V_FMA_F64_e64;
4392 default:
4393 llvm_unreachable("invalid instruction");
4394 }
4395}
4396
4397/// Helper struct for the implementation of 3-address conversion to communicate
4398/// updates made to instruction operands.
4400 /// Other instruction whose def is no longer used by the converted
4401 /// instruction.
4403};
4404
4406 LiveIntervals *LIS) const {
4407 MachineBasicBlock &MBB = *MI.getParent();
4408 MachineInstr *CandidateMI = &MI;
4409
4410 if (MI.isBundle()) {
4411 // This is a temporary placeholder for bundle handling that enables us to
4412 // exercise the relevant code paths in the two-address instruction pass.
4413 if (MI.getBundleSize() != 1)
4414 return nullptr;
4415 CandidateMI = MI.getNextNode();
4416 }
4417
4419 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4420 if (!NewMI)
4421 return nullptr;
4422
4423 if (MI.isBundle()) {
4424 CandidateMI->eraseFromBundle();
4425
4426 for (MachineOperand &MO : MI.all_defs()) {
4427 if (MO.isTied())
4428 MI.untieRegOperand(MO.getOperandNo());
4429 }
4430 } else {
4431 if (LIS) {
4432 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
4433 // SlotIndex of defs needs to be updated when converting to early-clobber
4434 MachineOperand &Def = NewMI->getOperand(0);
4435 if (Def.isEarlyClobber() && Def.isReg() &&
4436 LIS->hasInterval(Def.getReg())) {
4437 SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
4438 SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
4439 auto &LI = LIS->getInterval(Def.getReg());
4440 auto UpdateDefIndex = [&](LiveRange &LR) {
4441 auto *S = LR.find(OldIndex);
4442 if (S != LR.end() && S->start == OldIndex) {
4443 assert(S->valno && S->valno->def == OldIndex);
4444 S->start = NewIndex;
4445 S->valno->def = NewIndex;
4446 }
4447 };
4448 UpdateDefIndex(LI);
4449 for (auto &SR : LI.subranges())
4450 UpdateDefIndex(SR);
4451 }
4452 }
4453 }
4454
4455 if (U.RemoveMIUse) {
4456 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4457 // The only user is the instruction which will be killed.
4458 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4459
4460 if (MRI.hasOneNonDBGUse(DefReg)) {
4461 // We cannot just remove the DefMI here, calling pass will crash.
4462 U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
4463 U.RemoveMIUse->getOperand(0).setIsDead(true);
4464 for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
4465 U.RemoveMIUse->removeOperand(I);
4466 }
4467
4468 if (MI.isBundle()) {
4469 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4470 if (!VRI.Reads && !VRI.Writes) {
4471 for (MachineOperand &MO : MI.all_uses()) {
4472 if (MO.isReg() && MO.getReg() == DefReg) {
4473 assert(MO.getSubReg() == 0 &&
4474 "tied sub-registers in bundles currently not supported");
4475 MI.removeOperand(MO.getOperandNo());
4476 break;
4477 }
4478 }
4479
4480 if (LIS)
4481 LIS->shrinkToUses(&LIS->getInterval(DefReg));
4482 }
4483 } else if (LIS) {
4484 LiveInterval &DefLI = LIS->getInterval(DefReg);
4485
4486 // We cannot delete the original instruction here, so hack out the use
4487 // in the original instruction with a dummy register so we can use
4488 // shrinkToUses to deal with any multi-use edge cases. Other targets do
4489 // not have the complexity of deleting a use to consider here.
4490 Register DummyReg = MRI.cloneVirtualRegister(DefReg);
4491 for (MachineOperand &MIOp : MI.uses()) {
4492 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4493 MIOp.setIsUndef(true);
4494 MIOp.setReg(DummyReg);
4495 }
4496 }
4497
4498 if (MI.isBundle()) {
4499 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4500 if (!VRI.Reads && !VRI.Writes) {
4501 for (MachineOperand &MIOp : MI.uses()) {
4502 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4503 MIOp.setIsUndef(true);
4504 MIOp.setReg(DummyReg);
4505 }
4506 }
4507 }
4508
4509 MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
4510 false, /*isUndef=*/true));
4511 }
4512
4513 LIS->shrinkToUses(&DefLI);
4514 }
4515 }
4516
4517 return MI.isBundle() ? &MI : NewMI;
4518}
4519
4521SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
4522 ThreeAddressUpdates &U) const {
4523 MachineBasicBlock &MBB = *MI.getParent();
4524 unsigned Opc = MI.getOpcode();
4525
4526 // Handle MFMA.
4527 int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
4528 if (NewMFMAOpc != -1) {
4530 BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
4531 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4532 MIB.add(MI.getOperand(I));
4533 return MIB;
4534 }
4535
4536 if (SIInstrInfo::isWMMA(MI)) {
4537 unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
4538 MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4539 .setMIFlags(MI.getFlags());
4540 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4541 MIB->addOperand(MI.getOperand(I));
4542 return MIB;
4543 }
4544
4545 assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4546 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4547 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4548 "present pre-RA");
4549
4550 // Handle MAC/FMAC.
4551 bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
4552 bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4553 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4554 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4555 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4556 bool Src0Literal = false;
4557
4558 switch (Opc) {
4559 default:
4560 return nullptr;
4561 case AMDGPU::V_MAC_F16_e64:
4562 case AMDGPU::V_FMAC_F16_e64:
4563 case AMDGPU::V_FMAC_F16_t16_e64:
4564 case AMDGPU::V_FMAC_F16_fake16_e64:
4565 case AMDGPU::V_MAC_F32_e64:
4566 case AMDGPU::V_MAC_LEGACY_F32_e64:
4567 case AMDGPU::V_FMAC_F32_e64:
4568 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4569 case AMDGPU::V_FMAC_F64_e64:
4570 break;
4571 case AMDGPU::V_MAC_F16_e32:
4572 case AMDGPU::V_FMAC_F16_e32:
4573 case AMDGPU::V_MAC_F32_e32:
4574 case AMDGPU::V_MAC_LEGACY_F32_e32:
4575 case AMDGPU::V_FMAC_F32_e32:
4576 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4577 case AMDGPU::V_FMAC_F64_e32: {
4578 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
4579 AMDGPU::OpName::src0);
4580 const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
4581 if (!Src0->isReg() && !Src0->isImm())
4582 return nullptr;
4583
4584 if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
4585 Src0Literal = true;
4586
4587 break;
4588 }
4589 }
4590
4591 MachineInstrBuilder MIB;
4592 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
4593 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
4594 const MachineOperand *Src0Mods =
4595 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
4596 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4597 const MachineOperand *Src1Mods =
4598 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
4599 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4600 const MachineOperand *Src2Mods =
4601 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
4602 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
4603 const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
4604 const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);
4605
4606 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4607 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4608 // If we have an SGPR input, we will violate the constant bus restriction.
4609 (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
4610 !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
4611 MachineInstr *DefMI = nullptr;
4612 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4613 std::optional<int64_t> ImmOpt;
4614 int64_t Imm;
4615
4616 if (!Src0Literal &&
4617 (ImmOpt = getImmOrMaterializedImm(MRI, *Src2, &DefMI))) {
4618 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4619 if (pseudoToMCOpcode(NewOpc) != -1) {
4620 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4621 .add(*Dst)
4622 .add(*Src0)
4623 .add(*Src1)
4624 .addImm(*ImmOpt)
4625 .setMIFlags(MI.getFlags());
4626 U.RemoveMIUse = DefMI;
4627 return MIB;
4628 }
4629 }
4630 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4631 if (!Src0Literal &&
4632 (ImmOpt = getImmOrMaterializedImm(MRI, *Src1, &DefMI))) {
4633 if (pseudoToMCOpcode(NewOpc) != -1) {
4634 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4635 .add(*Dst)
4636 .add(*Src0)
4637 .addImm(*ImmOpt)
4638 .add(*Src2)
4639 .setMIFlags(MI.getFlags());
4640 U.RemoveMIUse = DefMI;
4641 return MIB;
4642 }
4643 }
4644 if ((ImmOpt = getImmOrMaterializedImm(MRI, *Src0, &DefMI))) {
4645 Imm = *ImmOpt;
4646 if (pseudoToMCOpcode(NewOpc) != -1 &&
4648 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4649 Src1)) {
4650 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4651 .add(*Dst)
4652 .add(*Src1)
4653 .addImm(Imm)
4654 .add(*Src2)
4655 .setMIFlags(MI.getFlags());
4656 U.RemoveMIUse = DefMI;
4657 return MIB;
4658 }
4659 }
4660 }
4661
4662 // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
4663 // if VOP3 does not allow a literal operand.
4664 if (Src0Literal && !ST.hasVOP3Literal())
4665 return nullptr;
4666
4667 unsigned NewOpc = getNewFMAInst(ST, Opc);
4668
4669 if (pseudoToMCOpcode(NewOpc) == -1)
4670 return nullptr;
4671
4672 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4673 .add(*Dst)
4674 .addImm(Src0Mods ? Src0Mods->getImm() : 0)
4675 .add(*Src0)
4676 .addImm(Src1Mods ? Src1Mods->getImm() : 0)
4677 .add(*Src1)
4678 .addImm(Src2Mods ? Src2Mods->getImm() : 0)
4679 .add(*Src2)
4680 .addImm(Clamp ? Clamp->getImm() : 0)
4681 .addImm(Omod ? Omod->getImm() : 0)
4682 .setMIFlags(MI.getFlags());
4683 if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
4684 MIB.addImm(OpSel ? OpSel->getImm() : 0);
4685 return MIB;
4686}
4687
4688// It's not generally safe to move VALU instructions across these since it will
4689// start using the register as a base index rather than directly.
4690// XXX - Why isn't hasSideEffects sufficient for these?
4692 switch (MI.getOpcode()) {
4693 case AMDGPU::S_SET_GPR_IDX_ON:
4694 case AMDGPU::S_SET_GPR_IDX_MODE:
4695 case AMDGPU::S_SET_GPR_IDX_OFF:
4696 return true;
4697 default:
4698 return false;
4699 }
4700}
4701
4703 const MachineBasicBlock *MBB,
4704 const MachineFunction &MF) const {
4705 // Skipping the check for SP writes in the base implementation. The reason it
4706 // was added was apparently due to compile time concerns.
4707 //
4708 // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
4709 // but is probably avoidable.
4710
4711 // Copied from base implementation.
4712 // Terminators and labels can't be scheduled around.
4713 if (MI.isTerminator() || MI.isPosition())
4714 return true;
4715
4716 // INLINEASM_BR can jump to another block
4717 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4718 return true;
4719
4720 if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
4721 return true;
4722
4723 // Target-independent instructions do not have an implicit-use of EXEC, even
4724 // when they operate on VGPRs. Treating EXEC modifications as scheduling
4725 // boundaries prevents incorrect movements of such instructions.
4726 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4727 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4728 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4729 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4730 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4732}
4733
4735 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4736 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4737 Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
4738}
4739
4741 // Instructions that access scratch use FLAT encoding or BUF encodings.
4742 if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
4743 return false;
4744
4745 // SCRATCH instructions always access scratch.
4746 if (isFLATScratch(MI))
4747 return true;
4748
4749 // If FLAT_SCRATCH registers are not initialized, we can never access scratch
4750 // via the aperture.
4751 if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
4752 return false;
4753
4754 // If there are no memory operands then conservatively assume the flat
4755 // operation may access scratch.
4756 if (MI.memoperands_empty())
4757 return true;
4758
4759 // See if any memory operand specifies an address space that involves scratch.
4760 return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
4761 unsigned AS = Memop->getAddrSpace();
4762 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4763 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4764 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4765 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4766 }
4767 return AS == AMDGPUAS::PRIVATE_ADDRESS;
4768 });
4769}
4770
4772 assert(isFLAT(MI));
4773
4774 // All flat instructions use the VMEM counter except prefetch.
4775 if (!usesVM_CNT(MI))
4776 return false;
4777
4778 // If there are no memory operands then conservatively assume the flat
4779 // operation may access VMEM.
4780 if (MI.memoperands_empty())
4781 return true;
4782
4783 // See if any memory operand specifies an address space that involves VMEM.
4784 // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
4785 // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
4786 // (GDS) address space is not supported by flat operations. Therefore, simply
4787 // return true unless only the LDS address space is found.
4788 for (const MachineMemOperand *Memop : MI.memoperands()) {
4789 unsigned AS = Memop->getAddrSpace();
4791 if (AS != AMDGPUAS::LOCAL_ADDRESS)
4792 return true;
4793 }
4794
4795 return false;
4796}
4797
4799 bool TgSplit) const {
4800 assert(isFLAT(MI));
4801
4802 // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
4803 if (!usesLGKM_CNT(MI))
4804 return false;
4805
4806 // If in tgsplit mode then there can be no use of LDS.
4807 if (TgSplit)
4808 return false;
4809
4810 // If there are no memory operands then conservatively assume the flat
4811 // operation may access LDS.
4812 if (MI.memoperands_empty())
4813 return true;
4814
4815 // See if any memory operand specifies an address space that involves LDS.
4816 for (const MachineMemOperand *Memop : MI.memoperands()) {
4817 unsigned AS = Memop->getAddrSpace();
4819 return true;
4820 }
4821
4822 return false;
4823}
4824
4826 // Skip the full operand and register alias search modifiesRegister
4827 // does. There's only a handful of instructions that touch this, it's only an
4828 // implicit def, and doesn't alias any other registers.
4829 return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
4830}
4831
4833 unsigned Opcode = MI.getOpcode();
4834
4835 if (MI.mayStore() && isSMRD(MI))
4836 return true; // scalar store or atomic
4837
4838 // This will terminate the function when other lanes may need to continue.
4839 if (MI.isReturn())
4840 return true;
4841
4842 // These instructions cause shader I/O that may cause hardware lockups
4843 // when executed with an empty EXEC mask.
4844 //
4845 // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
4846 // EXEC = 0, but checking for that case here seems not worth it
4847 // given the typical code patterns.
4848 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4849 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4850 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4851 Opcode == AMDGPU::S_SETHALT)
4852 return true;
4853
4854 if (MI.isCall() || MI.isInlineAsm())
4855 return true; // conservative assumption
4856
4857 // V_PERM_PK16 must issue with EXEC != 0 so its follower (or an inserted
4858 // V_NOP) actually runs on the VALU pipe. Returning true here keeps the
4859 // s_cbranch_execz that skips this region when EXEC is empty.
4860 if (ST.hasVPermPk16Hazard() && isVPermPk16(Opcode))
4861 return true;
4862
4863 // Assume that barrier interactions are only intended with active lanes.
4864 if (isBarrier(Opcode))
4865 return true;
4866
4867 // A mode change is a scalar operation that influences vector instructions.
4869 return true;
4870
4871 // These are like SALU instructions in terms of effects, so it's questionable
4872 // whether we should return true for those.
4873 //
4874 // However, executing them with EXEC = 0 causes them to operate on undefined
4875 // data, which we avoid by returning true here.
4876 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4877 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4878 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4879 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4880 return true;
4881
4882 return false;
4883}
4884
4886 const MachineInstr &MI) const {
4887 if (MI.isMetaInstruction())
4888 return false;
4889
4890 // This won't read exec if this is an SGPR->SGPR copy.
4891 if (MI.isCopyLike()) {
4892 if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
4893 return true;
4894
4895 // Make sure this isn't copying exec as a normal operand
4896 return MI.readsRegister(AMDGPU::EXEC, &RI);
4897 }
4898
4899 // Make a conservative assumption about the callee.
4900 if (MI.isCall())
4901 return true;
4902
4903 // Be conservative with any unhandled generic opcodes.
4904 if (!isTargetSpecificOpcode(MI.getOpcode()))
4905 return true;
4906
4907 return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
4908}
4909
4911 switch (Imm.getBitWidth()) {
4912 case 1: // This likely will be a condition code mask.
4913 return true;
4914
4915 case 32:
4916 return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
4917 ST.hasInv2PiInlineImm());
4918 case 64:
4919 return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
4920 ST.hasInv2PiInlineImm());
4921 case 16:
4922 return ST.has16BitInsts() &&
4923 AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
4924 ST.hasInv2PiInlineImm());
4925 default:
4926 llvm_unreachable("invalid bitwidth");
4927 }
4928}
4929
4931 APInt IntImm = Imm.bitcastToAPInt();
4932 int64_t IntImmVal = IntImm.getSExtValue();
4933 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4934 switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
4935 default:
4936 llvm_unreachable("invalid fltSemantics");
4939 return isInlineConstant(IntImm);
4941 return ST.has16BitInsts() &&
4942 AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
4944 return ST.has16BitInsts() &&
4945 AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
4946 }
4947}
4948
4949bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
4950 // MachineOperand provides no way to tell the true operand size, since it only
4951 // records a 64-bit value. We need to know the size to determine if a 32-bit
4952 // floating point immediate bit pattern is legal for an integer immediate. It
4953 // would be for any 32-bit integer operand, but would not be for a 64-bit one.
4954 switch (OperandType) {
4964 int32_t Trunc = static_cast<int32_t>(Imm);
4965 return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
4966 }
4974 return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
4977 // We would expect inline immediates to not be concerned with an integer/fp
4978 // distinction. However, in the case of 16-bit integer operations, the
4979 // "floating point" values appear to not work. It seems read the low 16-bits
4980 // of 32-bit immediates, which happens to always work for the integer
4981 // values.
4982 //
4983 // See llvm bugzilla 46302.
4984 //
4985 // TODO: Theoretically we could use op-sel to use the high bits of the
4986 // 32-bit FP values.
4995 return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
5000 return false;
5003 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
5004 // A few special case instructions have 16-bit operands on subtargets
5005 // where 16-bit instructions are not legal.
5006 // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
5007 // constants in these cases
5008 int16_t Trunc = static_cast<int16_t>(Imm);
5009 return ST.has16BitInsts() &&
5010 AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
5011 }
5012
5013 return false;
5014 }
5017 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
5018 int16_t Trunc = static_cast<int16_t>(Imm);
5019 return ST.has16BitInsts() &&
5020 AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
5021 }
5022 return false;
5023 }
5028 return false;
5030 return isLegalAV64PseudoImm(Imm);
5033 // Always embedded in the instruction for free.
5034 return true;
5044 // Just ignore anything else.
5045 return false;
5046 default:
5047 llvm_unreachable("invalid operand type");
5048 }
5049}
5050
5051static bool compareMachineOp(const MachineOperand &Op0,
5052 const MachineOperand &Op1) {
5053 if (Op0.getType() != Op1.getType())
5054 return false;
5055
5056 switch (Op0.getType()) {
5058 return Op0.getReg() == Op1.getReg();
5060 return Op0.getImm() == Op1.getImm();
5061 default:
5062 llvm_unreachable("Didn't expect to be comparing these operand types");
5063 }
5064}
5065
5067 const MCOperandInfo &OpInfo) const {
5068 if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
5069 return true;
5070
5071 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5072 return false;
5073
5074 if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
5075 return true;
5076
5077 return ST.hasVOP3Literal();
5078}
5079
5080bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5081 int64_t ImmVal) const {
5082 const unsigned Opc = InstDesc.getOpcode();
5083 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
5084 if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
5085 OpNo == static_cast<unsigned>(Src1Idx))
5086 return false;
5087
5088 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5089 if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
5090 if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5091 OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
5092 AMDGPU::OpName::src2))
5093 return false;
5094
5095 if (ST.hasBF16InlineConstFromUpperFP32() && isVOP1(Opc)) {
5096 if ((OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_BF16 ||
5097 OpInfo.OperandType == AMDGPU::OPERAND_REG_INLINE_C_BF16) &&
5098 isInlineConstant(ImmVal, OpInfo.OperandType))
5099 return false;
5100 }
5101
5102 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5103 }
5104
5105 return isLiteralOperandLegal(InstDesc, OpInfo);
5106}
5107
5108bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5109 const MachineOperand &MO) const {
5110 if (MO.isImm())
5111 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
5112
5113 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
5114 "unexpected imm-like operand kind");
5115 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5116 return isLiteralOperandLegal(InstDesc, OpInfo);
5117}
5118
5120 // 2 32-bit inline constants packed into one.
5121 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
5122 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
5123}
5124
5125bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
5126 // GFX90A does not have V_MUL_LEGACY_F32_e32.
5127 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5128 return false;
5129
5130 int Op32 = AMDGPU::getVOPe32(Opcode);
5131 if (Op32 == -1)
5132 return false;
5133
5134 return pseudoToMCOpcode(Op32) != -1;
5135}
5136
5137/// Return true if \p MI is a VALU comparison, i.e. an instruction that writes
5138/// a lane mask with one bit per lane, and zeroes the bits of lanes that were
5139/// inactive when it executed.
5140///
5141/// TODO: Also handle the sdst result of V_ADD_CO_U32 and V_SUB_CO_U32 and
5142/// V_DIV_SCALE_F32.
5143static bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI) {
5144 if (TII.isVOPC(MI))
5145 return true;
5146 int Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5147 return Op32 != -1 && TII.isVOPC(Op32);
5148}
5149
5151 const MachineRegisterInfo &MRI,
5152 unsigned Depth) const {
5153 assert(MRI.isSSA() && "isMaskedByExec requires SSA form");
5155 const MachineBasicBlock *MBB = Use.getParent();
5156
5157 // EXEC itself is trivially masked by EXEC.
5158 if (Reg == LMC.ExecReg)
5159 return true;
5160
5161 // Maximum depth of the def-use walk.
5162 constexpr unsigned MaxDepth = 6;
5163 if (Depth >= MaxDepth || !Reg.isVirtual())
5164 return false;
5165
5166 // Only look at definitions that can execute under the same EXEC mask as the
5167 // use.
5168 const MachineInstr *Def = MRI.getVRegDef(Reg);
5169 if (!Def || Def->getParent() != MBB)
5170 return false;
5171
5172 if (isVCmp(*this, *Def))
5173 return true;
5174
5175 // Recurse into an operand, which must be a whole register to say anything
5176 // about the whole lane mask.
5177 auto Recurse = [&](unsigned OpIdx) {
5178 const MachineOperand &MO = Def->getOperand(OpIdx);
5179 return MO.isReg() && !MO.getSubReg() &&
5180 isMaskedByExec(MO.getReg(), Use, MRI, Depth + 1);
5181 };
5182
5183 unsigned Opc = Def->getOpcode();
5184 if (Opc == AMDGPU::COPY && Recurse(1))
5185 return true;
5186 if (Opc == LMC.AndOpc && (Recurse(1) || Recurse(2)))
5187 return true;
5188 if (Opc == LMC.AndN2Opc && Recurse(1))
5189 return true;
5190 if ((Opc == LMC.OrOpc || Opc == LMC.XorOpc) && Recurse(1) && Recurse(2))
5191 return true;
5192 // TODO: Sometimes we encounter "reg = S_CSELECT -1, 0". If Reg has no other
5193 // uses this could be optimized to "reg = S_CSELECT $exec, 0".
5194
5195 return false;
5196}
5197
5198bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
5199 // The src0_modifier operand is present on all instructions
5200 // that have modifiers.
5201
5202 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
5203}
5204
5206 AMDGPU::OpName OpName) const {
5207 const MachineOperand *Mods = getNamedOperand(MI, OpName);
5208 return Mods && Mods->getImm();
5209}
5210
5212 return any_of(ModifierOpNames,
5213 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
5214}
5215
5217 const MachineRegisterInfo &MRI) const {
5218 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5219 // Can't shrink instruction with three operands.
5220 if (Src2) {
5221 switch (MI.getOpcode()) {
5222 default: return false;
5223
5224 case AMDGPU::V_ADDC_U32_e64:
5225 case AMDGPU::V_SUBB_U32_e64:
5226 case AMDGPU::V_SUBBREV_U32_e64: {
5227 const MachineOperand *Src1
5228 = getNamedOperand(MI, AMDGPU::OpName::src1);
5229 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
5230 return false;
5231 // Additional verification is needed for sdst/src2.
5232 return true;
5233 }
5234 case AMDGPU::V_MAC_F16_e64:
5235 case AMDGPU::V_MAC_F32_e64:
5236 case AMDGPU::V_MAC_LEGACY_F32_e64:
5237 case AMDGPU::V_FMAC_F16_e64:
5238 case AMDGPU::V_FMAC_F16_t16_e64:
5239 case AMDGPU::V_FMAC_F16_fake16_e64:
5240 case AMDGPU::V_FMAC_F32_e64:
5241 case AMDGPU::V_FMAC_F64_e64:
5242 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5243 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
5244 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
5245 return false;
5246 break;
5247
5248 case AMDGPU::V_CNDMASK_B32_e64:
5249 break;
5250 }
5251 }
5252
5253 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
5254 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5255 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
5256 return false;
5257
5258 // Make sure src0 isn't using any modifiers.
5259 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
5260 return false;
5261
5262 // Can it be shrunk to a valid 32 bit opcode?
5263 if (!hasVALU32BitEncoding(MI.getOpcode()))
5264 return false;
5265
5266 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
5267 if (Src0 && Src0->isImm()) {
5268 unsigned Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5269 if (!isImmOperandLegal(
5270 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5271 *Src0))
5272 return false;
5273 }
5274
5275 // Check output modifiers
5276 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
5277 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
5278 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
5279 // TODO: Can we avoid checking bound_ctrl/fi here?
5280 // They are only used by permlane*_swap special case.
5281 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
5282 !hasModifiersSet(MI, AMDGPU::OpName::fi);
5283}
5284
5285// Set VCC operand with all flags from \p Orig, except for setting it as
5286// implicit.
5288 const MachineOperand &Orig) {
5289
5290 for (MachineOperand &Use : MI.implicit_operands()) {
5291 if (Use.isUse() &&
5292 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
5293 Use.setIsUndef(Orig.isUndef());
5294 Use.setIsKill(Orig.isKill());
5295 return;
5296 }
5297 }
5298}
5299
5301 unsigned Op32) const {
5302 MachineBasicBlock *MBB = MI.getParent();
5303
5304 const MCInstrDesc &Op32Desc = get(Op32);
5305 MachineInstrBuilder Inst32 =
5306 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
5307 .setMIFlags(MI.getFlags());
5308
5309 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
5310 // For VOPC instructions, this is replaced by an implicit def of vcc.
5311
5312 // We assume the defs of the shrunk opcode are in the same order, and the
5313 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
5314 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
5315 Inst32.add(MI.getOperand(I));
5316
5317 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5318
5319 int Idx = MI.getNumExplicitDefs();
5320 for (const MachineOperand &Use : MI.explicit_uses()) {
5321 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
5323 continue;
5324
5325 if (&Use == Src2) {
5326 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5327 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
5328 // replaced with an implicit read of vcc or vcc_lo. The implicit read
5329 // of vcc was already added during the initial BuildMI, but we
5330 // 1) may need to change vcc to vcc_lo to preserve the original register
5331 // 2) have to preserve the original flags.
5332 copyFlagsToImplicitVCC(*Inst32, *Src2);
5333 continue;
5334 }
5335 }
5336
5337 Inst32.add(Use);
5338 }
5339
5340 // FIXME: Losing implicit operands
5341 fixImplicitOperands(*Inst32);
5342
5343 // The explicit carry/result def is dropped in favor of an implicit VCC def;
5344 // preserve the dead flag.
5345 const MachineOperand *OldSDst = getNamedOperand(MI, AMDGPU::OpName::sdst);
5346 if (OldSDst && OldSDst->isDead()) {
5347 if (MachineOperand *NewVCC =
5348 Inst32->findRegisterDefOperand(RI.getVCC(), &RI))
5349 NewVCC->setIsDead();
5350 }
5351
5352 return Inst32;
5353}
5354
5356 // Null is free
5357 Register Reg = RegOp.getReg();
5358 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5359 return false;
5360
5361 // SGPRs use the constant bus
5362
5363 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
5364 // physical register operands should also count, except for exec.
5365 if (RegOp.isImplicit())
5366 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5367
5368 // SGPRs use the constant bus
5369 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5370 AMDGPU::SReg_64RegClass.contains(Reg);
5371}
5372
5374 const MachineRegisterInfo &MRI) const {
5375 Register Reg = RegOp.getReg();
5376 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5377 : physRegUsesConstantBus(RegOp);
5378}
5379
5381 const MachineOperand &MO,
5382 const MCOperandInfo &OpInfo) const {
5383 // Literal constants use the constant bus.
5384 if (!MO.isReg())
5385 return !isInlineConstant(MO, OpInfo);
5386
5387 Register Reg = MO.getReg();
5388 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5390}
5391
5393 for (const MachineOperand &MO : MI.implicit_operands()) {
5394 // We only care about reads.
5395 if (MO.isDef())
5396 continue;
5397
5398 switch (MO.getReg()) {
5399 case AMDGPU::VCC:
5400 case AMDGPU::VCC_LO:
5401 case AMDGPU::VCC_HI:
5402 case AMDGPU::M0:
5403 case AMDGPU::FLAT_SCR:
5404 return MO.getReg();
5405
5406 default:
5407 break;
5408 }
5409 }
5410
5411 return Register();
5412}
5413
5414static bool shouldReadExec(const MachineInstr &MI) {
5415 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5416 switch (MI.getOpcode()) {
5417 case AMDGPU::V_READLANE_B32:
5418 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5419 case AMDGPU::V_WRITELANE_B32:
5420 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5421 return false;
5422 }
5423
5424 return true;
5425 }
5426
5427 if (MI.isPreISelOpcode() ||
5428 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5431 return false;
5432
5433 return true;
5434}
5435
5436static bool isRegOrFI(const MachineOperand &MO) {
5437 return MO.isReg() || MO.isFI();
5438}
5439
5440static bool isSubRegOf(const SIRegisterInfo &TRI,
5441 const MachineOperand &SuperVec,
5442 const MachineOperand &SubReg) {
5443 if (SubReg.getReg().isPhysical())
5444 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5445
5446 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5447 SubReg.getReg() == SuperVec.getReg();
5448}
5449
5450// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5451bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5452 const MachineRegisterInfo &MRI,
5453 StringRef &ErrInfo) const {
5454 Register DstReg = MI.getOperand(0).getReg();
5455 Register SrcReg = MI.getOperand(1).getReg();
5456 // This is a check for copy from vector register to SGPR
5457 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5458 ErrInfo = "illegal copy from vector register to SGPR";
5459 return false;
5460 }
5461 return true;
5462}
5463
5465 StringRef &ErrInfo) const {
5466 uint32_t Opcode = MI.getOpcode();
5467 const MachineFunction *MF = MI.getMF();
5468 const MachineRegisterInfo &MRI = MF->getRegInfo();
5469
5470 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5471 // Find a better property to recognize the point where instruction selection
5472 // is just done.
5473 // We can only enforce this check after SIFixSGPRCopies pass so that the
5474 // illegal copies are legalized and thereafter we don't expect a pass
5475 // inserting similar copies.
5476 if (!MRI.isSSA() && MI.isCopy())
5477 return verifyCopy(MI, MRI, ErrInfo);
5478
5479 if (SIInstrInfo::isGenericOpcode(Opcode))
5480 return true;
5481
5482 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5483 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5484 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5485 int Src3Idx = -1;
5486 if (Src0Idx == -1) {
5487 // VOPD V_DUAL_* instructions use different operand names.
5488 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5489 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5490 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5491 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5492 }
5493
5494 // Make sure the number of operands is correct.
5495 const MCInstrDesc &Desc = get(Opcode);
5496 if (!Desc.isVariadic() &&
5497 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5498 ErrInfo = "Instruction has wrong number of operands.";
5499 return false;
5500 }
5501
5502 if (MI.isInlineAsm()) {
5503 // Verify register classes for inlineasm constraints.
5504 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5505 I != E; ++I) {
5506 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5507 if (!RC)
5508 continue;
5509
5510 const MachineOperand &Op = MI.getOperand(I);
5511 if (!Op.isReg())
5512 continue;
5513
5514 Register Reg = Op.getReg();
5515 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5516 ErrInfo = "inlineasm operand has incorrect register class.";
5517 return false;
5518 }
5519 }
5520
5521 return true;
5522 }
5523
5524 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5525 ErrInfo = "missing memory operand from image instruction.";
5526 return false;
5527 }
5528
5529 // Make sure the register classes are correct.
5530 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5531 const MachineOperand &MO = MI.getOperand(i);
5532 if (MO.isFPImm()) {
5533 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5534 "all fp values to integers.";
5535 return false;
5536 }
5537
5538 const MCOperandInfo &OpInfo = Desc.operands()[i];
5539
5540 switch (OpInfo.OperandType) {
5542 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5543 ErrInfo = "Illegal immediate value for operand.";
5544 return false;
5545 }
5546 break;
5560 break;
5574 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5575 ErrInfo = "Illegal immediate value for operand.";
5576 return false;
5577 }
5578 break;
5579 }
5584 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5585 !isInlineConstant(MI, i) &&
5587 OpInfo.OperandType ==
5589 ErrInfo = "illegal 64-bit immediate value for operand.";
5590 return false;
5591 }
5592 break;
5595 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5596 ErrInfo = "Expected inline constant for operand.";
5597 return false;
5598 }
5599 break;
5602 break;
5607 // Check if this operand is an immediate.
5608 // FrameIndex operands will be replaced by immediates, so they are
5609 // allowed.
5610 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5611 ErrInfo = "Expected immediate, but got non-immediate";
5612 return false;
5613 }
5614 break;
5618 break;
5619 default:
5620 if (OpInfo.isGenericType())
5621 continue;
5622 break;
5623 }
5624 }
5625
5626 // Verify SDWA
5627 if (isSDWA(MI)) {
5628 if (!ST.hasSDWA()) {
5629 ErrInfo = "SDWA is not supported on this target";
5630 return false;
5631 }
5632
5633 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5634 AMDGPU::OpName::dst_sel}) {
5635 const MachineOperand *MO = getNamedOperand(MI, Op);
5636 if (!MO)
5637 continue;
5638 int64_t Imm = MO->getImm();
5640 ErrInfo = "Invalid SDWA selection";
5641 return false;
5642 }
5643 }
5644
5645 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5646
5647 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5648 if (OpIdx == -1)
5649 continue;
5650 const MachineOperand &MO = MI.getOperand(OpIdx);
5651
5652 if (!ST.hasSDWAScalar()) {
5653 // Only VGPRS on VI
5654 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5655 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5656 return false;
5657 }
5658 } else {
5659 // No immediates on GFX9
5660 if (!MO.isReg()) {
5661 ErrInfo =
5662 "Only reg allowed as operands in SDWA instructions on GFX9+";
5663 return false;
5664 }
5665 }
5666 }
5667
5668 if (!ST.hasSDWAOmod()) {
5669 // No omod allowed on VI
5670 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5671 if (OMod != nullptr &&
5672 (!OMod->isImm() || OMod->getImm() != 0)) {
5673 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5674 return false;
5675 }
5676 }
5677
5678 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5679 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5680 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5681 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5682 const MachineOperand *Src0ModsMO =
5683 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5684 unsigned Mods = Src0ModsMO->getImm();
5685 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5686 Mods & SISrcMods::SEXT) {
5687 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5688 return false;
5689 }
5690 }
5691
5692 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5693 if (isVOPC(BasicOpcode)) {
5694 if (!ST.hasSDWASdst() && DstIdx != -1) {
5695 // Only vcc allowed as dst on VI for VOPC
5696 const MachineOperand &Dst = MI.getOperand(DstIdx);
5697 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5698 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5699 return false;
5700 }
5701 } else if (!ST.hasSDWAOutModsVOPC()) {
5702 // No clamp allowed on GFX9 for VOPC
5703 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5704 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5705 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5706 return false;
5707 }
5708
5709 // No omod allowed on GFX9 for VOPC
5710 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5711 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5712 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5713 return false;
5714 }
5715 }
5716 }
5717
5718 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5719 if (DstUnused && DstUnused->isImm() &&
5720 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5721 const MachineOperand &Dst = MI.getOperand(DstIdx);
5722 if (!Dst.isReg() || !Dst.isTied()) {
5723 ErrInfo = "Dst register should have tied register";
5724 return false;
5725 }
5726
5727 const MachineOperand &TiedMO =
5728 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5729 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5730 ErrInfo =
5731 "Dst register should be tied to implicit use of preserved register";
5732 return false;
5733 }
5734 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5735 ErrInfo = "Dst register should use same physical register as preserved";
5736 return false;
5737 }
5738 }
5739 }
5740
5741 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5742 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5743 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5744 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5745 return false;
5746 }
5747 if (Src1MO.isImm()) {
5748 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5749 return false;
5750 }
5751 }
5752
5753 // Verify MIMG / VIMAGE / VSAMPLE
5754 if (isImage(Opcode) && !MI.mayStore()) {
5755 // Ensure that the return type used is large enough for all the options
5756 // being used TFE/LWE require an extra result register.
5757 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5758 if (DMask) {
5759 uint64_t DMaskImm = DMask->getImm();
5760 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5761 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5762 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5763 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5764
5765 // Adjust for packed 16 bit values
5766 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5767 RegCount = divideCeil(RegCount, 2);
5768
5769 // Adjust if using LWE or TFE
5770 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5771 RegCount += 1;
5772
5773 const uint32_t DstIdx =
5774 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5775 const MachineOperand &Dst = MI.getOperand(DstIdx);
5776 if (Dst.isReg()) {
5777 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5778 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5779 if (RegCount > DstSize) {
5780 ErrInfo = "Image instruction returns too many registers for dst "
5781 "register class";
5782 return false;
5783 }
5784 }
5785 }
5786 }
5787
5788 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5789 if (isVALU(MI, /*AllowLDSDMA=*/false) &&
5790 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5791 unsigned ConstantBusCount = 0;
5792 bool UsesLiteral = false;
5793 const MachineOperand *LiteralVal = nullptr;
5794
5795 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5796 if (ImmIdx != -1) {
5797 ++ConstantBusCount;
5798 UsesLiteral = true;
5799 LiteralVal = &MI.getOperand(ImmIdx);
5800 }
5801
5802 SmallVector<Register, 2> SGPRsUsed;
5803 Register SGPRUsed;
5804
5805 // Only look at the true operands. Only a real operand can use the constant
5806 // bus, and we don't want to check pseudo-operands like the source modifier
5807 // flags.
5808 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5809 if (OpIdx == -1)
5810 continue;
5811 const MachineOperand &MO = MI.getOperand(OpIdx);
5812 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5813 if (MO.isReg()) {
5814 SGPRUsed = MO.getReg();
5815 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5816 ++ConstantBusCount;
5817 SGPRsUsed.push_back(SGPRUsed);
5818 }
5819 } else if (!MO.isFI()) { // Treat FI like a register.
5820 if (!UsesLiteral) {
5821 ++ConstantBusCount;
5822 UsesLiteral = true;
5823 LiteralVal = &MO;
5824 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5825 assert(isVOP2(MI) || isVOP3(MI));
5826 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5827 return false;
5828 }
5829 }
5830 }
5831 }
5832
5833 SGPRUsed = findImplicitSGPRRead(MI);
5834 if (SGPRUsed) {
5835 // Implicit uses may safely overlap true operands
5836 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5837 return !RI.regsOverlap(SGPRUsed, SGPR);
5838 })) {
5839 ++ConstantBusCount;
5840 SGPRsUsed.push_back(SGPRUsed);
5841 }
5842 }
5843
5844 // v_writelane_b32 is an exception from constant bus restriction:
5845 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5846 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5847 Opcode != AMDGPU::V_WRITELANE_B32) {
5848 ErrInfo = "VOP* instruction violates constant bus restriction";
5849 return false;
5850 }
5851
5852 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5853 ErrInfo = "VOP3 instruction uses literal";
5854 return false;
5855 }
5856 }
5857
5858 // Special case for writelane - this can break the multiple constant bus rule,
5859 // but still can't use more than one SGPR register
5860 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5861 unsigned SGPRCount = 0;
5862 Register SGPRUsed;
5863
5864 for (int OpIdx : {Src0Idx, Src1Idx}) {
5865 if (OpIdx == -1)
5866 break;
5867
5868 const MachineOperand &MO = MI.getOperand(OpIdx);
5869
5870 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5871 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5872 if (MO.getReg() != SGPRUsed)
5873 ++SGPRCount;
5874 SGPRUsed = MO.getReg();
5875 }
5876 }
5877 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5878 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5879 return false;
5880 }
5881 }
5882 }
5883
5884 // Verify misc. restrictions on specific instructions.
5885 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5886 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5887 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5888 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5889 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
5890 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5891 if (!compareMachineOp(Src0, Src1) &&
5892 !compareMachineOp(Src0, Src2)) {
5893 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
5894 return false;
5895 }
5896 }
5897 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
5898 SISrcMods::ABS) ||
5899 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
5900 SISrcMods::ABS) ||
5901 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
5902 SISrcMods::ABS)) {
5903 ErrInfo = "ABS not allowed in VOP3B instructions";
5904 return false;
5905 }
5906 }
5907
5908 if (isSOP2(MI) || isSOPC(MI)) {
5909 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5910 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5911
5912 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
5913 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
5914 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
5915 !Src0.isIdenticalTo(Src1)) {
5916 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
5917 return false;
5918 }
5919 }
5920
5921 if (isSOPK(MI)) {
5922 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
5923 if (Desc.isBranch()) {
5924 if (!Op->isMBB()) {
5925 ErrInfo = "invalid branch target for SOPK instruction";
5926 return false;
5927 }
5928 } else {
5929 uint64_t Imm = Op->getImm();
5930 if (sopkIsZext(Opcode)) {
5931 if (!isUInt<16>(Imm)) {
5932 ErrInfo = "invalid immediate for SOPK instruction";
5933 return false;
5934 }
5935 } else {
5936 if (!isInt<16>(Imm)) {
5937 ErrInfo = "invalid immediate for SOPK instruction";
5938 return false;
5939 }
5940 }
5941 }
5942 }
5943
5944 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5945 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5946 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5947 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5948 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5949 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5950
5951 const unsigned StaticNumOps =
5952 Desc.getNumOperands() + Desc.implicit_uses().size();
5953 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5954
5955 // Require additional implicit operands. This allows a fixup done by the
5956 // post RA scheduler where the main implicit operand is killed and
5957 // implicit-defs are added for sub-registers that remain live after this
5958 // instruction.
5959 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5960 ErrInfo = "missing implicit register operands";
5961 return false;
5962 }
5963
5964 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5965 if (IsDst) {
5966 if (!Dst->isUse()) {
5967 ErrInfo = "v_movreld_b32 vdst should be a use operand";
5968 return false;
5969 }
5970
5971 unsigned UseOpIdx;
5972 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5973 UseOpIdx != StaticNumOps + 1) {
5974 ErrInfo = "movrel implicit operands should be tied";
5975 return false;
5976 }
5977 }
5978
5979 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5980 const MachineOperand &ImpUse
5981 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5982 if (!ImpUse.isReg() || !ImpUse.isUse() ||
5983 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5984 ErrInfo = "src0 should be subreg of implicit vector use";
5985 return false;
5986 }
5987 }
5988
5989 // Make sure we aren't losing exec uses in the td files. This mostly requires
5990 // being careful when using let Uses to try to add other use registers.
5991 if (shouldReadExec(MI)) {
5992 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5993 ErrInfo = "VALU instruction does not implicitly read exec mask";
5994 return false;
5995 }
5996 }
5997
5998 if (isSMRD(MI)) {
5999 if (MI.mayStore() &&
6000 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
6001 // The register offset form of scalar stores may only use m0 as the
6002 // soffset register.
6003 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
6004 if (Soff && Soff->getReg() != AMDGPU::M0) {
6005 ErrInfo = "scalar stores must use m0 as offset register";
6006 return false;
6007 }
6008 }
6009 }
6010
6011 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
6012 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
6013 if (Offset->getImm() != 0) {
6014 ErrInfo = "subtarget does not support offsets in flat instructions";
6015 return false;
6016 }
6017 }
6018
6019 if (isDS(MI) && !ST.hasGDS()) {
6020 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
6021 if (GDSOp && GDSOp->getImm() != 0) {
6022 ErrInfo = "GDS is not supported on this subtarget";
6023 return false;
6024 }
6025 }
6026
6027 if (isImage(MI)) {
6028 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
6029 if (DimOp) {
6030 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
6031 AMDGPU::OpName::vaddr0);
6032 AMDGPU::OpName RSrcOpName =
6033 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
6034 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
6035 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
6036 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
6037 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
6038 const AMDGPU::MIMGDimInfo *Dim =
6040
6041 if (!Dim) {
6042 ErrInfo = "dim is out of range";
6043 return false;
6044 }
6045
6046 bool IsA16 = false;
6047 if (ST.hasR128A16()) {
6048 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
6049 IsA16 = R128A16->getImm() != 0;
6050 } else if (ST.hasA16()) {
6051 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
6052 IsA16 = A16->getImm() != 0;
6053 }
6054
6055 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
6056
6057 unsigned AddrWords =
6058 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
6059
6060 unsigned VAddrWords;
6061 if (IsNSA) {
6062 VAddrWords = RsrcIdx - VAddr0Idx;
6063 if (ST.hasPartialNSAEncoding() &&
6064 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
6065 unsigned LastVAddrIdx = RsrcIdx - 1;
6066 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
6067 }
6068 } else {
6069 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
6070 if (AddrWords > 12)
6071 AddrWords = 16;
6072 }
6073
6074 if (VAddrWords != AddrWords) {
6075 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
6076 << " but got " << VAddrWords << "\n");
6077 ErrInfo = "bad vaddr size";
6078 return false;
6079 }
6080 }
6081 }
6082
6083 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
6084 if (DppCt) {
6085 using namespace AMDGPU::DPP;
6086
6087 unsigned DC = DppCt->getImm();
6088 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6089 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6090 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6091 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6092 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6093 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6094 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6095 ErrInfo = "Invalid dpp_ctrl value";
6096 return false;
6097 }
6098 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6099 !ST.hasDPPWavefrontShifts()) {
6100 ErrInfo = "Invalid dpp_ctrl value: "
6101 "wavefront shifts are not supported on GFX10+";
6102 return false;
6103 }
6104 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6105 !ST.hasDPPBroadcasts()) {
6106 ErrInfo = "Invalid dpp_ctrl value: "
6107 "broadcasts are not supported on GFX10+";
6108 return false;
6109 }
6110 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6111 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
6112 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6113 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6114 !ST.hasGFX90AInsts()) {
6115 ErrInfo = "Invalid dpp_ctrl value: "
6116 "row_newbroadcast/row_share is not supported before "
6117 "GFX90A/GFX10";
6118 return false;
6119 }
6120 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6121 ErrInfo = "Invalid dpp_ctrl value: "
6122 "row_share and row_xmask are not supported before GFX10";
6123 return false;
6124 }
6125 }
6126
6127 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6129 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6130 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
6131 ErrInfo = "Invalid dpp_ctrl value: "
6132 "DP ALU dpp only support row_newbcast";
6133 return false;
6134 }
6135 }
6136
6137 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
6138 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
6139 AMDGPU::OpName DataName =
6140 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6141 const MachineOperand *Data = getNamedOperand(MI, DataName);
6142 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
6143 if (Data && !Data->isReg())
6144 Data = nullptr;
6145
6146 if (!ST.hasGFX90AInsts()) {
6147 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6148 (Data && RI.isAGPR(MRI, Data->getReg())) ||
6149 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
6150 ErrInfo = "Invalid register class: "
6151 "agpr loads and stores not supported on this GPU";
6152 return false;
6153 }
6154 }
6155 }
6156
6157 if (ST.needsAlignedVGPRs()) {
6158 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
6160 if (!Op)
6161 return true;
6162 Register Reg = Op->getReg();
6163 if (Reg.isPhysical())
6164 return !(RI.getHWRegIndex(Reg) & 1);
6165 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
6166 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6167 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
6168 };
6169
6170 if (isMIMG(MI)) {
6171 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6172 ErrInfo = "Subtarget requires even aligned vector registers "
6173 "for vaddr operand of image instructions";
6174 return false;
6175 }
6176 }
6177 }
6178
6179 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6180 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
6181 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6182 ErrInfo = "Invalid register class: "
6183 "v_accvgpr_write with an SGPR is not supported on this GPU";
6184 return false;
6185 }
6186 }
6187
6188 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6189 const MachineOperand &SrcOp = MI.getOperand(1);
6190 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
6191 ErrInfo = "pseudo expects only physical SGPRs";
6192 return false;
6193 }
6194 }
6195
6196 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
6197 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
6198 if (!ST.hasScaleOffset()) {
6199 ErrInfo = "Subtarget does not support offset scaling";
6200 return false;
6201 }
6202 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
6203 ErrInfo = "Instruction does not support offset scaling";
6204 return false;
6205 }
6206 }
6207 }
6208
6209 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6210 if (AMDGPU::isSingleSGPRReadInst(Opcode)) {
6211 for (unsigned I = 0; I < 3; ++I) {
6213 return false;
6214 }
6215 }
6216
6217 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
6218 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
6219 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
6220 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6221 &AMDGPU::SReg_64RegClass) ||
6222 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6223 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
6224 return false;
6225 }
6226 }
6227
6228 return true;
6229}
6230
6232 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
6233 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6234 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
6235 ? AMDGPU::COPY
6236 : AMDGPU::V_MOV_B32_e32;
6237 }
6238 return getVALUOp(MI.getOpcode());
6239}
6240
6241// It is more readable to list mapped opcodes on the same line.
6242// clang-format off
6243
6244unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
6245 switch (Opc) {
6246 default: return AMDGPU::INSTRUCTION_LIST_END;
6247 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
6248 case AMDGPU::COPY: return AMDGPU::COPY;
6249 case AMDGPU::PHI: return AMDGPU::PHI;
6250 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
6251 case AMDGPU::WQM: return AMDGPU::WQM;
6252 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
6253 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
6254 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
6255 case AMDGPU::S_ADD_I32:
6256 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6257 case AMDGPU::S_ADDC_U32:
6258 return AMDGPU::V_ADDC_U32_e32;
6259 case AMDGPU::S_SUB_I32:
6260 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6261 // FIXME: These are not consistently handled, and selected when the carry is
6262 // used.
6263 case AMDGPU::S_ADD_U32:
6264 return AMDGPU::V_ADD_CO_U32_e32;
6265 case AMDGPU::S_SUB_U32:
6266 return AMDGPU::V_SUB_CO_U32_e32;
6267 case AMDGPU::S_ADD_U64_PSEUDO:
6268 return AMDGPU::V_ADD_U64_PSEUDO;
6269 case AMDGPU::S_SUB_U64_PSEUDO:
6270 return AMDGPU::V_SUB_U64_PSEUDO;
6271 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
6272 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
6273 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
6274 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
6275 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
6276 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
6277 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
6278 case AMDGPU::S_XNOR_B32:
6279 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6280 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
6281 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
6282 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
6283 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
6284 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
6285 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
6286 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
6287 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
6288 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
6289 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
6290 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
6291 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
6292 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
6293 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
6294 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
6295 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
6296 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
6297 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
6298 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
6299 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
6300 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
6301 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
6302 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
6303 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
6304 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
6305 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
6306 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
6307 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
6308 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
6309 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
6310 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
6311 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
6312 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
6313 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
6314 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
6315 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
6316 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
6317 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
6318 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
6319 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
6320 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
6321 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
6322 case AMDGPU::S_CVT_F32_F16:
6323 case AMDGPU::S_CVT_HI_F32_F16:
6324 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6325 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6326 case AMDGPU::S_CVT_F16_F32:
6327 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6328 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6329 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
6330 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
6331 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
6332 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
6333 case AMDGPU::S_CEIL_F16:
6334 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6335 : AMDGPU::V_CEIL_F16_fake16_e64;
6336 case AMDGPU::S_FLOOR_F16:
6337 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6338 : AMDGPU::V_FLOOR_F16_fake16_e64;
6339 case AMDGPU::S_TRUNC_F16:
6340 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6341 : AMDGPU::V_TRUNC_F16_fake16_e64;
6342 case AMDGPU::S_RNDNE_F16:
6343 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6344 : AMDGPU::V_RNDNE_F16_fake16_e64;
6345 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6346 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6347 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6348 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6349 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6350 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6351 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6352 case AMDGPU::S_ADD_F16:
6353 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6354 : AMDGPU::V_ADD_F16_fake16_e64;
6355 case AMDGPU::S_SUB_F16:
6356 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6357 : AMDGPU::V_SUB_F16_fake16_e64;
6358 case AMDGPU::S_MIN_F16:
6359 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6360 : AMDGPU::V_MIN_F16_fake16_e64;
6361 case AMDGPU::S_MAX_F16:
6362 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6363 : AMDGPU::V_MAX_F16_fake16_e64;
6364 case AMDGPU::S_MINIMUM_F16:
6365 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6366 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6367 case AMDGPU::S_MAXIMUM_F16:
6368 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6369 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6370 case AMDGPU::S_MUL_F16:
6371 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6372 : AMDGPU::V_MUL_F16_fake16_e64;
6373 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6374 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6375 case AMDGPU::S_FMAC_F16:
6376 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6377 : AMDGPU::V_FMAC_F16_fake16_e64;
6378 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6379 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6380 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6381 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6382 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6383 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6384 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6385 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6386 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6387 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6388 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6389 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6390 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6391 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6392 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6393 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6394 case AMDGPU::S_CMP_LT_F16:
6395 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6396 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6397 case AMDGPU::S_CMP_EQ_F16:
6398 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6399 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6400 case AMDGPU::S_CMP_LE_F16:
6401 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6402 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6403 case AMDGPU::S_CMP_GT_F16:
6404 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6405 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6406 case AMDGPU::S_CMP_LG_F16:
6407 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6408 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6409 case AMDGPU::S_CMP_GE_F16:
6410 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6411 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6412 case AMDGPU::S_CMP_O_F16:
6413 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6414 : AMDGPU::V_CMP_O_F16_fake16_e64;
6415 case AMDGPU::S_CMP_U_F16:
6416 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6417 : AMDGPU::V_CMP_U_F16_fake16_e64;
6418 case AMDGPU::S_CMP_NGE_F16:
6419 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6420 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6421 case AMDGPU::S_CMP_NLG_F16:
6422 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6423 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6424 case AMDGPU::S_CMP_NGT_F16:
6425 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6426 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6427 case AMDGPU::S_CMP_NLE_F16:
6428 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6429 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6430 case AMDGPU::S_CMP_NEQ_F16:
6431 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6432 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6433 case AMDGPU::S_CMP_NLT_F16:
6434 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6435 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6436 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6437 case AMDGPU::V_S_EXP_F16_e64:
6438 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6439 : AMDGPU::V_EXP_F16_fake16_e64;
6440 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6441 case AMDGPU::V_S_LOG_F16_e64:
6442 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6443 : AMDGPU::V_LOG_F16_fake16_e64;
6444 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6445 case AMDGPU::V_S_RCP_F16_e64:
6446 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6447 : AMDGPU::V_RCP_F16_fake16_e64;
6448 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6449 case AMDGPU::V_S_RSQ_F16_e64:
6450 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6451 : AMDGPU::V_RSQ_F16_fake16_e64;
6452 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6453 case AMDGPU::V_S_SQRT_F16_e64:
6454 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6455 : AMDGPU::V_SQRT_F16_fake16_e64;
6456 }
6458 "Unexpected scalar opcode without corresponding vector one!");
6459}
6460
6461// clang-format on
6462
6466 const DebugLoc &DL, Register Reg,
6467 bool IsSCCLive,
6468 SlotIndexes *Indexes) const {
6469 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6470 const SIInstrInfo *TII = ST.getInstrInfo();
6472 if (IsSCCLive) {
6473 // Insert two move instructions, one to save the original value of EXEC and
6474 // the other to turn on all bits in EXEC. This is required as we can't use
6475 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6476 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6478 auto FlipExecMI =
6479 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6480 if (Indexes) {
6481 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6482 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6483 }
6484 } else {
6485 auto SaveExec =
6486 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6487 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6488 if (Indexes)
6489 Indexes->insertMachineInstrInMaps(*SaveExec);
6490 }
6491}
6492
6495 const DebugLoc &DL, Register Reg,
6496 SlotIndexes *Indexes) const {
6498 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6499 .addReg(Reg, RegState::Kill);
6500 if (Indexes)
6501 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6502}
6503
6507 "Not a whole wave func");
6508 MachineBasicBlock &MBB = *MF.begin();
6509 for (MachineInstr &MI : MBB)
6510 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6511 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6512 return &MI;
6513
6514 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6515}
6516
6518 unsigned OpNo) const {
6519 const MCInstrDesc &Desc = get(MI.getOpcode());
6520 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6521 Desc.operands()[OpNo].RegClass == -1) {
6522 Register Reg = MI.getOperand(OpNo).getReg();
6523
6524 if (Reg.isVirtual()) {
6525 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6526 return MRI.getRegClass(Reg);
6527 }
6528 return RI.getPhysRegBaseClass(Reg);
6529 }
6530
6531 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6532 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6533}
6534
6535// Convert VOP3 operand index to source number.
6536static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx) {
6537 constexpr AMDGPU::OpName OpNames[] = {
6538 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6539
6540 for (auto [I, OpName] : enumerate(OpNames)) {
6541 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6542 if (static_cast<unsigned>(SrcIdx) == OpIdx)
6543 return I;
6544 }
6545
6546 return UINT_MAX;
6547}
6548
6551 MachineBasicBlock *MBB = MI.getParent();
6552 MachineOperand &MO = MI.getOperand(OpIdx);
6553 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6554 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6555 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6556 unsigned Size = RI.getRegSizeInBits(*RC);
6557 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6558 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6559 : AMDGPU::V_MOV_B32_e32;
6560 if (MO.isReg())
6561 Opcode = AMDGPU::COPY;
6562 else if (RI.isSGPRClass(RC))
6563 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6564
6565 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6566 Register Reg = MRI.createVirtualRegister(VRC);
6567 DebugLoc DL = MBB->findDebugLoc(I);
6568
6569 if (Size == 128 && AMDGPU::isPackedSingleSGPR64BitInst(MI.getOpcode()) &&
6571 // Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
6572 // sources behave like OPSEL is set replicating low 64-bits into high. VGPR
6573 // sources in turn read actual 4 registers. To move operand from an SGPR to
6574 // a VGPR we need to replicate low half.
6575 // We also do not select immediates for these instructions so it always has
6576 // to be an SGPR register here.
6577 // Operands which are not legal as per isLegalSingleSGPRReadInstOperand()
6578 // sent here specifically to fix a non-splat SGPR and shall perform a full
6579 // copy.
6580
6581 const TargetRegisterClass *VRC64 = RI.getVGPRClassForBitWidth(64);
6582 Register Low64 = MRI.createVirtualRegister(VRC64);
6583 assert(MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()));
6584 BuildMI(*MBB, I, DL, get(TargetOpcode::COPY), Low64)
6585 .addReg(MO.getReg(), {}, AMDGPU::sub0_sub1);
6586 BuildMI(*MBB, I, DL, get(TargetOpcode::REG_SEQUENCE), Reg)
6587 .addReg(Low64)
6588 .addImm(AMDGPU::sub0_sub1)
6589 .addReg(Low64)
6590 .addImm(AMDGPU::sub2_sub3);
6591 } else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6592 BuildMI(*MBB, I, DL, get(Opcode), Reg)
6593 .addImm(0) // src0_modifiers
6594 .add(MO)
6595 .addImm(0); // op_sel
6596 } else {
6597 BuildMI(*MBB, I, DL, get(Opcode), Reg).add(MO);
6598 }
6599
6600 MO.ChangeToRegister(Reg, false);
6601}
6602
6605 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6606 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6607 if (!SuperReg.getReg().isVirtual())
6608 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6609
6610 MachineBasicBlock *MBB = MI->getParent();
6611 const DebugLoc &DL = MI->getDebugLoc();
6612 Register SubReg = MRI.createVirtualRegister(SubRC);
6613
6614 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6615 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6616 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6617 return SubReg;
6618}
6619
6622 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6623 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6624 if (Op.isImm()) {
6625 if (SubIdx == AMDGPU::sub0)
6626 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6627 if (SubIdx == AMDGPU::sub1)
6628 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6629
6630 llvm_unreachable("Unhandled register index for immediate");
6631 }
6632
6633 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6634 SubIdx, SubRC);
6635 return MachineOperand::CreateReg(SubReg, false);
6636}
6637
6638// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6639void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6640 assert(Inst.getNumExplicitOperands() == 3);
6641 MachineOperand Op1 = Inst.getOperand(1);
6642 Inst.removeOperand(1);
6643 Inst.addOperand(Op1);
6644}
6645
6647 const MCOperandInfo &OpInfo,
6648 const MachineOperand &MO) const {
6649 if (!MO.isReg())
6650 return false;
6651
6652 Register Reg = MO.getReg();
6653
6654 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6655 if (Reg.isPhysical())
6656 return DRC->contains(Reg);
6657
6658 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6659
6660 if (MO.getSubReg()) {
6661 const TargetRegisterClass *SuperRC =
6662 RI.getLargestLegalSuperClass(RC, MRI.getMF());
6663 if (!SuperRC)
6664 return false;
6665 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6666 }
6667
6668 return RI.getCommonSubClass(DRC, RC) != nullptr;
6669}
6670
6672 const MachineOperand &MO) const {
6673 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6674 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6675 unsigned Opc = MI.getOpcode();
6676
6677 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6678 if (MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
6679 AMDGPU::isSingleSGPRReadInst(MI.getOpcode()) &&
6681 &MO))
6682 return false;
6683
6684 if (!isLegalRegOperand(MRI, OpInfo, MO))
6685 return false;
6686
6687 // check Accumulate GPR operand
6688 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6689 if (IsAGPR && !ST.hasMAIInsts())
6690 return false;
6691 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6692 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6693 return false;
6694 // Atomics should have both vdst and vdata either vgpr or agpr.
6695 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6696 const int DataIdx = AMDGPU::getNamedOperandIdx(
6697 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6698 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6699 MI.getOperand(DataIdx).isReg() &&
6700 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6701 return false;
6702 if ((int)OpIdx == DataIdx) {
6703 if (VDstIdx != -1 &&
6704 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6705 return false;
6706 // DS instructions with 2 src operands also must have tied RC.
6707 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6708 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6709 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6710 return false;
6711 }
6712
6713 // Check V_ACCVGPR_WRITE_B32_e64
6714 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6715 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6716 RI.isSGPRReg(MRI, MO.getReg()))
6717 return false;
6718
6719 if (ST.hasFlatScratchHiInB64InstHazard() &&
6720 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6721 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6722 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6723 64)
6724 return false;
6725 }
6726 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6727 return false;
6728 }
6729 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6730 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6731 return false;
6732
6733 return true;
6734}
6735
6737 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6738 const MachineOperand *MO) const {
6739 constexpr unsigned NumOps = 3;
6740 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6741 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6742 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6743 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6744
6745 assert(SrcN < NumOps);
6746
6747 if (!MO) {
6748 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6749 if (SrcIdx == -1)
6750 return true;
6751 MO = &MI.getOperand(SrcIdx);
6752 }
6753
6754 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6755 return true;
6756
6757 int ModsIdx =
6758 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6759 if (ModsIdx == -1)
6760 return false;
6761
6762 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6763 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6764 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6765
6766 return !OpSel && !OpSelHi;
6767}
6768
6769// Check if V_PK_FMA_F32 does not have the invalid opsel conditions.
6771 if (!ST.hasPkF32InvalidOpSel() || MI.getOpcode() != AMDGPU::V_PK_FMA_F32)
6772 return true;
6773
6774 const MachineOperand *Src1Mods =
6775 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
6776 const MachineOperand *Src2Mods =
6777 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
6778
6779 auto HasOpSel0 = [](const MachineOperand *Mods) {
6780 return Mods->getImm() & SISrcMods::OP_SEL_0;
6781 };
6782
6783 // Illegal iff opsel[2:1] == 2'b01, 2'b10, or 2'b11
6784 return !HasOpSel0(Src1Mods) && !HasOpSel0(Src2Mods);
6785}
6786
6788 MachineRegisterInfo &MRI) const {
6789 assert(MI.getOpcode() == AMDGPU::V_PK_FMA_F32);
6790
6791 MachineBasicBlock &MBB = *MI.getParent();
6792 const DebugLoc &DL = MI.getDebugLoc();
6793
6794 MachineOperand *Srcs[3] = {getNamedOperand(MI, AMDGPU::OpName::src0),
6795 getNamedOperand(MI, AMDGPU::OpName::src1),
6796 getNamedOperand(MI, AMDGPU::OpName::src2)};
6797 const unsigned Mods[3] = {
6798 static_cast<unsigned>(
6799 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm()),
6800 static_cast<unsigned>(
6801 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm()),
6802 static_cast<unsigned>(
6803 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm())};
6804
6805 // extract op_sel / op_sel_hi
6806 bool OpSel[3][2];
6807 for (unsigned I = 0; I != 3; ++I) {
6808 OpSel[I][0] = Mods[I] & SISrcMods::OP_SEL_0;
6809 OpSel[I][1] = Mods[I] & SISrcMods::OP_SEL_1;
6810 }
6811
6812 // The packed op can read only one SGPR on the constant bus (limit is 1 on
6813 // gfx9), so all its SGPR sources are the same pair. Each scalar lane can also
6814 // read only one SGPR, but op_sel may make a lane read different halves of
6815 // that pair, e.g.
6816 // 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]
6817 // => v_fma_f32 v0, s0, 0, s1 / v_fma_f32 v1, s1, 0, s0
6818 // If so, copy the pair to a VGPR once before extracting the lanes, rather
6819 // than moving a scalar into a VGPR per lane.
6820 SmallVector<unsigned, 3> SGPRSrcs;
6821 bool DivergentSGPRs = false;
6822 for (unsigned I = 0; I != 3; ++I) {
6823 if (!Srcs[I]->isReg() || !RI.isSGPRReg(MRI, Srcs[I]->getReg()))
6824 continue;
6825 if (!SGPRSrcs.empty()) {
6826 unsigned First = SGPRSrcs.front();
6827 assert(Srcs[I]->getReg() == Srcs[First]->getReg() &&
6828 Srcs[I]->getSubReg() == Srcs[First]->getSubReg() &&
6829 "constant bus limit allows only one SGPR source");
6830 DivergentSGPRs |=
6831 OpSel[I][0] != OpSel[First][0] || OpSel[I][1] != OpSel[First][1];
6832 }
6833 SGPRSrcs.push_back(I);
6834 }
6835
6836 if (DivergentSGPRs) {
6837 unsigned First = SGPRSrcs.front();
6838 legalizeOpWithMove(MI, MI.getOperandNo(Srcs[First]));
6839 for (unsigned I : ArrayRef(SGPRSrcs).drop_front())
6840 Srcs[I]->ChangeToRegister(Srcs[First]->getReg(), /*isDef=*/false);
6841 }
6842
6843 // Extract the low or high lane of a packed VOP3P source operand.
6844 auto ExtractLane = [&](MachineOperand &Op, bool UseSub1) -> MachineOperand {
6845 unsigned SubIdx = (Op.isReg() && UseSub1) ? AMDGPU::sub1 : AMDGPU::sub0;
6846 const TargetRegisterClass *RC =
6847 Op.isReg() ? MRI.getRegClass(Op.getReg()) : nullptr;
6848 const TargetRegisterClass *SubRC = !Op.isReg() ? nullptr
6849 : RI.isVGPR(MRI, Op.getReg())
6850 ? RI.getVGPRClassForBitWidth(32)
6851 : RI.getSGPRClassForBitWidth(32);
6852 return buildExtractSubRegOrImm(MI, MRI, Op, RC, SubIdx, SubRC);
6853 };
6854
6855 // neg_lo/neg_hi on the packed operand become a plain NEG modifier.
6856 auto LaneMods = [](unsigned Mods, bool Hi) -> unsigned {
6857 if (Hi)
6858 return (Mods & SISrcMods::NEG_HI) ? static_cast<unsigned>(SISrcMods::NEG)
6859 : 0u;
6860 return Mods & SISrcMods::NEG;
6861 };
6862
6863 auto BuildLane = [&](Register Dst, bool Hi) {
6864 MachineOperand L0 = ExtractLane(*Srcs[0], OpSel[0][Hi]);
6865 MachineOperand L1 = ExtractLane(*Srcs[1], OpSel[1][Hi]);
6866 MachineOperand L2 = ExtractLane(*Srcs[2], OpSel[2][Hi]);
6867 BuildMI(MBB, MI, DL, get(AMDGPU::V_FMA_F32_e64), Dst)
6868 .addImm(LaneMods(Mods[0], Hi))
6869 .add(L0)
6870 .addImm(LaneMods(Mods[1], Hi))
6871 .add(L1)
6872 .addImm(LaneMods(Mods[2], Hi))
6873 .add(L2)
6874 .addImm(0) // clamp
6875 .addImm(0); // omod
6876 };
6877
6878 const TargetRegisterClass *VGPR32 = RI.getVGPRClassForBitWidth(32);
6879 Register Lo = MRI.createVirtualRegister(VGPR32);
6880 Register Hi = MRI.createVirtualRegister(VGPR32);
6881 BuildLane(Lo, false);
6882 BuildLane(Hi, true);
6883
6884 Register Dst = getNamedOperand(MI, AMDGPU::OpName::vdst)->getReg();
6885 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
6886 .addReg(Lo)
6887 .addImm(AMDGPU::sub0)
6888 .addReg(Hi)
6889 .addImm(AMDGPU::sub1);
6890
6891 MI.eraseFromParent();
6892}
6893
6894bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
6895 const MachineOperand *MO) const {
6896 const MachineFunction &MF = *MI.getMF();
6897 const MachineRegisterInfo &MRI = MF.getRegInfo();
6898 const MCInstrDesc &InstDesc = MI.getDesc();
6899 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6900 int64_t RegClass = getOpRegClassID(OpInfo);
6901 const TargetRegisterClass *DefinedRC =
6902 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6903 if (!MO)
6904 MO = &MI.getOperand(OpIdx);
6905
6906 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6907
6908 if (isVALU(MI, /*AllowLDSDMA=*/false) && !IsInlineConst &&
6909 usesConstantBus(MRI, *MO, OpInfo)) {
6910 const MachineOperand *UsedLiteral = nullptr;
6911
6912 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6913 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6914
6915 // TODO: Be more permissive with frame indexes.
6916 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6917 if (!LiteralLimit--)
6918 return false;
6919
6920 UsedLiteral = MO;
6921 }
6922
6924 if (MO->isReg())
6925 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6926
6927 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6928 if (i == OpIdx)
6929 continue;
6930 const MachineOperand &Op = MI.getOperand(i);
6931 if (Op.isReg()) {
6932 if (Op.isUse()) {
6933 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6934 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6935 if (--ConstantBusLimit <= 0)
6936 return false;
6937 }
6938 }
6939 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6940 !isInlineConstant(Op, InstDesc.operands()[i])) {
6941 // The same literal may be used multiple times.
6942 if (!UsedLiteral)
6943 UsedLiteral = &Op;
6944 else if (UsedLiteral->isIdenticalTo(Op))
6945 continue;
6946
6947 if (!LiteralLimit--)
6948 return false;
6949 if (--ConstantBusLimit <= 0)
6950 return false;
6951 }
6952 }
6953 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6954 // There can be at most one literal operand, but it can be repeated.
6955 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6956 if (i == OpIdx)
6957 continue;
6958 const MachineOperand &Op = MI.getOperand(i);
6959 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6960 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6961 !Op.isIdenticalTo(*MO))
6962 return false;
6963
6964 // Do not fold a non-inlineable and non-register operand into an
6965 // instruction that already has a frame index. The frame index handling
6966 // code could not handle well when a frame index co-exists with another
6967 // non-register operand, unless that operand is an inlineable immediate.
6968 if (Op.isFI())
6969 return false;
6970 }
6971 }
6972
6973 if (MO->isReg()) {
6974 if (!DefinedRC)
6975 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6976 return isLegalRegOperand(MI, OpIdx, *MO);
6977 }
6978
6979 if (MO->isImm()) {
6980 uint64_t Imm = MO->getImm();
6981 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6982 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6983 bool Is64BitOp = Is64BitFPOp ||
6984 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6985 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6986 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6987 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6988 if (Is64BitOp &&
6989 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6990 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6991 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6992 return false;
6993
6994 // FIXME: We can use sign extended 64-bit literals, but only for signed
6995 // operands. At the moment we do not know if an operand is signed.
6996 // Such operand will be encoded as its low 32 bits and then either
6997 // correctly sign extended or incorrectly zero extended by HW.
6998 // If 64-bit literals are supported and the literal will be encoded
6999 // as full 64 bit we still can use it.
7000 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
7001 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
7002 return false;
7003 }
7004 }
7005
7006 // Handle non-register types that are treated like immediates.
7007 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
7008
7009 if (!DefinedRC) {
7010 // This operand expects an immediate.
7011 return true;
7012 }
7013
7014 return isImmOperandLegal(MI, OpIdx, *MO);
7015}
7016
7018 bool IsGFX950Only = ST.hasGFX950Insts();
7019 bool IsGFX940Only = ST.hasGFX940Insts();
7020
7021 if (!IsGFX950Only && !IsGFX940Only)
7022 return false;
7023
7024 if (!isVALU(MI, /*AllowLDSDMA=*/false))
7025 return false;
7026
7027 // V_COS, V_EXP, V_RCP, etc.
7028 if (isTRANS(MI))
7029 return true;
7030
7031 // DOT2, DOT2C, DOT4, etc.
7032 if (isDOT(MI))
7033 return true;
7034
7035 // MFMA, SMFMA
7036 if (isMFMA(MI))
7037 return true;
7038
7039 unsigned Opcode = MI.getOpcode();
7040 switch (Opcode) {
7041 case AMDGPU::V_CVT_PK_BF8_F32_e64:
7042 case AMDGPU::V_CVT_PK_FP8_F32_e64:
7043 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
7044 case AMDGPU::V_MQSAD_U32_U8_e64:
7045 case AMDGPU::V_PK_ADD_F16:
7046 case AMDGPU::V_PK_ADD_F32:
7047 case AMDGPU::V_PK_ADD_I16:
7048 case AMDGPU::V_PK_ADD_U16:
7049 case AMDGPU::V_PK_ASHRREV_I16:
7050 case AMDGPU::V_PK_FMA_F16:
7051 case AMDGPU::V_PK_FMA_F32:
7052 case AMDGPU::V_PK_FMAC_F16_e32:
7053 case AMDGPU::V_PK_FMAC_F16_e64:
7054 case AMDGPU::V_PK_LSHLREV_B16:
7055 case AMDGPU::V_PK_LSHRREV_B16:
7056 case AMDGPU::V_PK_MAD_I16:
7057 case AMDGPU::V_PK_MAD_U16:
7058 case AMDGPU::V_PK_MAX_F16:
7059 case AMDGPU::V_PK_MAX_I16:
7060 case AMDGPU::V_PK_MAX_U16:
7061 case AMDGPU::V_PK_MIN_F16:
7062 case AMDGPU::V_PK_MIN_I16:
7063 case AMDGPU::V_PK_MIN_U16:
7064 case AMDGPU::V_PK_MOV_B32:
7065 case AMDGPU::V_PK_MUL_F16:
7066 case AMDGPU::V_PK_MUL_F32:
7067 case AMDGPU::V_PK_MUL_LO_U16:
7068 case AMDGPU::V_PK_SUB_I16:
7069 case AMDGPU::V_PK_SUB_U16:
7070 case AMDGPU::V_QSAD_PK_U16_U8_e64:
7071 return true;
7072 default:
7073 return false;
7074 }
7075}
7076
7078 MachineInstr &MI) const {
7079 unsigned Opc = MI.getOpcode();
7080 const MCInstrDesc &InstrDesc = get(Opc);
7081
7082 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
7083 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7084
7085 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
7086 MachineOperand &Src1 = MI.getOperand(Src1Idx);
7087
7088 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
7089 // we need to only have one constant bus use before GFX10.
7090 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
7091 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
7092 RI.isSGPRReg(MRI, Src0.getReg()))
7093 legalizeOpWithMove(MI, Src0Idx);
7094
7095 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
7096 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
7097 // src0/src1 with V_READFIRSTLANE.
7098 if (Opc == AMDGPU::V_WRITELANE_B32) {
7099 const DebugLoc &DL = MI.getDebugLoc();
7100 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
7101 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7102 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7103 .add(Src0);
7104 Src0.ChangeToRegister(Reg, false);
7105 }
7106 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
7107 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7108 const DebugLoc &DL = MI.getDebugLoc();
7109 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7110 .add(Src1);
7111 Src1.ChangeToRegister(Reg, false);
7112 }
7113 return;
7114 }
7115
7116 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
7117 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
7118 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
7119 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
7120 legalizeOpWithMove(MI, Src2Idx);
7121 }
7122
7123 // VOP2 src0 instructions support all operand types, so we don't need to check
7124 // their legality. If src1 is already legal, we don't need to do anything.
7125 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
7126 return;
7127
7128 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
7129 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
7130 // select is uniform.
7131 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
7132 RI.isVGPR(MRI, Src1.getReg())) {
7133 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7134 const DebugLoc &DL = MI.getDebugLoc();
7135 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7136 .add(Src1);
7137 Src1.ChangeToRegister(Reg, false);
7138 return;
7139 }
7140
7141 // We do not use commuteInstruction here because it is too aggressive and will
7142 // commute if it is possible. We only want to commute here if it improves
7143 // legality. This can be called a fairly large number of times so don't waste
7144 // compile time pointlessly swapping and checking legality again.
7145 if (HasImplicitSGPR || !MI.isCommutable()) {
7146 legalizeOpWithMove(MI, Src1Idx);
7147 return;
7148 }
7149
7150 // If src0 can be used as src1, commuting will make the operands legal.
7151 // Otherwise we have to give up and insert a move.
7152 //
7153 // TODO: Other immediate-like operand kinds could be commuted if there was a
7154 // MachineOperand::ChangeTo* for them.
7155 if ((!Src1.isImm() && !Src1.isReg()) ||
7156 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
7157 legalizeOpWithMove(MI, Src1Idx);
7158 return;
7159 }
7160
7161 int CommutedOpc = commuteOpcode(MI);
7162 if (CommutedOpc == -1) {
7163 legalizeOpWithMove(MI, Src1Idx);
7164 return;
7165 }
7166
7167 MI.setDesc(get(CommutedOpc));
7168
7169 Register Src0Reg = Src0.getReg();
7170 unsigned Src0SubReg = Src0.getSubReg();
7171 bool Src0Kill = Src0.isKill();
7172
7173 if (Src1.isImm())
7174 Src0.ChangeToImmediate(Src1.getImm());
7175 else if (Src1.isReg()) {
7176 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
7177 Src0.setSubReg(Src1.getSubReg());
7178 } else
7179 llvm_unreachable("Should only have register or immediate operands");
7180
7181 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
7182 Src1.setSubReg(Src0SubReg);
7184}
7185
7186// Legalize VOP3 operands. All operand types are supported for any operand
7187// but only one literal constant and only starting from GFX10.
7189 MachineInstr &MI) const {
7190 unsigned Opc = MI.getOpcode();
7191
7192 int VOP3Idx[3] = {
7193 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
7194 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
7195 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
7196 };
7197
7198 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7199 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7200 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7201 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7202 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7203 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7204 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7205 // src1 and src2 must be scalar
7206 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
7207 const DebugLoc &DL = MI.getDebugLoc();
7208 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
7209 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7210 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7211 .add(Src1);
7212 Src1.ChangeToRegister(Reg, false);
7213 }
7214 if (VOP3Idx[2] != -1) {
7215 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
7216 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
7217 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7218 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7219 .add(Src2);
7220 Src2.ChangeToRegister(Reg, false);
7221 }
7222 }
7223 }
7224
7225 // Find the one SGPR operand we are allowed to use.
7226 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
7227 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7228 SmallDenseSet<unsigned> SGPRsUsed;
7229 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
7230 if (SGPRReg) {
7231 SGPRsUsed.insert(SGPRReg);
7232 --ConstantBusLimit;
7233 }
7234
7235 for (int Idx : VOP3Idx) {
7236 if (Idx == -1)
7237 break;
7238 MachineOperand &MO = MI.getOperand(Idx);
7239
7240 if (!MO.isReg()) {
7241 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
7242 continue;
7243
7244 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7245 --LiteralLimit;
7246 --ConstantBusLimit;
7247 continue;
7248 }
7249
7250 --LiteralLimit;
7251 --ConstantBusLimit;
7252 legalizeOpWithMove(MI, Idx);
7253 continue;
7254 }
7255
7256 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
7257 continue; // VGPRs are legal
7258
7259 // We can use one SGPR in each VOP3 instruction prior to GFX10
7260 // and two starting from GFX10.
7261 if (SGPRsUsed.count(MO.getReg()))
7262 continue;
7263 if (ConstantBusLimit > 0) {
7264 SGPRsUsed.insert(MO.getReg());
7265 --ConstantBusLimit;
7266 continue;
7267 }
7268
7269 // If we make it this far, then the operand is not legal and we must
7270 // legalize it.
7271 legalizeOpWithMove(MI, Idx);
7272 }
7273
7274 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
7275 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
7276 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
7277 Opc == AMDGPU::V_FMAC_F16_t16_e64) &&
7278 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
7279 legalizeOpWithMove(MI, VOP3Idx[2]);
7280
7281 // Fix the register class of single-sgpr-read instructions on gfx12+. See
7282 // SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
7284 for (unsigned I = 0; I < 3; ++I) {
7285 if (!isLegalSingleSGPRReadInstOperand(MRI, MI, /*SrcN=*/I))
7286 legalizeOpWithMove(MI, VOP3Idx[I]);
7287 }
7288 }
7289}
7290
7293 const TargetRegisterClass *DstRC /*=nullptr*/) const {
7294 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
7295 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
7296 if (DstRC)
7297 SRC = RI.getCommonSubClass(SRC, DstRC);
7298
7299 Register DstReg = MRI.createVirtualRegister(SRC);
7300 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7301
7302 if (RI.hasAGPRs(VRC)) {
7303 VRC = RI.getEquivalentVGPRClass(VRC);
7304 Register NewSrcReg = MRI.createVirtualRegister(VRC);
7305 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7306 get(TargetOpcode::COPY), NewSrcReg)
7307 .addReg(SrcReg);
7308 SrcReg = NewSrcReg;
7309 }
7310
7311 if (SubRegs == 1) {
7312 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7313 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7314 .addReg(SrcReg);
7315 return DstReg;
7316 }
7317
7319 for (unsigned i = 0; i < SubRegs; ++i) {
7320 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7321 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7322 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7323 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7324 SRegs.push_back(SGPR);
7325 }
7326
7328 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7329 get(AMDGPU::REG_SEQUENCE), DstReg);
7330 for (unsigned i = 0; i < SubRegs; ++i) {
7331 MIB.addReg(SRegs[i]);
7332 MIB.addImm(RI.getSubRegFromChannel(i));
7333 }
7334 return DstReg;
7335}
7336
7338 MachineInstr &MI) const {
7339
7340 // If the pointer is store in VGPRs, then we need to move them to
7341 // SGPRs using v_readfirstlane. This is safe because we only select
7342 // loads with uniform pointers to SMRD instruction so we know the
7343 // pointer value is uniform.
7344 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
7345 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
7346 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
7347 SBase->setReg(SGPR);
7348 }
7349 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
7350 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
7351 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
7352 SOff->setReg(SGPR);
7353 }
7354}
7355
7357 unsigned Opc = Inst.getOpcode();
7358 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
7359 if (OldSAddrIdx < 0)
7360 return false;
7361
7362 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
7363
7364 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
7365 if (NewOpc < 0)
7367 if (NewOpc < 0)
7368 return false;
7369
7370 MachineRegisterInfo &MRI = Inst.getMF()->getRegInfo();
7371 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
7372 if (RI.isSGPRReg(MRI, SAddr.getReg()))
7373 return false;
7374
7375 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7376 if (NewVAddrIdx < 0)
7377 return false;
7378
7379 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
7380
7381 // Check vaddr, it shall be zero or absent.
7382 MachineInstr *VAddrDef = nullptr;
7383 if (OldVAddrIdx >= 0) {
7384 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
7385 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
7386 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
7387 !VAddrDef->getOperand(1).isImm() ||
7388 VAddrDef->getOperand(1).getImm() != 0)
7389 return false;
7390 }
7391
7392 const MCInstrDesc &NewDesc = get(NewOpc);
7393 Inst.setDesc(NewDesc);
7394
7395 // Callers expect iterator to be valid after this call, so modify the
7396 // instruction in place.
7397 if (OldVAddrIdx == NewVAddrIdx) {
7398 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
7399 // Clear use list from the old vaddr holding a zero register.
7400 MRI.removeRegOperandFromUseList(&NewVAddr);
7401 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7402 Inst.removeOperand(OldSAddrIdx);
7403 // Update the use list with the pointer we have just moved from vaddr to
7404 // saddr position. Otherwise new vaddr will be missing from the use list.
7405 MRI.removeRegOperandFromUseList(&NewVAddr);
7406 MRI.addRegOperandToUseList(&NewVAddr);
7407 } else {
7408 assert(OldSAddrIdx == NewVAddrIdx);
7409
7410 if (OldVAddrIdx >= 0) {
7411 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7412 AMDGPU::OpName::vdst_in);
7413
7414 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
7415 // it asserts. Untie the operands for now and retie them afterwards.
7416 if (NewVDstIn != -1) {
7417 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
7418 Inst.untieRegOperand(OldVDstIn);
7419 }
7420
7421 Inst.removeOperand(OldVAddrIdx);
7422
7423 if (NewVDstIn != -1) {
7424 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7425 Inst.tieOperands(NewVDst, NewVDstIn);
7426 }
7427 }
7428 }
7429
7430 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
7431 VAddrDef->eraseFromParent();
7432
7433 return true;
7434}
7435
7436// FIXME: Remove this when SelectionDAG is obsoleted.
7438 MachineInstr &MI) const {
7439 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
7440 return;
7441
7442 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
7443 // thinks they are uniform, so a readfirstlane should be valid.
7444 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
7445 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
7446 return;
7447
7449 return;
7450
7451 const TargetRegisterClass *DeclaredRC =
7452 getRegClass(MI.getDesc(), SAddr->getOperandNo());
7453
7454 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
7455 SAddr->setReg(ToSGPR);
7456}
7457
7460 const TargetRegisterClass *DstRC,
7463 const DebugLoc &DL) const {
7464 Register OpReg = Op.getReg();
7465 unsigned OpSubReg = Op.getSubReg();
7466
7467 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
7468 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7469
7470 // Check if operand is already the correct register class.
7471 if (DstRC == OpRC)
7472 return;
7473
7474 Register DstReg = MRI.createVirtualRegister(DstRC);
7475 auto Copy = BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg)
7476 .addReg(OpReg, {}, OpSubReg);
7477 Op.setReg(DstReg);
7478 Op.setSubReg(AMDGPU::NoSubRegister);
7479
7480 MachineInstr *Def = MRI.getVRegDef(OpReg);
7481 if (!Def)
7482 return;
7483
7484 // Try to eliminate the copy if it is copying an immediate value.
7485 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7486 foldImmediate(*Copy, *Def, OpReg, &MRI);
7487
7488 bool ImpDef = Def->isImplicitDef();
7489 while (!ImpDef && Def && Def->isCopy()) {
7490 if (Def->getOperand(1).getReg().isPhysical())
7491 break;
7492 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7493 ImpDef = Def && Def->isImplicitDef();
7494 }
7495 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7496 !ImpDef)
7497 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7498}
7499
7500// Emit the actual waterfall loop, executing the wrapped instruction for each
7501// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7502// iteration, in the worst case we execute 64 (once per lane).
7505 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7506 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7507 MachineFunction &MF = *LoopBB.getParent();
7509 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7511 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7512
7513 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7514 // available. Otherwise, use the previous pattern of v_cmp_eq,
7515 // s_and_saveexec, and s_xor.
7516 bool UseNewExecInstructions =
7517 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7518
7520 Register CondReg;
7521
7522 Register PhiExec;
7523 Register NewExec;
7524
7525 if (UseNewExecInstructions) {
7526 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7527 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7528 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7529 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7530 .addReg(LMC.ExecReg);
7531
7532 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7533 .addReg(InitExec)
7534 .addMBB(&PredBB)
7535 .addReg(NewExec)
7536 .addMBB(&BodyBB);
7537 }
7538
7539 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7540 // involves a trade-off between register pressure and latency:
7541 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7542 // register pressure because arguments and results of all
7543 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7544 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7545 // increase latency by placing v_readfirstlane instructions
7546 // immediately before v_cmpx instruction that directly depend on it.
7547 ///
7548 // Emitting interleaved v_cmpx and v_readfirstlane requires
7549 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7550 // v_cmpx needs to be treated as terminator until after register allocation
7551 // (spill placement) and instruction reordering.
7552 //
7553 // Current implementation defers v_cmpx and leaves other instruction
7554 // scheduling decisions to later passes, where register pressure is known or
7555 // easier to approximate.
7556 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7557 // v_cmpx instructions are inserted at the end of LoopBB.
7558 // After the first v_cmpx is emitted, I is updated to point to it
7559 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7560 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7561 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7562 unsigned NumSubRegs = RegSize / 32;
7563 Register VScalarOp = ScalarOp->getReg();
7564
7565 const TargetRegisterClass *RFLSrcRC =
7566 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7567
7568 if (NumSubRegs == 1) {
7569 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7570 if (const TargetRegisterClass *Common =
7571 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7572 Common != VScalarOpRC) {
7573 Register VRReg = MRI.createVirtualRegister(Common);
7574 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7575 VScalarOp = VRReg;
7576 }
7577 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7578
7579 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7580 .addReg(VScalarOp);
7581
7582 if (UseNewExecInstructions) {
7583 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7584 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7585 .addReg(CurReg)
7586 .addReg(VScalarOp);
7587 if (I == LoopBB.end())
7588 I = CmpxMI.getInstr()->getIterator();
7589 } else {
7590 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7591
7592 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7593 .addReg(CurReg)
7594 .addReg(VScalarOp);
7595
7596 // Combine the comparison results with AND.
7597 if (!CondReg) { // First.
7598 CondReg = NewCondReg;
7599 } else { // If not the first, we create an AND.
7600 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7601 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7602 .addReg(CondReg)
7603 .addReg(NewCondReg)
7604 .setOperandDead(3);
7605 CondReg = AndReg;
7606 }
7607 }
7608
7609 // Update ScalarOp operand to use the SGPR ScalarOp.
7610 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7611 ScalarOp->setReg(CurReg);
7612 else {
7613 // Insert into the same block of use
7614 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7615 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7616 .addReg(CurReg);
7617 ScalarOp->setReg(PhySGPRs[Idx]);
7618 }
7619 } else {
7620 SmallVector<Register, 8> ReadlanePieces;
7621 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7622 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7623 "Unhandled register size");
7624
7625 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7626 Register CurRegLo =
7627 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7628 Register CurRegHi =
7629 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7630
7631 // Read the next variant <- also loop target.
7632 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7633 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7634
7635 // Read the next variant <- also loop target.
7636 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7637 .addReg(VScalarOp, VScalarOpUndef,
7638 TRI->getSubRegFromChannel(Idx + 1));
7639
7640 ReadlanePieces.push_back(CurRegLo);
7641 ReadlanePieces.push_back(CurRegHi);
7642
7643 // Comparison is to be done as 64-bit.
7644 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7645 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7646 .addReg(CurRegLo)
7647 .addImm(AMDGPU::sub0)
7648 .addReg(CurRegHi)
7649 .addImm(AMDGPU::sub1);
7650
7651 unsigned SubReg =
7652 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7653
7654 if (UseNewExecInstructions) {
7655 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7656 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7657 .addReg(CurReg)
7658 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7659 if (I == LoopBB.end())
7660 I = CmpxMI.getInstr()->getIterator();
7661 } else {
7662 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7663 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7664 .addReg(CurReg)
7665 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7666
7667 // Combine the comparison results with AND.
7668 if (!CondReg) { // First.
7669 CondReg = NewCondReg;
7670 } else { // If not the first, we create an AND.
7671 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7672 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7673 .addReg(CondReg)
7674 .addReg(NewCondReg)
7675 .setOperandDead(3);
7676 CondReg = AndReg;
7677 }
7678 }
7679 } // End for loop.
7680
7681 const auto *SScalarOpRC =
7682 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7683 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7684
7685 // Build scalar ScalarOp.
7686 auto Merge =
7687 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7688 unsigned Channel = 0;
7689 for (Register Piece : ReadlanePieces) {
7690 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7691 }
7692
7693 // Update ScalarOp operand to use the SGPR ScalarOp.
7694 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7695 ScalarOp->setReg(SScalarOp);
7696 else {
7697 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7698 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7699 .addReg(SScalarOp);
7700 ScalarOp->setReg(PhySGPRs[Idx]);
7701 }
7702 }
7703 }
7704
7705 // AndSaveExecOpc modifies EXEC but can't be isTerminator=1: terminators
7706 // that define virtual registers aren't supported.
7707 Register SaveExec;
7708 if (!UseNewExecInstructions) {
7709 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7710 MRI.setSimpleHint(SaveExec, CondReg);
7711
7712 // Update EXEC to matching lanes, saving original to SaveExec.
7713 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7714 .addReg(CondReg)
7715 .setOperandDead(3);
7716 }
7717
7718 // The original instruction is here; we insert the terminators after it.
7719 I = BodyBB.end();
7720
7721 if (UseNewExecInstructions) {
7722 // Compute the remaining lanes into a plain virtual register and write EXEC
7723 // from a terminator, so spill code for NewExec is placed before EXEC
7724 // changes. SIOptimizeExecMasking opportunistically folds the pair back
7725 // into S_ANDN2_WREXEC after register allocation.
7726 MRI.setSimpleHint(NewExec, PhiExec);
7727 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2Opc), NewExec)
7728 .addReg(PhiExec)
7729 .addReg(LMC.ExecReg)
7730 .setOperandDead(3);
7731 BuildMI(BodyBB, I, DL, TII.get(LMC.MovTermOpc), LMC.ExecReg)
7732 .addReg(NewExec);
7733 } else {
7734 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7735 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7736 .addReg(LMC.ExecReg)
7737 .addReg(SaveExec)
7738 .setOperandDead(3);
7739 }
7740
7741 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7742}
7743
7744// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7745// with SGPRs by iterating over all unique values across all lanes.
7746// Returns the loop basic block that now contains \p MI.
7747static MachineBasicBlock *
7751 MachineBasicBlock::iterator Begin = nullptr,
7753 ArrayRef<Register> PhySGPRs = {}) {
7754 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7755 "Physical SGPRs must be empty or match the number of scalar operands");
7757 MachineFunction &MF = *MBB.getParent();
7759 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7760 MachineRegisterInfo &MRI = MF.getRegInfo();
7761 if (!Begin.isValid())
7762 Begin = &MI;
7763 if (!End.isValid()) {
7764 End = &MI;
7765 ++End;
7766 }
7767 const DebugLoc &DL = MI.getDebugLoc();
7769 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7770
7771 // Save SCC. Waterfall Loop may overwrite SCC.
7772 Register SaveSCCReg;
7773
7774 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7775 // rather than unlimited scan everywhere
7776 bool SCCNotDead =
7777 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7778 std::numeric_limits<unsigned>::max()) !=
7780 if (SCCNotDead) {
7781 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7782 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7783 .addImm(1)
7784 .addImm(0);
7785 }
7786
7787 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7788
7789 // Save the EXEC mask
7790 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7791
7792 // Killed uses in the instruction we are waterfalling around will be
7793 // incorrect due to the added control-flow.
7795 ++AfterMI;
7796 for (auto I = Begin; I != AfterMI; I++) {
7797 for (auto &MO : I->all_uses())
7798 MRI.clearKillFlags(MO.getReg());
7799 }
7800
7801 // To insert the loop we need to split the block. Move everything after this
7802 // point to a new block, and insert a new empty block between the two.
7805 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7807 ++MBBI;
7808
7809 MF.insert(MBBI, LoopBB);
7810 MF.insert(MBBI, BodyBB);
7811 MF.insert(MBBI, RemainderBB);
7812
7813 LoopBB->addSuccessor(BodyBB);
7814 BodyBB->addSuccessor(LoopBB);
7815 BodyBB->addSuccessor(RemainderBB);
7816
7817 // Move Begin to MI to the BodyBB, and the remainder of the block to
7818 // RemainderBB.
7819 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7820 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7821 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7822
7823 MBB.addSuccessor(LoopBB);
7824
7825 // Update dominators. We know that MBB immediately dominates LoopBB, that
7826 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7827 // RemainderBB. RemainderBB immediately dominates all of the successors
7828 // transferred to it from MBB that MBB used to properly dominate.
7829 if (MDT) {
7830 MDT->addNewBlock(LoopBB, &MBB);
7831 MDT->addNewBlock(BodyBB, LoopBB);
7832 MDT->addNewBlock(RemainderBB, BodyBB);
7833 for (auto &Succ : RemainderBB->successors()) {
7834 if (MDT->properlyDominates(&MBB, Succ)) {
7835 MDT->changeImmediateDominator(Succ, RemainderBB);
7836 }
7837 }
7838 }
7839
7840 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7841 PhySGPRs);
7842
7843 MachineBasicBlock::iterator First = RemainderBB->begin();
7844 // Restore SCC
7845 if (SCCNotDead) {
7846 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7847 .addReg(SaveSCCReg)
7848 .addImm(0);
7849 }
7850
7851 // Restore the EXEC mask
7852 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7853 .addReg(SaveExec);
7854 return BodyBB;
7855}
7856
7857// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7858static std::tuple<unsigned, unsigned>
7860 MachineBasicBlock &MBB = *MI.getParent();
7861 MachineFunction &MF = *MBB.getParent();
7862 MachineRegisterInfo &MRI = MF.getRegInfo();
7863
7864 // Extract the ptr from the resource descriptor.
7865 unsigned RsrcPtr =
7866 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7867 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7868
7869 // Create an empty resource descriptor
7870 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7871 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7872 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7873 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7874 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7875
7876 // Zero64 = 0
7877 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7878 .addImm(0);
7879
7880 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7881 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7882 .addImm(Lo_32(RsrcDataFormat));
7883
7884 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7885 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7886 .addImm(Hi_32(RsrcDataFormat));
7887
7888 // NewSRsrc = {Zero64, SRsrcFormat}
7889 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7890 .addReg(Zero64)
7891 .addImm(AMDGPU::sub0_sub1)
7892 .addReg(SRsrcFormatLo)
7893 .addImm(AMDGPU::sub2)
7894 .addReg(SRsrcFormatHi)
7895 .addImm(AMDGPU::sub3);
7896
7897 return std::tuple(RsrcPtr, NewSRsrc);
7898}
7899
7902 MachineDominatorTree *MDT) const {
7903 MachineFunction &MF = *MI.getMF();
7904 MachineRegisterInfo &MRI = MF.getRegInfo();
7905 MachineBasicBlock *CreatedBB = nullptr;
7906
7907 // Legalize True16
7908 if (ST.useRealTrue16Insts())
7910
7911 // Legalize VOP2
7912 if (isVOP2(MI) || isVOPC(MI)) {
7914 return CreatedBB;
7915 }
7916
7917 // Legalize VOP3
7918 if (isVOP3(MI)) {
7920 return CreatedBB;
7921 }
7922
7923 // Legalize SMRD
7924 if (isSMRD(MI)) {
7926 return CreatedBB;
7927 }
7928
7929 // Legalize FLAT
7930 if (isFLAT(MI)) {
7932 return CreatedBB;
7933 }
7934
7935 // Legalize PHI
7936 // The register class of the operands must be the same type as the register
7937 // class of the output.
7938 if (MI.getOpcode() == AMDGPU::PHI) {
7939 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7940 assert(!RI.isSGPRClass(VRC));
7941
7942 // Update all the operands so they have the same type.
7943 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7944 MachineOperand &Op = MI.getOperand(I);
7945 if (!Op.isReg() || !Op.getReg().isVirtual())
7946 continue;
7947
7948 // MI is a PHI instruction.
7949 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7951
7952 // Avoid creating no-op copies with the same src and dst reg class. These
7953 // confuse some of the machine passes.
7954 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7955 }
7956 }
7957
7958 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7959 // VGPR dest type and SGPR sources, insert copies so all operands are
7960 // VGPRs. This seems to help operand folding / the register coalescer.
7961 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7962 MachineBasicBlock *MBB = MI.getParent();
7963 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7964 if (RI.hasVGPRs(DstRC)) {
7965 // Update all the operands so they are VGPR register classes. These may
7966 // not be the same register class because REG_SEQUENCE supports mixing
7967 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7968 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7969 MachineOperand &Op = MI.getOperand(I);
7970 if (!Op.isReg() || !Op.getReg().isVirtual())
7971 continue;
7972
7973 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7974 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7975 if (VRC == OpRC)
7976 continue;
7977
7978 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7979 }
7980 }
7981
7982 return CreatedBB;
7983 }
7984
7985 // Legalize INSERT_SUBREG
7986 // src0 must have the same register class as dst
7987 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7988 Register Dst = MI.getOperand(0).getReg();
7989 Register Src0 = MI.getOperand(1).getReg();
7990 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7991 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7992 if (DstRC != Src0RC) {
7993 MachineBasicBlock *MBB = MI.getParent();
7994 MachineOperand &Op = MI.getOperand(1);
7995 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7996 }
7997 return CreatedBB;
7998 }
7999
8000 // Legalize SI_INIT_M0
8001 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
8002 MachineOperand &Src = MI.getOperand(0);
8003 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
8004 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
8005 return CreatedBB;
8006 }
8007
8008 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
8009 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
8010 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
8011 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
8012 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
8013 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
8014 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
8015 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
8016 MachineOperand &Src = MI.getOperand(1);
8017 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
8018 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
8019 return CreatedBB;
8020 }
8021
8022 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
8023 //
8024 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
8025 // scratch memory access. In both cases, the legalization never involves
8026 // conversion to the addr64 form.
8028 (isMUBUF(MI) || isMTBUF(MI)))) {
8029 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
8030 ? AMDGPU::OpName::rsrc
8031 : AMDGPU::OpName::srsrc;
8032 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
8033 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
8034 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
8035
8036 AMDGPU::OpName SampOpName =
8037 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
8038 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
8039 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
8040 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
8041
8042 return CreatedBB;
8043 }
8044
8045 // Legalize SI_CALL
8046 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
8047 MachineOperand *Dest = &MI.getOperand(0);
8048 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
8049 createWaterFallForSiCall(&MI, MDT, {Dest});
8050 }
8051 }
8052
8053 // Legalize s_sleep_var.
8054 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
8055 const DebugLoc &DL = MI.getDebugLoc();
8056 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8057 int Src0Idx =
8058 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
8059 MachineOperand &Src0 = MI.getOperand(Src0Idx);
8060 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
8061 .add(Src0);
8062 Src0.ChangeToRegister(Reg, false);
8063 return nullptr;
8064 }
8065
8066 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
8067 // operands are scalar.
8068 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
8069 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
8070 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
8071 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
8072 for (MachineOperand &Src : MI.explicit_operands()) {
8073 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
8074 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
8075 }
8076 return CreatedBB;
8077 }
8078
8079 // Legalize MUBUF instructions.
8080 bool isSoffsetLegal = true;
8081 int SoffsetIdx =
8082 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
8083 if (SoffsetIdx != -1) {
8084 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
8085 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
8086 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
8087 isSoffsetLegal = false;
8088 }
8089 }
8090
8091 bool isRsrcLegal = true;
8092 int RsrcIdx =
8093 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
8094 if (RsrcIdx != -1) {
8095 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
8096 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
8097 isRsrcLegal = false;
8098 }
8099
8100 // The operands are legal.
8101 if (isRsrcLegal && isSoffsetLegal)
8102 return CreatedBB;
8103
8104 if (!isRsrcLegal) {
8105 // Legalize a VGPR Rsrc
8106 //
8107 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
8108 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
8109 // a zero-value SRsrc.
8110 //
8111 // If the instruction is _OFFSET (both idxen and offen disabled), and we
8112 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
8113 // above.
8114 //
8115 // Otherwise we are on non-ADDR64 hardware, and/or we have
8116 // idxen/offen/bothen and we fall back to a waterfall loop.
8117
8118 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
8119 MachineBasicBlock &MBB = *MI.getParent();
8120
8121 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
8122 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
8123 // This is already an ADDR64 instruction so we need to add the pointer
8124 // extracted from the resource descriptor to the current value of VAddr.
8125 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8126 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8127 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8128
8129 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
8130 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
8131 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
8132
8133 unsigned RsrcPtr, NewSRsrc;
8134 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
8135
8136 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
8137 const DebugLoc &DL = MI.getDebugLoc();
8138 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
8139 .addDef(CondReg0)
8140 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8141 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
8142 .addImm(0);
8143
8144 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
8145 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
8146 .addDef(CondReg1, RegState::Dead)
8147 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8148 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
8149 .addReg(CondReg0)
8150 .addImm(0);
8151
8152 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8153 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
8154 .addReg(NewVAddrLo)
8155 .addImm(AMDGPU::sub0)
8156 .addReg(NewVAddrHi)
8157 .addImm(AMDGPU::sub1);
8158
8159 VAddr->setReg(NewVAddr);
8160 Rsrc->setReg(NewSRsrc);
8161 } else if (!VAddr && ST.hasAddr64()) {
8162 // This instructions is the _OFFSET variant, so we need to convert it to
8163 // ADDR64.
8164 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
8165 "FIXME: Need to emit flat atomics here");
8166
8167 unsigned RsrcPtr, NewSRsrc;
8168 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
8169
8170 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8171 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
8172 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
8173 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8174 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
8175
8176 // Atomics with return have an additional tied operand and are
8177 // missing some of the special bits.
8178 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
8179 MachineInstr *Addr64;
8180
8181 if (!VDataIn) {
8182 // Regular buffer load / store.
8184 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
8185 .add(*VData)
8186 .addReg(NewVAddr)
8187 .addReg(NewSRsrc)
8188 .add(*SOffset)
8189 .add(*Offset);
8190
8191 if (const MachineOperand *CPol =
8192 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
8193 MIB.addImm(CPol->getImm());
8194 }
8195
8196 if (const MachineOperand *TFE =
8197 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
8198 MIB.addImm(TFE->getImm());
8199 }
8200
8201 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
8202
8203 MIB.cloneMemRefs(MI);
8204 Addr64 = MIB;
8205 } else {
8206 // Atomics with return.
8207 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
8208 .add(*VData)
8209 .add(*VDataIn)
8210 .addReg(NewVAddr)
8211 .addReg(NewSRsrc)
8212 .add(*SOffset)
8213 .add(*Offset)
8214 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
8215 .cloneMemRefs(MI);
8216 }
8217
8218 MI.removeFromParent();
8219
8220 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8221 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
8222 NewVAddr)
8223 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8224 .addImm(AMDGPU::sub0)
8225 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8226 .addImm(AMDGPU::sub1);
8227 } else {
8228 // Legalize a VGPR Rsrc and soffset together.
8229 if (!isSoffsetLegal) {
8230 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8231 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
8232 return CreatedBB;
8233 }
8234 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
8235 return CreatedBB;
8236 }
8237 }
8238
8239 // Legalize a VGPR soffset.
8240 if (!isSoffsetLegal) {
8241 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8242 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
8243 return CreatedBB;
8244 }
8245 return CreatedBB;
8246}
8247
8249 if (InSet.insert(MI).second)
8250 InstrList.push_back(MI);
8251 // Add MBUF instructiosn to deferred list.
8252 int RsrcIdx =
8253 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
8254 if (RsrcIdx != -1) {
8255 DeferredList.insert(MI);
8256 }
8257}
8258
8260 return DeferredList.contains(MI);
8261}
8262
8263// Legalize size mismatches between 16bit and 32bit registers in v2s copy
8264// lowering (change sgpr to vgpr).
8265// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
8266// size. Need to legalize the size of the operands during the vgpr lowering
8267// chain. This can be removed after we have sgpr16 in place
8269 MachineRegisterInfo &MRI) const {
8270 if (!ST.useRealTrue16Insts())
8271 return;
8272
8273 unsigned Opcode = MI.getOpcode();
8274 MachineBasicBlock *MBB = MI.getParent();
8275 // Legalize operands and check for size mismatch
8276 if (OpIdx >= MI.getNumExplicitOperands() ||
8277 OpIdx >= get(Opcode).getNumOperands() ||
8278 get(Opcode).operands()[OpIdx].RegClass == -1)
8279 return;
8280
8281 MachineOperand &Op = MI.getOperand(OpIdx);
8282 if (!Op.isReg() || !Op.getReg().isVirtual() || Op.isDef())
8283 return;
8284
8285 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
8286 if (!RI.isVGPRClass(CurrRC))
8287 return;
8288
8289 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
8290 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
8291 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8292 // Default to the lo16 only if the subregister is not specified.
8293 if (Op.getSubReg() == AMDGPU::NoSubRegister)
8294 Op.setSubReg(AMDGPU::lo16);
8295 return;
8296 }
8297
8298 const TargetRegisterClass *CurrSRC =
8299 RI.getSubRegisterClass(CurrRC, Op.getSubReg());
8300 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8301 const DebugLoc &DL = MI.getDebugLoc();
8302 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8303 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8304 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
8305 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
8306 .addReg(Op.getReg(), {}, Op.getSubReg())
8307 .addImm(AMDGPU::lo16)
8308 .addReg(Undef)
8309 .addImm(AMDGPU::hi16);
8310 Op.setReg(NewDstReg);
8311 Op.setSubReg(AMDGPU::NoSubRegister);
8312 }
8313}
8315 MachineRegisterInfo &MRI) const {
8316 for (unsigned OpIdx = 0; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
8317 legalizeOperandsVALUt16(MI, OpIdx, MRI);
8318}
8319
8323 ArrayRef<Register> PhySGPRs) const {
8324 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8325 "This only handle waterfall for SI_CALL_ISEL");
8326 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
8327 // following copies, we also need to move copies from and to physical
8328 // registers into the loop block.
8329 // Also move the copies to physical registers into the loop block
8330 MachineBasicBlock &MBB = *MI->getParent();
8332 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8333 --Start;
8335 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8336 ++End;
8337
8338 // Also include following copies of the return value
8339 ++End;
8340 while (End != MBB.end() && End->isCopy() &&
8341 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8342 ++End;
8343
8344 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
8345}
8346
8348 MachineDominatorTree *MDT) const {
8350 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
8351 while (!Worklist.empty()) {
8352 MachineInstr &Inst = *Worklist.top();
8353 Worklist.erase_top();
8354 // Skip MachineInstr in the deferred list.
8355 if (Worklist.isDeferred(&Inst))
8356 continue;
8357 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8358 }
8359
8360 // Deferred list of instructions will be processed once
8361 // all the MachineInstr in the worklist are done.
8362 for (MachineInstr *Inst : Worklist.getDeferredList()) {
8363 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8364 assert(Worklist.empty() &&
8365 "Deferred MachineInstr are not supposed to re-populate worklist");
8366 }
8367
8368 for (auto &Entry : WaterFalls) {
8369 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8370 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
8371 Entry.second.SGPRs);
8372 }
8373
8374 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8375 if (Entry.second)
8376 Entry.first->eraseFromParent();
8377}
8379 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
8380 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
8381 // hope for the best.
8382 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
8383 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
8384 if (SubRegIndices.size() <= 1) {
8385 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8386 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8387 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8388 .add(Inst.getOperand(1));
8389 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
8390 DstReg)
8391 .addReg(NewDst);
8392 } else {
8394 for (int16_t Indice : SubRegIndices) {
8395 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8396 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8397 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8398 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
8399
8400 DstRegs.push_back(NewDst);
8401 }
8403 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8404 get(AMDGPU::REG_SEQUENCE), DstReg);
8405 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
8406 MIB.addReg(DstRegs[i]);
8407 MIB.addImm(RI.getSubRegFromChannel(i));
8408 }
8409 }
8410}
8411
8413 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
8416 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8417 if (DstReg == AMDGPU::M0) {
8418 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8419 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8420 return;
8421 }
8422 Register SrcReg = Inst.getOperand(1).getReg();
8425 // Only search current block since phyreg's def & use cannot cross
8426 // blocks when MF.NoPhi = false.
8427 while (++I != E) {
8428 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
8429 // and record the operand for later waterfall loop generation.
8430 if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8431 MachineInstr *UseMI = &*I;
8432 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
8433 if (UseMI->getOperand(i).isReg() &&
8434 UseMI->getOperand(i).getReg() == DstReg) {
8435 MachineOperand *MO = &UseMI->getOperand(i);
8436 MO->setReg(SrcReg);
8437 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
8438 V2SCopyInfo.MOs.push_back(MO);
8439 V2SCopyInfo.SGPRs.push_back(DstReg);
8440 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8441 }
8442 }
8443 } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8444 I->getOperand(0).isReg() &&
8445 I->getOperand(0).getReg() == DstReg) {
8446 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8447 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8448 } else if (I->readsRegister(DstReg, &RI)) {
8449 // COPY cannot be erased if other type of inst uses it.
8450 V2SPhyCopiesToErase[&Inst] = false;
8451 }
8452 if (I->findRegisterDefOperand(DstReg, &RI))
8453 break;
8454 }
8455}
8456
8458 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
8460 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8461
8463 if (!MBB)
8464 return;
8465 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
8466 unsigned Opcode = Inst.getOpcode();
8467 unsigned NewOpcode = getVALUOp(Inst);
8468 const DebugLoc &DL = Inst.getDebugLoc();
8469
8470 // Handle some special cases
8471 switch (Opcode) {
8472 default:
8473 break;
8474 case AMDGPU::S_ADD_I32:
8475 case AMDGPU::S_SUB_I32: {
8476 // FIXME: The u32 versions currently selected use the carry.
8477 bool Changed;
8478 MachineBasicBlock *CreatedBBTmp = nullptr;
8479 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8480 if (Changed)
8481 return;
8482
8483 // Default handling
8484 break;
8485 }
8486
8487 case AMDGPU::S_MUL_U64:
8488 if (ST.useVMulU64Inst()) {
8489 NewOpcode = AMDGPU::V_MUL_U64_e64;
8490 break;
8491 }
8492 // Split s_mul_u64 in 32-bit vector multiplications.
8493 splitScalarSMulU64(Worklist, Inst, MDT);
8494 Inst.eraseFromParent();
8495 return;
8496
8497 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8498 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8499 // This is a special case of s_mul_u64 where all the operands are either
8500 // zero extended or sign extended.
8501 splitScalarSMulPseudo(Worklist, Inst, MDT);
8502 Inst.eraseFromParent();
8503 return;
8504
8505 case AMDGPU::S_AND_B64:
8506 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8507 Inst.eraseFromParent();
8508 return;
8509
8510 case AMDGPU::S_OR_B64:
8511 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8512 Inst.eraseFromParent();
8513 return;
8514
8515 case AMDGPU::S_XOR_B64:
8516 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8517 Inst.eraseFromParent();
8518 return;
8519
8520 case AMDGPU::S_NAND_B64:
8521 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8522 Inst.eraseFromParent();
8523 return;
8524
8525 case AMDGPU::S_NOR_B64:
8526 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8527 Inst.eraseFromParent();
8528 return;
8529
8530 case AMDGPU::S_XNOR_B64:
8531 if (ST.hasDLInsts())
8532 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8533 else
8534 splitScalar64BitXnor(Worklist, Inst, MDT);
8535 Inst.eraseFromParent();
8536 return;
8537
8538 case AMDGPU::S_ANDN2_B64:
8539 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8540 Inst.eraseFromParent();
8541 return;
8542
8543 case AMDGPU::S_ORN2_B64:
8544 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8545 Inst.eraseFromParent();
8546 return;
8547
8548 case AMDGPU::S_BREV_B64:
8549 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8550 Inst.eraseFromParent();
8551 return;
8552
8553 case AMDGPU::S_NOT_B64:
8554 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8555 Inst.eraseFromParent();
8556 return;
8557
8558 case AMDGPU::S_BCNT1_I32_B64:
8559 splitScalar64BitBCNT(Worklist, Inst);
8560 Inst.eraseFromParent();
8561 return;
8562
8563 case AMDGPU::S_BFE_I64:
8564 splitScalar64BitBFE(Worklist, Inst);
8565 Inst.eraseFromParent();
8566 return;
8567
8568 case AMDGPU::S_FLBIT_I32_B64:
8569 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8570 Inst.eraseFromParent();
8571 return;
8572 case AMDGPU::S_FF1_I32_B64:
8573 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8574 Inst.eraseFromParent();
8575 return;
8576
8577 case AMDGPU::S_LSHL_B32:
8578 if (ST.hasOnlyRevVALUShifts()) {
8579 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8580 swapOperands(Inst);
8581 }
8582 break;
8583 case AMDGPU::S_ASHR_I32:
8584 if (ST.hasOnlyRevVALUShifts()) {
8585 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8586 swapOperands(Inst);
8587 }
8588 break;
8589 case AMDGPU::S_LSHR_B32:
8590 if (ST.hasOnlyRevVALUShifts()) {
8591 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8592 swapOperands(Inst);
8593 }
8594 break;
8595 case AMDGPU::S_LSHL_B64:
8596 if (ST.hasOnlyRevVALUShifts()) {
8597 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8598 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8599 : AMDGPU::V_LSHLREV_B64_e64;
8600 swapOperands(Inst);
8601 }
8602 break;
8603 case AMDGPU::S_ASHR_I64:
8604 if (ST.hasOnlyRevVALUShifts()) {
8605 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8606 swapOperands(Inst);
8607 }
8608 break;
8609 case AMDGPU::S_LSHR_B64:
8610 if (ST.hasOnlyRevVALUShifts()) {
8611 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8612 swapOperands(Inst);
8613 }
8614 break;
8615
8616 case AMDGPU::S_ABS_I32:
8617 lowerScalarAbs(Worklist, Inst);
8618 Inst.eraseFromParent();
8619 return;
8620
8621 case AMDGPU::S_ABSDIFF_I32:
8622 lowerScalarAbsDiff(Worklist, Inst);
8623 Inst.eraseFromParent();
8624 return;
8625
8626 case AMDGPU::S_CBRANCH_SCC0:
8627 case AMDGPU::S_CBRANCH_SCC1: {
8628 // Clear unused bits of vcc
8629 Register CondReg = Inst.getOperand(1).getReg();
8630 bool IsSCC = CondReg == AMDGPU::SCC;
8632 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8633 .addReg(LMC.ExecReg)
8634 .addReg(IsSCC ? LMC.VccReg : CondReg)
8635 .setOperandDead(3); // implicit-def $scc
8636 Inst.removeOperand(1);
8637 } break;
8638
8639 case AMDGPU::S_BFE_U64:
8640 case AMDGPU::S_BFM_B64:
8641 llvm_unreachable("Moving this op to VALU not implemented");
8642
8643 case AMDGPU::S_PACK_LL_B32_B16:
8644 case AMDGPU::S_PACK_LH_B32_B16:
8645 case AMDGPU::S_PACK_HL_B32_B16:
8646 case AMDGPU::S_PACK_HH_B32_B16:
8647 movePackToVALU(Worklist, MRI, Inst);
8648 Inst.eraseFromParent();
8649 return;
8650
8651 case AMDGPU::S_XNOR_B32:
8652 lowerScalarXnor(Worklist, Inst);
8653 Inst.eraseFromParent();
8654 return;
8655
8656 case AMDGPU::S_NAND_B32:
8657 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8658 Inst.eraseFromParent();
8659 return;
8660
8661 case AMDGPU::S_NOR_B32:
8662 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8663 Inst.eraseFromParent();
8664 return;
8665
8666 case AMDGPU::S_ANDN2_B32:
8667 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8668 Inst.eraseFromParent();
8669 return;
8670
8671 case AMDGPU::S_ORN2_B32:
8672 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8673 Inst.eraseFromParent();
8674 return;
8675
8676 // TODO: remove as soon as everything is ready
8677 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8678 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8679 // can only be selected from the uniform SDNode.
8680 case AMDGPU::S_ADD_CO_PSEUDO:
8681 case AMDGPU::S_SUB_CO_PSEUDO: {
8682 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8683 ? AMDGPU::V_ADDC_U32_e64
8684 : AMDGPU::V_SUBB_U32_e64;
8685 const auto *CarryRC = RI.getWaveMaskRegClass();
8686
8687 Register CarryInReg = Inst.getOperand(4).getReg();
8688 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8689 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8690 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8691 .addReg(CarryInReg);
8692 }
8693
8694 Register CarryOutReg = Inst.getOperand(1).getReg();
8695
8696 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8697 MRI.getRegClass(Inst.getOperand(0).getReg())));
8698 MachineInstr *CarryOp =
8699 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8700 .addReg(CarryOutReg, RegState::Define)
8701 .add(Inst.getOperand(2))
8702 .add(Inst.getOperand(3))
8703 .addReg(CarryInReg)
8704 .addImm(0);
8705 legalizeOperands(*CarryOp);
8706 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8707 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8708 Inst.eraseFromParent();
8709 }
8710 return;
8711 case AMDGPU::S_UADDO_PSEUDO:
8712 case AMDGPU::S_USUBO_PSEUDO: {
8713 MachineOperand &Dest0 = Inst.getOperand(0);
8714 MachineOperand &Dest1 = Inst.getOperand(1);
8715 MachineOperand &Src0 = Inst.getOperand(2);
8716 MachineOperand &Src1 = Inst.getOperand(3);
8717
8718 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8719 ? AMDGPU::V_ADD_CO_U32_e64
8720 : AMDGPU::V_SUB_CO_U32_e64;
8721 const TargetRegisterClass *NewRC =
8722 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8723 Register DestReg = MRI.createVirtualRegister(NewRC);
8724 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8725 .addReg(Dest1.getReg(), RegState::Define)
8726 .add(Src0)
8727 .add(Src1)
8728 .addImm(0); // clamp bit
8729
8730 legalizeOperands(*NewInstr, MDT);
8731 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8732 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8733 Inst.eraseFromParent();
8734 }
8735 return;
8736 case AMDGPU::S_LSHL1_ADD_U32:
8737 case AMDGPU::S_LSHL2_ADD_U32:
8738 case AMDGPU::S_LSHL3_ADD_U32:
8739 case AMDGPU::S_LSHL4_ADD_U32: {
8740 MachineOperand &Dest = Inst.getOperand(0);
8741 MachineOperand &Src0 = Inst.getOperand(1);
8742 MachineOperand &Src1 = Inst.getOperand(2);
8743 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8744 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8745 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8746 : 4);
8747
8748 const TargetRegisterClass *NewRC =
8749 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8750 Register DestReg = MRI.createVirtualRegister(NewRC);
8751 MachineInstr *NewInstr =
8752 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8753 .add(Src0)
8754 .addImm(ShiftAmt)
8755 .add(Src1);
8756
8757 legalizeOperands(*NewInstr, MDT);
8758 MRI.replaceRegWith(Dest.getReg(), DestReg);
8759 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8760 Inst.eraseFromParent();
8761 }
8762 return;
8763 case AMDGPU::S_CSELECT_B32:
8764 case AMDGPU::S_CSELECT_B64:
8765 lowerSelect(Worklist, Inst, MDT);
8766 Inst.eraseFromParent();
8767 return;
8768 case AMDGPU::S_CMP_EQ_I32:
8769 case AMDGPU::S_CMP_LG_I32:
8770 case AMDGPU::S_CMP_GT_I32:
8771 case AMDGPU::S_CMP_GE_I32:
8772 case AMDGPU::S_CMP_LT_I32:
8773 case AMDGPU::S_CMP_LE_I32:
8774 case AMDGPU::S_CMP_EQ_U32:
8775 case AMDGPU::S_CMP_LG_U32:
8776 case AMDGPU::S_CMP_GT_U32:
8777 case AMDGPU::S_CMP_GE_U32:
8778 case AMDGPU::S_CMP_LT_U32:
8779 case AMDGPU::S_CMP_LE_U32:
8780 case AMDGPU::S_CMP_EQ_U64:
8781 case AMDGPU::S_CMP_LG_U64:
8782 case AMDGPU::S_CMP_LT_F32:
8783 case AMDGPU::S_CMP_EQ_F32:
8784 case AMDGPU::S_CMP_LE_F32:
8785 case AMDGPU::S_CMP_GT_F32:
8786 case AMDGPU::S_CMP_LG_F32:
8787 case AMDGPU::S_CMP_GE_F32:
8788 case AMDGPU::S_CMP_O_F32:
8789 case AMDGPU::S_CMP_U_F32:
8790 case AMDGPU::S_CMP_NGE_F32:
8791 case AMDGPU::S_CMP_NLG_F32:
8792 case AMDGPU::S_CMP_NGT_F32:
8793 case AMDGPU::S_CMP_NLE_F32:
8794 case AMDGPU::S_CMP_NEQ_F32:
8795 case AMDGPU::S_CMP_NLT_F32: {
8796 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8797 auto NewInstr =
8798 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8799 .setMIFlags(Inst.getFlags());
8800 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8801 0) {
8802 NewInstr
8803 .addImm(0) // src0_modifiers
8804 .add(Inst.getOperand(0)) // src0
8805 .addImm(0) // src1_modifiers
8806 .add(Inst.getOperand(1)) // src1
8807 .addImm(0); // clamp
8808 } else {
8809 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8810 }
8811 legalizeOperands(*NewInstr, MDT);
8812 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8813 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8814 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8815 Inst.eraseFromParent();
8816 return;
8817 }
8818 case AMDGPU::S_CMP_LT_F16:
8819 case AMDGPU::S_CMP_EQ_F16:
8820 case AMDGPU::S_CMP_LE_F16:
8821 case AMDGPU::S_CMP_GT_F16:
8822 case AMDGPU::S_CMP_LG_F16:
8823 case AMDGPU::S_CMP_GE_F16:
8824 case AMDGPU::S_CMP_O_F16:
8825 case AMDGPU::S_CMP_U_F16:
8826 case AMDGPU::S_CMP_NGE_F16:
8827 case AMDGPU::S_CMP_NLG_F16:
8828 case AMDGPU::S_CMP_NGT_F16:
8829 case AMDGPU::S_CMP_NLE_F16:
8830 case AMDGPU::S_CMP_NEQ_F16:
8831 case AMDGPU::S_CMP_NLT_F16: {
8832 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8833 auto NewInstr =
8834 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8835 .setMIFlags(Inst.getFlags());
8836 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8837 NewInstr
8838 .addImm(0) // src0_modifiers
8839 .add(Inst.getOperand(0)) // src0
8840 .addImm(0) // src1_modifiers
8841 .add(Inst.getOperand(1)) // src1
8842 .addImm(0); // clamp
8843 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8844 NewInstr.addImm(0); // op_sel0
8845 } else {
8846 NewInstr
8847 .add(Inst.getOperand(0))
8848 .add(Inst.getOperand(1));
8849 }
8850 legalizeOperands(*NewInstr, MDT);
8851 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8852 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8853 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8854 Inst.eraseFromParent();
8855 return;
8856 }
8857 case AMDGPU::S_CVT_HI_F32_F16: {
8858 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8859 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8860 if (ST.useRealTrue16Insts()) {
8861 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8862 .add(Inst.getOperand(1));
8863 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8864 .addImm(0) // src0_modifiers
8865 .addReg(TmpReg, {}, AMDGPU::hi16)
8866 .addImm(0) // clamp
8867 .addImm(0) // omod
8868 .addImm(0); // op_sel0
8869 } else {
8870 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8871 .addImm(16)
8872 .add(Inst.getOperand(1));
8873 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8874 .addImm(0) // src0_modifiers
8875 .addReg(TmpReg)
8876 .addImm(0) // clamp
8877 .addImm(0); // omod
8878 }
8879
8880 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8881 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8882 Inst.eraseFromParent();
8883 return;
8884 }
8885 case AMDGPU::S_MINIMUM_F32:
8886 case AMDGPU::S_MAXIMUM_F32: {
8887 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8888 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8889 .addImm(0) // src0_modifiers
8890 .add(Inst.getOperand(1))
8891 .addImm(0) // src1_modifiers
8892 .add(Inst.getOperand(2))
8893 .addImm(0) // clamp
8894 .addImm(0); // omod
8895 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8896
8897 legalizeOperands(*NewInstr, MDT);
8898 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8899 Inst.eraseFromParent();
8900 return;
8901 }
8902 case AMDGPU::S_MINIMUM_F16:
8903 case AMDGPU::S_MAXIMUM_F16: {
8904 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8905 ? &AMDGPU::VGPR_16RegClass
8906 : &AMDGPU::VGPR_32RegClass);
8907 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8908 .addImm(0) // src0_modifiers
8909 .add(Inst.getOperand(1))
8910 .addImm(0) // src1_modifiers
8911 .add(Inst.getOperand(2))
8912 .addImm(0) // clamp
8913 .addImm(0) // omod
8914 .addImm(0); // opsel0
8915 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8916 legalizeOperands(*NewInstr, MDT);
8917 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8918 Inst.eraseFromParent();
8919 return;
8920 }
8921 case AMDGPU::V_S_EXP_F16_e64:
8922 case AMDGPU::V_S_LOG_F16_e64:
8923 case AMDGPU::V_S_RCP_F16_e64:
8924 case AMDGPU::V_S_RSQ_F16_e64:
8925 case AMDGPU::V_S_SQRT_F16_e64: {
8926 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8927 ? &AMDGPU::VGPR_16RegClass
8928 : &AMDGPU::VGPR_32RegClass);
8929 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8930 .add(Inst.getOperand(1)) // src0_modifiers
8931 .add(Inst.getOperand(2))
8932 .add(Inst.getOperand(3)) // clamp
8933 .add(Inst.getOperand(4)) // omod
8934 .setMIFlags(Inst.getFlags());
8935 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8936 NewInstr.addImm(0); // opsel0
8937 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8938 legalizeOperands(*NewInstr, MDT);
8939 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8940 Inst.eraseFromParent();
8941 return;
8942 }
8943 }
8944
8945 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8946 // We cannot move this instruction to the VALU, so we should try to
8947 // legalize its operands instead.
8948 legalizeOperands(Inst, MDT);
8949 return;
8950 }
8951 // Handle converting generic instructions like COPY-to-SGPR into
8952 // COPY-to-VGPR.
8953 if (NewOpcode == Opcode) {
8954 Register DstReg = Inst.getOperand(0).getReg();
8955 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8956
8957 if (Inst.isCopy() && DstReg.isPhysical() &&
8958 Inst.getOperand(1).getReg().isVirtual()) {
8959 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8960 V2SPhyCopiesToErase);
8961 return;
8962 }
8963
8964 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8965 Register NewDstReg = Inst.getOperand(1).getReg();
8966 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8967 if (const TargetRegisterClass *CommonRC =
8968 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8969 // Instead of creating a copy where src and dst are the same register
8970 // class, we just replace all uses of dst with src. These kinds of
8971 // copies interfere with the heuristics MachineSink uses to decide
8972 // whether or not to split a critical edge. Since the pass assumes
8973 // that copies will end up as machine instructions and not be
8974 // eliminated.
8975 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8976 unsigned SrcSubReg = Inst.getOperand(1).getSubReg();
8977 bool IsUndef = Inst.getOperand(1).isUndef();
8978 for (MachineOperand &UseMO :
8979 make_early_inc_range(MRI.use_operands(DstReg))) {
8980 UseMO.setSubReg(
8981 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8982 UseMO.setReg(NewDstReg);
8983 if (IsUndef)
8984 UseMO.setIsUndef();
8985 }
8986 MRI.clearKillFlags(NewDstReg);
8987
8988 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8989 llvm_unreachable("failed to constrain register");
8990
8991 Inst.eraseFromParent();
8992
8993 for (MachineOperand &UseMO :
8994 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8995 MachineInstr &UseMI = *UseMO.getParent();
8996
8997 // Legalize t16 operands since replaceReg is called after
8998 // addUsersToVALU.
9000
9001 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
9002 if (const TargetRegisterClass *OpRC =
9003 getRegClass(UseMI.getDesc(), OpIdx))
9004 MRI.constrainRegClass(NewDstReg, OpRC);
9005 }
9006
9007 return;
9008 }
9009 }
9010
9011 // If this is a v2s copy between 16bit and 32bit reg,
9012 // replace vgpr copy to reg_sequence/extract_subreg
9013 // This can be remove after we have sgpr16 in place
9014 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
9015 Inst.getOperand(1).getReg().isVirtual() &&
9016 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
9017 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
9018 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
9019 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9020 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
9021 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
9022 get(AMDGPU::IMPLICIT_DEF), Undef);
9023 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
9024 get(AMDGPU::REG_SEQUENCE), NewDstReg)
9025 .addReg(Inst.getOperand(1).getReg())
9026 .addImm(AMDGPU::lo16)
9027 .addReg(Undef)
9028 .addImm(AMDGPU::hi16);
9029 Inst.eraseFromParent();
9030 MRI.replaceRegWith(DstReg, NewDstReg);
9031 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9032 return;
9033 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
9034 AMDGPU::lo16)) {
9035 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
9036 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9037 MRI.replaceRegWith(DstReg, NewDstReg);
9038 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9039 return;
9040 }
9041 }
9042
9043 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9044 MRI.replaceRegWith(DstReg, NewDstReg);
9045 legalizeOperands(Inst, MDT);
9046 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9047 return;
9048 }
9049
9050 // Use the new VALU Opcode.
9051 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
9052 .setMIFlags(Inst.getFlags());
9053 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
9054 // Intersperse VOP3 modifiers among the SALU operands.
9055 NewInstr->addOperand(Inst.getOperand(0));
9056 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9057 AMDGPU::OpName::src0_modifiers) >= 0)
9058 NewInstr.addImm(0);
9059 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
9060 const MachineOperand &Src = Inst.getOperand(1);
9061 NewInstr->addOperand(Src);
9062 }
9063
9064 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
9065 // We are converting these to a BFE, so we need to add the missing
9066 // operands for the size and offset.
9067 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
9068 NewInstr.addImm(0);
9069 NewInstr.addImm(Size);
9070 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
9071 // The VALU version adds the second operand to the result, so insert an
9072 // extra 0 operand.
9073 NewInstr.addImm(0);
9074 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
9075 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
9076 // If we need to move this to VGPRs, we need to unpack the second
9077 // operand back into the 2 separate ones for bit offset and width.
9078 assert(OffsetWidthOp.isImm() &&
9079 "Scalar BFE is only implemented for constant width and offset");
9080 uint32_t Imm = OffsetWidthOp.getImm();
9081
9082 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9083 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9084 NewInstr.addImm(Offset);
9085 NewInstr.addImm(BitWidth);
9086 } else {
9087 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9088 AMDGPU::OpName::src1_modifiers) >= 0)
9089 NewInstr.addImm(0);
9090 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
9091 NewInstr->addOperand(Inst.getOperand(2));
9092 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9093 AMDGPU::OpName::src2_modifiers) >= 0)
9094 NewInstr.addImm(0);
9095 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
9096 NewInstr->addOperand(Inst.getOperand(3));
9097 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
9098 NewInstr.addImm(0);
9099 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
9100 NewInstr.addImm(0);
9101 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
9102 NewInstr.addImm(0);
9103 }
9104 } else {
9105 // Just copy the SALU operands.
9106 for (const MachineOperand &Op : Inst.explicit_operands())
9107 NewInstr->addOperand(Op);
9108 }
9109
9110 // Remove any references to SCC. Vector instructions can't read from it, and
9111 // We're just about to add the implicit use / defs of VCC, and we don't want
9112 // both.
9113 bool DeadSCCDef = false;
9114 for (MachineOperand &Op : Inst.implicit_operands()) {
9115 if (Op.getReg() == AMDGPU::SCC) {
9116 // Only propagate through live-def of SCC.
9117 if (Op.isDef()) {
9118 if (Op.isDead())
9119 DeadSCCDef = true;
9120 else
9121 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
9122 continue;
9123 }
9124
9125 addSCCDefsToVALUWorklist(NewInstr, Worklist);
9126 }
9127 }
9128 Inst.eraseFromParent();
9129 Register NewDstReg;
9130 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
9131 Register DstReg = NewInstr->getOperand(0).getReg();
9132 assert(DstReg.isVirtual());
9133 // Update the destination register class.
9134 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
9135 assert(NewDstRC);
9136 NewDstReg = MRI.createVirtualRegister(NewDstRC);
9137 MRI.replaceRegWith(DstReg, NewDstReg);
9138 }
9139 fixImplicitOperands(*NewInstr);
9140
9141 if (DeadSCCDef) {
9142 // A scalar op with a dead SCC def lowers to a VALU op whose VCC def will
9143 // also be dead.
9144 if (MachineOperand *VCCDef =
9145 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
9146 VCCDef->setIsDead();
9147 }
9148
9149 // Legalize the operands
9150 legalizeOperands(*NewInstr, MDT);
9151 if (NewDstReg)
9152 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9153}
9154
9155// Add/sub require special handling to deal with carry outs.
9156std::pair<bool, MachineBasicBlock *>
9157SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
9158 MachineDominatorTree *MDT) const {
9159 if (ST.hasAddNoCarryInsts()) {
9160 // Assume there is no user of scc since we don't select this in that case.
9161 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
9162 // is used.
9163
9164 MachineBasicBlock &MBB = *Inst.getParent();
9165 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9166
9167 Register OldDstReg = Inst.getOperand(0).getReg();
9168 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9169
9170 unsigned Opc = Inst.getOpcode();
9171 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
9172
9173 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
9174 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9175
9176 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
9177 Inst.removeOperand(3);
9178
9179 Inst.setDesc(get(NewOpc));
9180 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
9181 Inst.addImplicitDefUseOperands(*MBB.getParent());
9182 MRI.replaceRegWith(OldDstReg, ResultReg);
9183 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
9184
9185 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9186 return std::pair(true, NewBB);
9187 }
9188
9189 return std::pair(false, nullptr);
9190}
9191
9192void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
9193 MachineDominatorTree *MDT) const {
9194
9195 MachineBasicBlock &MBB = *Inst.getParent();
9196 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9197 MachineBasicBlock::iterator MII = Inst;
9198 const DebugLoc &DL = Inst.getDebugLoc();
9199
9200 MachineOperand &Dest = Inst.getOperand(0);
9201 MachineOperand &Src0 = Inst.getOperand(1);
9202 MachineOperand &Src1 = Inst.getOperand(2);
9203 MachineOperand &Cond = Inst.getOperand(3);
9204
9205 Register CondReg = Cond.getReg();
9206 bool IsSCC = (CondReg == AMDGPU::SCC);
9207
9208 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
9209 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
9210 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
9211 // output directly into the V_CNDMASK.
9212 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
9213 (Src1.getImm() == 0)) {
9214 for (MachineOperand &UseMO :
9216 MachineInstr &UseMI = *UseMO.getParent();
9217 switch (UseMI.getOpcode()) {
9218 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9219 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9220 case AMDGPU::V_CNDMASK_B16_t16_e32:
9221 case AMDGPU::V_CNDMASK_B16_t16_e64:
9222 case AMDGPU::V_CNDMASK_B32_e32:
9223 case AMDGPU::V_CNDMASK_B32_e64:
9224 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9225 if (UseMO.isImplicit() ||
9226 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
9227 UseMO.setReg(CondReg);
9228 }
9229 }
9230 if (MRI.use_nodbg_empty(Dest.getReg()))
9231 return;
9232 }
9233
9234 Register NewCondReg = CondReg;
9235 if (IsSCC) {
9236 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
9237 NewCondReg = MRI.createVirtualRegister(TC);
9238
9239 // Now look for the closest SCC def if it is a copy
9240 // replacing the CondReg with the COPY source register
9241 bool CopyFound = false;
9242 for (MachineInstr &CandI :
9244 Inst.getParent()->rend())) {
9245 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
9246 -1) {
9247 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9248 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
9249 .addReg(CandI.getOperand(1).getReg());
9250 CopyFound = true;
9251 }
9252 break;
9253 }
9254 }
9255 if (!CopyFound) {
9256 // SCC def is not a copy
9257 // Insert a trivial select instead of creating a copy, because a copy from
9258 // SCC would semantically mean just copying a single bit, but we may need
9259 // the result to be a vector condition mask that needs preserving.
9260 unsigned Opcode =
9261 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9262 auto NewSelect =
9263 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
9264 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
9265 }
9266 }
9267
9268 Register NewDestReg = MRI.createVirtualRegister(
9269 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
9270 MachineInstr *NewInst;
9271 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
9272 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9273 .addImm(0)
9274 .add(Src1) // False
9275 .addImm(0)
9276 .add(Src0) // True
9277 .addReg(NewCondReg);
9278 } else {
9279 NewInst =
9280 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
9281 .add(Src1) // False
9282 .add(Src0) // True
9283 .addReg(NewCondReg);
9284 }
9285 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
9286 legalizeOperands(*NewInst, MDT);
9287 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9288}
9289
9290void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
9291 MachineInstr &Inst) const {
9292 MachineBasicBlock &MBB = *Inst.getParent();
9293 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9294 MachineBasicBlock::iterator MII = Inst;
9295 const DebugLoc &DL = Inst.getDebugLoc();
9296
9297 MachineOperand &Dest = Inst.getOperand(0);
9298 MachineOperand &Src = Inst.getOperand(1);
9299 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9300 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9301
9302 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9303 unsigned SubOp =
9304 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9305
9306 MachineInstrBuilder Sub =
9307 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(Src.getReg());
9308 if (HasCarryOut)
9309 Sub.setOperandDead(3); // Dead vcc
9310
9311 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9312 .addReg(Src.getReg())
9313 .addReg(TmpReg);
9314
9315 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9316 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9317}
9318
9319void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
9320 MachineInstr &Inst) const {
9321 MachineBasicBlock &MBB = *Inst.getParent();
9322 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9323 MachineBasicBlock::iterator MII = Inst;
9324 const DebugLoc &DL = Inst.getDebugLoc();
9325
9326 MachineOperand &Dest = Inst.getOperand(0);
9327 MachineOperand &Src1 = Inst.getOperand(1);
9328 MachineOperand &Src2 = Inst.getOperand(2);
9329 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9330 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9331 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9332
9333 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9334 unsigned SubOp =
9335 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9336
9337 MachineInstrBuilder Sub1 = BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
9338 .addReg(Src1.getReg())
9339 .addReg(Src2.getReg());
9340
9341 MachineInstrBuilder Sub2 =
9342 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
9343
9344 if (HasCarryOut) {
9345 Sub1.setOperandDead(3); // Dead vcc
9346 Sub2.setOperandDead(3); // Dead vcc
9347 }
9348
9349 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9350 .addReg(SubResultReg)
9351 .addReg(TmpReg);
9352
9353 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9354 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9355}
9356
9357void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
9358 MachineInstr &Inst) const {
9359 MachineBasicBlock &MBB = *Inst.getParent();
9360 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9361 MachineBasicBlock::iterator MII = Inst;
9362 const DebugLoc &DL = Inst.getDebugLoc();
9363
9364 MachineOperand &Dest = Inst.getOperand(0);
9365 MachineOperand &Src0 = Inst.getOperand(1);
9366 MachineOperand &Src1 = Inst.getOperand(2);
9367
9368 if (ST.hasDLInsts()) {
9369 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9370 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
9371 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
9372
9373 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
9374 .add(Src0)
9375 .add(Src1);
9376
9377 MRI.replaceRegWith(Dest.getReg(), NewDest);
9378 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9379 } else {
9380 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
9381 // invert either source and then perform the XOR. If either source is a
9382 // scalar register, then we can leave the inversion on the scalar unit to
9383 // achieve a better distribution of scalar and vector instructions.
9384 bool Src0IsSGPR = Src0.isReg() &&
9385 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
9386 bool Src1IsSGPR = Src1.isReg() &&
9387 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
9388 MachineInstr *Xor;
9389 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9390 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9391
9392 // Build a pair of scalar instructions and add them to the work list.
9393 // The next iteration over the work list will lower these to the vector
9394 // unit as necessary.
9395 if (Src0IsSGPR) {
9396 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
9397 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9398 .addReg(Temp)
9399 .add(Src1);
9400 } else if (Src1IsSGPR) {
9401 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
9402 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9403 .add(Src0)
9404 .addReg(Temp);
9405 } else {
9406 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
9407 .add(Src0)
9408 .add(Src1);
9409 MachineInstr *Not =
9410 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
9411 Worklist.insert(Not);
9412 }
9413
9414 MRI.replaceRegWith(Dest.getReg(), NewDest);
9415
9416 Worklist.insert(Xor);
9417
9418 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9419 }
9420}
9421
9422void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
9423 MachineInstr &Inst,
9424 unsigned Opcode) const {
9425 MachineBasicBlock &MBB = *Inst.getParent();
9426 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9427 MachineBasicBlock::iterator MII = Inst;
9428 const DebugLoc &DL = Inst.getDebugLoc();
9429
9430 MachineOperand &Dest = Inst.getOperand(0);
9431 MachineOperand &Src0 = Inst.getOperand(1);
9432 MachineOperand &Src1 = Inst.getOperand(2);
9433
9434 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9435 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9436
9437 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
9438 .add(Src0)
9439 .add(Src1);
9440
9441 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
9442 .addReg(Interm);
9443
9444 Worklist.insert(&Op);
9445 Worklist.insert(&Not);
9446
9447 MRI.replaceRegWith(Dest.getReg(), NewDest);
9448 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9449}
9450
9451void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
9452 MachineInstr &Inst,
9453 unsigned Opcode) const {
9454 MachineBasicBlock &MBB = *Inst.getParent();
9455 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9456 MachineBasicBlock::iterator MII = Inst;
9457 const DebugLoc &DL = Inst.getDebugLoc();
9458
9459 MachineOperand &Dest = Inst.getOperand(0);
9460 MachineOperand &Src0 = Inst.getOperand(1);
9461 MachineOperand &Src1 = Inst.getOperand(2);
9462
9463 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9464 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9465
9466 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
9467 .add(Src1);
9468
9469 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
9470 .add(Src0)
9471 .addReg(Interm);
9472
9473 Worklist.insert(&Not);
9474 Worklist.insert(&Op);
9475
9476 MRI.replaceRegWith(Dest.getReg(), NewDest);
9477 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9478}
9479
9480void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
9481 MachineInstr &Inst, unsigned Opcode,
9482 bool Swap) const {
9483 MachineBasicBlock &MBB = *Inst.getParent();
9484 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9485
9486 MachineOperand &Dest = Inst.getOperand(0);
9487 MachineOperand &Src0 = Inst.getOperand(1);
9488 const DebugLoc &DL = Inst.getDebugLoc();
9489
9490 MachineBasicBlock::iterator MII = Inst;
9491
9492 const MCInstrDesc &InstDesc = get(Opcode);
9493 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9494 MRI.getRegClass(Src0.getReg()) :
9495 &AMDGPU::SGPR_32RegClass;
9496
9497 const TargetRegisterClass *Src0SubRC =
9498 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9499
9500 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9501 AMDGPU::sub0, Src0SubRC);
9502
9503 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9504 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9505 const TargetRegisterClass *NewDestSubRC =
9506 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9507
9508 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9509 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
9510
9511 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9512 AMDGPU::sub1, Src0SubRC);
9513
9514 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9515 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
9516
9517 if (Swap)
9518 std::swap(DestSub0, DestSub1);
9519
9520 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9521 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9522 .addReg(DestSub0)
9523 .addImm(AMDGPU::sub0)
9524 .addReg(DestSub1)
9525 .addImm(AMDGPU::sub1);
9526
9527 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9528
9529 Worklist.insert(&LoHalf);
9530 Worklist.insert(&HiHalf);
9531
9532 // We don't need to legalizeOperands here because for a single operand, src0
9533 // will support any kind of input.
9534
9535 // Move all users of this moved value.
9536 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9537}
9538
9539// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9540// split the s_mul_u64 in 32-bit vector multiplications.
9541void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9542 MachineInstr &Inst,
9543 MachineDominatorTree *MDT) const {
9544 MachineBasicBlock &MBB = *Inst.getParent();
9545 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9546
9547 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9548 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9549 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9550
9551 MachineOperand &Dest = Inst.getOperand(0);
9552 MachineOperand &Src0 = Inst.getOperand(1);
9553 MachineOperand &Src1 = Inst.getOperand(2);
9554 const DebugLoc &DL = Inst.getDebugLoc();
9555 MachineBasicBlock::iterator MII = Inst;
9556
9557 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9558 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9559 const TargetRegisterClass *Src0SubRC =
9560 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9561 if (RI.isSGPRClass(Src0SubRC))
9562 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9563 const TargetRegisterClass *Src1SubRC =
9564 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9565 if (RI.isSGPRClass(Src1SubRC))
9566 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9567
9568 // First, we extract the low 32-bit and high 32-bit values from each of the
9569 // operands.
9570 MachineOperand Op0L =
9571 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9572 MachineOperand Op1L =
9573 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9574 MachineOperand Op0H =
9575 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9576 MachineOperand Op1H =
9577 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9578
9579 // The multilication is done as follows:
9580 //
9581 // Op1H Op1L
9582 // * Op0H Op0L
9583 // --------------------
9584 // Op1H*Op0L Op1L*Op0L
9585 // + Op1H*Op0H Op1L*Op0H
9586 // -----------------------------------------
9587 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9588 //
9589 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9590 // value and that would overflow.
9591 // The low 32-bit value is Op1L*Op0L.
9592 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9593
9594 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9595 MachineInstr *Op1L_Op0H =
9596 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9597 .add(Op1L)
9598 .add(Op0H);
9599
9600 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9601 MachineInstr *Op1H_Op0L =
9602 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9603 .add(Op1H)
9604 .add(Op0L);
9605
9606 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9607 MachineInstr *Carry =
9608 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9609 .add(Op1L)
9610 .add(Op0L);
9611
9612 MachineInstr *LoHalf =
9613 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9614 .add(Op1L)
9615 .add(Op0L);
9616
9617 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9618 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9619 .addReg(Op1L_Op0H_Reg)
9620 .addReg(Op1H_Op0L_Reg);
9621
9622 MachineInstr *HiHalf =
9623 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9624 .addReg(AddReg)
9625 .addReg(CarryReg);
9626
9627 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9628 .addReg(DestSub0)
9629 .addImm(AMDGPU::sub0)
9630 .addReg(DestSub1)
9631 .addImm(AMDGPU::sub1);
9632
9633 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9634
9635 // Try to legalize the operands in case we need to swap the order to keep it
9636 // valid.
9637 legalizeOperands(*Op1L_Op0H, MDT);
9638 legalizeOperands(*Op1H_Op0L, MDT);
9639 legalizeOperands(*Carry, MDT);
9640 legalizeOperands(*LoHalf, MDT);
9641 legalizeOperands(*Add, MDT);
9642 legalizeOperands(*HiHalf, MDT);
9643
9644 // Move all users of this moved value.
9645 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9646}
9647
9648// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9649// multiplications.
9650void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9651 MachineInstr &Inst,
9652 MachineDominatorTree *MDT) const {
9653 MachineBasicBlock &MBB = *Inst.getParent();
9654 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9655
9656 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9657 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9658 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9659
9660 MachineOperand &Dest = Inst.getOperand(0);
9661 MachineOperand &Src0 = Inst.getOperand(1);
9662 MachineOperand &Src1 = Inst.getOperand(2);
9663 const DebugLoc &DL = Inst.getDebugLoc();
9664 MachineBasicBlock::iterator MII = Inst;
9665
9666 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9667 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9668 const TargetRegisterClass *Src0SubRC =
9669 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9670 if (RI.isSGPRClass(Src0SubRC))
9671 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9672 const TargetRegisterClass *Src1SubRC =
9673 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9674 if (RI.isSGPRClass(Src1SubRC))
9675 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9676
9677 // First, we extract the low 32-bit and high 32-bit values from each of the
9678 // operands.
9679 MachineOperand Op0L =
9680 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9681 MachineOperand Op1L =
9682 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9683
9684 unsigned Opc = Inst.getOpcode();
9685 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9686 ? AMDGPU::V_MUL_HI_U32_e64
9687 : AMDGPU::V_MUL_HI_I32_e64;
9688 MachineInstr *HiHalf =
9689 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9690
9691 MachineInstr *LoHalf =
9692 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9693 .add(Op1L)
9694 .add(Op0L);
9695
9696 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9697 .addReg(DestSub0)
9698 .addImm(AMDGPU::sub0)
9699 .addReg(DestSub1)
9700 .addImm(AMDGPU::sub1);
9701
9702 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9703
9704 // Try to legalize the operands in case we need to swap the order to keep it
9705 // valid.
9706 legalizeOperands(*HiHalf, MDT);
9707 legalizeOperands(*LoHalf, MDT);
9708
9709 // Move all users of this moved value.
9710 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9711}
9712
9713void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9714 MachineInstr &Inst, unsigned Opcode,
9715 MachineDominatorTree *MDT) const {
9716 MachineBasicBlock &MBB = *Inst.getParent();
9717 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9718
9719 MachineOperand &Dest = Inst.getOperand(0);
9720 MachineOperand &Src0 = Inst.getOperand(1);
9721 MachineOperand &Src1 = Inst.getOperand(2);
9722 const DebugLoc &DL = Inst.getDebugLoc();
9723
9724 MachineBasicBlock::iterator MII = Inst;
9725
9726 const MCInstrDesc &InstDesc = get(Opcode);
9727 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9728 MRI.getRegClass(Src0.getReg()) :
9729 &AMDGPU::SGPR_32RegClass;
9730
9731 const TargetRegisterClass *Src0SubRC =
9732 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9733 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9734 MRI.getRegClass(Src1.getReg()) :
9735 &AMDGPU::SGPR_32RegClass;
9736
9737 const TargetRegisterClass *Src1SubRC =
9738 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9739
9740 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9741 AMDGPU::sub0, Src0SubRC);
9742 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9743 AMDGPU::sub0, Src1SubRC);
9744 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9745 AMDGPU::sub1, Src0SubRC);
9746 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9747 AMDGPU::sub1, Src1SubRC);
9748
9749 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9750 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9751 const TargetRegisterClass *NewDestSubRC =
9752 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9753
9754 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9755 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9756 .add(SrcReg0Sub0)
9757 .add(SrcReg1Sub0);
9758
9759 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9760 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9761 .add(SrcReg0Sub1)
9762 .add(SrcReg1Sub1);
9763
9764 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9765 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9766 .addReg(DestSub0)
9767 .addImm(AMDGPU::sub0)
9768 .addReg(DestSub1)
9769 .addImm(AMDGPU::sub1);
9770
9771 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9772
9773 Worklist.insert(&LoHalf);
9774 Worklist.insert(&HiHalf);
9775
9776 // Move all users of this moved value.
9777 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9778}
9779
9780void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9781 MachineInstr &Inst,
9782 MachineDominatorTree *MDT) const {
9783 MachineBasicBlock &MBB = *Inst.getParent();
9784 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9785
9786 MachineOperand &Dest = Inst.getOperand(0);
9787 MachineOperand &Src0 = Inst.getOperand(1);
9788 MachineOperand &Src1 = Inst.getOperand(2);
9789 const DebugLoc &DL = Inst.getDebugLoc();
9790
9791 MachineBasicBlock::iterator MII = Inst;
9792
9793 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9794
9795 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9796
9797 MachineOperand* Op0;
9798 MachineOperand* Op1;
9799
9800 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9801 Op0 = &Src0;
9802 Op1 = &Src1;
9803 } else {
9804 Op0 = &Src1;
9805 Op1 = &Src0;
9806 }
9807
9808 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9809 .add(*Op0);
9810
9811 Register NewDest = MRI.createVirtualRegister(DestRC);
9812
9813 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9814 .addReg(Interm)
9815 .add(*Op1);
9816
9817 MRI.replaceRegWith(Dest.getReg(), NewDest);
9818
9819 Worklist.insert(&Xor);
9820}
9821
9822void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9823 MachineInstr &Inst) const {
9824 MachineBasicBlock &MBB = *Inst.getParent();
9825 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9826
9827 MachineBasicBlock::iterator MII = Inst;
9828 const DebugLoc &DL = Inst.getDebugLoc();
9829
9830 MachineOperand &Dest = Inst.getOperand(0);
9831 MachineOperand &Src = Inst.getOperand(1);
9832
9833 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9834 const TargetRegisterClass *SrcRC = Src.isReg() ?
9835 MRI.getRegClass(Src.getReg()) :
9836 &AMDGPU::SGPR_32RegClass;
9837
9838 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9839 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9840
9841 const TargetRegisterClass *SrcSubRC =
9842 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9843
9844 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9845 AMDGPU::sub0, SrcSubRC);
9846 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9847 AMDGPU::sub1, SrcSubRC);
9848
9849 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9850
9851 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9852
9853 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9854
9855 // We don't need to legalize operands here. src0 for either instruction can be
9856 // an SGPR, and the second input is unused or determined here.
9857 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9858}
9859
9860void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9861 MachineInstr &Inst) const {
9862 MachineBasicBlock &MBB = *Inst.getParent();
9863 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9864 MachineBasicBlock::iterator MII = Inst;
9865 const DebugLoc &DL = Inst.getDebugLoc();
9866
9867 MachineOperand &Dest = Inst.getOperand(0);
9868 uint32_t Imm = Inst.getOperand(2).getImm();
9869 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9870 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9871
9872 (void) Offset;
9873
9874 // Only sext_inreg cases handled.
9875 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9876 Offset == 0 && "Not implemented");
9877
9878 if (BitWidth < 32) {
9879 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9880 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9881 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9882
9883 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9884 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9885 .addImm(0)
9886 .addImm(BitWidth);
9887
9888 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9889 .addImm(31)
9890 .addReg(MidRegLo);
9891
9892 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9893 .addReg(MidRegLo)
9894 .addImm(AMDGPU::sub0)
9895 .addReg(MidRegHi)
9896 .addImm(AMDGPU::sub1);
9897
9898 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9899 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9900 return;
9901 }
9902
9903 MachineOperand &Src = Inst.getOperand(1);
9904 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9905 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9906
9907 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9908 .addImm(31)
9909 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9910
9911 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9912 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9913 .addImm(AMDGPU::sub0)
9914 .addReg(TmpReg)
9915 .addImm(AMDGPU::sub1);
9916
9917 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9918 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9919}
9920
9921void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9922 MachineInstr &Inst, unsigned Opcode,
9923 MachineDominatorTree *MDT) const {
9924 // (S_FLBIT_I32_B64 hi:lo) ->
9925 // -> (umin (V_FFBH_U32_e32 hi), (or (V_FFBH_U32_e32 lo), 32))
9926 // (S_FF1_I32_B64 hi:lo) ->
9927 // ->(umin (or (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9928
9929 MachineBasicBlock &MBB = *Inst.getParent();
9930 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9931 MachineBasicBlock::iterator MII = Inst;
9932 const DebugLoc &DL = Inst.getDebugLoc();
9933
9934 MachineOperand &Dest = Inst.getOperand(0);
9935 MachineOperand &Src = Inst.getOperand(1);
9936
9937 const MCInstrDesc &InstDesc = get(Opcode);
9938
9939 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9940
9941 const TargetRegisterClass *SrcRC =
9942 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9943 const TargetRegisterClass *SrcSubRC =
9944 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9945
9946 MachineOperand SrcRegSub0 =
9947 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9948 MachineOperand SrcRegSub1 =
9949 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9950
9951 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9952 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9953 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9954 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9955
9956 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9957
9958 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9959
9960 BuildMI(MBB, MII, DL, get(AMDGPU::V_OR_B32_e32), MidReg3)
9961 .addImm(32)
9962 .addReg(IsCtlz ? MidReg1 : MidReg2);
9963
9964 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9965 .addReg(MidReg3)
9966 .addReg(IsCtlz ? MidReg2 : MidReg1);
9967
9968 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9969
9970 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9971}
9972
9973void SIInstrInfo::addUsersToMoveToVALUWorklist(
9974 Register DstReg, MachineRegisterInfo &MRI,
9975 SIInstrWorklist &Worklist) const {
9976 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9977 MachineInstr &UseMI = *MO.getParent();
9978
9979 unsigned OpNo = 0;
9980
9981 switch (UseMI.getOpcode()) {
9982 case AMDGPU::COPY:
9983 case AMDGPU::WQM:
9984 case AMDGPU::SOFT_WQM:
9985 case AMDGPU::STRICT_WWM:
9986 case AMDGPU::STRICT_WQM:
9987 case AMDGPU::REG_SEQUENCE:
9988 case AMDGPU::PHI:
9989 case AMDGPU::INSERT_SUBREG:
9990 break;
9991 default:
9992 OpNo = MO.getOperandNo();
9993 break;
9994 }
9995
9996 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9997 MRI.constrainRegClass(DstReg, OpRC);
9998
9999 if (!RI.hasVectorRegisters(OpRC))
10000 Worklist.insert(&UseMI);
10001 else
10002 // Legalization could change user list.
10003 legalizeOperandsVALUt16(UseMI, OpNo, MRI);
10004 }
10005}
10006
10007void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
10009 MachineInstr &Inst) const {
10010 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10011 MachineBasicBlock *MBB = Inst.getParent();
10012 MachineOperand &Src0 = Inst.getOperand(1);
10013 MachineOperand &Src1 = Inst.getOperand(2);
10014 const DebugLoc &DL = Inst.getDebugLoc();
10015
10016 if (ST.useRealTrue16Insts()) {
10017 Register SrcReg0, SrcReg1;
10018 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
10019 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10020 BuildMI(*MBB, Inst, DL,
10021 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
10022 .add(Src0);
10023 } else {
10024 SrcReg0 = Src0.getReg();
10025 }
10026
10027 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
10028 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10029 BuildMI(*MBB, Inst, DL,
10030 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
10031 .add(Src1);
10032 } else {
10033 SrcReg1 = Src1.getReg();
10034 }
10035
10036 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
10037 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
10038
10039 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
10040 switch (Inst.getOpcode()) {
10041 case AMDGPU::S_PACK_LL_B32_B16:
10042 NewMI
10043 .addReg(SrcReg0, {},
10044 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10045 .addImm(AMDGPU::lo16)
10046 .addReg(SrcReg1, {},
10047 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10048 .addImm(AMDGPU::hi16);
10049 break;
10050 case AMDGPU::S_PACK_LH_B32_B16:
10051 NewMI
10052 .addReg(SrcReg0, {},
10053 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10054 .addImm(AMDGPU::lo16)
10055 .addReg(SrcReg1, {}, AMDGPU::hi16)
10056 .addImm(AMDGPU::hi16);
10057 break;
10058 case AMDGPU::S_PACK_HL_B32_B16:
10059 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10060 .addImm(AMDGPU::lo16)
10061 .addReg(SrcReg1, {},
10062 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10063 .addImm(AMDGPU::hi16);
10064 break;
10065 case AMDGPU::S_PACK_HH_B32_B16:
10066 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10067 .addImm(AMDGPU::lo16)
10068 .addReg(SrcReg1, {}, AMDGPU::hi16)
10069 .addImm(AMDGPU::hi16);
10070 break;
10071 default:
10072 llvm_unreachable("unhandled s_pack_* instruction");
10073 }
10074
10075 MachineOperand &Dest = Inst.getOperand(0);
10076 MRI.replaceRegWith(Dest.getReg(), ResultReg);
10077 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10078 return;
10079 }
10080
10081 switch (Inst.getOpcode()) {
10082 case AMDGPU::S_PACK_LL_B32_B16: {
10083 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10084 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10085
10086 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
10087 // 0.
10088 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10089 .addImm(0xffff);
10090
10091 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
10092 .addReg(ImmReg)
10093 .add(Src0);
10094
10095 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
10096 .add(Src1)
10097 .addImm(16)
10098 .addReg(TmpReg);
10099 break;
10100 }
10101 case AMDGPU::S_PACK_LH_B32_B16: {
10102 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10103 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10104 .addImm(0xffff);
10105 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
10106 .addReg(ImmReg)
10107 .add(Src0)
10108 .add(Src1);
10109 break;
10110 }
10111 case AMDGPU::S_PACK_HL_B32_B16: {
10112 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10113 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
10114 .addImm(16)
10115 .add(Src0);
10116 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
10117 .add(Src1)
10118 .addImm(16)
10119 .addReg(TmpReg);
10120 break;
10121 }
10122 case AMDGPU::S_PACK_HH_B32_B16: {
10123 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10124 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10125 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
10126 .addImm(16)
10127 .add(Src0);
10128 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10129 .addImm(0xffff0000);
10130 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
10131 .add(Src1)
10132 .addReg(ImmReg)
10133 .addReg(TmpReg);
10134 break;
10135 }
10136 default:
10137 llvm_unreachable("unhandled s_pack_* instruction");
10138 }
10139
10140 MachineOperand &Dest = Inst.getOperand(0);
10141 MRI.replaceRegWith(Dest.getReg(), ResultReg);
10142 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10143}
10144
10145void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
10146 MachineInstr &SCCDefInst,
10147 SIInstrWorklist &Worklist,
10148 Register NewCond) const {
10149
10150 // Ensure that def inst defines SCC, which is still live.
10151 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
10152 !Op.isDead() && Op.getParent() == &SCCDefInst);
10153 SmallVector<MachineInstr *, 4> CopyToDelete;
10154 // This assumes that all the users of SCC are in the same block
10155 // as the SCC def.
10156 for (MachineInstr &MI : // Skip the def inst itself.
10157 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
10158 SCCDefInst.getParent()->end())) {
10159 // Check if SCC is used first.
10160 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
10161 if (SCCIdx != -1) {
10162 if (MI.isCopy()) {
10163 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10164 Register DestReg = MI.getOperand(0).getReg();
10165
10166 MRI.replaceRegWith(DestReg, NewCond);
10167 CopyToDelete.push_back(&MI);
10168 } else {
10169
10170 if (NewCond.isValid())
10171 MI.getOperand(SCCIdx).setReg(NewCond);
10172
10173 Worklist.insert(&MI);
10174 }
10175 }
10176 // Exit if we find another SCC def.
10177 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
10178 break;
10179 }
10180 for (auto &Copy : CopyToDelete)
10181 Copy->eraseFromParent();
10182}
10183
10184// Instructions that use SCC may be converted to VALU instructions. When that
10185// happens, the SCC register is changed to VCC_LO. The instruction that defines
10186// SCC must be changed to an instruction that defines VCC. This function makes
10187// sure that the instruction that defines SCC is added to the moveToVALU
10188// worklist.
10189void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
10190 SIInstrWorklist &Worklist) const {
10191 // Look for a preceding instruction that either defines VCC or SCC. If VCC
10192 // then there is nothing to do because the defining instruction has been
10193 // converted to a VALU already. If SCC then that instruction needs to be
10194 // converted to a VALU.
10195 for (MachineInstr &MI :
10196 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
10197 SCCUseInst->getParent()->rend())) {
10198 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
10199 break;
10200 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
10201 Worklist.insert(&MI);
10202 break;
10203 }
10204 }
10205}
10206
10207const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
10208 const MachineInstr &Inst) const {
10209 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
10210
10211 switch (Inst.getOpcode()) {
10212 // For target instructions, getOpRegClass just returns the virtual register
10213 // class associated with the operand, so we need to find an equivalent VGPR
10214 // register class in order to move the instruction to the VALU.
10215 case AMDGPU::COPY:
10216 case AMDGPU::PHI:
10217 case AMDGPU::REG_SEQUENCE:
10218 case AMDGPU::INSERT_SUBREG:
10219 case AMDGPU::WQM:
10220 case AMDGPU::SOFT_WQM:
10221 case AMDGPU::STRICT_WWM:
10222 case AMDGPU::STRICT_WQM: {
10223 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
10224 if (RI.isAGPRClass(SrcRC)) {
10225 if (RI.isAGPRClass(NewDstRC))
10226 return nullptr;
10227
10228 switch (Inst.getOpcode()) {
10229 case AMDGPU::PHI:
10230 case AMDGPU::REG_SEQUENCE:
10231 case AMDGPU::INSERT_SUBREG:
10232 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10233 break;
10234 default:
10235 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10236 }
10237
10238 if (!NewDstRC)
10239 return nullptr;
10240 } else {
10241 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10242 return nullptr;
10243
10244 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10245 if (!NewDstRC)
10246 return nullptr;
10247 }
10248
10249 return NewDstRC;
10250 }
10251 default:
10252 return NewDstRC;
10253 }
10254}
10255
10256// Find the one SGPR operand we are allowed to use.
10257Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
10258 int OpIndices[3]) const {
10259 const MCInstrDesc &Desc = MI.getDesc();
10260
10261 // Find the one SGPR operand we are allowed to use.
10262 //
10263 // First we need to consider the instruction's operand requirements before
10264 // legalizing. Some operands are required to be SGPRs, such as implicit uses
10265 // of VCC, but we are still bound by the constant bus requirement to only use
10266 // one.
10267 //
10268 // If the operand's class is an SGPR, we can never move it.
10269
10270 Register SGPRReg = findImplicitSGPRRead(MI);
10271 if (SGPRReg)
10272 return SGPRReg;
10273
10274 Register UsedSGPRs[3] = {Register()};
10275 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10276
10277 for (unsigned i = 0; i < 3; ++i) {
10278 int Idx = OpIndices[i];
10279 if (Idx == -1)
10280 break;
10281
10282 const MachineOperand &MO = MI.getOperand(Idx);
10283 if (!MO.isReg())
10284 continue;
10285
10286 // Is this operand statically required to be an SGPR based on the operand
10287 // constraints?
10288 const TargetRegisterClass *OpRC =
10289 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
10290 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10291 if (IsRequiredSGPR)
10292 return MO.getReg();
10293
10294 // If this could be a VGPR or an SGPR, Check the dynamic register class.
10295 Register Reg = MO.getReg();
10296 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
10297 if (RI.isSGPRClass(RegRC))
10298 UsedSGPRs[i] = Reg;
10299 }
10300
10301 // We don't have a required SGPR operand, so we have a bit more freedom in
10302 // selecting operands to move.
10303
10304 // Try to select the most used SGPR. If an SGPR is equal to one of the
10305 // others, we choose that.
10306 //
10307 // e.g.
10308 // V_FMA_F32 v0, s0, s0, s0 -> No moves
10309 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
10310
10311 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
10312 // prefer those.
10313
10314 if (UsedSGPRs[0]) {
10315 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10316 SGPRReg = UsedSGPRs[0];
10317 }
10318
10319 if (!SGPRReg && UsedSGPRs[1]) {
10320 if (UsedSGPRs[1] == UsedSGPRs[2])
10321 SGPRReg = UsedSGPRs[1];
10322 }
10323
10324 return SGPRReg;
10325}
10326
10328 AMDGPU::OpName OperandName) const {
10329 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10330 return nullptr;
10331
10332 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
10333 if (Idx == -1)
10334 return nullptr;
10335
10336 return &MI.getOperand(Idx);
10337}
10338
10340 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
10341 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
10344 return (Format << 44) |
10345 (1ULL << 56) | // RESOURCE_LEVEL = 1
10346 (3ULL << 60); // OOB_SELECT = 3
10347 }
10348
10349 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
10350 if (ST.isAmdHsaOS()) {
10351 // Set ATC = 1. GFX9 doesn't have this bit.
10352 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10353 RsrcDataFormat |= (1ULL << 56);
10354
10355 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
10356 // BTW, it disables TC L2 and therefore decreases performance.
10357 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
10358 RsrcDataFormat |= (2ULL << 59);
10359 }
10360
10361 return RsrcDataFormat;
10362}
10363
10365 uint64_t Rsrc23 = getDefaultRsrcDataFormat() |
10367 0xffffffff; // Size;
10368
10369 // GFX9 doesn't have ELEMENT_SIZE.
10370 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
10371 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
10372 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
10373 }
10374
10375 // IndexStride = 64 / 32.
10376 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10377 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
10378
10379 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
10380 // Clear them unless we want a huge stride.
10381 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
10382 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
10383 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
10384
10385 return Rsrc23;
10386}
10387
10389 unsigned Opc = MI.getOpcode();
10390
10391 return isSMRD(Opc);
10392}
10393
10395 return get(Opc).mayLoad() &&
10396 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
10397}
10398
10400 TypeSize &MemBytes) const {
10401 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
10402 if (!Addr || !Addr->isFI())
10403 return Register();
10404
10405 assert(!MI.memoperands_empty() &&
10406 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
10407
10408 FrameIndex = Addr->getIndex();
10409
10410 int VDataIdx =
10411 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
10412 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
10413 return MI.getOperand(VDataIdx).getReg();
10414}
10415
10417 TypeSize &MemBytes) const {
10418 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
10419 assert(Addr && Addr->isFI());
10420 FrameIndex = Addr->getIndex();
10421
10422 int DataIdx =
10423 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
10424 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
10425 return MI.getOperand(DataIdx).getReg();
10426}
10427
10429 int &FrameIndex,
10430 TypeSize &MemBytes) const {
10431 if (!MI.mayLoad())
10432 return Register();
10433
10434 if (isMUBUF(MI) || isVGPRSpill(MI))
10435 return isStackAccess(MI, FrameIndex, MemBytes);
10436
10437 if (isSGPRSpill(MI))
10438 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10439
10440 return Register();
10441}
10442
10444 int &FrameIndex,
10445 TypeSize &MemBytes) const {
10446 if (!MI.mayStore())
10447 return Register();
10448
10449 if (isMUBUF(MI) || isVGPRSpill(MI))
10450 return isStackAccess(MI, FrameIndex, MemBytes);
10451
10452 if (isSGPRSpill(MI))
10453 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10454
10455 return Register();
10456}
10457
10459 unsigned Opc = MI.getOpcode();
10461 unsigned DescSize = Desc.getSize();
10462
10463 // If we have a definitive size, we can use it. Otherwise we need to inspect
10464 // the operands to know the size.
10465 if (isFixedSize(MI)) {
10466 unsigned Size = DescSize;
10467
10468 // If we hit the buggy offset, an extra nop will be inserted in MC so
10469 // estimate the worst case.
10470 if (MI.isBranch() && ST.hasOffset3fBug())
10471 Size += 4;
10472
10473 return Size;
10474 }
10475
10476 // Instructions may have a 32-bit literal encoded after them. Check
10477 // operands that could ever be literals.
10478 if (isVALU(MI, /*AllowLDSDMA=*/false) || isSALU(MI)) {
10479 if (isDPP(MI))
10480 return DescSize;
10481 bool HasLiteral = false;
10482 unsigned LiteralSize = 4;
10483 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
10484 const MachineOperand &Op = MI.getOperand(I);
10485 const MCOperandInfo &OpInfo = Desc.operands()[I];
10486 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
10487 HasLiteral = true;
10488 if (ST.has64BitLiterals()) {
10489 switch (OpInfo.OperandType) {
10490 default:
10491 break;
10494 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
10495 LiteralSize = 8;
10496 break;
10499 // A 32-bit literal is only valid when the value fits in BOTH signed
10500 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
10501 // emitter's getLit64Encoding logic. This is because of the lack of
10502 // abilility to tell signedness of the literal, therefore we need to
10503 // be conservative and assume values outside this range require a
10504 // 64-bit literal encoding (8 bytes).
10505 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
10506 !isUInt<32>(Op.getImm()))
10507 LiteralSize = 8;
10508 break;
10509 }
10510 }
10511 break;
10512 }
10513 }
10514 return HasLiteral ? DescSize + LiteralSize : DescSize;
10515 }
10516
10517 // Check whether we have extra NSA words.
10518 if (isMIMG(MI)) {
10519 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
10520 if (VAddr0Idx < 0)
10521 return 8;
10522
10523 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
10524 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10525 }
10526
10527 switch (Opc) {
10528 case TargetOpcode::BUNDLE:
10529 return getInstBundleSize(MI);
10530 case TargetOpcode::INLINEASM:
10531 case TargetOpcode::INLINEASM_BR: {
10532 const MachineFunction *MF = MI.getMF();
10533 const char *AsmStr = MI.getOperand(0).getSymbolName();
10534 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10535 }
10536 default:
10537 if (MI.isMetaInstruction())
10538 return 0;
10539
10540 // If D16 Pseudo inst, get correct MC code size
10541 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10542 if (D16Info) {
10543 // Assume d16_lo/hi inst are always in same size
10544 unsigned LoInstOpcode = D16Info->LoOp;
10545 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10546 DescSize = Desc.getSize();
10547 }
10548
10549 // If FMA Pseudo inst, get correct MC code size
10550 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10551 // All potential lowerings are the same size; arbitrarily pick one.
10552 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10553 DescSize = Desc.getSize();
10554 }
10555
10556 return DescSize;
10557 }
10558}
10559
10562 if (MI.isBranch() && ST.hasOffset3fBug())
10563 return InstSizeVerifyMode::NoVerify;
10564 return InstSizeVerifyMode::ExactSize;
10565}
10566
10569 static const std::pair<int, const char *> TargetIndices[] = {
10570 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10571 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10572 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10573 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10574 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10575 return ArrayRef(TargetIndices);
10576}
10577
10578/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10579/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10582 const ScheduleDAG *DAG) const {
10583 return new GCNHazardRecognizer(DAG->MF);
10584}
10585
10586/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10587/// pass.
10594
10595// Called during:
10596// - pre-RA scheduling and post-RA scheduling
10599 const ScheduleDAGMI *DAG) const {
10600 // Borrowed from Arm Target
10601 // We would like to restrict this hazard recognizer to only
10602 // post-RA scheduling; we can tell that we're post-RA because we don't
10603 // track VRegLiveness.
10604 if (!DAG->hasVRegLiveness())
10605 return new GCNHazardRecognizer(DAG->MF);
10607}
10608
10609std::pair<unsigned, unsigned>
10611 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10612}
10613
10616 static const std::pair<unsigned, const char *> TargetFlags[] = {
10617 {MO_GOTPCREL, "amdgpu-gotprel"},
10618 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10619 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10620 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10621 {MO_REL32_LO, "amdgpu-rel32-lo"},
10622 {MO_REL32_HI, "amdgpu-rel32-hi"},
10623 {MO_REL64, "amdgpu-rel64"},
10624 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10625 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10626 {MO_ABS64, "amdgpu-abs64"},
10627 };
10628
10629 return ArrayRef(TargetFlags);
10630}
10631
10634 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10635 {
10636 {MONoClobber, "amdgpu-noclobber"},
10637 {MOLastUse, "amdgpu-last-use"},
10638 {MOCooperative, "amdgpu-cooperative"},
10639 {MOThreadPrivate, "amdgpu-thread-private"},
10640 };
10641
10642 return ArrayRef(TargetFlags);
10643}
10644
10646 const MachineFunction &MF) const {
10648 assert(SrcReg.isVirtual());
10649 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10650 return AMDGPU::WWM_COPY;
10651
10652 return AMDGPU::COPY;
10653}
10654
10656 uint32_t Opcode = MI.getOpcode();
10657 // Check if it is SGPR spill or wwm-register spill Opcode.
10658 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10659 return true;
10660
10661 const MachineFunction *MF = MI.getMF();
10662 const MachineRegisterInfo &MRI = MF->getRegInfo();
10664
10665 // See if this is Liverange split instruction inserted for SGPR or
10666 // wwm-register. The implicit def inserted for wwm-registers should also be
10667 // included as they can appear at the bb begin.
10668 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10669 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10670 return false;
10671
10672 Register Reg = MI.getOperand(0).getReg();
10673 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10674 return IsLRSplitInst;
10675
10676 return MFI->isWWMReg(Reg);
10677}
10678
10680 Register Reg) const {
10681 // We need to handle instructions which may be inserted during register
10682 // allocation to handle the prolog. The initial prolog instruction may have
10683 // been separated from the start of the block by spills and copies inserted
10684 // needed by the prolog. However, the insertions for scalar registers can
10685 // always be placed at the BB top as they are independent of the exec mask
10686 // value.
10687 bool IsNullOrVectorRegister = true;
10688 if (Reg) {
10689 const MachineFunction *MF = MI.getMF();
10690 const MachineRegisterInfo &MRI = MF->getRegInfo();
10691 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10692 }
10693
10694 return IsNullOrVectorRegister &&
10695 (canAddToBBProlog(MI) ||
10696 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10697 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10698}
10699
10703 const DebugLoc &DL,
10704 Register DestReg) const {
10705 if (ST.hasAddNoCarryInsts())
10706 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10707
10708 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10709 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10710 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10711
10712 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10713 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10714}
10715
10718 const DebugLoc &DL,
10719 Register DestReg,
10720 RegScavenger &RS) const {
10721 if (ST.hasAddNoCarryInsts())
10722 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10723
10724 // If available, prefer to use vcc.
10725 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10726 ? Register(RI.getVCC())
10727 : RS.scavengeRegisterBackwards(
10728 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10729 0, /* AllowSpill */ false);
10730
10731 // TODO: Users need to deal with this.
10732 if (!UnusedCarry.isValid())
10733 return MachineInstrBuilder();
10734
10735 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10736 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10737}
10738
10739bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10740 switch (Opcode) {
10741 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10742 case AMDGPU::SI_KILL_I1_TERMINATOR:
10743 return true;
10744 default:
10745 return false;
10746 }
10747}
10748
10750 switch (Opcode) {
10751 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10752 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10753 case AMDGPU::SI_KILL_I1_PSEUDO:
10754 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10755 default:
10756 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10757 }
10758}
10759
10761 return Imm <= getMaxMUBUFImmOffset(ST);
10762}
10763
10765 // GFX12 field is non-negative 24-bit signed byte offset.
10766 const unsigned OffsetBits =
10767 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10768 return (1 << OffsetBits) - 1;
10769}
10770
10772 if (!ST.isWave32())
10773 return;
10774
10775 if (MI.isInlineAsm())
10776 return;
10777
10778 if (MI.getNumOperands() < MI.getDesc().getNumOperands())
10779 return;
10780
10781 for (auto &Op : MI.implicit_operands()) {
10782 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10783 Op.setReg(AMDGPU::VCC_LO);
10784 }
10785}
10786
10788 if (!isSMRD(MI))
10789 return false;
10790
10791 // Check that it is using a buffer resource.
10792 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10793 if (Idx == -1) // e.g. s_memtime
10794 return false;
10795
10796 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10797 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10798}
10799
10800// Given Imm, split it into the values to put into the SOffset and ImmOffset
10801// fields in an MUBUF instruction. Return false if it is not possible (due to a
10802// hardware bug needing a workaround).
10803//
10804// The required alignment ensures that individual address components remain
10805// aligned if they are aligned to begin with. It also ensures that additional
10806// offsets within the given alignment can be added to the resulting ImmOffset.
10808 uint32_t &ImmOffset, Align Alignment) const {
10809 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10810 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10811 uint32_t Overflow = 0;
10812
10813 if (Imm > MaxImm) {
10814 if (Imm <= MaxImm + 64) {
10815 // Use an SOffset inline constant for 4..64
10816 Overflow = Imm - MaxImm;
10817 Imm = MaxImm;
10818 } else {
10819 // Try to keep the same value in SOffset for adjacent loads, so that
10820 // the corresponding register contents can be re-used.
10821 //
10822 // Load values with all low-bits (except for alignment bits) set into
10823 // SOffset, so that a larger range of values can be covered using
10824 // s_movk_i32.
10825 //
10826 // Atomic operations fail to work correctly when individual address
10827 // components are unaligned, even if their sum is aligned.
10828 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10829 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10830 Imm = Low;
10831 Overflow = High - Alignment.value();
10832 }
10833 }
10834
10835 if (Overflow > 0) {
10836 // There is a hardware bug in SI and CI which prevents address clamping in
10837 // MUBUF instructions from working correctly with SOffsets. The immediate
10838 // offset is unaffected.
10839 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10840 return false;
10841
10842 // It is not possible to set immediate in SOffset field on some targets.
10843 if (ST.hasRestrictedSOffset())
10844 return false;
10845 }
10846
10847 ImmOffset = Imm;
10848 SOffset = Overflow;
10849 return true;
10850}
10851
10852// Depending on the used address space and instructions, some immediate offsets
10853// are allowed and some are not.
10854// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10855// scratch instruction offsets can also be negative. On GFX12, offsets can be
10856// negative for all variants.
10857//
10858// There are several bugs related to these offsets:
10859// On gfx10.1, flat instructions that go into the global address space cannot
10860// use an offset.
10861//
10862// For scratch instructions, the address can be either an SGPR or a VGPR.
10863// The following offsets can be used, depending on the architecture (x means
10864// cannot be used):
10865// +----------------------------+------+------+
10866// | Address-Mode | SGPR | VGPR |
10867// +----------------------------+------+------+
10868// | gfx9 | | |
10869// | negative, 4-aligned offset | x | ok |
10870// | negative, unaligned offset | x | ok |
10871// +----------------------------+------+------+
10872// | gfx10 | | |
10873// | negative, 4-aligned offset | ok | ok |
10874// | negative, unaligned offset | ok | x |
10875// +----------------------------+------+------+
10876// | gfx10.3 | | |
10877// | negative, 4-aligned offset | ok | ok |
10878// | negative, unaligned offset | ok | ok |
10879// +----------------------------+------+------+
10880//
10881// This function ignores the addressing mode, so if an offset cannot be used in
10882// one addressing mode, it is considered illegal.
10883bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10884 AMDGPU::FlatAddrSpace FlatVariant) const {
10885 // TODO: Should 0 be special cased?
10886 if (!ST.hasFlatInstOffsets())
10887 return false;
10888
10890 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10891 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10892 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10893 return false;
10894
10895 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10896 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10897 (Offset % 4) != 0) {
10898 return false;
10899 }
10900
10901 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10902 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10903 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10904}
10905
10906// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10907std::pair<int64_t, int64_t>
10908SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10909 AMDGPU::FlatAddrSpace FlatVariant) const {
10910 int64_t RemainderOffset = COffsetVal;
10911 int64_t ImmField = 0;
10912
10913 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10914 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10915
10916 if (AllowNegative) {
10917 // Use signed division by a power of two to truncate towards 0.
10918 int64_t D = 1LL << NumBits;
10919 RemainderOffset = (COffsetVal / D) * D;
10920 ImmField = COffsetVal - RemainderOffset;
10921
10922 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10923 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10924 (ImmField % 4) != 0) {
10925 // Make ImmField a multiple of 4
10926 RemainderOffset += ImmField % 4;
10927 ImmField -= ImmField % 4;
10928 }
10929 } else if (COffsetVal >= 0) {
10930 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10931 RemainderOffset = COffsetVal - ImmField;
10932 }
10933
10934 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10935 assert(RemainderOffset + ImmField == COffsetVal);
10936 return {ImmField, RemainderOffset};
10937}
10938
10940 AMDGPU::FlatAddrSpace FlatVariant) const {
10941 if (ST.hasNegativeScratchOffsetBug() &&
10943 return false;
10944
10945 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10946}
10947
10948static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10949 switch (ST.getGeneration()) {
10950 default:
10951 break;
10954 return SIEncodingFamily::SI;
10956 // The GFX80 encoding family only contains buffer instructions with unpacked
10957 // D16 data; pseudoToMCOpcode falls back on VI for everything else.
10958 // TODO: remove this when we discard GFX80 encoding.
10959 return ST.hasUnpackedD16VMem() ? SIEncodingFamily::GFX80
10962 return SIEncodingFamily::VI;
10966 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10969 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10973 }
10974 llvm_unreachable("Unknown subtarget generation!");
10975}
10976
10977bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10978 switch(MCOp) {
10979 // These opcodes use indirect register addressing so
10980 // they need special handling by codegen (currently missing).
10981 // Therefore it is too risky to allow these opcodes
10982 // to be selected by dpp combiner or sdwa peepholer.
10983 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10984 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10985 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10986 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10987 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10988 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10989 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10990 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10991 return true;
10992 default:
10993 return false;
10994 }
10995}
10996
10997#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10998 case OPCODE##_dpp: \
10999 case OPCODE##_e32: \
11000 case OPCODE##_e64:
11001
11002static bool isRenamedInGFX9(int Opcode) {
11003 switch (Opcode) {
11004 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
11005 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
11006 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
11007 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
11008 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
11009 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
11010 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
11011 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
11012 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
11013 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
11014 case AMDGPU::V_FMA_F16_gfx9_e64:
11015 case AMDGPU::V_INTERP_P2_F16:
11016 case AMDGPU::V_MAD_F16_e64:
11017 case AMDGPU::V_MAD_U16_e64:
11018 case AMDGPU::V_MAD_I16_e64:
11019 return true;
11020 default:
11021 return false;
11022 }
11023}
11024
11025int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
11026 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
11027 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
11028
11029 unsigned Gen = subtargetEncodingFamily(ST);
11030
11031 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
11033
11034 if (SIInstrFlags::isSDWA(get(Opcode))) {
11035 switch (ST.getGeneration()) {
11036 default:
11038 break;
11041 break;
11044 break;
11045 }
11046 }
11047
11048 if (isMAI(Opcode)) {
11049 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
11050 if (MFMAOp != -1)
11051 Opcode = MFMAOp;
11052 }
11053
11054 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
11055
11056 // Only buffer instructions with unpacked D16 data have a GFX80 encoding.
11057 // Anything else on such a subtarget uses the plain VI encoding.
11058 // TODO: remove this when we discard GFX80 encoding.
11059 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && Gen == SIEncodingFamily::GFX80)
11061
11062 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
11064
11065 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
11067
11068 // -1 means that Opcode is already a native instruction.
11069 if (MCOp == -1)
11070 return Opcode;
11071
11072 if (ST.hasGFX90AInsts()) {
11073 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
11074 if (ST.hasGFX940Insts())
11076 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11078 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11080 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
11081 MCOp = NMCOp;
11082 }
11083
11084 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
11085 // encoding in the given subtarget generation.
11086 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
11087 return -1;
11088
11089 if (isAsmOnlyOpcode(MCOp))
11090 return -1;
11091
11092 return MCOp;
11093}
11094
11095static
11097 assert(RegOpnd.isReg());
11098 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
11099 getRegSubRegPair(RegOpnd);
11100}
11101
11104 assert(MI.isRegSequence());
11105 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
11106 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
11107 auto &RegOp = MI.getOperand(1 + 2 * I);
11108 return getRegOrUndef(RegOp);
11109 }
11111}
11112
11113// Try to find the definition of reg:subreg in subreg-manipulation pseudos
11114// Following a subreg of reg:subreg isn't supported
11117 if (!RSR.SubReg)
11118 return false;
11119 switch (MI.getOpcode()) {
11120 default: break;
11121 case AMDGPU::REG_SEQUENCE:
11122 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
11123 return true;
11124 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
11125 case AMDGPU::INSERT_SUBREG:
11126 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
11127 // inserted the subreg we're looking for
11128 RSR = getRegOrUndef(MI.getOperand(2));
11129 else { // the subreg in the rest of the reg
11130 auto R1 = getRegOrUndef(MI.getOperand(1));
11131 if (R1.SubReg) // subreg of subreg isn't supported
11132 return false;
11133 RSR.Reg = R1.Reg;
11134 }
11135 return true;
11136 }
11137 return false;
11138}
11139
11141 const MachineRegisterInfo &MRI) {
11142 assert(MRI.isSSA());
11143 if (!P.Reg.isVirtual())
11144 return nullptr;
11145
11146 auto RSR = P;
11147 auto *DefInst = MRI.getVRegDef(RSR.Reg);
11148 while (auto *MI = DefInst) {
11149 DefInst = nullptr;
11150 switch (MI->getOpcode()) {
11151 case AMDGPU::COPY:
11152 case AMDGPU::V_MOV_B32_e32: {
11153 auto &Op1 = MI->getOperand(1);
11154 if (Op1.isReg() && Op1.getReg().isVirtual()) {
11155 if (Op1.isUndef())
11156 return nullptr;
11157 RSR = getRegSubRegPair(Op1);
11158 DefInst = MRI.getVRegDef(RSR.Reg);
11159 }
11160 break;
11161 }
11162 default:
11163 if (followSubRegDef(*MI, RSR)) {
11164 if (!RSR.Reg)
11165 return nullptr;
11166 DefInst = MRI.getVRegDef(RSR.Reg);
11167 }
11168 }
11169 if (!DefInst)
11170 return MI;
11171 }
11172 return nullptr;
11173}
11174
11176 Register VReg,
11177 const MachineInstr &DefMI,
11178 const MachineInstr &UseMI) {
11179 assert(MRI.isSSA() && "Must be run on SSA");
11180
11181 auto *TRI = MRI.getTargetRegisterInfo();
11182 auto *DefBB = DefMI.getParent();
11183
11184 // Don't bother searching between blocks, although it is possible this block
11185 // doesn't modify exec.
11186 if (UseMI.getParent() != DefBB)
11187 return true;
11188
11189 const int MaxInstScan = 20;
11190 int NumInst = 0;
11191
11192 // Stop scan at the use.
11193 auto E = UseMI.getIterator();
11194 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
11195 if (I->isDebugInstr())
11196 continue;
11197
11198 if (++NumInst > MaxInstScan)
11199 return true;
11200
11201 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
11202 return true;
11203 }
11204
11205 return false;
11206}
11207
11209 Register VReg,
11210 const MachineInstr &DefMI) {
11211 assert(MRI.isSSA() && "Must be run on SSA");
11212
11213 auto *TRI = MRI.getTargetRegisterInfo();
11214 auto *DefBB = DefMI.getParent();
11215
11216 const int MaxUseScan = 10;
11217 int NumUse = 0;
11218
11219 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
11220 auto &UseInst = *Use.getParent();
11221 // Don't bother searching between blocks, although it is possible this block
11222 // doesn't modify exec.
11223 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11224 return true;
11225
11226 if (++NumUse > MaxUseScan)
11227 return true;
11228 }
11229
11230 if (NumUse == 0)
11231 return false;
11232
11233 const int MaxInstScan = 20;
11234 int NumInst = 0;
11235
11236 // Stop scan when we have seen all the uses.
11237 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
11238 assert(I != DefBB->end());
11239
11240 if (I->isDebugInstr())
11241 continue;
11242
11243 if (++NumInst > MaxInstScan)
11244 return true;
11245
11246 for (const MachineOperand &Op : I->operands()) {
11247 // We don't check reg masks here as they're used only on calls:
11248 // 1. EXEC is only considered const within one BB
11249 // 2. Call should be a terminator instruction if present in a BB
11250
11251 if (!Op.isReg())
11252 continue;
11253
11254 Register Reg = Op.getReg();
11255 if (Op.isUse()) {
11256 if (Reg == VReg && --NumUse == 0)
11257 return false;
11258 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
11259 return true;
11260 }
11261 }
11262}
11263
11266 const DebugLoc &DL, Register Src, Register Dst) const {
11267 auto Cur = MBB.begin();
11268 if (Cur != MBB.end())
11269 do {
11270 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
11271 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
11272 ++Cur;
11273 } while (Cur != MBB.end() && Cur != LastPHIIt);
11274
11275 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
11276 Dst);
11277}
11278
11281 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
11282 if (InsPt != MBB.end() &&
11283 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11284 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11285 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11286 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
11287 InsPt++;
11288 return BuildMI(MBB, InsPt, DL,
11289 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
11290 .addReg(Src, {}, SrcSubReg)
11291 .addReg(AMDGPU::EXEC, RegState::Implicit);
11292 }
11293 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
11294 Dst);
11295}
11296
11297bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
11298
11300 const MachineInstr &SecondMI) const {
11301 for (const auto &Use : SecondMI.all_uses()) {
11302 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
11303 return true;
11304 }
11305 return false;
11306}
11307
11308/// If OpX is multicycle, anti-dependencies are not allowed.
11309/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
11310/// purpose.
11312 const MachineInstr &OpX) const {
11314}
11315
11318 ArrayRef<unsigned> Ops, int FrameIndex,
11319 MachineInstr *&CopyMI, LiveIntervals *LIS,
11320 VirtRegMap *VRM) const {
11321 // This is a bit of a hack (copied from AArch64). Consider this instruction:
11322 //
11323 // %0:sreg_32 = COPY $m0
11324 //
11325 // We explicitly chose SReg_32 for the virtual register so such a copy might
11326 // be eliminated by RegisterCoalescer. However, that may not be possible, and
11327 // %0 may even spill. We can't spill $m0 normally (it would require copying to
11328 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
11329 // TargetInstrInfo::foldMemoryOperand() is going to try.
11330 // A similar issue also exists with spilling and reloading $exec registers.
11331 //
11332 // To prevent that, constrain the %0 register class here.
11333 if (isFullCopyInstr(MI)) {
11334 Register DstReg = MI.getOperand(0).getReg();
11335 Register SrcReg = MI.getOperand(1).getReg();
11336 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
11337 (DstReg.isVirtual() != SrcReg.isVirtual())) {
11338 MachineRegisterInfo &MRI = MF.getRegInfo();
11339 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
11340 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
11341 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
11342 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11343 return nullptr;
11344 }
11345 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
11346 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11347 return nullptr;
11348 }
11349 }
11350 }
11351
11352 return nullptr;
11353}
11354
11356 const MachineInstr &MI,
11357 unsigned *PredCost) const {
11358 if (MI.isBundle()) {
11360 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
11361 unsigned Lat = 0, Count = 0;
11362 for (++I; I != E && I->isBundledWithPred(); ++I) {
11363 ++Count;
11364 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
11365 }
11366 return Lat + Count - 1;
11367 }
11368
11369 return SchedModel.computeInstrLatency(&MI);
11370}
11371
11373 if (!ST.hasGFX1250VALUBlockingCycles())
11374 return 0;
11376}
11377
11378unsigned
11380 if (const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(MI.getOpcode()))
11381 return Entry->GFX1250BlockingCycles;
11382 return 0;
11383}
11384
11385const MachineOperand &
11387 if (const MachineOperand *CallAddrOp =
11388 getNamedOperand(MI, AMDGPU::OpName::src0))
11389 return *CallAddrOp;
11391}
11392
11395 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11396 unsigned Opcode = MI.getOpcode();
11397
11398 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
11399 Register Dst = MI.getOperand(0).getReg();
11400 Register Src = MI.getOperand(1).getReg();
11401 LLT DstTy = MRI.getType(Dst);
11402 LLT SrcTy = MRI.getType(Src);
11403 unsigned DstAS = DstTy.getAddressSpace();
11404 unsigned SrcAS = SrcTy.getAddressSpace();
11405 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
11406 DstAS == AMDGPUAS::FLAT_ADDRESS &&
11407 ST.hasGloballyAddressableScratch()
11410 };
11411
11412 // If the target supports globally addressable scratch, the mapping from
11413 // scratch memory to the flat aperture changes therefore an address space cast
11414 // is no longer uniform.
11415 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11416 return HandleAddrSpaceCast(MI);
11417
11418 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
11419 auto IID = GI->getIntrinsicID();
11424
11425 switch (IID) {
11426 case Intrinsic::amdgcn_if:
11427 case Intrinsic::amdgcn_else:
11428 // FIXME: Uniform if second result
11429 break;
11430 }
11431
11433 }
11434
11435 // Loads from the private and flat address spaces are divergent, because
11436 // threads can execute the load instruction with the same inputs and get
11437 // different results.
11438 //
11439 // All other loads are not divergent, because if threads issue loads with the
11440 // same arguments, they will always get the same result.
11441 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11442 Opcode == AMDGPU::G_SEXTLOAD) {
11443 if (MI.memoperands_empty())
11444 return ValueUniformity::NeverUniform; // conservative assumption
11445
11446 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11447 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11448 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11449 })) {
11450 // At least one MMO in a non-global address space.
11452 }
11454 }
11455
11456 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11457 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11458 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11459 AMDGPU::isGenericAtomic(Opcode)) {
11461 }
11462
11463 // Result is computed from uniform SP and uniform wave-wide max size.
11464 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11466
11467 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11469
11471}
11472
11474 if (!Formatter)
11475 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11476 return Formatter.get();
11477}
11478
11480
11481 if (isNeverUniform(MI))
11483
11484 unsigned opcode = MI.getOpcode();
11485 if (opcode == AMDGPU::V_READLANE_B32 ||
11486 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11487 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11489
11490 // If any of defs is divergent, report as NeverUniform. isUniformReg will
11491 // calculate in more detail for each def from its reg class, if available.
11492 if (MI.isInlineAsm()) {
11493 for (const MachineOperand &MO : MI.operands()) {
11494 if (!MO.isReg() || !MO.isDef())
11495 continue;
11496 const TargetRegisterClass *RC =
11497 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
11498 if (!RC || !RI.isSGPRClass(RC))
11500 }
11501 }
11502
11503 if (isCopyInstr(MI)) {
11504 const MachineOperand &srcOp = MI.getOperand(1);
11505 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
11506 const TargetRegisterClass *regClass =
11507 RI.getPhysRegBaseClass(srcOp.getReg());
11508 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
11510 }
11512 }
11513
11514 // GMIR handling
11515 if (MI.isPreISelOpcode())
11517
11518 // Atomics are divergent because they are executed sequentially: when an
11519 // atomic operation refers to the same address in each thread, then each
11520 // thread after the first sees the value written by the previous thread as
11521 // original value.
11522
11523 if (isAtomic(MI))
11525
11526 // Loads from the private and flat address spaces are divergent, because
11527 // threads can execute the load instruction with the same inputs and get
11528 // different results.
11529 if (isFLAT(MI) && MI.mayLoad()) {
11530 if (MI.memoperands_empty())
11531 return ValueUniformity::NeverUniform; // conservative assumption
11532
11533 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11534 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11535 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11536 })) {
11537 // At least one MMO in a non-global address space.
11539 }
11540
11542 }
11543
11544 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11545 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11546
11547 // FIXME: It's conceptually broken to report this for an instruction, and not
11548 // a specific def operand. For inline asm in particular, there could be mixed
11549 // uniform and divergent results.
11550 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11551 const MachineOperand &SrcOp = MI.getOperand(I);
11552 if (!SrcOp.isReg())
11553 continue;
11554
11555 Register Reg = SrcOp.getReg();
11556 if (!Reg || !SrcOp.readsReg())
11557 continue;
11558
11559 // If RegBank is null, this is unassigned or an unallocatable special
11560 // register, which are all scalars.
11561 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11562 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11564 }
11565
11566 // TODO: Uniformity check condtions above can be rearranged for more
11567 // redability
11568
11569 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11570 // currently turned into no-op COPYs by SelectionDAG ISel and are
11571 // therefore no longer recognizable.
11572
11574}
11575
11577 switch (MF.getFunction().getCallingConv()) {
11579 return 1;
11581 return 2;
11583 return 3;
11587 const Function &F = MF.getFunction();
11588 F.getContext().diagnose(DiagnosticInfoUnsupported(
11589 F, "ds_ordered_count unsupported for this calling conv"));
11590 [[fallthrough]];
11591 }
11594 case CallingConv::C:
11595 case CallingConv::Fast:
11596 default:
11597 // Assume other calling conventions are various compute callable functions
11598 return 0;
11599 }
11600}
11601
11603 Register &SrcReg2, int64_t &CmpMask,
11604 int64_t &CmpValue) const {
11605 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11606 return false;
11607
11608 switch (MI.getOpcode()) {
11609 default:
11610 break;
11611 case AMDGPU::S_CMP_EQ_U32:
11612 case AMDGPU::S_CMP_EQ_I32:
11613 case AMDGPU::S_CMP_LG_U32:
11614 case AMDGPU::S_CMP_LG_I32:
11615 case AMDGPU::S_CMP_LT_U32:
11616 case AMDGPU::S_CMP_LT_I32:
11617 case AMDGPU::S_CMP_GT_U32:
11618 case AMDGPU::S_CMP_GT_I32:
11619 case AMDGPU::S_CMP_LE_U32:
11620 case AMDGPU::S_CMP_LE_I32:
11621 case AMDGPU::S_CMP_GE_U32:
11622 case AMDGPU::S_CMP_GE_I32:
11623 case AMDGPU::S_CMP_EQ_U64:
11624 case AMDGPU::S_CMP_LG_U64:
11625 SrcReg = MI.getOperand(0).getReg();
11626 if (MI.getOperand(1).isReg()) {
11627 if (MI.getOperand(1).getSubReg())
11628 return false;
11629 SrcReg2 = MI.getOperand(1).getReg();
11630 CmpValue = 0;
11631 } else if (MI.getOperand(1).isImm()) {
11632 SrcReg2 = Register();
11633 CmpValue = MI.getOperand(1).getImm();
11634 } else {
11635 return false;
11636 }
11637 CmpMask = ~0;
11638 return true;
11639 case AMDGPU::S_CMPK_EQ_U32:
11640 case AMDGPU::S_CMPK_EQ_I32:
11641 case AMDGPU::S_CMPK_LG_U32:
11642 case AMDGPU::S_CMPK_LG_I32:
11643 case AMDGPU::S_CMPK_LT_U32:
11644 case AMDGPU::S_CMPK_LT_I32:
11645 case AMDGPU::S_CMPK_GT_U32:
11646 case AMDGPU::S_CMPK_GT_I32:
11647 case AMDGPU::S_CMPK_LE_U32:
11648 case AMDGPU::S_CMPK_LE_I32:
11649 case AMDGPU::S_CMPK_GE_U32:
11650 case AMDGPU::S_CMPK_GE_I32:
11651 SrcReg = MI.getOperand(0).getReg();
11652 SrcReg2 = Register();
11653 CmpValue = MI.getOperand(1).getImm();
11654 CmpMask = ~0;
11655 return true;
11656 }
11657
11658 return false;
11659}
11660
11662 for (MachineBasicBlock *S : MBB->successors()) {
11663 if (S->isLiveIn(AMDGPU::SCC))
11664 return false;
11665 }
11666 return true;
11667}
11668
11669// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11670// (incoming SCC) = !(SCC defined by SCCDef).
11671// Return true if all uses can be re-written, false otherwise.
11672bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11673 MachineBasicBlock *MBB = SCCDef->getParent();
11674 SmallVector<MachineInstr *> InvertInstr;
11675 bool SCCIsDead = false;
11676
11677 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11678 constexpr unsigned ScanLimit = 12;
11679 unsigned Count = 0;
11680 for (MachineInstr &MI : instructionsWithoutDebug(
11681 std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11682 if (++Count > ScanLimit)
11683 return false;
11684 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11685 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11686 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11687 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11688 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11689 InvertInstr.push_back(&MI);
11690 else
11691 return false;
11692 }
11693 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11694 SCCIsDead = true;
11695 break;
11696 }
11697 }
11698 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11699 SCCIsDead = true;
11700
11701 // SCC may have more uses. Can't invert all of them.
11702 if (!SCCIsDead)
11703 return false;
11704
11705 // Invert uses
11706 for (MachineInstr *MI : InvertInstr) {
11707 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11708 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11709 swapOperands(*MI);
11710 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11711 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11712 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11713 ? AMDGPU::S_CBRANCH_SCC1
11714 : AMDGPU::S_CBRANCH_SCC0));
11715 } else {
11716 llvm_unreachable("SCC used but no inversion handling");
11717 }
11718 }
11719 return true;
11720}
11721
11722// SCC is already valid after SCCValid.
11723// SCCRedefine will redefine SCC to the same value already available after
11724// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11725// update kill/dead flags if necessary.
11726bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11727 bool NeedInversion) const {
11728 MachineInstr *KillsSCC = nullptr;
11729 if (SCCValid->getParent() != SCCRedefine->getParent())
11730 return false;
11731 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11732 SCCRedefine->getIterator())) {
11733 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11734 return false;
11735 if (MI.killsRegister(AMDGPU::SCC, &RI))
11736 KillsSCC = &MI;
11737 }
11738 if (NeedInversion && !invertSCCUse(SCCRedefine))
11739 return false;
11740 if (MachineOperand *SccDef =
11741 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11742 SccDef->setIsDead(false);
11743 if (KillsSCC)
11744 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11745 SCCRedefine->eraseFromParent();
11746 return true;
11747}
11748
11749/// If \p Sel is an S_CSELECT* of two different constants A and B, return them,
11750/// truncated to the width of the select.
11751static std::optional<std::pair<int64_t, int64_t>>
11753 const MachineInstr &Sel) {
11754 unsigned Opc = Sel.getOpcode();
11755 if (Opc != AMDGPU::S_CSELECT_B32 && Opc != AMDGPU::S_CSELECT_B64)
11756 return {};
11757 std::optional<int64_t> A =
11758 TII.getImmOrMaterializedImm(MRI, Sel.getOperand(1));
11759 if (!A)
11760 return {};
11761 std::optional<int64_t> B =
11762 TII.getImmOrMaterializedImm(MRI, Sel.getOperand(2));
11763 if (!B)
11764 return {};
11765 if (Opc == AMDGPU::S_CSELECT_B32) {
11766 A = Lo_32(*A);
11767 B = Lo_32(*B);
11768 }
11769 if (*A == *B)
11770 return {};
11771 return std::pair(*A, *B);
11772}
11773
11774static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11775 unsigned &NewDefOpc) {
11776 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11777 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11778 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11779 Def.getOpcode() != AMDGPU::S_ADD_U32)
11780 return false;
11781 const MachineOperand &AddSrc1 = Def.getOperand(1);
11782 const MachineOperand &AddSrc2 = Def.getOperand(2);
11783 const MachineRegisterInfo &MRI = Def.getMF()->getRegInfo();
11784 const SIInstrInfo *TII = static_cast<const SIInstrInfo *>(
11785 Def.getMF()->getSubtarget().getInstrInfo());
11786
11787 auto Imm1 = TII->getImmOrMaterializedImm(MRI, AddSrc1);
11788 auto Imm2 = TII->getImmOrMaterializedImm(MRI, AddSrc2);
11789 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11790 return false;
11791
11792 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11793 const MachineOperand *SccDef =
11794 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11795 if (!SccDef->isDead())
11796 return false;
11797 NewDefOpc = AMDGPU::S_ADD_U32;
11798 }
11799 NeedInversion = !NeedInversion;
11800 return true;
11801}
11802
11804 Register SrcReg2, int64_t CmpMask,
11805 int64_t CmpValue,
11806 const MachineRegisterInfo *MRI) const {
11807 if (!SrcReg || SrcReg.isPhysical())
11808 return false;
11809
11810 if (SrcReg2) {
11811 auto ImmOpt = getImmOrMaterializedImm(*MRI, SrcReg2);
11812 if (!ImmOpt)
11813 return false;
11814 CmpValue = *ImmOpt;
11815 }
11816
11817 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11818 this](bool NeedInversion) -> bool {
11819 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11820 if (!Def)
11821 return false;
11822
11823 unsigned NewDefOpc = Def->getOpcode();
11824 if (auto Consts = getSelectConstants(*this, *MRI, *Def)) {
11825 // sX = S_CSELECT* A, B with A != B, so sX == A exactly when SCC was set.
11826 // Comparing sX with A or B recomputes SCC or its inverse:
11827 //
11828 // s_cmp_eq_* sX, A => SCC s_cmp_lg_* sX, A => !SCC
11829 // s_cmp_eq_* sX, B => !SCC s_cmp_lg_* sX, B => SCC
11830 auto [A, B] = *Consts;
11831 int64_t C = Def->getOpcode() == AMDGPU::S_CSELECT_B32 ? Lo_32(CmpValue)
11832 : CmpValue;
11833 if (C == A)
11834 NeedInversion = !NeedInversion;
11835 else if (C != B)
11836 return false;
11837 } else {
11838 // For S_OP that set SCC = DST!=0, do the transformation
11839 //
11840 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11841 //
11842 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11843 // do the transformation:
11844 //
11845 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11846 if (CmpValue != 0 ||
11847 (!setsSCCIfResultIsNonZero(*Def) &&
11848 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc)))
11849 return false;
11850 }
11851
11852 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11853 return false;
11854
11855 if (NewDefOpc != Def->getOpcode())
11856 Def->setDesc(get(NewDefOpc));
11857
11858 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11859 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11860 // 64-bit select then delete s_or_b32 in the sequence:
11861 // sX = s_cselect_b64 A, B (A != B, one of them 0)
11862 // sLo = copy sX.sub0
11863 // sHi = copy sX.sub1
11864 // sY = s_or_b32 sLo, sHi
11865 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11866 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11867 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11868 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11869 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11870 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11871 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11872 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11873 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11874 Def2->getOperand(1).isReg() &&
11875 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11876 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11877 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11878 if (MachineInstr *Select =
11879 MRI->getVRegDef(Def1->getOperand(1).getReg())) {
11880 if (auto Consts = getSelectConstants(*this, *MRI, *Select)) {
11881 auto [A, B] = *Consts;
11882 if (A == 0 || B == 0)
11883 optimizeSCC(Select, Def, /*NeedInversion=*/A == 0);
11884 }
11885 }
11886 }
11887 }
11888 }
11889 return true;
11890 };
11891
11892 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11893 this](int64_t ExpectedValue, unsigned SrcSize,
11894 bool IsReversible, bool IsSigned) -> bool {
11895 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11896 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11897 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11898 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11899 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11900 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11901 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11902 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11903 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11904 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11905 //
11906 // Signed ge/gt are not used for the sign bit.
11907 //
11908 // If result of the AND is unused except in the compare:
11909 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11910 //
11911 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11912 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11913 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11914 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11915 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11916 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11917
11918 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11919 if (!Def)
11920 return false;
11921
11922 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11923 Def->getOpcode() != AMDGPU::S_AND_B64)
11924 return false;
11925
11926 int64_t Mask;
11927 const auto isMask = [&Mask, SrcSize, MRI,
11928 this](const MachineOperand *MO) -> bool {
11929 auto ImmOpt = this->getImmOrMaterializedImm(*MRI, *MO);
11930 if (!ImmOpt)
11931 return false;
11932 Mask = *ImmOpt;
11933 Mask &= maxUIntN(SrcSize);
11934 return isPowerOf2_64(Mask);
11935 };
11936
11937 MachineOperand *SrcOp = &Def->getOperand(1);
11938 if (isMask(SrcOp))
11939 SrcOp = &Def->getOperand(2);
11940 else if (isMask(&Def->getOperand(2)))
11941 SrcOp = &Def->getOperand(1);
11942 else
11943 return false;
11944
11945 // A valid Mask is required to have a single bit set, hence a non-zero and
11946 // power-of-two value. This verifies that we will not do 64-bit shift below.
11947 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11948 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11949 if (IsSigned && BitNo == SrcSize - 1)
11950 return false;
11951
11952 ExpectedValue <<= BitNo;
11953
11954 bool IsReversedCC = false;
11955 if (CmpValue != ExpectedValue) {
11956 if (!IsReversible)
11957 return false;
11958 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11959 if (!IsReversedCC)
11960 return false;
11961 }
11962
11963 Register DefReg = Def->getOperand(0).getReg();
11964 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11965 return false;
11966
11967 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11968 return false;
11969
11970 if (!MRI->use_nodbg_empty(DefReg)) {
11971 assert(!IsReversedCC);
11972 return true;
11973 }
11974
11975 // Replace AND with unused result with a S_BITCMP.
11976 MachineBasicBlock *MBB = Def->getParent();
11977
11978 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11979 : AMDGPU::S_BITCMP1_B32
11980 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11981 : AMDGPU::S_BITCMP1_B64;
11982
11983 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11984 .add(*SrcOp)
11985 .addImm(BitNo);
11986 Def->eraseFromParent();
11987
11988 return true;
11989 };
11990
11991 switch (CmpInstr.getOpcode()) {
11992 default:
11993 break;
11994 case AMDGPU::S_CMP_EQ_U32:
11995 case AMDGPU::S_CMP_EQ_I32:
11996 case AMDGPU::S_CMPK_EQ_U32:
11997 case AMDGPU::S_CMPK_EQ_I32:
11998 return optimizeCmpAnd(1, 32, true, false) ||
11999 optimizeCmpSelect(/*NeedInversion=*/true);
12000 case AMDGPU::S_CMP_GE_U32:
12001 case AMDGPU::S_CMPK_GE_U32:
12002 return optimizeCmpAnd(1, 32, false, false);
12003 case AMDGPU::S_CMP_GE_I32:
12004 case AMDGPU::S_CMPK_GE_I32:
12005 return optimizeCmpAnd(1, 32, false, true);
12006 case AMDGPU::S_CMP_EQ_U64:
12007 return optimizeCmpAnd(1, 64, true, false) ||
12008 optimizeCmpSelect(/*NeedInversion=*/true);
12009 case AMDGPU::S_CMP_LG_U32:
12010 case AMDGPU::S_CMP_LG_I32:
12011 case AMDGPU::S_CMPK_LG_U32:
12012 case AMDGPU::S_CMPK_LG_I32:
12013 return optimizeCmpAnd(0, 32, true, false) ||
12014 optimizeCmpSelect(/*NeedInversion=*/false);
12015 case AMDGPU::S_CMP_GT_U32:
12016 case AMDGPU::S_CMPK_GT_U32:
12017 return optimizeCmpAnd(0, 32, false, false);
12018 case AMDGPU::S_CMP_GT_I32:
12019 case AMDGPU::S_CMPK_GT_I32:
12020 return optimizeCmpAnd(0, 32, false, true);
12021 case AMDGPU::S_CMP_LG_U64:
12022 return optimizeCmpAnd(0, 64, true, false) ||
12023 optimizeCmpSelect(/*NeedInversion=*/false);
12024 }
12025
12026 return false;
12027}
12028
12030 AMDGPU::OpName OpName) const {
12031 if (!ST.needsAlignedVGPRs())
12032 return;
12033
12034 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
12035 if (OpNo < 0)
12036 return;
12037 MachineOperand &Op = MI.getOperand(OpNo);
12038 if (getOpSize(MI, OpNo) > 4)
12039 return;
12040
12041 // Add implicit aligned super-reg to force alignment on the data operand.
12042 const DebugLoc &DL = MI.getDebugLoc();
12043 MachineBasicBlock *BB = MI.getParent();
12045 Register DataReg = Op.getReg();
12046 bool IsAGPR = RI.isAGPR(MRI, DataReg);
12048 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
12049 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
12050 Register NewVR =
12051 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
12052 : &AMDGPU::VReg_64_Align2RegClass);
12053 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
12054 .addReg(DataReg, {}, Op.getSubReg())
12055 .addImm(AMDGPU::sub0)
12056 .addReg(Undef)
12057 .addImm(AMDGPU::sub1);
12058 Op.setReg(NewVR);
12059 Op.setSubReg(AMDGPU::sub0);
12060 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
12061}
12062
12064 if (!SchedModel.hasInstrSchedModel())
12065 return 0;
12066
12067 // The repeat rate is the throughput-limiting resource occupancy: the largest
12068 // number of cycles any written processor resource is held.
12069 const MCSchedClassDesc *SCDesc = SchedModel.resolveSchedClass(&MI);
12070 unsigned RepeatRate = 0;
12072 PI = SchedModel.getWriteProcResBegin(SCDesc),
12073 PE = SchedModel.getWriteProcResEnd(SCDesc);
12074 PI != PE; ++PI) {
12075 RepeatRate = std::max(RepeatRate, (unsigned)PI->ReleaseAtCycle);
12076 }
12077
12078 return RepeatRate;
12079}
12080
12082 if (isIGLP(*MI))
12083 return false;
12084
12086}
12087
12089 if (!isWMMA(MI) && !isSWMMAC(MI))
12090 return false;
12091
12092 if (ST.hasGFX1250Insts())
12093 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
12094
12095 return true;
12096}
12097
12099 unsigned Opcode = MI.getOpcode();
12100
12101 if (AMDGPU::isGFX12Plus(ST))
12102 return isDOT(MI) || isXDLWMMA(MI);
12103
12104 if (!isMAI(MI) || isDGEMM(Opcode) ||
12105 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
12106 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
12107 return false;
12108
12109 if (!ST.hasGFX940Insts())
12110 return true;
12111
12112 return AMDGPU::getMAIIsGFX940XDL(Opcode);
12113}
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
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
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:185
Class for arbitrary precision integers.
Definition APInt.h:78
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
This class is the base class for the comparison instructions.
Definition InstrTypes.h:728
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A debug info location.
Definition DebugLoc.h:126
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:856
Diagnostic information for unsupported feature in backend.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:273
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:352
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
CycleRef getParentCycle(CycleRef C) const
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
Itinerary data supplied by a subtarget to be used by a target.
constexpr unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
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,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
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...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
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 void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps)
Move NumOps operands from Src to Dst, updating use-def lists as needed.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
LLVM_ABI void clearVirtRegs()
clearVirtRegs - Remove all virtual registers (after physreg assignment).
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
const MachineFunction & getMF() const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI bool isConstantPhysReg(MCRegister PhysReg) const
Returns true if PhysReg is unallocatable and constant throughout the function.
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
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 removeRegOperandFromUseList(MachineOperand *MO)
Remove MO from its use-def list.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI void addRegOperandToUseList(MachineOperand *MO)
Add MO to the linked list of operands for its register.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
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:66
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:344
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
Changed
#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)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
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.
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
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:541
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
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:567
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:267
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:68
MachineInstr * top() const
Definition SIInstrInfo.h:73
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
Definition SIInstrInfo.h:91
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.