LLVM 24.0.0git
SIInstrInfo.cpp
Go to the documentation of this file.
1//===- SIInstrInfo.cpp - SI Instruction Information ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// SI Implementation of TargetInstrInfo.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SIInstrInfo.h"
15#include "AMDGPU.h"
16#include "AMDGPUInstrInfo.h"
17#include "AMDGPULaneMaskUtils.h"
18#include "GCNHazardRecognizer.h"
19#include "GCNSubtarget.h"
22#include "llvm/ADT/STLExtras.h"
33#include "llvm/IR/IntrinsicsAMDGPU.h"
34#include "llvm/MC/MCContext.h"
37#include <tuple>
38
39using namespace llvm;
40
41#define DEBUG_TYPE "si-instr-info"
42
43#define GET_INSTRINFO_CTOR_DTOR
44#include "AMDGPUGenInstrInfo.inc"
45
46namespace llvm::AMDGPU {
47#define GET_ImageDimIntrinsicTable_IMPL
48#define GET_RsrcIntrinsics_IMPL
49#define GET_GFX1250BlockingCyclesTable_DECL
50#define GET_GFX1250BlockingCyclesTable_IMPL
51
56
57#include "AMDGPUGenSearchableTables.inc"
58} // namespace llvm::AMDGPU
59
60// Must be at least 4 to be able to branch over minimum unconditional branch
61// code. This is only for making it possible to write reasonably small tests for
62// long branches.
64BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16),
65 cl::desc("Restrict range of branch instructions (DEBUG)"));
66
68 "amdgpu-fix-16-bit-physreg-copies",
69 cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"),
70 cl::init(true),
72
74 : AMDGPUGenInstrInfo(ST, RI, AMDGPU::ADJCALLSTACKUP,
75 AMDGPU::ADJCALLSTACKDOWN),
76 RI(ST), ST(ST) {
77 SchedModel.init(&ST);
78}
79
80//===----------------------------------------------------------------------===//
81// TargetInstrInfo callbacks
82//===----------------------------------------------------------------------===//
83
84static unsigned getNumOperandsNoGlue(SDNode *Node) {
85 unsigned N = Node->getNumOperands();
86 while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
87 --N;
88 return N;
89}
90
91/// Returns true if both nodes have the same value for the given
92/// operand \p Op, or if both nodes do not have this operand.
94 AMDGPU::OpName OpName) {
95 unsigned Opc0 = N0->getMachineOpcode();
96 unsigned Opc1 = N1->getMachineOpcode();
97
98 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName);
99 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName);
100
101 if (Op0Idx == -1 && Op1Idx == -1)
102 return true;
103
104
105 if ((Op0Idx == -1 && Op1Idx != -1) ||
106 (Op1Idx == -1 && Op0Idx != -1))
107 return false;
108
109 // getNamedOperandIdx returns the index for the MachineInstr's operands,
110 // which includes the result as the first operand. We are indexing into the
111 // MachineSDNode's operands, so we need to skip the result operand to get
112 // the real index.
113 --Op0Idx;
114 --Op1Idx;
115
116 return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx);
117}
118
119static bool canRemat(const MachineInstr &MI) {
120
124 return true;
125
126 if (SIInstrInfo::isSMRD(MI)) {
127 return !MI.memoperands_empty() &&
128 llvm::all_of(MI.memoperands(), [](const MachineMemOperand *MMO) {
129 return MMO->isLoad() && MMO->isInvariant();
130 });
131 }
132
133 return false;
134}
135
136// Split relocation flags for 64-bit global-address materialization into a
137// common base and the hi/lo relocation variants.
138static std::tuple<unsigned, unsigned, unsigned>
140 const MachineOperand &SrcOp) {
141 const unsigned BaseFlags = SrcOp.getTargetFlags() & ~SIInstrInfo::MO_MASK;
142 const unsigned Reloc = SrcOp.getTargetFlags() & SIInstrInfo::MO_MASK;
143
144 // Infer the relocation type from the existing flags on the global operand.
145 // The relocation type should have been determined earlier in the pipeline.
146 unsigned LoReloc, HiReloc;
147 switch (Reloc) {
151 LoReloc = SIInstrInfo::MO_REL32_LO;
152 HiReloc = SIInstrInfo::MO_REL32_HI;
153 break;
158 break;
161 // For 64-bit GOT-relative, use the 64-bit relocation.
164 break;
168 LoReloc = SIInstrInfo::MO_ABS32_LO;
169 HiReloc = SIInstrInfo::MO_ABS32_HI;
170 break;
171 default:
172 llvm_unreachable("unknown relocation type for global address");
173 break;
174 }
175
176 return {BaseFlags, LoReloc, HiReloc};
177}
178
180 const MachineInstr &MI) const {
181
182 if (canRemat(MI)) {
183 // Normally VALU use of exec would block the rematerialization, but that
184 // is OK in this case to have an implicit exec read as all VALU do.
185 // We really want all of the generic logic for this except for this.
186
187 // Another potential implicit use is mode register. The core logic of
188 // the RA will not attempt rematerialization if mode is set anywhere
189 // in the function, otherwise it is safe since mode is not changed.
190
191 // There is difference to generic method which does not allow
192 // rematerialization if there are virtual register uses. We allow this,
193 // therefore this method includes SOP instructions as well.
194 if (!MI.hasImplicitDef() &&
195 MI.getNumImplicitOperands() == MI.getDesc().implicit_uses().size() &&
196 !MI.mayRaiseFPException())
197 return true;
198 }
199
200 // Everything below copied from TargetInstrInfo::isReMaterializableImpl. The
201 // only difference is that we allow operations that perform read-modify-write
202 // on sub-registers.
203
204 // Remat clients assume operand 0 is the defined register.
205 if (!MI.getNumOperands() || !MI.getOperand(0).isReg())
206 return false;
207 Register DefReg = MI.getOperand(0).getReg();
208
209 const MachineFunction &MF = *MI.getMF();
210
211 // A load from a fixed stack slot can be rematerialized. This may be
212 // redundant with subsequent checks, but it's target-independent,
213 // simple, and a common case.
214 int FrameIdx = 0;
215 if (isLoadFromStackSlot(MI, FrameIdx) &&
217 return true;
218
219 // Avoid instructions obviously unsafe for remat.
220 if (MI.isNotDuplicable() || MI.mayStore() || MI.mayRaiseFPException() ||
221 MI.hasUnmodeledSideEffects())
222 return false;
223
224 // Don't remat inline asm. We have no idea how expensive it is
225 // even if it's side effect free.
226 if (MI.isInlineAsm())
227 return false;
228
229 // Avoid instructions which load from potentially varying memory.
230 if (MI.mayLoad() && !MI.isDereferenceableInvariantLoad())
231 return false;
232
233 const MachineRegisterInfo &MRI = MF.getRegInfo();
234
235 // If any of the registers accessed are non-constant, conservatively assume
236 // the instruction is not rematerializable.
237 for (const MachineOperand &MO : MI.operands()) {
238 if (!MO.isReg())
239 continue;
240 Register Reg = MO.getReg();
241 if (Reg == 0)
242 continue;
243
244 // Check for a well-behaved physical register.
245 if (Reg.isPhysical()) {
246 if (MO.isUse()) {
247 // If the physreg has no defs anywhere, it's just an ambient register
248 // and we can freely move its uses. Alternatively, if it's allocatable,
249 // it could get allocated to something with a def during allocation.
250 if (!MRI.isConstantPhysReg(Reg))
251 return false;
252 } else {
253 // A physreg def. We can't remat it.
254 return false;
255 }
256 continue;
257 }
258
259 // Only allow one virtual-register def. There may be multiple defs of the
260 // same virtual register, though.
261 if (MO.isDef() && Reg != DefReg)
262 return false;
263 }
264
265 return true;
266}
267
269 switch (Opcode) {
270 // v_subrev_u16 (gfx9)
271 case AMDGPU::V_SUBREV_U16_e32:
272 case AMDGPU::V_SUBREV_U16_e64:
273 // v_subrev_u32 (gfx9) / v_subrev_nc_u32 (gfx10+)
274 case AMDGPU::V_SUBREV_U32_e32:
275 case AMDGPU::V_SUBREV_U32_e64:
276 // v_subrev_co_u32
277 case AMDGPU::V_SUBREV_CO_U32_e32:
278 case AMDGPU::V_SUBREV_CO_U32_e64:
279 // v_subbrev_u32 (gfx9) / v_subrev_co_ci_u32 (gfx10+)
280 case AMDGPU::V_SUBBREV_U32_e32:
281 case AMDGPU::V_SUBBREV_U32_e64:
282 return true;
283 // REV shift opcodes worked this way before GFX11, verified on hardware
284 case AMDGPU::V_ASHRREV_I16_e32:
285 case AMDGPU::V_ASHRREV_I16_e64:
286 case AMDGPU::V_ASHRREV_I32_e32:
287 case AMDGPU::V_ASHRREV_I32_e64:
288 case AMDGPU::V_ASHRREV_I64_e64:
289 case AMDGPU::V_LSHLREV_B16_e32:
290 case AMDGPU::V_LSHLREV_B16_e64:
291 case AMDGPU::V_LSHLREV_B32_e32:
292 case AMDGPU::V_LSHLREV_B32_e64:
293 case AMDGPU::V_LSHLREV_B64_e64:
294 case AMDGPU::V_LSHRREV_B16_e32:
295 case AMDGPU::V_LSHRREV_B16_e64:
296 case AMDGPU::V_LSHRREV_B32_e32:
297 case AMDGPU::V_LSHRREV_B32_e64:
298 case AMDGPU::V_LSHRREV_B64_e64:
299 return !ST.hasGFX11Insts();
300 default:
301 return false;
302 }
303}
304
305// Returns true if the result of a VALU instruction depends on exec.
306bool SIInstrInfo::resultDependsOnExec(const MachineInstr &MI) const {
307 assert(isVALU(MI, /*AllowLDSDMA=*/true));
308
309 // If it is convergent it depends on EXEC.
310 if (MI.isConvergent())
311 return true;
312
313 // If it defines an SGPR it depends on EXEC, unless it's dead.
314 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
315 for (const MachineOperand &Def : MI.defs()) {
316 if (Def.isDead())
317 continue;
318
319 Register Reg = Def.getReg();
320 if (Reg && RI.isSGPRReg(MRI, Reg))
321 return true;
322 }
323
324 return false;
325}
326
327bool SIInstrInfo::isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const {
328 const MachineOperand &MO = MI.getOperand(OpIdx);
329 // Any implicit use of exec by VALU is not a real register read.
330 return MO.getReg() == AMDGPU::EXEC && MO.isImplicit() &&
331 isVALU(MI, /*AllowLDSDMA=*/true) && !resultDependsOnExec(MI);
332}
333
335 MachineBasicBlock *SuccToSinkTo,
336 MachineCycleInfo *CI) const {
337 // Allow sinking if MI edits lane mask (divergent i1 in sgpr).
338 if (MI.getOpcode() == AMDGPU::SI_IF_BREAK)
339 return true;
340
341 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
342 // Check if sinking of MI would create temporal divergent use.
343 for (auto Op : MI.uses()) {
344 if (Op.isReg() && Op.getReg().isVirtual() &&
345 RI.isSGPRClass(MRI.getRegClass(Op.getReg()))) {
346 MachineInstr *SgprDef = MRI.getVRegDef(Op.getReg());
347 if (!SgprDef)
348 continue;
349
350 // SgprDef defined inside cycle
351 CycleRef FromCycle = CI->getCycle(SgprDef->getParent());
352 if (!FromCycle)
353 continue;
354
355 CycleRef ToCycle = CI->getCycle(SuccToSinkTo);
356 // Check if there is a FromCycle that contains SgprDef's basic block but
357 // does not contain SuccToSinkTo and also has divergent exit condition.
358 while (FromCycle && !(ToCycle && CI->contains(FromCycle, ToCycle))) {
360 CI->getExitingBlocks(FromCycle, ExitingBlocks);
361
362 // FromCycle has divergent exit condition.
363 for (MachineBasicBlock *ExitingBlock : ExitingBlocks) {
364 if (hasDivergentBranch(ExitingBlock))
365 return false;
366 }
367
368 FromCycle = CI->getParentCycle(FromCycle);
369 }
370 }
371 }
372
373 return true;
374}
375
377 int64_t &Offset0,
378 int64_t &Offset1) const {
379 if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode())
380 return false;
381
382 unsigned Opc0 = Load0->getMachineOpcode();
383 unsigned Opc1 = Load1->getMachineOpcode();
384
385 // Make sure both are actually loads.
386 if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad())
387 return false;
388
389 // A mayLoad instruction without a def is not a load. Likely a prefetch.
390 if (!get(Opc0).getNumDefs() || !get(Opc1).getNumDefs())
391 return false;
392
393 if (isDS(Opc0) && isDS(Opc1)) {
394
395 // FIXME: Handle this case:
396 if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1))
397 return false;
398
399 // Check base reg.
400 if (Load0->getOperand(0) != Load1->getOperand(0))
401 return false;
402
403 // Skip read2 / write2 variants for simplicity.
404 // TODO: We should report true if the used offsets are adjacent (excluded
405 // st64 versions).
406 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
407 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
408 if (Offset0Idx == -1 || Offset1Idx == -1)
409 return false;
410
411 // XXX - be careful of dataless loads
412 // getNamedOperandIdx returns the index for MachineInstrs. Since they
413 // include the output in the operand list, but SDNodes don't, we need to
414 // subtract the index by one.
415 Offset0Idx -= get(Opc0).NumDefs;
416 Offset1Idx -= get(Opc1).NumDefs;
417 Offset0 = Load0->getConstantOperandVal(Offset0Idx);
418 Offset1 = Load1->getConstantOperandVal(Offset1Idx);
419 return true;
420 }
421
422 if (isSMRD(Opc0) && isSMRD(Opc1)) {
423 // Skip time and cache invalidation instructions.
424 if (!AMDGPU::hasNamedOperand(Opc0, AMDGPU::OpName::sbase) ||
425 !AMDGPU::hasNamedOperand(Opc1, AMDGPU::OpName::sbase))
426 return false;
427
428 unsigned NumOps = getNumOperandsNoGlue(Load0);
429 if (NumOps != getNumOperandsNoGlue(Load1))
430 return false;
431
432 // Check base reg.
433 if (Load0->getOperand(0) != Load1->getOperand(0))
434 return false;
435
436 // Match register offsets, if both register and immediate offsets present.
437 assert(NumOps == 4 || NumOps == 5);
438 if (NumOps == 5 && Load0->getOperand(1) != Load1->getOperand(1))
439 return false;
440
441 const ConstantSDNode *Load0Offset =
443 const ConstantSDNode *Load1Offset =
445
446 if (!Load0Offset || !Load1Offset)
447 return false;
448
449 Offset0 = Load0Offset->getZExtValue();
450 Offset1 = Load1Offset->getZExtValue();
451 return true;
452 }
453
454 // MUBUF and MTBUF can access the same addresses.
455 if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) {
456
457 // MUBUF and MTBUF have vaddr at different indices.
458 if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) ||
459 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) ||
460 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc))
461 return false;
462
463 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
464 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
465
466 if (OffIdx0 == -1 || OffIdx1 == -1)
467 return false;
468
469 // getNamedOperandIdx returns the index for MachineInstrs. Since they
470 // include the output in the operand list, but SDNodes don't, we need to
471 // subtract the index by one.
472 OffIdx0 -= get(Opc0).NumDefs;
473 OffIdx1 -= get(Opc1).NumDefs;
474
475 SDValue Off0 = Load0->getOperand(OffIdx0);
476 SDValue Off1 = Load1->getOperand(OffIdx1);
477
478 // The offset might be a FrameIndexSDNode.
479 if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1))
480 return false;
481
482 Offset0 = Off0->getAsZExtVal();
483 Offset1 = Off1->getAsZExtVal();
484 return true;
485 }
486
487 return false;
488}
489
490static bool isStride64(unsigned Opc) {
491 switch (Opc) {
492 case AMDGPU::DS_READ2ST64_B32:
493 case AMDGPU::DS_READ2ST64_B64:
494 case AMDGPU::DS_WRITE2ST64_B32:
495 case AMDGPU::DS_WRITE2ST64_B64:
496 return true;
497 default:
498 return false;
499 }
500}
501
504 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const {
505 if (!LdSt.mayLoadOrStore())
506 return false;
507
508 unsigned Opc = LdSt.getOpcode();
509 OffsetIsScalable = false;
510 const MachineOperand *BaseOp, *OffsetOp;
511 int DataOpIdx;
512
513 if (isDS(LdSt)) {
514 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr);
515 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
516 if (OffsetOp) {
517 // Normal, single offset LDS instruction.
518 if (!BaseOp) {
519 // DS_CONSUME/DS_APPEND use M0 for the base address.
520 // TODO: find the implicit use operand for M0 and use that as BaseOp?
521 return false;
522 }
523 BaseOps.push_back(BaseOp);
524 Offset = OffsetOp->getImm();
525 // Get appropriate operand, and compute width accordingly.
526 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
527 if (DataOpIdx == -1)
528 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
529 if (Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
530 Width = LocationSize::precise(64);
531 else
532 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
533 } else {
534 // The 2 offset instructions use offset0 and offset1 instead. We can treat
535 // these as a load with a single offset if the 2 offsets are consecutive.
536 // We will use this for some partially aligned loads.
537 const MachineOperand *Offset0Op =
538 getNamedOperand(LdSt, AMDGPU::OpName::offset0);
539 const MachineOperand *Offset1Op =
540 getNamedOperand(LdSt, AMDGPU::OpName::offset1);
541
542 unsigned Offset0 = Offset0Op->getImm() & 0xff;
543 unsigned Offset1 = Offset1Op->getImm() & 0xff;
544 if (Offset0 + 1 != Offset1)
545 return false;
546
547 // Each of these offsets is in element sized units, so we need to convert
548 // to bytes of the individual reads.
549
550 unsigned EltSize;
551 if (LdSt.mayLoad())
552 EltSize = RI.getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16;
553 else {
554 assert(LdSt.mayStore());
555 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
556 EltSize = RI.getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8;
557 }
558
559 if (isStride64(Opc))
560 EltSize *= 64;
561
562 BaseOps.push_back(BaseOp);
563 Offset = EltSize * Offset0;
564 // Get appropriate operand(s), and compute width accordingly.
565 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
566 if (DataOpIdx == -1) {
567 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
568 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
569 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
570 Width = LocationSize::precise(
571 Width.getValue() + TypeSize::getFixed(getOpSize(LdSt, DataOpIdx)));
572 } else {
573 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
574 }
575 }
576 return true;
577 }
578
579 if (isMUBUF(LdSt) || isMTBUF(LdSt)) {
580 const MachineOperand *RSrc = getNamedOperand(LdSt, AMDGPU::OpName::srsrc);
581 if (!RSrc) // e.g. BUFFER_WBINVL1_VOL
582 return false;
583 BaseOps.push_back(RSrc);
584 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
585 if (BaseOp && !BaseOp->isFI())
586 BaseOps.push_back(BaseOp);
587 const MachineOperand *OffsetImm =
588 getNamedOperand(LdSt, AMDGPU::OpName::offset);
589 Offset = OffsetImm->getImm();
590 const MachineOperand *SOffset =
591 getNamedOperand(LdSt, AMDGPU::OpName::soffset);
592 if (SOffset) {
593 if (SOffset->isReg())
594 BaseOps.push_back(SOffset);
595 else
596 Offset += SOffset->getImm();
597 }
598 // Get appropriate operand, and compute width accordingly.
599 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
600 if (DataOpIdx == -1)
601 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
602 if (DataOpIdx == -1) // LDS DMA
603 return false;
604 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
605 return true;
606 }
607
608 if (isImage(LdSt)) {
609 auto RsrcOpName =
610 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
611 int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RsrcOpName);
612 BaseOps.push_back(&LdSt.getOperand(SRsrcIdx));
613 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
614 if (VAddr0Idx >= 0) {
615 // GFX10 possible NSA encoding.
616 for (int I = VAddr0Idx; I < SRsrcIdx; ++I)
617 BaseOps.push_back(&LdSt.getOperand(I));
618 } else {
619 BaseOps.push_back(getNamedOperand(LdSt, AMDGPU::OpName::vaddr));
620 }
621 Offset = 0;
622 // Get appropriate operand, and compute width accordingly.
623 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
624 if (DataOpIdx == -1)
625 return false; // no return sampler
626 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
627 return true;
628 }
629
630 if (isSMRD(LdSt)) {
631 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::sbase);
632 if (!BaseOp) // e.g. S_MEMTIME
633 return false;
634 BaseOps.push_back(BaseOp);
635 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
636 Offset = OffsetOp ? OffsetOp->getImm() : 0;
637 // Get appropriate operand, and compute width accordingly.
638 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
639 if (DataOpIdx == -1)
640 return false;
641 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
642 return true;
643 }
644
645 if (isFLAT(LdSt)) {
646 // Instructions have either vaddr or saddr or both or none.
647 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
648 if (BaseOp)
649 BaseOps.push_back(BaseOp);
650 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr);
651 if (BaseOp)
652 BaseOps.push_back(BaseOp);
653 Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm();
654 // Get appropriate operand, and compute width accordingly.
655 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
656 if (DataOpIdx == -1)
657 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
658 if (DataOpIdx == -1) // LDS DMA
659 return false;
660 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
661 return true;
662 }
663
664 return false;
665}
666
667static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
669 const MachineInstr &MI2,
671 // Only examine the first "base" operand of each instruction, on the
672 // assumption that it represents the real base address of the memory access.
673 // Other operands are typically offsets or indices from this base address.
674 if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
675 return true;
676
677 if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
678 return false;
679
680 auto *MO1 = *MI1.memoperands_begin();
681 auto *MO2 = *MI2.memoperands_begin();
682 if (MO1->getAddrSpace() != MO2->getAddrSpace())
683 return false;
684
685 const auto *Base1 = MO1->getValue();
686 const auto *Base2 = MO2->getValue();
687 if (!Base1 || !Base2)
688 return false;
689 Base1 = getUnderlyingObject(Base1);
690 Base2 = getUnderlyingObject(Base2);
691
692 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
693 return false;
694
695 return Base1 == Base2;
696}
697
700 ArrayRef<const MachineOperand *> BaseOps2) const {
701 // Accesses without base operands (e.g. scratch addressed only by an
702 // immediate offset) share the same implicit base.
703 if (BaseOps1.empty() || BaseOps2.empty())
704 return BaseOps1.empty() && BaseOps2.empty();
705 return memOpsHaveSameBasePtr(*BaseOps1.front()->getParent(), BaseOps1,
706 *BaseOps2.front()->getParent(), BaseOps2);
707}
708
710 int64_t Offset1, bool OffsetIsScalable1,
712 int64_t Offset2, bool OffsetIsScalable2,
713 unsigned ClusterSize,
714 unsigned NumBytes) const {
715 // If the mem ops (to be clustered) do not have the same base ptr, then they
716 // should not be clustered
717 if (!memOpsHaveSameBase(BaseOps1, BaseOps2))
718 return false;
719
720 // Both lists are empty or neither is, so BaseOps1 alone decides whether
721 // there is an instruction to read the budget from.
722 assert(BaseOps1.empty() == BaseOps2.empty());
723 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;
724 if (!BaseOps1.empty()) {
725 const MachineFunction *MF = BaseOps1.front()->getParent()->getMF();
726 MaxMemoryClusterDWords =
727 MF->getInfo<SIMachineFunctionInfo>()->getMaxMemoryClusterDWords();
728 }
729
730 // In order to avoid register pressure, on an average, the number of DWORDS
731 // loaded together by all clustered mem ops should not exceed
732 // MaxMemoryClusterDWords. This is an empirical value based on certain
733 // observations and performance related experiments.
734 // The good thing about this heuristic is - it avoids clustering of too many
735 // sub-word loads, and also avoids clustering of wide loads. Below is the
736 // brief summary of how the heuristic behaves for various `LoadSize` when
737 // MaxMemoryClusterDWords is 8.
738 //
739 // (1) 1 <= LoadSize <= 4: cluster at max 8 mem ops
740 // (2) 5 <= LoadSize <= 8: cluster at max 4 mem ops
741 // (3) 9 <= LoadSize <= 12: cluster at max 2 mem ops
742 // (4) 13 <= LoadSize <= 16: cluster at max 2 mem ops
743 // (5) LoadSize >= 17: do not cluster
744 const unsigned LoadSize = NumBytes / ClusterSize;
745 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
746 return NumDWords <= MaxMemoryClusterDWords;
747}
748
749// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
750// the first 16 loads will be interleaved with the stores, and the next 16 will
751// be clustered as expected. It should really split into 2 16 store batches.
752//
753// Loads are clustered until this returns false, rather than trying to schedule
754// groups of stores. This also means we have to deal with saying different
755// address space loads should be clustered, and ones which might cause bank
756// conflicts.
757//
758// This might be deprecated so it might not be worth that much effort to fix.
760 int64_t Offset0, int64_t Offset1,
761 unsigned NumLoads) const {
762 assert(Offset1 > Offset0 &&
763 "Second offset should be larger than first offset!");
764 // If we have less than 16 loads in a row, and the offsets are within 64
765 // bytes, then schedule together.
766
767 // A cacheline is 64 bytes (for global memory).
768 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
769}
770
773 const DebugLoc &DL, MCRegister DestReg,
774 MCRegister SrcReg, bool KillSrc,
775 const char *Msg = "illegal VGPR to SGPR copy") {
776 MachineFunction *MF = MBB.getParent();
777
780
781 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg)
782 .addReg(SrcReg, getKillRegState(KillSrc));
783}
784
785/// Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908. It is not
786/// possible to have a direct copy in these cases on GFX908, so an intermediate
787/// VGPR copy is required.
790 const DebugLoc &DL, MCRegister DestReg,
791 MCRegister SrcReg, bool KillSrc,
792 RegScavenger &RS, bool RegsOverlap,
793 Register ImpUseSuperReg = Register()) {
794 assert((TII.getSubtarget().hasMAIInsts() &&
795 !TII.getSubtarget().hasGFX90AInsts()) &&
796 "Expected GFX908 subtarget.");
797
798 assert((AMDGPU::SReg_32RegClass.contains(SrcReg) ||
799 AMDGPU::AGPR_32RegClass.contains(SrcReg)) &&
800 "Source register of the copy should be either an SGPR or an AGPR.");
801
802 assert(AMDGPU::AGPR_32RegClass.contains(DestReg) &&
803 "Destination register of the copy should be an AGPR.");
804
805 const SIRegisterInfo &RI = TII.getRegisterInfo();
806
807 // First try to find defining accvgpr_write to avoid temporary registers.
808 // In the case of copies of overlapping AGPRs, we conservatively do not
809 // reuse previous accvgpr_writes. Otherwise, we may incorrectly pick up
810 // an accvgpr_write used for this same copy due to implicit-defs
811 if (!RegsOverlap) {
812 for (auto Def = MI, E = MBB.begin(); Def != E; ) {
813 --Def;
814
815 if (!Def->modifiesRegister(SrcReg, &RI))
816 continue;
817
818 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
819 Def->getOperand(0).getReg() != SrcReg)
820 break;
821
822 MachineOperand &DefOp = Def->getOperand(1);
823 assert(DefOp.isReg() || DefOp.isImm());
824
825 if (DefOp.isReg()) {
826 bool SafeToPropagate = true;
827 // Check that register source operand is not clobbered before MI.
828 // Immediate operands are always safe to propagate.
829 for (auto I = Def; I != MI && SafeToPropagate; ++I)
830 if (I->modifiesRegister(DefOp.getReg(), &RI))
831 SafeToPropagate = false;
832
833 if (!SafeToPropagate)
834 break;
835
836 for (auto I = Def; I != MI; ++I)
837 I->clearRegisterKills(DefOp.getReg(), &RI);
838 }
839
840 MachineInstrBuilder Builder =
841 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64),
842 DestReg)
843 .add(DefOp);
844
845 if (ImpUseSuperReg) {
846 Builder.addReg(ImpUseSuperReg,
848 }
849
850 return;
851 }
852 }
853
854 RS.enterBasicBlockEnd(MBB);
855 RS.backward(std::next(MI));
856
857 // Ideally we want to have three registers for a long reg_sequence copy
858 // to hide 2 waitstates between v_mov_b32 and accvgpr_write.
859 unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass,
860 *MBB.getParent());
861
862 // Registers in the sequence are allocated contiguously so we can just
863 // use register number to pick one of three round-robin temps.
864 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
865 Register Tmp =
866 MBB.getParent()->getInfo<SIMachineFunctionInfo>()->getVGPRForAGPRCopy();
867 assert(MBB.getParent()->getRegInfo().isReserved(Tmp) &&
868 "VGPR used for an intermediate copy should have been reserved.");
869
870 // Only loop through if there are any free registers left. We don't want to
871 // spill.
872 while (RegNo--) {
873 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI,
874 /* RestoreAfter */ false, 0,
875 /* AllowSpill */ false);
876 if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs)
877 break;
878 Tmp = Tmp2;
879 RS.setRegUsed(Tmp);
880 }
881
882 // Insert copy to temporary VGPR.
883 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
884 if (AMDGPU::AGPR_32RegClass.contains(SrcReg)) {
885 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
886 } else {
887 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
888 }
889
890 MachineInstrBuilder UseBuilder = BuildMI(MBB, MI, DL, TII.get(TmpCopyOp), Tmp)
891 .addReg(SrcReg, getKillRegState(KillSrc));
892 if (ImpUseSuperReg) {
893 UseBuilder.addReg(ImpUseSuperReg,
895 }
896
897 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
898 .addReg(Tmp, RegState::Kill);
899}
900
903 MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
904 const TargetRegisterClass *RC, bool Forward) {
905 const SIRegisterInfo &RI = TII.getRegisterInfo();
906 ArrayRef<int16_t> BaseIndices = RI.getRegSplitParts(RC, 4);
908 MachineInstr *FirstMI = nullptr, *LastMI = nullptr;
909
910 for (unsigned Idx = 0; Idx < BaseIndices.size(); ++Idx) {
911 int16_t SubIdx = BaseIndices[Idx];
912 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
913 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
914 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
915 unsigned Opcode = AMDGPU::S_MOV_B32;
916
917 // Is SGPR aligned? If so try to combine with next.
918 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
919 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
920 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.size())) {
921 // Can use SGPR64 copy
922 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
923 SubIdx = RI.getSubRegFromChannel(Channel, 2);
924 DestSubReg = RI.getSubReg(DestReg, SubIdx);
925 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
926 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
927 Opcode = AMDGPU::S_MOV_B64;
928 Idx++;
929 }
930
931 LastMI = BuildMI(MBB, I, DL, TII.get(Opcode), DestSubReg)
932 .addReg(SrcSubReg)
933 .addReg(SrcReg, RegState::Implicit);
934
935 if (!FirstMI)
936 FirstMI = LastMI;
937
938 if (!Forward)
939 I--;
940 }
941
942 assert(FirstMI && LastMI);
943 if (!Forward)
944 std::swap(FirstMI, LastMI);
945
946 if (KillSrc)
947 LastMI->addRegisterKilled(SrcReg, &RI);
948}
949
952 const DebugLoc &DL, Register DestReg,
953 Register SrcReg, bool KillSrc, bool RenamableDest,
954 bool RenamableSrc) const {
955 const TargetRegisterClass *RC = RI.getPhysRegBaseClass(DestReg);
956 unsigned Size = RI.getRegSizeInBits(*RC);
957 const TargetRegisterClass *SrcRC = RI.getPhysRegBaseClass(SrcReg);
958 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
959
960 // The rest of copyPhysReg assumes Src and Dst size are the same size.
961 // TODO-GFX11_16BIT If all true 16 bit instruction patterns are completed can
962 // we remove Fix16BitCopies and this code block?
963 if (Fix16BitCopies) {
964 if (((Size == 16) != (SrcSize == 16))) {
965 // Non-VGPR Src and Dst will later be expanded back to 32 bits.
966 assert(ST.useRealTrue16Insts());
967 Register &RegToFix = (Size == 32) ? DestReg : SrcReg;
968 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
969 RegToFix = SubReg;
970
971 if (DestReg == SrcReg) {
972 // Identity copy. Insert empty bundle since ExpandPostRA expects an
973 // instruction here.
974 BuildMI(MBB, MI, DL, get(AMDGPU::BUNDLE));
975 return;
976 }
977 RC = RI.getPhysRegBaseClass(DestReg);
978 Size = RI.getRegSizeInBits(*RC);
979 SrcRC = RI.getPhysRegBaseClass(SrcReg);
980 SrcSize = RI.getRegSizeInBits(*SrcRC);
981 }
982 }
983
984 if (RC == &AMDGPU::VGPR_32RegClass) {
985 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
986 AMDGPU::SReg_32RegClass.contains(SrcReg) ||
987 AMDGPU::AGPR_32RegClass.contains(SrcReg));
988 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
989 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
990 BuildMI(MBB, MI, DL, get(Opc), DestReg)
991 .addReg(SrcReg, getKillRegState(KillSrc));
992 return;
993 }
994
995 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
996 RC == &AMDGPU::SReg_32RegClass) {
997 if (SrcReg == AMDGPU::SCC) {
998 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg)
999 .addImm(1)
1000 .addImm(0);
1001 return;
1002 }
1003
1004 if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) {
1005 if (DestReg == AMDGPU::VCC_LO) {
1006 // FIXME: Hack until VReg_1 removed.
1007 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
1008 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
1009 .addImm(0)
1010 .addReg(SrcReg, getKillRegState(KillSrc));
1011 return;
1012 }
1013
1014 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1015 return;
1016 }
1017
1018 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
1019 .addReg(SrcReg, getKillRegState(KillSrc));
1020 return;
1021 }
1022
1023 if (RC == &AMDGPU::SReg_64RegClass) {
1024 if (SrcReg == AMDGPU::SCC) {
1025 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B64), DestReg)
1026 .addImm(1)
1027 .addImm(0);
1028 return;
1029 }
1030
1031 if (!AMDGPU::SReg_64_EncodableRegClass.contains(SrcReg)) {
1032 if (DestReg == AMDGPU::VCC) {
1033 // FIXME: Hack until VReg_1 removed.
1034 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
1035 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
1036 .addImm(0)
1037 .addReg(SrcReg, getKillRegState(KillSrc));
1038 return;
1039 }
1040
1041 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1042 return;
1043 }
1044
1045 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
1046 .addReg(SrcReg, getKillRegState(KillSrc));
1047 return;
1048 }
1049
1050 if (DestReg == AMDGPU::SCC) {
1051 // Copying 64-bit or 32-bit sources to SCC barely makes sense,
1052 // but SelectionDAG emits such copies for i1 sources.
1053 if (AMDGPU::SReg_64RegClass.contains(SrcReg)) {
1054 // This copy can only be produced by patterns
1055 // with explicit SCC, which are known to be enabled
1056 // only for subtargets with S_CMP_LG_U64 present.
1057 assert(ST.hasScalarCompareEq64());
1058 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U64))
1059 .addReg(SrcReg, getKillRegState(KillSrc))
1060 .addImm(0);
1061 } else {
1062 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
1063 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32))
1064 .addReg(SrcReg, getKillRegState(KillSrc))
1065 .addImm(0);
1066 }
1067
1068 return;
1069 }
1070
1071 if (RC == &AMDGPU::AGPR_32RegClass) {
1072 if (AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
1073 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1074 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
1075 .addReg(SrcReg, getKillRegState(KillSrc));
1076 return;
1077 }
1078
1079 if (AMDGPU::AGPR_32RegClass.contains(SrcReg) && ST.hasGFX90AInsts()) {
1080 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_MOV_B32), DestReg)
1081 .addReg(SrcReg, getKillRegState(KillSrc));
1082 return;
1083 }
1084
1085 // FIXME: Pass should maintain scavenger to avoid scan through the block on
1086 // every AGPR spill.
1087 RegScavenger RS;
1088 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1089 indirectCopyToAGPR(*this, MBB, MI, DL, DestReg, SrcReg, KillSrc, RS, Overlap);
1090 return;
1091 }
1092
1093 if (Size == 16) {
1094 assert(AMDGPU::VGPR_16RegClass.contains(SrcReg) ||
1095 AMDGPU::SReg_LO16RegClass.contains(SrcReg) ||
1096 AMDGPU::AGPR_LO16RegClass.contains(SrcReg));
1097
1098 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1099 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1100 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1101 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1102 bool DstLow = !AMDGPU::isHi16Reg(DestReg, RI);
1103 bool SrcLow = !AMDGPU::isHi16Reg(SrcReg, RI);
1104 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1105 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1106
1107 if (IsSGPRDst) {
1108 if (!IsSGPRSrc) {
1109 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1110 return;
1111 }
1112
1113 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), NewDestReg)
1114 .addReg(NewSrcReg, getKillRegState(KillSrc));
1115 return;
1116 }
1117
1118 if (IsAGPRDst || IsAGPRSrc) {
1119 if (!DstLow || !SrcLow) {
1120 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1121 "Cannot use hi16 subreg with an AGPR!");
1122 }
1123
1124 copyPhysReg(MBB, MI, DL, NewDestReg, NewSrcReg, KillSrc);
1125 return;
1126 }
1127
1128 if (ST.useRealTrue16Insts()) {
1129 if (IsSGPRSrc) {
1130 assert(SrcLow);
1131 SrcReg = NewSrcReg;
1132 }
1133 // Use the smaller instruction encoding if possible.
1134 if (AMDGPU::VGPR_16_Lo128RegClass.contains(DestReg) &&
1135 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.contains(SrcReg))) {
1136 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e32), DestReg)
1137 .addReg(SrcReg);
1138 } else {
1139 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e64), DestReg)
1140 .addImm(0) // src0_modifiers
1141 .addReg(SrcReg)
1142 .addImm(0); // op_sel
1143 }
1144 return;
1145 }
1146
1147 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1148 if (!DstLow || !SrcLow) {
1149 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1150 "Cannot use hi16 subreg on VI!");
1151 }
1152
1153 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), NewDestReg)
1154 .addReg(NewSrcReg, getKillRegState(KillSrc));
1155 return;
1156 }
1157
1158 auto MIB = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_sdwa), NewDestReg)
1159 .addImm(0) // src0_modifiers
1160 .addReg(NewSrcReg)
1161 .addImm(0) // clamp
1168 // First implicit operand is $exec.
1169 MIB->tieOperands(0, MIB->getNumOperands() - 1);
1170 return;
1171 }
1172
1173 // Returns true if Dst and Src are in Opc's HwMode-resolved destination and
1174 // source operand classes.
1175 auto CanCopyWith = [&](unsigned Opc, MCRegister Dst, MCRegister Src,
1176 unsigned SrcOp = 1) {
1177 const MCInstrDesc &Desc = get(Opc);
1178 const TargetRegisterClass *DstOpRC = getRegClass(Desc, 0);
1179 const TargetRegisterClass *SrcOpRC = getRegClass(Desc, SrcOp);
1180 return DstOpRC && SrcOpRC && DstOpRC->contains(Dst) &&
1181 SrcOpRC->contains(Src);
1182 };
1183
1184 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1185 if (ST.hasVMovB64Inst() &&
1186 CanCopyWith(AMDGPU::V_MOV_B64_e32, DestReg, SrcReg)) {
1187 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_e32), DestReg)
1188 .addReg(SrcReg, getKillRegState(KillSrc));
1189 return;
1190 }
1191 if (ST.hasPkMovB32() &&
1192 CanCopyWith(AMDGPU::V_PK_MOV_B32, DestReg, SrcReg, /*SrcOp=*/2)) {
1193 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestReg)
1195 .addReg(SrcReg)
1197 .addReg(SrcReg)
1198 .addImm(0) // op_sel_lo
1199 .addImm(0) // op_sel_hi
1200 .addImm(0) // neg_lo
1201 .addImm(0) // neg_hi
1202 .addImm(0) // clamp
1203 .addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
1204 return;
1205 }
1206 }
1207
1208 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1209 if (RI.isSGPRClass(RC)) {
1210 if (!RI.isSGPRClass(SrcRC)) {
1211 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1212 return;
1213 }
1214 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1215 expandSGPRCopy(*this, MBB, MI, DL, DestReg, SrcReg, CanKillSuperReg, RC,
1216 Forward);
1217 return;
1218 }
1219
1220 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1221 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1222 if (RI.isAGPRClass(RC)) {
1223 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1224 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1225 else if (RI.hasVGPRs(SrcRC) ||
1226 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1227 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1228 else
1229 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1230 } else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1231 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1232 } else if (RI.isVGPRClass(RC)) {
1233 if (ST.hasVMovB64Inst())
1234 WideOpcode = AMDGPU::V_MOV_B64_e32;
1235 else if (ST.hasPkMovB32())
1236 WideOpcode = AMDGPU::V_PK_MOV_B32;
1237 }
1238
1239 const TargetRegisterClass *WideDstRC{}, *WideSrcRC{};
1240 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1241 const MCInstrDesc &Desc = get(WideOpcode);
1242 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1243 WideDstRC = getRegClass(Desc, 0);
1244 WideSrcRC = getRegClass(Desc, SrcOp);
1245 }
1246
1247 // If there is an overlap, we can't kill the super-register on the last
1248 // instruction, since it will also kill the components made live by this def.
1249 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1250 const bool CanKillSuperReg = KillSrc && !Overlap;
1251
1252 // For the cases where we need an intermediate instruction/temporary register
1253 // (destination is an AGPR), we need a scavenger.
1254 //
1255 // FIXME: The pass should maintain this for us so we don't have to re-scan the
1256 // whole block for every handled copy.
1257 std::unique_ptr<RegScavenger> RS;
1258 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1259 RS = std::make_unique<RegScavenger>();
1260
1261 ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, 4);
1262
1263 for (unsigned Idx{}; Idx < SubIndices.size();) {
1264 unsigned NumRegs = 1;
1265 unsigned ThisOpcode = Opcode;
1266 unsigned SubIdx =
1267 Forward ? SubIndices[Idx] : SubIndices[SubIndices.size() - Idx - 1];
1268
1269 if (WideDstRC && WideSrcRC && Idx + 1 < SubIndices.size()) {
1270 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1271 if (!Forward)
1272 --Channel;
1273
1274 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1275 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1276 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1277
1278 if (WideDst && WideSrc && WideDstRC->contains(WideDst) &&
1279 WideSrcRC->contains(WideSrc)) {
1280 SubIdx = WideSubIdx;
1281 NumRegs = 2;
1282 ThisOpcode = WideOpcode;
1283 }
1284 }
1285
1286 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1287 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1288 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
1289
1290 Idx += NumRegs;
1291 bool UseKill = CanKillSuperReg && Idx == SubIndices.size();
1292
1293 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1294 Register ImpUseSuper = SrcReg;
1295 indirectCopyToAGPR(*this, MBB, MI, DL, DestSubReg, SrcSubReg, UseKill,
1296 *RS, Overlap, ImpUseSuper);
1297 } else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1298 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestSubReg)
1300 .addReg(SrcSubReg)
1302 .addReg(SrcSubReg)
1303 .addImm(0) // op_sel_lo
1304 .addImm(0) // op_sel_hi
1305 .addImm(0) // neg_lo
1306 .addImm(0) // neg_hi
1307 .addImm(0) // clamp
1308 .addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1309 } else {
1310 MachineInstrBuilder Builder =
1311 BuildMI(MBB, MI, DL, get(ThisOpcode), DestSubReg).addReg(SrcSubReg);
1312
1313 Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1314 }
1315 }
1316}
1317
1318int SIInstrInfo::commuteOpcode(unsigned Opcode) const {
1319 int32_t NewOpc;
1320
1321 // Try to map original to commuted opcode
1322 NewOpc = AMDGPU::getCommuteRev(Opcode);
1323 if (NewOpc != -1)
1324 // Check if the commuted (REV) opcode exists on the target.
1325 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1326
1327 // Try to map commuted to original opcode
1328 NewOpc = AMDGPU::getCommuteOrig(Opcode);
1329 if (NewOpc != -1)
1330 // Check if the original (non-REV) opcode exists on the target.
1331 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1332
1333 return Opcode;
1334}
1335
1337 const Register Reg,
1338 int64_t &ImmVal) const {
1339 switch (MI.getOpcode()) {
1340 case AMDGPU::V_MOV_B32_e32:
1341 case AMDGPU::S_MOV_B32:
1342 case AMDGPU::S_MOVK_I32:
1343 case AMDGPU::S_MOV_B64:
1344 case AMDGPU::V_MOV_B64_e32:
1345 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1346 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1347 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1348 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1349 case AMDGPU::V_MOV_B64_PSEUDO:
1350 case AMDGPU::V_MOV_B16_t16_e32: {
1351 const MachineOperand &Src0 = MI.getOperand(1);
1352 if (Src0.isImm()) {
1353 ImmVal = Src0.getImm();
1354 return MI.getOperand(0).getReg() == Reg;
1355 }
1356
1357 return false;
1358 }
1359 case AMDGPU::V_MOV_B16_t16_e64: {
1360 const MachineOperand &Src0 = MI.getOperand(2);
1361 if (Src0.isImm() && !MI.getOperand(1).getImm()) {
1362 ImmVal = Src0.getImm();
1363 return MI.getOperand(0).getReg() == Reg;
1364 }
1365
1366 return false;
1367 }
1368 case AMDGPU::S_BREV_B32:
1369 case AMDGPU::V_BFREV_B32_e32:
1370 case AMDGPU::V_BFREV_B32_e64: {
1371 const MachineOperand &Src0 = MI.getOperand(1);
1372 if (Src0.isImm()) {
1373 ImmVal = static_cast<int64_t>(reverseBits<int32_t>(Src0.getImm()));
1374 return MI.getOperand(0).getReg() == Reg;
1375 }
1376
1377 return false;
1378 }
1379 case AMDGPU::S_NOT_B32:
1380 case AMDGPU::V_NOT_B32_e32:
1381 case AMDGPU::V_NOT_B32_e64: {
1382 const MachineOperand &Src0 = MI.getOperand(1);
1383 if (Src0.isImm()) {
1384 ImmVal = static_cast<int64_t>(~static_cast<int32_t>(Src0.getImm()));
1385 return MI.getOperand(0).getReg() == Reg;
1386 }
1387
1388 return false;
1389 }
1390 default:
1391 return false;
1392 }
1393}
1394
1395std::optional<int64_t>
1397 const MachineOperand &Op,
1398 MachineInstr **DefMI) const {
1399 if (DefMI)
1400 *DefMI = nullptr;
1401
1402 if (Op.isImm())
1403 return Op.getImm();
1404
1405 if (!Op.isReg() || !Op.getReg().isVirtual())
1406 return std::nullopt;
1407 MachineInstr *Def = MRI.getUniqueVRegDef(Op.getReg());
1408 if (Def && Def->isMoveImmediate()) {
1409 const MachineOperand &ImmSrc = Def->getOperand(1);
1410 if (ImmSrc.isImm()) {
1411 if (DefMI)
1412 *DefMI = Def;
1413 return extractSubregFromImm(ImmSrc.getImm(), Op.getSubReg());
1414 }
1415 }
1416
1417 return std::nullopt;
1418}
1419
1420std::optional<int64_t>
1426
1428
1429 if (RI.isAGPRClass(DstRC))
1430 return AMDGPU::COPY;
1431 if (RI.getRegSizeInBits(*DstRC) == 16) {
1432 // Assume hi bits are unneeded. Only _e64 true16 instructions are legal
1433 // before RA.
1434 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1435 }
1436 if (RI.getRegSizeInBits(*DstRC) == 32)
1437 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1438 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1439 return AMDGPU::S_MOV_B64;
1440 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1441 return AMDGPU::V_MOV_B64_PSEUDO;
1442 return AMDGPU::COPY;
1443}
1444
1445const MCInstrDesc &
1447 bool IsIndirectSrc) const {
1448 if (IsIndirectSrc) {
1449 if (VecSize <= 32) // 4 bytes
1450 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1451 if (VecSize <= 64) // 8 bytes
1452 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1453 if (VecSize <= 96) // 12 bytes
1454 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1455 if (VecSize <= 128) // 16 bytes
1456 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1457 if (VecSize <= 160) // 20 bytes
1458 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1459 if (VecSize <= 192) // 24 bytes
1460 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1461 if (VecSize <= 224) // 28 bytes
1462 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1463 if (VecSize <= 256) // 32 bytes
1464 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1465 if (VecSize <= 288) // 36 bytes
1466 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1467 if (VecSize <= 320) // 40 bytes
1468 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1469 if (VecSize <= 352) // 44 bytes
1470 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1471 if (VecSize <= 384) // 48 bytes
1472 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1473 if (VecSize <= 512) // 64 bytes
1474 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1475 if (VecSize <= 1024) // 128 bytes
1476 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1477
1478 llvm_unreachable("unsupported size for IndirectRegReadGPRIDX pseudos");
1479 }
1480
1481 if (VecSize <= 32) // 4 bytes
1482 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1483 if (VecSize <= 64) // 8 bytes
1484 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1485 if (VecSize <= 96) // 12 bytes
1486 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1487 if (VecSize <= 128) // 16 bytes
1488 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1489 if (VecSize <= 160) // 20 bytes
1490 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1491 if (VecSize <= 192) // 24 bytes
1492 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1493 if (VecSize <= 224) // 28 bytes
1494 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1495 if (VecSize <= 256) // 32 bytes
1496 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1497 if (VecSize <= 288) // 36 bytes
1498 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1499 if (VecSize <= 320) // 40 bytes
1500 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1501 if (VecSize <= 352) // 44 bytes
1502 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1503 if (VecSize <= 384) // 48 bytes
1504 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1505 if (VecSize <= 512) // 64 bytes
1506 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1507 if (VecSize <= 1024) // 128 bytes
1508 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1509
1510 llvm_unreachable("unsupported size for IndirectRegWriteGPRIDX pseudos");
1511}
1512
1513static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize) {
1514 if (VecSize <= 32) // 4 bytes
1515 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1516 if (VecSize <= 64) // 8 bytes
1517 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1518 if (VecSize <= 96) // 12 bytes
1519 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1520 if (VecSize <= 128) // 16 bytes
1521 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1522 if (VecSize <= 160) // 20 bytes
1523 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1524 if (VecSize <= 192) // 24 bytes
1525 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1526 if (VecSize <= 224) // 28 bytes
1527 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1528 if (VecSize <= 256) // 32 bytes
1529 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1530 if (VecSize <= 288) // 36 bytes
1531 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1532 if (VecSize <= 320) // 40 bytes
1533 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1534 if (VecSize <= 352) // 44 bytes
1535 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1536 if (VecSize <= 384) // 48 bytes
1537 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1538 if (VecSize <= 512) // 64 bytes
1539 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1540 if (VecSize <= 1024) // 128 bytes
1541 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1542
1543 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1544}
1545
1546static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize) {
1547 if (VecSize <= 32) // 4 bytes
1548 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1549 if (VecSize <= 64) // 8 bytes
1550 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1551 if (VecSize <= 96) // 12 bytes
1552 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1553 if (VecSize <= 128) // 16 bytes
1554 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1555 if (VecSize <= 160) // 20 bytes
1556 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1557 if (VecSize <= 192) // 24 bytes
1558 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1559 if (VecSize <= 224) // 28 bytes
1560 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1561 if (VecSize <= 256) // 32 bytes
1562 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1563 if (VecSize <= 288) // 36 bytes
1564 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1565 if (VecSize <= 320) // 40 bytes
1566 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1567 if (VecSize <= 352) // 44 bytes
1568 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1569 if (VecSize <= 384) // 48 bytes
1570 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1571 if (VecSize <= 512) // 64 bytes
1572 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1573 if (VecSize <= 1024) // 128 bytes
1574 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1575
1576 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1577}
1578
1579static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize) {
1580 if (VecSize <= 64) // 8 bytes
1581 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1582 if (VecSize <= 128) // 16 bytes
1583 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1584 if (VecSize <= 256) // 32 bytes
1585 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1586 if (VecSize <= 512) // 64 bytes
1587 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1588 if (VecSize <= 1024) // 128 bytes
1589 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1590
1591 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1592}
1593
1594const MCInstrDesc &
1595SIInstrInfo::getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize,
1596 bool IsSGPR) const {
1597 if (IsSGPR) {
1598 switch (EltSize) {
1599 case 32:
1600 return get(getIndirectSGPRWriteMovRelPseudo32(VecSize));
1601 case 64:
1602 return get(getIndirectSGPRWriteMovRelPseudo64(VecSize));
1603 default:
1604 llvm_unreachable("invalid reg indexing elt size");
1605 }
1606 }
1607
1608 assert(EltSize == 32 && "invalid reg indexing elt size");
1610}
1611
1612static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1613 switch (Size) {
1614 case 4:
1615 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1616 case 8:
1617 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1618 case 12:
1619 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1620 case 16:
1621 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1622 : AMDGPU::SI_SPILL_S128_SAVE;
1623 case 20:
1624 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1625 : AMDGPU::SI_SPILL_S160_SAVE;
1626 case 24:
1627 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1628 : AMDGPU::SI_SPILL_S192_SAVE;
1629 case 28:
1630 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1631 : AMDGPU::SI_SPILL_S224_SAVE;
1632 case 32:
1633 return AMDGPU::SI_SPILL_S256_SAVE;
1634 case 36:
1635 return AMDGPU::SI_SPILL_S288_SAVE;
1636 case 40:
1637 return AMDGPU::SI_SPILL_S320_SAVE;
1638 case 44:
1639 return AMDGPU::SI_SPILL_S352_SAVE;
1640 case 48:
1641 return AMDGPU::SI_SPILL_S384_SAVE;
1642 case 64:
1643 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1644 : AMDGPU::SI_SPILL_S512_SAVE;
1645 case 128:
1646 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1647 : AMDGPU::SI_SPILL_S1024_SAVE;
1648 default:
1649 llvm_unreachable("unknown register size");
1650 }
1651}
1652
1653static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1654 switch (Size) {
1655 case 2:
1656 return AMDGPU::SI_SPILL_V16_SAVE;
1657 case 4:
1658 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1659 case 8:
1660 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1661 case 12:
1662 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1663 case 16:
1664 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1665 : AMDGPU::SI_SPILL_V128_SAVE;
1666 case 20:
1667 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1668 : AMDGPU::SI_SPILL_V160_SAVE;
1669 case 24:
1670 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1671 : AMDGPU::SI_SPILL_V192_SAVE;
1672 case 28:
1673 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1674 : AMDGPU::SI_SPILL_V224_SAVE;
1675 case 32:
1676 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1677 : AMDGPU::SI_SPILL_V256_SAVE;
1678 case 36:
1679 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1680 : AMDGPU::SI_SPILL_V288_SAVE;
1681 case 40:
1682 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1683 : AMDGPU::SI_SPILL_V320_SAVE;
1684 case 44:
1685 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1686 : AMDGPU::SI_SPILL_V352_SAVE;
1687 case 48:
1688 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1689 : AMDGPU::SI_SPILL_V384_SAVE;
1690 case 64:
1691 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1692 : AMDGPU::SI_SPILL_V512_SAVE;
1693 case 128:
1694 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1695 : AMDGPU::SI_SPILL_V1024_SAVE;
1696 default:
1697 llvm_unreachable("unknown register size");
1698 }
1699}
1700
1701static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1702 switch (Size) {
1703 case 4:
1704 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1705 : AMDGPU::SI_SPILL_AV32_SAVE;
1706 case 8:
1707 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1708 : AMDGPU::SI_SPILL_AV64_SAVE;
1709 case 12:
1710 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1711 : AMDGPU::SI_SPILL_AV96_SAVE;
1712 case 16:
1713 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1714 : AMDGPU::SI_SPILL_AV128_SAVE;
1715 case 20:
1716 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1717 : AMDGPU::SI_SPILL_AV160_SAVE;
1718 case 24:
1719 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1720 : AMDGPU::SI_SPILL_AV192_SAVE;
1721 case 28:
1722 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1723 : AMDGPU::SI_SPILL_AV224_SAVE;
1724 case 32:
1725 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1726 : AMDGPU::SI_SPILL_AV256_SAVE;
1727 case 36:
1728 return AMDGPU::SI_SPILL_AV288_SAVE;
1729 case 40:
1730 return AMDGPU::SI_SPILL_AV320_SAVE;
1731 case 44:
1732 return AMDGPU::SI_SPILL_AV352_SAVE;
1733 case 48:
1734 return AMDGPU::SI_SPILL_AV384_SAVE;
1735 case 64:
1736 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1737 : AMDGPU::SI_SPILL_AV512_SAVE;
1738 case 128:
1739 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1740 : AMDGPU::SI_SPILL_AV1024_SAVE;
1741 default:
1742 llvm_unreachable("unknown register size");
1743 }
1744}
1745
1746static unsigned getWWMRegSpillSaveOpcode(unsigned Size,
1747 bool IsVectorSuperClass) {
1748 // Currently, there is only 32-bit WWM register spills needed.
1749 if (Size != 4)
1750 llvm_unreachable("unknown wwm register spill size");
1751
1752 if (IsVectorSuperClass)
1753 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1754
1755 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1756}
1757
1759 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1760 const SIMachineFunctionInfo &MFI, bool NeedsCFI) const {
1761 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1762
1763 // Choose the right opcode if spilling a WWM register.
1765 return getWWMRegSpillSaveOpcode(Size, IsVectorSuperClass);
1766
1767 // TODO: Check if AGPRs are available
1768 if (ST.hasMAIInsts())
1769 return getAVSpillSaveOpcode(Size, NeedsCFI);
1770
1771 return getVGPRSpillSaveOpcode(Size, NeedsCFI);
1772}
1773
1774void SIInstrInfo::storeRegToStackSlotImpl(
1776 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1777 MachineInstr::MIFlag Flags, bool NeedsCFI) const {
1778 MachineFunction *MF = MBB.getParent();
1780 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1781 const DebugLoc &DL = MBB.findDebugLoc(MI);
1782
1783 MachinePointerInfo PtrInfo
1784 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1786 PtrInfo, MachineMemOperand::MOStore, FrameInfo.getObjectSize(FrameIndex),
1787 FrameInfo.getObjectAlign(FrameIndex));
1788 unsigned SpillSize = RI.getSpillSize(*RC);
1789
1791 if (RI.isSGPRClass(RC)) {
1792 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1793 MFI->setHasSpilledSGPRs();
1794 assert(SrcReg != AMDGPU::M0 && "m0 should not be spilled");
1795 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1796 SrcReg != AMDGPU::EXEC && "exec should not be spilled");
1797
1798 // We are only allowed to create one new instruction when spilling
1799 // registers, so we need to use pseudo instruction for spilling SGPRs.
1800 const MCInstrDesc &OpDesc =
1801 get(getSGPRSpillSaveOpcode(SpillSize, NeedsCFI));
1802
1803 // The SGPR spill/restore instructions only work on number sgprs, so we need
1804 // to make sure we are using the correct register class.
1805 if (SrcReg.isVirtual() && SpillSize == 4) {
1806 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1807 }
1808
1809 BuildMI(MBB, MI, DL, OpDesc)
1810 .addReg(SrcReg, getKillRegState(isKill)) // data
1811 .addFrameIndex(FrameIndex) // addr
1812 .addMemOperand(MMO)
1814
1815 return;
1816 }
1817
1818 unsigned Opcode = getVectorRegSpillSaveOpcode(VReg ? VReg : SrcReg, RC,
1819 SpillSize, *MFI, NeedsCFI);
1820 MFI->setHasSpilledVGPRs();
1821
1822 BuildMI(MBB, MI, DL, get(Opcode))
1823 .addReg(SrcReg, getKillRegState(isKill)) // data
1824 .addFrameIndex(FrameIndex) // addr
1825 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1826 .addImm(0) // offset
1827 .addMemOperand(MMO);
1828}
1829
1832 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1833 MachineInstr::MIFlag Flags) const {
1834 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1835 false);
1836}
1837
1840 Register SrcReg, bool isKill,
1841 int FrameIndex,
1842 const TargetRegisterClass *RC) const {
1843 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, Register(),
1844 MachineInstr::NoFlags, true);
1845}
1846
1847static unsigned getSGPRSpillRestoreOpcode(unsigned Size) {
1848 switch (Size) {
1849 case 4:
1850 return AMDGPU::SI_SPILL_S32_RESTORE;
1851 case 8:
1852 return AMDGPU::SI_SPILL_S64_RESTORE;
1853 case 12:
1854 return AMDGPU::SI_SPILL_S96_RESTORE;
1855 case 16:
1856 return AMDGPU::SI_SPILL_S128_RESTORE;
1857 case 20:
1858 return AMDGPU::SI_SPILL_S160_RESTORE;
1859 case 24:
1860 return AMDGPU::SI_SPILL_S192_RESTORE;
1861 case 28:
1862 return AMDGPU::SI_SPILL_S224_RESTORE;
1863 case 32:
1864 return AMDGPU::SI_SPILL_S256_RESTORE;
1865 case 36:
1866 return AMDGPU::SI_SPILL_S288_RESTORE;
1867 case 40:
1868 return AMDGPU::SI_SPILL_S320_RESTORE;
1869 case 44:
1870 return AMDGPU::SI_SPILL_S352_RESTORE;
1871 case 48:
1872 return AMDGPU::SI_SPILL_S384_RESTORE;
1873 case 64:
1874 return AMDGPU::SI_SPILL_S512_RESTORE;
1875 case 128:
1876 return AMDGPU::SI_SPILL_S1024_RESTORE;
1877 default:
1878 llvm_unreachable("unknown register size");
1879 }
1880}
1881
1882static unsigned getVGPRSpillRestoreOpcode(unsigned Size) {
1883 switch (Size) {
1884 case 2:
1885 return AMDGPU::SI_SPILL_V16_RESTORE;
1886 case 4:
1887 return AMDGPU::SI_SPILL_V32_RESTORE;
1888 case 8:
1889 return AMDGPU::SI_SPILL_V64_RESTORE;
1890 case 12:
1891 return AMDGPU::SI_SPILL_V96_RESTORE;
1892 case 16:
1893 return AMDGPU::SI_SPILL_V128_RESTORE;
1894 case 20:
1895 return AMDGPU::SI_SPILL_V160_RESTORE;
1896 case 24:
1897 return AMDGPU::SI_SPILL_V192_RESTORE;
1898 case 28:
1899 return AMDGPU::SI_SPILL_V224_RESTORE;
1900 case 32:
1901 return AMDGPU::SI_SPILL_V256_RESTORE;
1902 case 36:
1903 return AMDGPU::SI_SPILL_V288_RESTORE;
1904 case 40:
1905 return AMDGPU::SI_SPILL_V320_RESTORE;
1906 case 44:
1907 return AMDGPU::SI_SPILL_V352_RESTORE;
1908 case 48:
1909 return AMDGPU::SI_SPILL_V384_RESTORE;
1910 case 64:
1911 return AMDGPU::SI_SPILL_V512_RESTORE;
1912 case 128:
1913 return AMDGPU::SI_SPILL_V1024_RESTORE;
1914 default:
1915 llvm_unreachable("unknown register size");
1916 }
1917}
1918
1919static unsigned getAVSpillRestoreOpcode(unsigned Size) {
1920 switch (Size) {
1921 case 4:
1922 return AMDGPU::SI_SPILL_AV32_RESTORE;
1923 case 8:
1924 return AMDGPU::SI_SPILL_AV64_RESTORE;
1925 case 12:
1926 return AMDGPU::SI_SPILL_AV96_RESTORE;
1927 case 16:
1928 return AMDGPU::SI_SPILL_AV128_RESTORE;
1929 case 20:
1930 return AMDGPU::SI_SPILL_AV160_RESTORE;
1931 case 24:
1932 return AMDGPU::SI_SPILL_AV192_RESTORE;
1933 case 28:
1934 return AMDGPU::SI_SPILL_AV224_RESTORE;
1935 case 32:
1936 return AMDGPU::SI_SPILL_AV256_RESTORE;
1937 case 36:
1938 return AMDGPU::SI_SPILL_AV288_RESTORE;
1939 case 40:
1940 return AMDGPU::SI_SPILL_AV320_RESTORE;
1941 case 44:
1942 return AMDGPU::SI_SPILL_AV352_RESTORE;
1943 case 48:
1944 return AMDGPU::SI_SPILL_AV384_RESTORE;
1945 case 64:
1946 return AMDGPU::SI_SPILL_AV512_RESTORE;
1947 case 128:
1948 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1949 default:
1950 llvm_unreachable("unknown register size");
1951 }
1952}
1953
1954static unsigned getWWMRegSpillRestoreOpcode(unsigned Size,
1955 bool IsVectorSuperClass) {
1956 // Currently, there is only 32-bit WWM register spills needed.
1957 if (Size != 4)
1958 llvm_unreachable("unknown wwm register spill size");
1959
1960 if (IsVectorSuperClass) // TODO: Always use this if there are AGPRs
1961 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1962
1963 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1964}
1965
1967 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1968 const SIMachineFunctionInfo &MFI) const {
1969 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1970
1971 // Choose the right opcode if restoring a WWM register.
1973 return getWWMRegSpillRestoreOpcode(Size, IsVectorSuperClass);
1974
1975 // TODO: Check if AGPRs are available
1976 if (ST.hasMAIInsts())
1978
1979 assert(!RI.isAGPRClass(RC));
1981}
1982
1985 Register DestReg, int FrameIndex,
1986 const TargetRegisterClass *RC,
1987 Register VReg, unsigned SubReg,
1988 MachineInstr::MIFlag Flags) const {
1989 MachineFunction *MF = MBB.getParent();
1991 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1992 const DebugLoc &DL = MBB.findDebugLoc(MI);
1993 unsigned SpillSize = RI.getSpillSize(*RC);
1994
1995 MachinePointerInfo PtrInfo
1996 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1997
1999 PtrInfo, MachineMemOperand::MOLoad, FrameInfo.getObjectSize(FrameIndex),
2000 FrameInfo.getObjectAlign(FrameIndex));
2001
2002 if (RI.isSGPRClass(RC)) {
2003 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
2004 MFI->setHasSpilledSGPRs();
2005 assert(DestReg != AMDGPU::M0 && "m0 should not be reloaded into");
2006 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
2007 DestReg != AMDGPU::EXEC && "exec should not be spilled");
2008
2009 // FIXME: Maybe this should not include a memoperand because it will be
2010 // lowered to non-memory instructions.
2011 const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize));
2012 if (DestReg.isVirtual() && SpillSize == 4) {
2014 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
2015 }
2016
2017 BuildMI(MBB, MI, DL, OpDesc, DestReg)
2018 .addFrameIndex(FrameIndex) // addr
2019 .addMemOperand(MMO)
2021
2022 return;
2023 }
2024
2025 unsigned Opcode = getVectorRegSpillRestoreOpcode(VReg ? VReg : DestReg, RC,
2026 SpillSize, *MFI);
2027 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
2028 .addFrameIndex(FrameIndex) // vaddr
2029 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
2030 .addImm(0) // offset
2031 .addMemOperand(MMO);
2032}
2033
2038
2041 unsigned Quantity) const {
2042 DebugLoc DL = MBB.findDebugLoc(MI);
2043 unsigned MaxSNopCount = 1u << ST.getSNopBits();
2044 while (Quantity > 0) {
2045 unsigned Arg = std::min(Quantity, MaxSNopCount);
2046 Quantity -= Arg;
2047 BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
2048 }
2049}
2050
2054 const DebugLoc &DL) const {
2055 MachineFunction *MF = MBB.getParent();
2056 constexpr unsigned DoorbellIDMask = 0x3ff;
2057 constexpr unsigned ECQueueWaveAbort = 0x400;
2058
2059 MachineBasicBlock *TrapBB = &MBB;
2060 MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock();
2061
2062 if (!MBB.succ_empty() ||
2064 /*SkipPseudoOp=*/false) != MBB.end()) {
2065 MBB.splitAt(MI, /*UpdateLiveIns=*/false);
2066 TrapBB = MF->CreateMachineBasicBlock();
2067 BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB);
2068 MF->push_back(TrapBB);
2069 MBB.addSuccessor(TrapBB);
2070 }
2071 // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this
2072 // will be a nop.
2073 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP))
2074 .addImm(static_cast<unsigned>(GCNSubtarget::TrapID::LLVMAMDHSATrap));
2075 Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2076 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32),
2077 DoorbellReg)
2079 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2080 .addUse(AMDGPU::M0);
2081 Register DoorbellRegMasked =
2082 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2083 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2084 .addUse(DoorbellReg)
2085 .addImm(DoorbellIDMask)
2086 .setOperandDead(3); // implicit-def $scc
2087 Register SetWaveAbortBit =
2088 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2089 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2090 .addUse(DoorbellRegMasked)
2091 .addImm(ECQueueWaveAbort)
2092 .setOperandDead(3); // implicit-def $scc
2093 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2094 .addUse(SetWaveAbortBit);
2095 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG))
2097 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2098 .addUse(AMDGPU::TTMP2);
2099 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB);
2100 TrapBB->addSuccessor(HaltLoopBB);
2101
2102 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5);
2103 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH))
2104 .addMBB(HaltLoopBB);
2105 MF->push_back(HaltLoopBB);
2106 HaltLoopBB->addSuccessor(HaltLoopBB);
2107
2108 return MBB.getNextNode();
2109}
2110
2112 switch (MI.getOpcode()) {
2113 default:
2114 if (MI.isMetaInstruction())
2115 return 0;
2116 return 1; // FIXME: Do wait states equal cycles?
2117
2118 case AMDGPU::S_NOP:
2119 return MI.getOperand(0).getImm() + 1;
2120 // SI_RETURN_TO_EPILOG is a fallthrough to code outside of the function. The
2121 // hazard, even if one exist, won't really be visible. Should we handle it?
2122 }
2123}
2124
2126 MachineBasicBlock &MBB = *MI.getParent();
2127 DebugLoc DL = MBB.findDebugLoc(MI);
2129
2130 switch (MI.getOpcode()) {
2131 default: return TargetInstrInfo::expandPostRAPseudo(MI);
2132 case AMDGPU::S_MOV_B64_term:
2133 // This is only a terminator to get the correct spill code placement during
2134 // register allocation.
2135 MI.setDesc(get(AMDGPU::S_MOV_B64));
2136 break;
2137
2138 case AMDGPU::S_MOV_B32_term:
2139 // This is only a terminator to get the correct spill code placement during
2140 // register allocation.
2141 MI.setDesc(get(AMDGPU::S_MOV_B32));
2142 break;
2143
2144 case AMDGPU::S_XOR_B64_term:
2145 // This is only a terminator to get the correct spill code placement during
2146 // register allocation.
2147 MI.setDesc(get(AMDGPU::S_XOR_B64));
2148 break;
2149
2150 case AMDGPU::S_XOR_B32_term:
2151 // This is only a terminator to get the correct spill code placement during
2152 // register allocation.
2153 MI.setDesc(get(AMDGPU::S_XOR_B32));
2154 break;
2155 case AMDGPU::S_OR_B64_term:
2156 // This is only a terminator to get the correct spill code placement during
2157 // register allocation.
2158 MI.setDesc(get(AMDGPU::S_OR_B64));
2159 break;
2160 case AMDGPU::S_OR_B32_term:
2161 // This is only a terminator to get the correct spill code placement during
2162 // register allocation.
2163 MI.setDesc(get(AMDGPU::S_OR_B32));
2164 break;
2165
2166 case AMDGPU::S_ANDN2_B64_term:
2167 // This is only a terminator to get the correct spill code placement during
2168 // register allocation.
2169 MI.setDesc(get(AMDGPU::S_ANDN2_B64));
2170 break;
2171
2172 case AMDGPU::S_ANDN2_B32_term:
2173 // This is only a terminator to get the correct spill code placement during
2174 // register allocation.
2175 MI.setDesc(get(AMDGPU::S_ANDN2_B32));
2176 break;
2177
2178 case AMDGPU::S_AND_B64_term:
2179 // This is only a terminator to get the correct spill code placement during
2180 // register allocation.
2181 MI.setDesc(get(AMDGPU::S_AND_B64));
2182 break;
2183
2184 case AMDGPU::S_AND_B32_term:
2185 // This is only a terminator to get the correct spill code placement during
2186 // register allocation.
2187 MI.setDesc(get(AMDGPU::S_AND_B32));
2188 break;
2189
2190 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2191 // This is only a terminator to get the correct spill code placement during
2192 // register allocation.
2193 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B64));
2194 break;
2195
2196 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2197 // This is only a terminator to get the correct spill code placement during
2198 // register allocation.
2199 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B32));
2200 break;
2201
2202 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2203 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2204 break;
2205 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2206 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2207 break;
2208
2209 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2210 MI.setDesc(get(AMDGPU::V_WRITELANE_B32));
2211 break;
2212
2213 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2214 MI.setDesc(get(AMDGPU::V_READLANE_B32));
2215 break;
2216 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2217 Register Dst = MI.getOperand(0).getReg();
2218 bool IsAGPR = SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst));
2219 MI.setDesc(
2220 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2221 break;
2222 }
2223 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2224 Register Dst = MI.getOperand(0).getReg();
2225 if (SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst))) {
2226 int64_t Imm = MI.getOperand(1).getImm();
2227
2228 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2229 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2230 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstLo)
2232 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstHi)
2233 .addImm(SignExtend64<32>(Imm >> 32));
2234 MI.eraseFromParent();
2235 break;
2236 }
2237
2238 [[fallthrough]];
2239 }
2240 case AMDGPU::V_MOV_B64_PSEUDO: {
2241 Register Dst = MI.getOperand(0).getReg();
2242 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2243 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2244
2245 const MCInstrDesc &Mov64Desc = get(AMDGPU::V_MOV_B64_e32);
2246 const TargetRegisterClass *Mov64RC = getRegClass(Mov64Desc, /*OpNum=*/0);
2247
2248 const MachineOperand &SrcOp = MI.getOperand(1);
2249 // FIXME: Will this work for 64-bit floating point immediates?
2250 assert(!SrcOp.isFPImm());
2251 if (ST.hasVMovB64Inst() && Mov64RC->contains(Dst)) {
2252 MI.setDesc(Mov64Desc);
2253 if (SrcOp.isReg() || isInlineConstant(MI, 1) ||
2254 (SrcOp.isImm() &&
2255 (isUInt<32>(SrcOp.getImm()) || ST.has64BitLiterals())) ||
2256 (SrcOp.isGlobal() && ST.has64BitLiterals()))
2257 break;
2258 }
2259 if (SrcOp.isGlobal()) {
2260 // The address is unknown until link time, so the PK_MOV inline-constant
2261 // shortcut cannot apply.
2262 const GlobalValue *GV = SrcOp.getGlobal();
2263 int64_t Offset = SrcOp.getOffset();
2264 unsigned BaseFlags, LoReloc, HiReloc;
2265 std::tie(BaseFlags, LoReloc, HiReloc) =
2267
2268 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2269 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2270 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2271 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2272 } else if (SrcOp.isImm()) {
2273 APInt Imm(64, SrcOp.getImm());
2274 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2275 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2276 const MCInstrDesc &PkMovDesc = get(AMDGPU::V_PK_MOV_B32);
2277 const TargetRegisterClass *PkMovRC = getRegClass(PkMovDesc, /*OpNum=*/0);
2278
2279 if (ST.hasPkMovB32() && Lo == Hi && isInlineConstant(Lo) &&
2280 PkMovRC->contains(Dst)) {
2281 BuildMI(MBB, MI, DL, PkMovDesc, Dst)
2283 .addImm(Lo.getSExtValue())
2285 .addImm(Lo.getSExtValue())
2286 .addImm(0) // op_sel_lo
2287 .addImm(0) // op_sel_hi
2288 .addImm(0) // neg_lo
2289 .addImm(0) // neg_hi
2290 .addImm(0); // clamp
2291 } else {
2292 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2293 .addImm(Lo.getSExtValue());
2294 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2295 .addImm(Hi.getSExtValue());
2296 }
2297 } else {
2298 assert(SrcOp.isReg());
2299 if (ST.hasPkMovB32() &&
2300 !RI.isAGPR(MBB.getParent()->getRegInfo(), SrcOp.getReg())) {
2301 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), Dst)
2302 .addImm(SISrcMods::OP_SEL_1) // src0_mod
2303 .addReg(SrcOp.getReg())
2305 .addReg(SrcOp.getReg())
2306 .addImm(0) // op_sel_lo
2307 .addImm(0) // op_sel_hi
2308 .addImm(0) // neg_lo
2309 .addImm(0) // neg_hi
2310 .addImm(0); // clamp
2311 } else {
2312 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2313 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0));
2314 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2315 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1));
2316 }
2317 }
2318 MI.eraseFromParent();
2319 break;
2320 }
2321 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2323 break;
2324 }
2325 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2326 const MachineOperand &SrcOp = MI.getOperand(1);
2327 assert(!SrcOp.isFPImm());
2328
2329 if (ST.has64BitLiterals()) {
2330 MI.setDesc(get(AMDGPU::S_MOV_B64));
2331 break;
2332 }
2333
2334 if (SrcOp.isGlobal()) {
2335 Register Dst = MI.getOperand(0).getReg();
2336 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2337 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2338 const GlobalValue *GV = SrcOp.getGlobal();
2339 int64_t Offset = SrcOp.getOffset();
2340 unsigned BaseFlags, LoReloc, HiReloc;
2341 std::tie(BaseFlags, LoReloc, HiReloc) =
2343
2344 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2345 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2346 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2347 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2348 MI.eraseFromParent();
2349 break;
2350 }
2351
2352 // SrcOp is immediate
2353 APInt Imm(64, SrcOp.getImm());
2354 if (Imm.isIntN(32) || isInlineConstant(Imm)) {
2355 MI.setDesc(get(AMDGPU::S_MOV_B64));
2356 break;
2357 }
2358
2359 Register Dst = MI.getOperand(0).getReg();
2360 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2361 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2362
2363 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2364 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2365 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2366 .addImm(Lo.getSExtValue());
2367 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2368 .addImm(Hi.getSExtValue());
2369 MI.eraseFromParent();
2370 break;
2371 }
2372 case AMDGPU::V_SET_INACTIVE_B32: {
2373 // Lower V_SET_INACTIVE_B32 to V_CNDMASK_B32.
2374 Register DstReg = MI.getOperand(0).getReg();
2375 BuildMI(MBB, MI, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2376 .add(MI.getOperand(3))
2377 .add(MI.getOperand(4))
2378 .add(MI.getOperand(1))
2379 .add(MI.getOperand(2))
2380 .add(MI.getOperand(5));
2381 MI.eraseFromParent();
2382 break;
2383 }
2384 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2385 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2386 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2387 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2388 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2389 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2390 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2391 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2392 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2393 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2394 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2395 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2396 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2397 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2398 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2399 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2400 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2401 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2402 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2403 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2404 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2405 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2406 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2407 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2408 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2409 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2410 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2411 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2412 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2413 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2414 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2415 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2416 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2417 const TargetRegisterClass *EltRC = getOpRegClass(MI, 2);
2418
2419 unsigned Opc;
2420 if (RI.hasVGPRs(EltRC)) {
2421 Opc = AMDGPU::V_MOVRELD_B32_e32;
2422 } else {
2423 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2424 : AMDGPU::S_MOVRELD_B32;
2425 }
2426
2427 const MCInstrDesc &OpDesc = get(Opc);
2428 Register VecReg = MI.getOperand(0).getReg();
2429 bool IsUndef = MI.getOperand(1).isUndef();
2430 unsigned SubReg = MI.getOperand(3).getImm();
2431 assert(VecReg == MI.getOperand(1).getReg());
2432
2434 BuildMI(MBB, MI, DL, OpDesc)
2435 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2436 .add(MI.getOperand(2))
2438 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2439
2440 const int ImpDefIdx =
2441 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2442 const int ImpUseIdx = ImpDefIdx + 1;
2443 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2444 MI.eraseFromParent();
2445 break;
2446 }
2447 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2448 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2449 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2450 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2451 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2452 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2453 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2454 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2455 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2456 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2457 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2458 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2459 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2460 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2461 assert(ST.useVGPRIndexMode());
2462 Register VecReg = MI.getOperand(0).getReg();
2463 bool IsUndef = MI.getOperand(1).isUndef();
2464 MachineOperand &Idx = MI.getOperand(3);
2465 Register SubReg = MI.getOperand(4).getImm();
2466
2467 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2468 .add(Idx)
2470 SetOn->getOperand(3).setIsUndef();
2471
2472 const MCInstrDesc &OpDesc = get(AMDGPU::V_MOV_B32_indirect_write);
2474 BuildMI(MBB, MI, DL, OpDesc)
2475 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2476 .add(MI.getOperand(2))
2478 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2479
2480 const int ImpDefIdx =
2481 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2482 const int ImpUseIdx = ImpDefIdx + 1;
2483 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2484
2485 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2486
2487 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2488
2489 MI.eraseFromParent();
2490 break;
2491 }
2492 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2493 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2494 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2495 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2496 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2497 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2498 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2499 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2500 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2501 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2502 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2503 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2504 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2505 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2506 assert(ST.useVGPRIndexMode());
2507 Register Dst = MI.getOperand(0).getReg();
2508 Register VecReg = MI.getOperand(1).getReg();
2509 bool IsUndef = MI.getOperand(1).isUndef();
2510 Register SubReg = MI.getOperand(3).getImm();
2511
2512 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2513 .add(MI.getOperand(2))
2515 SetOn->getOperand(3).setIsUndef();
2516
2517 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_indirect_read))
2518 .addDef(Dst)
2519 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2520 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2521
2522 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2523
2524 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2525
2526 MI.eraseFromParent();
2527 break;
2528 }
2529 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2530 MachineFunction &MF = *MBB.getParent();
2531 Register Reg = MI.getOperand(0).getReg();
2532 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2533 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2534 MachineOperand OpLo = MI.getOperand(1);
2535 MachineOperand OpHi = MI.getOperand(2);
2536
2537 // Create a bundle so these instructions won't be re-ordered by the
2538 // post-RA scheduler.
2539 MIBundleBuilder Bundler(MBB, MI);
2540 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2541
2542 // What we want here is an offset from the value returned by s_getpc (which
2543 // is the address of the s_add_u32 instruction) to the global variable, but
2544 // since the encoding of $symbol starts 4 bytes after the start of the
2545 // s_add_u32 instruction, we end up with an offset that is 4 bytes too
2546 // small. This requires us to add 4 to the global variable offset in order
2547 // to compute the correct address. Similarly for the s_addc_u32 instruction,
2548 // the encoding of $symbol starts 12 bytes after the start of the s_add_u32
2549 // instruction.
2550
2551 int64_t Adjust = 0;
2552 if (ST.hasGetPCZeroExtension()) {
2553 // Fix up hardware that does not sign-extend the 48-bit PC value by
2554 // inserting: s_sext_i32_i16 reghi, reghi
2555 Bundler.append(
2556 BuildMI(MF, DL, get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2557 Adjust += 4;
2558 }
2559
2560 if (OpLo.isGlobal())
2561 OpLo.setOffset(OpLo.getOffset() + Adjust + 4);
2562 Bundler.append(
2563 BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2564
2565 if (OpHi.isGlobal())
2566 OpHi.setOffset(OpHi.getOffset() + Adjust + 12);
2567 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi)
2568 .addReg(RegHi)
2569 .add(OpHi));
2570
2571 finalizeBundle(MBB, Bundler.begin());
2572
2573 MI.eraseFromParent();
2574 break;
2575 }
2576 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2577 MachineFunction &MF = *MBB.getParent();
2578 Register Reg = MI.getOperand(0).getReg();
2579 MachineOperand Op = MI.getOperand(1);
2580
2581 // Create a bundle so these instructions won't be re-ordered by the
2582 // post-RA scheduler.
2583 MIBundleBuilder Bundler(MBB, MI);
2584 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2585 if (Op.isGlobal())
2586 Op.setOffset(Op.getOffset() + 4);
2587 Bundler.append(
2588 BuildMI(MF, DL, get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(Op));
2589
2590 finalizeBundle(MBB, Bundler.begin());
2591
2592 MI.eraseFromParent();
2593 break;
2594 }
2595 case AMDGPU::ENTER_STRICT_WWM: {
2596 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2597 // Whole Wave Mode is entered.
2598 MI.setDesc(get(LMC.OrSaveExecOpc));
2599 break;
2600 }
2601 case AMDGPU::ENTER_STRICT_WQM: {
2602 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2603 // STRICT_WQM is entered.
2604 BuildMI(MBB, MI, DL, get(LMC.MovOpc), MI.getOperand(0).getReg())
2605 .addReg(LMC.ExecReg);
2606 BuildMI(MBB, MI, DL, get(LMC.WQMOpc), LMC.ExecReg).addReg(LMC.ExecReg);
2607
2608 MI.eraseFromParent();
2609 break;
2610 }
2611 case AMDGPU::EXIT_STRICT_WWM:
2612 case AMDGPU::EXIT_STRICT_WQM: {
2613 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2614 // WWM/STICT_WQM is exited.
2615 MI.setDesc(get(LMC.MovOpc));
2616 break;
2617 }
2618 case AMDGPU::SI_RETURN: {
2619 const MachineFunction *MF = MBB.getParent();
2620 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2621 const SIRegisterInfo *TRI = ST.getRegisterInfo();
2622 // Hiding the return address use with SI_RETURN may lead to extra kills in
2623 // the function and missing live-ins. We are fine in practice because callee
2624 // saved register handling ensures the register value is restored before
2625 // RET, but we need the undef flag here to appease the MachineVerifier
2626 // liveness checks.
2628 BuildMI(MBB, MI, DL, get(AMDGPU::S_SETPC_B64_return))
2629 .addReg(TRI->getReturnAddressReg(*MF), RegState::Undef);
2630
2631 MIB.copyImplicitOps(MI);
2632 MI.eraseFromParent();
2633 break;
2634 }
2635
2636 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2637 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2638 MI.setDesc(get(AMDGPU::S_MUL_U64));
2639 break;
2640
2641 case AMDGPU::S_GETPC_B64_pseudo:
2642 MI.setDesc(get(AMDGPU::S_GETPC_B64));
2643 if (ST.hasGetPCZeroExtension()) {
2644 Register Dst = MI.getOperand(0).getReg();
2645 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2646 // Fix up hardware that does not sign-extend the 48-bit PC value by
2647 // inserting: s_sext_i32_i16 dsthi, dsthi
2648 BuildMI(MBB, std::next(MI.getIterator()), DL, get(AMDGPU::S_SEXT_I32_I16),
2649 DstHi)
2650 .addReg(DstHi);
2651 }
2652 break;
2653
2654 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2655 assert(ST.hasBF16PackedInsts());
2656 MI.setDesc(get(AMDGPU::V_PK_MAX_NUM_BF16));
2657 MI.addOperand(MachineOperand::CreateImm(0)); // op_sel
2658 MI.addOperand(MachineOperand::CreateImm(0)); // neg_lo
2659 MI.addOperand(MachineOperand::CreateImm(0)); // neg_hi
2660 auto Op0 = getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
2661 Op0->setImm(Op0->getImm() | SISrcMods::OP_SEL_1);
2662 auto Op1 = getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
2663 Op1->setImm(Op1->getImm() | SISrcMods::OP_SEL_1);
2664 break;
2665 }
2666
2667 case AMDGPU::GET_STACK_BASE:
2668 // The stack starts at offset 0 unless we need to reserve some space at the
2669 // bottom.
2670 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*MBB.getParent())) {
2671 // When CWSR is used in dynamic VGPR mode, the trap handler needs to save
2672 // some of the VGPRs. The size of the required scratch space has already
2673 // been computed by prolog epilog insertion.
2674 const SIMachineFunctionInfo *MFI =
2675 MBB.getParent()->getInfo<SIMachineFunctionInfo>();
2676 unsigned VGPRSize = MFI->getScratchReservedForDynamicVGPRs();
2677 Register DestReg = MI.getOperand(0).getReg();
2678 BuildMI(MBB, MI, DL, get(AMDGPU::S_GETREG_B32), DestReg)
2681 // The MicroEngine ID is 0 for the graphics queue, and 1 or 2 for compute
2682 // (3 is unused, so we ignore it). Unfortunately, S_GETREG doesn't set
2683 // SCC, so we need to check for 0 manually.
2684 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)).addImm(0).addReg(DestReg);
2685 // Change the implicif-def of SCC to an explicit use (but first remove
2686 // the dead flag if present).
2687 MI.getOperand(MI.getNumExplicitOperands()).setIsDead(false);
2688 MI.getOperand(MI.getNumExplicitOperands()).setIsUse();
2689 MI.setDesc(get(AMDGPU::S_CMOVK_I32));
2690 MI.addOperand(MachineOperand::CreateImm(VGPRSize));
2691 } else {
2692 MI.setDesc(get(AMDGPU::S_MOV_B32));
2693 MI.addOperand(MachineOperand::CreateImm(0));
2694 MI.removeOperand(
2695 MI.getNumExplicitOperands()); // Drop implicit def of SCC.
2696 }
2697 break;
2698 }
2699
2700 return true;
2701}
2702
2705 unsigned SubIdx, const MachineInstr &Orig,
2706 LaneBitmask UsedLanes) const {
2707
2708 // Try shrinking the instruction to remat only the part needed for current
2709 // context.
2710 // TODO: Handle more cases.
2711 unsigned Opcode = Orig.getOpcode();
2712 switch (Opcode) {
2713 case AMDGPU::S_MOV_B64:
2714 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2715 if (SubIdx != 0)
2716 break;
2717
2718 if (!Orig.getOperand(1).isImm())
2719 break;
2720
2721 // Shrink S_MOV_B64 to S_MOV_B32 when UsedLanes indicates only a single
2722 // 32-bit lane of the 64-bit value is live at the rematerialization point.
2723 if (UsedLanes.all())
2724 break;
2725
2726 // Determine which half of the 64-bit immediate corresponds to the use.
2727 unsigned OrigSubReg = Orig.getOperand(0).getSubReg();
2728 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2729 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2730
2731 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2732 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2733
2734 if (NeedLo && NeedHi)
2735 break;
2736
2737 int64_t Imm64 = Orig.getOperand(1).getImm();
2738 int32_t Imm32 = NeedLo ? Lo_32(Imm64) : Hi_32(Imm64);
2739
2740 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2741
2742 // Emit S_MOV_B32 defining just the needed 32-bit subreg of DestReg.
2743 BuildMI(MBB, I, Orig.getDebugLoc(), get(AMDGPU::S_MOV_B32))
2744 .addReg(DestReg, RegState::Define | RegState::Undef, UseSubReg)
2745 .addImm(Imm32);
2746 return;
2747 }
2748
2749 case AMDGPU::S_LOAD_DWORDX16_IMM:
2750 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2751 if (SubIdx != 0 || UsedLanes.all())
2752 break;
2753
2754 if (I == MBB.end())
2755 break;
2756
2757 if (I->isBundled())
2758 break;
2759
2760 MachineFunction *MF = MBB.getParent();
2762 assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");
2763
2764 // Look for a single use of the register at the insertion point that is also
2765 // a subreg.
2766 Register RegToFind = Orig.getOperand(0).getReg();
2767 MachineOperand *UseMO = MRI.getOneNonDBGUse(RegToFind);
2768 if (!UseMO ||
2769 UseMO != I->findRegisterUseOperand(RegToFind, /*TRI=*/nullptr) ||
2770 UseMO->getSubReg() == AMDGPU::NoSubRegister)
2771 break;
2772
2773 unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
2774 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());
2775
2776 unsigned NewOpcode = -1;
2777 if (SubregSize == 256)
2778 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2779 else if (SubregSize == 128)
2780 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2781 else
2782 break;
2783
2784 const MCInstrDesc &TID = get(NewOpcode);
2785 const TargetRegisterClass *NewRC =
2786 RI.getAllocatableClass(getRegClass(TID, 0));
2787 MRI.setRegClass(DestReg, NewRC);
2788
2789 UseMO->setReg(DestReg);
2790 UseMO->setSubReg(AMDGPU::NoSubRegister);
2791
2792 // Use a smaller load with the desired size, possibly with updated offset.
2793 MachineInstr *MI = MF->CloneMachineInstr(&Orig);
2794 MI->setDesc(TID);
2795 MI->getOperand(0).setReg(DestReg);
2796 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2797 if (Offset) {
2798 MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
2799 int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
2800 OffsetMO->setImm(FinalOffset);
2801 }
2803 for (const MachineMemOperand *MemOp : Orig.memoperands())
2804 NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
2805 SubregSize / 8));
2806 MI->setMemRefs(*MF, NewMMOs);
2807
2808 MBB.insert(I, MI);
2809 return;
2810 }
2811
2812 default:
2813 break;
2814 }
2815
2816 TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
2817}
2818
2819std::pair<MachineInstr*, MachineInstr*>
2821 assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2822
2823 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2825 ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
2826 MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
2827 return std::pair(&MI, nullptr);
2828 }
2829
2830 MachineBasicBlock &MBB = *MI.getParent();
2831 DebugLoc DL = MBB.findDebugLoc(MI);
2832 MachineFunction *MF = MBB.getParent();
2834 Register Dst = MI.getOperand(0).getReg();
2835 unsigned Part = 0;
2836 MachineInstr *Split[2];
2837
2838 for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2839 auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
2840 if (Dst.isPhysical()) {
2841 MovDPP.addDef(RI.getSubReg(Dst, Sub));
2842 } else {
2843 assert(MRI.isSSA());
2844 auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2845 MovDPP.addDef(Tmp);
2846 }
2847
2848 for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
2849 const MachineOperand &SrcOp = MI.getOperand(I);
2850 assert(!SrcOp.isFPImm());
2851 if (SrcOp.isImm()) {
2852 APInt Imm(64, SrcOp.getImm());
2853 Imm.ashrInPlace(Part * 32);
2854 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2855 } else {
2856 assert(SrcOp.isReg());
2857 Register Src = SrcOp.getReg();
2858 if (Src.isPhysical())
2859 MovDPP.addReg(RI.getSubReg(Src, Sub));
2860 else
2861 MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
2862 }
2863 }
2864
2865 for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
2866 MovDPP.addImm(MO.getImm());
2867
2868 Split[Part] = MovDPP;
2869 ++Part;
2870 }
2871
2872 if (Dst.isVirtual())
2873 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
2874 .addReg(Split[0]->getOperand(0).getReg())
2875 .addImm(AMDGPU::sub0)
2876 .addReg(Split[1]->getOperand(0).getReg())
2877 .addImm(AMDGPU::sub1);
2878
2879 MI.eraseFromParent();
2880 return std::pair(Split[0], Split[1]);
2881}
2882
2883std::optional<DestSourcePair>
2885 if (MI.getOpcode() == AMDGPU::WWM_COPY)
2886 return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
2887
2888 return std::nullopt;
2889}
2890
2892 AMDGPU::OpName Src0OpName,
2893 MachineOperand &Src1,
2894 AMDGPU::OpName Src1OpName) const {
2895 MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
2896 if (!Src0Mods)
2897 return false;
2898
2899 MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
2900 assert(Src1Mods &&
2901 "All commutable instructions have both src0 and src1 modifiers");
2902
2903 int Src0ModsVal = Src0Mods->getImm();
2904 int Src1ModsVal = Src1Mods->getImm();
2905
2906 Src1Mods->setImm(Src0ModsVal);
2907 Src0Mods->setImm(Src1ModsVal);
2908 return true;
2909}
2910
2912 MachineOperand &RegOp,
2913 MachineOperand &NonRegOp) {
2914 Register Reg = RegOp.getReg();
2915 unsigned SubReg = RegOp.getSubReg();
2916 bool IsKill = RegOp.isKill();
2917 bool IsDead = RegOp.isDead();
2918 bool IsUndef = RegOp.isUndef();
2919 bool IsDebug = RegOp.isDebug();
2920
2921 if (NonRegOp.isImm())
2922 RegOp.ChangeToImmediate(NonRegOp.getImm());
2923 else if (NonRegOp.isFI())
2924 RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
2925 else if (NonRegOp.isGlobal()) {
2926 RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
2927 NonRegOp.getTargetFlags());
2928 } else
2929 return nullptr;
2930
2931 // Make sure we don't reinterpret a subreg index in the target flags.
2932 RegOp.setTargetFlags(NonRegOp.getTargetFlags());
2933
2934 NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
2935 NonRegOp.setSubReg(SubReg);
2936
2937 return &MI;
2938}
2939
2941 MachineOperand &NonRegOp1,
2942 MachineOperand &NonRegOp2) {
2943 unsigned TargetFlags = NonRegOp1.getTargetFlags();
2944 int64_t NonRegVal = NonRegOp1.getImm();
2945
2946 NonRegOp1.setImm(NonRegOp2.getImm());
2947 NonRegOp2.setImm(NonRegVal);
2948 NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
2949 NonRegOp2.setTargetFlags(TargetFlags);
2950 return &MI;
2951}
2952
2953// GFX950 v_pk_{add,mul}_f32 must not have opsel[1:0] == 2'b10, i.e. OP_SEL_0 on
2954// src1 but not on src0, and v_pk_fma_f32 must not have OP_SEL_0 on src1 or
2955// src2.
2957 bool CheckSwappedSrc = false) {
2958 unsigned Opc = MI.getOpcode();
2959 if (!TII.getSubtarget().hasPkF32InvalidOpSel() ||
2960 (Opc != AMDGPU::V_PK_ADD_F32 && Opc != AMDGPU::V_PK_MUL_F32 &&
2961 Opc != AMDGPU::V_PK_FMA_F32))
2962 return true;
2963
2964 auto Mods = [&](AMDGPU::OpName Name) {
2965 const MachineOperand *Op = TII.getNamedOperand(MI, Name);
2966 return Op ? static_cast<unsigned>(Op->getImm()) : 0u;
2967 };
2968 unsigned Src0Mods = Mods(AMDGPU::OpName::src0_modifiers);
2969 unsigned Src1Mods = Mods(AMDGPU::OpName::src1_modifiers);
2970 unsigned Src2Mods = Mods(AMDGPU::OpName::src2_modifiers);
2971
2972 if (CheckSwappedSrc)
2973 std::swap(Src0Mods, Src1Mods);
2974
2975 if (Opc == AMDGPU::V_PK_FMA_F32)
2976 return !((Src1Mods | Src2Mods) & SISrcMods::OP_SEL_0);
2977 return (Src0Mods & SISrcMods::OP_SEL_0) || !(Src1Mods & SISrcMods::OP_SEL_0);
2978}
2979
2980bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
2981 unsigned OpIdx1) const {
2982 const MCInstrDesc &InstDesc = MI.getDesc();
2983 const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
2984 const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];
2985
2986 unsigned Opc = MI.getOpcode();
2987 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2988 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
2989
2990 // Swapping src0 and src1 swaps their modifiers; refuse a swap that would
2991 // leave an invalid GFX950 packed FP32 op_sel.
2992 bool IsSrc01Swap = ((int)OpIdx0 == Src0Idx && (int)OpIdx1 == Src1Idx) ||
2993 ((int)OpIdx0 == Src1Idx && (int)OpIdx1 == Src0Idx);
2994 if (IsSrc01Swap && !isLegalPkF32OpSel(*this, MI, true))
2995 return false;
2996
2997 const MachineOperand &MO0 = MI.getOperand(OpIdx0);
2998 const MachineOperand &MO1 = MI.getOperand(OpIdx1);
2999
3000 // Swap doesn't breach constant bus or literal limits, but it may move a
3001 // constant out of src0. Allow that for immediates where the destination
3002 // operand can hold them, e.g. VOP3 sources on targets with VOP3 literal
3003 // support. Other non-register operands stay in src0.
3004 if (isVALU(MI, /*AllowLDSDMA=*/false)) {
3005 if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
3006 (!MO0.isImm() || !isImmOperandLegal(MI, OpIdx1, MO0)))
3007 return false;
3008 if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
3009 (!MO1.isImm() || !isImmOperandLegal(MI, OpIdx0, MO1)))
3010 return false;
3011 }
3012
3013 if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
3014 if (OpInfo1.RegClass == -1)
3015 return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
3016 return isLegalRegOperand(MI, OpIdx1, MO0) &&
3017 (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
3018 }
3019 if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
3020 if (OpInfo0.RegClass == -1)
3021 return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
3022 return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
3023 isLegalRegOperand(MI, OpIdx0, MO1);
3024 }
3025
3026 // No need to check 64-bit literals since swapping does not bring new
3027 // 64-bit literals into current instruction to fold to 32-bit
3028
3029 return isImmOperandLegal(MI, OpIdx1, MO0);
3030}
3031
3033 if (!isDPP(MI))
3034 return false;
3035 const MachineOperand *DppCtrl = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
3036 return !DppCtrl || DppCtrl->getImm() != AMDGPU::DPP::QUAD_PERM_ID;
3037}
3038
3040 unsigned Src0Idx,
3041 unsigned Src1Idx) const {
3042 assert(!NewMI && "this should never be used");
3043
3045 return nullptr;
3046
3047 unsigned Opc = MI.getOpcode();
3048 int CommutedOpcode = commuteOpcode(Opc);
3049 if (CommutedOpcode == -1)
3050 return nullptr;
3051
3052 if (Src0Idx > Src1Idx)
3053 std::swap(Src0Idx, Src1Idx);
3054
3055 assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
3056 static_cast<int>(Src0Idx) &&
3057 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
3058 static_cast<int>(Src1Idx) &&
3059 "inconsistency with findCommutedOpIndices");
3060
3061 if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
3062 return nullptr;
3063
3064 MachineInstr *CommutedMI = nullptr;
3065 MachineOperand &Src0 = MI.getOperand(Src0Idx);
3066 MachineOperand &Src1 = MI.getOperand(Src1Idx);
3067 if (Src0.isReg() && Src1.isReg()) {
3068 // Be sure to copy the source modifiers to the right place.
3069 CommutedMI =
3070 TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
3071 } else if (Src0.isReg() && !Src1.isReg()) {
3072 CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
3073 } else if (!Src0.isReg() && Src1.isReg()) {
3074 CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
3075 } else if (Src0.isImm() && Src1.isImm()) {
3076 CommutedMI = swapImmOperands(MI, Src0, Src1);
3077 } else {
3078 // FIXME: Found two non registers to commute. This does happen.
3079 return nullptr;
3080 }
3081
3082 if (CommutedMI) {
3083 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
3084 Src1, AMDGPU::OpName::src1_modifiers);
3085
3086 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
3087 AMDGPU::OpName::src1_sel);
3088
3089 CommutedMI->setDesc(get(CommutedOpcode));
3090 }
3091
3092 return CommutedMI;
3093}
3094
3095// This needs to be implemented because the source modifiers may be inserted
3096// between the true commutable operands, and the base
3097// TargetInstrInfo::commuteInstruction uses it.
3099 unsigned &SrcOpIdx0,
3100 unsigned &SrcOpIdx1) const {
3102 return false;
3103
3104 return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
3105}
3106
3108 unsigned &SrcOpIdx0,
3109 unsigned &SrcOpIdx1) const {
3110 if (!Desc.isCommutable())
3111 return false;
3112
3113 unsigned Opc = Desc.getOpcode();
3114 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
3115 if (Src0Idx == -1)
3116 return false;
3117
3118 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
3119 if (Src1Idx == -1)
3120 return false;
3121
3122 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3123}
3124
3126 int64_t BrOffset) const {
3127 // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
3128 // because its dest block is unanalyzable.
3129 assert(isSOPP(BranchOp) || isSOPK(BranchOp));
3130
3131 // Convert to dwords.
3132 BrOffset /= 4;
3133
3134 // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
3135 // from the next instruction.
3136 BrOffset -= 1;
3137
3138 return isIntN(BranchOffsetBits, BrOffset);
3139}
3140
3143 return MI.getOperand(0).getMBB();
3144}
3145
3147 for (const MachineInstr &MI : MBB->terminators()) {
3148 if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
3149 MI.getOpcode() == AMDGPU::SI_LOOP ||
3150 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3151 return true;
3152 }
3153 return false;
3154}
3155
3157 MachineBasicBlock &DestBB,
3158 MachineBasicBlock &RestoreBB,
3159 const DebugLoc &DL, int64_t BrOffset,
3160 RegScavenger *RS) const {
3161 assert(MBB.empty() &&
3162 "new block should be inserted for expanding unconditional branch");
3163 assert(MBB.pred_size() == 1);
3164 assert(RestoreBB.empty() &&
3165 "restore block should be inserted for restoring clobbered registers");
3166
3167 MachineFunction *MF = MBB.getParent();
3170 auto I = MBB.end();
3171 auto &MCCtx = MF->getContext();
3172
3173 if (ST.useAddPCI64Inst()) {
3174 MCSymbol *Offset =
3175 MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
3176 auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
3178 MCSymbol *PostAddPCLabel =
3179 MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
3180 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3181 auto *OffsetExpr = MCBinaryExpr::createSub(
3182 MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
3183 MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
3184 Offset->setVariableValue(OffsetExpr);
3185 return;
3186 }
3187
3188 assert(RS && "RegScavenger required for long branching");
3189
3190 // FIXME: Virtual register workaround for RegScavenger not working with empty
3191 // blocks.
3192 Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3193
3194 // Note: as this is used after hazard recognizer we need to apply some hazard
3195 // workarounds directly.
3196 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3197 ST.hasVALUReadSGPRHazard();
3198 auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
3199 if (FlushSGPRWrites)
3200 BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
3202 };
3203
3204 // We need to compute the offset relative to the instruction immediately after
3205 // s_getpc_b64. Insert pc arithmetic code before last terminator.
3206 MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
3207 ApplyHazardWorkarounds();
3208
3209 MCSymbol *PostGetPCLabel =
3210 MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
3211 GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);
3212
3213 MCSymbol *OffsetLo =
3214 MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
3215 MCSymbol *OffsetHi =
3216 MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
3217 BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
3218 .addReg(PCReg, RegState::Define, AMDGPU::sub0)
3219 .addReg(PCReg, {}, AMDGPU::sub0)
3220 .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
3221 BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
3222 .addReg(PCReg, RegState::Define, AMDGPU::sub1)
3223 .addReg(PCReg, {}, AMDGPU::sub1)
3224 .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
3225 ApplyHazardWorkarounds();
3226
3227 // Insert the indirect branch after the other terminator.
3228 BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
3229 .addReg(PCReg);
3230
3231 // If a spill is needed for the pc register pair, we need to insert a spill
3232 // restore block right before the destination block, and insert a short branch
3233 // into the old destination block's fallthrough predecessor.
3234 // e.g.:
3235 //
3236 // s_cbranch_scc0 skip_long_branch:
3237 //
3238 // long_branch_bb:
3239 // spill s[8:9]
3240 // s_getpc_b64 s[8:9]
3241 // s_add_u32 s8, s8, restore_bb
3242 // s_addc_u32 s9, s9, 0
3243 // s_setpc_b64 s[8:9]
3244 //
3245 // skip_long_branch:
3246 // foo;
3247 //
3248 // .....
3249 //
3250 // dest_bb_fallthrough_predecessor:
3251 // bar;
3252 // s_branch dest_bb
3253 //
3254 // restore_bb:
3255 // restore s[8:9]
3256 // fallthrough dest_bb
3257 ///
3258 // dest_bb:
3259 // buzz;
3260
3261 Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
3262 Register Scav;
3263
3264 // If we've previously reserved a register for long branches
3265 // avoid running the scavenger and just use those registers
3266 if (LongBranchReservedReg) {
3267 RS->enterBasicBlock(MBB);
3268 Scav = LongBranchReservedReg;
3269 } else {
3270 RS->enterBasicBlockEnd(MBB);
3271 Scav = RS->scavengeRegisterBackwards(
3272 AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
3273 /* RestoreAfter */ false, 0, /* AllowSpill */ false);
3274 }
3275 if (Scav) {
3276 RS->setRegUsed(Scav);
3277 MRI.replaceRegWith(PCReg, Scav);
3278 MRI.clearVirtRegs();
3279 } else {
3280 // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
3281 // SGPR spill.
3282 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
3283 const SIRegisterInfo *TRI = ST.getRegisterInfo();
3284 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3285 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3286 MRI.clearVirtRegs();
3287 }
3288
3289 MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
3290 // Now, the distance could be defined.
3292 MCSymbolRefExpr::create(DestLabel, MCCtx),
3293 MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
3294 // Add offset assignments.
3295 auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
3296 OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
3297 auto *ShAmt = MCConstantExpr::create(32, MCCtx);
3298 OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
3299}
3300
3301unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
3302 switch (Cond) {
3303 case SIInstrInfo::SCC_TRUE:
3304 return AMDGPU::S_CBRANCH_SCC1;
3305 case SIInstrInfo::SCC_FALSE:
3306 return AMDGPU::S_CBRANCH_SCC0;
3307 case SIInstrInfo::VCCNZ:
3308 return AMDGPU::S_CBRANCH_VCCNZ;
3309 case SIInstrInfo::VCCZ:
3310 return AMDGPU::S_CBRANCH_VCCZ;
3311 case SIInstrInfo::EXECNZ:
3312 return AMDGPU::S_CBRANCH_EXECNZ;
3313 case SIInstrInfo::EXECZ:
3314 return AMDGPU::S_CBRANCH_EXECZ;
3315 default:
3316 llvm_unreachable("invalid branch predicate");
3317 }
3318}
3319
3320SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
3321 switch (Opcode) {
3322 case AMDGPU::S_CBRANCH_SCC0:
3323 return SCC_FALSE;
3324 case AMDGPU::S_CBRANCH_SCC1:
3325 return SCC_TRUE;
3326 case AMDGPU::S_CBRANCH_VCCNZ:
3327 return VCCNZ;
3328 case AMDGPU::S_CBRANCH_VCCZ:
3329 return VCCZ;
3330 case AMDGPU::S_CBRANCH_EXECNZ:
3331 return EXECNZ;
3332 case AMDGPU::S_CBRANCH_EXECZ:
3333 return EXECZ;
3334 default:
3335 return INVALID_BR;
3336 }
3337}
3338
3342 MachineBasicBlock *&FBB,
3344 bool AllowModify) const {
3345 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3346 // Unconditional Branch
3347 TBB = I->getOperand(0).getMBB();
3348 return false;
3349 }
3350
3351 BranchPredicate Pred = getBranchPredicate(I->getOpcode());
3352 if (Pred == INVALID_BR)
3353 return true;
3354
3355 MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
3356 Cond.push_back(MachineOperand::CreateImm(Pred));
3357 Cond.push_back(I->getOperand(1)); // Save the branch register.
3358
3359 ++I;
3360
3361 if (I == MBB.end()) {
3362 // Conditional branch followed by fall-through.
3363 TBB = CondBB;
3364 return false;
3365 }
3366
3367 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3368 TBB = CondBB;
3369 FBB = I->getOperand(0).getMBB();
3370 return false;
3371 }
3372
3373 return true;
3374}
3375
3377 MachineBasicBlock *&FBB,
3379 bool AllowModify) const {
3380 MachineBasicBlock::iterator I = MBB.getFirstTerminator();
3381 auto E = MBB.end();
3382 if (I == E)
3383 return false;
3384
3385 // Skip over the instructions that are artificially terminators for special
3386 // exec management.
3387 while (I != E && !I->isBranch() && !I->isReturn()) {
3388 switch (I->getOpcode()) {
3389 case AMDGPU::S_MOV_B64_term:
3390 case AMDGPU::S_XOR_B64_term:
3391 case AMDGPU::S_OR_B64_term:
3392 case AMDGPU::S_ANDN2_B64_term:
3393 case AMDGPU::S_AND_B64_term:
3394 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3395 case AMDGPU::S_MOV_B32_term:
3396 case AMDGPU::S_XOR_B32_term:
3397 case AMDGPU::S_OR_B32_term:
3398 case AMDGPU::S_ANDN2_B32_term:
3399 case AMDGPU::S_AND_B32_term:
3400 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3401 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3402 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3403 break;
3404 case AMDGPU::SI_IF:
3405 case AMDGPU::SI_ELSE:
3406 case AMDGPU::SI_KILL_I1_TERMINATOR:
3407 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3408 // FIXME: It's messy that these need to be considered here at all.
3409 return true;
3410 default:
3411 llvm_unreachable("unexpected non-branch terminator inst");
3412 }
3413
3414 ++I;
3415 }
3416
3417 if (I == E)
3418 return false;
3419
3420 return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
3421}
3422
3424 int *BytesRemoved) const {
3425 unsigned Count = 0;
3426 unsigned RemovedSize = 0;
3427 for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
3428 // Skip over artificial terminators when removing instructions.
3429 if (MI.isBranch() || MI.isReturn()) {
3430 RemovedSize += getInstSizeInBytes(MI);
3431 MI.eraseFromParent();
3432 ++Count;
3433 }
3434 }
3435
3436 if (BytesRemoved)
3437 *BytesRemoved = RemovedSize;
3438
3439 return Count;
3440}
3441
3442// Copy the flags onto the implicit condition register operand.
3444 const MachineOperand &OrigCond) {
3445 CondReg.setIsUndef(OrigCond.isUndef());
3446 CondReg.setIsKill(OrigCond.isKill());
3447}
3448
3451 MachineBasicBlock *FBB,
3453 const DebugLoc &DL,
3454 int *BytesAdded) const {
3455 if (!FBB && Cond.empty()) {
3456 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3457 .addMBB(TBB);
3458 if (BytesAdded)
3459 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3460 return 1;
3461 }
3462
3463 assert(TBB && Cond[0].isImm());
3464
3465 unsigned Opcode
3466 = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));
3467
3468 if (!FBB) {
3469 MachineInstr *CondBr =
3470 BuildMI(&MBB, DL, get(Opcode))
3471 .addMBB(TBB);
3472
3473 // Copy the flags onto the implicit condition register operand.
3474 preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
3475 fixImplicitOperands(*CondBr);
3476
3477 if (BytesAdded)
3478 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3479 return 1;
3480 }
3481
3482 assert(TBB && FBB);
3483
3484 MachineInstr *CondBr =
3485 BuildMI(&MBB, DL, get(Opcode))
3486 .addMBB(TBB);
3487 fixImplicitOperands(*CondBr);
3488 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3489 .addMBB(FBB);
3490
3491 MachineOperand &CondReg = CondBr->getOperand(1);
3492 CondReg.setIsUndef(Cond[1].isUndef());
3493 CondReg.setIsKill(Cond[1].isKill());
3494
3495 if (BytesAdded)
3496 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3497
3498 return 2;
3499}
3500
3503 if (Cond.size() != 2) {
3504 return true;
3505 }
3506
3507 if (Cond[0].isImm()) {
3508 Cond[0].setImm(-Cond[0].getImm());
3509 return false;
3510 }
3511
3512 return true;
3513}
3514
3515namespace {
3516class AMDGPUPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
3517private:
3518 /// The compare instruction for loop control
3519 const MachineInstr *CmpInst = nullptr;
3520 /// The normalized condition used by createTripCountGreaterCondition()
3522
3523public:
3524 AMDGPUPipelinerLoopInfo(MachineInstr *CmpInst,
3526 : CmpInst(CmpInst), Cond(Cond.begin(), Cond.end()) {}
3527
3528 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
3529 return CmpInst && MI == CmpInst;
3530 }
3531
3532 std::optional<bool> createTripCountGreaterCondition(
3533 int TC, MachineBasicBlock &MBB,
3534 SmallVectorImpl<MachineOperand> &CondParam) override {
3535 CondParam = this->Cond;
3536 return {};
3537 }
3538
3539 void adjustTripCount(int TripCountAdjust) override {}
3540
3541 void setPreheader(MachineBasicBlock *NewPreheader) override {}
3542};
3543} // namespace
3544
3545std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3547 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
3549 // Unanalyzable terminator.
3550 if (analyzeBranch(*LoopBB, TBB, FBB, Cond, /*AllowModify=*/false))
3551 return nullptr;
3552
3553 // Infinite loops are not supported.
3554 if (TBB == LoopBB && FBB == LoopBB)
3555 return nullptr;
3556
3557 // Must be conditional branch.
3558 if (FBB == nullptr)
3559 return nullptr;
3560
3561 assert((TBB == LoopBB || FBB == LoopBB) &&
3562 "The Loop must be a single-basic-block loop");
3563
3564 // Divergent (VCC/EXEC) back-edge is not supported.
3565 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3566 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3567 return nullptr;
3568
3569 // Calls and inline assembly are not supported.
3570 for (const MachineInstr &MI : *LoopBB)
3571 if (MI.isCall() || MI.isInlineAsm())
3572 return nullptr;
3573
3574 // Normalization for createTripCountGreaterCondition(): make Cond mean
3575 // "exit the loop" so the expander emits correct prolog guard branches.
3576 if (TBB == LoopBB)
3578
3579 auto Instructions = make_range(
3581 LoopBB->rend());
3582 auto CmpI = llvm::find_if(Instructions, [&](const MachineInstr &MI) {
3583 return MI.modifiesRegister(Cond[1].getReg(), &RI);
3584 });
3585
3586 if (CmpI == Instructions.end() || CmpI->isPHI())
3587 return nullptr;
3588 MachineInstr *CmpInst = &*CmpI;
3589
3590 return std::make_unique<AMDGPUPipelinerLoopInfo>(CmpInst, Cond);
3591}
3592
3595 Register DstReg, Register TrueReg,
3596 Register FalseReg,
3597 SelectExpansion &Exp) const {
3598 switch (Cond[0].getImm()) {
3599 case VCCNZ:
3600 case VCCZ: {
3601 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3602 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3603 if (MRI.getRegClass(FalseReg) != RC)
3604 return false;
3605
3606 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3607 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts; // ???
3608
3609 // Limit to equal cost for branch vs. N v_cndmask_b32s.
3610 return RI.hasVGPRs(RC) && NumInsts <= 6;
3611 }
3612 case SCC_TRUE:
3613 case SCC_FALSE: {
3614 // FIXME: We could insert for VGPRs if we could replace the original compare
3615 // with a vector one.
3616 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3617 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3618 if (MRI.getRegClass(FalseReg) != RC)
3619 return false;
3620
3621 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3622
3623 // Multiples of 8 can do s_cselect_b64
3624 if (NumInsts % 2 == 0)
3625 NumInsts /= 2;
3626
3627 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts; // ???
3628 return RI.isSGPRClass(RC);
3629 }
3630 default:
3631 return false;
3632 }
3633}
3634
3638 Register TrueReg, Register FalseReg) const {
3639 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3640 if (Pred == VCCZ || Pred == SCC_FALSE) {
3641 Pred = static_cast<BranchPredicate>(-Pred);
3642 std::swap(TrueReg, FalseReg);
3643 }
3644
3645 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3646 const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
3647 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3648
3649 if (DstSize == 32) {
3651 if (Pred == SCC_TRUE) {
3652 Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
3653 .addReg(TrueReg)
3654 .addReg(FalseReg);
3655 } else {
3656 // Instruction's operands are backwards from what is expected.
3657 Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
3658 .addReg(FalseReg)
3659 .addReg(TrueReg);
3660 }
3661
3662 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3663 return;
3664 }
3665
3666 if (DstSize == 64 && Pred == SCC_TRUE) {
3668 BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
3669 .addReg(TrueReg)
3670 .addReg(FalseReg);
3671
3672 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3673 return;
3674 }
3675
3676 static const int16_t Sub0_15[] = {
3677 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3678 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3679 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3680 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3681 };
3682
3683 static const int16_t Sub0_15_64[] = {
3684 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3685 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3686 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3687 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3688 };
3689
3690 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3691 const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
3692 const int16_t *SubIndices = Sub0_15;
3693 int NElts = DstSize / 32;
3694
3695 // 64-bit select is only available for SALU.
3696 // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
3697 if (Pred == SCC_TRUE) {
3698 if (NElts % 2) {
3699 SelOp = AMDGPU::S_CSELECT_B32;
3700 EltRC = &AMDGPU::SGPR_32RegClass;
3701 } else {
3702 SelOp = AMDGPU::S_CSELECT_B64;
3703 EltRC = &AMDGPU::SGPR_64RegClass;
3704 SubIndices = Sub0_15_64;
3705 NElts /= 2;
3706 }
3707 }
3708
3710 MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);
3711
3712 I = MIB->getIterator();
3713
3715 for (int Idx = 0; Idx != NElts; ++Idx) {
3716 Register DstElt = MRI.createVirtualRegister(EltRC);
3717 Regs.push_back(DstElt);
3718
3719 unsigned SubIdx = SubIndices[Idx];
3720
3722 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3723 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3724 .addReg(FalseReg, {}, SubIdx)
3725 .addReg(TrueReg, {}, SubIdx);
3726 } else {
3727 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3728 .addReg(TrueReg, {}, SubIdx)
3729 .addReg(FalseReg, {}, SubIdx);
3730 }
3731
3732 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3734
3735 MIB.addReg(DstElt)
3736 .addImm(SubIdx);
3737 }
3738}
3739
3741
3742 if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
3743 return true;
3744
3745 switch (MI.getOpcode()) {
3746 case AMDGPU::S_ENDPGM:
3747 case AMDGPU::S_ENDPGM_SAVED:
3748 case AMDGPU::S_TRAP:
3749 case AMDGPU::S_GETREG_B32:
3750 case AMDGPU::S_SETREG_B32:
3751 case AMDGPU::S_SETREG_B32_mode:
3752 case AMDGPU::S_SETREG_IMM32_B32:
3753 case AMDGPU::S_SETREG_IMM32_B32_mode:
3754 case AMDGPU::S_SENDMSG:
3755 case AMDGPU::S_SENDMSGHALT:
3756 case AMDGPU::S_SENDMSG_RTN_B32:
3757 case AMDGPU::S_SENDMSG_RTN_B64:
3758 case AMDGPU::S_BARRIER_WAIT:
3759 case AMDGPU::S_BARRIER_SIGNAL_M0:
3760 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3761 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3762 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3763 return true;
3764 default:
3765 return false;
3766 }
3767}
3768
3770 switch (MI.getOpcode()) {
3771 case AMDGPU::V_MOV_B16_t16_e32:
3772 case AMDGPU::V_MOV_B16_t16_e64:
3773 case AMDGPU::V_MOV_B32_e32:
3774 case AMDGPU::V_MOV_B32_e64:
3775 case AMDGPU::V_MOV_B64_PSEUDO:
3776 case AMDGPU::V_MOV_B64_e32:
3777 case AMDGPU::V_MOV_B64_e64:
3778 case AMDGPU::S_MOV_B32:
3779 case AMDGPU::S_MOV_B64:
3780 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3781 case AMDGPU::COPY:
3782 case AMDGPU::WWM_COPY:
3783 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3784 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3785 case AMDGPU::V_ACCVGPR_MOV_B32:
3786 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3787 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3788 return true;
3789 default:
3790 return false;
3791 }
3792}
3793
3795 switch (MI.getOpcode()) {
3796 case AMDGPU::V_MOV_B16_t16_e32:
3797 case AMDGPU::V_MOV_B16_t16_e64:
3798 return 2;
3799 case AMDGPU::V_MOV_B32_e32:
3800 case AMDGPU::V_MOV_B32_e64:
3801 case AMDGPU::V_MOV_B64_PSEUDO:
3802 case AMDGPU::V_MOV_B64_e32:
3803 case AMDGPU::V_MOV_B64_e64:
3804 case AMDGPU::S_MOV_B32:
3805 case AMDGPU::S_MOV_B64:
3806 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3807 case AMDGPU::COPY:
3808 case AMDGPU::WWM_COPY:
3809 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3810 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3811 case AMDGPU::V_ACCVGPR_MOV_B32:
3812 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3813 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3814 return 1;
3815 default:
3816 llvm_unreachable("MI is not a foldable copy");
3817 }
3818}
3819
3820static constexpr AMDGPU::OpName ModifierOpNames[] = {
3821 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3822 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3823 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3824
3826 unsigned Opc = MI.getOpcode();
3827 for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
3828 int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
3829 if (Idx >= 0)
3830 MI.removeOperand(Idx);
3831 }
3832}
3833
3835 const MCInstrDesc &NewDesc) const {
3836 MI.setDesc(NewDesc);
3837
3838 // Remove any leftover implicit operands from mutating the instruction. e.g.
3839 // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
3840 // anymore.
3841 const MCInstrDesc &Desc = MI.getDesc();
3842 unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
3843 Desc.implicit_defs().size();
3844
3845 for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
3846 MI.removeOperand(I);
3847}
3848
3849std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
3850 unsigned SubRegIndex) {
3851 switch (SubRegIndex) {
3852 case AMDGPU::NoSubRegister:
3853 return Imm;
3854 case AMDGPU::sub0:
3855 return SignExtend64<32>(Imm);
3856 case AMDGPU::sub1:
3857 return SignExtend64<32>(Imm >> 32);
3858 case AMDGPU::lo16:
3859 return SignExtend64<16>(Imm);
3860 case AMDGPU::hi16:
3861 return SignExtend64<16>(Imm >> 16);
3862 case AMDGPU::sub1_lo16:
3863 return SignExtend64<16>(Imm >> 32);
3864 case AMDGPU::sub1_hi16:
3865 return SignExtend64<16>(Imm >> 48);
3866 default:
3867 return std::nullopt;
3868 }
3869
3870 llvm_unreachable("covered subregister switch");
3871}
3872
3873static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
3874 switch (Opc) {
3875 case AMDGPU::V_MAC_F16_e32:
3876 case AMDGPU::V_MAC_F16_e64:
3877 case AMDGPU::V_MAD_F16_e64:
3878 return AMDGPU::V_MADAK_F16;
3879 case AMDGPU::V_MAC_F32_e32:
3880 case AMDGPU::V_MAC_F32_e64:
3881 case AMDGPU::V_MAD_F32_e64:
3882 return AMDGPU::V_MADAK_F32;
3883 case AMDGPU::V_FMAC_F32_e32:
3884 case AMDGPU::V_FMAC_F32_e64:
3885 case AMDGPU::V_FMA_F32_e64:
3886 return AMDGPU::V_FMAAK_F32;
3887 case AMDGPU::V_FMAC_F16_e32:
3888 case AMDGPU::V_FMAC_F16_e64:
3889 case AMDGPU::V_FMAC_F16_t16_e64:
3890 case AMDGPU::V_FMAC_F16_fake16_e64:
3891 case AMDGPU::V_FMAC_F16_t16_e32:
3892 case AMDGPU::V_FMAC_F16_fake16_e32:
3893 case AMDGPU::V_FMA_F16_e64:
3894 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3895 ? AMDGPU::V_FMAAK_F16_t16
3896 : AMDGPU::V_FMAAK_F16_fake16
3897 : AMDGPU::V_FMAAK_F16;
3898 case AMDGPU::V_FMAC_F64_e32:
3899 case AMDGPU::V_FMAC_F64_e64:
3900 case AMDGPU::V_FMA_F64_e64:
3901 return AMDGPU::V_FMAAK_F64;
3902 default:
3903 llvm_unreachable("invalid instruction");
3904 }
3905}
3906
3907static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
3908 switch (Opc) {
3909 case AMDGPU::V_MAC_F16_e32:
3910 case AMDGPU::V_MAC_F16_e64:
3911 case AMDGPU::V_MAD_F16_e64:
3912 return AMDGPU::V_MADMK_F16;
3913 case AMDGPU::V_MAC_F32_e32:
3914 case AMDGPU::V_MAC_F32_e64:
3915 case AMDGPU::V_MAD_F32_e64:
3916 return AMDGPU::V_MADMK_F32;
3917 case AMDGPU::V_FMAC_F32_e32:
3918 case AMDGPU::V_FMAC_F32_e64:
3919 case AMDGPU::V_FMA_F32_e64:
3920 return AMDGPU::V_FMAMK_F32;
3921 case AMDGPU::V_FMAC_F16_e32:
3922 case AMDGPU::V_FMAC_F16_e64:
3923 case AMDGPU::V_FMAC_F16_t16_e64:
3924 case AMDGPU::V_FMAC_F16_fake16_e64:
3925 case AMDGPU::V_FMAC_F16_t16_e32:
3926 case AMDGPU::V_FMAC_F16_fake16_e32:
3927 case AMDGPU::V_FMA_F16_e64:
3928 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3929 ? AMDGPU::V_FMAMK_F16_t16
3930 : AMDGPU::V_FMAMK_F16_fake16
3931 : AMDGPU::V_FMAMK_F16;
3932 case AMDGPU::V_FMAC_F64_e32:
3933 case AMDGPU::V_FMAC_F64_e64:
3934 case AMDGPU::V_FMA_F64_e64:
3935 return AMDGPU::V_FMAMK_F64;
3936 default:
3937 llvm_unreachable("invalid instruction");
3938 }
3939}
3940
3942 Register Reg, MachineRegisterInfo *MRI) const {
3943 int64_t Imm;
3944 if (!getConstValDefinedInReg(DefMI, Reg, Imm))
3945 return false;
3946
3947 const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);
3948
3949 assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");
3950
3951 unsigned Opc = UseMI.getOpcode();
3952 if (Opc == AMDGPU::COPY) {
3953 assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");
3954
3955 Register DstReg = UseMI.getOperand(0).getReg();
3956 Register UseSubReg = UseMI.getOperand(1).getSubReg();
3957
3958 const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);
3959
3960 if (HasMultipleUses) {
3961 // TODO: This should fold in more cases with multiple use, but we need to
3962 // more carefully consider what those uses are.
3963 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));
3964
3965 // Avoid breaking up a 64-bit inline immediate into a subregister extract.
3966 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3967 return false;
3968
3969 // Most of the time folding a 32-bit inline constant is free (though this
3970 // might not be true if we can't later fold it into a real user).
3971 //
3972 // FIXME: This isInlineConstant check is imprecise if
3973 // getConstValDefinedInReg handled the tricky non-mov cases.
3974 if (ImmDefSize == 32 &&
3976 return false;
3977 }
3978
3979 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3980 RI.getSubRegIdxSize(UseSubReg) == 16;
3981
3982 if (Is16Bit) {
3983 if (RI.hasVGPRs(DstRC))
3984 return false; // Do not clobber vgpr_hi16
3985
3986 if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
3987 return false;
3988 }
3989
3990 MachineFunction *MF = UseMI.getMF();
3991
3992 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3993 MCRegister MovDstPhysReg =
3994 DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();
3995
3996 std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);
3997
3998 // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
3999 for (unsigned MovOp :
4000 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
4001 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
4002 const MCInstrDesc &MovDesc = get(MovOp);
4003
4004 const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
4005 if (Is16Bit) {
4006 // We just need to find a correctly sized register class, so the
4007 // subregister index compatibility doesn't matter since we're statically
4008 // extracting the immediate value.
4009 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
4010 if (!MovDstRC)
4011 continue;
4012
4013 if (MovDstPhysReg) {
4014 // FIXME: We probably should not do this. If there is a live value in
4015 // the high half of the register, it will be corrupted.
4016 MovDstPhysReg =
4017 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
4018 if (!MovDstPhysReg)
4019 continue;
4020 }
4021 }
4022
4023 // Result class isn't the right size, try the next instruction.
4024 if (MovDstPhysReg) {
4025 if (!MovDstRC->contains(MovDstPhysReg))
4026 return false;
4027 } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
4028 // TODO: This will be overly conservative in the case of 16-bit virtual
4029 // SGPRs. We could hack up the virtual register uses to use a compatible
4030 // 32-bit class.
4031 continue;
4032 }
4033
4034 const MCOperandInfo &OpInfo = MovDesc.operands()[1];
4035
4036 // Ensure the interpreted immediate value is a valid operand in the new
4037 // mov.
4038 //
4039 // FIXME: isImmOperandLegal should have form that doesn't require existing
4040 // MachineInstr or MachineOperand
4041 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4042 !isInlineConstant(*SubRegImm, OpInfo.OperandType))
4043 break;
4044
4045 NewOpc = MovOp;
4046 break;
4047 }
4048
4049 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4050 return false;
4051
4052 if (Is16Bit) {
4053 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4054 if (MovDstPhysReg)
4055 UseMI.getOperand(0).setReg(MovDstPhysReg);
4056 assert(UseMI.getOperand(1).getReg().isVirtual());
4057 }
4058
4059 const MCInstrDesc &NewMCID = get(NewOpc);
4060 UseMI.setDesc(NewMCID);
4061 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4062 UseMI.addImplicitDefUseOperands(*MF);
4063 return true;
4064 }
4065
4066 if (HasMultipleUses)
4067 return false;
4068
4069 if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
4070 Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4071 Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
4072 Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
4073 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4074 Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
4075 Opc == AMDGPU::V_FMAC_F64_e64) {
4076 // Don't fold if we are using source or output modifiers. The new VOP2
4077 // instructions don't have them.
4079 return false;
4080
4081 // If this is a free constant, there's no reason to do this.
4082 // TODO: We could fold this here instead of letting SIFoldOperands do it
4083 // later.
4084 int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4085
4086 // Any src operand can be used for the legality check.
4087 if (isInlineConstant(UseMI, Src0Idx, Imm))
4088 return false;
4089
4090 MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);
4091
4092 MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
4093 MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);
4094
4095 auto CopyRegOperandToNarrowerRC =
4096 [MRI, this](MachineInstr &MI, unsigned OpNo,
4097 const TargetRegisterClass *NewRC) -> void {
4098 if (!MI.getOperand(OpNo).isReg())
4099 return;
4100 Register Reg = MI.getOperand(OpNo).getReg();
4101 const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
4102 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4103 return;
4104 Register Tmp = MRI->createVirtualRegister(NewRC);
4105 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
4106 get(AMDGPU::COPY), Tmp)
4107 .addReg(Reg);
4108 MI.getOperand(OpNo).setReg(Tmp);
4109 };
4110
4111 // Multiplied part is the constant: Use v_madmk_{f16, f32}.
4112 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4113 (Src1->isReg() && Src1->getReg() == Reg)) {
4114 MachineOperand *RegSrc =
4115 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4116 if (!RegSrc->isReg())
4117 return false;
4118 if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
4119 ST.getConstantBusLimit(Opc) < 2)
4120 return false;
4121
4122 if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
4123 return false;
4124
4125 // If src2 is also a literal constant then we have to choose which one to
4126 // fold. In general it is better to choose madak so that the other literal
4127 // can be materialized in an sgpr instead of a vgpr:
4128 // s_mov_b32 s0, literal
4129 // v_madak_f32 v0, s0, v0, literal
4130 // Instead of:
4131 // v_mov_b32 v1, literal
4132 // v_madmk_f32 v0, v0, literal, v1
4133 MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
4134 if (Def && Def->isMoveImmediate() &&
4135 !isInlineConstant(Def->getOperand(1)))
4136 return false;
4137
4138 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4139 if (pseudoToMCOpcode(NewOpc) == -1)
4140 return false;
4141
4142 const std::optional<int64_t> SubRegImm = extractSubregFromImm(
4143 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4144
4145 // FIXME: This would be a lot easier if we could return a new instruction
4146 // instead of having to modify in place.
4147
4148 Register SrcReg = RegSrc->getReg();
4149 unsigned SrcSubReg = RegSrc->getSubReg();
4150 Src0->setReg(SrcReg);
4151 Src0->setSubReg(SrcSubReg);
4152 Src0->setIsKill(RegSrc->isKill());
4153
4154 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4155 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4156 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4157 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4158 UseMI.untieRegOperand(
4159 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4160
4161 Src1->ChangeToImmediate(*SubRegImm);
4162
4164 UseMI.setDesc(get(NewOpc));
4165
4166 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4167 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4168 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4169 Register Tmp = MRI->createVirtualRegister(NewRC);
4170 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4171 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4172 UseMI.getOperand(0).getReg())
4173 .addReg(Tmp);
4174 UseMI.getOperand(0).setReg(Tmp);
4175 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4176 CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
4177 }
4178
4179 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4180 if (DeleteDef)
4181 DefMI.eraseFromParent();
4182
4183 return true;
4184 }
4185
4186 // Added part is the constant: Use v_madak_{f16, f32}.
4187 if (Src2->isReg() && Src2->getReg() == Reg) {
4188 if (ST.getConstantBusLimit(Opc) < 2) {
4189 // Not allowed to use constant bus for another operand.
4190 // We can however allow an inline immediate as src0.
4191 bool Src0Inlined = false;
4192 if (Src0->isReg()) {
4193 // Try to inline constant if possible.
4194 // If the Def moves immediate and the use is single
4195 // We are saving VGPR here.
4196 MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
4197 if (Def && Def->isMoveImmediate() &&
4198 isInlineConstant(Def->getOperand(1)) &&
4199 MRI->hasOneNonDBGUse(Src0->getReg())) {
4200 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4201 Src0Inlined = true;
4202 } else if (ST.getConstantBusLimit(Opc) <= 1 &&
4203 RI.isSGPRReg(*MRI, Src0->getReg())) {
4204 return false;
4205 }
4206 // VGPR is okay as Src0 - fallthrough
4207 }
4208
4209 if (Src1->isReg() && !Src0Inlined) {
4210 // We have one slot for inlinable constant so far - try to fill it
4211 MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
4212 if (Def && Def->isMoveImmediate() &&
4213 isInlineConstant(Def->getOperand(1)) &&
4214 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
4215 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4216 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
4217 return false;
4218 // VGPR is okay as Src1 - fallthrough
4219 }
4220 }
4221
4222 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4223 if (pseudoToMCOpcode(NewOpc) == -1)
4224 return false;
4225
4226 // FIXME: This would be a lot easier if we could return a new instruction
4227 // instead of having to modify in place.
4228
4229 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4230 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4231 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4232 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4233 UseMI.untieRegOperand(
4234 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4235
4236 const std::optional<int64_t> SubRegImm =
4237 extractSubregFromImm(Imm, Src2->getSubReg());
4238
4239 // ChangingToImmediate adds Src2 back to the instruction.
4240 Src2->ChangeToImmediate(*SubRegImm);
4241
4242 // These come before src2.
4244 UseMI.setDesc(get(NewOpc));
4245
4246 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4247 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4248 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4249 Register Tmp = MRI->createVirtualRegister(NewRC);
4250 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4251 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4252 UseMI.getOperand(0).getReg())
4253 .addReg(Tmp);
4254 UseMI.getOperand(0).setReg(Tmp);
4255 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4256 CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
4257 }
4258
4259 // It might happen that UseMI was commuted
4260 // and we now have SGPR as SRC1. If so 2 inlined
4261 // constant and SGPR are illegal.
4263
4264 int NewSrc0Idx =
4265 AMDGPU::getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4266 if (!isOperandLegal(UseMI, NewSrc0Idx))
4267 legalizeOpWithMove(UseMI, NewSrc0Idx);
4268
4269 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4270 if (DeleteDef)
4271 DefMI.eraseFromParent();
4272
4273 return true;
4274 }
4275 }
4276
4277 return false;
4278}
4279
4280static bool
4283 if (BaseOps1.size() != BaseOps2.size())
4284 return false;
4285 for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
4286 if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
4287 return false;
4288 }
4289 return true;
4290}
4291
4292static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
4293 LocationSize WidthB, int OffsetB) {
4294 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4295 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4296 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4297 return LowWidth.hasValue() &&
4298 LowOffset + (int)LowWidth.getValue() <= HighOffset;
4299}
4300
4301bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
4302 const MachineInstr &MIb) const {
4303 SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
4304 int64_t Offset0, Offset1;
4305 LocationSize Dummy0 = LocationSize::precise(0);
4306 LocationSize Dummy1 = LocationSize::precise(0);
4307 bool Offset0IsScalable, Offset1IsScalable;
4308 if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
4309 Dummy0) ||
4310 !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
4311 Dummy1))
4312 return false;
4313
4314 if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
4315 return false;
4316
4317 if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
4318 // FIXME: Handle ds_read2 / ds_write2.
4319 return false;
4320 }
4321 LocationSize Width0 = MIa.memoperands().front()->getSize();
4322 LocationSize Width1 = MIb.memoperands().front()->getSize();
4323 return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
4324}
4325
4327 const MachineInstr &MIb) const {
4328 assert(MIa.mayLoadOrStore() &&
4329 "MIa must load from or modify a memory location");
4330 assert(MIb.mayLoadOrStore() &&
4331 "MIb must load from or modify a memory location");
4332
4334 return false;
4335
4336 // XXX - Can we relax this between address spaces?
4337 if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
4338 return false;
4339
4340 if (isLDSDMA(MIa) || isLDSDMA(MIb))
4341 return false;
4342
4343 if (MIa.isBundle() || MIb.isBundle())
4344 return false;
4345
4346 // TODO: Should we check the address space from the MachineMemOperand? That
4347 // would allow us to distinguish objects we know don't alias based on the
4348 // underlying address space, even if it was lowered to a different one,
4349 // e.g. private accesses lowered to use MUBUF instructions on a scratch
4350 // buffer.
4351 if (isDS(MIa)) {
4352 if (isDS(MIb))
4353 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4354
4355 return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
4356 }
4357
4358 if (isMUBUF(MIa) || isMTBUF(MIa)) {
4359 if (isMUBUF(MIb) || isMTBUF(MIb))
4360 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4361
4362 if (isFLAT(MIb))
4363 return isFLATScratch(MIb);
4364
4365 return !isSMRD(MIb);
4366 }
4367
4368 if (isSMRD(MIa)) {
4369 if (isSMRD(MIb))
4370 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4371
4372 if (isFLAT(MIb))
4373 return isFLATScratch(MIb);
4374
4375 return !isMUBUF(MIb) && !isMTBUF(MIb);
4376 }
4377
4378 if (isFLAT(MIa)) {
4379 if (isFLAT(MIb)) {
4380 if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
4381 (isFLATGlobal(MIa) && isFLATScratch(MIb)))
4382 return true;
4383
4384 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4385 }
4386
4387 return false;
4388 }
4389
4390 return false;
4391}
4392
4393static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
4394 switch (Opc) {
4395 case AMDGPU::V_MAC_F16_e32:
4396 case AMDGPU::V_MAC_F16_e64:
4397 return AMDGPU::V_MAD_F16_e64;
4398 case AMDGPU::V_MAC_F32_e32:
4399 case AMDGPU::V_MAC_F32_e64:
4400 return AMDGPU::V_MAD_F32_e64;
4401 case AMDGPU::V_MAC_LEGACY_F32_e32:
4402 case AMDGPU::V_MAC_LEGACY_F32_e64:
4403 return AMDGPU::V_MAD_LEGACY_F32_e64;
4404 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4405 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4406 return AMDGPU::V_FMA_LEGACY_F32_e64;
4407 case AMDGPU::V_FMAC_F16_e32:
4408 case AMDGPU::V_FMAC_F16_e64:
4409 case AMDGPU::V_FMAC_F16_t16_e64:
4410 case AMDGPU::V_FMAC_F16_fake16_e64:
4411 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4412 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4413 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4414 : AMDGPU::V_FMA_F16_gfx9_e64;
4415 case AMDGPU::V_FMAC_F32_e32:
4416 case AMDGPU::V_FMAC_F32_e64:
4417 return AMDGPU::V_FMA_F32_e64;
4418 case AMDGPU::V_FMAC_F64_e32:
4419 case AMDGPU::V_FMAC_F64_e64:
4420 return AMDGPU::V_FMA_F64_e64;
4421 default:
4422 llvm_unreachable("invalid instruction");
4423 }
4424}
4425
4426/// Helper struct for the implementation of 3-address conversion to communicate
4427/// updates made to instruction operands.
4429 /// Other instruction whose def is no longer used by the converted
4430 /// instruction.
4432};
4433
4435 LiveIntervals *LIS) const {
4436 MachineBasicBlock &MBB = *MI.getParent();
4437 MachineInstr *CandidateMI = &MI;
4438
4439 if (MI.isBundle()) {
4440 // This is a temporary placeholder for bundle handling that enables us to
4441 // exercise the relevant code paths in the two-address instruction pass.
4442 if (MI.getBundleSize() != 1)
4443 return nullptr;
4444 CandidateMI = MI.getNextNode();
4445 }
4446
4448 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4449 if (!NewMI)
4450 return nullptr;
4451
4452 if (MI.isBundle()) {
4453 CandidateMI->eraseFromBundle();
4454
4455 for (MachineOperand &MO : MI.all_defs()) {
4456 if (MO.isTied())
4457 MI.untieRegOperand(MO.getOperandNo());
4458 }
4459 } else {
4460 if (LIS) {
4461 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
4462 // SlotIndex of defs needs to be updated when converting to early-clobber
4463 MachineOperand &Def = NewMI->getOperand(0);
4464 if (Def.isEarlyClobber() && Def.isReg() &&
4465 LIS->hasInterval(Def.getReg())) {
4466 SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
4467 SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
4468 auto &LI = LIS->getInterval(Def.getReg());
4469 auto UpdateDefIndex = [&](LiveRange &LR) {
4470 auto *S = LR.find(OldIndex);
4471 if (S != LR.end() && S->start == OldIndex) {
4472 assert(S->valno && S->valno->def == OldIndex);
4473 S->start = NewIndex;
4474 S->valno->def = NewIndex;
4475 }
4476 };
4477 UpdateDefIndex(LI);
4478 for (auto &SR : LI.subranges())
4479 UpdateDefIndex(SR);
4480 }
4481 }
4482 }
4483
4484 if (U.RemoveMIUse) {
4485 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4486 // The only user is the instruction which will be killed.
4487 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4488
4489 if (MRI.hasOneNonDBGUse(DefReg)) {
4490 // We cannot just remove the DefMI here, calling pass will crash.
4491 U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
4492 U.RemoveMIUse->getOperand(0).setIsDead(true);
4493 for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
4494 U.RemoveMIUse->removeOperand(I);
4495 }
4496
4497 if (MI.isBundle()) {
4498 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4499 if (!VRI.Reads && !VRI.Writes) {
4500 for (MachineOperand &MO : MI.all_uses()) {
4501 if (MO.isReg() && MO.getReg() == DefReg) {
4502 assert(MO.getSubReg() == 0 &&
4503 "tied sub-registers in bundles currently not supported");
4504 MI.removeOperand(MO.getOperandNo());
4505 break;
4506 }
4507 }
4508
4509 if (LIS)
4510 LIS->shrinkToUses(&LIS->getInterval(DefReg));
4511 }
4512 } else if (LIS) {
4513 LiveInterval &DefLI = LIS->getInterval(DefReg);
4514
4515 // We cannot delete the original instruction here, so hack out the use
4516 // in the original instruction with a dummy register so we can use
4517 // shrinkToUses to deal with any multi-use edge cases. Other targets do
4518 // not have the complexity of deleting a use to consider here.
4519 Register DummyReg = MRI.cloneVirtualRegister(DefReg);
4520 for (MachineOperand &MIOp : MI.uses()) {
4521 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4522 MIOp.setIsUndef(true);
4523 MIOp.setReg(DummyReg);
4524 }
4525 }
4526
4527 if (MI.isBundle()) {
4528 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4529 if (!VRI.Reads && !VRI.Writes) {
4530 for (MachineOperand &MIOp : MI.uses()) {
4531 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4532 MIOp.setIsUndef(true);
4533 MIOp.setReg(DummyReg);
4534 }
4535 }
4536 }
4537
4538 MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
4539 false, /*isUndef=*/true));
4540 }
4541
4542 LIS->shrinkToUses(&DefLI);
4543 }
4544 }
4545
4546 return MI.isBundle() ? &MI : NewMI;
4547}
4548
4550SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
4551 ThreeAddressUpdates &U) const {
4552 MachineBasicBlock &MBB = *MI.getParent();
4553 unsigned Opc = MI.getOpcode();
4554
4555 // Handle MFMA.
4556 int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
4557 if (NewMFMAOpc != -1) {
4559 BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
4560 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4561 MIB.add(MI.getOperand(I));
4562 return MIB;
4563 }
4564
4565 if (SIInstrInfo::isWMMA(MI)) {
4566 unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
4567 MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4568 .setMIFlags(MI.getFlags());
4569 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4570 MIB->addOperand(MI.getOperand(I));
4571 return MIB;
4572 }
4573
4574 assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4575 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4576 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4577 "present pre-RA");
4578
4579 // Handle MAC/FMAC.
4580 bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
4581 bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4582 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4583 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4584 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4585 bool Src0Literal = false;
4586
4587 switch (Opc) {
4588 default:
4589 return nullptr;
4590 case AMDGPU::V_MAC_F16_e64:
4591 case AMDGPU::V_FMAC_F16_e64:
4592 case AMDGPU::V_FMAC_F16_t16_e64:
4593 case AMDGPU::V_FMAC_F16_fake16_e64:
4594 case AMDGPU::V_MAC_F32_e64:
4595 case AMDGPU::V_MAC_LEGACY_F32_e64:
4596 case AMDGPU::V_FMAC_F32_e64:
4597 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4598 case AMDGPU::V_FMAC_F64_e64:
4599 break;
4600 case AMDGPU::V_MAC_F16_e32:
4601 case AMDGPU::V_FMAC_F16_e32:
4602 case AMDGPU::V_MAC_F32_e32:
4603 case AMDGPU::V_MAC_LEGACY_F32_e32:
4604 case AMDGPU::V_FMAC_F32_e32:
4605 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4606 case AMDGPU::V_FMAC_F64_e32: {
4607 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
4608 AMDGPU::OpName::src0);
4609 const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
4610 if (!Src0->isReg() && !Src0->isImm())
4611 return nullptr;
4612
4613 if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
4614 Src0Literal = true;
4615
4616 break;
4617 }
4618 }
4619
4620 MachineInstrBuilder MIB;
4621 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
4622 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
4623 const MachineOperand *Src0Mods =
4624 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
4625 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4626 const MachineOperand *Src1Mods =
4627 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
4628 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4629 const MachineOperand *Src2Mods =
4630 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
4631 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
4632 const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
4633 const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);
4634
4635 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4636 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4637 // If we have an SGPR input, we will violate the constant bus restriction.
4638 (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
4639 !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
4640 MachineInstr *DefMI = nullptr;
4641 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4642 std::optional<int64_t> ImmOpt;
4643 int64_t Imm;
4644
4645 if (!Src0Literal &&
4646 (ImmOpt = getImmOrMaterializedImm(MRI, *Src2, &DefMI))) {
4647 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4648 if (pseudoToMCOpcode(NewOpc) != -1) {
4649 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4650 .add(*Dst)
4651 .add(*Src0)
4652 .add(*Src1)
4653 .addImm(*ImmOpt)
4654 .setMIFlags(MI.getFlags());
4655 U.RemoveMIUse = DefMI;
4656 return MIB;
4657 }
4658 }
4659 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4660 if (!Src0Literal &&
4661 (ImmOpt = getImmOrMaterializedImm(MRI, *Src1, &DefMI))) {
4662 if (pseudoToMCOpcode(NewOpc) != -1) {
4663 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4664 .add(*Dst)
4665 .add(*Src0)
4666 .addImm(*ImmOpt)
4667 .add(*Src2)
4668 .setMIFlags(MI.getFlags());
4669 U.RemoveMIUse = DefMI;
4670 return MIB;
4671 }
4672 }
4673 if ((ImmOpt = getImmOrMaterializedImm(MRI, *Src0, &DefMI))) {
4674 Imm = *ImmOpt;
4675 if (pseudoToMCOpcode(NewOpc) != -1 &&
4677 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4678 Src1)) {
4679 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4680 .add(*Dst)
4681 .add(*Src1)
4682 .addImm(Imm)
4683 .add(*Src2)
4684 .setMIFlags(MI.getFlags());
4685 U.RemoveMIUse = DefMI;
4686 return MIB;
4687 }
4688 }
4689 }
4690
4691 // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
4692 // if VOP3 does not allow a literal operand.
4693 if (Src0Literal && !ST.hasVOP3Literal())
4694 return nullptr;
4695
4696 unsigned NewOpc = getNewFMAInst(ST, Opc);
4697
4698 if (pseudoToMCOpcode(NewOpc) == -1)
4699 return nullptr;
4700
4701 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4702 .add(*Dst)
4703 .addImm(Src0Mods ? Src0Mods->getImm() : 0)
4704 .add(*Src0)
4705 .addImm(Src1Mods ? Src1Mods->getImm() : 0)
4706 .add(*Src1)
4707 .addImm(Src2Mods ? Src2Mods->getImm() : 0)
4708 .add(*Src2)
4709 .addImm(Clamp ? Clamp->getImm() : 0)
4710 .addImm(Omod ? Omod->getImm() : 0)
4711 .setMIFlags(MI.getFlags());
4712 if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
4713 MIB.addImm(OpSel ? OpSel->getImm() : 0);
4714 return MIB;
4715}
4716
4717// It's not generally safe to move VALU instructions across these since it will
4718// start using the register as a base index rather than directly.
4719// XXX - Why isn't hasSideEffects sufficient for these?
4721 switch (MI.getOpcode()) {
4722 case AMDGPU::S_SET_GPR_IDX_ON:
4723 case AMDGPU::S_SET_GPR_IDX_MODE:
4724 case AMDGPU::S_SET_GPR_IDX_OFF:
4725 return true;
4726 default:
4727 return false;
4728 }
4729}
4730
4732 const MachineBasicBlock *MBB,
4733 const MachineFunction &MF) const {
4734 // Skipping the check for SP writes in the base implementation. The reason it
4735 // was added was apparently due to compile time concerns.
4736 //
4737 // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
4738 // but is probably avoidable.
4739
4740 // Copied from base implementation.
4741 // Terminators and labels can't be scheduled around.
4742 if (MI.isTerminator() || MI.isPosition())
4743 return true;
4744
4745 // INLINEASM_BR can jump to another block
4746 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4747 return true;
4748
4749 if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
4750 return true;
4751
4752 // Target-independent instructions do not have an implicit-use of EXEC, even
4753 // when they operate on VGPRs. Treating EXEC modifications as scheduling
4754 // boundaries prevents incorrect movements of such instructions.
4755 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4756 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4757 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4758 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4759 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4761}
4762
4764 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4765 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4766 Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
4767}
4768
4770 // Instructions that access scratch use FLAT encoding or BUF encodings.
4771 if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
4772 return false;
4773
4774 // SCRATCH instructions always access scratch.
4775 if (isFLATScratch(MI))
4776 return true;
4777
4778 // If FLAT_SCRATCH registers are not initialized, we can never access scratch
4779 // via the aperture.
4780 if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
4781 return false;
4782
4783 // If there are no memory operands then conservatively assume the flat
4784 // operation may access scratch.
4785 if (MI.memoperands_empty())
4786 return true;
4787
4788 // See if any memory operand specifies an address space that involves scratch.
4789 return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
4790 unsigned AS = Memop->getAddrSpace();
4791 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4792 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4793 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4794 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4795 }
4796 return AS == AMDGPUAS::PRIVATE_ADDRESS;
4797 });
4798}
4799
4801 assert(isFLAT(MI));
4802
4803 // All flat instructions use the VMEM counter except prefetch.
4804 if (!usesVM_CNT(MI))
4805 return false;
4806
4807 // If there are no memory operands then conservatively assume the flat
4808 // operation may access VMEM.
4809 if (MI.memoperands_empty())
4810 return true;
4811
4812 // See if any memory operand specifies an address space that involves VMEM.
4813 // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
4814 // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
4815 // (GDS) address space is not supported by flat operations. Therefore, simply
4816 // return true unless only the LDS address space is found.
4817 for (const MachineMemOperand *Memop : MI.memoperands()) {
4818 unsigned AS = Memop->getAddrSpace();
4820 if (AS != AMDGPUAS::LOCAL_ADDRESS)
4821 return true;
4822 }
4823
4824 return false;
4825}
4826
4828 bool TgSplit) const {
4829 assert(isFLAT(MI));
4830
4831 // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
4832 if (!usesLGKM_CNT(MI))
4833 return false;
4834
4835 // If in tgsplit mode then there can be no use of LDS.
4836 if (TgSplit)
4837 return false;
4838
4839 // If there are no memory operands then conservatively assume the flat
4840 // operation may access LDS.
4841 if (MI.memoperands_empty())
4842 return true;
4843
4844 // See if any memory operand specifies an address space that involves LDS.
4845 for (const MachineMemOperand *Memop : MI.memoperands()) {
4846 unsigned AS = Memop->getAddrSpace();
4848 return true;
4849 }
4850
4851 return false;
4852}
4853
4855 // Skip the full operand and register alias search modifiesRegister
4856 // does. There's only a handful of instructions that touch this, it's only an
4857 // implicit def, and doesn't alias any other registers.
4858 return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
4859}
4860
4862 unsigned Opcode = MI.getOpcode();
4863
4864 if (MI.mayStore() && isSMRD(MI))
4865 return true; // scalar store or atomic
4866
4867 // This will terminate the function when other lanes may need to continue.
4868 if (MI.isReturn())
4869 return true;
4870
4871 // These instructions cause shader I/O that may cause hardware lockups
4872 // when executed with an empty EXEC mask.
4873 //
4874 // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
4875 // EXEC = 0, but checking for that case here seems not worth it
4876 // given the typical code patterns.
4877 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4878 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4879 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4880 Opcode == AMDGPU::S_SETHALT)
4881 return true;
4882
4883 if (MI.isCall() || MI.isInlineAsm())
4884 return true; // conservative assumption
4885
4886 // V_PERM_PK16 must issue with EXEC != 0 so its follower (or an inserted
4887 // V_NOP) actually runs on the VALU pipe. Returning true here keeps the
4888 // s_cbranch_execz that skips this region when EXEC is empty.
4889 if (ST.hasVPermPk16Hazard() && isVPermPk16(Opcode))
4890 return true;
4891
4892 // Assume that barrier interactions are only intended with active lanes.
4893 if (isBarrier(Opcode))
4894 return true;
4895
4896 // A mode change is a scalar operation that influences vector instructions.
4898 return true;
4899
4900 // These are like SALU instructions in terms of effects, so it's questionable
4901 // whether we should return true for those.
4902 //
4903 // However, executing them with EXEC = 0 causes them to operate on undefined
4904 // data, which we avoid by returning true here.
4905 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4906 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4907 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4908 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4909 return true;
4910
4911 return false;
4912}
4913
4915 const MachineInstr &MI) const {
4916 if (MI.isMetaInstruction())
4917 return false;
4918
4919 // This won't read exec if this is an SGPR->SGPR copy.
4920 if (MI.isCopyLike()) {
4921 if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
4922 return true;
4923
4924 // Make sure this isn't copying exec as a normal operand
4925 return MI.readsRegister(AMDGPU::EXEC, &RI);
4926 }
4927
4928 // Make a conservative assumption about the callee.
4929 if (MI.isCall())
4930 return true;
4931
4932 // Be conservative with any unhandled generic opcodes.
4933 if (!isTargetSpecificOpcode(MI.getOpcode()))
4934 return true;
4935
4936 return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
4937}
4938
4940 switch (Imm.getBitWidth()) {
4941 case 1: // This likely will be a condition code mask.
4942 return true;
4943
4944 case 32:
4945 return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
4946 ST.hasInv2PiInlineImm());
4947 case 64:
4948 return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
4949 ST.hasInv2PiInlineImm());
4950 case 16:
4951 return ST.has16BitInsts() &&
4952 AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
4953 ST.hasInv2PiInlineImm());
4954 default:
4955 llvm_unreachable("invalid bitwidth");
4956 }
4957}
4958
4960 APInt IntImm = Imm.bitcastToAPInt();
4961 int64_t IntImmVal = IntImm.getSExtValue();
4962 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4963 switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
4964 default:
4965 llvm_unreachable("invalid fltSemantics");
4968 return isInlineConstant(IntImm);
4970 return ST.has16BitInsts() &&
4971 AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
4973 return ST.has16BitInsts() &&
4974 AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
4975 }
4976}
4977
4978bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
4979 // MachineOperand provides no way to tell the true operand size, since it only
4980 // records a 64-bit value. We need to know the size to determine if a 32-bit
4981 // floating point immediate bit pattern is legal for an integer immediate. It
4982 // would be for any 32-bit integer operand, but would not be for a 64-bit one.
4983 switch (OperandType) {
4993 int32_t Trunc = static_cast<int32_t>(Imm);
4994 return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
4995 }
5003 return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
5006 // We would expect inline immediates to not be concerned with an integer/fp
5007 // distinction. However, in the case of 16-bit integer operations, the
5008 // "floating point" values appear to not work. It seems read the low 16-bits
5009 // of 32-bit immediates, which happens to always work for the integer
5010 // values.
5011 //
5012 // See llvm bugzilla 46302.
5013 //
5014 // TODO: Theoretically we could use op-sel to use the high bits of the
5015 // 32-bit FP values.
5024 return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
5029 return false;
5032 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
5033 // A few special case instructions have 16-bit operands on subtargets
5034 // where 16-bit instructions are not legal.
5035 // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
5036 // constants in these cases
5037 int16_t Trunc = static_cast<int16_t>(Imm);
5038 return ST.has16BitInsts() &&
5039 AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
5040 }
5041
5042 return false;
5043 }
5046 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
5047 int16_t Trunc = static_cast<int16_t>(Imm);
5048 return ST.has16BitInsts() &&
5049 AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
5050 }
5051 return false;
5052 }
5057 return false;
5059 return isLegalAV64PseudoImm(Imm);
5062 // Always embedded in the instruction for free.
5063 return true;
5073 // Just ignore anything else.
5074 return false;
5075 default:
5076 llvm_unreachable("invalid operand type");
5077 }
5078}
5079
5080static bool compareMachineOp(const MachineOperand &Op0,
5081 const MachineOperand &Op1) {
5082 if (Op0.getType() != Op1.getType())
5083 return false;
5084
5085 switch (Op0.getType()) {
5087 return Op0.getReg() == Op1.getReg();
5089 return Op0.getImm() == Op1.getImm();
5090 default:
5091 llvm_unreachable("Didn't expect to be comparing these operand types");
5092 }
5093}
5094
5096 const MCOperandInfo &OpInfo) const {
5097 if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
5098 return true;
5099
5100 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5101 return false;
5102
5103 if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
5104 return true;
5105
5106 return ST.hasVOP3Literal();
5107}
5108
5109bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5110 int64_t ImmVal) const {
5111 const unsigned Opc = InstDesc.getOpcode();
5112 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
5113 if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
5114 OpNo == static_cast<unsigned>(Src1Idx))
5115 return false;
5116
5117 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5118 if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
5119 if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5120 OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
5121 AMDGPU::OpName::src2))
5122 return false;
5123
5124 if (ST.hasBF16InlineConstFromUpperFP32() && isVOP1(Opc)) {
5125 if ((OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_BF16 ||
5126 OpInfo.OperandType == AMDGPU::OPERAND_REG_INLINE_C_BF16) &&
5127 isInlineConstant(ImmVal, OpInfo.OperandType))
5128 return false;
5129 }
5130
5131 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5132 }
5133
5134 return isLiteralOperandLegal(InstDesc, OpInfo);
5135}
5136
5137bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5138 const MachineOperand &MO) const {
5139 if (MO.isImm())
5140 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
5141
5142 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
5143 "unexpected imm-like operand kind");
5144 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5145 return isLiteralOperandLegal(InstDesc, OpInfo);
5146}
5147
5149 // 2 32-bit inline constants packed into one.
5150 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
5151 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
5152}
5153
5154bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
5155 // GFX90A does not have V_MUL_LEGACY_F32_e32.
5156 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5157 return false;
5158
5159 int Op32 = AMDGPU::getVOPe32(Opcode);
5160 if (Op32 == -1)
5161 return false;
5162
5163 return pseudoToMCOpcode(Op32) != -1;
5164}
5165
5166/// Return true if \p MI is a VALU comparison, i.e. an instruction that writes
5167/// a lane mask with one bit per lane, and zeroes the bits of lanes that were
5168/// inactive when it executed.
5169///
5170/// TODO: Also handle the sdst result of V_ADD_CO_U32 and V_SUB_CO_U32 and
5171/// V_DIV_SCALE_F32.
5172static bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI) {
5173 if (TII.isVOPC(MI))
5174 return true;
5175 int Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5176 return Op32 != -1 && TII.isVOPC(Op32);
5177}
5178
5180 const MachineRegisterInfo &MRI,
5181 unsigned Depth) const {
5182 assert(MRI.isSSA() && "isMaskedByExec requires SSA form");
5184 const MachineBasicBlock *MBB = Use.getParent();
5185
5186 // EXEC itself is trivially masked by EXEC.
5187 if (Reg == LMC.ExecReg)
5188 return true;
5189
5190 // Maximum depth of the def-use walk.
5191 constexpr unsigned MaxDepth = 6;
5192 if (Depth >= MaxDepth || !Reg.isVirtual())
5193 return false;
5194
5195 // Only look at definitions that can execute under the same EXEC mask as the
5196 // use.
5197 const MachineInstr *Def = MRI.getVRegDef(Reg);
5198 if (!Def || Def->getParent() != MBB)
5199 return false;
5200
5201 if (isVCmp(*this, *Def))
5202 return true;
5203
5204 // Recurse into an operand, which must be a whole register to say anything
5205 // about the whole lane mask.
5206 auto Recurse = [&](unsigned OpIdx) {
5207 const MachineOperand &MO = Def->getOperand(OpIdx);
5208 return MO.isReg() && !MO.getSubReg() &&
5209 isMaskedByExec(MO.getReg(), Use, MRI, Depth + 1);
5210 };
5211
5212 unsigned Opc = Def->getOpcode();
5213 if (Opc == AMDGPU::COPY && Recurse(1))
5214 return true;
5215 if (Opc == LMC.AndOpc && (Recurse(1) || Recurse(2)))
5216 return true;
5217 if (Opc == LMC.AndN2Opc && Recurse(1))
5218 return true;
5219 if ((Opc == LMC.OrOpc || Opc == LMC.XorOpc) && Recurse(1) && Recurse(2))
5220 return true;
5221 // TODO: Sometimes we encounter "reg = S_CSELECT -1, 0". If Reg has no other
5222 // uses this could be optimized to "reg = S_CSELECT $exec, 0".
5223
5224 return false;
5225}
5226
5227bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
5228 // The src0_modifier operand is present on all instructions
5229 // that have modifiers.
5230
5231 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
5232}
5233
5235 AMDGPU::OpName OpName) const {
5236 const MachineOperand *Mods = getNamedOperand(MI, OpName);
5237 return Mods && Mods->getImm();
5238}
5239
5241 return any_of(ModifierOpNames,
5242 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
5243}
5244
5246 const MachineRegisterInfo &MRI) const {
5247 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5248 // Can't shrink instruction with three operands.
5249 if (Src2) {
5250 switch (MI.getOpcode()) {
5251 default: return false;
5252
5253 case AMDGPU::V_ADDC_U32_e64:
5254 case AMDGPU::V_SUBB_U32_e64:
5255 case AMDGPU::V_SUBBREV_U32_e64: {
5256 const MachineOperand *Src1
5257 = getNamedOperand(MI, AMDGPU::OpName::src1);
5258 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
5259 return false;
5260 // Additional verification is needed for sdst/src2.
5261 return true;
5262 }
5263 case AMDGPU::V_MAC_F16_e64:
5264 case AMDGPU::V_MAC_F32_e64:
5265 case AMDGPU::V_MAC_LEGACY_F32_e64:
5266 case AMDGPU::V_FMAC_F16_e64:
5267 case AMDGPU::V_FMAC_F16_t16_e64:
5268 case AMDGPU::V_FMAC_F16_fake16_e64:
5269 case AMDGPU::V_FMAC_F32_e64:
5270 case AMDGPU::V_FMAC_F64_e64:
5271 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5272 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
5273 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
5274 return false;
5275 break;
5276
5277 case AMDGPU::V_CNDMASK_B32_e64:
5278 break;
5279 }
5280 }
5281
5282 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
5283 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5284 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
5285 return false;
5286
5287 // Make sure src0 isn't using any modifiers.
5288 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
5289 return false;
5290
5291 // Can it be shrunk to a valid 32 bit opcode?
5292 if (!hasVALU32BitEncoding(MI.getOpcode()))
5293 return false;
5294
5295 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
5296 if (Src0 && Src0->isImm()) {
5297 unsigned Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5298 if (!isImmOperandLegal(
5299 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5300 *Src0))
5301 return false;
5302 }
5303
5304 // Check output modifiers
5305 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
5306 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
5307 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
5308 // TODO: Can we avoid checking bound_ctrl/fi here?
5309 // They are only used by permlane*_swap special case.
5310 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
5311 !hasModifiersSet(MI, AMDGPU::OpName::fi);
5312}
5313
5314// Set VCC operand with all flags from \p Orig, except for setting it as
5315// implicit.
5317 const MachineOperand &Orig) {
5318
5319 for (MachineOperand &Use : MI.implicit_operands()) {
5320 if (Use.isUse() &&
5321 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
5322 Use.setIsUndef(Orig.isUndef());
5323 Use.setIsKill(Orig.isKill());
5324 return;
5325 }
5326 }
5327}
5328
5330 unsigned Op32) const {
5331 MachineBasicBlock *MBB = MI.getParent();
5332
5333 const MCInstrDesc &Op32Desc = get(Op32);
5334 MachineInstrBuilder Inst32 =
5335 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
5336 .setMIFlags(MI.getFlags());
5337
5338 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
5339 // For VOPC instructions, this is replaced by an implicit def of vcc.
5340
5341 // We assume the defs of the shrunk opcode are in the same order, and the
5342 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
5343 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
5344 Inst32.add(MI.getOperand(I));
5345
5346 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5347
5348 int Idx = MI.getNumExplicitDefs();
5349 for (const MachineOperand &Use : MI.explicit_uses()) {
5350 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
5352 continue;
5353
5354 if (&Use == Src2) {
5355 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5356 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
5357 // replaced with an implicit read of vcc or vcc_lo. The implicit read
5358 // of vcc was already added during the initial BuildMI, but we
5359 // 1) may need to change vcc to vcc_lo to preserve the original register
5360 // 2) have to preserve the original flags.
5361 copyFlagsToImplicitVCC(*Inst32, *Src2);
5362 continue;
5363 }
5364 }
5365
5366 Inst32.add(Use);
5367 }
5368
5369 // FIXME: Losing implicit operands
5370 fixImplicitOperands(*Inst32);
5371
5372 // The explicit carry/result def is dropped in favor of an implicit VCC def;
5373 // preserve the dead flag.
5374 const MachineOperand *OldSDst = getNamedOperand(MI, AMDGPU::OpName::sdst);
5375 if (OldSDst && OldSDst->isDead()) {
5376 if (MachineOperand *NewVCC =
5377 Inst32->findRegisterDefOperand(RI.getVCC(), &RI))
5378 NewVCC->setIsDead();
5379 }
5380
5381 return Inst32;
5382}
5383
5385 // Null is free
5386 Register Reg = RegOp.getReg();
5387 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5388 return false;
5389
5390 // SGPRs use the constant bus
5391
5392 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
5393 // physical register operands should also count, except for exec.
5394 if (RegOp.isImplicit())
5395 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5396
5397 // SGPRs use the constant bus
5398 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5399 AMDGPU::SReg_64RegClass.contains(Reg);
5400}
5401
5403 const MachineRegisterInfo &MRI) const {
5404 Register Reg = RegOp.getReg();
5405 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5406 : physRegUsesConstantBus(RegOp);
5407}
5408
5410 const MachineOperand &MO,
5411 const MCOperandInfo &OpInfo) const {
5412 // Literal constants use the constant bus.
5413 if (!MO.isReg())
5414 return !isInlineConstant(MO, OpInfo);
5415
5416 Register Reg = MO.getReg();
5417 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5419}
5420
5422 for (const MachineOperand &MO : MI.implicit_operands()) {
5423 // We only care about reads.
5424 if (MO.isDef())
5425 continue;
5426
5427 switch (MO.getReg()) {
5428 case AMDGPU::VCC:
5429 case AMDGPU::VCC_LO:
5430 case AMDGPU::VCC_HI:
5431 case AMDGPU::M0:
5432 case AMDGPU::FLAT_SCR:
5433 return MO.getReg();
5434
5435 default:
5436 break;
5437 }
5438 }
5439
5440 return Register();
5441}
5442
5443static bool shouldReadExec(const MachineInstr &MI) {
5444 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5445 switch (MI.getOpcode()) {
5446 case AMDGPU::V_READLANE_B32:
5447 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5448 case AMDGPU::V_WRITELANE_B32:
5449 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5450 return false;
5451 }
5452
5453 return true;
5454 }
5455
5456 if (MI.isPreISelOpcode() ||
5457 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5460 return false;
5461
5462 return true;
5463}
5464
5465static bool isRegOrFI(const MachineOperand &MO) {
5466 return MO.isReg() || MO.isFI();
5467}
5468
5469static bool isSubRegOf(const SIRegisterInfo &TRI,
5470 const MachineOperand &SuperVec,
5471 const MachineOperand &SubReg) {
5472 if (SubReg.getReg().isPhysical())
5473 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5474
5475 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5476 SubReg.getReg() == SuperVec.getReg();
5477}
5478
5479// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5480bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5481 const MachineRegisterInfo &MRI,
5482 StringRef &ErrInfo) const {
5483 Register DstReg = MI.getOperand(0).getReg();
5484 Register SrcReg = MI.getOperand(1).getReg();
5485 // This is a check for copy from vector register to SGPR
5486 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5487 ErrInfo = "illegal copy from vector register to SGPR";
5488 return false;
5489 }
5490 return true;
5491}
5492
5494 StringRef &ErrInfo) const {
5495 uint32_t Opcode = MI.getOpcode();
5496 const MachineFunction *MF = MI.getMF();
5497 const MachineRegisterInfo &MRI = MF->getRegInfo();
5498
5499 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5500 // Find a better property to recognize the point where instruction selection
5501 // is just done.
5502 // We can only enforce this check after SIFixSGPRCopies pass so that the
5503 // illegal copies are legalized and thereafter we don't expect a pass
5504 // inserting similar copies.
5505 if (!MRI.isSSA() && MI.isCopy())
5506 return verifyCopy(MI, MRI, ErrInfo);
5507
5508 if (SIInstrInfo::isGenericOpcode(Opcode))
5509 return true;
5510
5511 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5512 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5513 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5514 int Src3Idx = -1;
5515 if (Src0Idx == -1) {
5516 // VOPD V_DUAL_* instructions use different operand names.
5517 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5518 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5519 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5520 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5521 }
5522
5523 // Make sure the number of operands is correct.
5524 const MCInstrDesc &Desc = get(Opcode);
5525 if (!Desc.isVariadic() &&
5526 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5527 ErrInfo = "Instruction has wrong number of operands.";
5528 return false;
5529 }
5530
5531 if (MI.isInlineAsm()) {
5532 // Verify register classes for inlineasm constraints.
5533 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5534 I != E; ++I) {
5535 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5536 if (!RC)
5537 continue;
5538
5539 const MachineOperand &Op = MI.getOperand(I);
5540 if (!Op.isReg())
5541 continue;
5542
5543 Register Reg = Op.getReg();
5544 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5545 ErrInfo = "inlineasm operand has incorrect register class.";
5546 return false;
5547 }
5548 }
5549
5550 return true;
5551 }
5552
5553 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5554 ErrInfo = "missing memory operand from image instruction.";
5555 return false;
5556 }
5557
5558 // Make sure the register classes are correct.
5559 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5560 const MachineOperand &MO = MI.getOperand(i);
5561 if (MO.isFPImm()) {
5562 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5563 "all fp values to integers.";
5564 return false;
5565 }
5566
5567 const MCOperandInfo &OpInfo = Desc.operands()[i];
5568
5569 switch (OpInfo.OperandType) {
5571 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5572 ErrInfo = "Illegal immediate value for operand.";
5573 return false;
5574 }
5575 break;
5589 break;
5603 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5604 ErrInfo = "Illegal immediate value for operand.";
5605 return false;
5606 }
5607 break;
5608 }
5613 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5614 !isInlineConstant(MI, i) &&
5616 OpInfo.OperandType ==
5618 ErrInfo = "illegal 64-bit immediate value for operand.";
5619 return false;
5620 }
5621 break;
5624 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5625 ErrInfo = "Expected inline constant for operand.";
5626 return false;
5627 }
5628 break;
5631 break;
5636 // Check if this operand is an immediate.
5637 // FrameIndex operands will be replaced by immediates, so they are
5638 // allowed.
5639 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5640 ErrInfo = "Expected immediate, but got non-immediate";
5641 return false;
5642 }
5643 break;
5647 break;
5648 default:
5649 if (OpInfo.isGenericType())
5650 continue;
5651 break;
5652 }
5653 }
5654
5655 // Verify SDWA
5656 if (isSDWA(MI)) {
5657 if (!ST.hasSDWA()) {
5658 ErrInfo = "SDWA is not supported on this target";
5659 return false;
5660 }
5661
5662 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5663 AMDGPU::OpName::dst_sel}) {
5664 const MachineOperand *MO = getNamedOperand(MI, Op);
5665 if (!MO)
5666 continue;
5667 int64_t Imm = MO->getImm();
5669 ErrInfo = "Invalid SDWA selection";
5670 return false;
5671 }
5672 }
5673
5674 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5675
5676 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5677 if (OpIdx == -1)
5678 continue;
5679 const MachineOperand &MO = MI.getOperand(OpIdx);
5680
5681 if (!ST.hasSDWAScalar()) {
5682 // Only VGPRS on VI
5683 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5684 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5685 return false;
5686 }
5687 } else {
5688 // No immediates on GFX9
5689 if (!MO.isReg()) {
5690 ErrInfo =
5691 "Only reg allowed as operands in SDWA instructions on GFX9+";
5692 return false;
5693 }
5694 }
5695 }
5696
5697 if (!ST.hasSDWAOmod()) {
5698 // No omod allowed on VI
5699 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5700 if (OMod != nullptr &&
5701 (!OMod->isImm() || OMod->getImm() != 0)) {
5702 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5703 return false;
5704 }
5705 }
5706
5707 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5708 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5709 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5710 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5711 const MachineOperand *Src0ModsMO =
5712 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5713 unsigned Mods = Src0ModsMO->getImm();
5714 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5715 Mods & SISrcMods::SEXT) {
5716 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5717 return false;
5718 }
5719 }
5720
5721 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5722 if (isVOPC(BasicOpcode)) {
5723 if (!ST.hasSDWASdst() && DstIdx != -1) {
5724 // Only vcc allowed as dst on VI for VOPC
5725 const MachineOperand &Dst = MI.getOperand(DstIdx);
5726 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5727 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5728 return false;
5729 }
5730 } else if (!ST.hasSDWAOutModsVOPC()) {
5731 // No clamp allowed on GFX9 for VOPC
5732 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5733 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5734 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5735 return false;
5736 }
5737
5738 // No omod allowed on GFX9 for VOPC
5739 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5740 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5741 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5742 return false;
5743 }
5744 }
5745 }
5746
5747 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5748 if (DstUnused && DstUnused->isImm() &&
5749 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5750 const MachineOperand &Dst = MI.getOperand(DstIdx);
5751 if (!Dst.isReg() || !Dst.isTied()) {
5752 ErrInfo = "Dst register should have tied register";
5753 return false;
5754 }
5755
5756 const MachineOperand &TiedMO =
5757 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5758 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5759 ErrInfo =
5760 "Dst register should be tied to implicit use of preserved register";
5761 return false;
5762 }
5763 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5764 ErrInfo = "Dst register should use same physical register as preserved";
5765 return false;
5766 }
5767 }
5768 }
5769
5770 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5771 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5772 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5773 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5774 return false;
5775 }
5776 if (Src1MO.isImm()) {
5777 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5778 return false;
5779 }
5780 }
5781
5782 // Verify MIMG / VIMAGE / VSAMPLE
5783 if (isImage(Opcode) && !MI.mayStore()) {
5784 // Ensure that the return type used is large enough for all the options
5785 // being used TFE/LWE require an extra result register.
5786 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5787 if (DMask) {
5788 uint64_t DMaskImm = DMask->getImm();
5789 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5790 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5791 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5792 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5793
5794 // Adjust for packed 16 bit values
5795 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5796 RegCount = divideCeil(RegCount, 2);
5797
5798 // Adjust if using LWE or TFE
5799 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5800 RegCount += 1;
5801
5802 const uint32_t DstIdx =
5803 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5804 const MachineOperand &Dst = MI.getOperand(DstIdx);
5805 if (Dst.isReg()) {
5806 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5807 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5808 if (RegCount > DstSize) {
5809 ErrInfo = "Image instruction returns too many registers for dst "
5810 "register class";
5811 return false;
5812 }
5813 }
5814 }
5815 }
5816
5817 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5818 if (isVALU(MI, /*AllowLDSDMA=*/false) &&
5819 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5820 unsigned ConstantBusCount = 0;
5821 bool UsesLiteral = false;
5822 const MachineOperand *LiteralVal = nullptr;
5823
5824 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5825 if (ImmIdx != -1) {
5826 ++ConstantBusCount;
5827 UsesLiteral = true;
5828 LiteralVal = &MI.getOperand(ImmIdx);
5829 }
5830
5831 SmallVector<Register, 2> SGPRsUsed;
5832 Register SGPRUsed;
5833
5834 // Only look at the true operands. Only a real operand can use the constant
5835 // bus, and we don't want to check pseudo-operands like the source modifier
5836 // flags.
5837 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5838 if (OpIdx == -1)
5839 continue;
5840 const MachineOperand &MO = MI.getOperand(OpIdx);
5841 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5842 if (MO.isReg()) {
5843 SGPRUsed = MO.getReg();
5844 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5845 ++ConstantBusCount;
5846 SGPRsUsed.push_back(SGPRUsed);
5847 }
5848 } else if (!MO.isFI()) { // Treat FI like a register.
5849 if (!UsesLiteral) {
5850 ++ConstantBusCount;
5851 UsesLiteral = true;
5852 LiteralVal = &MO;
5853 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5854 assert(isVOP2(MI) || isVOP3(MI));
5855 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5856 return false;
5857 }
5858 }
5859 }
5860 }
5861
5862 SGPRUsed = findImplicitSGPRRead(MI);
5863 if (SGPRUsed) {
5864 // Implicit uses may safely overlap true operands
5865 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5866 return !RI.regsOverlap(SGPRUsed, SGPR);
5867 })) {
5868 ++ConstantBusCount;
5869 SGPRsUsed.push_back(SGPRUsed);
5870 }
5871 }
5872
5873 // v_writelane_b32 is an exception from constant bus restriction:
5874 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5875 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5876 Opcode != AMDGPU::V_WRITELANE_B32) {
5877 ErrInfo = "VOP* instruction violates constant bus restriction";
5878 return false;
5879 }
5880
5881 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5882 ErrInfo = "VOP3 instruction uses literal";
5883 return false;
5884 }
5885 }
5886
5887 // Special case for writelane - this can break the multiple constant bus rule,
5888 // but still can't use more than one SGPR register
5889 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5890 unsigned SGPRCount = 0;
5891 Register SGPRUsed;
5892
5893 for (int OpIdx : {Src0Idx, Src1Idx}) {
5894 if (OpIdx == -1)
5895 break;
5896
5897 const MachineOperand &MO = MI.getOperand(OpIdx);
5898
5899 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5900 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5901 if (MO.getReg() != SGPRUsed)
5902 ++SGPRCount;
5903 SGPRUsed = MO.getReg();
5904 }
5905 }
5906 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5907 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5908 return false;
5909 }
5910 }
5911 }
5912
5913 // Verify misc. restrictions on specific instructions.
5914 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5915 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5916 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5917 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5918 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
5919 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5920 if (!compareMachineOp(Src0, Src1) &&
5921 !compareMachineOp(Src0, Src2)) {
5922 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
5923 return false;
5924 }
5925 }
5926 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
5927 SISrcMods::ABS) ||
5928 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
5929 SISrcMods::ABS) ||
5930 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
5931 SISrcMods::ABS)) {
5932 ErrInfo = "ABS not allowed in VOP3B instructions";
5933 return false;
5934 }
5935 }
5936
5937 if (isSOP2(MI) || isSOPC(MI)) {
5938 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5939 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5940
5941 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
5942 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
5943 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
5944 !Src0.isIdenticalTo(Src1)) {
5945 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
5946 return false;
5947 }
5948 }
5949
5950 if (isSOPK(MI)) {
5951 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
5952 if (Desc.isBranch()) {
5953 if (!Op->isMBB()) {
5954 ErrInfo = "invalid branch target for SOPK instruction";
5955 return false;
5956 }
5957 } else {
5958 uint64_t Imm = Op->getImm();
5959 if (sopkIsZext(Opcode)) {
5960 if (!isUInt<16>(Imm)) {
5961 ErrInfo = "invalid immediate for SOPK instruction";
5962 return false;
5963 }
5964 } else {
5965 if (!isInt<16>(Imm)) {
5966 ErrInfo = "invalid immediate for SOPK instruction";
5967 return false;
5968 }
5969 }
5970 }
5971 }
5972
5973 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5974 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5975 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5976 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5977 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5978 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5979
5980 const unsigned StaticNumOps =
5981 Desc.getNumOperands() + Desc.implicit_uses().size();
5982 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5983
5984 // Require additional implicit operands. This allows a fixup done by the
5985 // post RA scheduler where the main implicit operand is killed and
5986 // implicit-defs are added for sub-registers that remain live after this
5987 // instruction.
5988 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5989 ErrInfo = "missing implicit register operands";
5990 return false;
5991 }
5992
5993 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5994 if (IsDst) {
5995 if (!Dst->isUse()) {
5996 ErrInfo = "v_movreld_b32 vdst should be a use operand";
5997 return false;
5998 }
5999
6000 unsigned UseOpIdx;
6001 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
6002 UseOpIdx != StaticNumOps + 1) {
6003 ErrInfo = "movrel implicit operands should be tied";
6004 return false;
6005 }
6006 }
6007
6008 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
6009 const MachineOperand &ImpUse
6010 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
6011 if (!ImpUse.isReg() || !ImpUse.isUse() ||
6012 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
6013 ErrInfo = "src0 should be subreg of implicit vector use";
6014 return false;
6015 }
6016 }
6017
6018 // Make sure we aren't losing exec uses in the td files. This mostly requires
6019 // being careful when using let Uses to try to add other use registers.
6020 if (shouldReadExec(MI)) {
6021 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
6022 ErrInfo = "VALU instruction does not implicitly read exec mask";
6023 return false;
6024 }
6025 }
6026
6027 if (isSMRD(MI)) {
6028 if (MI.mayStore() &&
6029 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
6030 // The register offset form of scalar stores may only use m0 as the
6031 // soffset register.
6032 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
6033 if (Soff && Soff->getReg() != AMDGPU::M0) {
6034 ErrInfo = "scalar stores must use m0 as offset register";
6035 return false;
6036 }
6037 }
6038 }
6039
6040 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
6041 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
6042 if (Offset->getImm() != 0) {
6043 ErrInfo = "subtarget does not support offsets in flat instructions";
6044 return false;
6045 }
6046 }
6047
6048 if (isDS(MI) && !ST.hasGDS()) {
6049 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
6050 if (GDSOp && GDSOp->getImm() != 0) {
6051 ErrInfo = "GDS is not supported on this subtarget";
6052 return false;
6053 }
6054 }
6055
6056 if (isImage(MI)) {
6057 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
6058 if (DimOp) {
6059 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
6060 AMDGPU::OpName::vaddr0);
6061 AMDGPU::OpName RSrcOpName =
6062 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
6063 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
6064 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
6065 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
6066 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
6067 const AMDGPU::MIMGDimInfo *Dim =
6069
6070 if (!Dim) {
6071 ErrInfo = "dim is out of range";
6072 return false;
6073 }
6074
6075 bool IsA16 = false;
6076 if (ST.hasR128A16()) {
6077 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
6078 IsA16 = R128A16->getImm() != 0;
6079 } else if (ST.hasA16()) {
6080 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
6081 IsA16 = A16->getImm() != 0;
6082 }
6083
6084 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
6085
6086 unsigned AddrWords =
6087 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
6088
6089 unsigned VAddrWords;
6090 if (IsNSA) {
6091 VAddrWords = RsrcIdx - VAddr0Idx;
6092 if (ST.hasPartialNSAEncoding() &&
6093 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
6094 unsigned LastVAddrIdx = RsrcIdx - 1;
6095 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
6096 }
6097 } else {
6098 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
6099 if (AddrWords > 12)
6100 AddrWords = 16;
6101 }
6102
6103 if (VAddrWords != AddrWords) {
6104 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
6105 << " but got " << VAddrWords << "\n");
6106 ErrInfo = "bad vaddr size";
6107 return false;
6108 }
6109 }
6110 }
6111
6112 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
6113 if (DppCt) {
6114 using namespace AMDGPU::DPP;
6115
6116 unsigned DC = DppCt->getImm();
6117 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6118 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6119 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6120 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6121 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6122 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6123 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6124 ErrInfo = "Invalid dpp_ctrl value";
6125 return false;
6126 }
6127 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6128 !ST.hasDPPWavefrontShifts()) {
6129 ErrInfo = "Invalid dpp_ctrl value: "
6130 "wavefront shifts are not supported on GFX10+";
6131 return false;
6132 }
6133 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6134 !ST.hasDPPBroadcasts()) {
6135 ErrInfo = "Invalid dpp_ctrl value: "
6136 "broadcasts are not supported on GFX10+";
6137 return false;
6138 }
6139 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6140 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
6141 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6142 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6143 !ST.hasGFX90AInsts()) {
6144 ErrInfo = "Invalid dpp_ctrl value: "
6145 "row_newbroadcast/row_share is not supported before "
6146 "GFX90A/GFX10";
6147 return false;
6148 }
6149 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6150 ErrInfo = "Invalid dpp_ctrl value: "
6151 "row_share and row_xmask are not supported before GFX10";
6152 return false;
6153 }
6154 }
6155
6156 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6158 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6159 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
6160 ErrInfo = "Invalid dpp_ctrl value: "
6161 "DP ALU dpp only support row_newbcast";
6162 return false;
6163 }
6164 }
6165
6166 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
6167 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
6168 AMDGPU::OpName DataName =
6169 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6170 const MachineOperand *Data = getNamedOperand(MI, DataName);
6171 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
6172 if (Data && !Data->isReg())
6173 Data = nullptr;
6174
6175 if (!ST.hasGFX90AInsts()) {
6176 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6177 (Data && RI.isAGPR(MRI, Data->getReg())) ||
6178 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
6179 ErrInfo = "Invalid register class: "
6180 "agpr loads and stores not supported on this GPU";
6181 return false;
6182 }
6183 }
6184 }
6185
6186 if (ST.needsAlignedVGPRs()) {
6187 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
6189 if (!Op)
6190 return true;
6191 Register Reg = Op->getReg();
6192 if (Reg.isPhysical())
6193 return !(RI.getHWRegIndex(Reg) & 1);
6194 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
6195 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6196 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
6197 };
6198
6199 if (isMIMG(MI)) {
6200 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6201 ErrInfo = "Subtarget requires even aligned vector registers "
6202 "for vaddr operand of image instructions";
6203 return false;
6204 }
6205 }
6206 }
6207
6208 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6209 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
6210 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6211 ErrInfo = "Invalid register class: "
6212 "v_accvgpr_write with an SGPR is not supported on this GPU";
6213 return false;
6214 }
6215 }
6216
6217 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6218 const MachineOperand &SrcOp = MI.getOperand(1);
6219 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
6220 ErrInfo = "pseudo expects only physical SGPRs";
6221 return false;
6222 }
6223 }
6224
6225 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
6226 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
6227 if (!ST.hasScaleOffset()) {
6228 ErrInfo = "Subtarget does not support offset scaling";
6229 return false;
6230 }
6231 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
6232 ErrInfo = "Instruction does not support offset scaling";
6233 return false;
6234 }
6235 }
6236 }
6237
6238 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6239 if (AMDGPU::isSingleSGPRReadInst(Opcode)) {
6240 for (unsigned I = 0; I < 3; ++I) {
6242 return false;
6243 }
6244 }
6245
6246 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
6247 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
6248 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
6249 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6250 &AMDGPU::SReg_64RegClass) ||
6251 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6252 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
6253 return false;
6254 }
6255 }
6256
6257 // GFX950 v_pk_{add,mul,fma}_f32 must not have an invalid op_sel.
6258 if (!isLegalPkF32OpSel(*this, MI)) {
6259 ErrInfo = "GFX950 v_pk_{add,mul,fma}_f32 has an invalid op_sel.";
6260 return false;
6261 }
6262
6263 return true;
6264}
6265
6267 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
6268 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6269 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
6270 ? AMDGPU::COPY
6271 : AMDGPU::V_MOV_B32_e32;
6272 }
6273 return getVALUOp(MI.getOpcode());
6274}
6275
6276// It is more readable to list mapped opcodes on the same line.
6277// clang-format off
6278
6279unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
6280 switch (Opc) {
6281 default: return AMDGPU::INSTRUCTION_LIST_END;
6282 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
6283 case AMDGPU::COPY: return AMDGPU::COPY;
6284 case AMDGPU::PHI: return AMDGPU::PHI;
6285 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
6286 case AMDGPU::WQM: return AMDGPU::WQM;
6287 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
6288 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
6289 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
6290 case AMDGPU::S_ADD_I32:
6291 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6292 case AMDGPU::S_ADDC_U32:
6293 return AMDGPU::V_ADDC_U32_e32;
6294 case AMDGPU::S_SUB_I32:
6295 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6296 // FIXME: These are not consistently handled, and selected when the carry is
6297 // used.
6298 case AMDGPU::S_ADD_U32:
6299 return AMDGPU::V_ADD_CO_U32_e32;
6300 case AMDGPU::S_SUB_U32:
6301 return AMDGPU::V_SUB_CO_U32_e32;
6302 case AMDGPU::S_ADD_U64_PSEUDO:
6303 return AMDGPU::V_ADD_U64_PSEUDO;
6304 case AMDGPU::S_SUB_U64_PSEUDO:
6305 return AMDGPU::V_SUB_U64_PSEUDO;
6306 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
6307 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
6308 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
6309 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
6310 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
6311 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
6312 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
6313 case AMDGPU::S_XNOR_B32:
6314 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6315 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
6316 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
6317 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
6318 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
6319 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
6320 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
6321 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
6322 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
6323 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
6324 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
6325 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
6326 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
6327 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
6328 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
6329 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
6330 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
6331 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
6332 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
6333 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
6334 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
6335 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
6336 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
6337 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
6338 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
6339 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
6340 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
6341 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
6342 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
6343 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
6344 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
6345 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
6346 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
6347 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
6348 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
6349 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
6350 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
6351 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
6352 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
6353 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
6354 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
6355 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
6356 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
6357 case AMDGPU::S_CVT_F32_F16:
6358 case AMDGPU::S_CVT_HI_F32_F16:
6359 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6360 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6361 case AMDGPU::S_CVT_F16_F32:
6362 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6363 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6364 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
6365 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
6366 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
6367 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
6368 case AMDGPU::S_CEIL_F16:
6369 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6370 : AMDGPU::V_CEIL_F16_fake16_e64;
6371 case AMDGPU::S_FLOOR_F16:
6372 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6373 : AMDGPU::V_FLOOR_F16_fake16_e64;
6374 case AMDGPU::S_TRUNC_F16:
6375 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6376 : AMDGPU::V_TRUNC_F16_fake16_e64;
6377 case AMDGPU::S_RNDNE_F16:
6378 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6379 : AMDGPU::V_RNDNE_F16_fake16_e64;
6380 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6381 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6382 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6383 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6384 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6385 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6386 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6387 case AMDGPU::S_ADD_F16:
6388 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6389 : AMDGPU::V_ADD_F16_fake16_e64;
6390 case AMDGPU::S_SUB_F16:
6391 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6392 : AMDGPU::V_SUB_F16_fake16_e64;
6393 case AMDGPU::S_MIN_F16:
6394 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6395 : AMDGPU::V_MIN_F16_fake16_e64;
6396 case AMDGPU::S_MAX_F16:
6397 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6398 : AMDGPU::V_MAX_F16_fake16_e64;
6399 case AMDGPU::S_MINIMUM_F16:
6400 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6401 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6402 case AMDGPU::S_MAXIMUM_F16:
6403 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6404 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6405 case AMDGPU::S_MUL_F16:
6406 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6407 : AMDGPU::V_MUL_F16_fake16_e64;
6408 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6409 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6410 case AMDGPU::S_FMAC_F16:
6411 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6412 : AMDGPU::V_FMAC_F16_fake16_e64;
6413 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6414 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6415 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6416 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6417 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6418 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6419 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6420 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6421 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6422 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6423 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6424 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6425 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6426 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6427 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6428 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6429 case AMDGPU::S_CMP_LT_F16:
6430 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6431 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6432 case AMDGPU::S_CMP_EQ_F16:
6433 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6434 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6435 case AMDGPU::S_CMP_LE_F16:
6436 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6437 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6438 case AMDGPU::S_CMP_GT_F16:
6439 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6440 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6441 case AMDGPU::S_CMP_LG_F16:
6442 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6443 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6444 case AMDGPU::S_CMP_GE_F16:
6445 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6446 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6447 case AMDGPU::S_CMP_O_F16:
6448 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6449 : AMDGPU::V_CMP_O_F16_fake16_e64;
6450 case AMDGPU::S_CMP_U_F16:
6451 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6452 : AMDGPU::V_CMP_U_F16_fake16_e64;
6453 case AMDGPU::S_CMP_NGE_F16:
6454 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6455 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6456 case AMDGPU::S_CMP_NLG_F16:
6457 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6458 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6459 case AMDGPU::S_CMP_NGT_F16:
6460 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6461 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6462 case AMDGPU::S_CMP_NLE_F16:
6463 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6464 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6465 case AMDGPU::S_CMP_NEQ_F16:
6466 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6467 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6468 case AMDGPU::S_CMP_NLT_F16:
6469 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6470 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6471 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6472 case AMDGPU::V_S_EXP_F16_e64:
6473 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6474 : AMDGPU::V_EXP_F16_fake16_e64;
6475 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6476 case AMDGPU::V_S_LOG_F16_e64:
6477 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6478 : AMDGPU::V_LOG_F16_fake16_e64;
6479 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6480 case AMDGPU::V_S_RCP_F16_e64:
6481 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6482 : AMDGPU::V_RCP_F16_fake16_e64;
6483 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6484 case AMDGPU::V_S_RSQ_F16_e64:
6485 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6486 : AMDGPU::V_RSQ_F16_fake16_e64;
6487 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6488 case AMDGPU::V_S_SQRT_F16_e64:
6489 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6490 : AMDGPU::V_SQRT_F16_fake16_e64;
6491 }
6493 "Unexpected scalar opcode without corresponding vector one!");
6494}
6495
6496// clang-format on
6497
6501 const DebugLoc &DL, Register Reg,
6502 bool IsSCCLive,
6503 SlotIndexes *Indexes) const {
6504 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6505 const SIInstrInfo *TII = ST.getInstrInfo();
6507 if (IsSCCLive) {
6508 // Insert two move instructions, one to save the original value of EXEC and
6509 // the other to turn on all bits in EXEC. This is required as we can't use
6510 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6511 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6513 auto FlipExecMI =
6514 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6515 if (Indexes) {
6516 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6517 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6518 }
6519 } else {
6520 auto SaveExec =
6521 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6522 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6523 if (Indexes)
6524 Indexes->insertMachineInstrInMaps(*SaveExec);
6525 }
6526}
6527
6530 const DebugLoc &DL, Register Reg,
6531 SlotIndexes *Indexes) const {
6533 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6534 .addReg(Reg, RegState::Kill);
6535 if (Indexes)
6536 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6537}
6538
6542 "Not a whole wave func");
6543 MachineBasicBlock &MBB = *MF.begin();
6544 for (MachineInstr &MI : MBB)
6545 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6546 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6547 return &MI;
6548
6549 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6550}
6551
6553 unsigned OpNo) const {
6554 const MCInstrDesc &Desc = get(MI.getOpcode());
6555 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6556 Desc.operands()[OpNo].RegClass == -1) {
6557 Register Reg = MI.getOperand(OpNo).getReg();
6558
6559 if (Reg.isVirtual()) {
6560 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6561 return MRI.getRegClass(Reg);
6562 }
6563 return RI.getPhysRegBaseClass(Reg);
6564 }
6565
6566 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6567 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6568}
6569
6570// Convert VOP3 operand index to source number.
6571static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx) {
6572 constexpr AMDGPU::OpName OpNames[] = {
6573 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6574
6575 for (auto [I, OpName] : enumerate(OpNames)) {
6576 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6577 if (static_cast<unsigned>(SrcIdx) == OpIdx)
6578 return I;
6579 }
6580
6581 return UINT_MAX;
6582}
6583
6586 MachineBasicBlock *MBB = MI.getParent();
6587 MachineOperand &MO = MI.getOperand(OpIdx);
6588 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6589 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6590 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6591 unsigned Size = RI.getRegSizeInBits(*RC);
6592 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6593 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6594 : AMDGPU::V_MOV_B32_e32;
6595 if (MO.isReg())
6596 Opcode = AMDGPU::COPY;
6597 else if (RI.isSGPRClass(RC))
6598 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6599
6600 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6601 Register Reg = MRI.createVirtualRegister(VRC);
6602 DebugLoc DL = MBB->findDebugLoc(I);
6603
6604 if (Size == 128 && AMDGPU::isPackedSingleSGPR64BitInst(MI.getOpcode()) &&
6606 // Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
6607 // sources behave like OPSEL is set replicating low 64-bits into high. VGPR
6608 // sources in turn read actual 4 registers. To move operand from an SGPR to
6609 // a VGPR we need to replicate low half.
6610 // We also do not select immediates for these instructions so it always has
6611 // to be an SGPR register here.
6612 // Operands which are not legal as per isLegalSingleSGPRReadInstOperand()
6613 // sent here specifically to fix a non-splat SGPR and shall perform a full
6614 // copy.
6615
6616 const TargetRegisterClass *VRC64 = RI.getVGPRClassForBitWidth(64);
6617 Register Low64 = MRI.createVirtualRegister(VRC64);
6618 assert(MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()));
6619 BuildMI(*MBB, I, DL, get(TargetOpcode::COPY), Low64)
6620 .addReg(MO.getReg(), {}, AMDGPU::sub0_sub1);
6621 BuildMI(*MBB, I, DL, get(TargetOpcode::REG_SEQUENCE), Reg)
6622 .addReg(Low64)
6623 .addImm(AMDGPU::sub0_sub1)
6624 .addReg(Low64)
6625 .addImm(AMDGPU::sub2_sub3);
6626 } else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6627 BuildMI(*MBB, I, DL, get(Opcode), Reg)
6628 .addImm(0) // src0_modifiers
6629 .add(MO)
6630 .addImm(0); // op_sel
6631 } else {
6632 BuildMI(*MBB, I, DL, get(Opcode), Reg).add(MO);
6633 }
6634
6635 MO.ChangeToRegister(Reg, false);
6636}
6637
6640 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6641 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6642 if (!SuperReg.getReg().isVirtual())
6643 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6644
6645 MachineBasicBlock *MBB = MI->getParent();
6646 const DebugLoc &DL = MI->getDebugLoc();
6647 Register SubReg = MRI.createVirtualRegister(SubRC);
6648
6649 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6650 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6651 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6652 return SubReg;
6653}
6654
6657 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6658 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6659 if (Op.isImm()) {
6660 if (SubIdx == AMDGPU::sub0)
6661 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6662 if (SubIdx == AMDGPU::sub1)
6663 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6664
6665 llvm_unreachable("Unhandled register index for immediate");
6666 }
6667
6668 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6669 SubIdx, SubRC);
6670 return MachineOperand::CreateReg(SubReg, false);
6671}
6672
6673// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6674void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6675 assert(Inst.getNumExplicitOperands() == 3);
6676 MachineOperand Op1 = Inst.getOperand(1);
6677 Inst.removeOperand(1);
6678 Inst.addOperand(Op1);
6679}
6680
6682 const MCOperandInfo &OpInfo,
6683 const MachineOperand &MO) const {
6684 if (!MO.isReg())
6685 return false;
6686
6687 Register Reg = MO.getReg();
6688
6689 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6690 if (Reg.isPhysical())
6691 return DRC->contains(Reg);
6692
6693 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6694
6695 if (MO.getSubReg()) {
6696 const TargetRegisterClass *SuperRC =
6697 RI.getLargestLegalSuperClass(RC, MRI.getMF());
6698 if (!SuperRC)
6699 return false;
6700 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6701 }
6702
6703 return RI.getCommonSubClass(DRC, RC) != nullptr;
6704}
6705
6707 const MachineOperand &MO) const {
6708 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6709 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6710 unsigned Opc = MI.getOpcode();
6711
6712 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6713 if (MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
6714 AMDGPU::isSingleSGPRReadInst(MI.getOpcode()) &&
6716 &MO))
6717 return false;
6718
6719 if (!isLegalRegOperand(MRI, OpInfo, MO))
6720 return false;
6721
6722 // check Accumulate GPR operand
6723 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6724 if (IsAGPR && !ST.hasMAIInsts())
6725 return false;
6726 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6727 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6728 return false;
6729 // Atomics should have both vdst and vdata either vgpr or agpr.
6730 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6731 const int DataIdx = AMDGPU::getNamedOperandIdx(
6732 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6733 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6734 MI.getOperand(DataIdx).isReg() &&
6735 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6736 return false;
6737 if ((int)OpIdx == DataIdx) {
6738 if (VDstIdx != -1 &&
6739 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6740 return false;
6741 // DS instructions with 2 src operands also must have tied RC.
6742 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6743 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6744 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6745 return false;
6746 }
6747
6748 // Check V_ACCVGPR_WRITE_B32_e64
6749 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6750 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6751 RI.isSGPRReg(MRI, MO.getReg()))
6752 return false;
6753
6754 if (ST.hasFlatScratchHiInB64InstHazard() &&
6755 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6756 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6757 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6758 64)
6759 return false;
6760 }
6761 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6762 return false;
6763 }
6764 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6765 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6766 return false;
6767
6768 return true;
6769}
6770
6772 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6773 const MachineOperand *MO) const {
6774 constexpr unsigned NumOps = 3;
6775 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6776 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6777 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6778 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6779
6780 assert(SrcN < NumOps);
6781
6782 if (!MO) {
6783 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6784 if (SrcIdx == -1)
6785 return true;
6786 MO = &MI.getOperand(SrcIdx);
6787 }
6788
6789 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6790 return true;
6791
6792 int ModsIdx =
6793 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6794 if (ModsIdx == -1)
6795 return false;
6796
6797 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6798 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6799 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6800
6801 return !OpSel && !OpSelHi;
6802}
6803
6804bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
6805 const MachineOperand *MO) const {
6806 const MachineFunction &MF = *MI.getMF();
6807 const MachineRegisterInfo &MRI = MF.getRegInfo();
6808 const MCInstrDesc &InstDesc = MI.getDesc();
6809 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6810 int64_t RegClass = getOpRegClassID(OpInfo);
6811 const TargetRegisterClass *DefinedRC =
6812 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6813 if (!MO)
6814 MO = &MI.getOperand(OpIdx);
6815
6816 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6817
6818 if (isVALU(MI, /*AllowLDSDMA=*/false) && !IsInlineConst &&
6819 usesConstantBus(MRI, *MO, OpInfo)) {
6820 const MachineOperand *UsedLiteral = nullptr;
6821
6822 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6823 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6824
6825 // TODO: Be more permissive with frame indexes.
6826 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6827 if (!LiteralLimit--)
6828 return false;
6829
6830 UsedLiteral = MO;
6831 }
6832
6834 if (MO->isReg())
6835 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6836
6837 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6838 if (i == OpIdx)
6839 continue;
6840 const MachineOperand &Op = MI.getOperand(i);
6841 if (Op.isReg()) {
6842 if (Op.isUse()) {
6843 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6844 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6845 if (--ConstantBusLimit <= 0)
6846 return false;
6847 }
6848 }
6849 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6850 !isInlineConstant(Op, InstDesc.operands()[i])) {
6851 // The same literal may be used multiple times.
6852 if (!UsedLiteral)
6853 UsedLiteral = &Op;
6854 else if (UsedLiteral->isIdenticalTo(Op))
6855 continue;
6856
6857 if (!LiteralLimit--)
6858 return false;
6859 if (--ConstantBusLimit <= 0)
6860 return false;
6861 }
6862 }
6863 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6864 // There can be at most one literal operand, but it can be repeated.
6865 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6866 if (i == OpIdx)
6867 continue;
6868 const MachineOperand &Op = MI.getOperand(i);
6869 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6870 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6871 !Op.isIdenticalTo(*MO))
6872 return false;
6873
6874 // Do not fold a non-inlineable and non-register operand into an
6875 // instruction that already has a frame index. The frame index handling
6876 // code could not handle well when a frame index co-exists with another
6877 // non-register operand, unless that operand is an inlineable immediate.
6878 if (Op.isFI())
6879 return false;
6880 }
6881 }
6882
6883 if (MO->isReg()) {
6884 if (!DefinedRC)
6885 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6886 return isLegalRegOperand(MI, OpIdx, *MO);
6887 }
6888
6889 if (MO->isImm()) {
6890 uint64_t Imm = MO->getImm();
6891 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6892 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6893 bool Is64BitOp = Is64BitFPOp ||
6894 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6895 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6896 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6897 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6898 if (Is64BitOp &&
6899 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6900 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6901 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6902 return false;
6903
6904 // FIXME: We can use sign extended 64-bit literals, but only for signed
6905 // operands. At the moment we do not know if an operand is signed.
6906 // Such operand will be encoded as its low 32 bits and then either
6907 // correctly sign extended or incorrectly zero extended by HW.
6908 // If 64-bit literals are supported and the literal will be encoded
6909 // as full 64 bit we still can use it.
6910 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6911 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
6912 return false;
6913 }
6914 }
6915
6916 // Handle non-register types that are treated like immediates.
6917 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
6918
6919 if (!DefinedRC) {
6920 // This operand expects an immediate.
6921 return true;
6922 }
6923
6924 return isImmOperandLegal(MI, OpIdx, *MO);
6925}
6926
6928 bool IsGFX950Only = ST.hasGFX950Insts();
6929 bool IsGFX940Only = ST.hasGFX940Insts();
6930
6931 if (!IsGFX950Only && !IsGFX940Only)
6932 return false;
6933
6934 if (!isVALU(MI, /*AllowLDSDMA=*/false))
6935 return false;
6936
6937 // V_COS, V_EXP, V_RCP, etc.
6938 if (isTRANS(MI))
6939 return true;
6940
6941 // DOT2, DOT2C, DOT4, etc.
6942 if (isDOT(MI))
6943 return true;
6944
6945 // MFMA, SMFMA
6946 if (isMFMA(MI))
6947 return true;
6948
6949 unsigned Opcode = MI.getOpcode();
6950 switch (Opcode) {
6951 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6952 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6953 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6954 case AMDGPU::V_MQSAD_U32_U8_e64:
6955 case AMDGPU::V_PK_ADD_F16:
6956 case AMDGPU::V_PK_ADD_F32:
6957 case AMDGPU::V_PK_ADD_I16:
6958 case AMDGPU::V_PK_ADD_U16:
6959 case AMDGPU::V_PK_ASHRREV_I16:
6960 case AMDGPU::V_PK_FMA_F16:
6961 case AMDGPU::V_PK_FMA_F32:
6962 case AMDGPU::V_PK_FMAC_F16_e32:
6963 case AMDGPU::V_PK_FMAC_F16_e64:
6964 case AMDGPU::V_PK_LSHLREV_B16:
6965 case AMDGPU::V_PK_LSHRREV_B16:
6966 case AMDGPU::V_PK_MAD_I16:
6967 case AMDGPU::V_PK_MAD_U16:
6968 case AMDGPU::V_PK_MAX_F16:
6969 case AMDGPU::V_PK_MAX_I16:
6970 case AMDGPU::V_PK_MAX_U16:
6971 case AMDGPU::V_PK_MIN_F16:
6972 case AMDGPU::V_PK_MIN_I16:
6973 case AMDGPU::V_PK_MIN_U16:
6974 case AMDGPU::V_PK_MOV_B32:
6975 case AMDGPU::V_PK_MUL_F16:
6976 case AMDGPU::V_PK_MUL_F32:
6977 case AMDGPU::V_PK_MUL_LO_U16:
6978 case AMDGPU::V_PK_SUB_I16:
6979 case AMDGPU::V_PK_SUB_U16:
6980 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6981 return true;
6982 default:
6983 return false;
6984 }
6985}
6986
6988 MachineInstr &MI) const {
6989 unsigned Opc = MI.getOpcode();
6990 const MCInstrDesc &InstrDesc = get(Opc);
6991
6992 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
6993 MachineOperand &Src0 = MI.getOperand(Src0Idx);
6994
6995 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
6996 MachineOperand &Src1 = MI.getOperand(Src1Idx);
6997
6998 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
6999 // we need to only have one constant bus use before GFX10.
7000 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
7001 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
7002 RI.isSGPRReg(MRI, Src0.getReg()))
7003 legalizeOpWithMove(MI, Src0Idx);
7004
7005 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
7006 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
7007 // src0/src1 with V_READFIRSTLANE.
7008 if (Opc == AMDGPU::V_WRITELANE_B32) {
7009 const DebugLoc &DL = MI.getDebugLoc();
7010 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
7011 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7012 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7013 .add(Src0);
7014 Src0.ChangeToRegister(Reg, false);
7015 }
7016 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
7017 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7018 const DebugLoc &DL = MI.getDebugLoc();
7019 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7020 .add(Src1);
7021 Src1.ChangeToRegister(Reg, false);
7022 }
7023 return;
7024 }
7025
7026 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
7027 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
7028 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
7029 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
7030 legalizeOpWithMove(MI, Src2Idx);
7031 }
7032
7033 // VOP2 src0 instructions support all operand types, so we don't need to check
7034 // their legality. If src1 is already legal, we don't need to do anything.
7035 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
7036 return;
7037
7038 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
7039 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
7040 // select is uniform.
7041 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
7042 RI.isVGPR(MRI, Src1.getReg())) {
7043 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7044 const DebugLoc &DL = MI.getDebugLoc();
7045 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7046 .add(Src1);
7047 Src1.ChangeToRegister(Reg, false);
7048 return;
7049 }
7050
7051 // We do not use commuteInstruction here because it is too aggressive and will
7052 // commute if it is possible. We only want to commute here if it improves
7053 // legality. This can be called a fairly large number of times so don't waste
7054 // compile time pointlessly swapping and checking legality again.
7055 if (HasImplicitSGPR || !MI.isCommutable()) {
7056 legalizeOpWithMove(MI, Src1Idx);
7057 return;
7058 }
7059
7060 // If src0 can be used as src1, commuting will make the operands legal.
7061 // Otherwise we have to give up and insert a move.
7062 //
7063 // TODO: Other immediate-like operand kinds could be commuted if there was a
7064 // MachineOperand::ChangeTo* for them.
7065 if ((!Src1.isImm() && !Src1.isReg()) ||
7066 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
7067 legalizeOpWithMove(MI, Src1Idx);
7068 return;
7069 }
7070
7071 int CommutedOpc = commuteOpcode(MI);
7072 if (CommutedOpc == -1) {
7073 legalizeOpWithMove(MI, Src1Idx);
7074 return;
7075 }
7076
7077 MI.setDesc(get(CommutedOpc));
7078
7079 Register Src0Reg = Src0.getReg();
7080 unsigned Src0SubReg = Src0.getSubReg();
7081 bool Src0Kill = Src0.isKill();
7082
7083 if (Src1.isImm())
7084 Src0.ChangeToImmediate(Src1.getImm());
7085 else if (Src1.isReg()) {
7086 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
7087 Src0.setSubReg(Src1.getSubReg());
7088 } else
7089 llvm_unreachable("Should only have register or immediate operands");
7090
7091 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
7092 Src1.setSubReg(Src0SubReg);
7094}
7095
7096// Legalize VOP3 operands. All operand types are supported for any operand
7097// but only one literal constant and only starting from GFX10.
7099 MachineInstr &MI) const {
7100 unsigned Opc = MI.getOpcode();
7101
7102 int VOP3Idx[3] = {
7103 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
7104 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
7105 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
7106 };
7107
7108 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7109 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7110 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7111 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7112 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7113 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7114 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7115 // src1 and src2 must be scalar
7116 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
7117 const DebugLoc &DL = MI.getDebugLoc();
7118 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
7119 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7120 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7121 .add(Src1);
7122 Src1.ChangeToRegister(Reg, false);
7123 }
7124 if (VOP3Idx[2] != -1) {
7125 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
7126 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
7127 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7128 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7129 .add(Src2);
7130 Src2.ChangeToRegister(Reg, false);
7131 }
7132 }
7133 }
7134
7135 // Find the one SGPR operand we are allowed to use.
7136 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
7137 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7138 SmallDenseSet<unsigned> SGPRsUsed;
7139 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
7140 if (SGPRReg) {
7141 SGPRsUsed.insert(SGPRReg);
7142 --ConstantBusLimit;
7143 }
7144
7145 for (int Idx : VOP3Idx) {
7146 if (Idx == -1)
7147 break;
7148 MachineOperand &MO = MI.getOperand(Idx);
7149
7150 if (!MO.isReg()) {
7151 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
7152 continue;
7153
7154 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7155 --LiteralLimit;
7156 --ConstantBusLimit;
7157 continue;
7158 }
7159
7160 --LiteralLimit;
7161 --ConstantBusLimit;
7162 legalizeOpWithMove(MI, Idx);
7163 continue;
7164 }
7165
7166 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
7167 continue; // VGPRs are legal
7168
7169 // We can use one SGPR in each VOP3 instruction prior to GFX10
7170 // and two starting from GFX10.
7171 if (SGPRsUsed.count(MO.getReg()))
7172 continue;
7173 if (ConstantBusLimit > 0) {
7174 SGPRsUsed.insert(MO.getReg());
7175 --ConstantBusLimit;
7176 continue;
7177 }
7178
7179 // If we make it this far, then the operand is not legal and we must
7180 // legalize it.
7181 legalizeOpWithMove(MI, Idx);
7182 }
7183
7184 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
7185 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
7186 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
7187 Opc == AMDGPU::V_FMAC_F16_t16_e64) &&
7188 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
7189 legalizeOpWithMove(MI, VOP3Idx[2]);
7190
7191 // Fix the register class of single-sgpr-read instructions on gfx12+. See
7192 // SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
7194 for (unsigned I = 0; I < 3; ++I) {
7195 if (!isLegalSingleSGPRReadInstOperand(MRI, MI, /*SrcN=*/I))
7196 legalizeOpWithMove(MI, VOP3Idx[I]);
7197 }
7198 }
7199}
7200
7203 const TargetRegisterClass *DstRC /*=nullptr*/) const {
7204 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
7205 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
7206 if (DstRC)
7207 SRC = RI.getCommonSubClass(SRC, DstRC);
7208
7209 Register DstReg = MRI.createVirtualRegister(SRC);
7210 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7211
7212 if (RI.hasAGPRs(VRC)) {
7213 VRC = RI.getEquivalentVGPRClass(VRC);
7214 Register NewSrcReg = MRI.createVirtualRegister(VRC);
7215 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7216 get(TargetOpcode::COPY), NewSrcReg)
7217 .addReg(SrcReg);
7218 SrcReg = NewSrcReg;
7219 }
7220
7221 if (SubRegs == 1) {
7222 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7223 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7224 .addReg(SrcReg);
7225 return DstReg;
7226 }
7227
7229 for (unsigned i = 0; i < SubRegs; ++i) {
7230 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7231 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7232 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7233 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7234 SRegs.push_back(SGPR);
7235 }
7236
7238 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7239 get(AMDGPU::REG_SEQUENCE), DstReg);
7240 for (unsigned i = 0; i < SubRegs; ++i) {
7241 MIB.addReg(SRegs[i]);
7242 MIB.addImm(RI.getSubRegFromChannel(i));
7243 }
7244 return DstReg;
7245}
7246
7248 MachineInstr &MI) const {
7249
7250 // If the pointer is store in VGPRs, then we need to move them to
7251 // SGPRs using v_readfirstlane. This is safe because we only select
7252 // loads with uniform pointers to SMRD instruction so we know the
7253 // pointer value is uniform.
7254 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
7255 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
7256 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
7257 SBase->setReg(SGPR);
7258 }
7259 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
7260 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
7261 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
7262 SOff->setReg(SGPR);
7263 }
7264}
7265
7267 unsigned Opc = Inst.getOpcode();
7268 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
7269 if (OldSAddrIdx < 0)
7270 return false;
7271
7272 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
7273
7274 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
7275 if (NewOpc < 0)
7277 if (NewOpc < 0)
7278 return false;
7279
7281 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
7282 if (RI.isSGPRReg(MRI, SAddr.getReg()))
7283 return false;
7284
7285 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7286 if (NewVAddrIdx < 0)
7287 return false;
7288
7289 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
7290
7291 // Check vaddr, it shall be zero or absent.
7292 MachineInstr *VAddrDef = nullptr;
7293 if (OldVAddrIdx >= 0) {
7294 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
7295 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
7296 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
7297 !VAddrDef->getOperand(1).isImm() ||
7298 VAddrDef->getOperand(1).getImm() != 0)
7299 return false;
7300 }
7301
7302 const MCInstrDesc &NewDesc = get(NewOpc);
7303 Inst.setDesc(NewDesc);
7304
7305 // Callers expect iterator to be valid after this call, so modify the
7306 // instruction in place.
7307 if (OldVAddrIdx == NewVAddrIdx) {
7308 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
7309 // Clear use list from the old vaddr holding a zero register.
7310 MRI.removeRegOperandFromUseList(&NewVAddr);
7311 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7312 Inst.removeOperand(OldSAddrIdx);
7313 // Update the use list with the pointer we have just moved from vaddr to
7314 // saddr position. Otherwise new vaddr will be missing from the use list.
7315 MRI.removeRegOperandFromUseList(&NewVAddr);
7316 MRI.addRegOperandToUseList(&NewVAddr);
7317 } else {
7318 assert(OldSAddrIdx == NewVAddrIdx);
7319
7320 if (OldVAddrIdx >= 0) {
7321 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7322 AMDGPU::OpName::vdst_in);
7323
7324 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
7325 // it asserts. Untie the operands for now and retie them afterwards.
7326 if (NewVDstIn != -1) {
7327 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
7328 Inst.untieRegOperand(OldVDstIn);
7329 }
7330
7331 Inst.removeOperand(OldVAddrIdx);
7332
7333 if (NewVDstIn != -1) {
7334 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7335 Inst.tieOperands(NewVDst, NewVDstIn);
7336 }
7337 }
7338 }
7339
7340 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
7341 VAddrDef->eraseFromParent();
7342
7343 return true;
7344}
7345
7346// FIXME: Remove this when SelectionDAG is obsoleted.
7348 MachineInstr &MI) const {
7349 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
7350 return;
7351
7352 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
7353 // thinks they are uniform, so a readfirstlane should be valid.
7354 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
7355 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
7356 return;
7357
7359 return;
7360
7361 const TargetRegisterClass *DeclaredRC =
7362 getRegClass(MI.getDesc(), SAddr->getOperandNo());
7363
7364 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
7365 SAddr->setReg(ToSGPR);
7366}
7367
7370 const TargetRegisterClass *DstRC,
7373 const DebugLoc &DL) const {
7374 Register OpReg = Op.getReg();
7375 unsigned OpSubReg = Op.getSubReg();
7376
7377 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
7378 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7379
7380 // Check if operand is already the correct register class.
7381 if (DstRC == OpRC)
7382 return;
7383
7384 Register DstReg = MRI.createVirtualRegister(DstRC);
7385 auto Copy = BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg)
7386 .addReg(OpReg, {}, OpSubReg);
7387 Op.setReg(DstReg);
7388 Op.setSubReg(AMDGPU::NoSubRegister);
7389
7390 MachineInstr *Def = MRI.getVRegDef(OpReg);
7391 if (!Def)
7392 return;
7393
7394 // Try to eliminate the copy if it is copying an immediate value.
7395 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7396 foldImmediate(*Copy, *Def, OpReg, &MRI);
7397
7398 bool ImpDef = Def->isImplicitDef();
7399 while (!ImpDef && Def && Def->isCopy()) {
7400 if (Def->getOperand(1).getReg().isPhysical())
7401 break;
7402 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7403 ImpDef = Def && Def->isImplicitDef();
7404 }
7405 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7406 !ImpDef)
7407 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7408}
7409
7410// Emit the actual waterfall loop, executing the wrapped instruction for each
7411// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7412// iteration, in the worst case we execute 64 (once per lane).
7415 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7416 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7417 MachineFunction &MF = *LoopBB.getParent();
7419 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7421 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7422
7423 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7424 // available. Otherwise, use the previous pattern of v_cmp_eq,
7425 // s_and_saveexec, and s_xor.
7426 bool UseNewExecInstructions =
7427 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7428
7430 Register CondReg;
7431
7432 Register PhiExec;
7433 Register NewExec;
7434
7435 if (UseNewExecInstructions) {
7436 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7437 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7438 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7439 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7440 .addReg(LMC.ExecReg);
7441
7442 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7443 .addReg(InitExec)
7444 .addMBB(&PredBB)
7445 .addReg(NewExec)
7446 .addMBB(&BodyBB);
7447 }
7448
7449 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7450 // involves a trade-off between register pressure and latency:
7451 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7452 // register pressure because arguments and results of all
7453 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7454 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7455 // increase latency by placing v_readfirstlane instructions
7456 // immediately before v_cmpx instruction that directly depend on it.
7457 ///
7458 // Emitting interleaved v_cmpx and v_readfirstlane requires
7459 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7460 // v_cmpx needs to be treated as terminator until after register allocation
7461 // (spill placement) and instruction reordering.
7462 //
7463 // Current implementation defers v_cmpx and leaves other instruction
7464 // scheduling decisions to later passes, where register pressure is known or
7465 // easier to approximate.
7466 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7467 // v_cmpx instructions are inserted at the end of LoopBB.
7468 // After the first v_cmpx is emitted, I is updated to point to it
7469 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7470 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7471 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7472 unsigned NumSubRegs = RegSize / 32;
7473 Register VScalarOp = ScalarOp->getReg();
7474
7475 const TargetRegisterClass *RFLSrcRC =
7476 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7477
7478 if (NumSubRegs == 1) {
7479 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7480 if (const TargetRegisterClass *Common =
7481 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7482 Common != VScalarOpRC) {
7483 Register VRReg = MRI.createVirtualRegister(Common);
7484 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7485 VScalarOp = VRReg;
7486 }
7487 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7488
7489 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7490 .addReg(VScalarOp);
7491
7492 if (UseNewExecInstructions) {
7493 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7494 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7495 .addReg(CurReg)
7496 .addReg(VScalarOp);
7497 if (I == LoopBB.end())
7498 I = CmpxMI.getInstr()->getIterator();
7499 } else {
7500 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7501
7502 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7503 .addReg(CurReg)
7504 .addReg(VScalarOp);
7505
7506 // Combine the comparison results with AND.
7507 if (!CondReg) { // First.
7508 CondReg = NewCondReg;
7509 } else { // If not the first, we create an AND.
7510 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7511 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7512 .addReg(CondReg)
7513 .addReg(NewCondReg)
7514 .setOperandDead(3);
7515 CondReg = AndReg;
7516 }
7517 }
7518
7519 // Update ScalarOp operand to use the SGPR ScalarOp.
7520 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7521 ScalarOp->setReg(CurReg);
7522 else {
7523 // Insert into the same block of use
7524 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7525 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7526 .addReg(CurReg);
7527 ScalarOp->setReg(PhySGPRs[Idx]);
7528 }
7529 } else {
7530 SmallVector<Register, 8> ReadlanePieces;
7531 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7532 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7533 "Unhandled register size");
7534
7535 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7536 Register CurRegLo =
7537 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7538 Register CurRegHi =
7539 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7540
7541 // Read the next variant <- also loop target.
7542 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7543 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7544
7545 // Read the next variant <- also loop target.
7546 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7547 .addReg(VScalarOp, VScalarOpUndef,
7548 TRI->getSubRegFromChannel(Idx + 1));
7549
7550 ReadlanePieces.push_back(CurRegLo);
7551 ReadlanePieces.push_back(CurRegHi);
7552
7553 // Comparison is to be done as 64-bit.
7554 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7555 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7556 .addReg(CurRegLo)
7557 .addImm(AMDGPU::sub0)
7558 .addReg(CurRegHi)
7559 .addImm(AMDGPU::sub1);
7560
7561 unsigned SubReg =
7562 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7563
7564 if (UseNewExecInstructions) {
7565 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7566 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7567 .addReg(CurReg)
7568 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7569 if (I == LoopBB.end())
7570 I = CmpxMI.getInstr()->getIterator();
7571 } else {
7572 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7573 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7574 .addReg(CurReg)
7575 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7576
7577 // Combine the comparison results with AND.
7578 if (!CondReg) { // First.
7579 CondReg = NewCondReg;
7580 } else { // If not the first, we create an AND.
7581 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7582 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7583 .addReg(CondReg)
7584 .addReg(NewCondReg)
7585 .setOperandDead(3);
7586 CondReg = AndReg;
7587 }
7588 }
7589 } // End for loop.
7590
7591 const auto *SScalarOpRC =
7592 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7593 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7594
7595 // Build scalar ScalarOp.
7596 auto Merge =
7597 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7598 unsigned Channel = 0;
7599 for (Register Piece : ReadlanePieces) {
7600 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7601 }
7602
7603 // Update ScalarOp operand to use the SGPR ScalarOp.
7604 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7605 ScalarOp->setReg(SScalarOp);
7606 else {
7607 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7608 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7609 .addReg(SScalarOp);
7610 ScalarOp->setReg(PhySGPRs[Idx]);
7611 }
7612 }
7613 }
7614
7615 // AndSaveExecOpc modifies EXEC but can't be isTerminator=1: terminators
7616 // that define virtual registers aren't supported.
7617 Register SaveExec;
7618 if (!UseNewExecInstructions) {
7619 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7620 MRI.setSimpleHint(SaveExec, CondReg);
7621
7622 // Update EXEC to matching lanes, saving original to SaveExec.
7623 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7624 .addReg(CondReg)
7625 .setOperandDead(3);
7626 }
7627
7628 // The original instruction is here; we insert the terminators after it.
7629 I = BodyBB.end();
7630
7631 if (UseNewExecInstructions) {
7632 // Compute the remaining lanes into a plain virtual register and write EXEC
7633 // from a terminator, so spill code for NewExec is placed before EXEC
7634 // changes. SIOptimizeExecMasking opportunistically folds the pair back
7635 // into S_ANDN2_WREXEC after register allocation.
7636 MRI.setSimpleHint(NewExec, PhiExec);
7637 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2Opc), NewExec)
7638 .addReg(PhiExec)
7639 .addReg(LMC.ExecReg)
7640 .setOperandDead(3);
7641 BuildMI(BodyBB, I, DL, TII.get(LMC.MovTermOpc), LMC.ExecReg)
7642 .addReg(NewExec);
7643 } else {
7644 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7645 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7646 .addReg(LMC.ExecReg)
7647 .addReg(SaveExec)
7648 .setOperandDead(3);
7649 }
7650
7651 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7652}
7653
7654// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7655// with SGPRs by iterating over all unique values across all lanes.
7656// Returns the loop basic block that now contains \p MI.
7657static MachineBasicBlock *
7661 MachineBasicBlock::iterator Begin = nullptr,
7663 ArrayRef<Register> PhySGPRs = {}) {
7664 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7665 "Physical SGPRs must be empty or match the number of scalar operands");
7667 MachineFunction &MF = *MBB.getParent();
7669 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7671 if (!Begin.isValid())
7672 Begin = &MI;
7673 if (!End.isValid()) {
7674 End = &MI;
7675 ++End;
7676 }
7677 const DebugLoc &DL = MI.getDebugLoc();
7679 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7680
7681 // Save SCC. Waterfall Loop may overwrite SCC.
7682 Register SaveSCCReg;
7683
7684 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7685 // rather than unlimited scan everywhere
7686 bool SCCNotDead =
7687 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7688 std::numeric_limits<unsigned>::max()) !=
7690 if (SCCNotDead) {
7691 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7692 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7693 .addImm(1)
7694 .addImm(0);
7695 }
7696
7697 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7698
7699 // Save the EXEC mask
7700 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7701
7702 // Killed uses in the instruction we are waterfalling around will be
7703 // incorrect due to the added control-flow.
7705 ++AfterMI;
7706 for (auto I = Begin; I != AfterMI; I++) {
7707 for (auto &MO : I->all_uses())
7708 MRI.clearKillFlags(MO.getReg());
7709 }
7710
7711 // To insert the loop we need to split the block. Move everything after this
7712 // point to a new block, and insert a new empty block between the two.
7715 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7717 ++MBBI;
7718
7719 MF.insert(MBBI, LoopBB);
7720 MF.insert(MBBI, BodyBB);
7721 MF.insert(MBBI, RemainderBB);
7722
7723 LoopBB->addSuccessor(BodyBB);
7724 BodyBB->addSuccessor(LoopBB);
7725 BodyBB->addSuccessor(RemainderBB);
7726
7727 // Move Begin to MI to the BodyBB, and the remainder of the block to
7728 // RemainderBB.
7729 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7730 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7731 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7732
7733 MBB.addSuccessor(LoopBB);
7734
7735 // Update dominators. We know that MBB immediately dominates LoopBB, that
7736 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7737 // RemainderBB. RemainderBB immediately dominates all of the successors
7738 // transferred to it from MBB that MBB used to properly dominate.
7739 if (MDT) {
7740 MDT->addNewBlock(LoopBB, &MBB);
7741 MDT->addNewBlock(BodyBB, LoopBB);
7742 MDT->addNewBlock(RemainderBB, BodyBB);
7743 for (auto &Succ : RemainderBB->successors()) {
7744 if (MDT->properlyDominates(&MBB, Succ)) {
7745 MDT->changeImmediateDominator(Succ, RemainderBB);
7746 }
7747 }
7748 }
7749
7750 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7751 PhySGPRs);
7752
7753 MachineBasicBlock::iterator First = RemainderBB->begin();
7754 // Restore SCC
7755 if (SCCNotDead) {
7756 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7757 .addReg(SaveSCCReg)
7758 .addImm(0);
7759 }
7760
7761 // Restore the EXEC mask
7762 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7763 .addReg(SaveExec);
7764 return BodyBB;
7765}
7766
7767// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7768static std::tuple<unsigned, unsigned>
7770 MachineBasicBlock &MBB = *MI.getParent();
7771 MachineFunction &MF = *MBB.getParent();
7773
7774 // Extract the ptr from the resource descriptor.
7775 unsigned RsrcPtr =
7776 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7777 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7778
7779 // Create an empty resource descriptor
7780 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7781 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7782 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7783 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7784 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7785
7786 // Zero64 = 0
7787 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7788 .addImm(0);
7789
7790 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7791 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7792 .addImm(Lo_32(RsrcDataFormat));
7793
7794 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7795 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7796 .addImm(Hi_32(RsrcDataFormat));
7797
7798 // NewSRsrc = {Zero64, SRsrcFormat}
7799 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7800 .addReg(Zero64)
7801 .addImm(AMDGPU::sub0_sub1)
7802 .addReg(SRsrcFormatLo)
7803 .addImm(AMDGPU::sub2)
7804 .addReg(SRsrcFormatHi)
7805 .addImm(AMDGPU::sub3);
7806
7807 return std::tuple(RsrcPtr, NewSRsrc);
7808}
7809
7812 MachineDominatorTree *MDT) const {
7813 MachineFunction &MF = *MI.getMF();
7815 MachineBasicBlock *CreatedBB = nullptr;
7816
7817 // Legalize True16
7818 if (ST.useRealTrue16Insts())
7820
7821 // Legalize VOP2
7822 if (isVOP2(MI) || isVOPC(MI)) {
7824 return CreatedBB;
7825 }
7826
7827 // Legalize VOP3
7828 if (isVOP3(MI)) {
7830 return CreatedBB;
7831 }
7832
7833 // Legalize SMRD
7834 if (isSMRD(MI)) {
7836 return CreatedBB;
7837 }
7838
7839 // Legalize FLAT
7840 if (isFLAT(MI)) {
7842 return CreatedBB;
7843 }
7844
7845 // Legalize PHI
7846 // The register class of the operands must be the same type as the register
7847 // class of the output.
7848 if (MI.getOpcode() == AMDGPU::PHI) {
7849 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7850 assert(!RI.isSGPRClass(VRC));
7851
7852 // Update all the operands so they have the same type.
7853 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7854 MachineOperand &Op = MI.getOperand(I);
7855 if (!Op.isReg() || !Op.getReg().isVirtual())
7856 continue;
7857
7858 // MI is a PHI instruction.
7859 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7861
7862 // Avoid creating no-op copies with the same src and dst reg class. These
7863 // confuse some of the machine passes.
7864 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7865 }
7866 }
7867
7868 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7869 // VGPR dest type and SGPR sources, insert copies so all operands are
7870 // VGPRs. This seems to help operand folding / the register coalescer.
7871 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7872 MachineBasicBlock *MBB = MI.getParent();
7873 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7874 if (RI.hasVGPRs(DstRC)) {
7875 // Update all the operands so they are VGPR register classes. These may
7876 // not be the same register class because REG_SEQUENCE supports mixing
7877 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7878 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7879 MachineOperand &Op = MI.getOperand(I);
7880 if (!Op.isReg() || !Op.getReg().isVirtual())
7881 continue;
7882
7883 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7884 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7885 if (VRC == OpRC)
7886 continue;
7887
7888 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7889 }
7890 }
7891
7892 return CreatedBB;
7893 }
7894
7895 // Legalize INSERT_SUBREG
7896 // src0 must have the same register class as dst
7897 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7898 Register Dst = MI.getOperand(0).getReg();
7899 Register Src0 = MI.getOperand(1).getReg();
7900 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7901 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7902 if (DstRC != Src0RC) {
7903 MachineBasicBlock *MBB = MI.getParent();
7904 MachineOperand &Op = MI.getOperand(1);
7905 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7906 }
7907 return CreatedBB;
7908 }
7909
7910 // Legalize SI_INIT_M0
7911 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7912 MachineOperand &Src = MI.getOperand(0);
7913 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7914 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7915 return CreatedBB;
7916 }
7917
7918 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
7919 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7920 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7921 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7922 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7923 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7924 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7925 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7926 MachineOperand &Src = MI.getOperand(1);
7927 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7928 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7929 return CreatedBB;
7930 }
7931
7932 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
7933 //
7934 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
7935 // scratch memory access. In both cases, the legalization never involves
7936 // conversion to the addr64 form.
7938 (isMUBUF(MI) || isMTBUF(MI)))) {
7939 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
7940 ? AMDGPU::OpName::rsrc
7941 : AMDGPU::OpName::srsrc;
7942 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
7943 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
7944 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
7945
7946 AMDGPU::OpName SampOpName =
7947 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7948 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
7949 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
7950 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
7951
7952 return CreatedBB;
7953 }
7954
7955 // Legalize SI_CALL
7956 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7957 MachineOperand *Dest = &MI.getOperand(0);
7958 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
7959 createWaterFallForSiCall(&MI, MDT, {Dest});
7960 }
7961 }
7962
7963 // Legalize s_sleep_var.
7964 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7965 const DebugLoc &DL = MI.getDebugLoc();
7966 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7967 int Src0Idx =
7968 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
7969 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7970 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7971 .add(Src0);
7972 Src0.ChangeToRegister(Reg, false);
7973 return nullptr;
7974 }
7975
7976 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
7977 // operands are scalar.
7978 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7979 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7980 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7981 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7982 for (MachineOperand &Src : MI.explicit_operands()) {
7983 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7984 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7985 }
7986 return CreatedBB;
7987 }
7988
7989 // Legalize MUBUF instructions.
7990 bool isSoffsetLegal = true;
7991 int SoffsetIdx =
7992 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
7993 if (SoffsetIdx != -1) {
7994 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
7995 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
7996 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
7997 isSoffsetLegal = false;
7998 }
7999 }
8000
8001 bool isRsrcLegal = true;
8002 int RsrcIdx =
8003 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
8004 if (RsrcIdx != -1) {
8005 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
8006 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
8007 isRsrcLegal = false;
8008 }
8009
8010 // The operands are legal.
8011 if (isRsrcLegal && isSoffsetLegal)
8012 return CreatedBB;
8013
8014 if (!isRsrcLegal) {
8015 // Legalize a VGPR Rsrc
8016 //
8017 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
8018 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
8019 // a zero-value SRsrc.
8020 //
8021 // If the instruction is _OFFSET (both idxen and offen disabled), and we
8022 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
8023 // above.
8024 //
8025 // Otherwise we are on non-ADDR64 hardware, and/or we have
8026 // idxen/offen/bothen and we fall back to a waterfall loop.
8027
8028 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
8029 MachineBasicBlock &MBB = *MI.getParent();
8030
8031 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
8032 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
8033 // This is already an ADDR64 instruction so we need to add the pointer
8034 // extracted from the resource descriptor to the current value of VAddr.
8035 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8036 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8037 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8038
8039 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
8040 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
8041 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
8042
8043 unsigned RsrcPtr, NewSRsrc;
8044 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
8045
8046 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
8047 const DebugLoc &DL = MI.getDebugLoc();
8048 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
8049 .addDef(CondReg0)
8050 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8051 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
8052 .addImm(0);
8053
8054 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
8055 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
8056 .addDef(CondReg1, RegState::Dead)
8057 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8058 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
8059 .addReg(CondReg0)
8060 .addImm(0);
8061
8062 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8063 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
8064 .addReg(NewVAddrLo)
8065 .addImm(AMDGPU::sub0)
8066 .addReg(NewVAddrHi)
8067 .addImm(AMDGPU::sub1);
8068
8069 VAddr->setReg(NewVAddr);
8070 Rsrc->setReg(NewSRsrc);
8071 } else if (!VAddr && ST.hasAddr64()) {
8072 // This instructions is the _OFFSET variant, so we need to convert it to
8073 // ADDR64.
8074 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
8075 "FIXME: Need to emit flat atomics here");
8076
8077 unsigned RsrcPtr, NewSRsrc;
8078 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
8079
8080 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8081 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
8082 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
8083 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8084 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
8085
8086 // Atomics with return have an additional tied operand and are
8087 // missing some of the special bits.
8088 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
8089 MachineInstr *Addr64;
8090
8091 if (!VDataIn) {
8092 // Regular buffer load / store.
8094 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
8095 .add(*VData)
8096 .addReg(NewVAddr)
8097 .addReg(NewSRsrc)
8098 .add(*SOffset)
8099 .add(*Offset);
8100
8101 if (const MachineOperand *CPol =
8102 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
8103 MIB.addImm(CPol->getImm());
8104 }
8105
8106 if (const MachineOperand *TFE =
8107 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
8108 MIB.addImm(TFE->getImm());
8109 }
8110
8111 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
8112
8113 MIB.cloneMemRefs(MI);
8114 Addr64 = MIB;
8115 } else {
8116 // Atomics with return.
8117 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
8118 .add(*VData)
8119 .add(*VDataIn)
8120 .addReg(NewVAddr)
8121 .addReg(NewSRsrc)
8122 .add(*SOffset)
8123 .add(*Offset)
8124 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
8125 .cloneMemRefs(MI);
8126 }
8127
8128 MI.removeFromParent();
8129
8130 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8131 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
8132 NewVAddr)
8133 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8134 .addImm(AMDGPU::sub0)
8135 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8136 .addImm(AMDGPU::sub1);
8137 } else {
8138 // Legalize a VGPR Rsrc and soffset together.
8139 if (!isSoffsetLegal) {
8140 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8141 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
8142 return CreatedBB;
8143 }
8144 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
8145 return CreatedBB;
8146 }
8147 }
8148
8149 // Legalize a VGPR soffset.
8150 if (!isSoffsetLegal) {
8151 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8152 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
8153 return CreatedBB;
8154 }
8155 return CreatedBB;
8156}
8157
8159 if (InSet.insert(MI).second)
8160 InstrList.push_back(MI);
8161 // Add MBUF instructiosn to deferred list.
8162 int RsrcIdx =
8163 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
8164 if (RsrcIdx != -1) {
8165 DeferredList.insert(MI);
8166 }
8167}
8168
8170 return DeferredList.contains(MI);
8171}
8172
8173// Legalize size mismatches between 16bit and 32bit registers in v2s copy
8174// lowering (change sgpr to vgpr).
8175// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
8176// size. Need to legalize the size of the operands during the vgpr lowering
8177// chain. This can be removed after we have sgpr16 in place
8179 MachineRegisterInfo &MRI) const {
8180 if (!ST.useRealTrue16Insts())
8181 return;
8182
8183 unsigned Opcode = MI.getOpcode();
8184 MachineBasicBlock *MBB = MI.getParent();
8185 // Legalize operands and check for size mismatch
8186 if (OpIdx >= MI.getNumExplicitOperands() ||
8187 OpIdx >= get(Opcode).getNumOperands() ||
8188 get(Opcode).operands()[OpIdx].RegClass == -1)
8189 return;
8190
8191 MachineOperand &Op = MI.getOperand(OpIdx);
8192 if (!Op.isReg() || !Op.getReg().isVirtual() || Op.isDef())
8193 return;
8194
8195 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
8196 if (!RI.isVGPRClass(CurrRC))
8197 return;
8198
8199 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
8200 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
8201 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8202 // Default to the lo16 only if the subregister is not specified.
8203 if (Op.getSubReg() == AMDGPU::NoSubRegister)
8204 Op.setSubReg(AMDGPU::lo16);
8205 return;
8206 }
8207
8208 const TargetRegisterClass *CurrSRC =
8209 RI.getSubRegisterClass(CurrRC, Op.getSubReg());
8210 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8211 const DebugLoc &DL = MI.getDebugLoc();
8212 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8213 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8214 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
8215 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
8216 .addReg(Op.getReg(), {}, Op.getSubReg())
8217 .addImm(AMDGPU::lo16)
8218 .addReg(Undef)
8219 .addImm(AMDGPU::hi16);
8220 Op.setReg(NewDstReg);
8221 Op.setSubReg(AMDGPU::NoSubRegister);
8222 }
8223}
8225 MachineRegisterInfo &MRI) const {
8226 for (unsigned OpIdx = 0; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
8228}
8229
8233 ArrayRef<Register> PhySGPRs) const {
8234 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8235 "This only handle waterfall for SI_CALL_ISEL");
8236 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
8237 // following copies, we also need to move copies from and to physical
8238 // registers into the loop block.
8239 // Also move the copies to physical registers into the loop block
8240 MachineBasicBlock &MBB = *MI->getParent();
8242 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8243 --Start;
8245 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8246 ++End;
8247
8248 // Also include following copies of the return value
8249 ++End;
8250 while (End != MBB.end() && End->isCopy() &&
8251 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8252 ++End;
8253
8254 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
8255}
8256
8258 MachineDominatorTree *MDT) const {
8260 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
8261 while (!Worklist.empty()) {
8262 MachineInstr &Inst = *Worklist.top();
8263 Worklist.erase_top();
8264 // Skip MachineInstr in the deferred list.
8265 if (Worklist.isDeferred(&Inst))
8266 continue;
8267 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8268 }
8269
8270 // Deferred list of instructions will be processed once
8271 // all the MachineInstr in the worklist are done.
8272 for (MachineInstr *Inst : Worklist.getDeferredList()) {
8273 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8274 assert(Worklist.empty() &&
8275 "Deferred MachineInstr are not supposed to re-populate worklist");
8276 }
8277
8278 for (auto &Entry : WaterFalls) {
8279 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8280 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
8281 Entry.second.SGPRs);
8282 }
8283
8284 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8285 if (Entry.second)
8286 Entry.first->eraseFromParent();
8287}
8289 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
8290 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
8291 // hope for the best.
8292 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
8293 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
8294 if (SubRegIndices.size() <= 1) {
8295 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8296 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8297 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8298 .add(Inst.getOperand(1));
8299 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
8300 DstReg)
8301 .addReg(NewDst);
8302 } else {
8304 for (int16_t Indice : SubRegIndices) {
8305 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8306 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8307 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8308 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
8309
8310 DstRegs.push_back(NewDst);
8311 }
8313 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8314 get(AMDGPU::REG_SEQUENCE), DstReg);
8315 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
8316 MIB.addReg(DstRegs[i]);
8317 MIB.addImm(RI.getSubRegFromChannel(i));
8318 }
8319 }
8320}
8321
8323 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
8326 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8327 if (DstReg == AMDGPU::M0) {
8329 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8330 return;
8331 }
8332 Register SrcReg = Inst.getOperand(1).getReg();
8335 // Only search current block since phyreg's def & use cannot cross
8336 // blocks when MF.NoPhi = false.
8337 while (++I != E) {
8338 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
8339 // and record the operand for later waterfall loop generation.
8340 if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8341 MachineInstr *UseMI = &*I;
8342 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
8343 if (UseMI->getOperand(i).isReg() &&
8344 UseMI->getOperand(i).getReg() == DstReg) {
8345 MachineOperand *MO = &UseMI->getOperand(i);
8346 MO->setReg(SrcReg);
8347 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
8348 V2SCopyInfo.MOs.push_back(MO);
8349 V2SCopyInfo.SGPRs.push_back(DstReg);
8350 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8351 }
8352 }
8353 } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8354 I->getOperand(0).isReg() &&
8355 I->getOperand(0).getReg() == DstReg) {
8357 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8358 } else if (I->readsRegister(DstReg, &RI)) {
8359 // COPY cannot be erased if other type of inst uses it.
8360 V2SPhyCopiesToErase[&Inst] = false;
8361 }
8362 if (I->findRegisterDefOperand(DstReg, &RI))
8363 break;
8364 }
8365}
8366
8368 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
8370 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8371
8373 if (!MBB)
8374 return;
8375 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
8376 unsigned Opcode = Inst.getOpcode();
8377 unsigned NewOpcode = getVALUOp(Inst);
8378 const DebugLoc &DL = Inst.getDebugLoc();
8379
8380 // Handle some special cases
8381 switch (Opcode) {
8382 default:
8383 break;
8384 case AMDGPU::S_ADD_I32:
8385 case AMDGPU::S_SUB_I32: {
8386 // FIXME: The u32 versions currently selected use the carry.
8387 bool Changed;
8388 MachineBasicBlock *CreatedBBTmp = nullptr;
8389 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8390 if (Changed)
8391 return;
8392
8393 // Default handling
8394 break;
8395 }
8396
8397 case AMDGPU::S_MUL_U64:
8398 if (ST.useVMulU64Inst()) {
8399 NewOpcode = AMDGPU::V_MUL_U64_e64;
8400 break;
8401 }
8402 // Split s_mul_u64 in 32-bit vector multiplications.
8403 splitScalarSMulU64(Worklist, Inst, MDT);
8404 Inst.eraseFromParent();
8405 return;
8406
8407 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8408 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8409 // This is a special case of s_mul_u64 where all the operands are either
8410 // zero extended or sign extended.
8411 splitScalarSMulPseudo(Worklist, Inst, MDT);
8412 Inst.eraseFromParent();
8413 return;
8414
8415 case AMDGPU::S_AND_B64:
8416 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8417 Inst.eraseFromParent();
8418 return;
8419
8420 case AMDGPU::S_OR_B64:
8421 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8422 Inst.eraseFromParent();
8423 return;
8424
8425 case AMDGPU::S_XOR_B64:
8426 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8427 Inst.eraseFromParent();
8428 return;
8429
8430 case AMDGPU::S_NAND_B64:
8431 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8432 Inst.eraseFromParent();
8433 return;
8434
8435 case AMDGPU::S_NOR_B64:
8436 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8437 Inst.eraseFromParent();
8438 return;
8439
8440 case AMDGPU::S_XNOR_B64:
8441 if (ST.hasDLInsts())
8442 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8443 else
8444 splitScalar64BitXnor(Worklist, Inst, MDT);
8445 Inst.eraseFromParent();
8446 return;
8447
8448 case AMDGPU::S_ANDN2_B64:
8449 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8450 Inst.eraseFromParent();
8451 return;
8452
8453 case AMDGPU::S_ORN2_B64:
8454 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8455 Inst.eraseFromParent();
8456 return;
8457
8458 case AMDGPU::S_BREV_B64:
8459 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8460 Inst.eraseFromParent();
8461 return;
8462
8463 case AMDGPU::S_NOT_B64:
8464 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8465 Inst.eraseFromParent();
8466 return;
8467
8468 case AMDGPU::S_BCNT1_I32_B64:
8469 splitScalar64BitBCNT(Worklist, Inst);
8470 Inst.eraseFromParent();
8471 return;
8472
8473 case AMDGPU::S_BFE_I64:
8474 splitScalar64BitBFE(Worklist, Inst);
8475 Inst.eraseFromParent();
8476 return;
8477
8478 case AMDGPU::S_FLBIT_I32_B64:
8479 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8480 Inst.eraseFromParent();
8481 return;
8482 case AMDGPU::S_FF1_I32_B64:
8483 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8484 Inst.eraseFromParent();
8485 return;
8486
8487 case AMDGPU::S_LSHL_B32:
8488 if (ST.hasOnlyRevVALUShifts()) {
8489 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8490 swapOperands(Inst);
8491 }
8492 break;
8493 case AMDGPU::S_ASHR_I32:
8494 if (ST.hasOnlyRevVALUShifts()) {
8495 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8496 swapOperands(Inst);
8497 }
8498 break;
8499 case AMDGPU::S_LSHR_B32:
8500 if (ST.hasOnlyRevVALUShifts()) {
8501 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8502 swapOperands(Inst);
8503 }
8504 break;
8505 case AMDGPU::S_LSHL_B64:
8506 if (ST.hasOnlyRevVALUShifts()) {
8507 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8508 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8509 : AMDGPU::V_LSHLREV_B64_e64;
8510 swapOperands(Inst);
8511 }
8512 break;
8513 case AMDGPU::S_ASHR_I64:
8514 if (ST.hasOnlyRevVALUShifts()) {
8515 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8516 swapOperands(Inst);
8517 }
8518 break;
8519 case AMDGPU::S_LSHR_B64:
8520 if (ST.hasOnlyRevVALUShifts()) {
8521 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8522 swapOperands(Inst);
8523 }
8524 break;
8525
8526 case AMDGPU::S_ABS_I32:
8527 lowerScalarAbs(Worklist, Inst);
8528 Inst.eraseFromParent();
8529 return;
8530
8531 case AMDGPU::S_ABSDIFF_I32:
8532 lowerScalarAbsDiff(Worklist, Inst);
8533 Inst.eraseFromParent();
8534 return;
8535
8536 case AMDGPU::S_CBRANCH_SCC0:
8537 case AMDGPU::S_CBRANCH_SCC1: {
8538 // Clear unused bits of vcc
8539 Register CondReg = Inst.getOperand(1).getReg();
8540 bool IsSCC = CondReg == AMDGPU::SCC;
8542 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8543 .addReg(LMC.ExecReg)
8544 .addReg(IsSCC ? LMC.VccReg : CondReg)
8545 .setOperandDead(3); // implicit-def $scc
8546 Inst.removeOperand(1);
8547 } break;
8548
8549 case AMDGPU::S_BFE_U64:
8550 case AMDGPU::S_BFM_B64:
8551 llvm_unreachable("Moving this op to VALU not implemented");
8552
8553 case AMDGPU::S_PACK_LL_B32_B16:
8554 case AMDGPU::S_PACK_LH_B32_B16:
8555 case AMDGPU::S_PACK_HL_B32_B16:
8556 case AMDGPU::S_PACK_HH_B32_B16:
8557 movePackToVALU(Worklist, MRI, Inst);
8558 Inst.eraseFromParent();
8559 return;
8560
8561 case AMDGPU::S_XNOR_B32:
8562 lowerScalarXnor(Worklist, Inst);
8563 Inst.eraseFromParent();
8564 return;
8565
8566 case AMDGPU::S_NAND_B32:
8567 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8568 Inst.eraseFromParent();
8569 return;
8570
8571 case AMDGPU::S_NOR_B32:
8572 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8573 Inst.eraseFromParent();
8574 return;
8575
8576 case AMDGPU::S_ANDN2_B32:
8577 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8578 Inst.eraseFromParent();
8579 return;
8580
8581 case AMDGPU::S_ORN2_B32:
8582 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8583 Inst.eraseFromParent();
8584 return;
8585
8586 // TODO: remove as soon as everything is ready
8587 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8588 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8589 // can only be selected from the uniform SDNode.
8590 case AMDGPU::S_ADD_CO_PSEUDO:
8591 case AMDGPU::S_SUB_CO_PSEUDO: {
8592 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8593 ? AMDGPU::V_ADDC_U32_e64
8594 : AMDGPU::V_SUBB_U32_e64;
8595 const auto *CarryRC = RI.getWaveMaskRegClass();
8596
8597 Register CarryInReg = Inst.getOperand(4).getReg();
8598 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8599 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8600 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8601 .addReg(CarryInReg);
8602 }
8603
8604 Register CarryOutReg = Inst.getOperand(1).getReg();
8605
8606 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8607 MRI.getRegClass(Inst.getOperand(0).getReg())));
8608 MachineInstr *CarryOp =
8609 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8610 .addReg(CarryOutReg, RegState::Define)
8611 .add(Inst.getOperand(2))
8612 .add(Inst.getOperand(3))
8613 .addReg(CarryInReg)
8614 .addImm(0);
8615 legalizeOperands(*CarryOp);
8616 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8617 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8618 Inst.eraseFromParent();
8619 }
8620 return;
8621 case AMDGPU::S_UADDO_PSEUDO:
8622 case AMDGPU::S_USUBO_PSEUDO: {
8623 MachineOperand &Dest0 = Inst.getOperand(0);
8624 MachineOperand &Dest1 = Inst.getOperand(1);
8625 MachineOperand &Src0 = Inst.getOperand(2);
8626 MachineOperand &Src1 = Inst.getOperand(3);
8627
8628 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8629 ? AMDGPU::V_ADD_CO_U32_e64
8630 : AMDGPU::V_SUB_CO_U32_e64;
8631 const TargetRegisterClass *NewRC =
8632 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8633 Register DestReg = MRI.createVirtualRegister(NewRC);
8634 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8635 .addReg(Dest1.getReg(), RegState::Define)
8636 .add(Src0)
8637 .add(Src1)
8638 .addImm(0); // clamp bit
8639
8640 legalizeOperands(*NewInstr, MDT);
8641 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8642 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8643 Inst.eraseFromParent();
8644 }
8645 return;
8646 case AMDGPU::S_LSHL1_ADD_U32:
8647 case AMDGPU::S_LSHL2_ADD_U32:
8648 case AMDGPU::S_LSHL3_ADD_U32:
8649 case AMDGPU::S_LSHL4_ADD_U32: {
8650 MachineOperand &Dest = Inst.getOperand(0);
8651 MachineOperand &Src0 = Inst.getOperand(1);
8652 MachineOperand &Src1 = Inst.getOperand(2);
8653 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8654 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8655 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8656 : 4);
8657
8658 const TargetRegisterClass *NewRC =
8659 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8660 Register DestReg = MRI.createVirtualRegister(NewRC);
8661 MachineInstr *NewInstr =
8662 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8663 .add(Src0)
8664 .addImm(ShiftAmt)
8665 .add(Src1);
8666
8667 legalizeOperands(*NewInstr, MDT);
8668 MRI.replaceRegWith(Dest.getReg(), DestReg);
8669 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8670 Inst.eraseFromParent();
8671 }
8672 return;
8673 case AMDGPU::S_CSELECT_B32:
8674 case AMDGPU::S_CSELECT_B64:
8675 lowerSelect(Worklist, Inst, MDT);
8676 Inst.eraseFromParent();
8677 return;
8678 case AMDGPU::S_CMP_EQ_I32:
8679 case AMDGPU::S_CMP_LG_I32:
8680 case AMDGPU::S_CMP_GT_I32:
8681 case AMDGPU::S_CMP_GE_I32:
8682 case AMDGPU::S_CMP_LT_I32:
8683 case AMDGPU::S_CMP_LE_I32:
8684 case AMDGPU::S_CMP_EQ_U32:
8685 case AMDGPU::S_CMP_LG_U32:
8686 case AMDGPU::S_CMP_GT_U32:
8687 case AMDGPU::S_CMP_GE_U32:
8688 case AMDGPU::S_CMP_LT_U32:
8689 case AMDGPU::S_CMP_LE_U32:
8690 case AMDGPU::S_CMP_EQ_U64:
8691 case AMDGPU::S_CMP_LG_U64:
8692 case AMDGPU::S_CMP_LT_F32:
8693 case AMDGPU::S_CMP_EQ_F32:
8694 case AMDGPU::S_CMP_LE_F32:
8695 case AMDGPU::S_CMP_GT_F32:
8696 case AMDGPU::S_CMP_LG_F32:
8697 case AMDGPU::S_CMP_GE_F32:
8698 case AMDGPU::S_CMP_O_F32:
8699 case AMDGPU::S_CMP_U_F32:
8700 case AMDGPU::S_CMP_NGE_F32:
8701 case AMDGPU::S_CMP_NLG_F32:
8702 case AMDGPU::S_CMP_NGT_F32:
8703 case AMDGPU::S_CMP_NLE_F32:
8704 case AMDGPU::S_CMP_NEQ_F32:
8705 case AMDGPU::S_CMP_NLT_F32: {
8706 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8707 auto NewInstr =
8708 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8709 .setMIFlags(Inst.getFlags());
8710 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8711 0) {
8712 NewInstr
8713 .addImm(0) // src0_modifiers
8714 .add(Inst.getOperand(0)) // src0
8715 .addImm(0) // src1_modifiers
8716 .add(Inst.getOperand(1)) // src1
8717 .addImm(0); // clamp
8718 } else {
8719 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8720 }
8721 legalizeOperands(*NewInstr, MDT);
8722 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8723 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8724 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8725 Inst.eraseFromParent();
8726 return;
8727 }
8728 case AMDGPU::S_CMP_LT_F16:
8729 case AMDGPU::S_CMP_EQ_F16:
8730 case AMDGPU::S_CMP_LE_F16:
8731 case AMDGPU::S_CMP_GT_F16:
8732 case AMDGPU::S_CMP_LG_F16:
8733 case AMDGPU::S_CMP_GE_F16:
8734 case AMDGPU::S_CMP_O_F16:
8735 case AMDGPU::S_CMP_U_F16:
8736 case AMDGPU::S_CMP_NGE_F16:
8737 case AMDGPU::S_CMP_NLG_F16:
8738 case AMDGPU::S_CMP_NGT_F16:
8739 case AMDGPU::S_CMP_NLE_F16:
8740 case AMDGPU::S_CMP_NEQ_F16:
8741 case AMDGPU::S_CMP_NLT_F16: {
8742 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8743 auto NewInstr =
8744 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8745 .setMIFlags(Inst.getFlags());
8746 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8747 NewInstr
8748 .addImm(0) // src0_modifiers
8749 .add(Inst.getOperand(0)) // src0
8750 .addImm(0) // src1_modifiers
8751 .add(Inst.getOperand(1)) // src1
8752 .addImm(0); // clamp
8753 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8754 NewInstr.addImm(0); // op_sel0
8755 } else {
8756 NewInstr
8757 .add(Inst.getOperand(0))
8758 .add(Inst.getOperand(1));
8759 }
8760 legalizeOperands(*NewInstr, MDT);
8761 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8762 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8763 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8764 Inst.eraseFromParent();
8765 return;
8766 }
8767 case AMDGPU::S_CVT_HI_F32_F16: {
8768 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8769 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8770 if (ST.useRealTrue16Insts()) {
8771 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8772 .add(Inst.getOperand(1));
8773 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8774 .addImm(0) // src0_modifiers
8775 .addReg(TmpReg, {}, AMDGPU::hi16)
8776 .addImm(0) // clamp
8777 .addImm(0) // omod
8778 .addImm(0); // op_sel0
8779 } else {
8780 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8781 .addImm(16)
8782 .add(Inst.getOperand(1));
8783 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8784 .addImm(0) // src0_modifiers
8785 .addReg(TmpReg)
8786 .addImm(0) // clamp
8787 .addImm(0); // omod
8788 }
8789
8790 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8791 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8792 Inst.eraseFromParent();
8793 return;
8794 }
8795 case AMDGPU::S_MINIMUM_F32:
8796 case AMDGPU::S_MAXIMUM_F32: {
8797 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8798 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8799 .addImm(0) // src0_modifiers
8800 .add(Inst.getOperand(1))
8801 .addImm(0) // src1_modifiers
8802 .add(Inst.getOperand(2))
8803 .addImm(0) // clamp
8804 .addImm(0); // omod
8805 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8806
8807 legalizeOperands(*NewInstr, MDT);
8808 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8809 Inst.eraseFromParent();
8810 return;
8811 }
8812 case AMDGPU::S_MINIMUM_F16:
8813 case AMDGPU::S_MAXIMUM_F16: {
8814 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8815 ? &AMDGPU::VGPR_16RegClass
8816 : &AMDGPU::VGPR_32RegClass);
8817 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8818 .addImm(0) // src0_modifiers
8819 .add(Inst.getOperand(1))
8820 .addImm(0) // src1_modifiers
8821 .add(Inst.getOperand(2))
8822 .addImm(0) // clamp
8823 .addImm(0) // omod
8824 .addImm(0); // opsel0
8825 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8826 legalizeOperands(*NewInstr, MDT);
8827 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8828 Inst.eraseFromParent();
8829 return;
8830 }
8831 case AMDGPU::V_S_EXP_F16_e64:
8832 case AMDGPU::V_S_LOG_F16_e64:
8833 case AMDGPU::V_S_RCP_F16_e64:
8834 case AMDGPU::V_S_RSQ_F16_e64:
8835 case AMDGPU::V_S_SQRT_F16_e64: {
8836 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8837 ? &AMDGPU::VGPR_16RegClass
8838 : &AMDGPU::VGPR_32RegClass);
8839 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8840 .add(Inst.getOperand(1)) // src0_modifiers
8841 .add(Inst.getOperand(2))
8842 .add(Inst.getOperand(3)) // clamp
8843 .add(Inst.getOperand(4)) // omod
8844 .setMIFlags(Inst.getFlags());
8845 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8846 NewInstr.addImm(0); // opsel0
8847 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8848 legalizeOperands(*NewInstr, MDT);
8849 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8850 Inst.eraseFromParent();
8851 return;
8852 }
8853 }
8854
8855 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8856 // We cannot move this instruction to the VALU, so we should try to
8857 // legalize its operands instead.
8858 legalizeOperands(Inst, MDT);
8859 return;
8860 }
8861 // Handle converting generic instructions like COPY-to-SGPR into
8862 // COPY-to-VGPR.
8863 if (NewOpcode == Opcode) {
8864 Register DstReg = Inst.getOperand(0).getReg();
8865 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8866
8867 if (Inst.isCopy() && DstReg.isPhysical() &&
8868 Inst.getOperand(1).getReg().isVirtual()) {
8869 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8870 V2SPhyCopiesToErase);
8871 return;
8872 }
8873
8874 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8875 Register NewDstReg = Inst.getOperand(1).getReg();
8876 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8877 if (const TargetRegisterClass *CommonRC =
8878 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8879 // Instead of creating a copy where src and dst are the same register
8880 // class, we just replace all uses of dst with src. These kinds of
8881 // copies interfere with the heuristics MachineSink uses to decide
8882 // whether or not to split a critical edge. Since the pass assumes
8883 // that copies will end up as machine instructions and not be
8884 // eliminated.
8885 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8886 unsigned SrcSubReg = Inst.getOperand(1).getSubReg();
8887 bool IsUndef = Inst.getOperand(1).isUndef();
8888 for (MachineOperand &UseMO :
8889 make_early_inc_range(MRI.use_operands(DstReg))) {
8890 UseMO.setSubReg(
8891 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8892 UseMO.setReg(NewDstReg);
8893 if (IsUndef)
8894 UseMO.setIsUndef();
8895 }
8896 MRI.clearKillFlags(NewDstReg);
8897
8898 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8899 llvm_unreachable("failed to constrain register");
8900
8901 Inst.eraseFromParent();
8902
8903 for (MachineOperand &UseMO :
8904 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8905 MachineInstr &UseMI = *UseMO.getParent();
8906
8907 // Legalize t16 operands since replaceReg is called after
8908 // addUsersToVALU.
8910
8911 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
8912 if (const TargetRegisterClass *OpRC =
8913 getRegClass(UseMI.getDesc(), OpIdx))
8914 MRI.constrainRegClass(NewDstReg, OpRC);
8915 }
8916
8917 return;
8918 }
8919 }
8920
8921 // If this is a v2s copy between 16bit and 32bit reg,
8922 // replace vgpr copy to reg_sequence/extract_subreg
8923 // This can be remove after we have sgpr16 in place
8924 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
8925 Inst.getOperand(1).getReg().isVirtual() &&
8926 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
8927 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
8928 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8929 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8930 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8931 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8932 get(AMDGPU::IMPLICIT_DEF), Undef);
8933 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8934 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8935 .addReg(Inst.getOperand(1).getReg())
8936 .addImm(AMDGPU::lo16)
8937 .addReg(Undef)
8938 .addImm(AMDGPU::hi16);
8939 Inst.eraseFromParent();
8940 MRI.replaceRegWith(DstReg, NewDstReg);
8941 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8942 return;
8943 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8944 AMDGPU::lo16)) {
8945 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
8946 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8947 MRI.replaceRegWith(DstReg, NewDstReg);
8948 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8949 return;
8950 }
8951 }
8952
8953 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8954 MRI.replaceRegWith(DstReg, NewDstReg);
8955 legalizeOperands(Inst, MDT);
8956 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8957 return;
8958 }
8959
8960 // Use the new VALU Opcode.
8961 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
8962 .setMIFlags(Inst.getFlags());
8963 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
8964 // Intersperse VOP3 modifiers among the SALU operands.
8965 NewInstr->addOperand(Inst.getOperand(0));
8966 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8967 AMDGPU::OpName::src0_modifiers) >= 0)
8968 NewInstr.addImm(0);
8969 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
8970 const MachineOperand &Src = Inst.getOperand(1);
8971 NewInstr->addOperand(Src);
8972 }
8973
8974 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8975 // We are converting these to a BFE, so we need to add the missing
8976 // operands for the size and offset.
8977 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8978 NewInstr.addImm(0);
8979 NewInstr.addImm(Size);
8980 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8981 // The VALU version adds the second operand to the result, so insert an
8982 // extra 0 operand.
8983 NewInstr.addImm(0);
8984 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8985 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
8986 // If we need to move this to VGPRs, we need to unpack the second
8987 // operand back into the 2 separate ones for bit offset and width.
8988 assert(OffsetWidthOp.isImm() &&
8989 "Scalar BFE is only implemented for constant width and offset");
8990 uint32_t Imm = OffsetWidthOp.getImm();
8991
8992 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
8993 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
8994 NewInstr.addImm(Offset);
8995 NewInstr.addImm(BitWidth);
8996 } else {
8997 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8998 AMDGPU::OpName::src1_modifiers) >= 0)
8999 NewInstr.addImm(0);
9000 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
9001 NewInstr->addOperand(Inst.getOperand(2));
9002 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9003 AMDGPU::OpName::src2_modifiers) >= 0)
9004 NewInstr.addImm(0);
9005 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
9006 NewInstr->addOperand(Inst.getOperand(3));
9007 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
9008 NewInstr.addImm(0);
9009 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
9010 NewInstr.addImm(0);
9011 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
9012 NewInstr.addImm(0);
9013 }
9014 } else {
9015 // Just copy the SALU operands.
9016 for (const MachineOperand &Op : Inst.explicit_operands())
9017 NewInstr->addOperand(Op);
9018 }
9019
9020 // Remove any references to SCC. Vector instructions can't read from it, and
9021 // We're just about to add the implicit use / defs of VCC, and we don't want
9022 // both.
9023 bool DeadSCCDef = false;
9024 for (MachineOperand &Op : Inst.implicit_operands()) {
9025 if (Op.getReg() == AMDGPU::SCC) {
9026 // Only propagate through live-def of SCC.
9027 if (Op.isDef()) {
9028 if (Op.isDead())
9029 DeadSCCDef = true;
9030 else
9031 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
9032 continue;
9033 }
9034
9035 addSCCDefsToVALUWorklist(NewInstr, Worklist);
9036 }
9037 }
9038 Inst.eraseFromParent();
9039 Register NewDstReg;
9040 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
9041 Register DstReg = NewInstr->getOperand(0).getReg();
9042 assert(DstReg.isVirtual());
9043 // Update the destination register class.
9044 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
9045 assert(NewDstRC);
9046 NewDstReg = MRI.createVirtualRegister(NewDstRC);
9047 MRI.replaceRegWith(DstReg, NewDstReg);
9048 }
9049 fixImplicitOperands(*NewInstr);
9050
9051 if (DeadSCCDef) {
9052 // A scalar op with a dead SCC def lowers to a VALU op whose VCC def will
9053 // also be dead.
9054 if (MachineOperand *VCCDef =
9055 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
9056 VCCDef->setIsDead();
9057 }
9058
9059 // Legalize the operands
9060 legalizeOperands(*NewInstr, MDT);
9061 if (NewDstReg)
9062 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9063}
9064
9065// Add/sub require special handling to deal with carry outs.
9066std::pair<bool, MachineBasicBlock *>
9067SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
9068 MachineDominatorTree *MDT) const {
9069 if (ST.hasAddNoCarryInsts()) {
9070 // Assume there is no user of scc since we don't select this in that case.
9071 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
9072 // is used.
9073
9074 MachineBasicBlock &MBB = *Inst.getParent();
9075 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9076
9077 Register OldDstReg = Inst.getOperand(0).getReg();
9078 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9079
9080 unsigned Opc = Inst.getOpcode();
9081 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
9082
9083 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
9084 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9085
9086 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
9087 Inst.removeOperand(3);
9088
9089 Inst.setDesc(get(NewOpc));
9090 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
9091 Inst.addImplicitDefUseOperands(*MBB.getParent());
9092 MRI.replaceRegWith(OldDstReg, ResultReg);
9093 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
9094
9095 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9096 return std::pair(true, NewBB);
9097 }
9098
9099 return std::pair(false, nullptr);
9100}
9101
9102void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
9103 MachineDominatorTree *MDT) const {
9104
9105 MachineBasicBlock &MBB = *Inst.getParent();
9106 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9107 MachineBasicBlock::iterator MII = Inst;
9108 const DebugLoc &DL = Inst.getDebugLoc();
9109
9110 MachineOperand &Dest = Inst.getOperand(0);
9111 MachineOperand &Src0 = Inst.getOperand(1);
9112 MachineOperand &Src1 = Inst.getOperand(2);
9113 MachineOperand &Cond = Inst.getOperand(3);
9114
9115 Register CondReg = Cond.getReg();
9116 bool IsSCC = (CondReg == AMDGPU::SCC);
9117
9118 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
9119 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
9120 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
9121 // output directly into the V_CNDMASK.
9122 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
9123 (Src1.getImm() == 0)) {
9124 for (MachineOperand &UseMO :
9126 MachineInstr &UseMI = *UseMO.getParent();
9127 switch (UseMI.getOpcode()) {
9128 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9129 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9130 case AMDGPU::V_CNDMASK_B16_t16_e32:
9131 case AMDGPU::V_CNDMASK_B16_t16_e64:
9132 case AMDGPU::V_CNDMASK_B32_e32:
9133 case AMDGPU::V_CNDMASK_B32_e64:
9134 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9135 if (UseMO.isImplicit() ||
9136 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
9137 UseMO.setReg(CondReg);
9138 }
9139 }
9140 if (MRI.use_nodbg_empty(Dest.getReg()))
9141 return;
9142 }
9143
9144 Register NewCondReg = CondReg;
9145 if (IsSCC) {
9146 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
9147 NewCondReg = MRI.createVirtualRegister(TC);
9148
9149 // Now look for the closest SCC def if it is a copy
9150 // replacing the CondReg with the COPY source register
9151 bool CopyFound = false;
9152 for (MachineInstr &CandI :
9154 Inst.getParent()->rend())) {
9155 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
9156 -1) {
9157 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9158 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
9159 .addReg(CandI.getOperand(1).getReg());
9160 CopyFound = true;
9161 }
9162 break;
9163 }
9164 }
9165 if (!CopyFound) {
9166 // SCC def is not a copy
9167 // Insert a trivial select instead of creating a copy, because a copy from
9168 // SCC would semantically mean just copying a single bit, but we may need
9169 // the result to be a vector condition mask that needs preserving.
9170 unsigned Opcode =
9171 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9172 auto NewSelect =
9173 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
9174 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
9175 }
9176 }
9177
9178 Register NewDestReg = MRI.createVirtualRegister(
9179 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
9180 MachineInstr *NewInst;
9181 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
9182 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9183 .addImm(0)
9184 .add(Src1) // False
9185 .addImm(0)
9186 .add(Src0) // True
9187 .addReg(NewCondReg);
9188 } else {
9189 NewInst =
9190 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
9191 .add(Src1) // False
9192 .add(Src0) // True
9193 .addReg(NewCondReg);
9194 }
9195 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
9196 legalizeOperands(*NewInst, MDT);
9197 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9198}
9199
9200void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
9201 MachineInstr &Inst) const {
9202 MachineBasicBlock &MBB = *Inst.getParent();
9203 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9204 MachineBasicBlock::iterator MII = Inst;
9205 const DebugLoc &DL = Inst.getDebugLoc();
9206
9207 MachineOperand &Dest = Inst.getOperand(0);
9208 MachineOperand &Src = Inst.getOperand(1);
9209 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9210 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9211
9212 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9213 unsigned SubOp =
9214 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9215
9216 MachineInstrBuilder Sub =
9217 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(Src.getReg());
9218 if (HasCarryOut)
9219 Sub.setOperandDead(3); // Dead vcc
9220
9221 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9222 .addReg(Src.getReg())
9223 .addReg(TmpReg);
9224
9225 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9226 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9227}
9228
9229void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
9230 MachineInstr &Inst) const {
9231 MachineBasicBlock &MBB = *Inst.getParent();
9232 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9233 MachineBasicBlock::iterator MII = Inst;
9234 const DebugLoc &DL = Inst.getDebugLoc();
9235
9236 MachineOperand &Dest = Inst.getOperand(0);
9237 MachineOperand &Src1 = Inst.getOperand(1);
9238 MachineOperand &Src2 = Inst.getOperand(2);
9239 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9240 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9241 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9242
9243 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9244 unsigned SubOp =
9245 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9246
9247 MachineInstrBuilder Sub1 = BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
9248 .addReg(Src1.getReg())
9249 .addReg(Src2.getReg());
9250
9251 MachineInstrBuilder Sub2 =
9252 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
9253
9254 if (HasCarryOut) {
9255 Sub1.setOperandDead(3); // Dead vcc
9256 Sub2.setOperandDead(3); // Dead vcc
9257 }
9258
9259 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9260 .addReg(SubResultReg)
9261 .addReg(TmpReg);
9262
9263 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9264 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9265}
9266
9267void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
9268 MachineInstr &Inst) const {
9269 MachineBasicBlock &MBB = *Inst.getParent();
9270 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9271 MachineBasicBlock::iterator MII = Inst;
9272 const DebugLoc &DL = Inst.getDebugLoc();
9273
9274 MachineOperand &Dest = Inst.getOperand(0);
9275 MachineOperand &Src0 = Inst.getOperand(1);
9276 MachineOperand &Src1 = Inst.getOperand(2);
9277
9278 if (ST.hasDLInsts()) {
9279 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9280 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
9281 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
9282
9283 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
9284 .add(Src0)
9285 .add(Src1);
9286
9287 MRI.replaceRegWith(Dest.getReg(), NewDest);
9288 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9289 } else {
9290 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
9291 // invert either source and then perform the XOR. If either source is a
9292 // scalar register, then we can leave the inversion on the scalar unit to
9293 // achieve a better distribution of scalar and vector instructions.
9294 bool Src0IsSGPR = Src0.isReg() &&
9295 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
9296 bool Src1IsSGPR = Src1.isReg() &&
9297 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
9298 MachineInstr *Xor;
9299 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9300 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9301
9302 // Build a pair of scalar instructions and add them to the work list.
9303 // The next iteration over the work list will lower these to the vector
9304 // unit as necessary.
9305 if (Src0IsSGPR) {
9306 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
9307 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9308 .addReg(Temp)
9309 .add(Src1);
9310 } else if (Src1IsSGPR) {
9311 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
9312 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9313 .add(Src0)
9314 .addReg(Temp);
9315 } else {
9316 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
9317 .add(Src0)
9318 .add(Src1);
9319 MachineInstr *Not =
9320 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
9321 Worklist.insert(Not);
9322 }
9323
9324 MRI.replaceRegWith(Dest.getReg(), NewDest);
9325
9326 Worklist.insert(Xor);
9327
9328 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9329 }
9330}
9331
9332void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
9333 MachineInstr &Inst,
9334 unsigned Opcode) const {
9335 MachineBasicBlock &MBB = *Inst.getParent();
9336 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9337 MachineBasicBlock::iterator MII = Inst;
9338 const DebugLoc &DL = Inst.getDebugLoc();
9339
9340 MachineOperand &Dest = Inst.getOperand(0);
9341 MachineOperand &Src0 = Inst.getOperand(1);
9342 MachineOperand &Src1 = Inst.getOperand(2);
9343
9344 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9345 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9346
9347 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
9348 .add(Src0)
9349 .add(Src1);
9350
9351 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
9352 .addReg(Interm);
9353
9354 Worklist.insert(&Op);
9355 Worklist.insert(&Not);
9356
9357 MRI.replaceRegWith(Dest.getReg(), NewDest);
9358 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9359}
9360
9361void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
9362 MachineInstr &Inst,
9363 unsigned Opcode) const {
9364 MachineBasicBlock &MBB = *Inst.getParent();
9365 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9366 MachineBasicBlock::iterator MII = Inst;
9367 const DebugLoc &DL = Inst.getDebugLoc();
9368
9369 MachineOperand &Dest = Inst.getOperand(0);
9370 MachineOperand &Src0 = Inst.getOperand(1);
9371 MachineOperand &Src1 = Inst.getOperand(2);
9372
9373 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9374 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9375
9376 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
9377 .add(Src1);
9378
9379 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
9380 .add(Src0)
9381 .addReg(Interm);
9382
9383 Worklist.insert(&Not);
9384 Worklist.insert(&Op);
9385
9386 MRI.replaceRegWith(Dest.getReg(), NewDest);
9387 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9388}
9389
9390void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
9391 MachineInstr &Inst, unsigned Opcode,
9392 bool Swap) const {
9393 MachineBasicBlock &MBB = *Inst.getParent();
9394 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9395
9396 MachineOperand &Dest = Inst.getOperand(0);
9397 MachineOperand &Src0 = Inst.getOperand(1);
9398 const DebugLoc &DL = Inst.getDebugLoc();
9399
9400 MachineBasicBlock::iterator MII = Inst;
9401
9402 const MCInstrDesc &InstDesc = get(Opcode);
9403 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9404 MRI.getRegClass(Src0.getReg()) :
9405 &AMDGPU::SGPR_32RegClass;
9406
9407 const TargetRegisterClass *Src0SubRC =
9408 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9409
9410 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9411 AMDGPU::sub0, Src0SubRC);
9412
9413 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9414 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9415 const TargetRegisterClass *NewDestSubRC =
9416 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9417
9418 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9419 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
9420
9421 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9422 AMDGPU::sub1, Src0SubRC);
9423
9424 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9425 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
9426
9427 if (Swap)
9428 std::swap(DestSub0, DestSub1);
9429
9430 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9431 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9432 .addReg(DestSub0)
9433 .addImm(AMDGPU::sub0)
9434 .addReg(DestSub1)
9435 .addImm(AMDGPU::sub1);
9436
9437 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9438
9439 Worklist.insert(&LoHalf);
9440 Worklist.insert(&HiHalf);
9441
9442 // We don't need to legalizeOperands here because for a single operand, src0
9443 // will support any kind of input.
9444
9445 // Move all users of this moved value.
9446 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9447}
9448
9449// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9450// split the s_mul_u64 in 32-bit vector multiplications.
9451void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9452 MachineInstr &Inst,
9453 MachineDominatorTree *MDT) const {
9454 MachineBasicBlock &MBB = *Inst.getParent();
9455 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9456
9457 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9458 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9459 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9460
9461 MachineOperand &Dest = Inst.getOperand(0);
9462 MachineOperand &Src0 = Inst.getOperand(1);
9463 MachineOperand &Src1 = Inst.getOperand(2);
9464 const DebugLoc &DL = Inst.getDebugLoc();
9465 MachineBasicBlock::iterator MII = Inst;
9466
9467 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9468 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9469 const TargetRegisterClass *Src0SubRC =
9470 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9471 if (RI.isSGPRClass(Src0SubRC))
9472 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9473 const TargetRegisterClass *Src1SubRC =
9474 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9475 if (RI.isSGPRClass(Src1SubRC))
9476 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9477
9478 // First, we extract the low 32-bit and high 32-bit values from each of the
9479 // operands.
9480 MachineOperand Op0L =
9481 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9482 MachineOperand Op1L =
9483 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9484 MachineOperand Op0H =
9485 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9486 MachineOperand Op1H =
9487 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9488
9489 // The multilication is done as follows:
9490 //
9491 // Op1H Op1L
9492 // * Op0H Op0L
9493 // --------------------
9494 // Op1H*Op0L Op1L*Op0L
9495 // + Op1H*Op0H Op1L*Op0H
9496 // -----------------------------------------
9497 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9498 //
9499 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9500 // value and that would overflow.
9501 // The low 32-bit value is Op1L*Op0L.
9502 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9503
9504 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9505 MachineInstr *Op1L_Op0H =
9506 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9507 .add(Op1L)
9508 .add(Op0H);
9509
9510 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9511 MachineInstr *Op1H_Op0L =
9512 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9513 .add(Op1H)
9514 .add(Op0L);
9515
9516 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9517 MachineInstr *Carry =
9518 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9519 .add(Op1L)
9520 .add(Op0L);
9521
9522 MachineInstr *LoHalf =
9523 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9524 .add(Op1L)
9525 .add(Op0L);
9526
9527 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9528 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9529 .addReg(Op1L_Op0H_Reg)
9530 .addReg(Op1H_Op0L_Reg);
9531
9532 MachineInstr *HiHalf =
9533 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9534 .addReg(AddReg)
9535 .addReg(CarryReg);
9536
9537 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9538 .addReg(DestSub0)
9539 .addImm(AMDGPU::sub0)
9540 .addReg(DestSub1)
9541 .addImm(AMDGPU::sub1);
9542
9543 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9544
9545 // Try to legalize the operands in case we need to swap the order to keep it
9546 // valid.
9547 legalizeOperands(*Op1L_Op0H, MDT);
9548 legalizeOperands(*Op1H_Op0L, MDT);
9549 legalizeOperands(*Carry, MDT);
9550 legalizeOperands(*LoHalf, MDT);
9551 legalizeOperands(*Add, MDT);
9552 legalizeOperands(*HiHalf, MDT);
9553
9554 // Move all users of this moved value.
9555 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9556}
9557
9558// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9559// multiplications.
9560void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9561 MachineInstr &Inst,
9562 MachineDominatorTree *MDT) const {
9563 MachineBasicBlock &MBB = *Inst.getParent();
9564 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9565
9566 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9567 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9568 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9569
9570 MachineOperand &Dest = Inst.getOperand(0);
9571 MachineOperand &Src0 = Inst.getOperand(1);
9572 MachineOperand &Src1 = Inst.getOperand(2);
9573 const DebugLoc &DL = Inst.getDebugLoc();
9574 MachineBasicBlock::iterator MII = Inst;
9575
9576 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9577 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9578 const TargetRegisterClass *Src0SubRC =
9579 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9580 if (RI.isSGPRClass(Src0SubRC))
9581 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9582 const TargetRegisterClass *Src1SubRC =
9583 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9584 if (RI.isSGPRClass(Src1SubRC))
9585 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9586
9587 // First, we extract the low 32-bit and high 32-bit values from each of the
9588 // operands.
9589 MachineOperand Op0L =
9590 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9591 MachineOperand Op1L =
9592 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9593
9594 unsigned Opc = Inst.getOpcode();
9595 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9596 ? AMDGPU::V_MUL_HI_U32_e64
9597 : AMDGPU::V_MUL_HI_I32_e64;
9598 MachineInstr *HiHalf =
9599 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9600
9601 MachineInstr *LoHalf =
9602 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9603 .add(Op1L)
9604 .add(Op0L);
9605
9606 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9607 .addReg(DestSub0)
9608 .addImm(AMDGPU::sub0)
9609 .addReg(DestSub1)
9610 .addImm(AMDGPU::sub1);
9611
9612 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9613
9614 // Try to legalize the operands in case we need to swap the order to keep it
9615 // valid.
9616 legalizeOperands(*HiHalf, MDT);
9617 legalizeOperands(*LoHalf, MDT);
9618
9619 // Move all users of this moved value.
9620 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9621}
9622
9623void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9624 MachineInstr &Inst, unsigned Opcode,
9625 MachineDominatorTree *MDT) const {
9626 MachineBasicBlock &MBB = *Inst.getParent();
9627 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9628
9629 MachineOperand &Dest = Inst.getOperand(0);
9630 MachineOperand &Src0 = Inst.getOperand(1);
9631 MachineOperand &Src1 = Inst.getOperand(2);
9632 const DebugLoc &DL = Inst.getDebugLoc();
9633
9634 MachineBasicBlock::iterator MII = Inst;
9635
9636 const MCInstrDesc &InstDesc = get(Opcode);
9637 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9638 MRI.getRegClass(Src0.getReg()) :
9639 &AMDGPU::SGPR_32RegClass;
9640
9641 const TargetRegisterClass *Src0SubRC =
9642 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9643 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9644 MRI.getRegClass(Src1.getReg()) :
9645 &AMDGPU::SGPR_32RegClass;
9646
9647 const TargetRegisterClass *Src1SubRC =
9648 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9649
9650 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9651 AMDGPU::sub0, Src0SubRC);
9652 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9653 AMDGPU::sub0, Src1SubRC);
9654 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9655 AMDGPU::sub1, Src0SubRC);
9656 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9657 AMDGPU::sub1, Src1SubRC);
9658
9659 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9660 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9661 const TargetRegisterClass *NewDestSubRC =
9662 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9663
9664 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9665 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9666 .add(SrcReg0Sub0)
9667 .add(SrcReg1Sub0);
9668
9669 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9670 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9671 .add(SrcReg0Sub1)
9672 .add(SrcReg1Sub1);
9673
9674 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9675 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9676 .addReg(DestSub0)
9677 .addImm(AMDGPU::sub0)
9678 .addReg(DestSub1)
9679 .addImm(AMDGPU::sub1);
9680
9681 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9682
9683 Worklist.insert(&LoHalf);
9684 Worklist.insert(&HiHalf);
9685
9686 // Move all users of this moved value.
9687 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9688}
9689
9690void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9691 MachineInstr &Inst,
9692 MachineDominatorTree *MDT) const {
9693 MachineBasicBlock &MBB = *Inst.getParent();
9694 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9695
9696 MachineOperand &Dest = Inst.getOperand(0);
9697 MachineOperand &Src0 = Inst.getOperand(1);
9698 MachineOperand &Src1 = Inst.getOperand(2);
9699 const DebugLoc &DL = Inst.getDebugLoc();
9700
9701 MachineBasicBlock::iterator MII = Inst;
9702
9703 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9704
9705 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9706
9707 MachineOperand* Op0;
9708 MachineOperand* Op1;
9709
9710 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9711 Op0 = &Src0;
9712 Op1 = &Src1;
9713 } else {
9714 Op0 = &Src1;
9715 Op1 = &Src0;
9716 }
9717
9718 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9719 .add(*Op0);
9720
9721 Register NewDest = MRI.createVirtualRegister(DestRC);
9722
9723 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9724 .addReg(Interm)
9725 .add(*Op1);
9726
9727 MRI.replaceRegWith(Dest.getReg(), NewDest);
9728
9729 Worklist.insert(&Xor);
9730}
9731
9732void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9733 MachineInstr &Inst) const {
9734 MachineBasicBlock &MBB = *Inst.getParent();
9735 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9736
9737 MachineBasicBlock::iterator MII = Inst;
9738 const DebugLoc &DL = Inst.getDebugLoc();
9739
9740 MachineOperand &Dest = Inst.getOperand(0);
9741 MachineOperand &Src = Inst.getOperand(1);
9742
9743 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9744 const TargetRegisterClass *SrcRC = Src.isReg() ?
9745 MRI.getRegClass(Src.getReg()) :
9746 &AMDGPU::SGPR_32RegClass;
9747
9748 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9749 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9750
9751 const TargetRegisterClass *SrcSubRC =
9752 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9753
9754 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9755 AMDGPU::sub0, SrcSubRC);
9756 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9757 AMDGPU::sub1, SrcSubRC);
9758
9759 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9760
9761 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9762
9763 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9764
9765 // We don't need to legalize operands here. src0 for either instruction can be
9766 // an SGPR, and the second input is unused or determined here.
9767 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9768}
9769
9770void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9771 MachineInstr &Inst) const {
9772 MachineBasicBlock &MBB = *Inst.getParent();
9773 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9774 MachineBasicBlock::iterator MII = Inst;
9775 const DebugLoc &DL = Inst.getDebugLoc();
9776
9777 MachineOperand &Dest = Inst.getOperand(0);
9778 uint32_t Imm = Inst.getOperand(2).getImm();
9779 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9780 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9781
9782 (void) Offset;
9783
9784 // Only sext_inreg cases handled.
9785 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9786 Offset == 0 && "Not implemented");
9787
9788 if (BitWidth < 32) {
9789 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9790 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9791 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9792
9793 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9794 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9795 .addImm(0)
9796 .addImm(BitWidth);
9797
9798 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9799 .addImm(31)
9800 .addReg(MidRegLo);
9801
9802 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9803 .addReg(MidRegLo)
9804 .addImm(AMDGPU::sub0)
9805 .addReg(MidRegHi)
9806 .addImm(AMDGPU::sub1);
9807
9808 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9809 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9810 return;
9811 }
9812
9813 MachineOperand &Src = Inst.getOperand(1);
9814 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9815 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9816
9817 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9818 .addImm(31)
9819 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9820
9821 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9822 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9823 .addImm(AMDGPU::sub0)
9824 .addReg(TmpReg)
9825 .addImm(AMDGPU::sub1);
9826
9827 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9828 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9829}
9830
9831void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9832 MachineInstr &Inst, unsigned Opcode,
9833 MachineDominatorTree *MDT) const {
9834 // (S_FLBIT_I32_B64 hi:lo) ->
9835 // -> (umin (V_FFBH_U32_e32 hi), (or (V_FFBH_U32_e32 lo), 32))
9836 // (S_FF1_I32_B64 hi:lo) ->
9837 // ->(umin (or (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9838
9839 MachineBasicBlock &MBB = *Inst.getParent();
9840 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9841 MachineBasicBlock::iterator MII = Inst;
9842 const DebugLoc &DL = Inst.getDebugLoc();
9843
9844 MachineOperand &Dest = Inst.getOperand(0);
9845 MachineOperand &Src = Inst.getOperand(1);
9846
9847 const MCInstrDesc &InstDesc = get(Opcode);
9848
9849 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9850
9851 const TargetRegisterClass *SrcRC =
9852 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9853 const TargetRegisterClass *SrcSubRC =
9854 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9855
9856 MachineOperand SrcRegSub0 =
9857 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9858 MachineOperand SrcRegSub1 =
9859 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9860
9861 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9862 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9863 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9864 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9865
9866 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9867
9868 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9869
9870 BuildMI(MBB, MII, DL, get(AMDGPU::V_OR_B32_e32), MidReg3)
9871 .addImm(32)
9872 .addReg(IsCtlz ? MidReg1 : MidReg2);
9873
9874 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9875 .addReg(MidReg3)
9876 .addReg(IsCtlz ? MidReg2 : MidReg1);
9877
9878 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9879
9880 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9881}
9882
9883void SIInstrInfo::addUsersToMoveToVALUWorklist(
9885 SIInstrWorklist &Worklist) const {
9886 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9887 MachineInstr &UseMI = *MO.getParent();
9888
9889 unsigned OpNo = 0;
9890
9891 switch (UseMI.getOpcode()) {
9892 case AMDGPU::COPY:
9893 case AMDGPU::WQM:
9894 case AMDGPU::SOFT_WQM:
9895 case AMDGPU::STRICT_WWM:
9896 case AMDGPU::STRICT_WQM:
9897 case AMDGPU::REG_SEQUENCE:
9898 case AMDGPU::PHI:
9899 case AMDGPU::INSERT_SUBREG:
9900 break;
9901 default:
9902 OpNo = MO.getOperandNo();
9903 break;
9904 }
9905
9906 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9907 MRI.constrainRegClass(DstReg, OpRC);
9908
9909 if (!RI.hasVectorRegisters(OpRC))
9910 Worklist.insert(&UseMI);
9911 else
9912 // Legalization could change user list.
9914 }
9915}
9916
9917void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
9919 MachineInstr &Inst) const {
9920 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9921 MachineBasicBlock *MBB = Inst.getParent();
9922 MachineOperand &Src0 = Inst.getOperand(1);
9923 MachineOperand &Src1 = Inst.getOperand(2);
9924 const DebugLoc &DL = Inst.getDebugLoc();
9925
9926 if (ST.useRealTrue16Insts()) {
9927 Register SrcReg0, SrcReg1;
9928 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
9929 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9930 BuildMI(*MBB, Inst, DL,
9931 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9932 .add(Src0);
9933 } else {
9934 SrcReg0 = Src0.getReg();
9935 }
9936
9937 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
9938 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9939 BuildMI(*MBB, Inst, DL,
9940 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9941 .add(Src1);
9942 } else {
9943 SrcReg1 = Src1.getReg();
9944 }
9945
9946 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
9947 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
9948
9949 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
9950 switch (Inst.getOpcode()) {
9951 case AMDGPU::S_PACK_LL_B32_B16:
9952 NewMI
9953 .addReg(SrcReg0, {},
9954 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9955 .addImm(AMDGPU::lo16)
9956 .addReg(SrcReg1, {},
9957 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9958 .addImm(AMDGPU::hi16);
9959 break;
9960 case AMDGPU::S_PACK_LH_B32_B16:
9961 NewMI
9962 .addReg(SrcReg0, {},
9963 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9964 .addImm(AMDGPU::lo16)
9965 .addReg(SrcReg1, {}, AMDGPU::hi16)
9966 .addImm(AMDGPU::hi16);
9967 break;
9968 case AMDGPU::S_PACK_HL_B32_B16:
9969 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9970 .addImm(AMDGPU::lo16)
9971 .addReg(SrcReg1, {},
9972 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9973 .addImm(AMDGPU::hi16);
9974 break;
9975 case AMDGPU::S_PACK_HH_B32_B16:
9976 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9977 .addImm(AMDGPU::lo16)
9978 .addReg(SrcReg1, {}, AMDGPU::hi16)
9979 .addImm(AMDGPU::hi16);
9980 break;
9981 default:
9982 llvm_unreachable("unhandled s_pack_* instruction");
9983 }
9984
9985 MachineOperand &Dest = Inst.getOperand(0);
9986 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9987 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9988 return;
9989 }
9990
9991 switch (Inst.getOpcode()) {
9992 case AMDGPU::S_PACK_LL_B32_B16: {
9993 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9994 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9995
9996 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
9997 // 0.
9998 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9999 .addImm(0xffff);
10000
10001 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
10002 .addReg(ImmReg)
10003 .add(Src0);
10004
10005 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
10006 .add(Src1)
10007 .addImm(16)
10008 .addReg(TmpReg);
10009 break;
10010 }
10011 case AMDGPU::S_PACK_LH_B32_B16: {
10012 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10013 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10014 .addImm(0xffff);
10015 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
10016 .addReg(ImmReg)
10017 .add(Src0)
10018 .add(Src1);
10019 break;
10020 }
10021 case AMDGPU::S_PACK_HL_B32_B16: {
10022 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10023 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
10024 .addImm(16)
10025 .add(Src0);
10026 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
10027 .add(Src1)
10028 .addImm(16)
10029 .addReg(TmpReg);
10030 break;
10031 }
10032 case AMDGPU::S_PACK_HH_B32_B16: {
10033 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10034 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10035 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
10036 .addImm(16)
10037 .add(Src0);
10038 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10039 .addImm(0xffff0000);
10040 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
10041 .add(Src1)
10042 .addReg(ImmReg)
10043 .addReg(TmpReg);
10044 break;
10045 }
10046 default:
10047 llvm_unreachable("unhandled s_pack_* instruction");
10048 }
10049
10050 MachineOperand &Dest = Inst.getOperand(0);
10051 MRI.replaceRegWith(Dest.getReg(), ResultReg);
10052 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10053}
10054
10055void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
10056 MachineInstr &SCCDefInst,
10057 SIInstrWorklist &Worklist,
10058 Register NewCond) const {
10059
10060 // Ensure that def inst defines SCC, which is still live.
10061 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
10062 !Op.isDead() && Op.getParent() == &SCCDefInst);
10063 SmallVector<MachineInstr *, 4> CopyToDelete;
10064 // This assumes that all the users of SCC are in the same block
10065 // as the SCC def.
10066 for (MachineInstr &MI : // Skip the def inst itself.
10067 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
10068 SCCDefInst.getParent()->end())) {
10069 // Check if SCC is used first.
10070 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
10071 if (SCCIdx != -1) {
10072 if (MI.isCopy()) {
10073 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10074 Register DestReg = MI.getOperand(0).getReg();
10075
10076 MRI.replaceRegWith(DestReg, NewCond);
10077 CopyToDelete.push_back(&MI);
10078 } else {
10079
10080 if (NewCond.isValid())
10081 MI.getOperand(SCCIdx).setReg(NewCond);
10082
10083 Worklist.insert(&MI);
10084 }
10085 }
10086 // Exit if we find another SCC def.
10087 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
10088 break;
10089 }
10090 for (auto &Copy : CopyToDelete)
10091 Copy->eraseFromParent();
10092}
10093
10094// Instructions that use SCC may be converted to VALU instructions. When that
10095// happens, the SCC register is changed to VCC_LO. The instruction that defines
10096// SCC must be changed to an instruction that defines VCC. This function makes
10097// sure that the instruction that defines SCC is added to the moveToVALU
10098// worklist.
10099void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
10100 SIInstrWorklist &Worklist) const {
10101 // Look for a preceding instruction that either defines VCC or SCC. If VCC
10102 // then there is nothing to do because the defining instruction has been
10103 // converted to a VALU already. If SCC then that instruction needs to be
10104 // converted to a VALU.
10105 for (MachineInstr &MI :
10106 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
10107 SCCUseInst->getParent()->rend())) {
10108 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
10109 break;
10110 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
10111 Worklist.insert(&MI);
10112 break;
10113 }
10114 }
10115}
10116
10117const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
10118 const MachineInstr &Inst) const {
10119 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
10120
10121 switch (Inst.getOpcode()) {
10122 // For target instructions, getOpRegClass just returns the virtual register
10123 // class associated with the operand, so we need to find an equivalent VGPR
10124 // register class in order to move the instruction to the VALU.
10125 case AMDGPU::COPY:
10126 case AMDGPU::PHI:
10127 case AMDGPU::REG_SEQUENCE:
10128 case AMDGPU::INSERT_SUBREG:
10129 case AMDGPU::WQM:
10130 case AMDGPU::SOFT_WQM:
10131 case AMDGPU::STRICT_WWM:
10132 case AMDGPU::STRICT_WQM: {
10133 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
10134 if (RI.isAGPRClass(SrcRC)) {
10135 if (RI.isAGPRClass(NewDstRC))
10136 return nullptr;
10137
10138 switch (Inst.getOpcode()) {
10139 case AMDGPU::PHI:
10140 case AMDGPU::REG_SEQUENCE:
10141 case AMDGPU::INSERT_SUBREG:
10142 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10143 break;
10144 default:
10145 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10146 }
10147
10148 if (!NewDstRC)
10149 return nullptr;
10150 } else {
10151 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10152 return nullptr;
10153
10154 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10155 if (!NewDstRC)
10156 return nullptr;
10157 }
10158
10159 return NewDstRC;
10160 }
10161 default:
10162 return NewDstRC;
10163 }
10164}
10165
10166// Find the one SGPR operand we are allowed to use.
10167Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
10168 int OpIndices[3]) const {
10169 const MCInstrDesc &Desc = MI.getDesc();
10170
10171 // Find the one SGPR operand we are allowed to use.
10172 //
10173 // First we need to consider the instruction's operand requirements before
10174 // legalizing. Some operands are required to be SGPRs, such as implicit uses
10175 // of VCC, but we are still bound by the constant bus requirement to only use
10176 // one.
10177 //
10178 // If the operand's class is an SGPR, we can never move it.
10179
10180 Register SGPRReg = findImplicitSGPRRead(MI);
10181 if (SGPRReg)
10182 return SGPRReg;
10183
10184 Register UsedSGPRs[3] = {Register()};
10185 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10186
10187 for (unsigned i = 0; i < 3; ++i) {
10188 int Idx = OpIndices[i];
10189 if (Idx == -1)
10190 break;
10191
10192 const MachineOperand &MO = MI.getOperand(Idx);
10193 if (!MO.isReg())
10194 continue;
10195
10196 // Is this operand statically required to be an SGPR based on the operand
10197 // constraints?
10198 const TargetRegisterClass *OpRC =
10199 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
10200 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10201 if (IsRequiredSGPR)
10202 return MO.getReg();
10203
10204 // If this could be a VGPR or an SGPR, Check the dynamic register class.
10205 Register Reg = MO.getReg();
10206 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
10207 if (RI.isSGPRClass(RegRC))
10208 UsedSGPRs[i] = Reg;
10209 }
10210
10211 // We don't have a required SGPR operand, so we have a bit more freedom in
10212 // selecting operands to move.
10213
10214 // Try to select the most used SGPR. If an SGPR is equal to one of the
10215 // others, we choose that.
10216 //
10217 // e.g.
10218 // V_FMA_F32 v0, s0, s0, s0 -> No moves
10219 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
10220
10221 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
10222 // prefer those.
10223
10224 if (UsedSGPRs[0]) {
10225 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10226 SGPRReg = UsedSGPRs[0];
10227 }
10228
10229 if (!SGPRReg && UsedSGPRs[1]) {
10230 if (UsedSGPRs[1] == UsedSGPRs[2])
10231 SGPRReg = UsedSGPRs[1];
10232 }
10233
10234 return SGPRReg;
10235}
10236
10238 AMDGPU::OpName OperandName) const {
10239 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10240 return nullptr;
10241
10242 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
10243 if (Idx == -1)
10244 return nullptr;
10245
10246 return &MI.getOperand(Idx);
10247}
10248
10250 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
10251 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
10254 return (Format << 44) |
10255 (1ULL << 56) | // RESOURCE_LEVEL = 1
10256 (3ULL << 60); // OOB_SELECT = 3
10257 }
10258
10259 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
10260 if (ST.isAmdHsaOS()) {
10261 // Set ATC = 1. GFX9 doesn't have this bit.
10262 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10263 RsrcDataFormat |= (1ULL << 56);
10264
10265 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
10266 // BTW, it disables TC L2 and therefore decreases performance.
10267 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
10268 RsrcDataFormat |= (2ULL << 59);
10269 }
10270
10271 return RsrcDataFormat;
10272}
10273
10275 uint64_t Rsrc23 = getDefaultRsrcDataFormat() |
10277 0xffffffff; // Size;
10278
10279 // GFX9 doesn't have ELEMENT_SIZE.
10280 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
10281 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
10282 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
10283 }
10284
10285 // IndexStride = 64 / 32.
10286 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10287 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
10288
10289 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
10290 // Clear them unless we want a huge stride.
10291 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
10292 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
10293 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
10294
10295 return Rsrc23;
10296}
10297
10299 unsigned Opc = MI.getOpcode();
10300
10301 return isSMRD(Opc);
10302}
10303
10305 return get(Opc).mayLoad() &&
10306 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
10307}
10308
10310 TypeSize &MemBytes) const {
10311 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
10312 if (!Addr || !Addr->isFI())
10313 return Register();
10314
10315 assert(!MI.memoperands_empty() &&
10316 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
10317
10318 FrameIndex = Addr->getIndex();
10319
10320 int VDataIdx =
10321 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
10322 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
10323 return MI.getOperand(VDataIdx).getReg();
10324}
10325
10327 TypeSize &MemBytes) const {
10328 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
10329 assert(Addr && Addr->isFI());
10330 FrameIndex = Addr->getIndex();
10331
10332 int DataIdx =
10333 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
10334 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
10335 return MI.getOperand(DataIdx).getReg();
10336}
10337
10339 int &FrameIndex,
10340 TypeSize &MemBytes) const {
10341 if (!MI.mayLoad())
10342 return Register();
10343
10344 if (isMUBUF(MI) || isVGPRSpill(MI))
10345 return isStackAccess(MI, FrameIndex, MemBytes);
10346
10347 if (isSGPRSpill(MI))
10348 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10349
10350 return Register();
10351}
10352
10354 int &FrameIndex,
10355 TypeSize &MemBytes) const {
10356 if (!MI.mayStore())
10357 return Register();
10358
10359 if (isMUBUF(MI) || isVGPRSpill(MI))
10360 return isStackAccess(MI, FrameIndex, MemBytes);
10361
10362 if (isSGPRSpill(MI))
10363 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10364
10365 return Register();
10366}
10367
10369 unsigned Opc = MI.getOpcode();
10371 unsigned DescSize = Desc.getSize();
10372
10373 // If we have a definitive size, we can use it. Otherwise we need to inspect
10374 // the operands to know the size.
10375 if (isFixedSize(MI)) {
10376 unsigned Size = DescSize;
10377
10378 // If we hit the buggy offset, an extra nop will be inserted in MC so
10379 // estimate the worst case.
10380 if (MI.isBranch() && ST.hasOffset3fBug())
10381 Size += 4;
10382
10383 return Size;
10384 }
10385
10386 // Instructions may have a 32-bit literal encoded after them. Check
10387 // operands that could ever be literals.
10388 if (isVALU(MI, /*AllowLDSDMA=*/false) || isSALU(MI)) {
10389 if (isDPP(MI))
10390 return DescSize;
10391 bool HasLiteral = false;
10392 unsigned LiteralSize = 4;
10393 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
10394 const MachineOperand &Op = MI.getOperand(I);
10395 const MCOperandInfo &OpInfo = Desc.operands()[I];
10396 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
10397 HasLiteral = true;
10398 if (ST.has64BitLiterals()) {
10399 switch (OpInfo.OperandType) {
10400 default:
10401 break;
10404 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
10405 LiteralSize = 8;
10406 break;
10409 // A 32-bit literal is only valid when the value fits in BOTH signed
10410 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
10411 // emitter's getLit64Encoding logic. This is because of the lack of
10412 // abilility to tell signedness of the literal, therefore we need to
10413 // be conservative and assume values outside this range require a
10414 // 64-bit literal encoding (8 bytes).
10415 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
10416 !isUInt<32>(Op.getImm()))
10417 LiteralSize = 8;
10418 break;
10419 }
10420 }
10421 break;
10422 }
10423 }
10424 return HasLiteral ? DescSize + LiteralSize : DescSize;
10425 }
10426
10427 // Check whether we have extra NSA words.
10428 if (isMIMG(MI)) {
10429 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
10430 if (VAddr0Idx < 0)
10431 return 8;
10432
10433 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
10434 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10435 }
10436
10437 switch (Opc) {
10438 case TargetOpcode::BUNDLE:
10439 return getInstBundleSize(MI);
10440 case TargetOpcode::INLINEASM:
10441 case TargetOpcode::INLINEASM_BR: {
10442 const MachineFunction *MF = MI.getMF();
10443 const char *AsmStr = MI.getOperand(0).getSymbolName();
10444 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10445 }
10446 default:
10447 if (MI.isMetaInstruction())
10448 return 0;
10449
10450 // If D16 Pseudo inst, get correct MC code size
10451 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10452 if (D16Info) {
10453 // Assume d16_lo/hi inst are always in same size
10454 unsigned LoInstOpcode = D16Info->LoOp;
10455 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10456 DescSize = Desc.getSize();
10457 }
10458
10459 // If FMA Pseudo inst, get correct MC code size
10460 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10461 // All potential lowerings are the same size; arbitrarily pick one.
10462 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10463 DescSize = Desc.getSize();
10464 }
10465
10466 return DescSize;
10467 }
10468}
10469
10472 if (MI.isBranch() && ST.hasOffset3fBug())
10473 return InstSizeVerifyMode::NoVerify;
10474 return InstSizeVerifyMode::ExactSize;
10475}
10476
10479 static const std::pair<int, const char *> TargetIndices[] = {
10480 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10481 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10482 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10483 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10484 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10485 return ArrayRef(TargetIndices);
10486}
10487
10488/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10489/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10492 const ScheduleDAG *DAG) const {
10493 return new GCNHazardRecognizer(DAG->MF);
10494}
10495
10496/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10497/// pass.
10504
10505// Called during:
10506// - pre-RA scheduling and post-RA scheduling
10509 const ScheduleDAGMI *DAG) const {
10510 // Borrowed from Arm Target
10511 // We would like to restrict this hazard recognizer to only
10512 // post-RA scheduling; we can tell that we're post-RA because we don't
10513 // track VRegLiveness.
10514 if (!DAG->hasVRegLiveness())
10515 return new GCNHazardRecognizer(DAG->MF);
10517}
10518
10519std::pair<unsigned, unsigned>
10521 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10522}
10523
10526 static const std::pair<unsigned, const char *> TargetFlags[] = {
10527 {MO_GOTPCREL, "amdgpu-gotprel"},
10528 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10529 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10530 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10531 {MO_REL32_LO, "amdgpu-rel32-lo"},
10532 {MO_REL32_HI, "amdgpu-rel32-hi"},
10533 {MO_REL64, "amdgpu-rel64"},
10534 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10535 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10536 {MO_ABS64, "amdgpu-abs64"},
10537 };
10538
10539 return ArrayRef(TargetFlags);
10540}
10541
10544 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10545 {
10546 {MONoClobber, "amdgpu-noclobber"},
10547 {MOLastUse, "amdgpu-last-use"},
10548 {MOCooperative, "amdgpu-cooperative"},
10549 {MOThreadPrivate, "amdgpu-thread-private"},
10550 {MOCFSB0, "amdgpu-cfs0"},
10551 {MOCFSB1, "amdgpu-cfs1"},
10552 };
10553
10554 return ArrayRef(TargetFlags);
10555}
10556
10558 const MachineFunction &MF) const {
10560 assert(SrcReg.isVirtual());
10561 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10562 return AMDGPU::WWM_COPY;
10563
10564 return AMDGPU::COPY;
10565}
10566
10568 uint32_t Opcode = MI.getOpcode();
10569 // Check if it is SGPR spill or wwm-register spill Opcode.
10570 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10571 return true;
10572
10573 const MachineFunction *MF = MI.getMF();
10574 const MachineRegisterInfo &MRI = MF->getRegInfo();
10576
10577 // See if this is Liverange split instruction inserted for SGPR or
10578 // wwm-register. The implicit def inserted for wwm-registers should also be
10579 // included as they can appear at the bb begin.
10580 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10581 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10582 return false;
10583
10584 Register Reg = MI.getOperand(0).getReg();
10585 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10586 return IsLRSplitInst;
10587
10588 return MFI->isWWMReg(Reg);
10589}
10590
10592 Register Reg) const {
10593 // We need to handle instructions which may be inserted during register
10594 // allocation to handle the prolog. The initial prolog instruction may have
10595 // been separated from the start of the block by spills and copies inserted
10596 // needed by the prolog. However, the insertions for scalar registers can
10597 // always be placed at the BB top as they are independent of the exec mask
10598 // value.
10599 bool IsNullOrVectorRegister = true;
10600 if (Reg) {
10601 const MachineFunction *MF = MI.getMF();
10602 const MachineRegisterInfo &MRI = MF->getRegInfo();
10603 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10604 }
10605
10606 return IsNullOrVectorRegister &&
10607 (canAddToBBProlog(MI) ||
10608 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10609 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10610}
10611
10615 const DebugLoc &DL,
10616 Register DestReg) const {
10617 if (ST.hasAddNoCarryInsts())
10618 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10619
10620 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10621 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10622 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10623
10624 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10625 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10626}
10627
10630 const DebugLoc &DL,
10631 Register DestReg,
10632 RegScavenger &RS) const {
10633 if (ST.hasAddNoCarryInsts())
10634 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10635
10636 // If available, prefer to use vcc.
10637 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10638 ? Register(RI.getVCC())
10639 : RS.scavengeRegisterBackwards(
10640 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10641 0, /* AllowSpill */ false);
10642
10643 // TODO: Users need to deal with this.
10644 if (!UnusedCarry.isValid())
10645 return MachineInstrBuilder();
10646
10647 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10648 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10649}
10650
10651bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10652 switch (Opcode) {
10653 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10654 case AMDGPU::SI_KILL_I1_TERMINATOR:
10655 return true;
10656 default:
10657 return false;
10658 }
10659}
10660
10662 switch (Opcode) {
10663 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10664 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10665 case AMDGPU::SI_KILL_I1_PSEUDO:
10666 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10667 default:
10668 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10669 }
10670}
10671
10673 return Imm <= getMaxMUBUFImmOffset(ST);
10674}
10675
10677 // GFX12 field is non-negative 24-bit signed byte offset.
10678 const unsigned OffsetBits =
10679 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10680 return (1 << OffsetBits) - 1;
10681}
10682
10684 if (!ST.isWave32())
10685 return;
10686
10687 if (MI.isInlineAsm())
10688 return;
10689
10690 if (MI.getNumOperands() < MI.getDesc().getNumOperands())
10691 return;
10692
10693 for (auto &Op : MI.implicit_operands()) {
10694 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10695 Op.setReg(AMDGPU::VCC_LO);
10696 }
10697}
10698
10700 if (!isSMRD(MI))
10701 return false;
10702
10703 // Check that it is using a buffer resource.
10704 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10705 if (Idx == -1) // e.g. s_memtime
10706 return false;
10707
10708 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10709 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10710}
10711
10712// Given Imm, split it into the values to put into the SOffset and ImmOffset
10713// fields in an MUBUF instruction. Return false if it is not possible (due to a
10714// hardware bug needing a workaround).
10715//
10716// The required alignment ensures that individual address components remain
10717// aligned if they are aligned to begin with. It also ensures that additional
10718// offsets within the given alignment can be added to the resulting ImmOffset.
10720 uint32_t &ImmOffset, Align Alignment) const {
10721 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10722 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10723 uint32_t Overflow = 0;
10724
10725 if (Imm > MaxImm) {
10726 if (Imm <= MaxImm + 64) {
10727 // Use an SOffset inline constant for 4..64
10728 Overflow = Imm - MaxImm;
10729 Imm = MaxImm;
10730 } else {
10731 // Try to keep the same value in SOffset for adjacent loads, so that
10732 // the corresponding register contents can be re-used.
10733 //
10734 // Load values with all low-bits (except for alignment bits) set into
10735 // SOffset, so that a larger range of values can be covered using
10736 // s_movk_i32.
10737 //
10738 // Atomic operations fail to work correctly when individual address
10739 // components are unaligned, even if their sum is aligned.
10740 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10741 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10742 Imm = Low;
10743 Overflow = High - Alignment.value();
10744 }
10745 }
10746
10747 if (Overflow > 0) {
10748 // There is a hardware bug in SI and CI which prevents address clamping in
10749 // MUBUF instructions from working correctly with SOffsets. The immediate
10750 // offset is unaffected.
10751 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10752 return false;
10753
10754 // It is not possible to set immediate in SOffset field on some targets.
10755 if (ST.hasRestrictedSOffset())
10756 return false;
10757 }
10758
10759 ImmOffset = Imm;
10760 SOffset = Overflow;
10761 return true;
10762}
10763
10764// Depending on the used address space and instructions, some immediate offsets
10765// are allowed and some are not.
10766// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10767// scratch instruction offsets can also be negative. On GFX12, offsets can be
10768// negative for all variants.
10769//
10770// There are several bugs related to these offsets:
10771// On gfx10.1, flat instructions that go into the global address space cannot
10772// use an offset.
10773//
10774// For scratch instructions, the address can be either an SGPR or a VGPR.
10775// The following offsets can be used, depending on the architecture (x means
10776// cannot be used):
10777// +----------------------------+------+------+
10778// | Address-Mode | SGPR | VGPR |
10779// +----------------------------+------+------+
10780// | gfx9 | | |
10781// | negative, 4-aligned offset | x | ok |
10782// | negative, unaligned offset | x | ok |
10783// +----------------------------+------+------+
10784// | gfx10 | | |
10785// | negative, 4-aligned offset | ok | ok |
10786// | negative, unaligned offset | ok | x |
10787// +----------------------------+------+------+
10788// | gfx10.3 | | |
10789// | negative, 4-aligned offset | ok | ok |
10790// | negative, unaligned offset | ok | ok |
10791// +----------------------------+------+------+
10792//
10793// This function ignores the addressing mode, so if an offset cannot be used in
10794// one addressing mode, it is considered illegal.
10795bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10796 AMDGPU::FlatAddrSpace FlatVariant) const {
10797 // TODO: Should 0 be special cased?
10798 if (!ST.hasFlatInstOffsets())
10799 return false;
10800
10802 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10803 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10804 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10805 return false;
10806
10807 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10808 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10809 (Offset % 4) != 0) {
10810 return false;
10811 }
10812
10813 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10814 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10815 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10816}
10817
10818// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10819std::pair<int64_t, int64_t>
10820SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10821 AMDGPU::FlatAddrSpace FlatVariant) const {
10822 int64_t RemainderOffset = COffsetVal;
10823 int64_t ImmField = 0;
10824
10825 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10826 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10827
10828 if (AllowNegative) {
10829 // Use signed division by a power of two to truncate towards 0.
10830 int64_t D = 1LL << NumBits;
10831 RemainderOffset = (COffsetVal / D) * D;
10832 ImmField = COffsetVal - RemainderOffset;
10833
10834 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10835 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10836 (ImmField % 4) != 0) {
10837 // Make ImmField a multiple of 4
10838 RemainderOffset += ImmField % 4;
10839 ImmField -= ImmField % 4;
10840 }
10841 } else if (COffsetVal >= 0) {
10842 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10843 RemainderOffset = COffsetVal - ImmField;
10844 }
10845
10846 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10847 assert(RemainderOffset + ImmField == COffsetVal);
10848 return {ImmField, RemainderOffset};
10849}
10850
10852 AMDGPU::FlatAddrSpace FlatVariant) const {
10853 if (ST.hasNegativeScratchOffsetBug() &&
10855 return false;
10856
10857 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10858}
10859
10860static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10861 switch (ST.getGeneration()) {
10862 default:
10863 break;
10866 return SIEncodingFamily::SI;
10868 // The GFX80 encoding family only contains buffer instructions with unpacked
10869 // D16 data; pseudoToMCOpcode falls back on VI for everything else.
10870 // TODO: remove this when we discard GFX80 encoding.
10871 return ST.hasUnpackedD16VMem() ? SIEncodingFamily::GFX80
10874 return SIEncodingFamily::VI;
10878 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10881 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10885 }
10886 llvm_unreachable("Unknown subtarget generation!");
10887}
10888
10889bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10890 switch(MCOp) {
10891 // These opcodes use indirect register addressing so
10892 // they need special handling by codegen (currently missing).
10893 // Therefore it is too risky to allow these opcodes
10894 // to be selected by dpp combiner or sdwa peepholer.
10895 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10896 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10897 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10898 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10899 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10900 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10901 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10902 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10903 return true;
10904 default:
10905 return false;
10906 }
10907}
10908
10909#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10910 case OPCODE##_dpp: \
10911 case OPCODE##_e32: \
10912 case OPCODE##_e64:
10913
10914static bool isRenamedInGFX9(int Opcode) {
10915 switch (Opcode) {
10916 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
10917 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
10918 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
10919 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
10920 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
10921 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
10922 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
10923 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
10924 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
10925 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10926 case AMDGPU::V_FMA_F16_gfx9_e64:
10927 case AMDGPU::V_INTERP_P2_F16:
10928 case AMDGPU::V_MAD_F16_e64:
10929 case AMDGPU::V_MAD_U16_e64:
10930 case AMDGPU::V_MAD_I16_e64:
10931 case AMDGPU::V_MAD_U16_gfx9_e64:
10932 case AMDGPU::V_MAD_I16_gfx9_e64:
10933 return true;
10934 default:
10935 return false;
10936 }
10937}
10938
10939int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
10940 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
10941 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10942
10943 unsigned Gen = subtargetEncodingFamily(ST);
10944
10945 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
10947
10948 if (SIInstrFlags::isSDWA(get(Opcode))) {
10949 switch (ST.getGeneration()) {
10950 default:
10952 break;
10955 break;
10958 break;
10959 }
10960 }
10961
10962 if (isMAI(Opcode)) {
10963 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
10964 if (MFMAOp != -1)
10965 Opcode = MFMAOp;
10966 }
10967
10968 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
10969
10970 // Only buffer instructions with unpacked D16 data have a GFX80 encoding.
10971 // Anything else on such a subtarget uses the plain VI encoding.
10972 // TODO: remove this when we discard GFX80 encoding.
10973 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && Gen == SIEncodingFamily::GFX80)
10975
10976 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10978
10979 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10981
10982 // -1 means that Opcode is already a native instruction.
10983 if (MCOp == -1)
10984 return Opcode;
10985
10986 if (ST.hasGFX90AInsts()) {
10987 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10988 if (ST.hasGFX940Insts())
10990 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10992 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10994 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10995 MCOp = NMCOp;
10996 }
10997
10998 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
10999 // encoding in the given subtarget generation.
11000 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
11001 return -1;
11002
11003 if (isAsmOnlyOpcode(MCOp))
11004 return -1;
11005
11006 return MCOp;
11007}
11008
11009static
11011 assert(RegOpnd.isReg());
11012 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
11013 getRegSubRegPair(RegOpnd);
11014}
11015
11018 assert(MI.isRegSequence());
11019 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
11020 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
11021 auto &RegOp = MI.getOperand(1 + 2 * I);
11022 return getRegOrUndef(RegOp);
11023 }
11025}
11026
11027// Try to find the definition of reg:subreg in subreg-manipulation pseudos
11028// Following a subreg of reg:subreg isn't supported
11031 if (!RSR.SubReg)
11032 return false;
11033 switch (MI.getOpcode()) {
11034 default: break;
11035 case AMDGPU::REG_SEQUENCE:
11036 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
11037 return true;
11038 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
11039 case AMDGPU::INSERT_SUBREG:
11040 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
11041 // inserted the subreg we're looking for
11042 RSR = getRegOrUndef(MI.getOperand(2));
11043 else { // the subreg in the rest of the reg
11044 auto R1 = getRegOrUndef(MI.getOperand(1));
11045 if (R1.SubReg) // subreg of subreg isn't supported
11046 return false;
11047 RSR.Reg = R1.Reg;
11048 }
11049 return true;
11050 }
11051 return false;
11052}
11053
11055 const MachineRegisterInfo &MRI) {
11056 assert(MRI.isSSA());
11057 if (!P.Reg.isVirtual())
11058 return nullptr;
11059
11060 auto RSR = P;
11061 auto *DefInst = MRI.getVRegDef(RSR.Reg);
11062 while (auto *MI = DefInst) {
11063 DefInst = nullptr;
11064 switch (MI->getOpcode()) {
11065 case AMDGPU::COPY:
11066 case AMDGPU::V_MOV_B32_e32: {
11067 auto &Op1 = MI->getOperand(1);
11068 if (Op1.isReg() && Op1.getReg().isVirtual()) {
11069 if (Op1.isUndef())
11070 return nullptr;
11071 RSR = getRegSubRegPair(Op1);
11072 DefInst = MRI.getVRegDef(RSR.Reg);
11073 }
11074 break;
11075 }
11076 default:
11077 if (followSubRegDef(*MI, RSR)) {
11078 if (!RSR.Reg)
11079 return nullptr;
11080 DefInst = MRI.getVRegDef(RSR.Reg);
11081 }
11082 }
11083 if (!DefInst)
11084 return MI;
11085 }
11086 return nullptr;
11087}
11088
11090 Register VReg,
11091 const MachineInstr &DefMI,
11092 const MachineInstr &UseMI) {
11093 assert(MRI.isSSA() && "Must be run on SSA");
11094
11095 auto *TRI = MRI.getTargetRegisterInfo();
11096 auto *DefBB = DefMI.getParent();
11097
11098 // Don't bother searching between blocks, although it is possible this block
11099 // doesn't modify exec.
11100 if (UseMI.getParent() != DefBB)
11101 return true;
11102
11103 const int MaxInstScan = 20;
11104 int NumInst = 0;
11105
11106 // Stop scan at the use.
11107 auto E = UseMI.getIterator();
11108 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
11109 if (I->isDebugInstr())
11110 continue;
11111
11112 if (++NumInst > MaxInstScan)
11113 return true;
11114
11115 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
11116 return true;
11117 }
11118
11119 return false;
11120}
11121
11123 Register VReg,
11124 const MachineInstr &DefMI) {
11125 assert(MRI.isSSA() && "Must be run on SSA");
11126
11127 auto *TRI = MRI.getTargetRegisterInfo();
11128 auto *DefBB = DefMI.getParent();
11129
11130 const int MaxUseScan = 10;
11131 int NumUse = 0;
11132
11133 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
11134 auto &UseInst = *Use.getParent();
11135 // Don't bother searching between blocks, although it is possible this block
11136 // doesn't modify exec.
11137 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11138 return true;
11139
11140 if (++NumUse > MaxUseScan)
11141 return true;
11142 }
11143
11144 if (NumUse == 0)
11145 return false;
11146
11147 const int MaxInstScan = 20;
11148 int NumInst = 0;
11149
11150 // Stop scan when we have seen all the uses.
11151 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
11152 assert(I != DefBB->end());
11153
11154 if (I->isDebugInstr())
11155 continue;
11156
11157 if (++NumInst > MaxInstScan)
11158 return true;
11159
11160 for (const MachineOperand &Op : I->operands()) {
11161 // We don't check reg masks here as they're used only on calls:
11162 // 1. EXEC is only considered const within one BB
11163 // 2. Call should be a terminator instruction if present in a BB
11164
11165 if (!Op.isReg())
11166 continue;
11167
11168 Register Reg = Op.getReg();
11169 if (Op.isUse()) {
11170 if (Reg == VReg && --NumUse == 0)
11171 return false;
11172 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
11173 return true;
11174 }
11175 }
11176}
11177
11180 const DebugLoc &DL, Register Src, Register Dst) const {
11181 auto Cur = MBB.begin();
11182 if (Cur != MBB.end())
11183 do {
11184 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
11185 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
11186 ++Cur;
11187 } while (Cur != MBB.end() && Cur != LastPHIIt);
11188
11189 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
11190 Dst);
11191}
11192
11195 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
11196 if (InsPt != MBB.end() &&
11197 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11198 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11199 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11200 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
11201 InsPt++;
11202 return BuildMI(MBB, InsPt, DL,
11203 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
11204 .addReg(Src, {}, SrcSubReg)
11205 .addReg(AMDGPU::EXEC, RegState::Implicit);
11206 }
11207 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
11208 Dst);
11209}
11210
11211bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
11212
11214 const MachineInstr &SecondMI) const {
11215 for (const auto &Use : SecondMI.all_uses()) {
11216 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
11217 return true;
11218 }
11219 return false;
11220}
11221
11222/// If OpX is multicycle, anti-dependencies are not allowed.
11223/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
11224/// purpose.
11226 const MachineInstr &OpX) const {
11228}
11229
11232 ArrayRef<unsigned> Ops, int FrameIndex,
11233 MachineInstr *&CopyMI, LiveIntervals *LIS,
11234 VirtRegMap *VRM) const {
11235 // This is a bit of a hack (copied from AArch64). Consider this instruction:
11236 //
11237 // %0:sreg_32 = COPY $m0
11238 //
11239 // We explicitly chose SReg_32 for the virtual register so such a copy might
11240 // be eliminated by RegisterCoalescer. However, that may not be possible, and
11241 // %0 may even spill. We can't spill $m0 normally (it would require copying to
11242 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
11243 // TargetInstrInfo::foldMemoryOperand() is going to try.
11244 // A similar issue also exists with spilling and reloading $exec registers.
11245 //
11246 // To prevent that, constrain the %0 register class here.
11247 if (isFullCopyInstr(MI)) {
11248 Register DstReg = MI.getOperand(0).getReg();
11249 Register SrcReg = MI.getOperand(1).getReg();
11250 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
11251 (DstReg.isVirtual() != SrcReg.isVirtual())) {
11253 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
11254 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
11255 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
11256 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11257 return nullptr;
11258 }
11259 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
11260 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11261 return nullptr;
11262 }
11263 }
11264 }
11265
11266 return nullptr;
11267}
11268
11270 const MachineInstr &MI,
11271 unsigned *PredCost) const {
11272 if (MI.isBundle()) {
11274 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
11275 unsigned Lat = 0, Count = 0;
11276 for (++I; I != E && I->isBundledWithPred(); ++I) {
11277 ++Count;
11278 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
11279 }
11280 return Lat + Count - 1;
11281 }
11282
11283 return SchedModel.computeInstrLatency(&MI);
11284}
11285
11287 if (!ST.hasGFX1250VALUBlockingCycles())
11288 return 0;
11290}
11291
11292unsigned
11294 if (const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(MI.getOpcode()))
11295 return Entry->GFX1250BlockingCycles;
11296 return 0;
11297}
11298
11299const MachineOperand &
11301 if (const MachineOperand *CallAddrOp =
11302 getNamedOperand(MI, AMDGPU::OpName::src0))
11303 return *CallAddrOp;
11305}
11306
11309 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11310 unsigned Opcode = MI.getOpcode();
11311
11312 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
11313 Register Dst = MI.getOperand(0).getReg();
11314 Register Src = MI.getOperand(1).getReg();
11315 LLT DstTy = MRI.getType(Dst);
11316 LLT SrcTy = MRI.getType(Src);
11317 unsigned DstAS = DstTy.getAddressSpace();
11318 unsigned SrcAS = SrcTy.getAddressSpace();
11319 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
11320 DstAS == AMDGPUAS::FLAT_ADDRESS &&
11321 ST.hasGloballyAddressableScratch()
11324 };
11325
11326 // If the target supports globally addressable scratch, the mapping from
11327 // scratch memory to the flat aperture changes therefore an address space cast
11328 // is no longer uniform.
11329 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11330 return HandleAddrSpaceCast(MI);
11331
11332 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
11333 auto IID = GI->getIntrinsicID();
11338
11339 switch (IID) {
11340 case Intrinsic::amdgcn_if:
11341 case Intrinsic::amdgcn_else:
11342 // FIXME: Uniform if second result
11343 break;
11344 }
11345
11347 }
11348
11349 // Loads from the private and flat address spaces are divergent, because
11350 // threads can execute the load instruction with the same inputs and get
11351 // different results.
11352 //
11353 // All other loads are not divergent, because if threads issue loads with the
11354 // same arguments, they will always get the same result.
11355 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11356 Opcode == AMDGPU::G_SEXTLOAD) {
11357 if (MI.memoperands_empty())
11358 return ValueUniformity::NeverUniform; // conservative assumption
11359
11360 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11361 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11362 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11363 })) {
11364 // At least one MMO in a non-global address space.
11366 }
11368 }
11369
11370 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11371 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11372 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11373 AMDGPU::isGenericAtomic(Opcode)) {
11375 }
11376
11377 // Result is computed from uniform SP and uniform wave-wide max size.
11378 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11380
11381 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11383
11385}
11386
11388 if (!Formatter)
11389 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11390 return Formatter.get();
11391}
11392
11394
11395 if (isNeverUniform(MI))
11397
11398 unsigned opcode = MI.getOpcode();
11399 if (opcode == AMDGPU::V_READLANE_B32 ||
11400 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11401 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11403
11404 // If any of defs is divergent, report as NeverUniform. isUniformReg will
11405 // calculate in more detail for each def from its reg class, if available.
11406 if (MI.isInlineAsm()) {
11407 for (const MachineOperand &MO : MI.operands()) {
11408 if (!MO.isReg() || !MO.isDef())
11409 continue;
11410 const TargetRegisterClass *RC =
11411 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
11412 if (!RC || !RI.isSGPRClass(RC))
11414 }
11415 }
11416
11417 if (isCopyInstr(MI)) {
11418 const MachineOperand &srcOp = MI.getOperand(1);
11419 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
11420 const TargetRegisterClass *regClass =
11421 RI.getPhysRegBaseClass(srcOp.getReg());
11422 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
11424 }
11426 }
11427
11428 // GMIR handling
11429 if (MI.isPreISelOpcode())
11431
11432 // Atomics are divergent because they are executed sequentially: when an
11433 // atomic operation refers to the same address in each thread, then each
11434 // thread after the first sees the value written by the previous thread as
11435 // original value.
11436
11437 if (isAtomic(MI))
11439
11440 // Loads from the private and flat address spaces are divergent, because
11441 // threads can execute the load instruction with the same inputs and get
11442 // different results.
11443 if (isFLAT(MI) && MI.mayLoad()) {
11444 if (MI.memoperands_empty())
11445 return ValueUniformity::NeverUniform; // conservative assumption
11446
11447 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11448 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11449 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11450 })) {
11451 // At least one MMO in a non-global address space.
11453 }
11454
11456 }
11457
11458 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11459 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11460
11461 // FIXME: It's conceptually broken to report this for an instruction, and not
11462 // a specific def operand. For inline asm in particular, there could be mixed
11463 // uniform and divergent results.
11464 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11465 const MachineOperand &SrcOp = MI.getOperand(I);
11466 if (!SrcOp.isReg())
11467 continue;
11468
11469 Register Reg = SrcOp.getReg();
11470 if (!Reg || !SrcOp.readsReg())
11471 continue;
11472
11473 // If RegBank is null, this is unassigned or an unallocatable special
11474 // register, which are all scalars.
11475 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11476 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11478 }
11479
11480 // TODO: Uniformity check condtions above can be rearranged for more
11481 // redability
11482
11483 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11484 // currently turned into no-op COPYs by SelectionDAG ISel and are
11485 // therefore no longer recognizable.
11486
11488}
11489
11491 switch (MF.getFunction().getCallingConv()) {
11493 return 1;
11495 return 2;
11497 return 3;
11501 const Function &F = MF.getFunction();
11502 F.getContext().diagnose(DiagnosticInfoUnsupported(
11503 F, "ds_ordered_count unsupported for this calling conv"));
11504 [[fallthrough]];
11505 }
11508 case CallingConv::C:
11509 case CallingConv::Fast:
11510 default:
11511 // Assume other calling conventions are various compute callable functions
11512 return 0;
11513 }
11514}
11515
11517 Register &SrcReg2, int64_t &CmpMask,
11518 int64_t &CmpValue) const {
11519 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11520 return false;
11521
11522 switch (MI.getOpcode()) {
11523 default:
11524 break;
11525 case AMDGPU::S_CMP_EQ_U32:
11526 case AMDGPU::S_CMP_EQ_I32:
11527 case AMDGPU::S_CMP_LG_U32:
11528 case AMDGPU::S_CMP_LG_I32:
11529 case AMDGPU::S_CMP_LT_U32:
11530 case AMDGPU::S_CMP_LT_I32:
11531 case AMDGPU::S_CMP_GT_U32:
11532 case AMDGPU::S_CMP_GT_I32:
11533 case AMDGPU::S_CMP_LE_U32:
11534 case AMDGPU::S_CMP_LE_I32:
11535 case AMDGPU::S_CMP_GE_U32:
11536 case AMDGPU::S_CMP_GE_I32:
11537 case AMDGPU::S_CMP_EQ_U64:
11538 case AMDGPU::S_CMP_LG_U64:
11539 SrcReg = MI.getOperand(0).getReg();
11540 if (MI.getOperand(1).isReg()) {
11541 if (MI.getOperand(1).getSubReg())
11542 return false;
11543 SrcReg2 = MI.getOperand(1).getReg();
11544 CmpValue = 0;
11545 } else if (MI.getOperand(1).isImm()) {
11546 SrcReg2 = Register();
11547 CmpValue = MI.getOperand(1).getImm();
11548 } else {
11549 return false;
11550 }
11551 CmpMask = ~0;
11552 return true;
11553 case AMDGPU::S_CMPK_EQ_U32:
11554 case AMDGPU::S_CMPK_EQ_I32:
11555 case AMDGPU::S_CMPK_LG_U32:
11556 case AMDGPU::S_CMPK_LG_I32:
11557 case AMDGPU::S_CMPK_LT_U32:
11558 case AMDGPU::S_CMPK_LT_I32:
11559 case AMDGPU::S_CMPK_GT_U32:
11560 case AMDGPU::S_CMPK_GT_I32:
11561 case AMDGPU::S_CMPK_LE_U32:
11562 case AMDGPU::S_CMPK_LE_I32:
11563 case AMDGPU::S_CMPK_GE_U32:
11564 case AMDGPU::S_CMPK_GE_I32:
11565 SrcReg = MI.getOperand(0).getReg();
11566 SrcReg2 = Register();
11567 CmpValue = MI.getOperand(1).getImm();
11568 CmpMask = ~0;
11569 return true;
11570 }
11571
11572 return false;
11573}
11574
11576 for (MachineBasicBlock *S : MBB->successors()) {
11577 if (S->isLiveIn(AMDGPU::SCC))
11578 return false;
11579 }
11580 return true;
11581}
11582
11583// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11584// (incoming SCC) = !(SCC defined by SCCDef).
11585// Return true if all uses can be re-written, false otherwise.
11586bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11587 MachineBasicBlock *MBB = SCCDef->getParent();
11588 SmallVector<MachineInstr *> InvertInstr;
11589 bool SCCIsDead = false;
11590
11591 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11592 constexpr unsigned ScanLimit = 12;
11593 unsigned Count = 0;
11594 for (MachineInstr &MI : instructionsWithoutDebug(
11595 std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11596 if (++Count > ScanLimit)
11597 return false;
11598 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11599 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11600 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11601 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11602 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11603 InvertInstr.push_back(&MI);
11604 else
11605 return false;
11606 }
11607 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11608 SCCIsDead = true;
11609 break;
11610 }
11611 }
11612 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11613 SCCIsDead = true;
11614
11615 // SCC may have more uses. Can't invert all of them.
11616 if (!SCCIsDead)
11617 return false;
11618
11619 // Invert uses
11620 for (MachineInstr *MI : InvertInstr) {
11621 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11622 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11623 swapOperands(*MI);
11624 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11625 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11626 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11627 ? AMDGPU::S_CBRANCH_SCC1
11628 : AMDGPU::S_CBRANCH_SCC0));
11629 } else {
11630 llvm_unreachable("SCC used but no inversion handling");
11631 }
11632 }
11633 return true;
11634}
11635
11636// SCC is already valid after SCCValid.
11637// SCCRedefine will redefine SCC to the same value already available after
11638// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11639// update kill/dead flags if necessary.
11640bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11641 bool NeedInversion) const {
11642 MachineInstr *KillsSCC = nullptr;
11643 if (SCCValid->getParent() != SCCRedefine->getParent())
11644 return false;
11645 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11646 SCCRedefine->getIterator())) {
11647 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11648 return false;
11649 if (MI.killsRegister(AMDGPU::SCC, &RI))
11650 KillsSCC = &MI;
11651 }
11652 if (NeedInversion && !invertSCCUse(SCCRedefine))
11653 return false;
11654 if (MachineOperand *SccDef =
11655 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11656 SccDef->setIsDead(false);
11657 if (KillsSCC)
11658 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11659 SCCRedefine->eraseFromParent();
11660 return true;
11661}
11662
11663/// If \p Sel is an S_CSELECT* of two different constants A and B, return them,
11664/// truncated to the width of the select.
11665static std::optional<std::pair<int64_t, int64_t>>
11667 const MachineInstr &Sel) {
11668 unsigned Opc = Sel.getOpcode();
11669 if (Opc != AMDGPU::S_CSELECT_B32 && Opc != AMDGPU::S_CSELECT_B64)
11670 return {};
11671 std::optional<int64_t> A =
11672 TII.getImmOrMaterializedImm(MRI, Sel.getOperand(1));
11673 if (!A)
11674 return {};
11675 std::optional<int64_t> B =
11676 TII.getImmOrMaterializedImm(MRI, Sel.getOperand(2));
11677 if (!B)
11678 return {};
11679 if (Opc == AMDGPU::S_CSELECT_B32) {
11680 A = Lo_32(*A);
11681 B = Lo_32(*B);
11682 }
11683 if (*A == *B)
11684 return {};
11685 return std::pair(*A, *B);
11686}
11687
11688static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11689 unsigned &NewDefOpc) {
11690 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11691 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11692 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11693 Def.getOpcode() != AMDGPU::S_ADD_U32)
11694 return false;
11695 const MachineOperand &AddSrc1 = Def.getOperand(1);
11696 const MachineOperand &AddSrc2 = Def.getOperand(2);
11697 const MachineRegisterInfo &MRI = Def.getMF()->getRegInfo();
11698 const SIInstrInfo *TII = static_cast<const SIInstrInfo *>(
11699 Def.getMF()->getSubtarget().getInstrInfo());
11700
11701 auto Imm1 = TII->getImmOrMaterializedImm(MRI, AddSrc1);
11702 auto Imm2 = TII->getImmOrMaterializedImm(MRI, AddSrc2);
11703 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11704 return false;
11705
11706 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11707 const MachineOperand *SccDef =
11708 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11709 if (!SccDef->isDead())
11710 return false;
11711 NewDefOpc = AMDGPU::S_ADD_U32;
11712 }
11713 NeedInversion = !NeedInversion;
11714 return true;
11715}
11716
11718 Register SrcReg2, int64_t CmpMask,
11719 int64_t CmpValue,
11720 const MachineRegisterInfo *MRI) const {
11721 if (!SrcReg || SrcReg.isPhysical())
11722 return false;
11723
11724 if (SrcReg2) {
11725 auto ImmOpt = getImmOrMaterializedImm(*MRI, SrcReg2);
11726 if (!ImmOpt)
11727 return false;
11728 CmpValue = *ImmOpt;
11729 }
11730
11731 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11732 this](bool NeedInversion) -> bool {
11733 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11734 if (!Def)
11735 return false;
11736
11737 unsigned NewDefOpc = Def->getOpcode();
11738 if (auto Consts = getSelectConstants(*this, *MRI, *Def)) {
11739 // sX = S_CSELECT* A, B with A != B, so sX == A exactly when SCC was set.
11740 // Comparing sX with A or B recomputes SCC or its inverse:
11741 //
11742 // s_cmp_eq_* sX, A => SCC s_cmp_lg_* sX, A => !SCC
11743 // s_cmp_eq_* sX, B => !SCC s_cmp_lg_* sX, B => SCC
11744 auto [A, B] = *Consts;
11745 int64_t C = Def->getOpcode() == AMDGPU::S_CSELECT_B32 ? Lo_32(CmpValue)
11746 : CmpValue;
11747 if (C == A)
11748 NeedInversion = !NeedInversion;
11749 else if (C != B)
11750 return false;
11751 } else {
11752 // For S_OP that set SCC = DST!=0, do the transformation
11753 //
11754 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11755 //
11756 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11757 // do the transformation:
11758 //
11759 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11760 if (CmpValue != 0 ||
11761 (!setsSCCIfResultIsNonZero(*Def) &&
11762 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc)))
11763 return false;
11764 }
11765
11766 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11767 return false;
11768
11769 if (NewDefOpc != Def->getOpcode())
11770 Def->setDesc(get(NewDefOpc));
11771
11772 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11773 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11774 // 64-bit select then delete s_or_b32 in the sequence:
11775 // sX = s_cselect_b64 A, B (A != B, one of them 0)
11776 // sLo = copy sX.sub0
11777 // sHi = copy sX.sub1
11778 // sY = s_or_b32 sLo, sHi
11779 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11780 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11781 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11782 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11783 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11784 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11785 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11786 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11787 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11788 Def2->getOperand(1).isReg() &&
11789 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11790 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11791 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11792 if (MachineInstr *Select =
11793 MRI->getVRegDef(Def1->getOperand(1).getReg())) {
11794 if (auto Consts = getSelectConstants(*this, *MRI, *Select)) {
11795 auto [A, B] = *Consts;
11796 if (A == 0 || B == 0)
11797 optimizeSCC(Select, Def, /*NeedInversion=*/A == 0);
11798 }
11799 }
11800 }
11801 }
11802 }
11803 return true;
11804 };
11805
11806 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11807 this](int64_t ExpectedValue, unsigned SrcSize,
11808 bool IsReversible, bool IsSigned) -> bool {
11809 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11810 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11811 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11812 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11813 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11814 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11815 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11816 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11817 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11818 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11819 //
11820 // Signed ge/gt are not used for the sign bit.
11821 //
11822 // If result of the AND is unused except in the compare:
11823 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11824 //
11825 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11826 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11827 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11828 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11829 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11830 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11831
11832 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11833 if (!Def)
11834 return false;
11835
11836 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11837 Def->getOpcode() != AMDGPU::S_AND_B64)
11838 return false;
11839
11840 int64_t Mask;
11841 const auto isMask = [&Mask, SrcSize, MRI,
11842 this](const MachineOperand *MO) -> bool {
11843 auto ImmOpt = this->getImmOrMaterializedImm(*MRI, *MO);
11844 if (!ImmOpt)
11845 return false;
11846 Mask = *ImmOpt;
11847 Mask &= maxUIntN(SrcSize);
11848 return isPowerOf2_64(Mask);
11849 };
11850
11851 MachineOperand *SrcOp = &Def->getOperand(1);
11852 if (isMask(SrcOp))
11853 SrcOp = &Def->getOperand(2);
11854 else if (isMask(&Def->getOperand(2)))
11855 SrcOp = &Def->getOperand(1);
11856 else
11857 return false;
11858
11859 // A valid Mask is required to have a single bit set, hence a non-zero and
11860 // power-of-two value. This verifies that we will not do 64-bit shift below.
11861 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11862 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11863 if (IsSigned && BitNo == SrcSize - 1)
11864 return false;
11865
11866 ExpectedValue <<= BitNo;
11867
11868 bool IsReversedCC = false;
11869 if (CmpValue != ExpectedValue) {
11870 if (!IsReversible)
11871 return false;
11872 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11873 if (!IsReversedCC)
11874 return false;
11875 }
11876
11877 Register DefReg = Def->getOperand(0).getReg();
11878 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11879 return false;
11880
11881 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11882 return false;
11883
11884 if (!MRI->use_nodbg_empty(DefReg)) {
11885 assert(!IsReversedCC);
11886 return true;
11887 }
11888
11889 // Replace AND with unused result with a S_BITCMP.
11890 MachineBasicBlock *MBB = Def->getParent();
11891
11892 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11893 : AMDGPU::S_BITCMP1_B32
11894 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11895 : AMDGPU::S_BITCMP1_B64;
11896
11897 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11898 .add(*SrcOp)
11899 .addImm(BitNo);
11900 Def->eraseFromParent();
11901
11902 return true;
11903 };
11904
11905 switch (CmpInstr.getOpcode()) {
11906 default:
11907 break;
11908 case AMDGPU::S_CMP_EQ_U32:
11909 case AMDGPU::S_CMP_EQ_I32:
11910 case AMDGPU::S_CMPK_EQ_U32:
11911 case AMDGPU::S_CMPK_EQ_I32:
11912 return optimizeCmpAnd(1, 32, true, false) ||
11913 optimizeCmpSelect(/*NeedInversion=*/true);
11914 case AMDGPU::S_CMP_GE_U32:
11915 case AMDGPU::S_CMPK_GE_U32:
11916 return optimizeCmpAnd(1, 32, false, false);
11917 case AMDGPU::S_CMP_GE_I32:
11918 case AMDGPU::S_CMPK_GE_I32:
11919 return optimizeCmpAnd(1, 32, false, true);
11920 case AMDGPU::S_CMP_EQ_U64:
11921 return optimizeCmpAnd(1, 64, true, false) ||
11922 optimizeCmpSelect(/*NeedInversion=*/true);
11923 case AMDGPU::S_CMP_LG_U32:
11924 case AMDGPU::S_CMP_LG_I32:
11925 case AMDGPU::S_CMPK_LG_U32:
11926 case AMDGPU::S_CMPK_LG_I32:
11927 return optimizeCmpAnd(0, 32, true, false) ||
11928 optimizeCmpSelect(/*NeedInversion=*/false);
11929 case AMDGPU::S_CMP_GT_U32:
11930 case AMDGPU::S_CMPK_GT_U32:
11931 return optimizeCmpAnd(0, 32, false, false);
11932 case AMDGPU::S_CMP_GT_I32:
11933 case AMDGPU::S_CMPK_GT_I32:
11934 return optimizeCmpAnd(0, 32, false, true);
11935 case AMDGPU::S_CMP_LG_U64:
11936 return optimizeCmpAnd(0, 64, true, false) ||
11937 optimizeCmpSelect(/*NeedInversion=*/false);
11938 }
11939
11940 return false;
11941}
11942
11944 AMDGPU::OpName OpName) const {
11945 if (!ST.needsAlignedVGPRs())
11946 return;
11947
11948 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
11949 if (OpNo < 0)
11950 return;
11951 MachineOperand &Op = MI.getOperand(OpNo);
11952 if (getOpSize(MI, OpNo) > 4)
11953 return;
11954
11955 // Add implicit aligned super-reg to force alignment on the data operand.
11956 const DebugLoc &DL = MI.getDebugLoc();
11957 MachineBasicBlock *BB = MI.getParent();
11959 Register DataReg = Op.getReg();
11960 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11961 Register Undef = MRI.createVirtualRegister(
11962 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11963 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
11964 Register NewVR =
11965 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
11966 : &AMDGPU::VReg_64_Align2RegClass);
11967 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
11968 .addReg(DataReg, {}, Op.getSubReg())
11969 .addImm(AMDGPU::sub0)
11970 .addReg(Undef)
11971 .addImm(AMDGPU::sub1);
11972 Op.setReg(NewVR);
11973 Op.setSubReg(AMDGPU::sub0);
11974 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
11975}
11976
11978 if (!SchedModel.hasInstrSchedModel())
11979 return 0;
11980
11981 // The repeat rate is the throughput-limiting resource occupancy: the largest
11982 // number of cycles any written processor resource is held.
11983 const MCSchedClassDesc *SCDesc = SchedModel.resolveSchedClass(&MI);
11984 unsigned RepeatRate = 0;
11986 PI = SchedModel.getWriteProcResBegin(SCDesc),
11987 PE = SchedModel.getWriteProcResEnd(SCDesc);
11988 PI != PE; ++PI) {
11989 RepeatRate = std::max(RepeatRate, (unsigned)PI->ReleaseAtCycle);
11990 }
11991
11992 return RepeatRate;
11993}
11994
11996 if (isIGLP(*MI))
11997 return false;
11998
12000}
12001
12003 if (!isWMMA(MI) && !isSWMMAC(MI))
12004 return false;
12005
12006 if (ST.hasGFX1250Insts())
12007 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
12008
12009 return true;
12010}
12011
12013 unsigned Opcode = MI.getOpcode();
12014
12015 if (AMDGPU::isGFX12Plus(ST))
12016 return isDOT(MI) || isXDLWMMA(MI);
12017
12018 if (!isMAI(MI) || isDGEMM(Opcode) ||
12019 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
12020 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
12021 return false;
12022
12023 if (!ST.hasGFX940Insts())
12024 return true;
12025
12026 return AMDGPU::getMAIIsGFX940XDL(Opcode);
12027}
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)
uint64_t High
uint64_t IntrinsicInst * II
#define P(N)
R600 Clause Merge
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
This file declares the machine register scavenger class.
static cl::opt< bool > Fix16BitCopies("amdgpu-fix-16-bit-physreg-copies", cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"), cl::init(true), cl::ReallyHidden)
static void expandSGPRCopy(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RC, bool Forward)
static std::optional< std::pair< int64_t, int64_t > > getSelectConstants(const SIInstrInfo &TII, const MachineRegisterInfo &MRI, const MachineInstr &Sel)
If Sel is an S_CSELECT* of two different constants A and B, return them, truncated to the width of th...
static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc)
static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize)
static bool compareMachineOp(const MachineOperand &Op0, const MachineOperand &Op1)
static bool isStride64(unsigned Opc)
static MachineBasicBlock * generateWaterFallLoop(const SIInstrInfo &TII, MachineInstr &MI, ArrayRef< MachineOperand * > ScalarOps, MachineDominatorTree *MDT, MachineBasicBlock::iterator Begin=nullptr, MachineBasicBlock::iterator End=nullptr, ArrayRef< Register > PhySGPRs={})
#define GENERATE_RENAMED_GFX9_CASES(OPCODE)
static std::tuple< unsigned, unsigned > extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc)
static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx)
static bool followSubRegDef(MachineInstr &MI, TargetInstrInfo::RegSubRegPair &RSR)
static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize)
static MachineInstr * swapImmOperands(MachineInstr &MI, MachineOperand &NonRegOp1, MachineOperand &NonRegOp2)
static void copyFlagsToImplicitVCC(MachineInstr &MI, const MachineOperand &Orig)
static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, LocationSize WidthB, int OffsetB)
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, RegScavenger &RS, bool RegsOverlap, Register ImpUseSuperReg=Register())
Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908.
static unsigned getWWMRegSpillSaveOpcode(unsigned Size, bool IsVectorSuperClass)
static bool memOpsHaveSameBaseOperands(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getWWMRegSpillRestoreOpcode(unsigned Size, bool IsVectorSuperClass)
static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion, unsigned &NewDefOpc)
static bool isSCCDeadOnExit(MachineBasicBlock *MBB)
static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize)
static unsigned subtargetEncodingFamily(const GCNSubtarget &ST)
static void preserveCondRegFlags(MachineOperand &CondReg, const MachineOperand &OrigCond)
static Register findImplicitSGPRRead(const MachineInstr &MI)
static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc)
static cl::opt< unsigned > BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16), cl::desc("Restrict range of branch instructions (DEBUG)"))
static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getSGPRSpillRestoreOpcode(unsigned Size)
static bool isRegOrFI(const MachineOperand &MO)
static bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI)
Return true if MI is a VALU comparison, i.e.
static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static constexpr AMDGPU::OpName ModifierOpNames[]
static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const char *Msg="illegal VGPR to SGPR copy")
static MachineInstr * swapRegAndNonRegOperand(MachineInstr &MI, MachineOperand &RegOp, MachineOperand &NonRegOp)
static bool isLegalPkF32OpSel(const SIInstrInfo &TII, const MachineInstr &MI, bool CheckSwappedSrc=false)
static bool shouldReadExec(const MachineInstr &MI)
static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc)
static bool isRenamedInGFX9(int Opcode)
static TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd)
static std::tuple< unsigned, unsigned, unsigned > splitGlobalAddressRelocFlags(const GCNSubtarget &ST, const MachineOperand &SrcOp)
static bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
static bool nodesHaveSameOperandValue(SDNode *N0, SDNode *N1, AMDGPU::OpName OpName)
Returns true if both nodes have the same value for the given operand Op, or if both nodes do not have...
static unsigned getNumOperandsNoGlue(SDNode *Node)
static bool canRemat(const MachineInstr &MI)
static unsigned getAVSpillRestoreOpcode(unsigned Size)
static void emitLoadScalarOpsFromVGPRLoop(const SIInstrInfo &TII, MachineRegisterInfo &MRI, MachineBasicBlock &PredBB, MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={})
static unsigned getVGPRSpillRestoreOpcode(unsigned Size)
Interface definition for SIInstrInfo.
bool IsDead
const char * Msg
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
#define LLVM_DEBUG(...)
Definition Debug.h:119
static const LaneMaskConstants & get(const GCNSubtarget &ST)
static LLVM_ABI Semantics SemanticsToEnum(const llvm::fltSemantics &Sem)
Definition APFloat.cpp:184
Class for arbitrary precision integers.
Definition APInt.h:78
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
This class is the base class for the comparison instructions.
Definition InstrTypes.h:728
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A debug info location.
Definition DebugLoc.h:126
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:856
Diagnostic information for unsupported feature in backend.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:273
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:352
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
CycleRef getParentCycle(CycleRef C) const
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
Itinerary data supplied by a subtarget to be used by a target.
constexpr unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
LiveInterval - This class represents the liveness of a register, or stack slot.
bool hasInterval(Register Reg) const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
LLVM_ABI bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
This class represents the liveness of a register, stack slot, etc.
bool hasValue() const
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:347
static const MCBinaryExpr * createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:417
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
unsigned getOpcode() const
Return the opcode number for this descriptor.
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition MCInstrDesc.h:88
uint8_t OperandType
Information about the type of the operand.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition MCInstrDesc.h:94
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void setVariableValue(const MCExpr *Value)
Definition MCSymbol.cpp:50
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
MIRFormater - Interface to format MIR operand based on target.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
void push_back(MachineInstr *MI)
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isImmutableObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an immutable object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
bool isCopy() const
const MachineBasicBlock * getParent() const
LLVM_ABI void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
bool isBundle() const
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromBundle()
Unlink 'this' from its basic block and delete it.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mop_range explicit_operands()
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just after the instruction itself.
LLVM_ABI void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo)
Clear all kill flags affecting Reg.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
const GlobalValue * getGlobal() const
LLVM_ABI void ChangeToFrameIndex(int Idx, unsigned TargetFlags=0)
Replace this operand with a frame index.
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
LLVM_ABI void ChangeToGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
ChangeToGA - Replace this operand with a new global address operand.
void setIsKill(bool Val=true)
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
void setOffset(int64_t Offset)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isTargetIndex() const
isTargetIndex - Tests if this is a MO_TargetIndex operand.
void setTargetFlags(unsigned F)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
const MachineFunction & getMF() const
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
bool isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
unsigned getGFX1250BlockingCyclesTable(const MachineInstr &MI) const
GFX1250 blocking-cycles table lookup with no occupancy subtarget gate.
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const final
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
static bool isDOT(const MachineInstr &MI)
std::unique_ptr< PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
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
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
static unsigned getSubRegFromChannel(uint64_t Channel, uint64_t NumRegs=1)
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:70
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndexes pass.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:293
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
int64_t getImm() const
Register getReg() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Object returned by analyzeLoopForPipelining.
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:352
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:187
self_iterator getIterator()
Definition ilist_node.h:123
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi, bool *IsBF16)
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
@ OPERAND_REG_IMM_V2FP64
Definition SIDefines.h:441
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:459
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:426
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:434
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:450
@ OPERAND_REG_IMM_NOINLINE_FP16
Definition SIDefines.h:432
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:447
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:452
@ OPERAND_REG_IMM_V2INT64
Definition SIDefines.h:437
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:436
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:430
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:425
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:433
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:431
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:435
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:446
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:444
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:438
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:429
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:453
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:464
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:465
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:439
@ OPERAND_SDWA_VOPC_DST
Definition SIDefines.h:476
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:428
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:449
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:445
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:451
@ OPERAND_INLINE_C_AV64_PSEUDO
Definition SIDefines.h:470
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:440
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:466
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:448
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:427
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:456
LLVM_READONLY int32_t getBasicFromSDWAOp(uint32_t Opcode)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
@ TI_SCRATCH_RSRC_DWORD1
Definition AMDGPU.h:667
@ TI_SCRATCH_RSRC_DWORD3
Definition AMDGPU.h:669
@ TI_SCRATCH_RSRC_DWORD0
Definition AMDGPU.h:666
@ TI_SCRATCH_RSRC_DWORD2
Definition AMDGPU.h:668
@ TI_CONSTDATA_START
Definition AMDGPU.h:665
bool isSingleSGPRReadInst(unsigned Opc)
Packed instructions that read a single SGPR for SGPR operands, except for 64-bit elements which read ...
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
const uint64_t RSRC_INDEX_STRIDE_SHIFT
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition CallingConv.h:41
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ OPERAND_GENERIC_4
Definition MCInstrDesc.h:71
@ OPERAND_GENERIC_2
Definition MCInstrDesc.h:69
@ OPERAND_GENERIC_1
Definition MCInstrDesc.h:68
@ OPERAND_GENERIC_3
Definition MCInstrDesc.h:70
@ OPERAND_IMMEDIATE
Definition MCInstrDesc.h:61
@ OPERAND_GENERIC_0
Definition MCInstrDesc.h:67
@ OPERAND_GENERIC_5
Definition MCInstrDesc.h:72
Not(const Pred &P) -> Not< Pred >
constexpr bool isSDWA(const T &...O)
Definition SIDefines.h:249
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
Definition Threading.h:280
@ Offset
Definition DWP.cpp:577
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
constexpr uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
Definition MathExtras.h:208
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
static const MachineMemOperand::Flags MOCFSB1
Definition SIInstrInfo.h:71
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:546
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
Op::Description Desc
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg)
Return the SubReg component from REG_SEQUENCE.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
Definition SIInstrInfo.h:45
constexpr bool has_single_bit(T Value) noexcept
Definition bit.h:149
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
MachineInstr * getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, const MachineRegisterInfo &MRI)
Return the defining instruction for a given reg:subreg pair skipping copy like instructions and subre...
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI VirtRegInfo AnalyzeVirtRegInBundle(MachineInstr &MI, Register Reg, SmallVectorImpl< std::pair< MachineInstr *, unsigned > > *Ops=nullptr)
AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses a virtual register.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
Definition SIInstrInfo.h:53
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
Definition SIInstrInfo.h:41
constexpr unsigned BitWidth
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition SIInstrInfo.h:49
constexpr T reverseBits(T Val)
Reverse the bits in Val.
Definition MathExtras.h:119
static const MachineMemOperand::Flags MOCFSB0
Use two MMO flags to encode the 2-bit cache fill size field for GFX13+.
Definition SIInstrInfo.h:68
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:572
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320
constexpr RegState getUndefRegState(bool B)
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
Definition Uniformity.h:18
@ AlwaysUniform
The result value is always uniform.
Definition Uniformity.h:23
@ NeverUniform
The result value can never be assumed to be uniform.
Definition Uniformity.h:26
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
Definition SIInstrInfo.h:64
bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI)
Return false if EXEC is not changed between the def of VReg at DefMI and all its uses.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr bool all() const
Definition LaneBitmask.h:54
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:130
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Utility to store machine instructions worklist.
Definition SIInstrInfo.h:75
MachineInstr * top() const
Definition SIInstrInfo.h:80
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
Definition SIInstrInfo.h:98
void insert(MachineInstr *MI)
A pair composed of a register and a sub-register index.
VirtRegInfo - Information about a virtual register used by a set of operands.
bool Reads
Reads - One of the operands read the virtual register.
bool Writes
Writes - One of the operands writes the virtual register.