LLVM 24.0.0git
SIInstrInfo.cpp
Go to the documentation of this file.
1//===- SIInstrInfo.cpp - SI Instruction Information ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// SI Implementation of TargetInstrInfo.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SIInstrInfo.h"
15#include "AMDGPU.h"
16#include "AMDGPUInstrInfo.h"
17#include "AMDGPULaneMaskUtils.h"
18#include "GCNHazardRecognizer.h"
19#include "GCNSubtarget.h"
22#include "llvm/ADT/STLExtras.h"
33#include "llvm/IR/IntrinsicsAMDGPU.h"
34#include "llvm/MC/MCContext.h"
37#include <tuple>
38
39using namespace llvm;
40
41#define DEBUG_TYPE "si-instr-info"
42
43#define GET_INSTRINFO_CTOR_DTOR
44#include "AMDGPUGenInstrInfo.inc"
45
46namespace llvm::AMDGPU {
47#define GET_ImageDimIntrinsicTable_IMPL
48#define GET_RsrcIntrinsics_IMPL
49#define GET_GFX1250BlockingCyclesTable_DECL
50#define GET_GFX1250BlockingCyclesTable_IMPL
51
56
57#include "AMDGPUGenSearchableTables.inc"
58} // namespace llvm::AMDGPU
59
60// Must be at least 4 to be able to branch over minimum unconditional branch
61// code. This is only for making it possible to write reasonably small tests for
62// long branches.
64BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16),
65 cl::desc("Restrict range of branch instructions (DEBUG)"));
66
68 "amdgpu-fix-16-bit-physreg-copies",
69 cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"),
70 cl::init(true),
72
74 : AMDGPUGenInstrInfo(ST, RI, AMDGPU::ADJCALLSTACKUP,
75 AMDGPU::ADJCALLSTACKDOWN),
76 RI(ST), ST(ST) {
77 SchedModel.init(&ST);
78}
79
80//===----------------------------------------------------------------------===//
81// TargetInstrInfo callbacks
82//===----------------------------------------------------------------------===//
83
84static unsigned getNumOperandsNoGlue(SDNode *Node) {
85 unsigned N = Node->getNumOperands();
86 while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
87 --N;
88 return N;
89}
90
91/// Returns true if both nodes have the same value for the given
92/// operand \p Op, or if both nodes do not have this operand.
94 AMDGPU::OpName OpName) {
95 unsigned Opc0 = N0->getMachineOpcode();
96 unsigned Opc1 = N1->getMachineOpcode();
97
98 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName);
99 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName);
100
101 if (Op0Idx == -1 && Op1Idx == -1)
102 return true;
103
104
105 if ((Op0Idx == -1 && Op1Idx != -1) ||
106 (Op1Idx == -1 && Op0Idx != -1))
107 return false;
108
109 // getNamedOperandIdx returns the index for the MachineInstr's operands,
110 // which includes the result as the first operand. We are indexing into the
111 // MachineSDNode's operands, so we need to skip the result operand to get
112 // the real index.
113 --Op0Idx;
114 --Op1Idx;
115
116 return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx);
117}
118
119static bool canRemat(const MachineInstr &MI) {
120
124 return true;
125
126 if (SIInstrInfo::isSMRD(MI)) {
127 return !MI.memoperands_empty() &&
128 llvm::all_of(MI.memoperands(), [](const MachineMemOperand *MMO) {
129 return MMO->isLoad() && MMO->isInvariant();
130 });
131 }
132
133 return false;
134}
135
136// Split relocation flags for 64-bit global-address materialization into a
137// common base and the hi/lo relocation variants.
138static std::tuple<unsigned, unsigned, unsigned>
140 const MachineOperand &SrcOp) {
141 const unsigned BaseFlags = SrcOp.getTargetFlags() & ~SIInstrInfo::MO_MASK;
142 const unsigned Reloc = SrcOp.getTargetFlags() & SIInstrInfo::MO_MASK;
143
144 // Infer the relocation type from the existing flags on the global operand.
145 // The relocation type should have been determined earlier in the pipeline.
146 unsigned LoReloc, HiReloc;
147 switch (Reloc) {
151 LoReloc = SIInstrInfo::MO_REL32_LO;
152 HiReloc = SIInstrInfo::MO_REL32_HI;
153 break;
158 break;
161 // For 64-bit GOT-relative, use the 64-bit relocation.
164 break;
168 LoReloc = SIInstrInfo::MO_ABS32_LO;
169 HiReloc = SIInstrInfo::MO_ABS32_HI;
170 break;
171 default:
172 llvm_unreachable("unknown relocation type for global address");
173 break;
174 }
175
176 return {BaseFlags, LoReloc, HiReloc};
177}
178
180 const MachineInstr &MI) const {
181
182 if (canRemat(MI)) {
183 // Normally VALU use of exec would block the rematerialization, but that
184 // is OK in this case to have an implicit exec read as all VALU do.
185 // We really want all of the generic logic for this except for this.
186
187 // Another potential implicit use is mode register. The core logic of
188 // the RA will not attempt rematerialization if mode is set anywhere
189 // in the function, otherwise it is safe since mode is not changed.
190
191 // There is difference to generic method which does not allow
192 // rematerialization if there are virtual register uses. We allow this,
193 // therefore this method includes SOP instructions as well.
194 if (!MI.hasImplicitDef() &&
195 MI.getNumImplicitOperands() == MI.getDesc().implicit_uses().size() &&
196 !MI.mayRaiseFPException())
197 return true;
198 }
199
200 // Everything below copied from TargetInstrInfo::isReMaterializableImpl. The
201 // only difference is that we allow operations that perform read-modify-write
202 // on sub-registers.
203
204 // Remat clients assume operand 0 is the defined register.
205 if (!MI.getNumOperands() || !MI.getOperand(0).isReg())
206 return false;
207 Register DefReg = MI.getOperand(0).getReg();
208
209 const MachineFunction &MF = *MI.getMF();
210
211 // A load from a fixed stack slot can be rematerialized. This may be
212 // redundant with subsequent checks, but it's target-independent,
213 // simple, and a common case.
214 int FrameIdx = 0;
215 if (isLoadFromStackSlot(MI, FrameIdx) &&
217 return true;
218
219 // Avoid instructions obviously unsafe for remat.
220 if (MI.isNotDuplicable() || MI.mayStore() || MI.mayRaiseFPException() ||
221 MI.hasUnmodeledSideEffects())
222 return false;
223
224 // Don't remat inline asm. We have no idea how expensive it is
225 // even if it's side effect free.
226 if (MI.isInlineAsm())
227 return false;
228
229 // Avoid instructions which load from potentially varying memory.
230 if (MI.mayLoad() && !MI.isDereferenceableInvariantLoad())
231 return false;
232
233 const MachineRegisterInfo &MRI = MF.getRegInfo();
234
235 // If any of the registers accessed are non-constant, conservatively assume
236 // the instruction is not rematerializable.
237 for (const MachineOperand &MO : MI.operands()) {
238 if (!MO.isReg())
239 continue;
240 Register Reg = MO.getReg();
241 if (Reg == 0)
242 continue;
243
244 // Check for a well-behaved physical register.
245 if (Reg.isPhysical()) {
246 if (MO.isUse()) {
247 // If the physreg has no defs anywhere, it's just an ambient register
248 // and we can freely move its uses. Alternatively, if it's allocatable,
249 // it could get allocated to something with a def during allocation.
250 if (!MRI.isConstantPhysReg(Reg))
251 return false;
252 } else {
253 // A physreg def. We can't remat it.
254 return false;
255 }
256 continue;
257 }
258
259 // Only allow one virtual-register def. There may be multiple defs of the
260 // same virtual register, though.
261 if (MO.isDef() && Reg != DefReg)
262 return false;
263 }
264
265 return true;
266}
267
269 switch (Opcode) {
270 // v_subrev_u16 (gfx9)
271 case AMDGPU::V_SUBREV_U16_e32:
272 case AMDGPU::V_SUBREV_U16_e64:
273 // v_subrev_u32 (gfx9) / v_subrev_nc_u32 (gfx10+)
274 case AMDGPU::V_SUBREV_U32_e32:
275 case AMDGPU::V_SUBREV_U32_e64:
276 // v_subrev_co_u32
277 case AMDGPU::V_SUBREV_CO_U32_e32:
278 case AMDGPU::V_SUBREV_CO_U32_e64:
279 // v_subbrev_u32 (gfx9) / v_subrev_co_ci_u32 (gfx10+)
280 case AMDGPU::V_SUBBREV_U32_e32:
281 case AMDGPU::V_SUBBREV_U32_e64:
282 return true;
283 // REV shift opcodes worked this way before GFX11, verified on hardware
284 case AMDGPU::V_ASHRREV_I16_e32:
285 case AMDGPU::V_ASHRREV_I16_e64:
286 case AMDGPU::V_ASHRREV_I32_e32:
287 case AMDGPU::V_ASHRREV_I32_e64:
288 case AMDGPU::V_ASHRREV_I64_e64:
289 case AMDGPU::V_LSHLREV_B16_e32:
290 case AMDGPU::V_LSHLREV_B16_e64:
291 case AMDGPU::V_LSHLREV_B32_e32:
292 case AMDGPU::V_LSHLREV_B32_e64:
293 case AMDGPU::V_LSHLREV_B64_e64:
294 case AMDGPU::V_LSHRREV_B16_e32:
295 case AMDGPU::V_LSHRREV_B16_e64:
296 case AMDGPU::V_LSHRREV_B32_e32:
297 case AMDGPU::V_LSHRREV_B32_e64:
298 case AMDGPU::V_LSHRREV_B64_e64:
299 return !ST.hasGFX11Insts();
300 default:
301 return false;
302 }
303}
304
305// Returns true if the result of a VALU instruction depends on exec.
306bool SIInstrInfo::resultDependsOnExec(const MachineInstr &MI) const {
307 assert(isVALU(MI, /*AllowLDSDMA=*/true));
308
309 // If it is convergent it depends on EXEC.
310 if (MI.isConvergent())
311 return true;
312
313 // If it defines an SGPR it depends on EXEC, unless it's dead.
314 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
315 for (const MachineOperand &Def : MI.defs()) {
316 if (Def.isDead())
317 continue;
318
319 Register Reg = Def.getReg();
320 if (Reg && RI.isSGPRReg(MRI, Reg))
321 return true;
322 }
323
324 return false;
325}
326
327bool SIInstrInfo::isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const {
328 const MachineOperand &MO = MI.getOperand(OpIdx);
329 // Any implicit use of exec by VALU is not a real register read.
330 return MO.getReg() == AMDGPU::EXEC && MO.isImplicit() &&
331 isVALU(MI, /*AllowLDSDMA=*/true) && !resultDependsOnExec(MI);
332}
333
335 MachineBasicBlock *SuccToSinkTo,
336 MachineCycleInfo *CI) const {
337 // Allow sinking if MI edits lane mask (divergent i1 in sgpr).
338 if (MI.getOpcode() == AMDGPU::SI_IF_BREAK)
339 return true;
340
341 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
342 // Check if sinking of MI would create temporal divergent use.
343 for (auto Op : MI.uses()) {
344 if (Op.isReg() && Op.getReg().isVirtual() &&
345 RI.isSGPRClass(MRI.getRegClass(Op.getReg()))) {
346 MachineInstr *SgprDef = MRI.getVRegDef(Op.getReg());
347 if (!SgprDef)
348 continue;
349
350 // SgprDef defined inside cycle
351 CycleRef FromCycle = CI->getCycle(SgprDef->getParent());
352 if (!FromCycle)
353 continue;
354
355 CycleRef ToCycle = CI->getCycle(SuccToSinkTo);
356 // Check if there is a FromCycle that contains SgprDef's basic block but
357 // does not contain SuccToSinkTo and also has divergent exit condition.
358 while (FromCycle && !(ToCycle && CI->contains(FromCycle, ToCycle))) {
360 CI->getExitingBlocks(FromCycle, ExitingBlocks);
361
362 // FromCycle has divergent exit condition.
363 for (MachineBasicBlock *ExitingBlock : ExitingBlocks) {
364 if (hasDivergentBranch(ExitingBlock))
365 return false;
366 }
367
368 FromCycle = CI->getParentCycle(FromCycle);
369 }
370 }
371 }
372
373 return true;
374}
375
377 int64_t &Offset0,
378 int64_t &Offset1) const {
379 if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode())
380 return false;
381
382 unsigned Opc0 = Load0->getMachineOpcode();
383 unsigned Opc1 = Load1->getMachineOpcode();
384
385 // Make sure both are actually loads.
386 if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad())
387 return false;
388
389 // A mayLoad instruction without a def is not a load. Likely a prefetch.
390 if (!get(Opc0).getNumDefs() || !get(Opc1).getNumDefs())
391 return false;
392
393 if (isDS(Opc0) && isDS(Opc1)) {
394
395 // FIXME: Handle this case:
396 if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1))
397 return false;
398
399 // Check base reg.
400 if (Load0->getOperand(0) != Load1->getOperand(0))
401 return false;
402
403 // Skip read2 / write2 variants for simplicity.
404 // TODO: We should report true if the used offsets are adjacent (excluded
405 // st64 versions).
406 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
407 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
408 if (Offset0Idx == -1 || Offset1Idx == -1)
409 return false;
410
411 // XXX - be careful of dataless loads
412 // getNamedOperandIdx returns the index for MachineInstrs. Since they
413 // include the output in the operand list, but SDNodes don't, we need to
414 // subtract the index by one.
415 Offset0Idx -= get(Opc0).NumDefs;
416 Offset1Idx -= get(Opc1).NumDefs;
417 Offset0 = Load0->getConstantOperandVal(Offset0Idx);
418 Offset1 = Load1->getConstantOperandVal(Offset1Idx);
419 return true;
420 }
421
422 if (isSMRD(Opc0) && isSMRD(Opc1)) {
423 // Skip time and cache invalidation instructions.
424 if (!AMDGPU::hasNamedOperand(Opc0, AMDGPU::OpName::sbase) ||
425 !AMDGPU::hasNamedOperand(Opc1, AMDGPU::OpName::sbase))
426 return false;
427
428 unsigned NumOps = getNumOperandsNoGlue(Load0);
429 if (NumOps != getNumOperandsNoGlue(Load1))
430 return false;
431
432 // Check base reg.
433 if (Load0->getOperand(0) != Load1->getOperand(0))
434 return false;
435
436 // Match register offsets, if both register and immediate offsets present.
437 assert(NumOps == 4 || NumOps == 5);
438 if (NumOps == 5 && Load0->getOperand(1) != Load1->getOperand(1))
439 return false;
440
441 const ConstantSDNode *Load0Offset =
443 const ConstantSDNode *Load1Offset =
445
446 if (!Load0Offset || !Load1Offset)
447 return false;
448
449 Offset0 = Load0Offset->getZExtValue();
450 Offset1 = Load1Offset->getZExtValue();
451 return true;
452 }
453
454 // MUBUF and MTBUF can access the same addresses.
455 if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) {
456
457 // MUBUF and MTBUF have vaddr at different indices.
458 if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) ||
459 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) ||
460 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc))
461 return false;
462
463 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
464 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
465
466 if (OffIdx0 == -1 || OffIdx1 == -1)
467 return false;
468
469 // getNamedOperandIdx returns the index for MachineInstrs. Since they
470 // include the output in the operand list, but SDNodes don't, we need to
471 // subtract the index by one.
472 OffIdx0 -= get(Opc0).NumDefs;
473 OffIdx1 -= get(Opc1).NumDefs;
474
475 SDValue Off0 = Load0->getOperand(OffIdx0);
476 SDValue Off1 = Load1->getOperand(OffIdx1);
477
478 // The offset might be a FrameIndexSDNode.
479 if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1))
480 return false;
481
482 Offset0 = Off0->getAsZExtVal();
483 Offset1 = Off1->getAsZExtVal();
484 return true;
485 }
486
487 return false;
488}
489
490static bool isStride64(unsigned Opc) {
491 switch (Opc) {
492 case AMDGPU::DS_READ2ST64_B32:
493 case AMDGPU::DS_READ2ST64_B64:
494 case AMDGPU::DS_WRITE2ST64_B32:
495 case AMDGPU::DS_WRITE2ST64_B64:
496 return true;
497 default:
498 return false;
499 }
500}
501
504 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const {
505 if (!LdSt.mayLoadOrStore())
506 return false;
507
508 unsigned Opc = LdSt.getOpcode();
509 OffsetIsScalable = false;
510 const MachineOperand *BaseOp, *OffsetOp;
511 int DataOpIdx;
512
513 if (isDS(LdSt)) {
514 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr);
515 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
516 if (OffsetOp) {
517 // Normal, single offset LDS instruction.
518 if (!BaseOp) {
519 // DS_CONSUME/DS_APPEND use M0 for the base address.
520 // TODO: find the implicit use operand for M0 and use that as BaseOp?
521 return false;
522 }
523 BaseOps.push_back(BaseOp);
524 Offset = OffsetOp->getImm();
525 // Get appropriate operand, and compute width accordingly.
526 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
527 if (DataOpIdx == -1)
528 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
529 if (Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
530 Width = LocationSize::precise(64);
531 else
532 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
533 } else {
534 // The 2 offset instructions use offset0 and offset1 instead. We can treat
535 // these as a load with a single offset if the 2 offsets are consecutive.
536 // We will use this for some partially aligned loads.
537 const MachineOperand *Offset0Op =
538 getNamedOperand(LdSt, AMDGPU::OpName::offset0);
539 const MachineOperand *Offset1Op =
540 getNamedOperand(LdSt, AMDGPU::OpName::offset1);
541
542 unsigned Offset0 = Offset0Op->getImm() & 0xff;
543 unsigned Offset1 = Offset1Op->getImm() & 0xff;
544 if (Offset0 + 1 != Offset1)
545 return false;
546
547 // Each of these offsets is in element sized units, so we need to convert
548 // to bytes of the individual reads.
549
550 unsigned EltSize;
551 if (LdSt.mayLoad())
552 EltSize = RI.getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16;
553 else {
554 assert(LdSt.mayStore());
555 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
556 EltSize = RI.getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8;
557 }
558
559 if (isStride64(Opc))
560 EltSize *= 64;
561
562 BaseOps.push_back(BaseOp);
563 Offset = EltSize * Offset0;
564 // Get appropriate operand(s), and compute width accordingly.
565 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
566 if (DataOpIdx == -1) {
567 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
568 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
569 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
570 Width = LocationSize::precise(
571 Width.getValue() + TypeSize::getFixed(getOpSize(LdSt, DataOpIdx)));
572 } else {
573 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
574 }
575 }
576 return true;
577 }
578
579 if (isMUBUF(LdSt) || isMTBUF(LdSt)) {
580 const MachineOperand *RSrc = getNamedOperand(LdSt, AMDGPU::OpName::srsrc);
581 if (!RSrc) // e.g. BUFFER_WBINVL1_VOL
582 return false;
583 BaseOps.push_back(RSrc);
584 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
585 if (BaseOp && !BaseOp->isFI())
586 BaseOps.push_back(BaseOp);
587 const MachineOperand *OffsetImm =
588 getNamedOperand(LdSt, AMDGPU::OpName::offset);
589 Offset = OffsetImm->getImm();
590 const MachineOperand *SOffset =
591 getNamedOperand(LdSt, AMDGPU::OpName::soffset);
592 if (SOffset) {
593 if (SOffset->isReg())
594 BaseOps.push_back(SOffset);
595 else
596 Offset += SOffset->getImm();
597 }
598 // Get appropriate operand, and compute width accordingly.
599 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
600 if (DataOpIdx == -1)
601 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
602 if (DataOpIdx == -1) // LDS DMA
603 return false;
604 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
605 return true;
606 }
607
608 if (isImage(LdSt)) {
609 auto RsrcOpName =
610 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
611 int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RsrcOpName);
612 BaseOps.push_back(&LdSt.getOperand(SRsrcIdx));
613 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
614 if (VAddr0Idx >= 0) {
615 // GFX10 possible NSA encoding.
616 for (int I = VAddr0Idx; I < SRsrcIdx; ++I)
617 BaseOps.push_back(&LdSt.getOperand(I));
618 } else {
619 BaseOps.push_back(getNamedOperand(LdSt, AMDGPU::OpName::vaddr));
620 }
621 Offset = 0;
622 // Get appropriate operand, and compute width accordingly.
623 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
624 if (DataOpIdx == -1)
625 return false; // no return sampler
626 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
627 return true;
628 }
629
630 if (isSMRD(LdSt)) {
631 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::sbase);
632 if (!BaseOp) // e.g. S_MEMTIME
633 return false;
634 BaseOps.push_back(BaseOp);
635 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
636 Offset = OffsetOp ? OffsetOp->getImm() : 0;
637 // Get appropriate operand, and compute width accordingly.
638 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
639 if (DataOpIdx == -1)
640 return false;
641 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
642 return true;
643 }
644
645 if (isFLAT(LdSt)) {
646 // Instructions have either vaddr or saddr or both or none.
647 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
648 if (BaseOp)
649 BaseOps.push_back(BaseOp);
650 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr);
651 if (BaseOp)
652 BaseOps.push_back(BaseOp);
653 Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm();
654 // Get appropriate operand, and compute width accordingly.
655 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
656 if (DataOpIdx == -1)
657 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
658 if (DataOpIdx == -1) // LDS DMA
659 return false;
660 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
661 return true;
662 }
663
664 return false;
665}
666
667static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
669 const MachineInstr &MI2,
671 // Only examine the first "base" operand of each instruction, on the
672 // assumption that it represents the real base address of the memory access.
673 // Other operands are typically offsets or indices from this base address.
674 if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
675 return true;
676
677 if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
678 return false;
679
680 auto *MO1 = *MI1.memoperands_begin();
681 auto *MO2 = *MI2.memoperands_begin();
682 if (MO1->getAddrSpace() != MO2->getAddrSpace())
683 return false;
684
685 const auto *Base1 = MO1->getValue();
686 const auto *Base2 = MO2->getValue();
687 if (!Base1 || !Base2)
688 return false;
689 Base1 = getUnderlyingObject(Base1);
690 Base2 = getUnderlyingObject(Base2);
691
692 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
693 return false;
694
695 return Base1 == Base2;
696}
697
700 ArrayRef<const MachineOperand *> BaseOps2) const {
701 // Accesses without base operands (e.g. scratch addressed only by an
702 // immediate offset) share the same implicit base.
703 if (BaseOps1.empty() || BaseOps2.empty())
704 return BaseOps1.empty() && BaseOps2.empty();
705 return memOpsHaveSameBasePtr(*BaseOps1.front()->getParent(), BaseOps1,
706 *BaseOps2.front()->getParent(), BaseOps2);
707}
708
710 int64_t Offset1, bool OffsetIsScalable1,
712 int64_t Offset2, bool OffsetIsScalable2,
713 unsigned ClusterSize,
714 unsigned NumBytes) const {
715 // If the mem ops (to be clustered) do not have the same base ptr, then they
716 // should not be clustered
717 if (!memOpsHaveSameBase(BaseOps1, BaseOps2))
718 return false;
719
720 // Both lists are empty or neither is, so BaseOps1 alone decides whether
721 // there is an instruction to read the budget from.
722 assert(BaseOps1.empty() == BaseOps2.empty());
723 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;
724 if (!BaseOps1.empty()) {
725 const MachineFunction *MF = BaseOps1.front()->getParent()->getMF();
726 MaxMemoryClusterDWords =
727 MF->getInfo<SIMachineFunctionInfo>()->getMaxMemoryClusterDWords();
728 }
729
730 // In order to avoid register pressure, on an average, the number of DWORDS
731 // loaded together by all clustered mem ops should not exceed
732 // MaxMemoryClusterDWords. This is an empirical value based on certain
733 // observations and performance related experiments.
734 // The good thing about this heuristic is - it avoids clustering of too many
735 // sub-word loads, and also avoids clustering of wide loads. Below is the
736 // brief summary of how the heuristic behaves for various `LoadSize` when
737 // MaxMemoryClusterDWords is 8.
738 //
739 // (1) 1 <= LoadSize <= 4: cluster at max 8 mem ops
740 // (2) 5 <= LoadSize <= 8: cluster at max 4 mem ops
741 // (3) 9 <= LoadSize <= 12: cluster at max 2 mem ops
742 // (4) 13 <= LoadSize <= 16: cluster at max 2 mem ops
743 // (5) LoadSize >= 17: do not cluster
744 const unsigned LoadSize = NumBytes / ClusterSize;
745 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
746 return NumDWords <= MaxMemoryClusterDWords;
747}
748
749// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
750// the first 16 loads will be interleaved with the stores, and the next 16 will
751// be clustered as expected. It should really split into 2 16 store batches.
752//
753// Loads are clustered until this returns false, rather than trying to schedule
754// groups of stores. This also means we have to deal with saying different
755// address space loads should be clustered, and ones which might cause bank
756// conflicts.
757//
758// This might be deprecated so it might not be worth that much effort to fix.
760 int64_t Offset0, int64_t Offset1,
761 unsigned NumLoads) const {
762 assert(Offset1 > Offset0 &&
763 "Second offset should be larger than first offset!");
764 // If we have less than 16 loads in a row, and the offsets are within 64
765 // bytes, then schedule together.
766
767 // A cacheline is 64 bytes (for global memory).
768 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
769}
770
773 const DebugLoc &DL, MCRegister DestReg,
774 MCRegister SrcReg, bool KillSrc,
775 const char *Msg = "illegal VGPR to SGPR copy") {
776 MachineFunction *MF = MBB.getParent();
777
780
781 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg)
782 .addReg(SrcReg, getKillRegState(KillSrc));
783}
784
785/// Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908. It is not
786/// possible to have a direct copy in these cases on GFX908, so an intermediate
787/// VGPR copy is required.
790 const DebugLoc &DL, MCRegister DestReg,
791 MCRegister SrcReg, bool KillSrc,
792 RegScavenger &RS, bool RegsOverlap,
793 Register ImpUseSuperReg = Register()) {
794 assert((TII.getSubtarget().hasMAIInsts() &&
795 !TII.getSubtarget().hasGFX90AInsts()) &&
796 "Expected GFX908 subtarget.");
797
798 assert((AMDGPU::SReg_32RegClass.contains(SrcReg) ||
799 AMDGPU::AGPR_32RegClass.contains(SrcReg)) &&
800 "Source register of the copy should be either an SGPR or an AGPR.");
801
802 assert(AMDGPU::AGPR_32RegClass.contains(DestReg) &&
803 "Destination register of the copy should be an AGPR.");
804
805 const SIRegisterInfo &RI = TII.getRegisterInfo();
806
807 // First try to find defining accvgpr_write to avoid temporary registers.
808 // In the case of copies of overlapping AGPRs, we conservatively do not
809 // reuse previous accvgpr_writes. Otherwise, we may incorrectly pick up
810 // an accvgpr_write used for this same copy due to implicit-defs
811 if (!RegsOverlap) {
812 for (auto Def = MI, E = MBB.begin(); Def != E; ) {
813 --Def;
814
815 if (!Def->modifiesRegister(SrcReg, &RI))
816 continue;
817
818 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
819 Def->getOperand(0).getReg() != SrcReg)
820 break;
821
822 MachineOperand &DefOp = Def->getOperand(1);
823 assert(DefOp.isReg() || DefOp.isImm());
824
825 if (DefOp.isReg()) {
826 bool SafeToPropagate = true;
827 // Check that register source operand is not clobbered before MI.
828 // Immediate operands are always safe to propagate.
829 for (auto I = Def; I != MI && SafeToPropagate; ++I)
830 if (I->modifiesRegister(DefOp.getReg(), &RI))
831 SafeToPropagate = false;
832
833 if (!SafeToPropagate)
834 break;
835
836 for (auto I = Def; I != MI; ++I)
837 I->clearRegisterKills(DefOp.getReg(), &RI);
838 }
839
840 MachineInstrBuilder Builder =
841 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64),
842 DestReg)
843 .add(DefOp);
844
845 if (ImpUseSuperReg) {
846 Builder.addReg(ImpUseSuperReg,
848 }
849
850 return;
851 }
852 }
853
854 RS.enterBasicBlockEnd(MBB);
855 RS.backward(std::next(MI));
856
857 // Ideally we want to have three registers for a long reg_sequence copy
858 // to hide 2 waitstates between v_mov_b32 and accvgpr_write.
859 unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass,
860 *MBB.getParent());
861
862 // Registers in the sequence are allocated contiguously so we can just
863 // use register number to pick one of three round-robin temps.
864 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
865 Register Tmp =
866 MBB.getParent()->getInfo<SIMachineFunctionInfo>()->getVGPRForAGPRCopy();
867 assert(MBB.getParent()->getRegInfo().isReserved(Tmp) &&
868 "VGPR used for an intermediate copy should have been reserved.");
869
870 // Only loop through if there are any free registers left. We don't want to
871 // spill.
872 while (RegNo--) {
873 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI,
874 /* RestoreAfter */ false, 0,
875 /* AllowSpill */ false);
876 if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs)
877 break;
878 Tmp = Tmp2;
879 RS.setRegUsed(Tmp);
880 }
881
882 // Insert copy to temporary VGPR.
883 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
884 if (AMDGPU::AGPR_32RegClass.contains(SrcReg)) {
885 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
886 } else {
887 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
888 }
889
890 MachineInstrBuilder UseBuilder = BuildMI(MBB, MI, DL, TII.get(TmpCopyOp), Tmp)
891 .addReg(SrcReg, getKillRegState(KillSrc));
892 if (ImpUseSuperReg) {
893 UseBuilder.addReg(ImpUseSuperReg,
895 }
896
897 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
898 .addReg(Tmp, RegState::Kill);
899}
900
903 MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
904 const TargetRegisterClass *RC, bool Forward) {
905 const SIRegisterInfo &RI = TII.getRegisterInfo();
906 ArrayRef<int16_t> BaseIndices = RI.getRegSplitParts(RC, 4);
908 MachineInstr *FirstMI = nullptr, *LastMI = nullptr;
909
910 for (unsigned Idx = 0; Idx < BaseIndices.size(); ++Idx) {
911 int16_t SubIdx = BaseIndices[Idx];
912 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
913 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
914 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
915 unsigned Opcode = AMDGPU::S_MOV_B32;
916
917 // Is SGPR aligned? If so try to combine with next.
918 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
919 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
920 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.size())) {
921 // Can use SGPR64 copy
922 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
923 SubIdx = RI.getSubRegFromChannel(Channel, 2);
924 DestSubReg = RI.getSubReg(DestReg, SubIdx);
925 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
926 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
927 Opcode = AMDGPU::S_MOV_B64;
928 Idx++;
929 }
930
931 LastMI = BuildMI(MBB, I, DL, TII.get(Opcode), DestSubReg)
932 .addReg(SrcSubReg)
933 .addReg(SrcReg, RegState::Implicit);
934
935 if (!FirstMI)
936 FirstMI = LastMI;
937
938 if (!Forward)
939 I--;
940 }
941
942 assert(FirstMI && LastMI);
943 if (!Forward)
944 std::swap(FirstMI, LastMI);
945
946 if (KillSrc)
947 LastMI->addRegisterKilled(SrcReg, &RI);
948}
949
952 const DebugLoc &DL, Register DestReg,
953 Register SrcReg, bool KillSrc, bool RenamableDest,
954 bool RenamableSrc) const {
955 const TargetRegisterClass *RC = RI.getPhysRegBaseClass(DestReg);
956 unsigned Size = RI.getRegSizeInBits(*RC);
957 const TargetRegisterClass *SrcRC = RI.getPhysRegBaseClass(SrcReg);
958 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
959
960 // The rest of copyPhysReg assumes Src and Dst size are the same size.
961 // TODO-GFX11_16BIT If all true 16 bit instruction patterns are completed can
962 // we remove Fix16BitCopies and this code block?
963 if (Fix16BitCopies) {
964 if (((Size == 16) != (SrcSize == 16))) {
965 // Non-VGPR Src and Dst will later be expanded back to 32 bits.
966 assert(ST.useRealTrue16Insts());
967 Register &RegToFix = (Size == 32) ? DestReg : SrcReg;
968 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
969 RegToFix = SubReg;
970
971 if (DestReg == SrcReg) {
972 // Identity copy. Insert empty bundle since ExpandPostRA expects an
973 // instruction here.
974 BuildMI(MBB, MI, DL, get(AMDGPU::BUNDLE));
975 return;
976 }
977 RC = RI.getPhysRegBaseClass(DestReg);
978 Size = RI.getRegSizeInBits(*RC);
979 SrcRC = RI.getPhysRegBaseClass(SrcReg);
980 SrcSize = RI.getRegSizeInBits(*SrcRC);
981 }
982 }
983
984 if (RC == &AMDGPU::VGPR_32RegClass) {
985 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
986 AMDGPU::SReg_32RegClass.contains(SrcReg) ||
987 AMDGPU::AGPR_32RegClass.contains(SrcReg));
988 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
989 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
990 BuildMI(MBB, MI, DL, get(Opc), DestReg)
991 .addReg(SrcReg, getKillRegState(KillSrc));
992 return;
993 }
994
995 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
996 RC == &AMDGPU::SReg_32RegClass) {
997 if (SrcReg == AMDGPU::SCC) {
998 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg)
999 .addImm(1)
1000 .addImm(0);
1001 return;
1002 }
1003
1004 if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) {
1005 if (DestReg == AMDGPU::VCC_LO) {
1006 // FIXME: Hack until VReg_1 removed.
1007 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
1008 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
1009 .addImm(0)
1010 .addReg(SrcReg, getKillRegState(KillSrc));
1011 return;
1012 }
1013
1014 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1015 return;
1016 }
1017
1018 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
1019 .addReg(SrcReg, getKillRegState(KillSrc));
1020 return;
1021 }
1022
1023 if (RC == &AMDGPU::SReg_64RegClass) {
1024 if (SrcReg == AMDGPU::SCC) {
1025 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B64), DestReg)
1026 .addImm(1)
1027 .addImm(0);
1028 return;
1029 }
1030
1031 if (!AMDGPU::SReg_64_EncodableRegClass.contains(SrcReg)) {
1032 if (DestReg == AMDGPU::VCC) {
1033 // FIXME: Hack until VReg_1 removed.
1034 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
1035 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
1036 .addImm(0)
1037 .addReg(SrcReg, getKillRegState(KillSrc));
1038 return;
1039 }
1040
1041 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1042 return;
1043 }
1044
1045 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
1046 .addReg(SrcReg, getKillRegState(KillSrc));
1047 return;
1048 }
1049
1050 if (DestReg == AMDGPU::SCC) {
1051 // Copying 64-bit or 32-bit sources to SCC barely makes sense,
1052 // but SelectionDAG emits such copies for i1 sources.
1053 if (AMDGPU::SReg_64RegClass.contains(SrcReg)) {
1054 // This copy can only be produced by patterns
1055 // with explicit SCC, which are known to be enabled
1056 // only for subtargets with S_CMP_LG_U64 present.
1057 assert(ST.hasScalarCompareEq64());
1058 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U64))
1059 .addReg(SrcReg, getKillRegState(KillSrc))
1060 .addImm(0);
1061 } else {
1062 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
1063 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32))
1064 .addReg(SrcReg, getKillRegState(KillSrc))
1065 .addImm(0);
1066 }
1067
1068 return;
1069 }
1070
1071 if (RC == &AMDGPU::AGPR_32RegClass) {
1072 if (AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
1073 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1074 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
1075 .addReg(SrcReg, getKillRegState(KillSrc));
1076 return;
1077 }
1078
1079 if (AMDGPU::AGPR_32RegClass.contains(SrcReg) && ST.hasGFX90AInsts()) {
1080 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_MOV_B32), DestReg)
1081 .addReg(SrcReg, getKillRegState(KillSrc));
1082 return;
1083 }
1084
1085 // FIXME: Pass should maintain scavenger to avoid scan through the block on
1086 // every AGPR spill.
1087 RegScavenger RS;
1088 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1089 indirectCopyToAGPR(*this, MBB, MI, DL, DestReg, SrcReg, KillSrc, RS, Overlap);
1090 return;
1091 }
1092
1093 if (Size == 16) {
1094 assert(AMDGPU::VGPR_16RegClass.contains(SrcReg) ||
1095 AMDGPU::SReg_LO16RegClass.contains(SrcReg) ||
1096 AMDGPU::AGPR_LO16RegClass.contains(SrcReg));
1097
1098 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1099 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1100 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1101 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1102 bool DstLow = !AMDGPU::isHi16Reg(DestReg, RI);
1103 bool SrcLow = !AMDGPU::isHi16Reg(SrcReg, RI);
1104 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1105 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1106
1107 if (IsSGPRDst) {
1108 if (!IsSGPRSrc) {
1109 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1110 return;
1111 }
1112
1113 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), NewDestReg)
1114 .addReg(NewSrcReg, getKillRegState(KillSrc));
1115 return;
1116 }
1117
1118 if (IsAGPRDst || IsAGPRSrc) {
1119 if (!DstLow || !SrcLow) {
1120 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1121 "Cannot use hi16 subreg with an AGPR!");
1122 }
1123
1124 copyPhysReg(MBB, MI, DL, NewDestReg, NewSrcReg, KillSrc);
1125 return;
1126 }
1127
1128 if (ST.useRealTrue16Insts()) {
1129 if (IsSGPRSrc) {
1130 assert(SrcLow);
1131 SrcReg = NewSrcReg;
1132 }
1133 // Use the smaller instruction encoding if possible.
1134 if (AMDGPU::VGPR_16_Lo128RegClass.contains(DestReg) &&
1135 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.contains(SrcReg))) {
1136 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e32), DestReg)
1137 .addReg(SrcReg);
1138 } else {
1139 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e64), DestReg)
1140 .addImm(0) // src0_modifiers
1141 .addReg(SrcReg)
1142 .addImm(0); // op_sel
1143 }
1144 return;
1145 }
1146
1147 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1148 if (!DstLow || !SrcLow) {
1149 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1150 "Cannot use hi16 subreg on VI!");
1151 }
1152
1153 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), NewDestReg)
1154 .addReg(NewSrcReg, getKillRegState(KillSrc));
1155 return;
1156 }
1157
1158 auto MIB = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_sdwa), NewDestReg)
1159 .addImm(0) // src0_modifiers
1160 .addReg(NewSrcReg)
1161 .addImm(0) // clamp
1168 // First implicit operand is $exec.
1169 MIB->tieOperands(0, MIB->getNumOperands() - 1);
1170 return;
1171 }
1172
1173 // Returns true if Dst and Src are in Opc's HwMode-resolved destination and
1174 // source operand classes.
1175 auto CanCopyWith = [&](unsigned Opc, MCRegister Dst, MCRegister Src,
1176 unsigned SrcOp = 1) {
1177 const MCInstrDesc &Desc = get(Opc);
1178 const TargetRegisterClass *DstOpRC = getRegClass(Desc, 0);
1179 const TargetRegisterClass *SrcOpRC = getRegClass(Desc, SrcOp);
1180 return DstOpRC && SrcOpRC && DstOpRC->contains(Dst) &&
1181 SrcOpRC->contains(Src);
1182 };
1183
1184 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1185 if (ST.hasVMovB64Inst() &&
1186 CanCopyWith(AMDGPU::V_MOV_B64_e32, DestReg, SrcReg)) {
1187 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_e32), DestReg)
1188 .addReg(SrcReg, getKillRegState(KillSrc));
1189 return;
1190 }
1191 if (ST.hasPkMovB32() &&
1192 CanCopyWith(AMDGPU::V_PK_MOV_B32, DestReg, SrcReg, /*SrcOp=*/2)) {
1193 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestReg)
1195 .addReg(SrcReg)
1197 .addReg(SrcReg)
1198 .addImm(0) // op_sel_lo
1199 .addImm(0) // op_sel_hi
1200 .addImm(0) // neg_lo
1201 .addImm(0) // neg_hi
1202 .addImm(0) // clamp
1203 .addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
1204 return;
1205 }
1206 }
1207
1208 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1209 if (RI.isSGPRClass(RC)) {
1210 if (!RI.isSGPRClass(SrcRC)) {
1211 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1212 return;
1213 }
1214 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1215 expandSGPRCopy(*this, MBB, MI, DL, DestReg, SrcReg, CanKillSuperReg, RC,
1216 Forward);
1217 return;
1218 }
1219
1220 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1221 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1222 if (RI.isAGPRClass(RC)) {
1223 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1224 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1225 else if (RI.hasVGPRs(SrcRC) ||
1226 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1227 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1228 else
1229 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1230 } else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1231 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1232 } else if (RI.isVGPRClass(RC)) {
1233 if (ST.hasVMovB64Inst())
1234 WideOpcode = AMDGPU::V_MOV_B64_e32;
1235 else if (ST.hasPkMovB32())
1236 WideOpcode = AMDGPU::V_PK_MOV_B32;
1237 }
1238
1239 const TargetRegisterClass *WideDstRC{}, *WideSrcRC{};
1240 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1241 const MCInstrDesc &Desc = get(WideOpcode);
1242 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1243 WideDstRC = getRegClass(Desc, 0);
1244 WideSrcRC = getRegClass(Desc, SrcOp);
1245 }
1246
1247 // If there is an overlap, we can't kill the super-register on the last
1248 // instruction, since it will also kill the components made live by this def.
1249 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1250 const bool CanKillSuperReg = KillSrc && !Overlap;
1251
1252 // For the cases where we need an intermediate instruction/temporary register
1253 // (destination is an AGPR), we need a scavenger.
1254 //
1255 // FIXME: The pass should maintain this for us so we don't have to re-scan the
1256 // whole block for every handled copy.
1257 std::unique_ptr<RegScavenger> RS;
1258 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1259 RS = std::make_unique<RegScavenger>();
1260
1261 ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, 4);
1262
1263 for (unsigned Idx{}; Idx < SubIndices.size();) {
1264 unsigned NumRegs = 1;
1265 unsigned ThisOpcode = Opcode;
1266 unsigned SubIdx =
1267 Forward ? SubIndices[Idx] : SubIndices[SubIndices.size() - Idx - 1];
1268
1269 if (WideDstRC && WideSrcRC && Idx + 1 < SubIndices.size()) {
1270 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1271 if (!Forward)
1272 --Channel;
1273
1274 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1275 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1276 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1277
1278 if (WideDst && WideSrc && WideDstRC->contains(WideDst) &&
1279 WideSrcRC->contains(WideSrc)) {
1280 SubIdx = WideSubIdx;
1281 NumRegs = 2;
1282 ThisOpcode = WideOpcode;
1283 }
1284 }
1285
1286 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1287 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1288 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
1289
1290 Idx += NumRegs;
1291 bool UseKill = CanKillSuperReg && Idx == SubIndices.size();
1292
1293 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1294 Register ImpUseSuper = SrcReg;
1295 indirectCopyToAGPR(*this, MBB, MI, DL, DestSubReg, SrcSubReg, UseKill,
1296 *RS, Overlap, ImpUseSuper);
1297 } else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1298 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestSubReg)
1300 .addReg(SrcSubReg)
1302 .addReg(SrcSubReg)
1303 .addImm(0) // op_sel_lo
1304 .addImm(0) // op_sel_hi
1305 .addImm(0) // neg_lo
1306 .addImm(0) // neg_hi
1307 .addImm(0) // clamp
1308 .addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1309 } else {
1310 MachineInstrBuilder Builder =
1311 BuildMI(MBB, MI, DL, get(ThisOpcode), DestSubReg).addReg(SrcSubReg);
1312
1313 Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1314 }
1315 }
1316}
1317
1318int SIInstrInfo::commuteOpcode(unsigned Opcode) const {
1319 int32_t NewOpc;
1320
1321 // Try to map original to commuted opcode
1322 NewOpc = AMDGPU::getCommuteRev(Opcode);
1323 if (NewOpc != -1)
1324 // Check if the commuted (REV) opcode exists on the target.
1325 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1326
1327 // Try to map commuted to original opcode
1328 NewOpc = AMDGPU::getCommuteOrig(Opcode);
1329 if (NewOpc != -1)
1330 // Check if the original (non-REV) opcode exists on the target.
1331 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1332
1333 return Opcode;
1334}
1335
1337 const Register Reg,
1338 int64_t &ImmVal) const {
1339 switch (MI.getOpcode()) {
1340 case AMDGPU::V_MOV_B32_e32:
1341 case AMDGPU::S_MOV_B32:
1342 case AMDGPU::S_MOVK_I32:
1343 case AMDGPU::S_MOV_B64:
1344 case AMDGPU::V_MOV_B64_e32:
1345 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1346 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1347 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1348 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1349 case AMDGPU::V_MOV_B64_PSEUDO:
1350 case AMDGPU::V_MOV_B16_t16_e32: {
1351 const MachineOperand &Src0 = MI.getOperand(1);
1352 if (Src0.isImm()) {
1353 ImmVal = Src0.getImm();
1354 return MI.getOperand(0).getReg() == Reg;
1355 }
1356
1357 return false;
1358 }
1359 case AMDGPU::V_MOV_B16_t16_e64: {
1360 const MachineOperand &Src0 = MI.getOperand(2);
1361 if (Src0.isImm() && !MI.getOperand(1).getImm()) {
1362 ImmVal = Src0.getImm();
1363 return MI.getOperand(0).getReg() == Reg;
1364 }
1365
1366 return false;
1367 }
1368 case AMDGPU::S_BREV_B32:
1369 case AMDGPU::V_BFREV_B32_e32:
1370 case AMDGPU::V_BFREV_B32_e64: {
1371 const MachineOperand &Src0 = MI.getOperand(1);
1372 if (Src0.isImm()) {
1373 ImmVal = static_cast<int64_t>(reverseBits<int32_t>(Src0.getImm()));
1374 return MI.getOperand(0).getReg() == Reg;
1375 }
1376
1377 return false;
1378 }
1379 case AMDGPU::S_NOT_B32:
1380 case AMDGPU::V_NOT_B32_e32:
1381 case AMDGPU::V_NOT_B32_e64: {
1382 const MachineOperand &Src0 = MI.getOperand(1);
1383 if (Src0.isImm()) {
1384 ImmVal = static_cast<int64_t>(~static_cast<int32_t>(Src0.getImm()));
1385 return MI.getOperand(0).getReg() == Reg;
1386 }
1387
1388 return false;
1389 }
1390 default:
1391 return false;
1392 }
1393}
1394
1395std::optional<int64_t>
1397 const MachineOperand &Op,
1398 MachineInstr **DefMI) const {
1399 if (DefMI)
1400 *DefMI = nullptr;
1401
1402 if (Op.isImm())
1403 return Op.getImm();
1404
1405 if (!Op.isReg() || !Op.getReg().isVirtual())
1406 return std::nullopt;
1407 MachineInstr *Def = MRI.getUniqueVRegDef(Op.getReg());
1408 if (Def && Def->isMoveImmediate()) {
1409 const MachineOperand &ImmSrc = Def->getOperand(1);
1410 if (ImmSrc.isImm()) {
1411 if (DefMI)
1412 *DefMI = Def;
1413 return extractSubregFromImm(ImmSrc.getImm(), Op.getSubReg());
1414 }
1415 }
1416
1417 return std::nullopt;
1418}
1419
1420std::optional<int64_t>
1426
1428
1429 if (RI.isAGPRClass(DstRC))
1430 return AMDGPU::COPY;
1431 if (RI.getRegSizeInBits(*DstRC) == 16) {
1432 // Assume hi bits are unneeded. Only _e64 true16 instructions are legal
1433 // before RA.
1434 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1435 }
1436 if (RI.getRegSizeInBits(*DstRC) == 32)
1437 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1438 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1439 return AMDGPU::S_MOV_B64;
1440 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1441 return AMDGPU::V_MOV_B64_PSEUDO;
1442 return AMDGPU::COPY;
1443}
1444
1445const MCInstrDesc &
1447 bool IsIndirectSrc) const {
1448 if (IsIndirectSrc) {
1449 if (VecSize <= 32) // 4 bytes
1450 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1451 if (VecSize <= 64) // 8 bytes
1452 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1453 if (VecSize <= 96) // 12 bytes
1454 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1455 if (VecSize <= 128) // 16 bytes
1456 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1457 if (VecSize <= 160) // 20 bytes
1458 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1459 if (VecSize <= 192) // 24 bytes
1460 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1461 if (VecSize <= 224) // 28 bytes
1462 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1463 if (VecSize <= 256) // 32 bytes
1464 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1465 if (VecSize <= 288) // 36 bytes
1466 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1467 if (VecSize <= 320) // 40 bytes
1468 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1469 if (VecSize <= 352) // 44 bytes
1470 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1471 if (VecSize <= 384) // 48 bytes
1472 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1473 if (VecSize <= 512) // 64 bytes
1474 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1475 if (VecSize <= 1024) // 128 bytes
1476 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1477
1478 llvm_unreachable("unsupported size for IndirectRegReadGPRIDX pseudos");
1479 }
1480
1481 if (VecSize <= 32) // 4 bytes
1482 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1483 if (VecSize <= 64) // 8 bytes
1484 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1485 if (VecSize <= 96) // 12 bytes
1486 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1487 if (VecSize <= 128) // 16 bytes
1488 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1489 if (VecSize <= 160) // 20 bytes
1490 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1491 if (VecSize <= 192) // 24 bytes
1492 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1493 if (VecSize <= 224) // 28 bytes
1494 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1495 if (VecSize <= 256) // 32 bytes
1496 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1497 if (VecSize <= 288) // 36 bytes
1498 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1499 if (VecSize <= 320) // 40 bytes
1500 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1501 if (VecSize <= 352) // 44 bytes
1502 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1503 if (VecSize <= 384) // 48 bytes
1504 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1505 if (VecSize <= 512) // 64 bytes
1506 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1507 if (VecSize <= 1024) // 128 bytes
1508 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1509
1510 llvm_unreachable("unsupported size for IndirectRegWriteGPRIDX pseudos");
1511}
1512
1513static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize) {
1514 if (VecSize <= 32) // 4 bytes
1515 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1516 if (VecSize <= 64) // 8 bytes
1517 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1518 if (VecSize <= 96) // 12 bytes
1519 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1520 if (VecSize <= 128) // 16 bytes
1521 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1522 if (VecSize <= 160) // 20 bytes
1523 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1524 if (VecSize <= 192) // 24 bytes
1525 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1526 if (VecSize <= 224) // 28 bytes
1527 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1528 if (VecSize <= 256) // 32 bytes
1529 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1530 if (VecSize <= 288) // 36 bytes
1531 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1532 if (VecSize <= 320) // 40 bytes
1533 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1534 if (VecSize <= 352) // 44 bytes
1535 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1536 if (VecSize <= 384) // 48 bytes
1537 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1538 if (VecSize <= 512) // 64 bytes
1539 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1540 if (VecSize <= 1024) // 128 bytes
1541 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1542
1543 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1544}
1545
1546static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize) {
1547 if (VecSize <= 32) // 4 bytes
1548 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1549 if (VecSize <= 64) // 8 bytes
1550 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1551 if (VecSize <= 96) // 12 bytes
1552 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1553 if (VecSize <= 128) // 16 bytes
1554 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1555 if (VecSize <= 160) // 20 bytes
1556 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1557 if (VecSize <= 192) // 24 bytes
1558 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1559 if (VecSize <= 224) // 28 bytes
1560 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1561 if (VecSize <= 256) // 32 bytes
1562 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1563 if (VecSize <= 288) // 36 bytes
1564 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1565 if (VecSize <= 320) // 40 bytes
1566 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1567 if (VecSize <= 352) // 44 bytes
1568 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1569 if (VecSize <= 384) // 48 bytes
1570 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1571 if (VecSize <= 512) // 64 bytes
1572 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1573 if (VecSize <= 1024) // 128 bytes
1574 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1575
1576 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1577}
1578
1579static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize) {
1580 if (VecSize <= 64) // 8 bytes
1581 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1582 if (VecSize <= 128) // 16 bytes
1583 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1584 if (VecSize <= 256) // 32 bytes
1585 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1586 if (VecSize <= 512) // 64 bytes
1587 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1588 if (VecSize <= 1024) // 128 bytes
1589 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1590
1591 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1592}
1593
1594const MCInstrDesc &
1595SIInstrInfo::getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize,
1596 bool IsSGPR) const {
1597 if (IsSGPR) {
1598 switch (EltSize) {
1599 case 32:
1600 return get(getIndirectSGPRWriteMovRelPseudo32(VecSize));
1601 case 64:
1602 return get(getIndirectSGPRWriteMovRelPseudo64(VecSize));
1603 default:
1604 llvm_unreachable("invalid reg indexing elt size");
1605 }
1606 }
1607
1608 assert(EltSize == 32 && "invalid reg indexing elt size");
1610}
1611
1612static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1613 switch (Size) {
1614 case 4:
1615 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1616 case 8:
1617 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1618 case 12:
1619 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1620 case 16:
1621 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1622 : AMDGPU::SI_SPILL_S128_SAVE;
1623 case 20:
1624 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1625 : AMDGPU::SI_SPILL_S160_SAVE;
1626 case 24:
1627 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1628 : AMDGPU::SI_SPILL_S192_SAVE;
1629 case 28:
1630 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1631 : AMDGPU::SI_SPILL_S224_SAVE;
1632 case 32:
1633 return AMDGPU::SI_SPILL_S256_SAVE;
1634 case 36:
1635 return AMDGPU::SI_SPILL_S288_SAVE;
1636 case 40:
1637 return AMDGPU::SI_SPILL_S320_SAVE;
1638 case 44:
1639 return AMDGPU::SI_SPILL_S352_SAVE;
1640 case 48:
1641 return AMDGPU::SI_SPILL_S384_SAVE;
1642 case 64:
1643 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1644 : AMDGPU::SI_SPILL_S512_SAVE;
1645 case 128:
1646 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1647 : AMDGPU::SI_SPILL_S1024_SAVE;
1648 default:
1649 llvm_unreachable("unknown register size");
1650 }
1651}
1652
1653static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1654 switch (Size) {
1655 case 2:
1656 return AMDGPU::SI_SPILL_V16_SAVE;
1657 case 4:
1658 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1659 case 8:
1660 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1661 case 12:
1662 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1663 case 16:
1664 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1665 : AMDGPU::SI_SPILL_V128_SAVE;
1666 case 20:
1667 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1668 : AMDGPU::SI_SPILL_V160_SAVE;
1669 case 24:
1670 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1671 : AMDGPU::SI_SPILL_V192_SAVE;
1672 case 28:
1673 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1674 : AMDGPU::SI_SPILL_V224_SAVE;
1675 case 32:
1676 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1677 : AMDGPU::SI_SPILL_V256_SAVE;
1678 case 36:
1679 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1680 : AMDGPU::SI_SPILL_V288_SAVE;
1681 case 40:
1682 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1683 : AMDGPU::SI_SPILL_V320_SAVE;
1684 case 44:
1685 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1686 : AMDGPU::SI_SPILL_V352_SAVE;
1687 case 48:
1688 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1689 : AMDGPU::SI_SPILL_V384_SAVE;
1690 case 64:
1691 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1692 : AMDGPU::SI_SPILL_V512_SAVE;
1693 case 128:
1694 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1695 : AMDGPU::SI_SPILL_V1024_SAVE;
1696 default:
1697 llvm_unreachable("unknown register size");
1698 }
1699}
1700
1701static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1702 switch (Size) {
1703 case 4:
1704 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1705 : AMDGPU::SI_SPILL_AV32_SAVE;
1706 case 8:
1707 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1708 : AMDGPU::SI_SPILL_AV64_SAVE;
1709 case 12:
1710 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1711 : AMDGPU::SI_SPILL_AV96_SAVE;
1712 case 16:
1713 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1714 : AMDGPU::SI_SPILL_AV128_SAVE;
1715 case 20:
1716 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1717 : AMDGPU::SI_SPILL_AV160_SAVE;
1718 case 24:
1719 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1720 : AMDGPU::SI_SPILL_AV192_SAVE;
1721 case 28:
1722 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1723 : AMDGPU::SI_SPILL_AV224_SAVE;
1724 case 32:
1725 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1726 : AMDGPU::SI_SPILL_AV256_SAVE;
1727 case 36:
1728 return AMDGPU::SI_SPILL_AV288_SAVE;
1729 case 40:
1730 return AMDGPU::SI_SPILL_AV320_SAVE;
1731 case 44:
1732 return AMDGPU::SI_SPILL_AV352_SAVE;
1733 case 48:
1734 return AMDGPU::SI_SPILL_AV384_SAVE;
1735 case 64:
1736 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1737 : AMDGPU::SI_SPILL_AV512_SAVE;
1738 case 128:
1739 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1740 : AMDGPU::SI_SPILL_AV1024_SAVE;
1741 default:
1742 llvm_unreachable("unknown register size");
1743 }
1744}
1745
1746static unsigned getWWMRegSpillSaveOpcode(unsigned Size,
1747 bool IsVectorSuperClass) {
1748 // Currently, there is only 32-bit WWM register spills needed.
1749 if (Size != 4)
1750 llvm_unreachable("unknown wwm register spill size");
1751
1752 if (IsVectorSuperClass)
1753 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1754
1755 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1756}
1757
1759 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1760 const SIMachineFunctionInfo &MFI, bool NeedsCFI) const {
1761 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1762
1763 // Choose the right opcode if spilling a WWM register.
1765 return getWWMRegSpillSaveOpcode(Size, IsVectorSuperClass);
1766
1767 // TODO: Check if AGPRs are available
1768 if (ST.hasMAIInsts())
1769 return getAVSpillSaveOpcode(Size, NeedsCFI);
1770
1771 return getVGPRSpillSaveOpcode(Size, NeedsCFI);
1772}
1773
1774void SIInstrInfo::storeRegToStackSlotImpl(
1776 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1777 MachineInstr::MIFlag Flags, bool NeedsCFI) const {
1778 MachineFunction *MF = MBB.getParent();
1780 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1781 const DebugLoc &DL = MBB.findDebugLoc(MI);
1782
1783 MachinePointerInfo PtrInfo
1784 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1786 PtrInfo, MachineMemOperand::MOStore, FrameInfo.getObjectSize(FrameIndex),
1787 FrameInfo.getObjectAlign(FrameIndex));
1788 unsigned SpillSize = RI.getSpillSize(*RC);
1789
1790 MachineRegisterInfo &MRI = MF->getRegInfo();
1791 if (RI.isSGPRClass(RC)) {
1792 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1793 MFI->setHasSpilledSGPRs();
1794 assert(SrcReg != AMDGPU::M0 && "m0 should not be spilled");
1795 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1796 SrcReg != AMDGPU::EXEC && "exec should not be spilled");
1797
1798 // We are only allowed to create one new instruction when spilling
1799 // registers, so we need to use pseudo instruction for spilling SGPRs.
1800 const MCInstrDesc &OpDesc =
1801 get(getSGPRSpillSaveOpcode(SpillSize, NeedsCFI));
1802
1803 // The SGPR spill/restore instructions only work on number sgprs, so we need
1804 // to make sure we are using the correct register class.
1805 if (SrcReg.isVirtual() && SpillSize == 4) {
1806 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1807 }
1808
1809 BuildMI(MBB, MI, DL, OpDesc)
1810 .addReg(SrcReg, getKillRegState(isKill)) // data
1811 .addFrameIndex(FrameIndex) // addr
1812 .addMemOperand(MMO)
1814
1815 return;
1816 }
1817
1818 unsigned Opcode = getVectorRegSpillSaveOpcode(VReg ? VReg : SrcReg, RC,
1819 SpillSize, *MFI, NeedsCFI);
1820 MFI->setHasSpilledVGPRs();
1821
1822 BuildMI(MBB, MI, DL, get(Opcode))
1823 .addReg(SrcReg, getKillRegState(isKill)) // data
1824 .addFrameIndex(FrameIndex) // addr
1825 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1826 .addImm(0) // offset
1827 .addMemOperand(MMO);
1828}
1829
1832 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1833 MachineInstr::MIFlag Flags) const {
1834 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1835 false);
1836}
1837
1840 Register SrcReg, bool isKill,
1841 int FrameIndex,
1842 const TargetRegisterClass *RC) const {
1843 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, Register(),
1844 MachineInstr::NoFlags, true);
1845}
1846
1847static unsigned getSGPRSpillRestoreOpcode(unsigned Size) {
1848 switch (Size) {
1849 case 4:
1850 return AMDGPU::SI_SPILL_S32_RESTORE;
1851 case 8:
1852 return AMDGPU::SI_SPILL_S64_RESTORE;
1853 case 12:
1854 return AMDGPU::SI_SPILL_S96_RESTORE;
1855 case 16:
1856 return AMDGPU::SI_SPILL_S128_RESTORE;
1857 case 20:
1858 return AMDGPU::SI_SPILL_S160_RESTORE;
1859 case 24:
1860 return AMDGPU::SI_SPILL_S192_RESTORE;
1861 case 28:
1862 return AMDGPU::SI_SPILL_S224_RESTORE;
1863 case 32:
1864 return AMDGPU::SI_SPILL_S256_RESTORE;
1865 case 36:
1866 return AMDGPU::SI_SPILL_S288_RESTORE;
1867 case 40:
1868 return AMDGPU::SI_SPILL_S320_RESTORE;
1869 case 44:
1870 return AMDGPU::SI_SPILL_S352_RESTORE;
1871 case 48:
1872 return AMDGPU::SI_SPILL_S384_RESTORE;
1873 case 64:
1874 return AMDGPU::SI_SPILL_S512_RESTORE;
1875 case 128:
1876 return AMDGPU::SI_SPILL_S1024_RESTORE;
1877 default:
1878 llvm_unreachable("unknown register size");
1879 }
1880}
1881
1882static unsigned getVGPRSpillRestoreOpcode(unsigned Size) {
1883 switch (Size) {
1884 case 2:
1885 return AMDGPU::SI_SPILL_V16_RESTORE;
1886 case 4:
1887 return AMDGPU::SI_SPILL_V32_RESTORE;
1888 case 8:
1889 return AMDGPU::SI_SPILL_V64_RESTORE;
1890 case 12:
1891 return AMDGPU::SI_SPILL_V96_RESTORE;
1892 case 16:
1893 return AMDGPU::SI_SPILL_V128_RESTORE;
1894 case 20:
1895 return AMDGPU::SI_SPILL_V160_RESTORE;
1896 case 24:
1897 return AMDGPU::SI_SPILL_V192_RESTORE;
1898 case 28:
1899 return AMDGPU::SI_SPILL_V224_RESTORE;
1900 case 32:
1901 return AMDGPU::SI_SPILL_V256_RESTORE;
1902 case 36:
1903 return AMDGPU::SI_SPILL_V288_RESTORE;
1904 case 40:
1905 return AMDGPU::SI_SPILL_V320_RESTORE;
1906 case 44:
1907 return AMDGPU::SI_SPILL_V352_RESTORE;
1908 case 48:
1909 return AMDGPU::SI_SPILL_V384_RESTORE;
1910 case 64:
1911 return AMDGPU::SI_SPILL_V512_RESTORE;
1912 case 128:
1913 return AMDGPU::SI_SPILL_V1024_RESTORE;
1914 default:
1915 llvm_unreachable("unknown register size");
1916 }
1917}
1918
1919static unsigned getAVSpillRestoreOpcode(unsigned Size) {
1920 switch (Size) {
1921 case 4:
1922 return AMDGPU::SI_SPILL_AV32_RESTORE;
1923 case 8:
1924 return AMDGPU::SI_SPILL_AV64_RESTORE;
1925 case 12:
1926 return AMDGPU::SI_SPILL_AV96_RESTORE;
1927 case 16:
1928 return AMDGPU::SI_SPILL_AV128_RESTORE;
1929 case 20:
1930 return AMDGPU::SI_SPILL_AV160_RESTORE;
1931 case 24:
1932 return AMDGPU::SI_SPILL_AV192_RESTORE;
1933 case 28:
1934 return AMDGPU::SI_SPILL_AV224_RESTORE;
1935 case 32:
1936 return AMDGPU::SI_SPILL_AV256_RESTORE;
1937 case 36:
1938 return AMDGPU::SI_SPILL_AV288_RESTORE;
1939 case 40:
1940 return AMDGPU::SI_SPILL_AV320_RESTORE;
1941 case 44:
1942 return AMDGPU::SI_SPILL_AV352_RESTORE;
1943 case 48:
1944 return AMDGPU::SI_SPILL_AV384_RESTORE;
1945 case 64:
1946 return AMDGPU::SI_SPILL_AV512_RESTORE;
1947 case 128:
1948 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1949 default:
1950 llvm_unreachable("unknown register size");
1951 }
1952}
1953
1954static unsigned getWWMRegSpillRestoreOpcode(unsigned Size,
1955 bool IsVectorSuperClass) {
1956 // Currently, there is only 32-bit WWM register spills needed.
1957 if (Size != 4)
1958 llvm_unreachable("unknown wwm register spill size");
1959
1960 if (IsVectorSuperClass) // TODO: Always use this if there are AGPRs
1961 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1962
1963 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1964}
1965
1967 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1968 const SIMachineFunctionInfo &MFI) const {
1969 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1970
1971 // Choose the right opcode if restoring a WWM register.
1973 return getWWMRegSpillRestoreOpcode(Size, IsVectorSuperClass);
1974
1975 // TODO: Check if AGPRs are available
1976 if (ST.hasMAIInsts())
1978
1979 assert(!RI.isAGPRClass(RC));
1981}
1982
1985 Register DestReg, int FrameIndex,
1986 const TargetRegisterClass *RC,
1987 Register VReg, unsigned SubReg,
1988 MachineInstr::MIFlag Flags) const {
1989 MachineFunction *MF = MBB.getParent();
1991 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1992 const DebugLoc &DL = MBB.findDebugLoc(MI);
1993 unsigned SpillSize = RI.getSpillSize(*RC);
1994
1995 MachinePointerInfo PtrInfo
1996 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1997
1999 PtrInfo, MachineMemOperand::MOLoad, FrameInfo.getObjectSize(FrameIndex),
2000 FrameInfo.getObjectAlign(FrameIndex));
2001
2002 if (RI.isSGPRClass(RC)) {
2003 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
2004 MFI->setHasSpilledSGPRs();
2005 assert(DestReg != AMDGPU::M0 && "m0 should not be reloaded into");
2006 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
2007 DestReg != AMDGPU::EXEC && "exec should not be spilled");
2008
2009 // FIXME: Maybe this should not include a memoperand because it will be
2010 // lowered to non-memory instructions.
2011 const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize));
2012 if (DestReg.isVirtual() && SpillSize == 4) {
2013 MachineRegisterInfo &MRI = MF->getRegInfo();
2014 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
2015 }
2016
2017 BuildMI(MBB, MI, DL, OpDesc, DestReg)
2018 .addFrameIndex(FrameIndex) // addr
2019 .addMemOperand(MMO)
2021
2022 return;
2023 }
2024
2025 unsigned Opcode = getVectorRegSpillRestoreOpcode(VReg ? VReg : DestReg, RC,
2026 SpillSize, *MFI);
2027 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
2028 .addFrameIndex(FrameIndex) // vaddr
2029 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
2030 .addImm(0) // offset
2031 .addMemOperand(MMO);
2032}
2033
2038
2041 unsigned Quantity) const {
2042 DebugLoc DL = MBB.findDebugLoc(MI);
2043 unsigned MaxSNopCount = 1u << ST.getSNopBits();
2044 while (Quantity > 0) {
2045 unsigned Arg = std::min(Quantity, MaxSNopCount);
2046 Quantity -= Arg;
2047 BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
2048 }
2049}
2050
2054 const DebugLoc &DL) const {
2055 MachineFunction *MF = MBB.getParent();
2056 constexpr unsigned DoorbellIDMask = 0x3ff;
2057 constexpr unsigned ECQueueWaveAbort = 0x400;
2058
2059 MachineBasicBlock *TrapBB = &MBB;
2060 MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock();
2061
2062 if (!MBB.succ_empty() || std::next(MI.getIterator()) != MBB.end()) {
2063 MBB.splitAt(MI, /*UpdateLiveIns=*/false);
2064 TrapBB = MF->CreateMachineBasicBlock();
2065 BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB);
2066 MF->push_back(TrapBB);
2067 MBB.addSuccessor(TrapBB);
2068 }
2069 // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this
2070 // will be a nop.
2071 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP))
2072 .addImm(static_cast<unsigned>(GCNSubtarget::TrapID::LLVMAMDHSATrap));
2073 Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2074 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32),
2075 DoorbellReg)
2077 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2078 .addUse(AMDGPU::M0);
2079 Register DoorbellRegMasked =
2080 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2081 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2082 .addUse(DoorbellReg)
2083 .addImm(DoorbellIDMask)
2084 .setOperandDead(3); // implicit-def $scc
2085 Register SetWaveAbortBit =
2086 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2087 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2088 .addUse(DoorbellRegMasked)
2089 .addImm(ECQueueWaveAbort)
2090 .setOperandDead(3); // implicit-def $scc
2091 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2092 .addUse(SetWaveAbortBit);
2093 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG))
2095 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2096 .addUse(AMDGPU::TTMP2);
2097 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB);
2098 TrapBB->addSuccessor(HaltLoopBB);
2099
2100 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5);
2101 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH))
2102 .addMBB(HaltLoopBB);
2103 MF->push_back(HaltLoopBB);
2104 HaltLoopBB->addSuccessor(HaltLoopBB);
2105
2106 return MBB.getNextNode();
2107}
2108
2110 switch (MI.getOpcode()) {
2111 default:
2112 if (MI.isMetaInstruction())
2113 return 0;
2114 return 1; // FIXME: Do wait states equal cycles?
2115
2116 case AMDGPU::S_NOP:
2117 return MI.getOperand(0).getImm() + 1;
2118 // SI_RETURN_TO_EPILOG is a fallthrough to code outside of the function. The
2119 // hazard, even if one exist, won't really be visible. Should we handle it?
2120 }
2121}
2122
2124 MachineBasicBlock &MBB = *MI.getParent();
2125 DebugLoc DL = MBB.findDebugLoc(MI);
2127
2128 switch (MI.getOpcode()) {
2129 default: return TargetInstrInfo::expandPostRAPseudo(MI);
2130 case AMDGPU::S_MOV_B64_term:
2131 // This is only a terminator to get the correct spill code placement during
2132 // register allocation.
2133 MI.setDesc(get(AMDGPU::S_MOV_B64));
2134 break;
2135
2136 case AMDGPU::S_MOV_B32_term:
2137 // This is only a terminator to get the correct spill code placement during
2138 // register allocation.
2139 MI.setDesc(get(AMDGPU::S_MOV_B32));
2140 break;
2141
2142 case AMDGPU::S_XOR_B64_term:
2143 // This is only a terminator to get the correct spill code placement during
2144 // register allocation.
2145 MI.setDesc(get(AMDGPU::S_XOR_B64));
2146 break;
2147
2148 case AMDGPU::S_XOR_B32_term:
2149 // This is only a terminator to get the correct spill code placement during
2150 // register allocation.
2151 MI.setDesc(get(AMDGPU::S_XOR_B32));
2152 break;
2153 case AMDGPU::S_OR_B64_term:
2154 // This is only a terminator to get the correct spill code placement during
2155 // register allocation.
2156 MI.setDesc(get(AMDGPU::S_OR_B64));
2157 break;
2158 case AMDGPU::S_OR_B32_term:
2159 // This is only a terminator to get the correct spill code placement during
2160 // register allocation.
2161 MI.setDesc(get(AMDGPU::S_OR_B32));
2162 break;
2163
2164 case AMDGPU::S_ANDN2_B64_term:
2165 // This is only a terminator to get the correct spill code placement during
2166 // register allocation.
2167 MI.setDesc(get(AMDGPU::S_ANDN2_B64));
2168 break;
2169
2170 case AMDGPU::S_ANDN2_B32_term:
2171 // This is only a terminator to get the correct spill code placement during
2172 // register allocation.
2173 MI.setDesc(get(AMDGPU::S_ANDN2_B32));
2174 break;
2175
2176 case AMDGPU::S_AND_B64_term:
2177 // This is only a terminator to get the correct spill code placement during
2178 // register allocation.
2179 MI.setDesc(get(AMDGPU::S_AND_B64));
2180 break;
2181
2182 case AMDGPU::S_AND_B32_term:
2183 // This is only a terminator to get the correct spill code placement during
2184 // register allocation.
2185 MI.setDesc(get(AMDGPU::S_AND_B32));
2186 break;
2187
2188 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2189 // This is only a terminator to get the correct spill code placement during
2190 // register allocation.
2191 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B64));
2192 break;
2193
2194 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2195 // This is only a terminator to get the correct spill code placement during
2196 // register allocation.
2197 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B32));
2198 break;
2199
2200 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2201 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2202 break;
2203 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2204 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2205 break;
2206
2207 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2208 MI.setDesc(get(AMDGPU::V_WRITELANE_B32));
2209 break;
2210
2211 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2212 MI.setDesc(get(AMDGPU::V_READLANE_B32));
2213 break;
2214 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2215 Register Dst = MI.getOperand(0).getReg();
2216 bool IsAGPR = SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst));
2217 MI.setDesc(
2218 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2219 break;
2220 }
2221 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2222 Register Dst = MI.getOperand(0).getReg();
2223 if (SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst))) {
2224 int64_t Imm = MI.getOperand(1).getImm();
2225
2226 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2227 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2228 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstLo)
2230 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstHi)
2231 .addImm(SignExtend64<32>(Imm >> 32));
2232 MI.eraseFromParent();
2233 break;
2234 }
2235
2236 [[fallthrough]];
2237 }
2238 case AMDGPU::V_MOV_B64_PSEUDO: {
2239 Register Dst = MI.getOperand(0).getReg();
2240 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2241 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2242
2243 const MCInstrDesc &Mov64Desc = get(AMDGPU::V_MOV_B64_e32);
2244 const TargetRegisterClass *Mov64RC = getRegClass(Mov64Desc, /*OpNum=*/0);
2245
2246 const MachineOperand &SrcOp = MI.getOperand(1);
2247 // FIXME: Will this work for 64-bit floating point immediates?
2248 assert(!SrcOp.isFPImm());
2249 if (ST.hasVMovB64Inst() && Mov64RC->contains(Dst)) {
2250 MI.setDesc(Mov64Desc);
2251 if (SrcOp.isReg() || isInlineConstant(MI, 1) ||
2252 (SrcOp.isImm() &&
2253 (isUInt<32>(SrcOp.getImm()) || ST.has64BitLiterals())) ||
2254 (SrcOp.isGlobal() && ST.has64BitLiterals()))
2255 break;
2256 }
2257 if (SrcOp.isGlobal()) {
2258 // The address is unknown until link time, so the PK_MOV inline-constant
2259 // shortcut cannot apply.
2260 const GlobalValue *GV = SrcOp.getGlobal();
2261 int64_t Offset = SrcOp.getOffset();
2262 unsigned BaseFlags, LoReloc, HiReloc;
2263 std::tie(BaseFlags, LoReloc, HiReloc) =
2265
2266 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2267 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2268 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2269 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2270 } else if (SrcOp.isImm()) {
2271 APInt Imm(64, SrcOp.getImm());
2272 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2273 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2274 const MCInstrDesc &PkMovDesc = get(AMDGPU::V_PK_MOV_B32);
2275 const TargetRegisterClass *PkMovRC = getRegClass(PkMovDesc, /*OpNum=*/0);
2276
2277 if (ST.hasPkMovB32() && Lo == Hi && isInlineConstant(Lo) &&
2278 PkMovRC->contains(Dst)) {
2279 BuildMI(MBB, MI, DL, PkMovDesc, Dst)
2281 .addImm(Lo.getSExtValue())
2283 .addImm(Lo.getSExtValue())
2284 .addImm(0) // op_sel_lo
2285 .addImm(0) // op_sel_hi
2286 .addImm(0) // neg_lo
2287 .addImm(0) // neg_hi
2288 .addImm(0); // clamp
2289 } else {
2290 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2291 .addImm(Lo.getSExtValue());
2292 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2293 .addImm(Hi.getSExtValue());
2294 }
2295 } else {
2296 assert(SrcOp.isReg());
2297 if (ST.hasPkMovB32() &&
2298 !RI.isAGPR(MBB.getParent()->getRegInfo(), SrcOp.getReg())) {
2299 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), Dst)
2300 .addImm(SISrcMods::OP_SEL_1) // src0_mod
2301 .addReg(SrcOp.getReg())
2303 .addReg(SrcOp.getReg())
2304 .addImm(0) // op_sel_lo
2305 .addImm(0) // op_sel_hi
2306 .addImm(0) // neg_lo
2307 .addImm(0) // neg_hi
2308 .addImm(0); // clamp
2309 } else {
2310 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2311 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0));
2312 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2313 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1));
2314 }
2315 }
2316 MI.eraseFromParent();
2317 break;
2318 }
2319 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2321 break;
2322 }
2323 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2324 const MachineOperand &SrcOp = MI.getOperand(1);
2325 assert(!SrcOp.isFPImm());
2326
2327 if (ST.has64BitLiterals()) {
2328 MI.setDesc(get(AMDGPU::S_MOV_B64));
2329 break;
2330 }
2331
2332 if (SrcOp.isGlobal()) {
2333 Register Dst = MI.getOperand(0).getReg();
2334 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2335 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2336 const GlobalValue *GV = SrcOp.getGlobal();
2337 int64_t Offset = SrcOp.getOffset();
2338 unsigned BaseFlags, LoReloc, HiReloc;
2339 std::tie(BaseFlags, LoReloc, HiReloc) =
2341
2342 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2343 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2344 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2345 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2346 MI.eraseFromParent();
2347 break;
2348 }
2349
2350 // SrcOp is immediate
2351 APInt Imm(64, SrcOp.getImm());
2352 if (Imm.isIntN(32) || isInlineConstant(Imm)) {
2353 MI.setDesc(get(AMDGPU::S_MOV_B64));
2354 break;
2355 }
2356
2357 Register Dst = MI.getOperand(0).getReg();
2358 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2359 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2360
2361 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2362 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2363 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2364 .addImm(Lo.getSExtValue());
2365 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2366 .addImm(Hi.getSExtValue());
2367 MI.eraseFromParent();
2368 break;
2369 }
2370 case AMDGPU::V_SET_INACTIVE_B32: {
2371 // Lower V_SET_INACTIVE_B32 to V_CNDMASK_B32.
2372 Register DstReg = MI.getOperand(0).getReg();
2373 BuildMI(MBB, MI, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2374 .add(MI.getOperand(3))
2375 .add(MI.getOperand(4))
2376 .add(MI.getOperand(1))
2377 .add(MI.getOperand(2))
2378 .add(MI.getOperand(5));
2379 MI.eraseFromParent();
2380 break;
2381 }
2382 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2383 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2384 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2385 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2386 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2387 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2388 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2389 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2390 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2391 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2392 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2393 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2394 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2395 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2396 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2397 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2398 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2399 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2400 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2401 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2402 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2403 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2404 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2405 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2406 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2407 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2408 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2409 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2410 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2411 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2412 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2413 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2414 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2415 const TargetRegisterClass *EltRC = getOpRegClass(MI, 2);
2416
2417 unsigned Opc;
2418 if (RI.hasVGPRs(EltRC)) {
2419 Opc = AMDGPU::V_MOVRELD_B32_e32;
2420 } else {
2421 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2422 : AMDGPU::S_MOVRELD_B32;
2423 }
2424
2425 const MCInstrDesc &OpDesc = get(Opc);
2426 Register VecReg = MI.getOperand(0).getReg();
2427 bool IsUndef = MI.getOperand(1).isUndef();
2428 unsigned SubReg = MI.getOperand(3).getImm();
2429 assert(VecReg == MI.getOperand(1).getReg());
2430
2432 BuildMI(MBB, MI, DL, OpDesc)
2433 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2434 .add(MI.getOperand(2))
2436 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2437
2438 const int ImpDefIdx =
2439 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2440 const int ImpUseIdx = ImpDefIdx + 1;
2441 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2442 MI.eraseFromParent();
2443 break;
2444 }
2445 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2446 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2447 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2448 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2449 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2450 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2451 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2452 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2453 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2454 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2455 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2456 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2457 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2458 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2459 assert(ST.useVGPRIndexMode());
2460 Register VecReg = MI.getOperand(0).getReg();
2461 bool IsUndef = MI.getOperand(1).isUndef();
2462 MachineOperand &Idx = MI.getOperand(3);
2463 Register SubReg = MI.getOperand(4).getImm();
2464
2465 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2466 .add(Idx)
2468 SetOn->getOperand(3).setIsUndef();
2469
2470 const MCInstrDesc &OpDesc = get(AMDGPU::V_MOV_B32_indirect_write);
2472 BuildMI(MBB, MI, DL, OpDesc)
2473 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2474 .add(MI.getOperand(2))
2476 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2477
2478 const int ImpDefIdx =
2479 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2480 const int ImpUseIdx = ImpDefIdx + 1;
2481 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2482
2483 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2484
2485 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2486
2487 MI.eraseFromParent();
2488 break;
2489 }
2490 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2491 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2492 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2493 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2494 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2495 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2496 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2497 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2498 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2499 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2500 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2501 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2502 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2503 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2504 assert(ST.useVGPRIndexMode());
2505 Register Dst = MI.getOperand(0).getReg();
2506 Register VecReg = MI.getOperand(1).getReg();
2507 bool IsUndef = MI.getOperand(1).isUndef();
2508 Register SubReg = MI.getOperand(3).getImm();
2509
2510 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2511 .add(MI.getOperand(2))
2513 SetOn->getOperand(3).setIsUndef();
2514
2515 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_indirect_read))
2516 .addDef(Dst)
2517 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2518 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2519
2520 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2521
2522 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2523
2524 MI.eraseFromParent();
2525 break;
2526 }
2527 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2528 MachineFunction &MF = *MBB.getParent();
2529 Register Reg = MI.getOperand(0).getReg();
2530 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2531 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2532 MachineOperand OpLo = MI.getOperand(1);
2533 MachineOperand OpHi = MI.getOperand(2);
2534
2535 // Create a bundle so these instructions won't be re-ordered by the
2536 // post-RA scheduler.
2537 MIBundleBuilder Bundler(MBB, MI);
2538 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2539
2540 // What we want here is an offset from the value returned by s_getpc (which
2541 // is the address of the s_add_u32 instruction) to the global variable, but
2542 // since the encoding of $symbol starts 4 bytes after the start of the
2543 // s_add_u32 instruction, we end up with an offset that is 4 bytes too
2544 // small. This requires us to add 4 to the global variable offset in order
2545 // to compute the correct address. Similarly for the s_addc_u32 instruction,
2546 // the encoding of $symbol starts 12 bytes after the start of the s_add_u32
2547 // instruction.
2548
2549 int64_t Adjust = 0;
2550 if (ST.hasGetPCZeroExtension()) {
2551 // Fix up hardware that does not sign-extend the 48-bit PC value by
2552 // inserting: s_sext_i32_i16 reghi, reghi
2553 Bundler.append(
2554 BuildMI(MF, DL, get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2555 Adjust += 4;
2556 }
2557
2558 if (OpLo.isGlobal())
2559 OpLo.setOffset(OpLo.getOffset() + Adjust + 4);
2560 Bundler.append(
2561 BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2562
2563 if (OpHi.isGlobal())
2564 OpHi.setOffset(OpHi.getOffset() + Adjust + 12);
2565 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi)
2566 .addReg(RegHi)
2567 .add(OpHi));
2568
2569 finalizeBundle(MBB, Bundler.begin());
2570
2571 MI.eraseFromParent();
2572 break;
2573 }
2574 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2575 MachineFunction &MF = *MBB.getParent();
2576 Register Reg = MI.getOperand(0).getReg();
2577 MachineOperand Op = MI.getOperand(1);
2578
2579 // Create a bundle so these instructions won't be re-ordered by the
2580 // post-RA scheduler.
2581 MIBundleBuilder Bundler(MBB, MI);
2582 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2583 if (Op.isGlobal())
2584 Op.setOffset(Op.getOffset() + 4);
2585 Bundler.append(
2586 BuildMI(MF, DL, get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(Op));
2587
2588 finalizeBundle(MBB, Bundler.begin());
2589
2590 MI.eraseFromParent();
2591 break;
2592 }
2593 case AMDGPU::ENTER_STRICT_WWM: {
2594 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2595 // Whole Wave Mode is entered.
2596 MI.setDesc(get(LMC.OrSaveExecOpc));
2597 break;
2598 }
2599 case AMDGPU::ENTER_STRICT_WQM: {
2600 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2601 // STRICT_WQM is entered.
2602 BuildMI(MBB, MI, DL, get(LMC.MovOpc), MI.getOperand(0).getReg())
2603 .addReg(LMC.ExecReg);
2604 BuildMI(MBB, MI, DL, get(LMC.WQMOpc), LMC.ExecReg).addReg(LMC.ExecReg);
2605
2606 MI.eraseFromParent();
2607 break;
2608 }
2609 case AMDGPU::EXIT_STRICT_WWM:
2610 case AMDGPU::EXIT_STRICT_WQM: {
2611 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2612 // WWM/STICT_WQM is exited.
2613 MI.setDesc(get(LMC.MovOpc));
2614 break;
2615 }
2616 case AMDGPU::SI_RETURN: {
2617 const MachineFunction *MF = MBB.getParent();
2618 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2619 const SIRegisterInfo *TRI = ST.getRegisterInfo();
2620 // Hiding the return address use with SI_RETURN may lead to extra kills in
2621 // the function and missing live-ins. We are fine in practice because callee
2622 // saved register handling ensures the register value is restored before
2623 // RET, but we need the undef flag here to appease the MachineVerifier
2624 // liveness checks.
2626 BuildMI(MBB, MI, DL, get(AMDGPU::S_SETPC_B64_return))
2627 .addReg(TRI->getReturnAddressReg(*MF), RegState::Undef);
2628
2629 MIB.copyImplicitOps(MI);
2630 MI.eraseFromParent();
2631 break;
2632 }
2633
2634 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2635 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2636 MI.setDesc(get(AMDGPU::S_MUL_U64));
2637 break;
2638
2639 case AMDGPU::S_GETPC_B64_pseudo:
2640 MI.setDesc(get(AMDGPU::S_GETPC_B64));
2641 if (ST.hasGetPCZeroExtension()) {
2642 Register Dst = MI.getOperand(0).getReg();
2643 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2644 // Fix up hardware that does not sign-extend the 48-bit PC value by
2645 // inserting: s_sext_i32_i16 dsthi, dsthi
2646 BuildMI(MBB, std::next(MI.getIterator()), DL, get(AMDGPU::S_SEXT_I32_I16),
2647 DstHi)
2648 .addReg(DstHi);
2649 }
2650 break;
2651
2652 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2653 assert(ST.hasBF16PackedInsts());
2654 MI.setDesc(get(AMDGPU::V_PK_MAX_NUM_BF16));
2655 MI.addOperand(MachineOperand::CreateImm(0)); // op_sel
2656 MI.addOperand(MachineOperand::CreateImm(0)); // neg_lo
2657 MI.addOperand(MachineOperand::CreateImm(0)); // neg_hi
2658 auto Op0 = getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
2659 Op0->setImm(Op0->getImm() | SISrcMods::OP_SEL_1);
2660 auto Op1 = getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
2661 Op1->setImm(Op1->getImm() | SISrcMods::OP_SEL_1);
2662 break;
2663 }
2664
2665 case AMDGPU::GET_STACK_BASE:
2666 // The stack starts at offset 0 unless we need to reserve some space at the
2667 // bottom.
2668 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*MBB.getParent())) {
2669 // When CWSR is used in dynamic VGPR mode, the trap handler needs to save
2670 // some of the VGPRs. The size of the required scratch space has already
2671 // been computed by prolog epilog insertion.
2672 const SIMachineFunctionInfo *MFI =
2673 MBB.getParent()->getInfo<SIMachineFunctionInfo>();
2674 unsigned VGPRSize = MFI->getScratchReservedForDynamicVGPRs();
2675 Register DestReg = MI.getOperand(0).getReg();
2676 BuildMI(MBB, MI, DL, get(AMDGPU::S_GETREG_B32), DestReg)
2679 // The MicroEngine ID is 0 for the graphics queue, and 1 or 2 for compute
2680 // (3 is unused, so we ignore it). Unfortunately, S_GETREG doesn't set
2681 // SCC, so we need to check for 0 manually.
2682 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)).addImm(0).addReg(DestReg);
2683 // Change the implicif-def of SCC to an explicit use (but first remove
2684 // the dead flag if present).
2685 MI.getOperand(MI.getNumExplicitOperands()).setIsDead(false);
2686 MI.getOperand(MI.getNumExplicitOperands()).setIsUse();
2687 MI.setDesc(get(AMDGPU::S_CMOVK_I32));
2688 MI.addOperand(MachineOperand::CreateImm(VGPRSize));
2689 } else {
2690 MI.setDesc(get(AMDGPU::S_MOV_B32));
2691 MI.addOperand(MachineOperand::CreateImm(0));
2692 MI.removeOperand(
2693 MI.getNumExplicitOperands()); // Drop implicit def of SCC.
2694 }
2695 break;
2696 }
2697
2698 return true;
2699}
2700
2703 unsigned SubIdx, const MachineInstr &Orig,
2704 LaneBitmask UsedLanes) const {
2705
2706 // Try shrinking the instruction to remat only the part needed for current
2707 // context.
2708 // TODO: Handle more cases.
2709 unsigned Opcode = Orig.getOpcode();
2710 switch (Opcode) {
2711 case AMDGPU::S_MOV_B64:
2712 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2713 if (SubIdx != 0)
2714 break;
2715
2716 if (!Orig.getOperand(1).isImm())
2717 break;
2718
2719 // Shrink S_MOV_B64 to S_MOV_B32 when UsedLanes indicates only a single
2720 // 32-bit lane of the 64-bit value is live at the rematerialization point.
2721 if (UsedLanes.all())
2722 break;
2723
2724 // Determine which half of the 64-bit immediate corresponds to the use.
2725 unsigned OrigSubReg = Orig.getOperand(0).getSubReg();
2726 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2727 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2728
2729 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2730 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2731
2732 if (NeedLo && NeedHi)
2733 break;
2734
2735 int64_t Imm64 = Orig.getOperand(1).getImm();
2736 int32_t Imm32 = NeedLo ? Lo_32(Imm64) : Hi_32(Imm64);
2737
2738 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2739
2740 // Emit S_MOV_B32 defining just the needed 32-bit subreg of DestReg.
2741 BuildMI(MBB, I, Orig.getDebugLoc(), get(AMDGPU::S_MOV_B32))
2742 .addReg(DestReg, RegState::Define | RegState::Undef, UseSubReg)
2743 .addImm(Imm32);
2744 return;
2745 }
2746
2747 case AMDGPU::S_LOAD_DWORDX16_IMM:
2748 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2749 if (SubIdx != 0)
2750 break;
2751
2752 if (I == MBB.end())
2753 break;
2754
2755 if (I->isBundled())
2756 break;
2757
2758 // Look for a single use of the register that is also a subreg.
2759 Register RegToFind = Orig.getOperand(0).getReg();
2760 MachineOperand *UseMO = nullptr;
2761 for (auto &CandMO : I->operands()) {
2762 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2763 continue;
2764 if (UseMO) {
2765 UseMO = nullptr;
2766 break;
2767 }
2768 UseMO = &CandMO;
2769 }
2770 if (!UseMO || UseMO->getSubReg() == AMDGPU::NoSubRegister)
2771 break;
2772
2773 unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
2774 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());
2775
2776 MachineFunction *MF = MBB.getParent();
2777 MachineRegisterInfo &MRI = MF->getRegInfo();
2778 assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");
2779
2780 unsigned NewOpcode = -1;
2781 if (SubregSize == 256)
2782 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2783 else if (SubregSize == 128)
2784 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2785 else
2786 break;
2787
2788 const MCInstrDesc &TID = get(NewOpcode);
2789 const TargetRegisterClass *NewRC =
2790 RI.getAllocatableClass(getRegClass(TID, 0));
2791 MRI.setRegClass(DestReg, NewRC);
2792
2793 UseMO->setReg(DestReg);
2794 UseMO->setSubReg(AMDGPU::NoSubRegister);
2795
2796 // Use a smaller load with the desired size, possibly with updated offset.
2797 MachineInstr *MI = MF->CloneMachineInstr(&Orig);
2798 MI->setDesc(TID);
2799 MI->getOperand(0).setReg(DestReg);
2800 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2801 if (Offset) {
2802 MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
2803 int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
2804 OffsetMO->setImm(FinalOffset);
2805 }
2807 for (const MachineMemOperand *MemOp : Orig.memoperands())
2808 NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
2809 SubregSize / 8));
2810 MI->setMemRefs(*MF, NewMMOs);
2811
2812 MBB.insert(I, MI);
2813 return;
2814 }
2815
2816 default:
2817 break;
2818 }
2819
2820 TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
2821}
2822
2823std::pair<MachineInstr*, MachineInstr*>
2825 assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2826
2827 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2829 ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
2830 MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
2831 return std::pair(&MI, nullptr);
2832 }
2833
2834 MachineBasicBlock &MBB = *MI.getParent();
2835 DebugLoc DL = MBB.findDebugLoc(MI);
2836 MachineFunction *MF = MBB.getParent();
2837 MachineRegisterInfo &MRI = MF->getRegInfo();
2838 Register Dst = MI.getOperand(0).getReg();
2839 unsigned Part = 0;
2840 MachineInstr *Split[2];
2841
2842 for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2843 auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
2844 if (Dst.isPhysical()) {
2845 MovDPP.addDef(RI.getSubReg(Dst, Sub));
2846 } else {
2847 assert(MRI.isSSA());
2848 auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2849 MovDPP.addDef(Tmp);
2850 }
2851
2852 for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
2853 const MachineOperand &SrcOp = MI.getOperand(I);
2854 assert(!SrcOp.isFPImm());
2855 if (SrcOp.isImm()) {
2856 APInt Imm(64, SrcOp.getImm());
2857 Imm.ashrInPlace(Part * 32);
2858 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2859 } else {
2860 assert(SrcOp.isReg());
2861 Register Src = SrcOp.getReg();
2862 if (Src.isPhysical())
2863 MovDPP.addReg(RI.getSubReg(Src, Sub));
2864 else
2865 MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
2866 }
2867 }
2868
2869 for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
2870 MovDPP.addImm(MO.getImm());
2871
2872 Split[Part] = MovDPP;
2873 ++Part;
2874 }
2875
2876 if (Dst.isVirtual())
2877 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
2878 .addReg(Split[0]->getOperand(0).getReg())
2879 .addImm(AMDGPU::sub0)
2880 .addReg(Split[1]->getOperand(0).getReg())
2881 .addImm(AMDGPU::sub1);
2882
2883 MI.eraseFromParent();
2884 return std::pair(Split[0], Split[1]);
2885}
2886
2887std::optional<DestSourcePair>
2889 if (MI.getOpcode() == AMDGPU::WWM_COPY)
2890 return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
2891
2892 return std::nullopt;
2893}
2894
2896 AMDGPU::OpName Src0OpName,
2897 MachineOperand &Src1,
2898 AMDGPU::OpName Src1OpName) const {
2899 MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
2900 if (!Src0Mods)
2901 return false;
2902
2903 MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
2904 assert(Src1Mods &&
2905 "All commutable instructions have both src0 and src1 modifiers");
2906
2907 int Src0ModsVal = Src0Mods->getImm();
2908 int Src1ModsVal = Src1Mods->getImm();
2909
2910 Src1Mods->setImm(Src0ModsVal);
2911 Src0Mods->setImm(Src1ModsVal);
2912 return true;
2913}
2914
2916 MachineOperand &RegOp,
2917 MachineOperand &NonRegOp) {
2918 Register Reg = RegOp.getReg();
2919 unsigned SubReg = RegOp.getSubReg();
2920 bool IsKill = RegOp.isKill();
2921 bool IsDead = RegOp.isDead();
2922 bool IsUndef = RegOp.isUndef();
2923 bool IsDebug = RegOp.isDebug();
2924
2925 if (NonRegOp.isImm())
2926 RegOp.ChangeToImmediate(NonRegOp.getImm());
2927 else if (NonRegOp.isFI())
2928 RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
2929 else if (NonRegOp.isGlobal()) {
2930 RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
2931 NonRegOp.getTargetFlags());
2932 } else
2933 return nullptr;
2934
2935 // Make sure we don't reinterpret a subreg index in the target flags.
2936 RegOp.setTargetFlags(NonRegOp.getTargetFlags());
2937
2938 NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
2939 NonRegOp.setSubReg(SubReg);
2940
2941 return &MI;
2942}
2943
2945 MachineOperand &NonRegOp1,
2946 MachineOperand &NonRegOp2) {
2947 unsigned TargetFlags = NonRegOp1.getTargetFlags();
2948 int64_t NonRegVal = NonRegOp1.getImm();
2949
2950 NonRegOp1.setImm(NonRegOp2.getImm());
2951 NonRegOp2.setImm(NonRegVal);
2952 NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
2953 NonRegOp2.setTargetFlags(TargetFlags);
2954 return &MI;
2955}
2956
2957bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
2958 unsigned OpIdx1) const {
2959 const MCInstrDesc &InstDesc = MI.getDesc();
2960 const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
2961 const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];
2962
2963 unsigned Opc = MI.getOpcode();
2964 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2965
2966 const MachineOperand &MO0 = MI.getOperand(OpIdx0);
2967 const MachineOperand &MO1 = MI.getOperand(OpIdx1);
2968
2969 // Swap doesn't breach constant bus or literal limits, but it may move a
2970 // constant out of src0. Allow that for immediates where the destination
2971 // operand can hold them, e.g. VOP3 sources on targets with VOP3 literal
2972 // support. Other non-register operands stay in src0.
2973 if (isVALU(MI, /*AllowLDSDMA=*/false)) {
2974 if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
2975 (!MO0.isImm() || !isImmOperandLegal(MI, OpIdx1, MO0)))
2976 return false;
2977 if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
2978 (!MO1.isImm() || !isImmOperandLegal(MI, OpIdx0, MO1)))
2979 return false;
2980 }
2981
2982 if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
2983 if (OpInfo1.RegClass == -1)
2984 return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
2985 return isLegalRegOperand(MI, OpIdx1, MO0) &&
2986 (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
2987 }
2988 if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
2989 if (OpInfo0.RegClass == -1)
2990 return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
2991 return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
2992 isLegalRegOperand(MI, OpIdx0, MO1);
2993 }
2994
2995 // No need to check 64-bit literals since swapping does not bring new
2996 // 64-bit literals into current instruction to fold to 32-bit
2997
2998 return isImmOperandLegal(MI, OpIdx1, MO0);
2999}
3000
3002 if (!isDPP(MI))
3003 return false;
3004 const MachineOperand *DppCtrl = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
3005 return !DppCtrl || DppCtrl->getImm() != AMDGPU::DPP::QUAD_PERM_ID;
3006}
3007
3009 unsigned Src0Idx,
3010 unsigned Src1Idx) const {
3011 assert(!NewMI && "this should never be used");
3012
3014 return nullptr;
3015
3016 unsigned Opc = MI.getOpcode();
3017 int CommutedOpcode = commuteOpcode(Opc);
3018 if (CommutedOpcode == -1)
3019 return nullptr;
3020
3021 if (Src0Idx > Src1Idx)
3022 std::swap(Src0Idx, Src1Idx);
3023
3024 assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
3025 static_cast<int>(Src0Idx) &&
3026 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
3027 static_cast<int>(Src1Idx) &&
3028 "inconsistency with findCommutedOpIndices");
3029
3030 if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
3031 return nullptr;
3032
3033 MachineInstr *CommutedMI = nullptr;
3034 MachineOperand &Src0 = MI.getOperand(Src0Idx);
3035 MachineOperand &Src1 = MI.getOperand(Src1Idx);
3036 if (Src0.isReg() && Src1.isReg()) {
3037 // Be sure to copy the source modifiers to the right place.
3038 CommutedMI =
3039 TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
3040 } else if (Src0.isReg() && !Src1.isReg()) {
3041 CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
3042 } else if (!Src0.isReg() && Src1.isReg()) {
3043 CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
3044 } else if (Src0.isImm() && Src1.isImm()) {
3045 CommutedMI = swapImmOperands(MI, Src0, Src1);
3046 } else {
3047 // FIXME: Found two non registers to commute. This does happen.
3048 return nullptr;
3049 }
3050
3051 if (CommutedMI) {
3052 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
3053 Src1, AMDGPU::OpName::src1_modifiers);
3054
3055 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
3056 AMDGPU::OpName::src1_sel);
3057
3058 CommutedMI->setDesc(get(CommutedOpcode));
3059 }
3060
3061 return CommutedMI;
3062}
3063
3064// This needs to be implemented because the source modifiers may be inserted
3065// between the true commutable operands, and the base
3066// TargetInstrInfo::commuteInstruction uses it.
3068 unsigned &SrcOpIdx0,
3069 unsigned &SrcOpIdx1) const {
3071 return false;
3072
3073 return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
3074}
3075
3077 unsigned &SrcOpIdx0,
3078 unsigned &SrcOpIdx1) const {
3079 if (!Desc.isCommutable())
3080 return false;
3081
3082 unsigned Opc = Desc.getOpcode();
3083 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
3084 if (Src0Idx == -1)
3085 return false;
3086
3087 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
3088 if (Src1Idx == -1)
3089 return false;
3090
3091 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3092}
3093
3095 int64_t BrOffset) const {
3096 // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
3097 // because its dest block is unanalyzable.
3098 assert(isSOPP(BranchOp) || isSOPK(BranchOp));
3099
3100 // Convert to dwords.
3101 BrOffset /= 4;
3102
3103 // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
3104 // from the next instruction.
3105 BrOffset -= 1;
3106
3107 return isIntN(BranchOffsetBits, BrOffset);
3108}
3109
3112 return MI.getOperand(0).getMBB();
3113}
3114
3116 for (const MachineInstr &MI : MBB->terminators()) {
3117 if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
3118 MI.getOpcode() == AMDGPU::SI_LOOP ||
3119 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3120 return true;
3121 }
3122 return false;
3123}
3124
3126 MachineBasicBlock &DestBB,
3127 MachineBasicBlock &RestoreBB,
3128 const DebugLoc &DL, int64_t BrOffset,
3129 RegScavenger *RS) const {
3130 assert(MBB.empty() &&
3131 "new block should be inserted for expanding unconditional branch");
3132 assert(MBB.pred_size() == 1);
3133 assert(RestoreBB.empty() &&
3134 "restore block should be inserted for restoring clobbered registers");
3135
3136 MachineFunction *MF = MBB.getParent();
3137 MachineRegisterInfo &MRI = MF->getRegInfo();
3139 auto I = MBB.end();
3140 auto &MCCtx = MF->getContext();
3141
3142 if (ST.useAddPC64Inst()) {
3143 MCSymbol *Offset =
3144 MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
3145 auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
3147 MCSymbol *PostAddPCLabel =
3148 MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
3149 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3150 auto *OffsetExpr = MCBinaryExpr::createSub(
3151 MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
3152 MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
3153 Offset->setVariableValue(OffsetExpr);
3154 return;
3155 }
3156
3157 assert(RS && "RegScavenger required for long branching");
3158
3159 // FIXME: Virtual register workaround for RegScavenger not working with empty
3160 // blocks.
3161 Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3162
3163 // Note: as this is used after hazard recognizer we need to apply some hazard
3164 // workarounds directly.
3165 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3166 ST.hasVALUReadSGPRHazard();
3167 auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
3168 if (FlushSGPRWrites)
3169 BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
3171 };
3172
3173 // We need to compute the offset relative to the instruction immediately after
3174 // s_getpc_b64. Insert pc arithmetic code before last terminator.
3175 MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
3176 ApplyHazardWorkarounds();
3177
3178 MCSymbol *PostGetPCLabel =
3179 MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
3180 GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);
3181
3182 MCSymbol *OffsetLo =
3183 MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
3184 MCSymbol *OffsetHi =
3185 MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
3186 BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
3187 .addReg(PCReg, RegState::Define, AMDGPU::sub0)
3188 .addReg(PCReg, {}, AMDGPU::sub0)
3189 .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
3190 BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
3191 .addReg(PCReg, RegState::Define, AMDGPU::sub1)
3192 .addReg(PCReg, {}, AMDGPU::sub1)
3193 .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
3194 ApplyHazardWorkarounds();
3195
3196 // Insert the indirect branch after the other terminator.
3197 BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
3198 .addReg(PCReg);
3199
3200 // If a spill is needed for the pc register pair, we need to insert a spill
3201 // restore block right before the destination block, and insert a short branch
3202 // into the old destination block's fallthrough predecessor.
3203 // e.g.:
3204 //
3205 // s_cbranch_scc0 skip_long_branch:
3206 //
3207 // long_branch_bb:
3208 // spill s[8:9]
3209 // s_getpc_b64 s[8:9]
3210 // s_add_u32 s8, s8, restore_bb
3211 // s_addc_u32 s9, s9, 0
3212 // s_setpc_b64 s[8:9]
3213 //
3214 // skip_long_branch:
3215 // foo;
3216 //
3217 // .....
3218 //
3219 // dest_bb_fallthrough_predecessor:
3220 // bar;
3221 // s_branch dest_bb
3222 //
3223 // restore_bb:
3224 // restore s[8:9]
3225 // fallthrough dest_bb
3226 ///
3227 // dest_bb:
3228 // buzz;
3229
3230 Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
3231 Register Scav;
3232
3233 // If we've previously reserved a register for long branches
3234 // avoid running the scavenger and just use those registers
3235 if (LongBranchReservedReg) {
3236 RS->enterBasicBlock(MBB);
3237 Scav = LongBranchReservedReg;
3238 } else {
3239 RS->enterBasicBlockEnd(MBB);
3240 Scav = RS->scavengeRegisterBackwards(
3241 AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
3242 /* RestoreAfter */ false, 0, /* AllowSpill */ false);
3243 }
3244 if (Scav) {
3245 RS->setRegUsed(Scav);
3246 MRI.replaceRegWith(PCReg, Scav);
3247 MRI.clearVirtRegs();
3248 } else {
3249 // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
3250 // SGPR spill.
3251 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
3252 const SIRegisterInfo *TRI = ST.getRegisterInfo();
3253 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3254 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3255 MRI.clearVirtRegs();
3256 }
3257
3258 MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
3259 // Now, the distance could be defined.
3261 MCSymbolRefExpr::create(DestLabel, MCCtx),
3262 MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
3263 // Add offset assignments.
3264 auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
3265 OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
3266 auto *ShAmt = MCConstantExpr::create(32, MCCtx);
3267 OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
3268}
3269
3270unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
3271 switch (Cond) {
3272 case SIInstrInfo::SCC_TRUE:
3273 return AMDGPU::S_CBRANCH_SCC1;
3274 case SIInstrInfo::SCC_FALSE:
3275 return AMDGPU::S_CBRANCH_SCC0;
3276 case SIInstrInfo::VCCNZ:
3277 return AMDGPU::S_CBRANCH_VCCNZ;
3278 case SIInstrInfo::VCCZ:
3279 return AMDGPU::S_CBRANCH_VCCZ;
3280 case SIInstrInfo::EXECNZ:
3281 return AMDGPU::S_CBRANCH_EXECNZ;
3282 case SIInstrInfo::EXECZ:
3283 return AMDGPU::S_CBRANCH_EXECZ;
3284 default:
3285 llvm_unreachable("invalid branch predicate");
3286 }
3287}
3288
3289SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
3290 switch (Opcode) {
3291 case AMDGPU::S_CBRANCH_SCC0:
3292 return SCC_FALSE;
3293 case AMDGPU::S_CBRANCH_SCC1:
3294 return SCC_TRUE;
3295 case AMDGPU::S_CBRANCH_VCCNZ:
3296 return VCCNZ;
3297 case AMDGPU::S_CBRANCH_VCCZ:
3298 return VCCZ;
3299 case AMDGPU::S_CBRANCH_EXECNZ:
3300 return EXECNZ;
3301 case AMDGPU::S_CBRANCH_EXECZ:
3302 return EXECZ;
3303 default:
3304 return INVALID_BR;
3305 }
3306}
3307
3311 MachineBasicBlock *&FBB,
3313 bool AllowModify) const {
3314 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3315 // Unconditional Branch
3316 TBB = I->getOperand(0).getMBB();
3317 return false;
3318 }
3319
3320 BranchPredicate Pred = getBranchPredicate(I->getOpcode());
3321 if (Pred == INVALID_BR)
3322 return true;
3323
3324 MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
3325 Cond.push_back(MachineOperand::CreateImm(Pred));
3326 Cond.push_back(I->getOperand(1)); // Save the branch register.
3327
3328 ++I;
3329
3330 if (I == MBB.end()) {
3331 // Conditional branch followed by fall-through.
3332 TBB = CondBB;
3333 return false;
3334 }
3335
3336 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3337 TBB = CondBB;
3338 FBB = I->getOperand(0).getMBB();
3339 return false;
3340 }
3341
3342 return true;
3343}
3344
3346 MachineBasicBlock *&FBB,
3348 bool AllowModify) const {
3349 MachineBasicBlock::iterator I = MBB.getFirstTerminator();
3350 auto E = MBB.end();
3351 if (I == E)
3352 return false;
3353
3354 // Skip over the instructions that are artificially terminators for special
3355 // exec management.
3356 while (I != E && !I->isBranch() && !I->isReturn()) {
3357 switch (I->getOpcode()) {
3358 case AMDGPU::S_MOV_B64_term:
3359 case AMDGPU::S_XOR_B64_term:
3360 case AMDGPU::S_OR_B64_term:
3361 case AMDGPU::S_ANDN2_B64_term:
3362 case AMDGPU::S_AND_B64_term:
3363 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3364 case AMDGPU::S_MOV_B32_term:
3365 case AMDGPU::S_XOR_B32_term:
3366 case AMDGPU::S_OR_B32_term:
3367 case AMDGPU::S_ANDN2_B32_term:
3368 case AMDGPU::S_AND_B32_term:
3369 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3370 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3371 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3372 break;
3373 case AMDGPU::SI_IF:
3374 case AMDGPU::SI_ELSE:
3375 case AMDGPU::SI_KILL_I1_TERMINATOR:
3376 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3377 // FIXME: It's messy that these need to be considered here at all.
3378 return true;
3379 default:
3380 llvm_unreachable("unexpected non-branch terminator inst");
3381 }
3382
3383 ++I;
3384 }
3385
3386 if (I == E)
3387 return false;
3388
3389 return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
3390}
3391
3393 int *BytesRemoved) const {
3394 unsigned Count = 0;
3395 unsigned RemovedSize = 0;
3396 for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
3397 // Skip over artificial terminators when removing instructions.
3398 if (MI.isBranch() || MI.isReturn()) {
3399 RemovedSize += getInstSizeInBytes(MI);
3400 MI.eraseFromParent();
3401 ++Count;
3402 }
3403 }
3404
3405 if (BytesRemoved)
3406 *BytesRemoved = RemovedSize;
3407
3408 return Count;
3409}
3410
3411// Copy the flags onto the implicit condition register operand.
3413 const MachineOperand &OrigCond) {
3414 CondReg.setIsUndef(OrigCond.isUndef());
3415 CondReg.setIsKill(OrigCond.isKill());
3416}
3417
3420 MachineBasicBlock *FBB,
3422 const DebugLoc &DL,
3423 int *BytesAdded) const {
3424 if (!FBB && Cond.empty()) {
3425 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3426 .addMBB(TBB);
3427 if (BytesAdded)
3428 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3429 return 1;
3430 }
3431
3432 assert(TBB && Cond[0].isImm());
3433
3434 unsigned Opcode
3435 = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));
3436
3437 if (!FBB) {
3438 MachineInstr *CondBr =
3439 BuildMI(&MBB, DL, get(Opcode))
3440 .addMBB(TBB);
3441
3442 // Copy the flags onto the implicit condition register operand.
3443 preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
3444 fixImplicitOperands(*CondBr);
3445
3446 if (BytesAdded)
3447 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3448 return 1;
3449 }
3450
3451 assert(TBB && FBB);
3452
3453 MachineInstr *CondBr =
3454 BuildMI(&MBB, DL, get(Opcode))
3455 .addMBB(TBB);
3456 fixImplicitOperands(*CondBr);
3457 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3458 .addMBB(FBB);
3459
3460 MachineOperand &CondReg = CondBr->getOperand(1);
3461 CondReg.setIsUndef(Cond[1].isUndef());
3462 CondReg.setIsKill(Cond[1].isKill());
3463
3464 if (BytesAdded)
3465 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3466
3467 return 2;
3468}
3469
3472 if (Cond.size() != 2) {
3473 return true;
3474 }
3475
3476 if (Cond[0].isImm()) {
3477 Cond[0].setImm(-Cond[0].getImm());
3478 return false;
3479 }
3480
3481 return true;
3482}
3483
3484namespace {
3485class AMDGPUPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
3486private:
3487 /// The compare instruction for loop control
3488 const MachineInstr *CmpInst = nullptr;
3489 /// The normalized condition used by createTripCountGreaterCondition()
3491
3492public:
3493 AMDGPUPipelinerLoopInfo(MachineInstr *CmpInst,
3495 : CmpInst(CmpInst), Cond(Cond.begin(), Cond.end()) {}
3496
3497 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
3498 return CmpInst && MI == CmpInst;
3499 }
3500
3501 std::optional<bool> createTripCountGreaterCondition(
3502 int TC, MachineBasicBlock &MBB,
3503 SmallVectorImpl<MachineOperand> &CondParam) override {
3504 CondParam = this->Cond;
3505 return {};
3506 }
3507
3508 void adjustTripCount(int TripCountAdjust) override {}
3509
3510 void setPreheader(MachineBasicBlock *NewPreheader) override {}
3511};
3512} // namespace
3513
3514std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3516 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
3518 // Unanalyzable terminator.
3519 if (analyzeBranch(*LoopBB, TBB, FBB, Cond, /*AllowModify=*/false))
3520 return nullptr;
3521
3522 // Infinite loops are not supported.
3523 if (TBB == LoopBB && FBB == LoopBB)
3524 return nullptr;
3525
3526 // Must be conditional branch.
3527 if (FBB == nullptr)
3528 return nullptr;
3529
3530 assert((TBB == LoopBB || FBB == LoopBB) &&
3531 "The Loop must be a single-basic-block loop");
3532
3533 // Divergent (VCC/EXEC) back-edge is not supported.
3534 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3535 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3536 return nullptr;
3537
3538 // Calls and inline assembly are not supported.
3539 for (const MachineInstr &MI : *LoopBB)
3540 if (MI.isCall() || MI.isInlineAsm())
3541 return nullptr;
3542
3543 // Normalization for createTripCountGreaterCondition(): make Cond mean
3544 // "exit the loop" so the expander emits correct prolog guard branches.
3545 if (TBB == LoopBB)
3547
3548 auto Instructions = make_range(
3550 LoopBB->rend());
3551 auto CmpI = llvm::find_if(Instructions, [&](const MachineInstr &MI) {
3552 return MI.modifiesRegister(Cond[1].getReg(), &RI);
3553 });
3554
3555 if (CmpI == Instructions.end() || CmpI->isPHI())
3556 return nullptr;
3557 MachineInstr *CmpInst = &*CmpI;
3558
3559 return std::make_unique<AMDGPUPipelinerLoopInfo>(CmpInst, Cond);
3560}
3561
3564 Register DstReg, Register TrueReg,
3565 Register FalseReg,
3566 SelectExpansion &Exp) const {
3567 switch (Cond[0].getImm()) {
3568 case VCCNZ:
3569 case VCCZ: {
3570 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3571 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3572 if (MRI.getRegClass(FalseReg) != RC)
3573 return false;
3574
3575 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3576 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts; // ???
3577
3578 // Limit to equal cost for branch vs. N v_cndmask_b32s.
3579 return RI.hasVGPRs(RC) && NumInsts <= 6;
3580 }
3581 case SCC_TRUE:
3582 case SCC_FALSE: {
3583 // FIXME: We could insert for VGPRs if we could replace the original compare
3584 // with a vector one.
3585 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3586 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3587 if (MRI.getRegClass(FalseReg) != RC)
3588 return false;
3589
3590 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3591
3592 // Multiples of 8 can do s_cselect_b64
3593 if (NumInsts % 2 == 0)
3594 NumInsts /= 2;
3595
3596 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts; // ???
3597 return RI.isSGPRClass(RC);
3598 }
3599 default:
3600 return false;
3601 }
3602}
3603
3607 Register TrueReg, Register FalseReg) const {
3608 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3609 if (Pred == VCCZ || Pred == SCC_FALSE) {
3610 Pred = static_cast<BranchPredicate>(-Pred);
3611 std::swap(TrueReg, FalseReg);
3612 }
3613
3614 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3615 const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
3616 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3617
3618 if (DstSize == 32) {
3620 if (Pred == SCC_TRUE) {
3621 Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
3622 .addReg(TrueReg)
3623 .addReg(FalseReg);
3624 } else {
3625 // Instruction's operands are backwards from what is expected.
3626 Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
3627 .addReg(FalseReg)
3628 .addReg(TrueReg);
3629 }
3630
3631 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3632 return;
3633 }
3634
3635 if (DstSize == 64 && Pred == SCC_TRUE) {
3637 BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
3638 .addReg(TrueReg)
3639 .addReg(FalseReg);
3640
3641 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3642 return;
3643 }
3644
3645 static const int16_t Sub0_15[] = {
3646 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3647 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3648 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3649 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3650 };
3651
3652 static const int16_t Sub0_15_64[] = {
3653 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3654 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3655 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3656 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3657 };
3658
3659 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3660 const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
3661 const int16_t *SubIndices = Sub0_15;
3662 int NElts = DstSize / 32;
3663
3664 // 64-bit select is only available for SALU.
3665 // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
3666 if (Pred == SCC_TRUE) {
3667 if (NElts % 2) {
3668 SelOp = AMDGPU::S_CSELECT_B32;
3669 EltRC = &AMDGPU::SGPR_32RegClass;
3670 } else {
3671 SelOp = AMDGPU::S_CSELECT_B64;
3672 EltRC = &AMDGPU::SGPR_64RegClass;
3673 SubIndices = Sub0_15_64;
3674 NElts /= 2;
3675 }
3676 }
3677
3679 MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);
3680
3681 I = MIB->getIterator();
3682
3684 for (int Idx = 0; Idx != NElts; ++Idx) {
3685 Register DstElt = MRI.createVirtualRegister(EltRC);
3686 Regs.push_back(DstElt);
3687
3688 unsigned SubIdx = SubIndices[Idx];
3689
3691 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3692 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3693 .addReg(FalseReg, {}, SubIdx)
3694 .addReg(TrueReg, {}, SubIdx);
3695 } else {
3696 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3697 .addReg(TrueReg, {}, SubIdx)
3698 .addReg(FalseReg, {}, SubIdx);
3699 }
3700
3701 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3703
3704 MIB.addReg(DstElt)
3705 .addImm(SubIdx);
3706 }
3707}
3708
3710
3711 if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
3712 return true;
3713
3714 switch (MI.getOpcode()) {
3715 case AMDGPU::S_ENDPGM:
3716 case AMDGPU::S_ENDPGM_SAVED:
3717 case AMDGPU::S_TRAP:
3718 case AMDGPU::S_GETREG_B32:
3719 case AMDGPU::S_SETREG_B32:
3720 case AMDGPU::S_SETREG_B32_mode:
3721 case AMDGPU::S_SETREG_IMM32_B32:
3722 case AMDGPU::S_SETREG_IMM32_B32_mode:
3723 case AMDGPU::S_SENDMSG:
3724 case AMDGPU::S_SENDMSGHALT:
3725 case AMDGPU::S_SENDMSG_RTN_B32:
3726 case AMDGPU::S_SENDMSG_RTN_B64:
3727 case AMDGPU::S_BARRIER_WAIT:
3728 case AMDGPU::S_BARRIER_SIGNAL_M0:
3729 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3730 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3731 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3732 return true;
3733 default:
3734 return false;
3735 }
3736}
3737
3739 switch (MI.getOpcode()) {
3740 case AMDGPU::V_MOV_B16_t16_e32:
3741 case AMDGPU::V_MOV_B16_t16_e64:
3742 case AMDGPU::V_MOV_B32_e32:
3743 case AMDGPU::V_MOV_B32_e64:
3744 case AMDGPU::V_MOV_B64_PSEUDO:
3745 case AMDGPU::V_MOV_B64_e32:
3746 case AMDGPU::V_MOV_B64_e64:
3747 case AMDGPU::S_MOV_B32:
3748 case AMDGPU::S_MOV_B64:
3749 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3750 case AMDGPU::COPY:
3751 case AMDGPU::WWM_COPY:
3752 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3753 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3754 case AMDGPU::V_ACCVGPR_MOV_B32:
3755 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3756 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3757 return true;
3758 default:
3759 return false;
3760 }
3761}
3762
3764 switch (MI.getOpcode()) {
3765 case AMDGPU::V_MOV_B16_t16_e32:
3766 case AMDGPU::V_MOV_B16_t16_e64:
3767 return 2;
3768 case AMDGPU::V_MOV_B32_e32:
3769 case AMDGPU::V_MOV_B32_e64:
3770 case AMDGPU::V_MOV_B64_PSEUDO:
3771 case AMDGPU::V_MOV_B64_e32:
3772 case AMDGPU::V_MOV_B64_e64:
3773 case AMDGPU::S_MOV_B32:
3774 case AMDGPU::S_MOV_B64:
3775 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3776 case AMDGPU::COPY:
3777 case AMDGPU::WWM_COPY:
3778 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3779 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3780 case AMDGPU::V_ACCVGPR_MOV_B32:
3781 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3782 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3783 return 1;
3784 default:
3785 llvm_unreachable("MI is not a foldable copy");
3786 }
3787}
3788
3789static constexpr AMDGPU::OpName ModifierOpNames[] = {
3790 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3791 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3792 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3793
3795 unsigned Opc = MI.getOpcode();
3796 for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
3797 int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
3798 if (Idx >= 0)
3799 MI.removeOperand(Idx);
3800 }
3801}
3802
3804 const MCInstrDesc &NewDesc) const {
3805 MI.setDesc(NewDesc);
3806
3807 // Remove any leftover implicit operands from mutating the instruction. e.g.
3808 // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
3809 // anymore.
3810 const MCInstrDesc &Desc = MI.getDesc();
3811 unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
3812 Desc.implicit_defs().size();
3813
3814 for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
3815 MI.removeOperand(I);
3816}
3817
3818std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
3819 unsigned SubRegIndex) {
3820 switch (SubRegIndex) {
3821 case AMDGPU::NoSubRegister:
3822 return Imm;
3823 case AMDGPU::sub0:
3824 return SignExtend64<32>(Imm);
3825 case AMDGPU::sub1:
3826 return SignExtend64<32>(Imm >> 32);
3827 case AMDGPU::lo16:
3828 return SignExtend64<16>(Imm);
3829 case AMDGPU::hi16:
3830 return SignExtend64<16>(Imm >> 16);
3831 case AMDGPU::sub1_lo16:
3832 return SignExtend64<16>(Imm >> 32);
3833 case AMDGPU::sub1_hi16:
3834 return SignExtend64<16>(Imm >> 48);
3835 default:
3836 return std::nullopt;
3837 }
3838
3839 llvm_unreachable("covered subregister switch");
3840}
3841
3842static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
3843 switch (Opc) {
3844 case AMDGPU::V_MAC_F16_e32:
3845 case AMDGPU::V_MAC_F16_e64:
3846 case AMDGPU::V_MAD_F16_e64:
3847 return AMDGPU::V_MADAK_F16;
3848 case AMDGPU::V_MAC_F32_e32:
3849 case AMDGPU::V_MAC_F32_e64:
3850 case AMDGPU::V_MAD_F32_e64:
3851 return AMDGPU::V_MADAK_F32;
3852 case AMDGPU::V_FMAC_F32_e32:
3853 case AMDGPU::V_FMAC_F32_e64:
3854 case AMDGPU::V_FMA_F32_e64:
3855 return AMDGPU::V_FMAAK_F32;
3856 case AMDGPU::V_FMAC_F16_e32:
3857 case AMDGPU::V_FMAC_F16_e64:
3858 case AMDGPU::V_FMAC_F16_t16_e64:
3859 case AMDGPU::V_FMAC_F16_fake16_e64:
3860 case AMDGPU::V_FMAC_F16_t16_e32:
3861 case AMDGPU::V_FMAC_F16_fake16_e32:
3862 case AMDGPU::V_FMA_F16_e64:
3863 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3864 ? AMDGPU::V_FMAAK_F16_t16
3865 : AMDGPU::V_FMAAK_F16_fake16
3866 : AMDGPU::V_FMAAK_F16;
3867 case AMDGPU::V_FMAC_F64_e32:
3868 case AMDGPU::V_FMAC_F64_e64:
3869 case AMDGPU::V_FMA_F64_e64:
3870 return AMDGPU::V_FMAAK_F64;
3871 default:
3872 llvm_unreachable("invalid instruction");
3873 }
3874}
3875
3876static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
3877 switch (Opc) {
3878 case AMDGPU::V_MAC_F16_e32:
3879 case AMDGPU::V_MAC_F16_e64:
3880 case AMDGPU::V_MAD_F16_e64:
3881 return AMDGPU::V_MADMK_F16;
3882 case AMDGPU::V_MAC_F32_e32:
3883 case AMDGPU::V_MAC_F32_e64:
3884 case AMDGPU::V_MAD_F32_e64:
3885 return AMDGPU::V_MADMK_F32;
3886 case AMDGPU::V_FMAC_F32_e32:
3887 case AMDGPU::V_FMAC_F32_e64:
3888 case AMDGPU::V_FMA_F32_e64:
3889 return AMDGPU::V_FMAMK_F32;
3890 case AMDGPU::V_FMAC_F16_e32:
3891 case AMDGPU::V_FMAC_F16_e64:
3892 case AMDGPU::V_FMAC_F16_t16_e64:
3893 case AMDGPU::V_FMAC_F16_fake16_e64:
3894 case AMDGPU::V_FMAC_F16_t16_e32:
3895 case AMDGPU::V_FMAC_F16_fake16_e32:
3896 case AMDGPU::V_FMA_F16_e64:
3897 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3898 ? AMDGPU::V_FMAMK_F16_t16
3899 : AMDGPU::V_FMAMK_F16_fake16
3900 : AMDGPU::V_FMAMK_F16;
3901 case AMDGPU::V_FMAC_F64_e32:
3902 case AMDGPU::V_FMAC_F64_e64:
3903 case AMDGPU::V_FMA_F64_e64:
3904 return AMDGPU::V_FMAMK_F64;
3905 default:
3906 llvm_unreachable("invalid instruction");
3907 }
3908}
3909
3911 Register Reg, MachineRegisterInfo *MRI) const {
3912 int64_t Imm;
3913 if (!getConstValDefinedInReg(DefMI, Reg, Imm))
3914 return false;
3915
3916 const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);
3917
3918 assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");
3919
3920 unsigned Opc = UseMI.getOpcode();
3921 if (Opc == AMDGPU::COPY) {
3922 assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");
3923
3924 Register DstReg = UseMI.getOperand(0).getReg();
3925 Register UseSubReg = UseMI.getOperand(1).getSubReg();
3926
3927 const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);
3928
3929 if (HasMultipleUses) {
3930 // TODO: This should fold in more cases with multiple use, but we need to
3931 // more carefully consider what those uses are.
3932 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));
3933
3934 // Avoid breaking up a 64-bit inline immediate into a subregister extract.
3935 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3936 return false;
3937
3938 // Most of the time folding a 32-bit inline constant is free (though this
3939 // might not be true if we can't later fold it into a real user).
3940 //
3941 // FIXME: This isInlineConstant check is imprecise if
3942 // getConstValDefinedInReg handled the tricky non-mov cases.
3943 if (ImmDefSize == 32 &&
3945 return false;
3946 }
3947
3948 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3949 RI.getSubRegIdxSize(UseSubReg) == 16;
3950
3951 if (Is16Bit) {
3952 if (RI.hasVGPRs(DstRC))
3953 return false; // Do not clobber vgpr_hi16
3954
3955 if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
3956 return false;
3957 }
3958
3959 MachineFunction *MF = UseMI.getMF();
3960
3961 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3962 MCRegister MovDstPhysReg =
3963 DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();
3964
3965 std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);
3966
3967 // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
3968 for (unsigned MovOp :
3969 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3970 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3971 const MCInstrDesc &MovDesc = get(MovOp);
3972
3973 const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
3974 if (Is16Bit) {
3975 // We just need to find a correctly sized register class, so the
3976 // subregister index compatibility doesn't matter since we're statically
3977 // extracting the immediate value.
3978 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3979 if (!MovDstRC)
3980 continue;
3981
3982 if (MovDstPhysReg) {
3983 // FIXME: We probably should not do this. If there is a live value in
3984 // the high half of the register, it will be corrupted.
3985 MovDstPhysReg =
3986 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3987 if (!MovDstPhysReg)
3988 continue;
3989 }
3990 }
3991
3992 // Result class isn't the right size, try the next instruction.
3993 if (MovDstPhysReg) {
3994 if (!MovDstRC->contains(MovDstPhysReg))
3995 return false;
3996 } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
3997 // TODO: This will be overly conservative in the case of 16-bit virtual
3998 // SGPRs. We could hack up the virtual register uses to use a compatible
3999 // 32-bit class.
4000 continue;
4001 }
4002
4003 const MCOperandInfo &OpInfo = MovDesc.operands()[1];
4004
4005 // Ensure the interpreted immediate value is a valid operand in the new
4006 // mov.
4007 //
4008 // FIXME: isImmOperandLegal should have form that doesn't require existing
4009 // MachineInstr or MachineOperand
4010 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4011 !isInlineConstant(*SubRegImm, OpInfo.OperandType))
4012 break;
4013
4014 NewOpc = MovOp;
4015 break;
4016 }
4017
4018 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4019 return false;
4020
4021 if (Is16Bit) {
4022 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4023 if (MovDstPhysReg)
4024 UseMI.getOperand(0).setReg(MovDstPhysReg);
4025 assert(UseMI.getOperand(1).getReg().isVirtual());
4026 }
4027
4028 const MCInstrDesc &NewMCID = get(NewOpc);
4029 UseMI.setDesc(NewMCID);
4030 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4031 UseMI.addImplicitDefUseOperands(*MF);
4032 return true;
4033 }
4034
4035 if (HasMultipleUses)
4036 return false;
4037
4038 if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
4039 Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4040 Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
4041 Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
4042 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4043 Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
4044 Opc == AMDGPU::V_FMAC_F64_e64) {
4045 // Don't fold if we are using source or output modifiers. The new VOP2
4046 // instructions don't have them.
4048 return false;
4049
4050 // If this is a free constant, there's no reason to do this.
4051 // TODO: We could fold this here instead of letting SIFoldOperands do it
4052 // later.
4053 int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4054
4055 // Any src operand can be used for the legality check.
4056 if (isInlineConstant(UseMI, Src0Idx, Imm))
4057 return false;
4058
4059 MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);
4060
4061 MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
4062 MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);
4063
4064 auto CopyRegOperandToNarrowerRC =
4065 [MRI, this](MachineInstr &MI, unsigned OpNo,
4066 const TargetRegisterClass *NewRC) -> void {
4067 if (!MI.getOperand(OpNo).isReg())
4068 return;
4069 Register Reg = MI.getOperand(OpNo).getReg();
4070 const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
4071 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4072 return;
4073 Register Tmp = MRI->createVirtualRegister(NewRC);
4074 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
4075 get(AMDGPU::COPY), Tmp)
4076 .addReg(Reg);
4077 MI.getOperand(OpNo).setReg(Tmp);
4078 MI.getOperand(OpNo).setIsKill();
4079 };
4080
4081 // Multiplied part is the constant: Use v_madmk_{f16, f32}.
4082 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4083 (Src1->isReg() && Src1->getReg() == Reg)) {
4084 MachineOperand *RegSrc =
4085 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4086 if (!RegSrc->isReg())
4087 return false;
4088 if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
4089 ST.getConstantBusLimit(Opc) < 2)
4090 return false;
4091
4092 if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
4093 return false;
4094
4095 // If src2 is also a literal constant then we have to choose which one to
4096 // fold. In general it is better to choose madak so that the other literal
4097 // can be materialized in an sgpr instead of a vgpr:
4098 // s_mov_b32 s0, literal
4099 // v_madak_f32 v0, s0, v0, literal
4100 // Instead of:
4101 // v_mov_b32 v1, literal
4102 // v_madmk_f32 v0, v0, literal, v1
4103 MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
4104 if (Def && Def->isMoveImmediate() &&
4105 !isInlineConstant(Def->getOperand(1)))
4106 return false;
4107
4108 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4109 if (pseudoToMCOpcode(NewOpc) == -1)
4110 return false;
4111
4112 const std::optional<int64_t> SubRegImm = extractSubregFromImm(
4113 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4114
4115 // FIXME: This would be a lot easier if we could return a new instruction
4116 // instead of having to modify in place.
4117
4118 Register SrcReg = RegSrc->getReg();
4119 unsigned SrcSubReg = RegSrc->getSubReg();
4120 Src0->setReg(SrcReg);
4121 Src0->setSubReg(SrcSubReg);
4122 Src0->setIsKill(RegSrc->isKill());
4123
4124 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4125 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4126 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4127 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4128 UseMI.untieRegOperand(
4129 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4130
4131 Src1->ChangeToImmediate(*SubRegImm);
4132
4134 UseMI.setDesc(get(NewOpc));
4135
4136 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4137 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4138 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4139 Register Tmp = MRI->createVirtualRegister(NewRC);
4140 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4141 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4142 UseMI.getOperand(0).getReg())
4143 .addReg(Tmp, RegState::Kill);
4144 UseMI.getOperand(0).setReg(Tmp);
4145 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4146 CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
4147 }
4148
4149 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4150 if (DeleteDef)
4151 DefMI.eraseFromParent();
4152
4153 return true;
4154 }
4155
4156 // Added part is the constant: Use v_madak_{f16, f32}.
4157 if (Src2->isReg() && Src2->getReg() == Reg) {
4158 if (ST.getConstantBusLimit(Opc) < 2) {
4159 // Not allowed to use constant bus for another operand.
4160 // We can however allow an inline immediate as src0.
4161 bool Src0Inlined = false;
4162 if (Src0->isReg()) {
4163 // Try to inline constant if possible.
4164 // If the Def moves immediate and the use is single
4165 // We are saving VGPR here.
4166 MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
4167 if (Def && Def->isMoveImmediate() &&
4168 isInlineConstant(Def->getOperand(1)) &&
4169 MRI->hasOneNonDBGUse(Src0->getReg())) {
4170 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4171 Src0Inlined = true;
4172 } else if (ST.getConstantBusLimit(Opc) <= 1 &&
4173 RI.isSGPRReg(*MRI, Src0->getReg())) {
4174 return false;
4175 }
4176 // VGPR is okay as Src0 - fallthrough
4177 }
4178
4179 if (Src1->isReg() && !Src0Inlined) {
4180 // We have one slot for inlinable constant so far - try to fill it
4181 MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
4182 if (Def && Def->isMoveImmediate() &&
4183 isInlineConstant(Def->getOperand(1)) &&
4184 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
4185 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4186 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
4187 return false;
4188 // VGPR is okay as Src1 - fallthrough
4189 }
4190 }
4191
4192 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4193 if (pseudoToMCOpcode(NewOpc) == -1)
4194 return false;
4195
4196 // FIXME: This would be a lot easier if we could return a new instruction
4197 // instead of having to modify in place.
4198
4199 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4200 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4201 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4202 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4203 UseMI.untieRegOperand(
4204 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4205
4206 const std::optional<int64_t> SubRegImm =
4207 extractSubregFromImm(Imm, Src2->getSubReg());
4208
4209 // ChangingToImmediate adds Src2 back to the instruction.
4210 Src2->ChangeToImmediate(*SubRegImm);
4211
4212 // These come before src2.
4214 UseMI.setDesc(get(NewOpc));
4215
4216 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4217 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4218 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4219 Register Tmp = MRI->createVirtualRegister(NewRC);
4220 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4221 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4222 UseMI.getOperand(0).getReg())
4223 .addReg(Tmp, RegState::Kill);
4224 UseMI.getOperand(0).setReg(Tmp);
4225 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4226 CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
4227 }
4228
4229 // It might happen that UseMI was commuted
4230 // and we now have SGPR as SRC1. If so 2 inlined
4231 // constant and SGPR are illegal.
4233
4234 int NewSrc0Idx =
4235 AMDGPU::getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4236 if (!isOperandLegal(UseMI, NewSrc0Idx))
4237 legalizeOpWithMove(UseMI, NewSrc0Idx);
4238
4239 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4240 if (DeleteDef)
4241 DefMI.eraseFromParent();
4242
4243 return true;
4244 }
4245 }
4246
4247 return false;
4248}
4249
4250static bool
4253 if (BaseOps1.size() != BaseOps2.size())
4254 return false;
4255 for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
4256 if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
4257 return false;
4258 }
4259 return true;
4260}
4261
4262static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
4263 LocationSize WidthB, int OffsetB) {
4264 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4265 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4266 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4267 return LowWidth.hasValue() &&
4268 LowOffset + (int)LowWidth.getValue() <= HighOffset;
4269}
4270
4271bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
4272 const MachineInstr &MIb) const {
4273 SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
4274 int64_t Offset0, Offset1;
4275 LocationSize Dummy0 = LocationSize::precise(0);
4276 LocationSize Dummy1 = LocationSize::precise(0);
4277 bool Offset0IsScalable, Offset1IsScalable;
4278 if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
4279 Dummy0) ||
4280 !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
4281 Dummy1))
4282 return false;
4283
4284 if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
4285 return false;
4286
4287 if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
4288 // FIXME: Handle ds_read2 / ds_write2.
4289 return false;
4290 }
4291 LocationSize Width0 = MIa.memoperands().front()->getSize();
4292 LocationSize Width1 = MIb.memoperands().front()->getSize();
4293 return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
4294}
4295
4297 const MachineInstr &MIb) const {
4298 assert(MIa.mayLoadOrStore() &&
4299 "MIa must load from or modify a memory location");
4300 assert(MIb.mayLoadOrStore() &&
4301 "MIb must load from or modify a memory location");
4302
4304 return false;
4305
4306 // XXX - Can we relax this between address spaces?
4307 if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
4308 return false;
4309
4310 if (isLDSDMA(MIa) || isLDSDMA(MIb))
4311 return false;
4312
4313 if (MIa.isBundle() || MIb.isBundle())
4314 return false;
4315
4316 // TODO: Should we check the address space from the MachineMemOperand? That
4317 // would allow us to distinguish objects we know don't alias based on the
4318 // underlying address space, even if it was lowered to a different one,
4319 // e.g. private accesses lowered to use MUBUF instructions on a scratch
4320 // buffer.
4321 if (isDS(MIa)) {
4322 if (isDS(MIb))
4323 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4324
4325 return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
4326 }
4327
4328 if (isMUBUF(MIa) || isMTBUF(MIa)) {
4329 if (isMUBUF(MIb) || isMTBUF(MIb))
4330 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4331
4332 if (isFLAT(MIb))
4333 return isFLATScratch(MIb);
4334
4335 return !isSMRD(MIb);
4336 }
4337
4338 if (isSMRD(MIa)) {
4339 if (isSMRD(MIb))
4340 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4341
4342 if (isFLAT(MIb))
4343 return isFLATScratch(MIb);
4344
4345 return !isMUBUF(MIb) && !isMTBUF(MIb);
4346 }
4347
4348 if (isFLAT(MIa)) {
4349 if (isFLAT(MIb)) {
4350 if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
4351 (isFLATGlobal(MIa) && isFLATScratch(MIb)))
4352 return true;
4353
4354 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4355 }
4356
4357 return false;
4358 }
4359
4360 return false;
4361}
4362
4363static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
4364 switch (Opc) {
4365 case AMDGPU::V_MAC_F16_e32:
4366 case AMDGPU::V_MAC_F16_e64:
4367 return AMDGPU::V_MAD_F16_e64;
4368 case AMDGPU::V_MAC_F32_e32:
4369 case AMDGPU::V_MAC_F32_e64:
4370 return AMDGPU::V_MAD_F32_e64;
4371 case AMDGPU::V_MAC_LEGACY_F32_e32:
4372 case AMDGPU::V_MAC_LEGACY_F32_e64:
4373 return AMDGPU::V_MAD_LEGACY_F32_e64;
4374 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4375 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4376 return AMDGPU::V_FMA_LEGACY_F32_e64;
4377 case AMDGPU::V_FMAC_F16_e32:
4378 case AMDGPU::V_FMAC_F16_e64:
4379 case AMDGPU::V_FMAC_F16_t16_e64:
4380 case AMDGPU::V_FMAC_F16_fake16_e64:
4381 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4382 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4383 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4384 : AMDGPU::V_FMA_F16_gfx9_e64;
4385 case AMDGPU::V_FMAC_F32_e32:
4386 case AMDGPU::V_FMAC_F32_e64:
4387 return AMDGPU::V_FMA_F32_e64;
4388 case AMDGPU::V_FMAC_F64_e32:
4389 case AMDGPU::V_FMAC_F64_e64:
4390 return AMDGPU::V_FMA_F64_e64;
4391 default:
4392 llvm_unreachable("invalid instruction");
4393 }
4394}
4395
4396/// Helper struct for the implementation of 3-address conversion to communicate
4397/// updates made to instruction operands.
4399 /// Other instruction whose def is no longer used by the converted
4400 /// instruction.
4402};
4403
4405 LiveIntervals *LIS) const {
4406 MachineBasicBlock &MBB = *MI.getParent();
4407 MachineInstr *CandidateMI = &MI;
4408
4409 if (MI.isBundle()) {
4410 // This is a temporary placeholder for bundle handling that enables us to
4411 // exercise the relevant code paths in the two-address instruction pass.
4412 if (MI.getBundleSize() != 1)
4413 return nullptr;
4414 CandidateMI = MI.getNextNode();
4415 }
4416
4418 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4419 if (!NewMI)
4420 return nullptr;
4421
4422 if (MI.isBundle()) {
4423 CandidateMI->eraseFromBundle();
4424
4425 for (MachineOperand &MO : MI.all_defs()) {
4426 if (MO.isTied())
4427 MI.untieRegOperand(MO.getOperandNo());
4428 }
4429 } else {
4430 if (LIS) {
4431 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
4432 // SlotIndex of defs needs to be updated when converting to early-clobber
4433 MachineOperand &Def = NewMI->getOperand(0);
4434 if (Def.isEarlyClobber() && Def.isReg() &&
4435 LIS->hasInterval(Def.getReg())) {
4436 SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
4437 SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
4438 auto &LI = LIS->getInterval(Def.getReg());
4439 auto UpdateDefIndex = [&](LiveRange &LR) {
4440 auto *S = LR.find(OldIndex);
4441 if (S != LR.end() && S->start == OldIndex) {
4442 assert(S->valno && S->valno->def == OldIndex);
4443 S->start = NewIndex;
4444 S->valno->def = NewIndex;
4445 }
4446 };
4447 UpdateDefIndex(LI);
4448 for (auto &SR : LI.subranges())
4449 UpdateDefIndex(SR);
4450 }
4451 }
4452 }
4453
4454 if (U.RemoveMIUse) {
4455 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4456 // The only user is the instruction which will be killed.
4457 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4458
4459 if (MRI.hasOneNonDBGUse(DefReg)) {
4460 // We cannot just remove the DefMI here, calling pass will crash.
4461 U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
4462 U.RemoveMIUse->getOperand(0).setIsDead(true);
4463 for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
4464 U.RemoveMIUse->removeOperand(I);
4465 }
4466
4467 if (MI.isBundle()) {
4468 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4469 if (!VRI.Reads && !VRI.Writes) {
4470 for (MachineOperand &MO : MI.all_uses()) {
4471 if (MO.isReg() && MO.getReg() == DefReg) {
4472 assert(MO.getSubReg() == 0 &&
4473 "tied sub-registers in bundles currently not supported");
4474 MI.removeOperand(MO.getOperandNo());
4475 break;
4476 }
4477 }
4478
4479 if (LIS)
4480 LIS->shrinkToUses(&LIS->getInterval(DefReg));
4481 }
4482 } else if (LIS) {
4483 LiveInterval &DefLI = LIS->getInterval(DefReg);
4484
4485 // We cannot delete the original instruction here, so hack out the use
4486 // in the original instruction with a dummy register so we can use
4487 // shrinkToUses to deal with any multi-use edge cases. Other targets do
4488 // not have the complexity of deleting a use to consider here.
4489 Register DummyReg = MRI.cloneVirtualRegister(DefReg);
4490 for (MachineOperand &MIOp : MI.uses()) {
4491 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4492 MIOp.setIsUndef(true);
4493 MIOp.setReg(DummyReg);
4494 }
4495 }
4496
4497 if (MI.isBundle()) {
4498 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4499 if (!VRI.Reads && !VRI.Writes) {
4500 for (MachineOperand &MIOp : MI.uses()) {
4501 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4502 MIOp.setIsUndef(true);
4503 MIOp.setReg(DummyReg);
4504 }
4505 }
4506 }
4507
4508 MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
4509 false, /*isUndef=*/true));
4510 }
4511
4512 LIS->shrinkToUses(&DefLI);
4513 }
4514 }
4515
4516 return MI.isBundle() ? &MI : NewMI;
4517}
4518
4520SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
4521 ThreeAddressUpdates &U) const {
4522 MachineBasicBlock &MBB = *MI.getParent();
4523 unsigned Opc = MI.getOpcode();
4524
4525 // Handle MFMA.
4526 int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
4527 if (NewMFMAOpc != -1) {
4529 BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
4530 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4531 MIB.add(MI.getOperand(I));
4532 return MIB;
4533 }
4534
4535 if (SIInstrInfo::isWMMA(MI)) {
4536 unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
4537 MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4538 .setMIFlags(MI.getFlags());
4539 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4540 MIB->addOperand(MI.getOperand(I));
4541 return MIB;
4542 }
4543
4544 assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4545 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4546 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4547 "present pre-RA");
4548
4549 // Handle MAC/FMAC.
4550 bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
4551 bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4552 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4553 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4554 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4555 bool Src0Literal = false;
4556
4557 switch (Opc) {
4558 default:
4559 return nullptr;
4560 case AMDGPU::V_MAC_F16_e64:
4561 case AMDGPU::V_FMAC_F16_e64:
4562 case AMDGPU::V_FMAC_F16_t16_e64:
4563 case AMDGPU::V_FMAC_F16_fake16_e64:
4564 case AMDGPU::V_MAC_F32_e64:
4565 case AMDGPU::V_MAC_LEGACY_F32_e64:
4566 case AMDGPU::V_FMAC_F32_e64:
4567 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4568 case AMDGPU::V_FMAC_F64_e64:
4569 break;
4570 case AMDGPU::V_MAC_F16_e32:
4571 case AMDGPU::V_FMAC_F16_e32:
4572 case AMDGPU::V_MAC_F32_e32:
4573 case AMDGPU::V_MAC_LEGACY_F32_e32:
4574 case AMDGPU::V_FMAC_F32_e32:
4575 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4576 case AMDGPU::V_FMAC_F64_e32: {
4577 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
4578 AMDGPU::OpName::src0);
4579 const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
4580 if (!Src0->isReg() && !Src0->isImm())
4581 return nullptr;
4582
4583 if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
4584 Src0Literal = true;
4585
4586 break;
4587 }
4588 }
4589
4590 MachineInstrBuilder MIB;
4591 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
4592 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
4593 const MachineOperand *Src0Mods =
4594 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
4595 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4596 const MachineOperand *Src1Mods =
4597 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
4598 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4599 const MachineOperand *Src2Mods =
4600 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
4601 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
4602 const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
4603 const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);
4604
4605 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4606 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4607 // If we have an SGPR input, we will violate the constant bus restriction.
4608 (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
4609 !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
4610 MachineInstr *DefMI = nullptr;
4611 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4612 std::optional<int64_t> ImmOpt;
4613 int64_t Imm;
4614
4615 if (!Src0Literal &&
4616 (ImmOpt = getImmOrMaterializedImm(MRI, *Src2, &DefMI))) {
4617 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4618 if (pseudoToMCOpcode(NewOpc) != -1) {
4619 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4620 .add(*Dst)
4621 .add(*Src0)
4622 .add(*Src1)
4623 .addImm(*ImmOpt)
4624 .setMIFlags(MI.getFlags());
4625 U.RemoveMIUse = DefMI;
4626 return MIB;
4627 }
4628 }
4629 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4630 if (!Src0Literal &&
4631 (ImmOpt = getImmOrMaterializedImm(MRI, *Src1, &DefMI))) {
4632 if (pseudoToMCOpcode(NewOpc) != -1) {
4633 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4634 .add(*Dst)
4635 .add(*Src0)
4636 .addImm(*ImmOpt)
4637 .add(*Src2)
4638 .setMIFlags(MI.getFlags());
4639 U.RemoveMIUse = DefMI;
4640 return MIB;
4641 }
4642 }
4643 if ((ImmOpt = getImmOrMaterializedImm(MRI, *Src0, &DefMI))) {
4644 Imm = *ImmOpt;
4645 if (pseudoToMCOpcode(NewOpc) != -1 &&
4647 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4648 Src1)) {
4649 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4650 .add(*Dst)
4651 .add(*Src1)
4652 .addImm(Imm)
4653 .add(*Src2)
4654 .setMIFlags(MI.getFlags());
4655 U.RemoveMIUse = DefMI;
4656 return MIB;
4657 }
4658 }
4659 }
4660
4661 // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
4662 // if VOP3 does not allow a literal operand.
4663 if (Src0Literal && !ST.hasVOP3Literal())
4664 return nullptr;
4665
4666 unsigned NewOpc = getNewFMAInst(ST, Opc);
4667
4668 if (pseudoToMCOpcode(NewOpc) == -1)
4669 return nullptr;
4670
4671 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4672 .add(*Dst)
4673 .addImm(Src0Mods ? Src0Mods->getImm() : 0)
4674 .add(*Src0)
4675 .addImm(Src1Mods ? Src1Mods->getImm() : 0)
4676 .add(*Src1)
4677 .addImm(Src2Mods ? Src2Mods->getImm() : 0)
4678 .add(*Src2)
4679 .addImm(Clamp ? Clamp->getImm() : 0)
4680 .addImm(Omod ? Omod->getImm() : 0)
4681 .setMIFlags(MI.getFlags());
4682 if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
4683 MIB.addImm(OpSel ? OpSel->getImm() : 0);
4684 return MIB;
4685}
4686
4687// It's not generally safe to move VALU instructions across these since it will
4688// start using the register as a base index rather than directly.
4689// XXX - Why isn't hasSideEffects sufficient for these?
4691 switch (MI.getOpcode()) {
4692 case AMDGPU::S_SET_GPR_IDX_ON:
4693 case AMDGPU::S_SET_GPR_IDX_MODE:
4694 case AMDGPU::S_SET_GPR_IDX_OFF:
4695 return true;
4696 default:
4697 return false;
4698 }
4699}
4700
4702 const MachineBasicBlock *MBB,
4703 const MachineFunction &MF) const {
4704 // Skipping the check for SP writes in the base implementation. The reason it
4705 // was added was apparently due to compile time concerns.
4706 //
4707 // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
4708 // but is probably avoidable.
4709
4710 // Copied from base implementation.
4711 // Terminators and labels can't be scheduled around.
4712 if (MI.isTerminator() || MI.isPosition())
4713 return true;
4714
4715 // INLINEASM_BR can jump to another block
4716 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4717 return true;
4718
4719 if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
4720 return true;
4721
4722 // Target-independent instructions do not have an implicit-use of EXEC, even
4723 // when they operate on VGPRs. Treating EXEC modifications as scheduling
4724 // boundaries prevents incorrect movements of such instructions.
4725 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4726 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4727 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4728 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4729 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4731}
4732
4734 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4735 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4736 Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
4737}
4738
4740 // Instructions that access scratch use FLAT encoding or BUF encodings.
4741 if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
4742 return false;
4743
4744 // SCRATCH instructions always access scratch.
4745 if (isFLATScratch(MI))
4746 return true;
4747
4748 // If FLAT_SCRATCH registers are not initialized, we can never access scratch
4749 // via the aperture.
4750 if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
4751 return false;
4752
4753 // If there are no memory operands then conservatively assume the flat
4754 // operation may access scratch.
4755 if (MI.memoperands_empty())
4756 return true;
4757
4758 // See if any memory operand specifies an address space that involves scratch.
4759 return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
4760 unsigned AS = Memop->getAddrSpace();
4761 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4762 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4763 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4764 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4765 }
4766 return AS == AMDGPUAS::PRIVATE_ADDRESS;
4767 });
4768}
4769
4771 assert(isFLAT(MI));
4772
4773 // All flat instructions use the VMEM counter except prefetch.
4774 if (!usesVM_CNT(MI))
4775 return false;
4776
4777 // If there are no memory operands then conservatively assume the flat
4778 // operation may access VMEM.
4779 if (MI.memoperands_empty())
4780 return true;
4781
4782 // See if any memory operand specifies an address space that involves VMEM.
4783 // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
4784 // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
4785 // (GDS) address space is not supported by flat operations. Therefore, simply
4786 // return true unless only the LDS address space is found.
4787 for (const MachineMemOperand *Memop : MI.memoperands()) {
4788 unsigned AS = Memop->getAddrSpace();
4790 if (AS != AMDGPUAS::LOCAL_ADDRESS)
4791 return true;
4792 }
4793
4794 return false;
4795}
4796
4798 bool TgSplit) const {
4799 assert(isFLAT(MI));
4800
4801 // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
4802 if (!usesLGKM_CNT(MI))
4803 return false;
4804
4805 // If in tgsplit mode then there can be no use of LDS.
4806 if (TgSplit)
4807 return false;
4808
4809 // If there are no memory operands then conservatively assume the flat
4810 // operation may access LDS.
4811 if (MI.memoperands_empty())
4812 return true;
4813
4814 // See if any memory operand specifies an address space that involves LDS.
4815 for (const MachineMemOperand *Memop : MI.memoperands()) {
4816 unsigned AS = Memop->getAddrSpace();
4818 return true;
4819 }
4820
4821 return false;
4822}
4823
4825 // Skip the full operand and register alias search modifiesRegister
4826 // does. There's only a handful of instructions that touch this, it's only an
4827 // implicit def, and doesn't alias any other registers.
4828 return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
4829}
4830
4832 unsigned Opcode = MI.getOpcode();
4833
4834 if (MI.mayStore() && isSMRD(MI))
4835 return true; // scalar store or atomic
4836
4837 // This will terminate the function when other lanes may need to continue.
4838 if (MI.isReturn())
4839 return true;
4840
4841 // These instructions cause shader I/O that may cause hardware lockups
4842 // when executed with an empty EXEC mask.
4843 //
4844 // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
4845 // EXEC = 0, but checking for that case here seems not worth it
4846 // given the typical code patterns.
4847 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4848 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4849 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4850 Opcode == AMDGPU::S_SETHALT)
4851 return true;
4852
4853 if (MI.isCall() || MI.isInlineAsm())
4854 return true; // conservative assumption
4855
4856 // V_PERM_PK16 must issue with EXEC != 0 so its follower (or an inserted
4857 // V_NOP) actually runs on the VALU pipe. Returning true here keeps the
4858 // s_cbranch_execz that skips this region when EXEC is empty.
4859 if (ST.hasVPermPk16Hazard() && isVPermPk16(Opcode))
4860 return true;
4861
4862 // Assume that barrier interactions are only intended with active lanes.
4863 if (isBarrier(Opcode))
4864 return true;
4865
4866 // A mode change is a scalar operation that influences vector instructions.
4868 return true;
4869
4870 // These are like SALU instructions in terms of effects, so it's questionable
4871 // whether we should return true for those.
4872 //
4873 // However, executing them with EXEC = 0 causes them to operate on undefined
4874 // data, which we avoid by returning true here.
4875 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4876 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4877 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4878 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4879 return true;
4880
4881 return false;
4882}
4883
4885 const MachineInstr &MI) const {
4886 if (MI.isMetaInstruction())
4887 return false;
4888
4889 // This won't read exec if this is an SGPR->SGPR copy.
4890 if (MI.isCopyLike()) {
4891 if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
4892 return true;
4893
4894 // Make sure this isn't copying exec as a normal operand
4895 return MI.readsRegister(AMDGPU::EXEC, &RI);
4896 }
4897
4898 // Make a conservative assumption about the callee.
4899 if (MI.isCall())
4900 return true;
4901
4902 // Be conservative with any unhandled generic opcodes.
4903 if (!isTargetSpecificOpcode(MI.getOpcode()))
4904 return true;
4905
4906 return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
4907}
4908
4910 switch (Imm.getBitWidth()) {
4911 case 1: // This likely will be a condition code mask.
4912 return true;
4913
4914 case 32:
4915 return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
4916 ST.hasInv2PiInlineImm());
4917 case 64:
4918 return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
4919 ST.hasInv2PiInlineImm());
4920 case 16:
4921 return ST.has16BitInsts() &&
4922 AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
4923 ST.hasInv2PiInlineImm());
4924 default:
4925 llvm_unreachable("invalid bitwidth");
4926 }
4927}
4928
4930 APInt IntImm = Imm.bitcastToAPInt();
4931 int64_t IntImmVal = IntImm.getSExtValue();
4932 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4933 switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
4934 default:
4935 llvm_unreachable("invalid fltSemantics");
4938 return isInlineConstant(IntImm);
4940 return ST.has16BitInsts() &&
4941 AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
4943 return ST.has16BitInsts() &&
4944 AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
4945 }
4946}
4947
4948bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
4949 // MachineOperand provides no way to tell the true operand size, since it only
4950 // records a 64-bit value. We need to know the size to determine if a 32-bit
4951 // floating point immediate bit pattern is legal for an integer immediate. It
4952 // would be for any 32-bit integer operand, but would not be for a 64-bit one.
4953 switch (OperandType) {
4963 int32_t Trunc = static_cast<int32_t>(Imm);
4964 return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
4965 }
4973 return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
4976 // We would expect inline immediates to not be concerned with an integer/fp
4977 // distinction. However, in the case of 16-bit integer operations, the
4978 // "floating point" values appear to not work. It seems read the low 16-bits
4979 // of 32-bit immediates, which happens to always work for the integer
4980 // values.
4981 //
4982 // See llvm bugzilla 46302.
4983 //
4984 // TODO: Theoretically we could use op-sel to use the high bits of the
4985 // 32-bit FP values.
4994 return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
4999 return false;
5002 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
5003 // A few special case instructions have 16-bit operands on subtargets
5004 // where 16-bit instructions are not legal.
5005 // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
5006 // constants in these cases
5007 int16_t Trunc = static_cast<int16_t>(Imm);
5008 return ST.has16BitInsts() &&
5009 AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
5010 }
5011
5012 return false;
5013 }
5016 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
5017 int16_t Trunc = static_cast<int16_t>(Imm);
5018 return ST.has16BitInsts() &&
5019 AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
5020 }
5021 return false;
5022 }
5027 return false;
5029 return isLegalAV64PseudoImm(Imm);
5032 // Always embedded in the instruction for free.
5033 return true;
5043 // Just ignore anything else.
5044 return false;
5045 default:
5046 llvm_unreachable("invalid operand type");
5047 }
5048}
5049
5050static bool compareMachineOp(const MachineOperand &Op0,
5051 const MachineOperand &Op1) {
5052 if (Op0.getType() != Op1.getType())
5053 return false;
5054
5055 switch (Op0.getType()) {
5057 return Op0.getReg() == Op1.getReg();
5059 return Op0.getImm() == Op1.getImm();
5060 default:
5061 llvm_unreachable("Didn't expect to be comparing these operand types");
5062 }
5063}
5064
5066 const MCOperandInfo &OpInfo) const {
5067 if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
5068 return true;
5069
5070 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5071 return false;
5072
5073 if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
5074 return true;
5075
5076 return ST.hasVOP3Literal();
5077}
5078
5079bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5080 int64_t ImmVal) const {
5081 const unsigned Opc = InstDesc.getOpcode();
5082 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
5083 if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
5084 OpNo == static_cast<unsigned>(Src1Idx))
5085 return false;
5086
5087 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5088 if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
5089 if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5090 OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
5091 AMDGPU::OpName::src2))
5092 return false;
5093
5094 if (ST.hasBF16InlineConstFromUpperFP32() && isVOP1(Opc)) {
5095 if ((OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_BF16 ||
5096 OpInfo.OperandType == AMDGPU::OPERAND_REG_INLINE_C_BF16) &&
5097 isInlineConstant(ImmVal, OpInfo.OperandType))
5098 return false;
5099 }
5100
5101 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5102 }
5103
5104 return isLiteralOperandLegal(InstDesc, OpInfo);
5105}
5106
5107bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5108 const MachineOperand &MO) const {
5109 if (MO.isImm())
5110 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
5111
5112 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
5113 "unexpected imm-like operand kind");
5114 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5115 return isLiteralOperandLegal(InstDesc, OpInfo);
5116}
5117
5119 // 2 32-bit inline constants packed into one.
5120 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
5121 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
5122}
5123
5124bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
5125 // GFX90A does not have V_MUL_LEGACY_F32_e32.
5126 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5127 return false;
5128
5129 int Op32 = AMDGPU::getVOPe32(Opcode);
5130 if (Op32 == -1)
5131 return false;
5132
5133 return pseudoToMCOpcode(Op32) != -1;
5134}
5135
5136/// Return true if \p MI is a VALU comparison, i.e. an instruction that writes
5137/// a lane mask with one bit per lane, and zeroes the bits of lanes that were
5138/// inactive when it executed.
5139///
5140/// TODO: Also handle the sdst result of V_ADD_CO_U32 and V_SUB_CO_U32 and
5141/// V_DIV_SCALE_F32.
5142static bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI) {
5143 if (TII.isVOPC(MI))
5144 return true;
5145 int Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5146 return Op32 != -1 && TII.isVOPC(Op32);
5147}
5148
5150 const MachineRegisterInfo &MRI,
5151 unsigned Depth) const {
5152 assert(MRI.isSSA() && "isMaskedByExec requires SSA form");
5154 const MachineBasicBlock *MBB = Use.getParent();
5155
5156 // EXEC itself is trivially masked by EXEC.
5157 if (Reg == LMC.ExecReg)
5158 return true;
5159
5160 // Maximum depth of the def-use walk.
5161 constexpr unsigned MaxDepth = 6;
5162 if (Depth >= MaxDepth || !Reg.isVirtual())
5163 return false;
5164
5165 // Only look at definitions that can execute under the same EXEC mask as the
5166 // use.
5167 const MachineInstr *Def = MRI.getVRegDef(Reg);
5168 if (!Def || Def->getParent() != MBB)
5169 return false;
5170
5171 if (isVCmp(*this, *Def))
5172 return true;
5173
5174 // Recurse into an operand, which must be a whole register to say anything
5175 // about the whole lane mask.
5176 auto Recurse = [&](unsigned OpIdx) {
5177 const MachineOperand &MO = Def->getOperand(OpIdx);
5178 return MO.isReg() && !MO.getSubReg() &&
5179 isMaskedByExec(MO.getReg(), Use, MRI, Depth + 1);
5180 };
5181
5182 unsigned Opc = Def->getOpcode();
5183 if (Opc == AMDGPU::COPY && Recurse(1))
5184 return true;
5185 if (Opc == LMC.AndOpc && (Recurse(1) || Recurse(2)))
5186 return true;
5187 if (Opc == LMC.AndN2Opc && Recurse(1))
5188 return true;
5189 if ((Opc == LMC.OrOpc || Opc == LMC.XorOpc) && Recurse(1) && Recurse(2))
5190 return true;
5191 // TODO: Sometimes we encounter "reg = S_CSELECT -1, 0". If Reg has no other
5192 // uses this could be optimized to "reg = S_CSELECT $exec, 0".
5193
5194 return false;
5195}
5196
5197bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
5198 // The src0_modifier operand is present on all instructions
5199 // that have modifiers.
5200
5201 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
5202}
5203
5205 AMDGPU::OpName OpName) const {
5206 const MachineOperand *Mods = getNamedOperand(MI, OpName);
5207 return Mods && Mods->getImm();
5208}
5209
5211 return any_of(ModifierOpNames,
5212 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
5213}
5214
5216 const MachineRegisterInfo &MRI) const {
5217 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5218 // Can't shrink instruction with three operands.
5219 if (Src2) {
5220 switch (MI.getOpcode()) {
5221 default: return false;
5222
5223 case AMDGPU::V_ADDC_U32_e64:
5224 case AMDGPU::V_SUBB_U32_e64:
5225 case AMDGPU::V_SUBBREV_U32_e64: {
5226 const MachineOperand *Src1
5227 = getNamedOperand(MI, AMDGPU::OpName::src1);
5228 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
5229 return false;
5230 // Additional verification is needed for sdst/src2.
5231 return true;
5232 }
5233 case AMDGPU::V_MAC_F16_e64:
5234 case AMDGPU::V_MAC_F32_e64:
5235 case AMDGPU::V_MAC_LEGACY_F32_e64:
5236 case AMDGPU::V_FMAC_F16_e64:
5237 case AMDGPU::V_FMAC_F16_t16_e64:
5238 case AMDGPU::V_FMAC_F16_fake16_e64:
5239 case AMDGPU::V_FMAC_F32_e64:
5240 case AMDGPU::V_FMAC_F64_e64:
5241 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5242 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
5243 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
5244 return false;
5245 break;
5246
5247 case AMDGPU::V_CNDMASK_B32_e64:
5248 break;
5249 }
5250 }
5251
5252 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
5253 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5254 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
5255 return false;
5256
5257 // Make sure src0 isn't using any modifiers.
5258 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
5259 return false;
5260
5261 // Can it be shrunk to a valid 32 bit opcode?
5262 if (!hasVALU32BitEncoding(MI.getOpcode()))
5263 return false;
5264
5265 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
5266 if (Src0 && Src0->isImm()) {
5267 unsigned Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5268 if (!isImmOperandLegal(
5269 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5270 *Src0))
5271 return false;
5272 }
5273
5274 // Check output modifiers
5275 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
5276 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
5277 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
5278 // TODO: Can we avoid checking bound_ctrl/fi here?
5279 // They are only used by permlane*_swap special case.
5280 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
5281 !hasModifiersSet(MI, AMDGPU::OpName::fi);
5282}
5283
5284// Set VCC operand with all flags from \p Orig, except for setting it as
5285// implicit.
5287 const MachineOperand &Orig) {
5288
5289 for (MachineOperand &Use : MI.implicit_operands()) {
5290 if (Use.isUse() &&
5291 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
5292 Use.setIsUndef(Orig.isUndef());
5293 Use.setIsKill(Orig.isKill());
5294 return;
5295 }
5296 }
5297}
5298
5300 unsigned Op32) const {
5301 MachineBasicBlock *MBB = MI.getParent();
5302
5303 const MCInstrDesc &Op32Desc = get(Op32);
5304 MachineInstrBuilder Inst32 =
5305 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
5306 .setMIFlags(MI.getFlags());
5307
5308 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
5309 // For VOPC instructions, this is replaced by an implicit def of vcc.
5310
5311 // We assume the defs of the shrunk opcode are in the same order, and the
5312 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
5313 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
5314 Inst32.add(MI.getOperand(I));
5315
5316 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5317
5318 int Idx = MI.getNumExplicitDefs();
5319 for (const MachineOperand &Use : MI.explicit_uses()) {
5320 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
5322 continue;
5323
5324 if (&Use == Src2) {
5325 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5326 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
5327 // replaced with an implicit read of vcc or vcc_lo. The implicit read
5328 // of vcc was already added during the initial BuildMI, but we
5329 // 1) may need to change vcc to vcc_lo to preserve the original register
5330 // 2) have to preserve the original flags.
5331 copyFlagsToImplicitVCC(*Inst32, *Src2);
5332 continue;
5333 }
5334 }
5335
5336 Inst32.add(Use);
5337 }
5338
5339 // FIXME: Losing implicit operands
5340 fixImplicitOperands(*Inst32);
5341
5342 // The explicit carry/result def is dropped in favor of an implicit VCC def;
5343 // preserve the dead flag.
5344 const MachineOperand *OldSDst = getNamedOperand(MI, AMDGPU::OpName::sdst);
5345 if (OldSDst && OldSDst->isDead()) {
5346 if (MachineOperand *NewVCC =
5347 Inst32->findRegisterDefOperand(RI.getVCC(), &RI))
5348 NewVCC->setIsDead();
5349 }
5350
5351 return Inst32;
5352}
5353
5355 // Null is free
5356 Register Reg = RegOp.getReg();
5357 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5358 return false;
5359
5360 // SGPRs use the constant bus
5361
5362 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
5363 // physical register operands should also count, except for exec.
5364 if (RegOp.isImplicit())
5365 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5366
5367 // SGPRs use the constant bus
5368 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5369 AMDGPU::SReg_64RegClass.contains(Reg);
5370}
5371
5373 const MachineRegisterInfo &MRI) const {
5374 Register Reg = RegOp.getReg();
5375 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5376 : physRegUsesConstantBus(RegOp);
5377}
5378
5380 const MachineOperand &MO,
5381 const MCOperandInfo &OpInfo) const {
5382 // Literal constants use the constant bus.
5383 if (!MO.isReg())
5384 return !isInlineConstant(MO, OpInfo);
5385
5386 Register Reg = MO.getReg();
5387 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5389}
5390
5392 for (const MachineOperand &MO : MI.implicit_operands()) {
5393 // We only care about reads.
5394 if (MO.isDef())
5395 continue;
5396
5397 switch (MO.getReg()) {
5398 case AMDGPU::VCC:
5399 case AMDGPU::VCC_LO:
5400 case AMDGPU::VCC_HI:
5401 case AMDGPU::M0:
5402 case AMDGPU::FLAT_SCR:
5403 return MO.getReg();
5404
5405 default:
5406 break;
5407 }
5408 }
5409
5410 return Register();
5411}
5412
5413static bool shouldReadExec(const MachineInstr &MI) {
5414 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5415 switch (MI.getOpcode()) {
5416 case AMDGPU::V_READLANE_B32:
5417 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5418 case AMDGPU::V_WRITELANE_B32:
5419 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5420 return false;
5421 }
5422
5423 return true;
5424 }
5425
5426 if (MI.isPreISelOpcode() ||
5427 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5430 return false;
5431
5432 return true;
5433}
5434
5435static bool isRegOrFI(const MachineOperand &MO) {
5436 return MO.isReg() || MO.isFI();
5437}
5438
5439static bool isSubRegOf(const SIRegisterInfo &TRI,
5440 const MachineOperand &SuperVec,
5441 const MachineOperand &SubReg) {
5442 if (SubReg.getReg().isPhysical())
5443 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5444
5445 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5446 SubReg.getReg() == SuperVec.getReg();
5447}
5448
5449// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5450bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5451 const MachineRegisterInfo &MRI,
5452 StringRef &ErrInfo) const {
5453 Register DstReg = MI.getOperand(0).getReg();
5454 Register SrcReg = MI.getOperand(1).getReg();
5455 // This is a check for copy from vector register to SGPR
5456 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5457 ErrInfo = "illegal copy from vector register to SGPR";
5458 return false;
5459 }
5460 return true;
5461}
5462
5464 StringRef &ErrInfo) const {
5465 uint32_t Opcode = MI.getOpcode();
5466 const MachineFunction *MF = MI.getMF();
5467 const MachineRegisterInfo &MRI = MF->getRegInfo();
5468
5469 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5470 // Find a better property to recognize the point where instruction selection
5471 // is just done.
5472 // We can only enforce this check after SIFixSGPRCopies pass so that the
5473 // illegal copies are legalized and thereafter we don't expect a pass
5474 // inserting similar copies.
5475 if (!MRI.isSSA() && MI.isCopy())
5476 return verifyCopy(MI, MRI, ErrInfo);
5477
5478 if (SIInstrInfo::isGenericOpcode(Opcode))
5479 return true;
5480
5481 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5482 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5483 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5484 int Src3Idx = -1;
5485 if (Src0Idx == -1) {
5486 // VOPD V_DUAL_* instructions use different operand names.
5487 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5488 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5489 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5490 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5491 }
5492
5493 // Make sure the number of operands is correct.
5494 const MCInstrDesc &Desc = get(Opcode);
5495 if (!Desc.isVariadic() &&
5496 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5497 ErrInfo = "Instruction has wrong number of operands.";
5498 return false;
5499 }
5500
5501 if (MI.isInlineAsm()) {
5502 // Verify register classes for inlineasm constraints.
5503 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5504 I != E; ++I) {
5505 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5506 if (!RC)
5507 continue;
5508
5509 const MachineOperand &Op = MI.getOperand(I);
5510 if (!Op.isReg())
5511 continue;
5512
5513 Register Reg = Op.getReg();
5514 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5515 ErrInfo = "inlineasm operand has incorrect register class.";
5516 return false;
5517 }
5518 }
5519
5520 return true;
5521 }
5522
5523 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5524 ErrInfo = "missing memory operand from image instruction.";
5525 return false;
5526 }
5527
5528 // Make sure the register classes are correct.
5529 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5530 const MachineOperand &MO = MI.getOperand(i);
5531 if (MO.isFPImm()) {
5532 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5533 "all fp values to integers.";
5534 return false;
5535 }
5536
5537 const MCOperandInfo &OpInfo = Desc.operands()[i];
5538
5539 switch (OpInfo.OperandType) {
5541 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5542 ErrInfo = "Illegal immediate value for operand.";
5543 return false;
5544 }
5545 break;
5559 break;
5573 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5574 ErrInfo = "Illegal immediate value for operand.";
5575 return false;
5576 }
5577 break;
5578 }
5583 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5584 !isInlineConstant(MI, i) &&
5586 OpInfo.OperandType ==
5588 ErrInfo = "illegal 64-bit immediate value for operand.";
5589 return false;
5590 }
5591 break;
5594 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5595 ErrInfo = "Expected inline constant for operand.";
5596 return false;
5597 }
5598 break;
5601 break;
5606 // Check if this operand is an immediate.
5607 // FrameIndex operands will be replaced by immediates, so they are
5608 // allowed.
5609 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5610 ErrInfo = "Expected immediate, but got non-immediate";
5611 return false;
5612 }
5613 break;
5617 break;
5618 default:
5619 if (OpInfo.isGenericType())
5620 continue;
5621 break;
5622 }
5623 }
5624
5625 // Verify SDWA
5626 if (isSDWA(MI)) {
5627 if (!ST.hasSDWA()) {
5628 ErrInfo = "SDWA is not supported on this target";
5629 return false;
5630 }
5631
5632 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5633 AMDGPU::OpName::dst_sel}) {
5634 const MachineOperand *MO = getNamedOperand(MI, Op);
5635 if (!MO)
5636 continue;
5637 int64_t Imm = MO->getImm();
5639 ErrInfo = "Invalid SDWA selection";
5640 return false;
5641 }
5642 }
5643
5644 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5645
5646 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5647 if (OpIdx == -1)
5648 continue;
5649 const MachineOperand &MO = MI.getOperand(OpIdx);
5650
5651 if (!ST.hasSDWAScalar()) {
5652 // Only VGPRS on VI
5653 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5654 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5655 return false;
5656 }
5657 } else {
5658 // No immediates on GFX9
5659 if (!MO.isReg()) {
5660 ErrInfo =
5661 "Only reg allowed as operands in SDWA instructions on GFX9+";
5662 return false;
5663 }
5664 }
5665 }
5666
5667 if (!ST.hasSDWAOmod()) {
5668 // No omod allowed on VI
5669 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5670 if (OMod != nullptr &&
5671 (!OMod->isImm() || OMod->getImm() != 0)) {
5672 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5673 return false;
5674 }
5675 }
5676
5677 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5678 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5679 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5680 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5681 const MachineOperand *Src0ModsMO =
5682 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5683 unsigned Mods = Src0ModsMO->getImm();
5684 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5685 Mods & SISrcMods::SEXT) {
5686 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5687 return false;
5688 }
5689 }
5690
5691 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5692 if (isVOPC(BasicOpcode)) {
5693 if (!ST.hasSDWASdst() && DstIdx != -1) {
5694 // Only vcc allowed as dst on VI for VOPC
5695 const MachineOperand &Dst = MI.getOperand(DstIdx);
5696 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5697 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5698 return false;
5699 }
5700 } else if (!ST.hasSDWAOutModsVOPC()) {
5701 // No clamp allowed on GFX9 for VOPC
5702 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5703 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5704 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5705 return false;
5706 }
5707
5708 // No omod allowed on GFX9 for VOPC
5709 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5710 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5711 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5712 return false;
5713 }
5714 }
5715 }
5716
5717 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5718 if (DstUnused && DstUnused->isImm() &&
5719 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5720 const MachineOperand &Dst = MI.getOperand(DstIdx);
5721 if (!Dst.isReg() || !Dst.isTied()) {
5722 ErrInfo = "Dst register should have tied register";
5723 return false;
5724 }
5725
5726 const MachineOperand &TiedMO =
5727 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5728 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5729 ErrInfo =
5730 "Dst register should be tied to implicit use of preserved register";
5731 return false;
5732 }
5733 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5734 ErrInfo = "Dst register should use same physical register as preserved";
5735 return false;
5736 }
5737 }
5738 }
5739
5740 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5741 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5742 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5743 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5744 return false;
5745 }
5746 if (Src1MO.isImm()) {
5747 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5748 return false;
5749 }
5750 }
5751
5752 // Verify MIMG / VIMAGE / VSAMPLE
5753 if (isImage(Opcode) && !MI.mayStore()) {
5754 // Ensure that the return type used is large enough for all the options
5755 // being used TFE/LWE require an extra result register.
5756 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5757 if (DMask) {
5758 uint64_t DMaskImm = DMask->getImm();
5759 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5760 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5761 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5762 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5763
5764 // Adjust for packed 16 bit values
5765 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5766 RegCount = divideCeil(RegCount, 2);
5767
5768 // Adjust if using LWE or TFE
5769 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5770 RegCount += 1;
5771
5772 const uint32_t DstIdx =
5773 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5774 const MachineOperand &Dst = MI.getOperand(DstIdx);
5775 if (Dst.isReg()) {
5776 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5777 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5778 if (RegCount > DstSize) {
5779 ErrInfo = "Image instruction returns too many registers for dst "
5780 "register class";
5781 return false;
5782 }
5783 }
5784 }
5785 }
5786
5787 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5788 if (isVALU(MI, /*AllowLDSDMA=*/false) &&
5789 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5790 unsigned ConstantBusCount = 0;
5791 bool UsesLiteral = false;
5792 const MachineOperand *LiteralVal = nullptr;
5793
5794 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5795 if (ImmIdx != -1) {
5796 ++ConstantBusCount;
5797 UsesLiteral = true;
5798 LiteralVal = &MI.getOperand(ImmIdx);
5799 }
5800
5801 SmallVector<Register, 2> SGPRsUsed;
5802 Register SGPRUsed;
5803
5804 // Only look at the true operands. Only a real operand can use the constant
5805 // bus, and we don't want to check pseudo-operands like the source modifier
5806 // flags.
5807 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5808 if (OpIdx == -1)
5809 continue;
5810 const MachineOperand &MO = MI.getOperand(OpIdx);
5811 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5812 if (MO.isReg()) {
5813 SGPRUsed = MO.getReg();
5814 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5815 ++ConstantBusCount;
5816 SGPRsUsed.push_back(SGPRUsed);
5817 }
5818 } else if (!MO.isFI()) { // Treat FI like a register.
5819 if (!UsesLiteral) {
5820 ++ConstantBusCount;
5821 UsesLiteral = true;
5822 LiteralVal = &MO;
5823 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5824 assert(isVOP2(MI) || isVOP3(MI));
5825 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5826 return false;
5827 }
5828 }
5829 }
5830 }
5831
5832 SGPRUsed = findImplicitSGPRRead(MI);
5833 if (SGPRUsed) {
5834 // Implicit uses may safely overlap true operands
5835 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5836 return !RI.regsOverlap(SGPRUsed, SGPR);
5837 })) {
5838 ++ConstantBusCount;
5839 SGPRsUsed.push_back(SGPRUsed);
5840 }
5841 }
5842
5843 // v_writelane_b32 is an exception from constant bus restriction:
5844 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5845 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5846 Opcode != AMDGPU::V_WRITELANE_B32) {
5847 ErrInfo = "VOP* instruction violates constant bus restriction";
5848 return false;
5849 }
5850
5851 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5852 ErrInfo = "VOP3 instruction uses literal";
5853 return false;
5854 }
5855 }
5856
5857 // Special case for writelane - this can break the multiple constant bus rule,
5858 // but still can't use more than one SGPR register
5859 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5860 unsigned SGPRCount = 0;
5861 Register SGPRUsed;
5862
5863 for (int OpIdx : {Src0Idx, Src1Idx}) {
5864 if (OpIdx == -1)
5865 break;
5866
5867 const MachineOperand &MO = MI.getOperand(OpIdx);
5868
5869 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5870 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5871 if (MO.getReg() != SGPRUsed)
5872 ++SGPRCount;
5873 SGPRUsed = MO.getReg();
5874 }
5875 }
5876 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5877 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5878 return false;
5879 }
5880 }
5881 }
5882
5883 // Verify misc. restrictions on specific instructions.
5884 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5885 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5886 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5887 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5888 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
5889 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5890 if (!compareMachineOp(Src0, Src1) &&
5891 !compareMachineOp(Src0, Src2)) {
5892 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
5893 return false;
5894 }
5895 }
5896 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
5897 SISrcMods::ABS) ||
5898 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
5899 SISrcMods::ABS) ||
5900 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
5901 SISrcMods::ABS)) {
5902 ErrInfo = "ABS not allowed in VOP3B instructions";
5903 return false;
5904 }
5905 }
5906
5907 if (isSOP2(MI) || isSOPC(MI)) {
5908 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5909 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5910
5911 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
5912 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
5913 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
5914 !Src0.isIdenticalTo(Src1)) {
5915 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
5916 return false;
5917 }
5918 }
5919
5920 if (isSOPK(MI)) {
5921 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
5922 if (Desc.isBranch()) {
5923 if (!Op->isMBB()) {
5924 ErrInfo = "invalid branch target for SOPK instruction";
5925 return false;
5926 }
5927 } else {
5928 uint64_t Imm = Op->getImm();
5929 if (sopkIsZext(Opcode)) {
5930 if (!isUInt<16>(Imm)) {
5931 ErrInfo = "invalid immediate for SOPK instruction";
5932 return false;
5933 }
5934 } else {
5935 if (!isInt<16>(Imm)) {
5936 ErrInfo = "invalid immediate for SOPK instruction";
5937 return false;
5938 }
5939 }
5940 }
5941 }
5942
5943 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5944 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5945 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5946 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5947 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5948 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5949
5950 const unsigned StaticNumOps =
5951 Desc.getNumOperands() + Desc.implicit_uses().size();
5952 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5953
5954 // Require additional implicit operands. This allows a fixup done by the
5955 // post RA scheduler where the main implicit operand is killed and
5956 // implicit-defs are added for sub-registers that remain live after this
5957 // instruction.
5958 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5959 ErrInfo = "missing implicit register operands";
5960 return false;
5961 }
5962
5963 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5964 if (IsDst) {
5965 if (!Dst->isUse()) {
5966 ErrInfo = "v_movreld_b32 vdst should be a use operand";
5967 return false;
5968 }
5969
5970 unsigned UseOpIdx;
5971 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5972 UseOpIdx != StaticNumOps + 1) {
5973 ErrInfo = "movrel implicit operands should be tied";
5974 return false;
5975 }
5976 }
5977
5978 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5979 const MachineOperand &ImpUse
5980 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5981 if (!ImpUse.isReg() || !ImpUse.isUse() ||
5982 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5983 ErrInfo = "src0 should be subreg of implicit vector use";
5984 return false;
5985 }
5986 }
5987
5988 // Make sure we aren't losing exec uses in the td files. This mostly requires
5989 // being careful when using let Uses to try to add other use registers.
5990 if (shouldReadExec(MI)) {
5991 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5992 ErrInfo = "VALU instruction does not implicitly read exec mask";
5993 return false;
5994 }
5995 }
5996
5997 if (isSMRD(MI)) {
5998 if (MI.mayStore() &&
5999 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
6000 // The register offset form of scalar stores may only use m0 as the
6001 // soffset register.
6002 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
6003 if (Soff && Soff->getReg() != AMDGPU::M0) {
6004 ErrInfo = "scalar stores must use m0 as offset register";
6005 return false;
6006 }
6007 }
6008 }
6009
6010 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
6011 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
6012 if (Offset->getImm() != 0) {
6013 ErrInfo = "subtarget does not support offsets in flat instructions";
6014 return false;
6015 }
6016 }
6017
6018 if (isDS(MI) && !ST.hasGDS()) {
6019 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
6020 if (GDSOp && GDSOp->getImm() != 0) {
6021 ErrInfo = "GDS is not supported on this subtarget";
6022 return false;
6023 }
6024 }
6025
6026 if (isImage(MI)) {
6027 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
6028 if (DimOp) {
6029 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
6030 AMDGPU::OpName::vaddr0);
6031 AMDGPU::OpName RSrcOpName =
6032 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
6033 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
6034 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
6035 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
6036 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
6037 const AMDGPU::MIMGDimInfo *Dim =
6039
6040 if (!Dim) {
6041 ErrInfo = "dim is out of range";
6042 return false;
6043 }
6044
6045 bool IsA16 = false;
6046 if (ST.hasR128A16()) {
6047 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
6048 IsA16 = R128A16->getImm() != 0;
6049 } else if (ST.hasA16()) {
6050 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
6051 IsA16 = A16->getImm() != 0;
6052 }
6053
6054 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
6055
6056 unsigned AddrWords =
6057 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
6058
6059 unsigned VAddrWords;
6060 if (IsNSA) {
6061 VAddrWords = RsrcIdx - VAddr0Idx;
6062 if (ST.hasPartialNSAEncoding() &&
6063 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
6064 unsigned LastVAddrIdx = RsrcIdx - 1;
6065 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
6066 }
6067 } else {
6068 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
6069 if (AddrWords > 12)
6070 AddrWords = 16;
6071 }
6072
6073 if (VAddrWords != AddrWords) {
6074 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
6075 << " but got " << VAddrWords << "\n");
6076 ErrInfo = "bad vaddr size";
6077 return false;
6078 }
6079 }
6080 }
6081
6082 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
6083 if (DppCt) {
6084 using namespace AMDGPU::DPP;
6085
6086 unsigned DC = DppCt->getImm();
6087 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6088 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6089 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6090 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6091 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6092 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6093 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6094 ErrInfo = "Invalid dpp_ctrl value";
6095 return false;
6096 }
6097 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6098 !ST.hasDPPWavefrontShifts()) {
6099 ErrInfo = "Invalid dpp_ctrl value: "
6100 "wavefront shifts are not supported on GFX10+";
6101 return false;
6102 }
6103 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6104 !ST.hasDPPBroadcasts()) {
6105 ErrInfo = "Invalid dpp_ctrl value: "
6106 "broadcasts are not supported on GFX10+";
6107 return false;
6108 }
6109 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6110 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
6111 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6112 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6113 !ST.hasGFX90AInsts()) {
6114 ErrInfo = "Invalid dpp_ctrl value: "
6115 "row_newbroadcast/row_share is not supported before "
6116 "GFX90A/GFX10";
6117 return false;
6118 }
6119 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6120 ErrInfo = "Invalid dpp_ctrl value: "
6121 "row_share and row_xmask are not supported before GFX10";
6122 return false;
6123 }
6124 }
6125
6126 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6128 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6129 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
6130 ErrInfo = "Invalid dpp_ctrl value: "
6131 "DP ALU dpp only support row_newbcast";
6132 return false;
6133 }
6134 }
6135
6136 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
6137 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
6138 AMDGPU::OpName DataName =
6139 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6140 const MachineOperand *Data = getNamedOperand(MI, DataName);
6141 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
6142 if (Data && !Data->isReg())
6143 Data = nullptr;
6144
6145 if (!ST.hasGFX90AInsts()) {
6146 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6147 (Data && RI.isAGPR(MRI, Data->getReg())) ||
6148 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
6149 ErrInfo = "Invalid register class: "
6150 "agpr loads and stores not supported on this GPU";
6151 return false;
6152 }
6153 }
6154 }
6155
6156 if (ST.needsAlignedVGPRs()) {
6157 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
6159 if (!Op)
6160 return true;
6161 Register Reg = Op->getReg();
6162 if (Reg.isPhysical())
6163 return !(RI.getHWRegIndex(Reg) & 1);
6164 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
6165 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6166 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
6167 };
6168
6169 if (isMIMG(MI)) {
6170 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6171 ErrInfo = "Subtarget requires even aligned vector registers "
6172 "for vaddr operand of image instructions";
6173 return false;
6174 }
6175 }
6176 }
6177
6178 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6179 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
6180 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6181 ErrInfo = "Invalid register class: "
6182 "v_accvgpr_write with an SGPR is not supported on this GPU";
6183 return false;
6184 }
6185 }
6186
6187 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6188 const MachineOperand &SrcOp = MI.getOperand(1);
6189 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
6190 ErrInfo = "pseudo expects only physical SGPRs";
6191 return false;
6192 }
6193 }
6194
6195 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
6196 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
6197 if (!ST.hasScaleOffset()) {
6198 ErrInfo = "Subtarget does not support offset scaling";
6199 return false;
6200 }
6201 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
6202 ErrInfo = "Instruction does not support offset scaling";
6203 return false;
6204 }
6205 }
6206 }
6207
6208 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6209 if (AMDGPU::isSingleSGPRReadInst(Opcode)) {
6210 for (unsigned I = 0; I < 3; ++I) {
6212 return false;
6213 }
6214 }
6215
6216 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
6217 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
6218 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
6219 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6220 &AMDGPU::SReg_64RegClass) ||
6221 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6222 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
6223 return false;
6224 }
6225 }
6226
6227 return true;
6228}
6229
6231 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
6232 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6233 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
6234 ? AMDGPU::COPY
6235 : AMDGPU::V_MOV_B32_e32;
6236 }
6237 return getVALUOp(MI.getOpcode());
6238}
6239
6240// It is more readable to list mapped opcodes on the same line.
6241// clang-format off
6242
6243unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
6244 switch (Opc) {
6245 default: return AMDGPU::INSTRUCTION_LIST_END;
6246 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
6247 case AMDGPU::COPY: return AMDGPU::COPY;
6248 case AMDGPU::PHI: return AMDGPU::PHI;
6249 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
6250 case AMDGPU::WQM: return AMDGPU::WQM;
6251 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
6252 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
6253 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
6254 case AMDGPU::S_ADD_I32:
6255 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6256 case AMDGPU::S_ADDC_U32:
6257 return AMDGPU::V_ADDC_U32_e32;
6258 case AMDGPU::S_SUB_I32:
6259 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6260 // FIXME: These are not consistently handled, and selected when the carry is
6261 // used.
6262 case AMDGPU::S_ADD_U32:
6263 return AMDGPU::V_ADD_CO_U32_e32;
6264 case AMDGPU::S_SUB_U32:
6265 return AMDGPU::V_SUB_CO_U32_e32;
6266 case AMDGPU::S_ADD_U64_PSEUDO:
6267 return AMDGPU::V_ADD_U64_PSEUDO;
6268 case AMDGPU::S_SUB_U64_PSEUDO:
6269 return AMDGPU::V_SUB_U64_PSEUDO;
6270 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
6271 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
6272 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
6273 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
6274 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
6275 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
6276 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
6277 case AMDGPU::S_XNOR_B32:
6278 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6279 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
6280 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
6281 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
6282 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
6283 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
6284 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
6285 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
6286 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
6287 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
6288 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
6289 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
6290 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
6291 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
6292 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
6293 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
6294 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
6295 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
6296 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
6297 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
6298 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
6299 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
6300 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
6301 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
6302 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
6303 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
6304 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
6305 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
6306 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
6307 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
6308 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
6309 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
6310 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
6311 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
6312 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
6313 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
6314 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
6315 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
6316 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
6317 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
6318 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
6319 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
6320 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
6321 case AMDGPU::S_CVT_F32_F16:
6322 case AMDGPU::S_CVT_HI_F32_F16:
6323 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6324 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6325 case AMDGPU::S_CVT_F16_F32:
6326 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6327 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6328 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
6329 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
6330 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
6331 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
6332 case AMDGPU::S_CEIL_F16:
6333 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6334 : AMDGPU::V_CEIL_F16_fake16_e64;
6335 case AMDGPU::S_FLOOR_F16:
6336 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6337 : AMDGPU::V_FLOOR_F16_fake16_e64;
6338 case AMDGPU::S_TRUNC_F16:
6339 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6340 : AMDGPU::V_TRUNC_F16_fake16_e64;
6341 case AMDGPU::S_RNDNE_F16:
6342 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6343 : AMDGPU::V_RNDNE_F16_fake16_e64;
6344 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6345 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6346 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6347 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6348 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6349 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6350 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6351 case AMDGPU::S_ADD_F16:
6352 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6353 : AMDGPU::V_ADD_F16_fake16_e64;
6354 case AMDGPU::S_SUB_F16:
6355 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6356 : AMDGPU::V_SUB_F16_fake16_e64;
6357 case AMDGPU::S_MIN_F16:
6358 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6359 : AMDGPU::V_MIN_F16_fake16_e64;
6360 case AMDGPU::S_MAX_F16:
6361 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6362 : AMDGPU::V_MAX_F16_fake16_e64;
6363 case AMDGPU::S_MINIMUM_F16:
6364 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6365 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6366 case AMDGPU::S_MAXIMUM_F16:
6367 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6368 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6369 case AMDGPU::S_MUL_F16:
6370 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6371 : AMDGPU::V_MUL_F16_fake16_e64;
6372 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6373 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6374 case AMDGPU::S_FMAC_F16:
6375 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6376 : AMDGPU::V_FMAC_F16_fake16_e64;
6377 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6378 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6379 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6380 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6381 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6382 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6383 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6384 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6385 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6386 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6387 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6388 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6389 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6390 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6391 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6392 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6393 case AMDGPU::S_CMP_LT_F16:
6394 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6395 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6396 case AMDGPU::S_CMP_EQ_F16:
6397 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6398 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6399 case AMDGPU::S_CMP_LE_F16:
6400 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6401 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6402 case AMDGPU::S_CMP_GT_F16:
6403 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6404 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6405 case AMDGPU::S_CMP_LG_F16:
6406 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6407 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6408 case AMDGPU::S_CMP_GE_F16:
6409 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6410 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6411 case AMDGPU::S_CMP_O_F16:
6412 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6413 : AMDGPU::V_CMP_O_F16_fake16_e64;
6414 case AMDGPU::S_CMP_U_F16:
6415 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6416 : AMDGPU::V_CMP_U_F16_fake16_e64;
6417 case AMDGPU::S_CMP_NGE_F16:
6418 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6419 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6420 case AMDGPU::S_CMP_NLG_F16:
6421 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6422 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6423 case AMDGPU::S_CMP_NGT_F16:
6424 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6425 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6426 case AMDGPU::S_CMP_NLE_F16:
6427 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6428 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6429 case AMDGPU::S_CMP_NEQ_F16:
6430 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6431 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6432 case AMDGPU::S_CMP_NLT_F16:
6433 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6434 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6435 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6436 case AMDGPU::V_S_EXP_F16_e64:
6437 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6438 : AMDGPU::V_EXP_F16_fake16_e64;
6439 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6440 case AMDGPU::V_S_LOG_F16_e64:
6441 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6442 : AMDGPU::V_LOG_F16_fake16_e64;
6443 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6444 case AMDGPU::V_S_RCP_F16_e64:
6445 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6446 : AMDGPU::V_RCP_F16_fake16_e64;
6447 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6448 case AMDGPU::V_S_RSQ_F16_e64:
6449 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6450 : AMDGPU::V_RSQ_F16_fake16_e64;
6451 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6452 case AMDGPU::V_S_SQRT_F16_e64:
6453 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6454 : AMDGPU::V_SQRT_F16_fake16_e64;
6455 }
6457 "Unexpected scalar opcode without corresponding vector one!");
6458}
6459
6460// clang-format on
6461
6465 const DebugLoc &DL, Register Reg,
6466 bool IsSCCLive,
6467 SlotIndexes *Indexes) const {
6468 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6469 const SIInstrInfo *TII = ST.getInstrInfo();
6471 if (IsSCCLive) {
6472 // Insert two move instructions, one to save the original value of EXEC and
6473 // the other to turn on all bits in EXEC. This is required as we can't use
6474 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6475 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6477 auto FlipExecMI =
6478 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6479 if (Indexes) {
6480 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6481 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6482 }
6483 } else {
6484 auto SaveExec =
6485 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6486 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6487 if (Indexes)
6488 Indexes->insertMachineInstrInMaps(*SaveExec);
6489 }
6490}
6491
6494 const DebugLoc &DL, Register Reg,
6495 SlotIndexes *Indexes) const {
6497 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6498 .addReg(Reg, RegState::Kill);
6499 if (Indexes)
6500 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6501}
6502
6506 "Not a whole wave func");
6507 MachineBasicBlock &MBB = *MF.begin();
6508 for (MachineInstr &MI : MBB)
6509 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6510 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6511 return &MI;
6512
6513 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6514}
6515
6517 unsigned OpNo) const {
6518 const MCInstrDesc &Desc = get(MI.getOpcode());
6519 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6520 Desc.operands()[OpNo].RegClass == -1) {
6521 Register Reg = MI.getOperand(OpNo).getReg();
6522
6523 if (Reg.isVirtual()) {
6524 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6525 return MRI.getRegClass(Reg);
6526 }
6527 return RI.getPhysRegBaseClass(Reg);
6528 }
6529
6530 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6531 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6532}
6533
6534// Convert VOP3 operand index to source number.
6535static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx) {
6536 constexpr AMDGPU::OpName OpNames[] = {
6537 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6538
6539 for (auto [I, OpName] : enumerate(OpNames)) {
6540 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6541 if (static_cast<unsigned>(SrcIdx) == OpIdx)
6542 return I;
6543 }
6544
6545 return UINT_MAX;
6546}
6547
6550 MachineBasicBlock *MBB = MI.getParent();
6551 MachineOperand &MO = MI.getOperand(OpIdx);
6552 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6553 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6554 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6555 unsigned Size = RI.getRegSizeInBits(*RC);
6556 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6557 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6558 : AMDGPU::V_MOV_B32_e32;
6559 if (MO.isReg())
6560 Opcode = AMDGPU::COPY;
6561 else if (RI.isSGPRClass(RC))
6562 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6563
6564 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6565 Register Reg = MRI.createVirtualRegister(VRC);
6566 DebugLoc DL = MBB->findDebugLoc(I);
6567
6568 if (Size == 128 && AMDGPU::isPackedSingleSGPR64BitInst(MI.getOpcode()) &&
6570 // Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
6571 // sources behave like OPSEL is set replicating low 64-bits into high. VGPR
6572 // sources in turn read actual 4 registers. To move operand from an SGPR to
6573 // a VGPR we need to replicate low half.
6574 // We also do not select immediates for these instructions so it always has
6575 // to be an SGPR register here.
6576 // Operands which are not legal as per isLegalSingleSGPRReadInstOperand()
6577 // sent here specifically to fix a non-splat SGPR and shall perform a full
6578 // copy.
6579
6580 const TargetRegisterClass *VRC64 = RI.getVGPRClassForBitWidth(64);
6581 Register Low64 = MRI.createVirtualRegister(VRC64);
6582 assert(MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()));
6583 BuildMI(*MBB, I, DL, get(TargetOpcode::COPY), Low64)
6584 .addReg(MO.getReg(), {}, AMDGPU::sub0_sub1);
6585 BuildMI(*MBB, I, DL, get(TargetOpcode::REG_SEQUENCE), Reg)
6586 .addReg(Low64)
6587 .addImm(AMDGPU::sub0_sub1)
6588 .addReg(Low64)
6589 .addImm(AMDGPU::sub2_sub3);
6590 } else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6591 BuildMI(*MBB, I, DL, get(Opcode), Reg)
6592 .addImm(0) // src0_modifiers
6593 .add(MO)
6594 .addImm(0); // op_sel
6595 } else {
6596 BuildMI(*MBB, I, DL, get(Opcode), Reg).add(MO);
6597 }
6598
6599 MO.ChangeToRegister(Reg, false);
6600}
6601
6604 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6605 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6606 if (!SuperReg.getReg().isVirtual())
6607 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6608
6609 MachineBasicBlock *MBB = MI->getParent();
6610 const DebugLoc &DL = MI->getDebugLoc();
6611 Register SubReg = MRI.createVirtualRegister(SubRC);
6612
6613 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6614 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6615 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6616 return SubReg;
6617}
6618
6621 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6622 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6623 if (Op.isImm()) {
6624 if (SubIdx == AMDGPU::sub0)
6625 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6626 if (SubIdx == AMDGPU::sub1)
6627 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6628
6629 llvm_unreachable("Unhandled register index for immediate");
6630 }
6631
6632 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6633 SubIdx, SubRC);
6634 return MachineOperand::CreateReg(SubReg, false);
6635}
6636
6637// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6638void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6639 assert(Inst.getNumExplicitOperands() == 3);
6640 MachineOperand Op1 = Inst.getOperand(1);
6641 Inst.removeOperand(1);
6642 Inst.addOperand(Op1);
6643}
6644
6646 const MCOperandInfo &OpInfo,
6647 const MachineOperand &MO) const {
6648 if (!MO.isReg())
6649 return false;
6650
6651 Register Reg = MO.getReg();
6652
6653 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6654 if (Reg.isPhysical())
6655 return DRC->contains(Reg);
6656
6657 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6658
6659 if (MO.getSubReg()) {
6660 const TargetRegisterClass *SuperRC =
6661 RI.getLargestLegalSuperClass(RC, MRI.getMF());
6662 if (!SuperRC)
6663 return false;
6664 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6665 }
6666
6667 return RI.getCommonSubClass(DRC, RC) != nullptr;
6668}
6669
6671 const MachineOperand &MO) const {
6672 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6673 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6674 unsigned Opc = MI.getOpcode();
6675
6676 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6677 if (MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
6678 AMDGPU::isSingleSGPRReadInst(MI.getOpcode()) &&
6680 &MO))
6681 return false;
6682
6683 if (!isLegalRegOperand(MRI, OpInfo, MO))
6684 return false;
6685
6686 // check Accumulate GPR operand
6687 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6688 if (IsAGPR && !ST.hasMAIInsts())
6689 return false;
6690 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6691 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6692 return false;
6693 // Atomics should have both vdst and vdata either vgpr or agpr.
6694 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6695 const int DataIdx = AMDGPU::getNamedOperandIdx(
6696 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6697 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6698 MI.getOperand(DataIdx).isReg() &&
6699 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6700 return false;
6701 if ((int)OpIdx == DataIdx) {
6702 if (VDstIdx != -1 &&
6703 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6704 return false;
6705 // DS instructions with 2 src operands also must have tied RC.
6706 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6707 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6708 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6709 return false;
6710 }
6711
6712 // Check V_ACCVGPR_WRITE_B32_e64
6713 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6714 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6715 RI.isSGPRReg(MRI, MO.getReg()))
6716 return false;
6717
6718 if (ST.hasFlatScratchHiInB64InstHazard() &&
6719 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6720 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6721 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6722 64)
6723 return false;
6724 }
6725 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6726 return false;
6727 }
6728 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6729 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6730 return false;
6731
6732 return true;
6733}
6734
6736 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6737 const MachineOperand *MO) const {
6738 constexpr unsigned NumOps = 3;
6739 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6740 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6741 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6742 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6743
6744 assert(SrcN < NumOps);
6745
6746 if (!MO) {
6747 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6748 if (SrcIdx == -1)
6749 return true;
6750 MO = &MI.getOperand(SrcIdx);
6751 }
6752
6753 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6754 return true;
6755
6756 int ModsIdx =
6757 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6758 if (ModsIdx == -1)
6759 return false;
6760
6761 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6762 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6763 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6764
6765 return !OpSel && !OpSelHi;
6766}
6767
6768// Check if V_PK_FMA_F32 does not have the invalid opsel conditions.
6770 if (!ST.hasPkF32InvalidOpSel() || MI.getOpcode() != AMDGPU::V_PK_FMA_F32)
6771 return true;
6772
6773 const MachineOperand *Src1Mods =
6774 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
6775 const MachineOperand *Src2Mods =
6776 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
6777
6778 auto HasOpSel0 = [](const MachineOperand *Mods) {
6779 return Mods->getImm() & SISrcMods::OP_SEL_0;
6780 };
6781
6782 // Illegal iff opsel[2:1] == 2'b01, 2'b10, or 2'b11
6783 return !HasOpSel0(Src1Mods) && !HasOpSel0(Src2Mods);
6784}
6785
6787 MachineRegisterInfo &MRI) const {
6788 assert(MI.getOpcode() == AMDGPU::V_PK_FMA_F32);
6789
6790 MachineBasicBlock &MBB = *MI.getParent();
6791 const DebugLoc &DL = MI.getDebugLoc();
6792
6793 MachineOperand *Srcs[3] = {getNamedOperand(MI, AMDGPU::OpName::src0),
6794 getNamedOperand(MI, AMDGPU::OpName::src1),
6795 getNamedOperand(MI, AMDGPU::OpName::src2)};
6796 const unsigned Mods[3] = {
6797 static_cast<unsigned>(
6798 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm()),
6799 static_cast<unsigned>(
6800 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm()),
6801 static_cast<unsigned>(
6802 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm())};
6803
6804 // extract op_sel / op_sel_hi
6805 bool OpSel[3][2];
6806 for (unsigned I = 0; I != 3; ++I) {
6807 OpSel[I][0] = Mods[I] & SISrcMods::OP_SEL_0;
6808 OpSel[I][1] = Mods[I] & SISrcMods::OP_SEL_1;
6809 }
6810
6811 // The packed op can read only one SGPR on the constant bus (limit is 1 on
6812 // gfx9), so all its SGPR sources are the same pair. Each scalar lane can also
6813 // read only one SGPR, but op_sel may make a lane read different halves of
6814 // that pair, e.g.
6815 // v_pk_fma_f32 v[0:1], s[0:1], 0, s[0:1] op_sel:[0,0,1] op_sel_hi:[1,1,0]
6816 // => v_fma_f32 v0, s0, 0, s1 / v_fma_f32 v1, s1, 0, s0
6817 // If so, copy the pair to a VGPR once before extracting the lanes, rather
6818 // than moving a scalar into a VGPR per lane.
6819 SmallVector<unsigned, 3> SGPRSrcs;
6820 bool DivergentSGPRs = false;
6821 for (unsigned I = 0; I != 3; ++I) {
6822 if (!Srcs[I]->isReg() || !RI.isSGPRReg(MRI, Srcs[I]->getReg()))
6823 continue;
6824 if (!SGPRSrcs.empty()) {
6825 unsigned First = SGPRSrcs.front();
6826 assert(Srcs[I]->getReg() == Srcs[First]->getReg() &&
6827 Srcs[I]->getSubReg() == Srcs[First]->getSubReg() &&
6828 "constant bus limit allows only one SGPR source");
6829 DivergentSGPRs |=
6830 OpSel[I][0] != OpSel[First][0] || OpSel[I][1] != OpSel[First][1];
6831 }
6832 SGPRSrcs.push_back(I);
6833 }
6834
6835 if (DivergentSGPRs) {
6836 unsigned First = SGPRSrcs.front();
6837 legalizeOpWithMove(MI, MI.getOperandNo(Srcs[First]));
6838 for (unsigned I : ArrayRef(SGPRSrcs).drop_front())
6839 Srcs[I]->ChangeToRegister(Srcs[First]->getReg(), /*isDef=*/false);
6840 }
6841
6842 // Extract the low or high lane of a packed VOP3P source operand.
6843 auto ExtractLane = [&](MachineOperand &Op, bool UseSub1) -> MachineOperand {
6844 unsigned SubIdx = (Op.isReg() && UseSub1) ? AMDGPU::sub1 : AMDGPU::sub0;
6845 const TargetRegisterClass *RC =
6846 Op.isReg() ? MRI.getRegClass(Op.getReg()) : nullptr;
6847 const TargetRegisterClass *SubRC = !Op.isReg() ? nullptr
6848 : RI.isVGPR(MRI, Op.getReg())
6849 ? RI.getVGPRClassForBitWidth(32)
6850 : RI.getSGPRClassForBitWidth(32);
6851 return buildExtractSubRegOrImm(MI, MRI, Op, RC, SubIdx, SubRC);
6852 };
6853
6854 // neg_lo/neg_hi on the packed operand become a plain NEG modifier.
6855 auto LaneMods = [](unsigned Mods, bool Hi) -> unsigned {
6856 if (Hi)
6857 return (Mods & SISrcMods::NEG_HI) ? static_cast<unsigned>(SISrcMods::NEG)
6858 : 0u;
6859 return Mods & SISrcMods::NEG;
6860 };
6861
6862 auto BuildLane = [&](Register Dst, bool Hi) {
6863 MachineOperand L0 = ExtractLane(*Srcs[0], OpSel[0][Hi]);
6864 MachineOperand L1 = ExtractLane(*Srcs[1], OpSel[1][Hi]);
6865 MachineOperand L2 = ExtractLane(*Srcs[2], OpSel[2][Hi]);
6866 BuildMI(MBB, MI, DL, get(AMDGPU::V_FMA_F32_e64), Dst)
6867 .addImm(LaneMods(Mods[0], Hi))
6868 .add(L0)
6869 .addImm(LaneMods(Mods[1], Hi))
6870 .add(L1)
6871 .addImm(LaneMods(Mods[2], Hi))
6872 .add(L2)
6873 .addImm(0) // clamp
6874 .addImm(0); // omod
6875 };
6876
6877 const TargetRegisterClass *VGPR32 = RI.getVGPRClassForBitWidth(32);
6878 Register Lo = MRI.createVirtualRegister(VGPR32);
6879 Register Hi = MRI.createVirtualRegister(VGPR32);
6880 BuildLane(Lo, false);
6881 BuildLane(Hi, true);
6882
6883 Register Dst = getNamedOperand(MI, AMDGPU::OpName::vdst)->getReg();
6884 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
6885 .addReg(Lo)
6886 .addImm(AMDGPU::sub0)
6887 .addReg(Hi)
6888 .addImm(AMDGPU::sub1);
6889
6890 MI.eraseFromParent();
6891}
6892
6893bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
6894 const MachineOperand *MO) const {
6895 const MachineFunction &MF = *MI.getMF();
6896 const MachineRegisterInfo &MRI = MF.getRegInfo();
6897 const MCInstrDesc &InstDesc = MI.getDesc();
6898 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6899 int64_t RegClass = getOpRegClassID(OpInfo);
6900 const TargetRegisterClass *DefinedRC =
6901 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6902 if (!MO)
6903 MO = &MI.getOperand(OpIdx);
6904
6905 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6906
6907 if (isVALU(MI, /*AllowLDSDMA=*/false) && !IsInlineConst &&
6908 usesConstantBus(MRI, *MO, OpInfo)) {
6909 const MachineOperand *UsedLiteral = nullptr;
6910
6911 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6912 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6913
6914 // TODO: Be more permissive with frame indexes.
6915 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6916 if (!LiteralLimit--)
6917 return false;
6918
6919 UsedLiteral = MO;
6920 }
6921
6923 if (MO->isReg())
6924 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6925
6926 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6927 if (i == OpIdx)
6928 continue;
6929 const MachineOperand &Op = MI.getOperand(i);
6930 if (Op.isReg()) {
6931 if (Op.isUse()) {
6932 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6933 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6934 if (--ConstantBusLimit <= 0)
6935 return false;
6936 }
6937 }
6938 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6939 !isInlineConstant(Op, InstDesc.operands()[i])) {
6940 // The same literal may be used multiple times.
6941 if (!UsedLiteral)
6942 UsedLiteral = &Op;
6943 else if (UsedLiteral->isIdenticalTo(Op))
6944 continue;
6945
6946 if (!LiteralLimit--)
6947 return false;
6948 if (--ConstantBusLimit <= 0)
6949 return false;
6950 }
6951 }
6952 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6953 // There can be at most one literal operand, but it can be repeated.
6954 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6955 if (i == OpIdx)
6956 continue;
6957 const MachineOperand &Op = MI.getOperand(i);
6958 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6959 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6960 !Op.isIdenticalTo(*MO))
6961 return false;
6962
6963 // Do not fold a non-inlineable and non-register operand into an
6964 // instruction that already has a frame index. The frame index handling
6965 // code could not handle well when a frame index co-exists with another
6966 // non-register operand, unless that operand is an inlineable immediate.
6967 if (Op.isFI())
6968 return false;
6969 }
6970 }
6971
6972 if (MO->isReg()) {
6973 if (!DefinedRC)
6974 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6975 return isLegalRegOperand(MI, OpIdx, *MO);
6976 }
6977
6978 if (MO->isImm()) {
6979 uint64_t Imm = MO->getImm();
6980 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6981 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6982 bool Is64BitOp = Is64BitFPOp ||
6983 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6984 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6985 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6986 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6987 if (Is64BitOp &&
6988 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6989 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6990 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6991 return false;
6992
6993 // FIXME: We can use sign extended 64-bit literals, but only for signed
6994 // operands. At the moment we do not know if an operand is signed.
6995 // Such operand will be encoded as its low 32 bits and then either
6996 // correctly sign extended or incorrectly zero extended by HW.
6997 // If 64-bit literals are supported and the literal will be encoded
6998 // as full 64 bit we still can use it.
6999 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
7000 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
7001 return false;
7002 }
7003 }
7004
7005 // Handle non-register types that are treated like immediates.
7006 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
7007
7008 if (!DefinedRC) {
7009 // This operand expects an immediate.
7010 return true;
7011 }
7012
7013 return isImmOperandLegal(MI, OpIdx, *MO);
7014}
7015
7017 bool IsGFX950Only = ST.hasGFX950Insts();
7018 bool IsGFX940Only = ST.hasGFX940Insts();
7019
7020 if (!IsGFX950Only && !IsGFX940Only)
7021 return false;
7022
7023 if (!isVALU(MI, /*AllowLDSDMA=*/false))
7024 return false;
7025
7026 // V_COS, V_EXP, V_RCP, etc.
7027 if (isTRANS(MI))
7028 return true;
7029
7030 // DOT2, DOT2C, DOT4, etc.
7031 if (isDOT(MI))
7032 return true;
7033
7034 // MFMA, SMFMA
7035 if (isMFMA(MI))
7036 return true;
7037
7038 unsigned Opcode = MI.getOpcode();
7039 switch (Opcode) {
7040 case AMDGPU::V_CVT_PK_BF8_F32_e64:
7041 case AMDGPU::V_CVT_PK_FP8_F32_e64:
7042 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
7043 case AMDGPU::V_MQSAD_U32_U8_e64:
7044 case AMDGPU::V_PK_ADD_F16:
7045 case AMDGPU::V_PK_ADD_F32:
7046 case AMDGPU::V_PK_ADD_I16:
7047 case AMDGPU::V_PK_ADD_U16:
7048 case AMDGPU::V_PK_ASHRREV_I16:
7049 case AMDGPU::V_PK_FMA_F16:
7050 case AMDGPU::V_PK_FMA_F32:
7051 case AMDGPU::V_PK_FMAC_F16_e32:
7052 case AMDGPU::V_PK_FMAC_F16_e64:
7053 case AMDGPU::V_PK_LSHLREV_B16:
7054 case AMDGPU::V_PK_LSHRREV_B16:
7055 case AMDGPU::V_PK_MAD_I16:
7056 case AMDGPU::V_PK_MAD_U16:
7057 case AMDGPU::V_PK_MAX_F16:
7058 case AMDGPU::V_PK_MAX_I16:
7059 case AMDGPU::V_PK_MAX_U16:
7060 case AMDGPU::V_PK_MIN_F16:
7061 case AMDGPU::V_PK_MIN_I16:
7062 case AMDGPU::V_PK_MIN_U16:
7063 case AMDGPU::V_PK_MOV_B32:
7064 case AMDGPU::V_PK_MUL_F16:
7065 case AMDGPU::V_PK_MUL_F32:
7066 case AMDGPU::V_PK_MUL_LO_U16:
7067 case AMDGPU::V_PK_SUB_I16:
7068 case AMDGPU::V_PK_SUB_U16:
7069 case AMDGPU::V_QSAD_PK_U16_U8_e64:
7070 return true;
7071 default:
7072 return false;
7073 }
7074}
7075
7077 MachineInstr &MI) const {
7078 unsigned Opc = MI.getOpcode();
7079 const MCInstrDesc &InstrDesc = get(Opc);
7080
7081 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
7082 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7083
7084 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
7085 MachineOperand &Src1 = MI.getOperand(Src1Idx);
7086
7087 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
7088 // we need to only have one constant bus use before GFX10.
7089 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
7090 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
7091 RI.isSGPRReg(MRI, Src0.getReg()))
7092 legalizeOpWithMove(MI, Src0Idx);
7093
7094 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
7095 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
7096 // src0/src1 with V_READFIRSTLANE.
7097 if (Opc == AMDGPU::V_WRITELANE_B32) {
7098 const DebugLoc &DL = MI.getDebugLoc();
7099 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
7100 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7101 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7102 .add(Src0);
7103 Src0.ChangeToRegister(Reg, false);
7104 }
7105 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
7106 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7107 const DebugLoc &DL = MI.getDebugLoc();
7108 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7109 .add(Src1);
7110 Src1.ChangeToRegister(Reg, false);
7111 }
7112 return;
7113 }
7114
7115 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
7116 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
7117 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
7118 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
7119 legalizeOpWithMove(MI, Src2Idx);
7120 }
7121
7122 // VOP2 src0 instructions support all operand types, so we don't need to check
7123 // their legality. If src1 is already legal, we don't need to do anything.
7124 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
7125 return;
7126
7127 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
7128 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
7129 // select is uniform.
7130 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
7131 RI.isVGPR(MRI, Src1.getReg())) {
7132 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7133 const DebugLoc &DL = MI.getDebugLoc();
7134 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7135 .add(Src1);
7136 Src1.ChangeToRegister(Reg, false);
7137 return;
7138 }
7139
7140 // We do not use commuteInstruction here because it is too aggressive and will
7141 // commute if it is possible. We only want to commute here if it improves
7142 // legality. This can be called a fairly large number of times so don't waste
7143 // compile time pointlessly swapping and checking legality again.
7144 if (HasImplicitSGPR || !MI.isCommutable()) {
7145 legalizeOpWithMove(MI, Src1Idx);
7146 return;
7147 }
7148
7149 // If src0 can be used as src1, commuting will make the operands legal.
7150 // Otherwise we have to give up and insert a move.
7151 //
7152 // TODO: Other immediate-like operand kinds could be commuted if there was a
7153 // MachineOperand::ChangeTo* for them.
7154 if ((!Src1.isImm() && !Src1.isReg()) ||
7155 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
7156 legalizeOpWithMove(MI, Src1Idx);
7157 return;
7158 }
7159
7160 int CommutedOpc = commuteOpcode(MI);
7161 if (CommutedOpc == -1) {
7162 legalizeOpWithMove(MI, Src1Idx);
7163 return;
7164 }
7165
7166 MI.setDesc(get(CommutedOpc));
7167
7168 Register Src0Reg = Src0.getReg();
7169 unsigned Src0SubReg = Src0.getSubReg();
7170 bool Src0Kill = Src0.isKill();
7171
7172 if (Src1.isImm())
7173 Src0.ChangeToImmediate(Src1.getImm());
7174 else if (Src1.isReg()) {
7175 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
7176 Src0.setSubReg(Src1.getSubReg());
7177 } else
7178 llvm_unreachable("Should only have register or immediate operands");
7179
7180 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
7181 Src1.setSubReg(Src0SubReg);
7183}
7184
7185// Legalize VOP3 operands. All operand types are supported for any operand
7186// but only one literal constant and only starting from GFX10.
7188 MachineInstr &MI) const {
7189 unsigned Opc = MI.getOpcode();
7190
7191 int VOP3Idx[3] = {
7192 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
7193 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
7194 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
7195 };
7196
7197 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7198 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7199 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7200 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7201 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7202 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7203 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7204 // src1 and src2 must be scalar
7205 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
7206 const DebugLoc &DL = MI.getDebugLoc();
7207 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
7208 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7209 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7210 .add(Src1);
7211 Src1.ChangeToRegister(Reg, false);
7212 }
7213 if (VOP3Idx[2] != -1) {
7214 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
7215 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
7216 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7217 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7218 .add(Src2);
7219 Src2.ChangeToRegister(Reg, false);
7220 }
7221 }
7222 }
7223
7224 // Find the one SGPR operand we are allowed to use.
7225 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
7226 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7227 SmallDenseSet<unsigned> SGPRsUsed;
7228 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
7229 if (SGPRReg) {
7230 SGPRsUsed.insert(SGPRReg);
7231 --ConstantBusLimit;
7232 }
7233
7234 for (int Idx : VOP3Idx) {
7235 if (Idx == -1)
7236 break;
7237 MachineOperand &MO = MI.getOperand(Idx);
7238
7239 if (!MO.isReg()) {
7240 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
7241 continue;
7242
7243 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7244 --LiteralLimit;
7245 --ConstantBusLimit;
7246 continue;
7247 }
7248
7249 --LiteralLimit;
7250 --ConstantBusLimit;
7251 legalizeOpWithMove(MI, Idx);
7252 continue;
7253 }
7254
7255 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
7256 continue; // VGPRs are legal
7257
7258 // We can use one SGPR in each VOP3 instruction prior to GFX10
7259 // and two starting from GFX10.
7260 if (SGPRsUsed.count(MO.getReg()))
7261 continue;
7262 if (ConstantBusLimit > 0) {
7263 SGPRsUsed.insert(MO.getReg());
7264 --ConstantBusLimit;
7265 continue;
7266 }
7267
7268 // If we make it this far, then the operand is not legal and we must
7269 // legalize it.
7270 legalizeOpWithMove(MI, Idx);
7271 }
7272
7273 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
7274 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
7275 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
7276 Opc == AMDGPU::V_FMAC_F16_t16_e64) &&
7277 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
7278 legalizeOpWithMove(MI, VOP3Idx[2]);
7279
7280 // Fix the register class of single-sgpr-read instructions on gfx12+. See
7281 // SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
7283 for (unsigned I = 0; I < 3; ++I) {
7284 if (!isLegalSingleSGPRReadInstOperand(MRI, MI, /*SrcN=*/I))
7285 legalizeOpWithMove(MI, VOP3Idx[I]);
7286 }
7287 }
7288}
7289
7292 const TargetRegisterClass *DstRC /*=nullptr*/) const {
7293 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
7294 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
7295 if (DstRC)
7296 SRC = RI.getCommonSubClass(SRC, DstRC);
7297
7298 Register DstReg = MRI.createVirtualRegister(SRC);
7299 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7300
7301 if (RI.hasAGPRs(VRC)) {
7302 VRC = RI.getEquivalentVGPRClass(VRC);
7303 Register NewSrcReg = MRI.createVirtualRegister(VRC);
7304 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7305 get(TargetOpcode::COPY), NewSrcReg)
7306 .addReg(SrcReg);
7307 SrcReg = NewSrcReg;
7308 }
7309
7310 if (SubRegs == 1) {
7311 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7312 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7313 .addReg(SrcReg);
7314 return DstReg;
7315 }
7316
7318 for (unsigned i = 0; i < SubRegs; ++i) {
7319 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7320 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7321 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7322 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7323 SRegs.push_back(SGPR);
7324 }
7325
7327 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7328 get(AMDGPU::REG_SEQUENCE), DstReg);
7329 for (unsigned i = 0; i < SubRegs; ++i) {
7330 MIB.addReg(SRegs[i]);
7331 MIB.addImm(RI.getSubRegFromChannel(i));
7332 }
7333 return DstReg;
7334}
7335
7337 MachineInstr &MI) const {
7338
7339 // If the pointer is store in VGPRs, then we need to move them to
7340 // SGPRs using v_readfirstlane. This is safe because we only select
7341 // loads with uniform pointers to SMRD instruction so we know the
7342 // pointer value is uniform.
7343 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
7344 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
7345 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
7346 SBase->setReg(SGPR);
7347 }
7348 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
7349 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
7350 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
7351 SOff->setReg(SGPR);
7352 }
7353}
7354
7356 unsigned Opc = Inst.getOpcode();
7357 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
7358 if (OldSAddrIdx < 0)
7359 return false;
7360
7361 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
7362
7363 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
7364 if (NewOpc < 0)
7366 if (NewOpc < 0)
7367 return false;
7368
7369 MachineRegisterInfo &MRI = Inst.getMF()->getRegInfo();
7370 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
7371 if (RI.isSGPRReg(MRI, SAddr.getReg()))
7372 return false;
7373
7374 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7375 if (NewVAddrIdx < 0)
7376 return false;
7377
7378 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
7379
7380 // Check vaddr, it shall be zero or absent.
7381 MachineInstr *VAddrDef = nullptr;
7382 if (OldVAddrIdx >= 0) {
7383 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
7384 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
7385 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
7386 !VAddrDef->getOperand(1).isImm() ||
7387 VAddrDef->getOperand(1).getImm() != 0)
7388 return false;
7389 }
7390
7391 const MCInstrDesc &NewDesc = get(NewOpc);
7392 Inst.setDesc(NewDesc);
7393
7394 // Callers expect iterator to be valid after this call, so modify the
7395 // instruction in place.
7396 if (OldVAddrIdx == NewVAddrIdx) {
7397 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
7398 // Clear use list from the old vaddr holding a zero register.
7399 MRI.removeRegOperandFromUseList(&NewVAddr);
7400 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7401 Inst.removeOperand(OldSAddrIdx);
7402 // Update the use list with the pointer we have just moved from vaddr to
7403 // saddr position. Otherwise new vaddr will be missing from the use list.
7404 MRI.removeRegOperandFromUseList(&NewVAddr);
7405 MRI.addRegOperandToUseList(&NewVAddr);
7406 } else {
7407 assert(OldSAddrIdx == NewVAddrIdx);
7408
7409 if (OldVAddrIdx >= 0) {
7410 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7411 AMDGPU::OpName::vdst_in);
7412
7413 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
7414 // it asserts. Untie the operands for now and retie them afterwards.
7415 if (NewVDstIn != -1) {
7416 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
7417 Inst.untieRegOperand(OldVDstIn);
7418 }
7419
7420 Inst.removeOperand(OldVAddrIdx);
7421
7422 if (NewVDstIn != -1) {
7423 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7424 Inst.tieOperands(NewVDst, NewVDstIn);
7425 }
7426 }
7427 }
7428
7429 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
7430 VAddrDef->eraseFromParent();
7431
7432 return true;
7433}
7434
7435// FIXME: Remove this when SelectionDAG is obsoleted.
7437 MachineInstr &MI) const {
7438 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
7439 return;
7440
7441 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
7442 // thinks they are uniform, so a readfirstlane should be valid.
7443 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
7444 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
7445 return;
7446
7448 return;
7449
7450 const TargetRegisterClass *DeclaredRC =
7451 getRegClass(MI.getDesc(), SAddr->getOperandNo());
7452
7453 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
7454 SAddr->setReg(ToSGPR);
7455}
7456
7459 const TargetRegisterClass *DstRC,
7462 const DebugLoc &DL) const {
7463 Register OpReg = Op.getReg();
7464 unsigned OpSubReg = Op.getSubReg();
7465
7466 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
7467 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7468
7469 // Check if operand is already the correct register class.
7470 if (DstRC == OpRC)
7471 return;
7472
7473 Register DstReg = MRI.createVirtualRegister(DstRC);
7474 auto Copy = BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg)
7475 .addReg(OpReg, {}, OpSubReg);
7476 Op.setReg(DstReg);
7477 Op.setSubReg(AMDGPU::NoSubRegister);
7478
7479 MachineInstr *Def = MRI.getVRegDef(OpReg);
7480 if (!Def)
7481 return;
7482
7483 // Try to eliminate the copy if it is copying an immediate value.
7484 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7485 foldImmediate(*Copy, *Def, OpReg, &MRI);
7486
7487 bool ImpDef = Def->isImplicitDef();
7488 while (!ImpDef && Def && Def->isCopy()) {
7489 if (Def->getOperand(1).getReg().isPhysical())
7490 break;
7491 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7492 ImpDef = Def && Def->isImplicitDef();
7493 }
7494 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7495 !ImpDef)
7496 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7497}
7498
7499// Emit the actual waterfall loop, executing the wrapped instruction for each
7500// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7501// iteration, in the worst case we execute 64 (once per lane).
7504 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7505 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7506 MachineFunction &MF = *LoopBB.getParent();
7508 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7510 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7511
7512 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7513 // available. Otherwise, use the previous pattern of v_cmp_eq,
7514 // s_and_saveexec, and s_xor.
7515 bool UseNewExecInstructions =
7516 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7517
7519 Register CondReg;
7520
7521 Register PhiExec;
7522 Register NewExec;
7523
7524 if (UseNewExecInstructions) {
7525 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7526 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7527 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7528 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7529 .addReg(LMC.ExecReg);
7530
7531 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7532 .addReg(InitExec)
7533 .addMBB(&PredBB)
7534 .addReg(NewExec)
7535 .addMBB(&BodyBB);
7536 }
7537
7538 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7539 // involves a trade-off between register pressure and latency:
7540 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7541 // register pressure because arguments and results of all
7542 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7543 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7544 // increase latency by placing v_readfirstlane instructions
7545 // immediately before v_cmpx instruction that directly depend on it.
7546 ///
7547 // Emitting interleaved v_cmpx and v_readfirstlane requires
7548 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7549 // v_cmpx needs to be treated as terminator until after register allocation
7550 // (spill placement) and instruction reordering.
7551 //
7552 // Current implementation defers v_cmpx and leaves other instruction
7553 // scheduling decisions to later passes, where register pressure is known or
7554 // easier to approximate.
7555 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7556 // v_cmpx instructions are inserted at the end of LoopBB.
7557 // After the first v_cmpx is emitted, I is updated to point to it
7558 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7559 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7560 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7561 unsigned NumSubRegs = RegSize / 32;
7562 Register VScalarOp = ScalarOp->getReg();
7563
7564 const TargetRegisterClass *RFLSrcRC =
7565 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7566
7567 if (NumSubRegs == 1) {
7568 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7569 if (const TargetRegisterClass *Common =
7570 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7571 Common != VScalarOpRC) {
7572 Register VRReg = MRI.createVirtualRegister(Common);
7573 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7574 VScalarOp = VRReg;
7575 }
7576 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7577
7578 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7579 .addReg(VScalarOp);
7580
7581 if (UseNewExecInstructions) {
7582 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7583 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7584 .addReg(CurReg)
7585 .addReg(VScalarOp);
7586 if (I == LoopBB.end())
7587 I = CmpxMI.getInstr()->getIterator();
7588 } else {
7589 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7590
7591 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7592 .addReg(CurReg)
7593 .addReg(VScalarOp);
7594
7595 // Combine the comparison results with AND.
7596 if (!CondReg) { // First.
7597 CondReg = NewCondReg;
7598 } else { // If not the first, we create an AND.
7599 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7600 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7601 .addReg(CondReg)
7602 .addReg(NewCondReg)
7603 .setOperandDead(3);
7604 CondReg = AndReg;
7605 }
7606 }
7607
7608 // Update ScalarOp operand to use the SGPR ScalarOp.
7609 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7610 ScalarOp->setReg(CurReg);
7611 else {
7612 // Insert into the same block of use
7613 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7614 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7615 .addReg(CurReg);
7616 ScalarOp->setReg(PhySGPRs[Idx]);
7617 }
7618 } else {
7619 SmallVector<Register, 8> ReadlanePieces;
7620 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7621 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7622 "Unhandled register size");
7623
7624 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7625 Register CurRegLo =
7626 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7627 Register CurRegHi =
7628 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7629
7630 // Read the next variant <- also loop target.
7631 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7632 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7633
7634 // Read the next variant <- also loop target.
7635 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7636 .addReg(VScalarOp, VScalarOpUndef,
7637 TRI->getSubRegFromChannel(Idx + 1));
7638
7639 ReadlanePieces.push_back(CurRegLo);
7640 ReadlanePieces.push_back(CurRegHi);
7641
7642 // Comparison is to be done as 64-bit.
7643 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7644 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7645 .addReg(CurRegLo)
7646 .addImm(AMDGPU::sub0)
7647 .addReg(CurRegHi)
7648 .addImm(AMDGPU::sub1);
7649
7650 unsigned SubReg =
7651 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7652
7653 if (UseNewExecInstructions) {
7654 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7655 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7656 .addReg(CurReg)
7657 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7658 if (I == LoopBB.end())
7659 I = CmpxMI.getInstr()->getIterator();
7660 } else {
7661 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7662 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7663 .addReg(CurReg)
7664 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7665
7666 // Combine the comparison results with AND.
7667 if (!CondReg) { // First.
7668 CondReg = NewCondReg;
7669 } else { // If not the first, we create an AND.
7670 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7671 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7672 .addReg(CondReg)
7673 .addReg(NewCondReg)
7674 .setOperandDead(3);
7675 CondReg = AndReg;
7676 }
7677 }
7678 } // End for loop.
7679
7680 const auto *SScalarOpRC =
7681 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7682 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7683
7684 // Build scalar ScalarOp.
7685 auto Merge =
7686 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7687 unsigned Channel = 0;
7688 for (Register Piece : ReadlanePieces) {
7689 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7690 }
7691
7692 // Update ScalarOp operand to use the SGPR ScalarOp.
7693 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7694 ScalarOp->setReg(SScalarOp);
7695 else {
7696 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7697 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7698 .addReg(SScalarOp);
7699 ScalarOp->setReg(PhySGPRs[Idx]);
7700 }
7701 }
7702 }
7703
7704 // AndSaveExecOpc modifies EXEC but can't be isTerminator=1: terminators
7705 // that define virtual registers aren't supported.
7706 Register SaveExec;
7707 if (!UseNewExecInstructions) {
7708 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7709 MRI.setSimpleHint(SaveExec, CondReg);
7710
7711 // Update EXEC to matching lanes, saving original to SaveExec.
7712 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7713 .addReg(CondReg)
7714 .setOperandDead(3);
7715 }
7716
7717 // The original instruction is here; we insert the terminators after it.
7718 I = BodyBB.end();
7719
7720 if (UseNewExecInstructions) {
7721 // Compute the remaining lanes into a plain virtual register and write EXEC
7722 // from a terminator, so spill code for NewExec is placed before EXEC
7723 // changes. SIOptimizeExecMasking opportunistically folds the pair back
7724 // into S_ANDN2_WREXEC after register allocation.
7725 MRI.setSimpleHint(NewExec, PhiExec);
7726 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2Opc), NewExec)
7727 .addReg(PhiExec)
7728 .addReg(LMC.ExecReg)
7729 .setOperandDead(3);
7730 BuildMI(BodyBB, I, DL, TII.get(LMC.MovTermOpc), LMC.ExecReg)
7731 .addReg(NewExec);
7732 } else {
7733 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7734 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7735 .addReg(LMC.ExecReg)
7736 .addReg(SaveExec)
7737 .setOperandDead(3);
7738 }
7739
7740 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7741}
7742
7743// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7744// with SGPRs by iterating over all unique values across all lanes.
7745// Returns the loop basic block that now contains \p MI.
7746static MachineBasicBlock *
7750 MachineBasicBlock::iterator Begin = nullptr,
7752 ArrayRef<Register> PhySGPRs = {}) {
7753 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7754 "Physical SGPRs must be empty or match the number of scalar operands");
7756 MachineFunction &MF = *MBB.getParent();
7758 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7759 MachineRegisterInfo &MRI = MF.getRegInfo();
7760 if (!Begin.isValid())
7761 Begin = &MI;
7762 if (!End.isValid()) {
7763 End = &MI;
7764 ++End;
7765 }
7766 const DebugLoc &DL = MI.getDebugLoc();
7768 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7769
7770 // Save SCC. Waterfall Loop may overwrite SCC.
7771 Register SaveSCCReg;
7772
7773 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7774 // rather than unlimited scan everywhere
7775 bool SCCNotDead =
7776 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7777 std::numeric_limits<unsigned>::max()) !=
7779 if (SCCNotDead) {
7780 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7781 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7782 .addImm(1)
7783 .addImm(0);
7784 }
7785
7786 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7787
7788 // Save the EXEC mask
7789 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7790
7791 // Killed uses in the instruction we are waterfalling around will be
7792 // incorrect due to the added control-flow.
7794 ++AfterMI;
7795 for (auto I = Begin; I != AfterMI; I++) {
7796 for (auto &MO : I->all_uses())
7797 MRI.clearKillFlags(MO.getReg());
7798 }
7799
7800 // To insert the loop we need to split the block. Move everything after this
7801 // point to a new block, and insert a new empty block between the two.
7804 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7806 ++MBBI;
7807
7808 MF.insert(MBBI, LoopBB);
7809 MF.insert(MBBI, BodyBB);
7810 MF.insert(MBBI, RemainderBB);
7811
7812 LoopBB->addSuccessor(BodyBB);
7813 BodyBB->addSuccessor(LoopBB);
7814 BodyBB->addSuccessor(RemainderBB);
7815
7816 // Move Begin to MI to the BodyBB, and the remainder of the block to
7817 // RemainderBB.
7818 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7819 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7820 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7821
7822 MBB.addSuccessor(LoopBB);
7823
7824 // Update dominators. We know that MBB immediately dominates LoopBB, that
7825 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7826 // RemainderBB. RemainderBB immediately dominates all of the successors
7827 // transferred to it from MBB that MBB used to properly dominate.
7828 if (MDT) {
7829 MDT->addNewBlock(LoopBB, &MBB);
7830 MDT->addNewBlock(BodyBB, LoopBB);
7831 MDT->addNewBlock(RemainderBB, BodyBB);
7832 for (auto &Succ : RemainderBB->successors()) {
7833 if (MDT->properlyDominates(&MBB, Succ)) {
7834 MDT->changeImmediateDominator(Succ, RemainderBB);
7835 }
7836 }
7837 }
7838
7839 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7840 PhySGPRs);
7841
7842 MachineBasicBlock::iterator First = RemainderBB->begin();
7843 // Restore SCC
7844 if (SCCNotDead) {
7845 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7846 .addReg(SaveSCCReg)
7847 .addImm(0);
7848 }
7849
7850 // Restore the EXEC mask
7851 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7852 .addReg(SaveExec);
7853 return BodyBB;
7854}
7855
7856// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7857static std::tuple<unsigned, unsigned>
7859 MachineBasicBlock &MBB = *MI.getParent();
7860 MachineFunction &MF = *MBB.getParent();
7861 MachineRegisterInfo &MRI = MF.getRegInfo();
7862
7863 // Extract the ptr from the resource descriptor.
7864 unsigned RsrcPtr =
7865 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7866 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7867
7868 // Create an empty resource descriptor
7869 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7870 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7871 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7872 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7873 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7874
7875 // Zero64 = 0
7876 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7877 .addImm(0);
7878
7879 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7880 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7881 .addImm(Lo_32(RsrcDataFormat));
7882
7883 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7884 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7885 .addImm(Hi_32(RsrcDataFormat));
7886
7887 // NewSRsrc = {Zero64, SRsrcFormat}
7888 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7889 .addReg(Zero64)
7890 .addImm(AMDGPU::sub0_sub1)
7891 .addReg(SRsrcFormatLo)
7892 .addImm(AMDGPU::sub2)
7893 .addReg(SRsrcFormatHi)
7894 .addImm(AMDGPU::sub3);
7895
7896 return std::tuple(RsrcPtr, NewSRsrc);
7897}
7898
7901 MachineDominatorTree *MDT) const {
7902 MachineFunction &MF = *MI.getMF();
7903 MachineRegisterInfo &MRI = MF.getRegInfo();
7904 MachineBasicBlock *CreatedBB = nullptr;
7905
7906 // Legalize True16
7907 if (ST.useRealTrue16Insts())
7909
7910 // Legalize VOP2
7911 if (isVOP2(MI) || isVOPC(MI)) {
7913 return CreatedBB;
7914 }
7915
7916 // Legalize VOP3
7917 if (isVOP3(MI)) {
7919 return CreatedBB;
7920 }
7921
7922 // Legalize SMRD
7923 if (isSMRD(MI)) {
7925 return CreatedBB;
7926 }
7927
7928 // Legalize FLAT
7929 if (isFLAT(MI)) {
7931 return CreatedBB;
7932 }
7933
7934 // Legalize PHI
7935 // The register class of the operands must be the same type as the register
7936 // class of the output.
7937 if (MI.getOpcode() == AMDGPU::PHI) {
7938 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7939 assert(!RI.isSGPRClass(VRC));
7940
7941 // Update all the operands so they have the same type.
7942 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7943 MachineOperand &Op = MI.getOperand(I);
7944 if (!Op.isReg() || !Op.getReg().isVirtual())
7945 continue;
7946
7947 // MI is a PHI instruction.
7948 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7950
7951 // Avoid creating no-op copies with the same src and dst reg class. These
7952 // confuse some of the machine passes.
7953 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7954 }
7955 }
7956
7957 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7958 // VGPR dest type and SGPR sources, insert copies so all operands are
7959 // VGPRs. This seems to help operand folding / the register coalescer.
7960 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7961 MachineBasicBlock *MBB = MI.getParent();
7962 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7963 if (RI.hasVGPRs(DstRC)) {
7964 // Update all the operands so they are VGPR register classes. These may
7965 // not be the same register class because REG_SEQUENCE supports mixing
7966 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7967 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7968 MachineOperand &Op = MI.getOperand(I);
7969 if (!Op.isReg() || !Op.getReg().isVirtual())
7970 continue;
7971
7972 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7973 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7974 if (VRC == OpRC)
7975 continue;
7976
7977 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7978 }
7979 }
7980
7981 return CreatedBB;
7982 }
7983
7984 // Legalize INSERT_SUBREG
7985 // src0 must have the same register class as dst
7986 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7987 Register Dst = MI.getOperand(0).getReg();
7988 Register Src0 = MI.getOperand(1).getReg();
7989 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7990 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7991 if (DstRC != Src0RC) {
7992 MachineBasicBlock *MBB = MI.getParent();
7993 MachineOperand &Op = MI.getOperand(1);
7994 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7995 }
7996 return CreatedBB;
7997 }
7998
7999 // Legalize SI_INIT_M0
8000 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
8001 MachineOperand &Src = MI.getOperand(0);
8002 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
8003 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
8004 return CreatedBB;
8005 }
8006
8007 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
8008 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
8009 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
8010 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
8011 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
8012 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
8013 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
8014 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
8015 MachineOperand &Src = MI.getOperand(1);
8016 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
8017 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
8018 return CreatedBB;
8019 }
8020
8021 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
8022 //
8023 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
8024 // scratch memory access. In both cases, the legalization never involves
8025 // conversion to the addr64 form.
8027 (isMUBUF(MI) || isMTBUF(MI)))) {
8028 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
8029 ? AMDGPU::OpName::rsrc
8030 : AMDGPU::OpName::srsrc;
8031 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
8032 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
8033 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
8034
8035 AMDGPU::OpName SampOpName =
8036 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
8037 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
8038 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
8039 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
8040
8041 return CreatedBB;
8042 }
8043
8044 // Legalize SI_CALL
8045 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
8046 MachineOperand *Dest = &MI.getOperand(0);
8047 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
8048 createWaterFallForSiCall(&MI, MDT, {Dest});
8049 }
8050 }
8051
8052 // Legalize s_sleep_var.
8053 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
8054 const DebugLoc &DL = MI.getDebugLoc();
8055 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8056 int Src0Idx =
8057 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
8058 MachineOperand &Src0 = MI.getOperand(Src0Idx);
8059 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
8060 .add(Src0);
8061 Src0.ChangeToRegister(Reg, false);
8062 return nullptr;
8063 }
8064
8065 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
8066 // operands are scalar.
8067 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
8068 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
8069 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
8070 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
8071 for (MachineOperand &Src : MI.explicit_operands()) {
8072 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
8073 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
8074 }
8075 return CreatedBB;
8076 }
8077
8078 // Legalize MUBUF instructions.
8079 bool isSoffsetLegal = true;
8080 int SoffsetIdx =
8081 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
8082 if (SoffsetIdx != -1) {
8083 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
8084 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
8085 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
8086 isSoffsetLegal = false;
8087 }
8088 }
8089
8090 bool isRsrcLegal = true;
8091 int RsrcIdx =
8092 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
8093 if (RsrcIdx != -1) {
8094 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
8095 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
8096 isRsrcLegal = false;
8097 }
8098
8099 // The operands are legal.
8100 if (isRsrcLegal && isSoffsetLegal)
8101 return CreatedBB;
8102
8103 if (!isRsrcLegal) {
8104 // Legalize a VGPR Rsrc
8105 //
8106 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
8107 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
8108 // a zero-value SRsrc.
8109 //
8110 // If the instruction is _OFFSET (both idxen and offen disabled), and we
8111 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
8112 // above.
8113 //
8114 // Otherwise we are on non-ADDR64 hardware, and/or we have
8115 // idxen/offen/bothen and we fall back to a waterfall loop.
8116
8117 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
8118 MachineBasicBlock &MBB = *MI.getParent();
8119
8120 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
8121 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
8122 // This is already an ADDR64 instruction so we need to add the pointer
8123 // extracted from the resource descriptor to the current value of VAddr.
8124 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8125 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8126 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8127
8128 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
8129 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
8130 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
8131
8132 unsigned RsrcPtr, NewSRsrc;
8133 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
8134
8135 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
8136 const DebugLoc &DL = MI.getDebugLoc();
8137 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
8138 .addDef(CondReg0)
8139 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8140 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
8141 .addImm(0);
8142
8143 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
8144 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
8145 .addDef(CondReg1, RegState::Dead)
8146 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8147 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
8148 .addReg(CondReg0)
8149 .addImm(0);
8150
8151 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8152 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
8153 .addReg(NewVAddrLo)
8154 .addImm(AMDGPU::sub0)
8155 .addReg(NewVAddrHi)
8156 .addImm(AMDGPU::sub1);
8157
8158 VAddr->setReg(NewVAddr);
8159 Rsrc->setReg(NewSRsrc);
8160 } else if (!VAddr && ST.hasAddr64()) {
8161 // This instructions is the _OFFSET variant, so we need to convert it to
8162 // ADDR64.
8163 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
8164 "FIXME: Need to emit flat atomics here");
8165
8166 unsigned RsrcPtr, NewSRsrc;
8167 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
8168
8169 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8170 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
8171 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
8172 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8173 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
8174
8175 // Atomics with return have an additional tied operand and are
8176 // missing some of the special bits.
8177 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
8178 MachineInstr *Addr64;
8179
8180 if (!VDataIn) {
8181 // Regular buffer load / store.
8183 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
8184 .add(*VData)
8185 .addReg(NewVAddr)
8186 .addReg(NewSRsrc)
8187 .add(*SOffset)
8188 .add(*Offset);
8189
8190 if (const MachineOperand *CPol =
8191 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
8192 MIB.addImm(CPol->getImm());
8193 }
8194
8195 if (const MachineOperand *TFE =
8196 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
8197 MIB.addImm(TFE->getImm());
8198 }
8199
8200 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
8201
8202 MIB.cloneMemRefs(MI);
8203 Addr64 = MIB;
8204 } else {
8205 // Atomics with return.
8206 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
8207 .add(*VData)
8208 .add(*VDataIn)
8209 .addReg(NewVAddr)
8210 .addReg(NewSRsrc)
8211 .add(*SOffset)
8212 .add(*Offset)
8213 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
8214 .cloneMemRefs(MI);
8215 }
8216
8217 MI.removeFromParent();
8218
8219 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8220 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
8221 NewVAddr)
8222 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8223 .addImm(AMDGPU::sub0)
8224 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8225 .addImm(AMDGPU::sub1);
8226 } else {
8227 // Legalize a VGPR Rsrc and soffset together.
8228 if (!isSoffsetLegal) {
8229 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8230 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
8231 return CreatedBB;
8232 }
8233 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
8234 return CreatedBB;
8235 }
8236 }
8237
8238 // Legalize a VGPR soffset.
8239 if (!isSoffsetLegal) {
8240 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8241 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
8242 return CreatedBB;
8243 }
8244 return CreatedBB;
8245}
8246
8248 if (InSet.insert(MI).second)
8249 InstrList.push_back(MI);
8250 // Add MBUF instructiosn to deferred list.
8251 int RsrcIdx =
8252 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
8253 if (RsrcIdx != -1) {
8254 DeferredList.insert(MI);
8255 }
8256}
8257
8259 return DeferredList.contains(MI);
8260}
8261
8262// Legalize size mismatches between 16bit and 32bit registers in v2s copy
8263// lowering (change sgpr to vgpr).
8264// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
8265// size. Need to legalize the size of the operands during the vgpr lowering
8266// chain. This can be removed after we have sgpr16 in place
8268 MachineRegisterInfo &MRI) const {
8269 if (!ST.useRealTrue16Insts())
8270 return;
8271
8272 unsigned Opcode = MI.getOpcode();
8273 MachineBasicBlock *MBB = MI.getParent();
8274 // Legalize operands and check for size mismatch
8275 if (OpIdx >= MI.getNumExplicitOperands() ||
8276 OpIdx >= get(Opcode).getNumOperands() ||
8277 get(Opcode).operands()[OpIdx].RegClass == -1)
8278 return;
8279
8280 MachineOperand &Op = MI.getOperand(OpIdx);
8281 if (!Op.isReg() || !Op.getReg().isVirtual() || Op.isDef())
8282 return;
8283
8284 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
8285 if (!RI.isVGPRClass(CurrRC))
8286 return;
8287
8288 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
8289 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
8290 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8291 // Default to the lo16 only if the subregister is not specified.
8292 if (Op.getSubReg() == AMDGPU::NoSubRegister)
8293 Op.setSubReg(AMDGPU::lo16);
8294 return;
8295 }
8296
8297 const TargetRegisterClass *CurrSRC =
8298 RI.getSubRegisterClass(CurrRC, Op.getSubReg());
8299 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8300 const DebugLoc &DL = MI.getDebugLoc();
8301 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8302 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8303 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
8304 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
8305 .addReg(Op.getReg(), {}, Op.getSubReg())
8306 .addImm(AMDGPU::lo16)
8307 .addReg(Undef)
8308 .addImm(AMDGPU::hi16);
8309 Op.setReg(NewDstReg);
8310 Op.setSubReg(AMDGPU::NoSubRegister);
8311 }
8312}
8314 MachineRegisterInfo &MRI) const {
8315 for (unsigned OpIdx = 0; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
8316 legalizeOperandsVALUt16(MI, OpIdx, MRI);
8317}
8318
8322 ArrayRef<Register> PhySGPRs) const {
8323 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8324 "This only handle waterfall for SI_CALL_ISEL");
8325 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
8326 // following copies, we also need to move copies from and to physical
8327 // registers into the loop block.
8328 // Also move the copies to physical registers into the loop block
8329 MachineBasicBlock &MBB = *MI->getParent();
8331 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8332 --Start;
8334 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8335 ++End;
8336
8337 // Also include following copies of the return value
8338 ++End;
8339 while (End != MBB.end() && End->isCopy() &&
8340 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8341 ++End;
8342
8343 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
8344}
8345
8347 MachineDominatorTree *MDT) const {
8349 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
8350 while (!Worklist.empty()) {
8351 MachineInstr &Inst = *Worklist.top();
8352 Worklist.erase_top();
8353 // Skip MachineInstr in the deferred list.
8354 if (Worklist.isDeferred(&Inst))
8355 continue;
8356 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8357 }
8358
8359 // Deferred list of instructions will be processed once
8360 // all the MachineInstr in the worklist are done.
8361 for (MachineInstr *Inst : Worklist.getDeferredList()) {
8362 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8363 assert(Worklist.empty() &&
8364 "Deferred MachineInstr are not supposed to re-populate worklist");
8365 }
8366
8367 for (auto &Entry : WaterFalls) {
8368 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8369 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
8370 Entry.second.SGPRs);
8371 }
8372
8373 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8374 if (Entry.second)
8375 Entry.first->eraseFromParent();
8376}
8378 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
8379 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
8380 // hope for the best.
8381 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
8382 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
8383 if (SubRegIndices.size() <= 1) {
8384 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8385 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8386 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8387 .add(Inst.getOperand(1));
8388 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
8389 DstReg)
8390 .addReg(NewDst);
8391 } else {
8393 for (int16_t Indice : SubRegIndices) {
8394 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8395 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8396 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8397 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
8398
8399 DstRegs.push_back(NewDst);
8400 }
8402 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8403 get(AMDGPU::REG_SEQUENCE), DstReg);
8404 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
8405 MIB.addReg(DstRegs[i]);
8406 MIB.addImm(RI.getSubRegFromChannel(i));
8407 }
8408 }
8409}
8410
8412 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
8415 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8416 if (DstReg == AMDGPU::M0) {
8417 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8418 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8419 return;
8420 }
8421 Register SrcReg = Inst.getOperand(1).getReg();
8424 // Only search current block since phyreg's def & use cannot cross
8425 // blocks when MF.NoPhi = false.
8426 while (++I != E) {
8427 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
8428 // and record the operand for later waterfall loop generation.
8429 if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8430 MachineInstr *UseMI = &*I;
8431 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
8432 if (UseMI->getOperand(i).isReg() &&
8433 UseMI->getOperand(i).getReg() == DstReg) {
8434 MachineOperand *MO = &UseMI->getOperand(i);
8435 MO->setReg(SrcReg);
8436 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
8437 V2SCopyInfo.MOs.push_back(MO);
8438 V2SCopyInfo.SGPRs.push_back(DstReg);
8439 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8440 }
8441 }
8442 } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8443 I->getOperand(0).isReg() &&
8444 I->getOperand(0).getReg() == DstReg) {
8445 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8446 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8447 } else if (I->readsRegister(DstReg, &RI)) {
8448 // COPY cannot be erased if other type of inst uses it.
8449 V2SPhyCopiesToErase[&Inst] = false;
8450 }
8451 if (I->findRegisterDefOperand(DstReg, &RI))
8452 break;
8453 }
8454}
8455
8457 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
8459 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8460
8462 if (!MBB)
8463 return;
8464 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
8465 unsigned Opcode = Inst.getOpcode();
8466 unsigned NewOpcode = getVALUOp(Inst);
8467 const DebugLoc &DL = Inst.getDebugLoc();
8468
8469 // Handle some special cases
8470 switch (Opcode) {
8471 default:
8472 break;
8473 case AMDGPU::S_ADD_I32:
8474 case AMDGPU::S_SUB_I32: {
8475 // FIXME: The u32 versions currently selected use the carry.
8476 bool Changed;
8477 MachineBasicBlock *CreatedBBTmp = nullptr;
8478 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8479 if (Changed)
8480 return;
8481
8482 // Default handling
8483 break;
8484 }
8485
8486 case AMDGPU::S_MUL_U64:
8487 if (ST.useVMulU64Inst()) {
8488 NewOpcode = AMDGPU::V_MUL_U64_e64;
8489 break;
8490 }
8491 // Split s_mul_u64 in 32-bit vector multiplications.
8492 splitScalarSMulU64(Worklist, Inst, MDT);
8493 Inst.eraseFromParent();
8494 return;
8495
8496 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8497 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8498 // This is a special case of s_mul_u64 where all the operands are either
8499 // zero extended or sign extended.
8500 splitScalarSMulPseudo(Worklist, Inst, MDT);
8501 Inst.eraseFromParent();
8502 return;
8503
8504 case AMDGPU::S_AND_B64:
8505 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8506 Inst.eraseFromParent();
8507 return;
8508
8509 case AMDGPU::S_OR_B64:
8510 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8511 Inst.eraseFromParent();
8512 return;
8513
8514 case AMDGPU::S_XOR_B64:
8515 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8516 Inst.eraseFromParent();
8517 return;
8518
8519 case AMDGPU::S_NAND_B64:
8520 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8521 Inst.eraseFromParent();
8522 return;
8523
8524 case AMDGPU::S_NOR_B64:
8525 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8526 Inst.eraseFromParent();
8527 return;
8528
8529 case AMDGPU::S_XNOR_B64:
8530 if (ST.hasDLInsts())
8531 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8532 else
8533 splitScalar64BitXnor(Worklist, Inst, MDT);
8534 Inst.eraseFromParent();
8535 return;
8536
8537 case AMDGPU::S_ANDN2_B64:
8538 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8539 Inst.eraseFromParent();
8540 return;
8541
8542 case AMDGPU::S_ORN2_B64:
8543 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8544 Inst.eraseFromParent();
8545 return;
8546
8547 case AMDGPU::S_BREV_B64:
8548 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8549 Inst.eraseFromParent();
8550 return;
8551
8552 case AMDGPU::S_NOT_B64:
8553 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8554 Inst.eraseFromParent();
8555 return;
8556
8557 case AMDGPU::S_BCNT1_I32_B64:
8558 splitScalar64BitBCNT(Worklist, Inst);
8559 Inst.eraseFromParent();
8560 return;
8561
8562 case AMDGPU::S_BFE_I64:
8563 splitScalar64BitBFE(Worklist, Inst);
8564 Inst.eraseFromParent();
8565 return;
8566
8567 case AMDGPU::S_FLBIT_I32_B64:
8568 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8569 Inst.eraseFromParent();
8570 return;
8571 case AMDGPU::S_FF1_I32_B64:
8572 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8573 Inst.eraseFromParent();
8574 return;
8575
8576 case AMDGPU::S_LSHL_B32:
8577 if (ST.hasOnlyRevVALUShifts()) {
8578 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8579 swapOperands(Inst);
8580 }
8581 break;
8582 case AMDGPU::S_ASHR_I32:
8583 if (ST.hasOnlyRevVALUShifts()) {
8584 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8585 swapOperands(Inst);
8586 }
8587 break;
8588 case AMDGPU::S_LSHR_B32:
8589 if (ST.hasOnlyRevVALUShifts()) {
8590 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8591 swapOperands(Inst);
8592 }
8593 break;
8594 case AMDGPU::S_LSHL_B64:
8595 if (ST.hasOnlyRevVALUShifts()) {
8596 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8597 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8598 : AMDGPU::V_LSHLREV_B64_e64;
8599 swapOperands(Inst);
8600 }
8601 break;
8602 case AMDGPU::S_ASHR_I64:
8603 if (ST.hasOnlyRevVALUShifts()) {
8604 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8605 swapOperands(Inst);
8606 }
8607 break;
8608 case AMDGPU::S_LSHR_B64:
8609 if (ST.hasOnlyRevVALUShifts()) {
8610 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8611 swapOperands(Inst);
8612 }
8613 break;
8614
8615 case AMDGPU::S_ABS_I32:
8616 lowerScalarAbs(Worklist, Inst);
8617 Inst.eraseFromParent();
8618 return;
8619
8620 case AMDGPU::S_ABSDIFF_I32:
8621 lowerScalarAbsDiff(Worklist, Inst);
8622 Inst.eraseFromParent();
8623 return;
8624
8625 case AMDGPU::S_CBRANCH_SCC0:
8626 case AMDGPU::S_CBRANCH_SCC1: {
8627 // Clear unused bits of vcc
8628 Register CondReg = Inst.getOperand(1).getReg();
8629 bool IsSCC = CondReg == AMDGPU::SCC;
8631 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8632 .addReg(LMC.ExecReg)
8633 .addReg(IsSCC ? LMC.VccReg : CondReg)
8634 .setOperandDead(3); // implicit-def $scc
8635 Inst.removeOperand(1);
8636 } break;
8637
8638 case AMDGPU::S_BFE_U64:
8639 case AMDGPU::S_BFM_B64:
8640 llvm_unreachable("Moving this op to VALU not implemented");
8641
8642 case AMDGPU::S_PACK_LL_B32_B16:
8643 case AMDGPU::S_PACK_LH_B32_B16:
8644 case AMDGPU::S_PACK_HL_B32_B16:
8645 case AMDGPU::S_PACK_HH_B32_B16:
8646 movePackToVALU(Worklist, MRI, Inst);
8647 Inst.eraseFromParent();
8648 return;
8649
8650 case AMDGPU::S_XNOR_B32:
8651 lowerScalarXnor(Worklist, Inst);
8652 Inst.eraseFromParent();
8653 return;
8654
8655 case AMDGPU::S_NAND_B32:
8656 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8657 Inst.eraseFromParent();
8658 return;
8659
8660 case AMDGPU::S_NOR_B32:
8661 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8662 Inst.eraseFromParent();
8663 return;
8664
8665 case AMDGPU::S_ANDN2_B32:
8666 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8667 Inst.eraseFromParent();
8668 return;
8669
8670 case AMDGPU::S_ORN2_B32:
8671 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8672 Inst.eraseFromParent();
8673 return;
8674
8675 // TODO: remove as soon as everything is ready
8676 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8677 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8678 // can only be selected from the uniform SDNode.
8679 case AMDGPU::S_ADD_CO_PSEUDO:
8680 case AMDGPU::S_SUB_CO_PSEUDO: {
8681 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8682 ? AMDGPU::V_ADDC_U32_e64
8683 : AMDGPU::V_SUBB_U32_e64;
8684 const auto *CarryRC = RI.getWaveMaskRegClass();
8685
8686 Register CarryInReg = Inst.getOperand(4).getReg();
8687 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8688 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8689 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8690 .addReg(CarryInReg);
8691 }
8692
8693 Register CarryOutReg = Inst.getOperand(1).getReg();
8694
8695 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8696 MRI.getRegClass(Inst.getOperand(0).getReg())));
8697 MachineInstr *CarryOp =
8698 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8699 .addReg(CarryOutReg, RegState::Define)
8700 .add(Inst.getOperand(2))
8701 .add(Inst.getOperand(3))
8702 .addReg(CarryInReg)
8703 .addImm(0);
8704 legalizeOperands(*CarryOp);
8705 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8706 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8707 Inst.eraseFromParent();
8708 }
8709 return;
8710 case AMDGPU::S_UADDO_PSEUDO:
8711 case AMDGPU::S_USUBO_PSEUDO: {
8712 MachineOperand &Dest0 = Inst.getOperand(0);
8713 MachineOperand &Dest1 = Inst.getOperand(1);
8714 MachineOperand &Src0 = Inst.getOperand(2);
8715 MachineOperand &Src1 = Inst.getOperand(3);
8716
8717 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8718 ? AMDGPU::V_ADD_CO_U32_e64
8719 : AMDGPU::V_SUB_CO_U32_e64;
8720 const TargetRegisterClass *NewRC =
8721 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8722 Register DestReg = MRI.createVirtualRegister(NewRC);
8723 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8724 .addReg(Dest1.getReg(), RegState::Define)
8725 .add(Src0)
8726 .add(Src1)
8727 .addImm(0); // clamp bit
8728
8729 legalizeOperands(*NewInstr, MDT);
8730 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8731 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8732 Inst.eraseFromParent();
8733 }
8734 return;
8735 case AMDGPU::S_LSHL1_ADD_U32:
8736 case AMDGPU::S_LSHL2_ADD_U32:
8737 case AMDGPU::S_LSHL3_ADD_U32:
8738 case AMDGPU::S_LSHL4_ADD_U32: {
8739 MachineOperand &Dest = Inst.getOperand(0);
8740 MachineOperand &Src0 = Inst.getOperand(1);
8741 MachineOperand &Src1 = Inst.getOperand(2);
8742 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8743 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8744 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8745 : 4);
8746
8747 const TargetRegisterClass *NewRC =
8748 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8749 Register DestReg = MRI.createVirtualRegister(NewRC);
8750 MachineInstr *NewInstr =
8751 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8752 .add(Src0)
8753 .addImm(ShiftAmt)
8754 .add(Src1);
8755
8756 legalizeOperands(*NewInstr, MDT);
8757 MRI.replaceRegWith(Dest.getReg(), DestReg);
8758 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8759 Inst.eraseFromParent();
8760 }
8761 return;
8762 case AMDGPU::S_CSELECT_B32:
8763 case AMDGPU::S_CSELECT_B64:
8764 lowerSelect(Worklist, Inst, MDT);
8765 Inst.eraseFromParent();
8766 return;
8767 case AMDGPU::S_CMP_EQ_I32:
8768 case AMDGPU::S_CMP_LG_I32:
8769 case AMDGPU::S_CMP_GT_I32:
8770 case AMDGPU::S_CMP_GE_I32:
8771 case AMDGPU::S_CMP_LT_I32:
8772 case AMDGPU::S_CMP_LE_I32:
8773 case AMDGPU::S_CMP_EQ_U32:
8774 case AMDGPU::S_CMP_LG_U32:
8775 case AMDGPU::S_CMP_GT_U32:
8776 case AMDGPU::S_CMP_GE_U32:
8777 case AMDGPU::S_CMP_LT_U32:
8778 case AMDGPU::S_CMP_LE_U32:
8779 case AMDGPU::S_CMP_EQ_U64:
8780 case AMDGPU::S_CMP_LG_U64:
8781 case AMDGPU::S_CMP_LT_F32:
8782 case AMDGPU::S_CMP_EQ_F32:
8783 case AMDGPU::S_CMP_LE_F32:
8784 case AMDGPU::S_CMP_GT_F32:
8785 case AMDGPU::S_CMP_LG_F32:
8786 case AMDGPU::S_CMP_GE_F32:
8787 case AMDGPU::S_CMP_O_F32:
8788 case AMDGPU::S_CMP_U_F32:
8789 case AMDGPU::S_CMP_NGE_F32:
8790 case AMDGPU::S_CMP_NLG_F32:
8791 case AMDGPU::S_CMP_NGT_F32:
8792 case AMDGPU::S_CMP_NLE_F32:
8793 case AMDGPU::S_CMP_NEQ_F32:
8794 case AMDGPU::S_CMP_NLT_F32: {
8795 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8796 auto NewInstr =
8797 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8798 .setMIFlags(Inst.getFlags());
8799 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8800 0) {
8801 NewInstr
8802 .addImm(0) // src0_modifiers
8803 .add(Inst.getOperand(0)) // src0
8804 .addImm(0) // src1_modifiers
8805 .add(Inst.getOperand(1)) // src1
8806 .addImm(0); // clamp
8807 } else {
8808 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8809 }
8810 legalizeOperands(*NewInstr, MDT);
8811 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8812 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8813 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8814 Inst.eraseFromParent();
8815 return;
8816 }
8817 case AMDGPU::S_CMP_LT_F16:
8818 case AMDGPU::S_CMP_EQ_F16:
8819 case AMDGPU::S_CMP_LE_F16:
8820 case AMDGPU::S_CMP_GT_F16:
8821 case AMDGPU::S_CMP_LG_F16:
8822 case AMDGPU::S_CMP_GE_F16:
8823 case AMDGPU::S_CMP_O_F16:
8824 case AMDGPU::S_CMP_U_F16:
8825 case AMDGPU::S_CMP_NGE_F16:
8826 case AMDGPU::S_CMP_NLG_F16:
8827 case AMDGPU::S_CMP_NGT_F16:
8828 case AMDGPU::S_CMP_NLE_F16:
8829 case AMDGPU::S_CMP_NEQ_F16:
8830 case AMDGPU::S_CMP_NLT_F16: {
8831 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8832 auto NewInstr =
8833 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8834 .setMIFlags(Inst.getFlags());
8835 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8836 NewInstr
8837 .addImm(0) // src0_modifiers
8838 .add(Inst.getOperand(0)) // src0
8839 .addImm(0) // src1_modifiers
8840 .add(Inst.getOperand(1)) // src1
8841 .addImm(0); // clamp
8842 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8843 NewInstr.addImm(0); // op_sel0
8844 } else {
8845 NewInstr
8846 .add(Inst.getOperand(0))
8847 .add(Inst.getOperand(1));
8848 }
8849 legalizeOperands(*NewInstr, MDT);
8850 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8851 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8852 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8853 Inst.eraseFromParent();
8854 return;
8855 }
8856 case AMDGPU::S_CVT_HI_F32_F16: {
8857 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8858 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8859 if (ST.useRealTrue16Insts()) {
8860 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8861 .add(Inst.getOperand(1));
8862 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8863 .addImm(0) // src0_modifiers
8864 .addReg(TmpReg, {}, AMDGPU::hi16)
8865 .addImm(0) // clamp
8866 .addImm(0) // omod
8867 .addImm(0); // op_sel0
8868 } else {
8869 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8870 .addImm(16)
8871 .add(Inst.getOperand(1));
8872 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8873 .addImm(0) // src0_modifiers
8874 .addReg(TmpReg)
8875 .addImm(0) // clamp
8876 .addImm(0); // omod
8877 }
8878
8879 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8880 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8881 Inst.eraseFromParent();
8882 return;
8883 }
8884 case AMDGPU::S_MINIMUM_F32:
8885 case AMDGPU::S_MAXIMUM_F32: {
8886 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8887 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8888 .addImm(0) // src0_modifiers
8889 .add(Inst.getOperand(1))
8890 .addImm(0) // src1_modifiers
8891 .add(Inst.getOperand(2))
8892 .addImm(0) // clamp
8893 .addImm(0); // omod
8894 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8895
8896 legalizeOperands(*NewInstr, MDT);
8897 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8898 Inst.eraseFromParent();
8899 return;
8900 }
8901 case AMDGPU::S_MINIMUM_F16:
8902 case AMDGPU::S_MAXIMUM_F16: {
8903 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8904 ? &AMDGPU::VGPR_16RegClass
8905 : &AMDGPU::VGPR_32RegClass);
8906 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8907 .addImm(0) // src0_modifiers
8908 .add(Inst.getOperand(1))
8909 .addImm(0) // src1_modifiers
8910 .add(Inst.getOperand(2))
8911 .addImm(0) // clamp
8912 .addImm(0) // omod
8913 .addImm(0); // opsel0
8914 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8915 legalizeOperands(*NewInstr, MDT);
8916 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8917 Inst.eraseFromParent();
8918 return;
8919 }
8920 case AMDGPU::V_S_EXP_F16_e64:
8921 case AMDGPU::V_S_LOG_F16_e64:
8922 case AMDGPU::V_S_RCP_F16_e64:
8923 case AMDGPU::V_S_RSQ_F16_e64:
8924 case AMDGPU::V_S_SQRT_F16_e64: {
8925 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8926 ? &AMDGPU::VGPR_16RegClass
8927 : &AMDGPU::VGPR_32RegClass);
8928 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8929 .add(Inst.getOperand(1)) // src0_modifiers
8930 .add(Inst.getOperand(2))
8931 .add(Inst.getOperand(3)) // clamp
8932 .add(Inst.getOperand(4)) // omod
8933 .setMIFlags(Inst.getFlags());
8934 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8935 NewInstr.addImm(0); // opsel0
8936 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8937 legalizeOperands(*NewInstr, MDT);
8938 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8939 Inst.eraseFromParent();
8940 return;
8941 }
8942 }
8943
8944 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8945 // We cannot move this instruction to the VALU, so we should try to
8946 // legalize its operands instead.
8947 legalizeOperands(Inst, MDT);
8948 return;
8949 }
8950 // Handle converting generic instructions like COPY-to-SGPR into
8951 // COPY-to-VGPR.
8952 if (NewOpcode == Opcode) {
8953 Register DstReg = Inst.getOperand(0).getReg();
8954 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8955
8956 if (Inst.isCopy() && DstReg.isPhysical() &&
8957 Inst.getOperand(1).getReg().isVirtual()) {
8958 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8959 V2SPhyCopiesToErase);
8960 return;
8961 }
8962
8963 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8964 Register NewDstReg = Inst.getOperand(1).getReg();
8965 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8966 if (const TargetRegisterClass *CommonRC =
8967 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8968 // Instead of creating a copy where src and dst are the same register
8969 // class, we just replace all uses of dst with src. These kinds of
8970 // copies interfere with the heuristics MachineSink uses to decide
8971 // whether or not to split a critical edge. Since the pass assumes
8972 // that copies will end up as machine instructions and not be
8973 // eliminated.
8974 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8975 unsigned SrcSubReg = Inst.getOperand(1).getSubReg();
8976 bool IsUndef = Inst.getOperand(1).isUndef();
8977 for (MachineOperand &UseMO :
8978 make_early_inc_range(MRI.use_operands(DstReg))) {
8979 UseMO.setSubReg(
8980 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8981 UseMO.setReg(NewDstReg);
8982 if (IsUndef)
8983 UseMO.setIsUndef();
8984 }
8985 MRI.clearKillFlags(NewDstReg);
8986
8987 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8988 llvm_unreachable("failed to constrain register");
8989
8990 Inst.eraseFromParent();
8991
8992 for (MachineOperand &UseMO :
8993 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8994 MachineInstr &UseMI = *UseMO.getParent();
8995
8996 // Legalize t16 operands since replaceReg is called after
8997 // addUsersToVALU.
8999
9000 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
9001 if (const TargetRegisterClass *OpRC =
9002 getRegClass(UseMI.getDesc(), OpIdx))
9003 MRI.constrainRegClass(NewDstReg, OpRC);
9004 }
9005
9006 return;
9007 }
9008 }
9009
9010 // If this is a v2s copy between 16bit and 32bit reg,
9011 // replace vgpr copy to reg_sequence/extract_subreg
9012 // This can be remove after we have sgpr16 in place
9013 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
9014 Inst.getOperand(1).getReg().isVirtual() &&
9015 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
9016 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
9017 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
9018 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9019 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
9020 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
9021 get(AMDGPU::IMPLICIT_DEF), Undef);
9022 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
9023 get(AMDGPU::REG_SEQUENCE), NewDstReg)
9024 .addReg(Inst.getOperand(1).getReg())
9025 .addImm(AMDGPU::lo16)
9026 .addReg(Undef)
9027 .addImm(AMDGPU::hi16);
9028 Inst.eraseFromParent();
9029 MRI.replaceRegWith(DstReg, NewDstReg);
9030 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9031 return;
9032 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
9033 AMDGPU::lo16)) {
9034 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
9035 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9036 MRI.replaceRegWith(DstReg, NewDstReg);
9037 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9038 return;
9039 }
9040 }
9041
9042 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9043 MRI.replaceRegWith(DstReg, NewDstReg);
9044 legalizeOperands(Inst, MDT);
9045 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9046 return;
9047 }
9048
9049 // Use the new VALU Opcode.
9050 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
9051 .setMIFlags(Inst.getFlags());
9052 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
9053 // Intersperse VOP3 modifiers among the SALU operands.
9054 NewInstr->addOperand(Inst.getOperand(0));
9055 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9056 AMDGPU::OpName::src0_modifiers) >= 0)
9057 NewInstr.addImm(0);
9058 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
9059 const MachineOperand &Src = Inst.getOperand(1);
9060 NewInstr->addOperand(Src);
9061 }
9062
9063 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
9064 // We are converting these to a BFE, so we need to add the missing
9065 // operands for the size and offset.
9066 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
9067 NewInstr.addImm(0);
9068 NewInstr.addImm(Size);
9069 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
9070 // The VALU version adds the second operand to the result, so insert an
9071 // extra 0 operand.
9072 NewInstr.addImm(0);
9073 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
9074 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
9075 // If we need to move this to VGPRs, we need to unpack the second
9076 // operand back into the 2 separate ones for bit offset and width.
9077 assert(OffsetWidthOp.isImm() &&
9078 "Scalar BFE is only implemented for constant width and offset");
9079 uint32_t Imm = OffsetWidthOp.getImm();
9080
9081 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9082 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9083 NewInstr.addImm(Offset);
9084 NewInstr.addImm(BitWidth);
9085 } else {
9086 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9087 AMDGPU::OpName::src1_modifiers) >= 0)
9088 NewInstr.addImm(0);
9089 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
9090 NewInstr->addOperand(Inst.getOperand(2));
9091 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9092 AMDGPU::OpName::src2_modifiers) >= 0)
9093 NewInstr.addImm(0);
9094 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
9095 NewInstr->addOperand(Inst.getOperand(3));
9096 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
9097 NewInstr.addImm(0);
9098 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
9099 NewInstr.addImm(0);
9100 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
9101 NewInstr.addImm(0);
9102 }
9103 } else {
9104 // Just copy the SALU operands.
9105 for (const MachineOperand &Op : Inst.explicit_operands())
9106 NewInstr->addOperand(Op);
9107 }
9108
9109 // Remove any references to SCC. Vector instructions can't read from it, and
9110 // We're just about to add the implicit use / defs of VCC, and we don't want
9111 // both.
9112 bool DeadSCCDef = false;
9113 for (MachineOperand &Op : Inst.implicit_operands()) {
9114 if (Op.getReg() == AMDGPU::SCC) {
9115 // Only propagate through live-def of SCC.
9116 if (Op.isDef()) {
9117 if (Op.isDead())
9118 DeadSCCDef = true;
9119 else
9120 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
9121 continue;
9122 }
9123
9124 addSCCDefsToVALUWorklist(NewInstr, Worklist);
9125 }
9126 }
9127 Inst.eraseFromParent();
9128 Register NewDstReg;
9129 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
9130 Register DstReg = NewInstr->getOperand(0).getReg();
9131 assert(DstReg.isVirtual());
9132 // Update the destination register class.
9133 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
9134 assert(NewDstRC);
9135 NewDstReg = MRI.createVirtualRegister(NewDstRC);
9136 MRI.replaceRegWith(DstReg, NewDstReg);
9137 }
9138 fixImplicitOperands(*NewInstr);
9139
9140 if (DeadSCCDef) {
9141 // A scalar op with a dead SCC def lowers to a VALU op whose VCC def will
9142 // also be dead.
9143 if (MachineOperand *VCCDef =
9144 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
9145 VCCDef->setIsDead();
9146 }
9147
9148 // Legalize the operands
9149 legalizeOperands(*NewInstr, MDT);
9150 if (NewDstReg)
9151 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9152}
9153
9154// Add/sub require special handling to deal with carry outs.
9155std::pair<bool, MachineBasicBlock *>
9156SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
9157 MachineDominatorTree *MDT) const {
9158 if (ST.hasAddNoCarryInsts()) {
9159 // Assume there is no user of scc since we don't select this in that case.
9160 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
9161 // is used.
9162
9163 MachineBasicBlock &MBB = *Inst.getParent();
9164 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9165
9166 Register OldDstReg = Inst.getOperand(0).getReg();
9167 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9168
9169 unsigned Opc = Inst.getOpcode();
9170 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
9171
9172 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
9173 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9174
9175 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
9176 Inst.removeOperand(3);
9177
9178 Inst.setDesc(get(NewOpc));
9179 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
9180 Inst.addImplicitDefUseOperands(*MBB.getParent());
9181 MRI.replaceRegWith(OldDstReg, ResultReg);
9182 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
9183
9184 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9185 return std::pair(true, NewBB);
9186 }
9187
9188 return std::pair(false, nullptr);
9189}
9190
9191void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
9192 MachineDominatorTree *MDT) const {
9193
9194 MachineBasicBlock &MBB = *Inst.getParent();
9195 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9196 MachineBasicBlock::iterator MII = Inst;
9197 const DebugLoc &DL = Inst.getDebugLoc();
9198
9199 MachineOperand &Dest = Inst.getOperand(0);
9200 MachineOperand &Src0 = Inst.getOperand(1);
9201 MachineOperand &Src1 = Inst.getOperand(2);
9202 MachineOperand &Cond = Inst.getOperand(3);
9203
9204 Register CondReg = Cond.getReg();
9205 bool IsSCC = (CondReg == AMDGPU::SCC);
9206
9207 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
9208 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
9209 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
9210 // output directly into the V_CNDMASK.
9211 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
9212 (Src1.getImm() == 0)) {
9213 for (MachineOperand &UseMO :
9215 MachineInstr &UseMI = *UseMO.getParent();
9216 switch (UseMI.getOpcode()) {
9217 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9218 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9219 case AMDGPU::V_CNDMASK_B16_t16_e32:
9220 case AMDGPU::V_CNDMASK_B16_t16_e64:
9221 case AMDGPU::V_CNDMASK_B32_e32:
9222 case AMDGPU::V_CNDMASK_B32_e64:
9223 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9224 if (UseMO.isImplicit() ||
9225 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
9226 UseMO.setReg(CondReg);
9227 }
9228 }
9229 if (MRI.use_nodbg_empty(Dest.getReg()))
9230 return;
9231 }
9232
9233 Register NewCondReg = CondReg;
9234 if (IsSCC) {
9235 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
9236 NewCondReg = MRI.createVirtualRegister(TC);
9237
9238 // Now look for the closest SCC def if it is a copy
9239 // replacing the CondReg with the COPY source register
9240 bool CopyFound = false;
9241 for (MachineInstr &CandI :
9243 Inst.getParent()->rend())) {
9244 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
9245 -1) {
9246 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9247 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
9248 .addReg(CandI.getOperand(1).getReg());
9249 CopyFound = true;
9250 }
9251 break;
9252 }
9253 }
9254 if (!CopyFound) {
9255 // SCC def is not a copy
9256 // Insert a trivial select instead of creating a copy, because a copy from
9257 // SCC would semantically mean just copying a single bit, but we may need
9258 // the result to be a vector condition mask that needs preserving.
9259 unsigned Opcode =
9260 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9261 auto NewSelect =
9262 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
9263 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
9264 }
9265 }
9266
9267 Register NewDestReg = MRI.createVirtualRegister(
9268 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
9269 MachineInstr *NewInst;
9270 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
9271 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9272 .addImm(0)
9273 .add(Src1) // False
9274 .addImm(0)
9275 .add(Src0) // True
9276 .addReg(NewCondReg);
9277 } else {
9278 NewInst =
9279 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
9280 .add(Src1) // False
9281 .add(Src0) // True
9282 .addReg(NewCondReg);
9283 }
9284 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
9285 legalizeOperands(*NewInst, MDT);
9286 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9287}
9288
9289void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
9290 MachineInstr &Inst) const {
9291 MachineBasicBlock &MBB = *Inst.getParent();
9292 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9293 MachineBasicBlock::iterator MII = Inst;
9294 const DebugLoc &DL = Inst.getDebugLoc();
9295
9296 MachineOperand &Dest = Inst.getOperand(0);
9297 MachineOperand &Src = Inst.getOperand(1);
9298 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9299 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9300
9301 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9302 unsigned SubOp =
9303 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9304
9305 MachineInstrBuilder Sub =
9306 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(Src.getReg());
9307 if (HasCarryOut)
9308 Sub.setOperandDead(3); // Dead vcc
9309
9310 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9311 .addReg(Src.getReg())
9312 .addReg(TmpReg);
9313
9314 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9315 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9316}
9317
9318void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
9319 MachineInstr &Inst) const {
9320 MachineBasicBlock &MBB = *Inst.getParent();
9321 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9322 MachineBasicBlock::iterator MII = Inst;
9323 const DebugLoc &DL = Inst.getDebugLoc();
9324
9325 MachineOperand &Dest = Inst.getOperand(0);
9326 MachineOperand &Src1 = Inst.getOperand(1);
9327 MachineOperand &Src2 = Inst.getOperand(2);
9328 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9329 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9330 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9331
9332 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9333 unsigned SubOp =
9334 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9335
9336 MachineInstrBuilder Sub1 = BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
9337 .addReg(Src1.getReg())
9338 .addReg(Src2.getReg());
9339
9340 MachineInstrBuilder Sub2 =
9341 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
9342
9343 if (HasCarryOut) {
9344 Sub1.setOperandDead(3); // Dead vcc
9345 Sub2.setOperandDead(3); // Dead vcc
9346 }
9347
9348 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9349 .addReg(SubResultReg)
9350 .addReg(TmpReg);
9351
9352 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9353 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9354}
9355
9356void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
9357 MachineInstr &Inst) const {
9358 MachineBasicBlock &MBB = *Inst.getParent();
9359 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9360 MachineBasicBlock::iterator MII = Inst;
9361 const DebugLoc &DL = Inst.getDebugLoc();
9362
9363 MachineOperand &Dest = Inst.getOperand(0);
9364 MachineOperand &Src0 = Inst.getOperand(1);
9365 MachineOperand &Src1 = Inst.getOperand(2);
9366
9367 if (ST.hasDLInsts()) {
9368 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9369 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
9370 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
9371
9372 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
9373 .add(Src0)
9374 .add(Src1);
9375
9376 MRI.replaceRegWith(Dest.getReg(), NewDest);
9377 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9378 } else {
9379 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
9380 // invert either source and then perform the XOR. If either source is a
9381 // scalar register, then we can leave the inversion on the scalar unit to
9382 // achieve a better distribution of scalar and vector instructions.
9383 bool Src0IsSGPR = Src0.isReg() &&
9384 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
9385 bool Src1IsSGPR = Src1.isReg() &&
9386 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
9387 MachineInstr *Xor;
9388 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9389 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9390
9391 // Build a pair of scalar instructions and add them to the work list.
9392 // The next iteration over the work list will lower these to the vector
9393 // unit as necessary.
9394 if (Src0IsSGPR) {
9395 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
9396 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9397 .addReg(Temp)
9398 .add(Src1);
9399 } else if (Src1IsSGPR) {
9400 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
9401 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9402 .add(Src0)
9403 .addReg(Temp);
9404 } else {
9405 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
9406 .add(Src0)
9407 .add(Src1);
9408 MachineInstr *Not =
9409 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
9410 Worklist.insert(Not);
9411 }
9412
9413 MRI.replaceRegWith(Dest.getReg(), NewDest);
9414
9415 Worklist.insert(Xor);
9416
9417 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9418 }
9419}
9420
9421void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
9422 MachineInstr &Inst,
9423 unsigned Opcode) const {
9424 MachineBasicBlock &MBB = *Inst.getParent();
9425 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9426 MachineBasicBlock::iterator MII = Inst;
9427 const DebugLoc &DL = Inst.getDebugLoc();
9428
9429 MachineOperand &Dest = Inst.getOperand(0);
9430 MachineOperand &Src0 = Inst.getOperand(1);
9431 MachineOperand &Src1 = Inst.getOperand(2);
9432
9433 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9434 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9435
9436 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
9437 .add(Src0)
9438 .add(Src1);
9439
9440 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
9441 .addReg(Interm);
9442
9443 Worklist.insert(&Op);
9444 Worklist.insert(&Not);
9445
9446 MRI.replaceRegWith(Dest.getReg(), NewDest);
9447 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9448}
9449
9450void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
9451 MachineInstr &Inst,
9452 unsigned Opcode) const {
9453 MachineBasicBlock &MBB = *Inst.getParent();
9454 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9455 MachineBasicBlock::iterator MII = Inst;
9456 const DebugLoc &DL = Inst.getDebugLoc();
9457
9458 MachineOperand &Dest = Inst.getOperand(0);
9459 MachineOperand &Src0 = Inst.getOperand(1);
9460 MachineOperand &Src1 = Inst.getOperand(2);
9461
9462 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9463 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9464
9465 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
9466 .add(Src1);
9467
9468 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
9469 .add(Src0)
9470 .addReg(Interm);
9471
9472 Worklist.insert(&Not);
9473 Worklist.insert(&Op);
9474
9475 MRI.replaceRegWith(Dest.getReg(), NewDest);
9476 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9477}
9478
9479void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
9480 MachineInstr &Inst, unsigned Opcode,
9481 bool Swap) const {
9482 MachineBasicBlock &MBB = *Inst.getParent();
9483 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9484
9485 MachineOperand &Dest = Inst.getOperand(0);
9486 MachineOperand &Src0 = Inst.getOperand(1);
9487 const DebugLoc &DL = Inst.getDebugLoc();
9488
9489 MachineBasicBlock::iterator MII = Inst;
9490
9491 const MCInstrDesc &InstDesc = get(Opcode);
9492 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9493 MRI.getRegClass(Src0.getReg()) :
9494 &AMDGPU::SGPR_32RegClass;
9495
9496 const TargetRegisterClass *Src0SubRC =
9497 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9498
9499 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9500 AMDGPU::sub0, Src0SubRC);
9501
9502 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9503 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9504 const TargetRegisterClass *NewDestSubRC =
9505 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9506
9507 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9508 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
9509
9510 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9511 AMDGPU::sub1, Src0SubRC);
9512
9513 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9514 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
9515
9516 if (Swap)
9517 std::swap(DestSub0, DestSub1);
9518
9519 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9520 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9521 .addReg(DestSub0)
9522 .addImm(AMDGPU::sub0)
9523 .addReg(DestSub1)
9524 .addImm(AMDGPU::sub1);
9525
9526 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9527
9528 Worklist.insert(&LoHalf);
9529 Worklist.insert(&HiHalf);
9530
9531 // We don't need to legalizeOperands here because for a single operand, src0
9532 // will support any kind of input.
9533
9534 // Move all users of this moved value.
9535 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9536}
9537
9538// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9539// split the s_mul_u64 in 32-bit vector multiplications.
9540void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9541 MachineInstr &Inst,
9542 MachineDominatorTree *MDT) const {
9543 MachineBasicBlock &MBB = *Inst.getParent();
9544 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9545
9546 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9547 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9548 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9549
9550 MachineOperand &Dest = Inst.getOperand(0);
9551 MachineOperand &Src0 = Inst.getOperand(1);
9552 MachineOperand &Src1 = Inst.getOperand(2);
9553 const DebugLoc &DL = Inst.getDebugLoc();
9554 MachineBasicBlock::iterator MII = Inst;
9555
9556 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9557 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9558 const TargetRegisterClass *Src0SubRC =
9559 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9560 if (RI.isSGPRClass(Src0SubRC))
9561 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9562 const TargetRegisterClass *Src1SubRC =
9563 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9564 if (RI.isSGPRClass(Src1SubRC))
9565 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9566
9567 // First, we extract the low 32-bit and high 32-bit values from each of the
9568 // operands.
9569 MachineOperand Op0L =
9570 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9571 MachineOperand Op1L =
9572 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9573 MachineOperand Op0H =
9574 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9575 MachineOperand Op1H =
9576 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9577
9578 // The multilication is done as follows:
9579 //
9580 // Op1H Op1L
9581 // * Op0H Op0L
9582 // --------------------
9583 // Op1H*Op0L Op1L*Op0L
9584 // + Op1H*Op0H Op1L*Op0H
9585 // -----------------------------------------
9586 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9587 //
9588 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9589 // value and that would overflow.
9590 // The low 32-bit value is Op1L*Op0L.
9591 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9592
9593 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9594 MachineInstr *Op1L_Op0H =
9595 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9596 .add(Op1L)
9597 .add(Op0H);
9598
9599 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9600 MachineInstr *Op1H_Op0L =
9601 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9602 .add(Op1H)
9603 .add(Op0L);
9604
9605 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9606 MachineInstr *Carry =
9607 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9608 .add(Op1L)
9609 .add(Op0L);
9610
9611 MachineInstr *LoHalf =
9612 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9613 .add(Op1L)
9614 .add(Op0L);
9615
9616 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9617 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9618 .addReg(Op1L_Op0H_Reg)
9619 .addReg(Op1H_Op0L_Reg);
9620
9621 MachineInstr *HiHalf =
9622 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9623 .addReg(AddReg)
9624 .addReg(CarryReg);
9625
9626 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9627 .addReg(DestSub0)
9628 .addImm(AMDGPU::sub0)
9629 .addReg(DestSub1)
9630 .addImm(AMDGPU::sub1);
9631
9632 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9633
9634 // Try to legalize the operands in case we need to swap the order to keep it
9635 // valid.
9636 legalizeOperands(*Op1L_Op0H, MDT);
9637 legalizeOperands(*Op1H_Op0L, MDT);
9638 legalizeOperands(*Carry, MDT);
9639 legalizeOperands(*LoHalf, MDT);
9640 legalizeOperands(*Add, MDT);
9641 legalizeOperands(*HiHalf, MDT);
9642
9643 // Move all users of this moved value.
9644 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9645}
9646
9647// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9648// multiplications.
9649void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9650 MachineInstr &Inst,
9651 MachineDominatorTree *MDT) const {
9652 MachineBasicBlock &MBB = *Inst.getParent();
9653 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9654
9655 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9656 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9657 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9658
9659 MachineOperand &Dest = Inst.getOperand(0);
9660 MachineOperand &Src0 = Inst.getOperand(1);
9661 MachineOperand &Src1 = Inst.getOperand(2);
9662 const DebugLoc &DL = Inst.getDebugLoc();
9663 MachineBasicBlock::iterator MII = Inst;
9664
9665 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9666 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9667 const TargetRegisterClass *Src0SubRC =
9668 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9669 if (RI.isSGPRClass(Src0SubRC))
9670 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9671 const TargetRegisterClass *Src1SubRC =
9672 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9673 if (RI.isSGPRClass(Src1SubRC))
9674 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9675
9676 // First, we extract the low 32-bit and high 32-bit values from each of the
9677 // operands.
9678 MachineOperand Op0L =
9679 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9680 MachineOperand Op1L =
9681 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9682
9683 unsigned Opc = Inst.getOpcode();
9684 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9685 ? AMDGPU::V_MUL_HI_U32_e64
9686 : AMDGPU::V_MUL_HI_I32_e64;
9687 MachineInstr *HiHalf =
9688 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9689
9690 MachineInstr *LoHalf =
9691 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9692 .add(Op1L)
9693 .add(Op0L);
9694
9695 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9696 .addReg(DestSub0)
9697 .addImm(AMDGPU::sub0)
9698 .addReg(DestSub1)
9699 .addImm(AMDGPU::sub1);
9700
9701 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9702
9703 // Try to legalize the operands in case we need to swap the order to keep it
9704 // valid.
9705 legalizeOperands(*HiHalf, MDT);
9706 legalizeOperands(*LoHalf, MDT);
9707
9708 // Move all users of this moved value.
9709 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9710}
9711
9712void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9713 MachineInstr &Inst, unsigned Opcode,
9714 MachineDominatorTree *MDT) const {
9715 MachineBasicBlock &MBB = *Inst.getParent();
9716 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9717
9718 MachineOperand &Dest = Inst.getOperand(0);
9719 MachineOperand &Src0 = Inst.getOperand(1);
9720 MachineOperand &Src1 = Inst.getOperand(2);
9721 const DebugLoc &DL = Inst.getDebugLoc();
9722
9723 MachineBasicBlock::iterator MII = Inst;
9724
9725 const MCInstrDesc &InstDesc = get(Opcode);
9726 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9727 MRI.getRegClass(Src0.getReg()) :
9728 &AMDGPU::SGPR_32RegClass;
9729
9730 const TargetRegisterClass *Src0SubRC =
9731 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9732 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9733 MRI.getRegClass(Src1.getReg()) :
9734 &AMDGPU::SGPR_32RegClass;
9735
9736 const TargetRegisterClass *Src1SubRC =
9737 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9738
9739 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9740 AMDGPU::sub0, Src0SubRC);
9741 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9742 AMDGPU::sub0, Src1SubRC);
9743 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9744 AMDGPU::sub1, Src0SubRC);
9745 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9746 AMDGPU::sub1, Src1SubRC);
9747
9748 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9749 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9750 const TargetRegisterClass *NewDestSubRC =
9751 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9752
9753 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9754 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9755 .add(SrcReg0Sub0)
9756 .add(SrcReg1Sub0);
9757
9758 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9759 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9760 .add(SrcReg0Sub1)
9761 .add(SrcReg1Sub1);
9762
9763 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9764 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9765 .addReg(DestSub0)
9766 .addImm(AMDGPU::sub0)
9767 .addReg(DestSub1)
9768 .addImm(AMDGPU::sub1);
9769
9770 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9771
9772 Worklist.insert(&LoHalf);
9773 Worklist.insert(&HiHalf);
9774
9775 // Move all users of this moved value.
9776 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9777}
9778
9779void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9780 MachineInstr &Inst,
9781 MachineDominatorTree *MDT) const {
9782 MachineBasicBlock &MBB = *Inst.getParent();
9783 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9784
9785 MachineOperand &Dest = Inst.getOperand(0);
9786 MachineOperand &Src0 = Inst.getOperand(1);
9787 MachineOperand &Src1 = Inst.getOperand(2);
9788 const DebugLoc &DL = Inst.getDebugLoc();
9789
9790 MachineBasicBlock::iterator MII = Inst;
9791
9792 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9793
9794 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9795
9796 MachineOperand* Op0;
9797 MachineOperand* Op1;
9798
9799 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9800 Op0 = &Src0;
9801 Op1 = &Src1;
9802 } else {
9803 Op0 = &Src1;
9804 Op1 = &Src0;
9805 }
9806
9807 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9808 .add(*Op0);
9809
9810 Register NewDest = MRI.createVirtualRegister(DestRC);
9811
9812 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9813 .addReg(Interm)
9814 .add(*Op1);
9815
9816 MRI.replaceRegWith(Dest.getReg(), NewDest);
9817
9818 Worklist.insert(&Xor);
9819}
9820
9821void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9822 MachineInstr &Inst) const {
9823 MachineBasicBlock &MBB = *Inst.getParent();
9824 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9825
9826 MachineBasicBlock::iterator MII = Inst;
9827 const DebugLoc &DL = Inst.getDebugLoc();
9828
9829 MachineOperand &Dest = Inst.getOperand(0);
9830 MachineOperand &Src = Inst.getOperand(1);
9831
9832 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9833 const TargetRegisterClass *SrcRC = Src.isReg() ?
9834 MRI.getRegClass(Src.getReg()) :
9835 &AMDGPU::SGPR_32RegClass;
9836
9837 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9838 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9839
9840 const TargetRegisterClass *SrcSubRC =
9841 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9842
9843 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9844 AMDGPU::sub0, SrcSubRC);
9845 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9846 AMDGPU::sub1, SrcSubRC);
9847
9848 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9849
9850 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9851
9852 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9853
9854 // We don't need to legalize operands here. src0 for either instruction can be
9855 // an SGPR, and the second input is unused or determined here.
9856 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9857}
9858
9859void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9860 MachineInstr &Inst) const {
9861 MachineBasicBlock &MBB = *Inst.getParent();
9862 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9863 MachineBasicBlock::iterator MII = Inst;
9864 const DebugLoc &DL = Inst.getDebugLoc();
9865
9866 MachineOperand &Dest = Inst.getOperand(0);
9867 uint32_t Imm = Inst.getOperand(2).getImm();
9868 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9869 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9870
9871 (void) Offset;
9872
9873 // Only sext_inreg cases handled.
9874 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9875 Offset == 0 && "Not implemented");
9876
9877 if (BitWidth < 32) {
9878 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9879 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9880 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9881
9882 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9883 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9884 .addImm(0)
9885 .addImm(BitWidth);
9886
9887 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9888 .addImm(31)
9889 .addReg(MidRegLo);
9890
9891 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9892 .addReg(MidRegLo)
9893 .addImm(AMDGPU::sub0)
9894 .addReg(MidRegHi)
9895 .addImm(AMDGPU::sub1);
9896
9897 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9898 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9899 return;
9900 }
9901
9902 MachineOperand &Src = Inst.getOperand(1);
9903 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9904 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9905
9906 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9907 .addImm(31)
9908 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9909
9910 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9911 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9912 .addImm(AMDGPU::sub0)
9913 .addReg(TmpReg)
9914 .addImm(AMDGPU::sub1);
9915
9916 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9917 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9918}
9919
9920void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9921 MachineInstr &Inst, unsigned Opcode,
9922 MachineDominatorTree *MDT) const {
9923 // (S_FLBIT_I32_B64 hi:lo) ->
9924 // -> (umin (V_FFBH_U32_e32 hi), (or (V_FFBH_U32_e32 lo), 32))
9925 // (S_FF1_I32_B64 hi:lo) ->
9926 // ->(umin (or (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9927
9928 MachineBasicBlock &MBB = *Inst.getParent();
9929 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9930 MachineBasicBlock::iterator MII = Inst;
9931 const DebugLoc &DL = Inst.getDebugLoc();
9932
9933 MachineOperand &Dest = Inst.getOperand(0);
9934 MachineOperand &Src = Inst.getOperand(1);
9935
9936 const MCInstrDesc &InstDesc = get(Opcode);
9937
9938 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9939
9940 const TargetRegisterClass *SrcRC =
9941 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9942 const TargetRegisterClass *SrcSubRC =
9943 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9944
9945 MachineOperand SrcRegSub0 =
9946 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9947 MachineOperand SrcRegSub1 =
9948 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9949
9950 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9951 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9952 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9953 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9954
9955 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9956
9957 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9958
9959 BuildMI(MBB, MII, DL, get(AMDGPU::V_OR_B32_e32), MidReg3)
9960 .addImm(32)
9961 .addReg(IsCtlz ? MidReg1 : MidReg2);
9962
9963 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9964 .addReg(MidReg3)
9965 .addReg(IsCtlz ? MidReg2 : MidReg1);
9966
9967 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9968
9969 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9970}
9971
9972void SIInstrInfo::addUsersToMoveToVALUWorklist(
9973 Register DstReg, MachineRegisterInfo &MRI,
9974 SIInstrWorklist &Worklist) const {
9975 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9976 MachineInstr &UseMI = *MO.getParent();
9977
9978 unsigned OpNo = 0;
9979
9980 switch (UseMI.getOpcode()) {
9981 case AMDGPU::COPY:
9982 case AMDGPU::WQM:
9983 case AMDGPU::SOFT_WQM:
9984 case AMDGPU::STRICT_WWM:
9985 case AMDGPU::STRICT_WQM:
9986 case AMDGPU::REG_SEQUENCE:
9987 case AMDGPU::PHI:
9988 case AMDGPU::INSERT_SUBREG:
9989 break;
9990 default:
9991 OpNo = MO.getOperandNo();
9992 break;
9993 }
9994
9995 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9996 MRI.constrainRegClass(DstReg, OpRC);
9997
9998 if (!RI.hasVectorRegisters(OpRC))
9999 Worklist.insert(&UseMI);
10000 else
10001 // Legalization could change user list.
10002 legalizeOperandsVALUt16(UseMI, OpNo, MRI);
10003 }
10004}
10005
10006void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
10008 MachineInstr &Inst) const {
10009 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10010 MachineBasicBlock *MBB = Inst.getParent();
10011 MachineOperand &Src0 = Inst.getOperand(1);
10012 MachineOperand &Src1 = Inst.getOperand(2);
10013 const DebugLoc &DL = Inst.getDebugLoc();
10014
10015 if (ST.useRealTrue16Insts()) {
10016 Register SrcReg0, SrcReg1;
10017 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
10018 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10019 BuildMI(*MBB, Inst, DL,
10020 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
10021 .add(Src0);
10022 } else {
10023 SrcReg0 = Src0.getReg();
10024 }
10025
10026 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
10027 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10028 BuildMI(*MBB, Inst, DL,
10029 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
10030 .add(Src1);
10031 } else {
10032 SrcReg1 = Src1.getReg();
10033 }
10034
10035 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
10036 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
10037
10038 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
10039 switch (Inst.getOpcode()) {
10040 case AMDGPU::S_PACK_LL_B32_B16:
10041 NewMI
10042 .addReg(SrcReg0, {},
10043 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10044 .addImm(AMDGPU::lo16)
10045 .addReg(SrcReg1, {},
10046 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10047 .addImm(AMDGPU::hi16);
10048 break;
10049 case AMDGPU::S_PACK_LH_B32_B16:
10050 NewMI
10051 .addReg(SrcReg0, {},
10052 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10053 .addImm(AMDGPU::lo16)
10054 .addReg(SrcReg1, {}, AMDGPU::hi16)
10055 .addImm(AMDGPU::hi16);
10056 break;
10057 case AMDGPU::S_PACK_HL_B32_B16:
10058 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10059 .addImm(AMDGPU::lo16)
10060 .addReg(SrcReg1, {},
10061 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10062 .addImm(AMDGPU::hi16);
10063 break;
10064 case AMDGPU::S_PACK_HH_B32_B16:
10065 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10066 .addImm(AMDGPU::lo16)
10067 .addReg(SrcReg1, {}, AMDGPU::hi16)
10068 .addImm(AMDGPU::hi16);
10069 break;
10070 default:
10071 llvm_unreachable("unhandled s_pack_* instruction");
10072 }
10073
10074 MachineOperand &Dest = Inst.getOperand(0);
10075 MRI.replaceRegWith(Dest.getReg(), ResultReg);
10076 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10077 return;
10078 }
10079
10080 switch (Inst.getOpcode()) {
10081 case AMDGPU::S_PACK_LL_B32_B16: {
10082 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10083 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10084
10085 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
10086 // 0.
10087 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10088 .addImm(0xffff);
10089
10090 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
10091 .addReg(ImmReg)
10092 .add(Src0);
10093
10094 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
10095 .add(Src1)
10096 .addImm(16)
10097 .addReg(TmpReg);
10098 break;
10099 }
10100 case AMDGPU::S_PACK_LH_B32_B16: {
10101 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10102 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10103 .addImm(0xffff);
10104 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
10105 .addReg(ImmReg)
10106 .add(Src0)
10107 .add(Src1);
10108 break;
10109 }
10110 case AMDGPU::S_PACK_HL_B32_B16: {
10111 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10112 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
10113 .addImm(16)
10114 .add(Src0);
10115 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
10116 .add(Src1)
10117 .addImm(16)
10118 .addReg(TmpReg);
10119 break;
10120 }
10121 case AMDGPU::S_PACK_HH_B32_B16: {
10122 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10123 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10124 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
10125 .addImm(16)
10126 .add(Src0);
10127 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10128 .addImm(0xffff0000);
10129 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
10130 .add(Src1)
10131 .addReg(ImmReg)
10132 .addReg(TmpReg);
10133 break;
10134 }
10135 default:
10136 llvm_unreachable("unhandled s_pack_* instruction");
10137 }
10138
10139 MachineOperand &Dest = Inst.getOperand(0);
10140 MRI.replaceRegWith(Dest.getReg(), ResultReg);
10141 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10142}
10143
10144void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
10145 MachineInstr &SCCDefInst,
10146 SIInstrWorklist &Worklist,
10147 Register NewCond) const {
10148
10149 // Ensure that def inst defines SCC, which is still live.
10150 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
10151 !Op.isDead() && Op.getParent() == &SCCDefInst);
10152 SmallVector<MachineInstr *, 4> CopyToDelete;
10153 // This assumes that all the users of SCC are in the same block
10154 // as the SCC def.
10155 for (MachineInstr &MI : // Skip the def inst itself.
10156 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
10157 SCCDefInst.getParent()->end())) {
10158 // Check if SCC is used first.
10159 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
10160 if (SCCIdx != -1) {
10161 if (MI.isCopy()) {
10162 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10163 Register DestReg = MI.getOperand(0).getReg();
10164
10165 MRI.replaceRegWith(DestReg, NewCond);
10166 CopyToDelete.push_back(&MI);
10167 } else {
10168
10169 if (NewCond.isValid())
10170 MI.getOperand(SCCIdx).setReg(NewCond);
10171
10172 Worklist.insert(&MI);
10173 }
10174 }
10175 // Exit if we find another SCC def.
10176 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
10177 break;
10178 }
10179 for (auto &Copy : CopyToDelete)
10180 Copy->eraseFromParent();
10181}
10182
10183// Instructions that use SCC may be converted to VALU instructions. When that
10184// happens, the SCC register is changed to VCC_LO. The instruction that defines
10185// SCC must be changed to an instruction that defines VCC. This function makes
10186// sure that the instruction that defines SCC is added to the moveToVALU
10187// worklist.
10188void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
10189 SIInstrWorklist &Worklist) const {
10190 // Look for a preceding instruction that either defines VCC or SCC. If VCC
10191 // then there is nothing to do because the defining instruction has been
10192 // converted to a VALU already. If SCC then that instruction needs to be
10193 // converted to a VALU.
10194 for (MachineInstr &MI :
10195 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
10196 SCCUseInst->getParent()->rend())) {
10197 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
10198 break;
10199 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
10200 Worklist.insert(&MI);
10201 break;
10202 }
10203 }
10204}
10205
10206const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
10207 const MachineInstr &Inst) const {
10208 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
10209
10210 switch (Inst.getOpcode()) {
10211 // For target instructions, getOpRegClass just returns the virtual register
10212 // class associated with the operand, so we need to find an equivalent VGPR
10213 // register class in order to move the instruction to the VALU.
10214 case AMDGPU::COPY:
10215 case AMDGPU::PHI:
10216 case AMDGPU::REG_SEQUENCE:
10217 case AMDGPU::INSERT_SUBREG:
10218 case AMDGPU::WQM:
10219 case AMDGPU::SOFT_WQM:
10220 case AMDGPU::STRICT_WWM:
10221 case AMDGPU::STRICT_WQM: {
10222 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
10223 if (RI.isAGPRClass(SrcRC)) {
10224 if (RI.isAGPRClass(NewDstRC))
10225 return nullptr;
10226
10227 switch (Inst.getOpcode()) {
10228 case AMDGPU::PHI:
10229 case AMDGPU::REG_SEQUENCE:
10230 case AMDGPU::INSERT_SUBREG:
10231 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10232 break;
10233 default:
10234 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10235 }
10236
10237 if (!NewDstRC)
10238 return nullptr;
10239 } else {
10240 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10241 return nullptr;
10242
10243 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10244 if (!NewDstRC)
10245 return nullptr;
10246 }
10247
10248 return NewDstRC;
10249 }
10250 default:
10251 return NewDstRC;
10252 }
10253}
10254
10255// Find the one SGPR operand we are allowed to use.
10256Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
10257 int OpIndices[3]) const {
10258 const MCInstrDesc &Desc = MI.getDesc();
10259
10260 // Find the one SGPR operand we are allowed to use.
10261 //
10262 // First we need to consider the instruction's operand requirements before
10263 // legalizing. Some operands are required to be SGPRs, such as implicit uses
10264 // of VCC, but we are still bound by the constant bus requirement to only use
10265 // one.
10266 //
10267 // If the operand's class is an SGPR, we can never move it.
10268
10269 Register SGPRReg = findImplicitSGPRRead(MI);
10270 if (SGPRReg)
10271 return SGPRReg;
10272
10273 Register UsedSGPRs[3] = {Register()};
10274 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10275
10276 for (unsigned i = 0; i < 3; ++i) {
10277 int Idx = OpIndices[i];
10278 if (Idx == -1)
10279 break;
10280
10281 const MachineOperand &MO = MI.getOperand(Idx);
10282 if (!MO.isReg())
10283 continue;
10284
10285 // Is this operand statically required to be an SGPR based on the operand
10286 // constraints?
10287 const TargetRegisterClass *OpRC =
10288 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
10289 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10290 if (IsRequiredSGPR)
10291 return MO.getReg();
10292
10293 // If this could be a VGPR or an SGPR, Check the dynamic register class.
10294 Register Reg = MO.getReg();
10295 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
10296 if (RI.isSGPRClass(RegRC))
10297 UsedSGPRs[i] = Reg;
10298 }
10299
10300 // We don't have a required SGPR operand, so we have a bit more freedom in
10301 // selecting operands to move.
10302
10303 // Try to select the most used SGPR. If an SGPR is equal to one of the
10304 // others, we choose that.
10305 //
10306 // e.g.
10307 // V_FMA_F32 v0, s0, s0, s0 -> No moves
10308 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
10309
10310 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
10311 // prefer those.
10312
10313 if (UsedSGPRs[0]) {
10314 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10315 SGPRReg = UsedSGPRs[0];
10316 }
10317
10318 if (!SGPRReg && UsedSGPRs[1]) {
10319 if (UsedSGPRs[1] == UsedSGPRs[2])
10320 SGPRReg = UsedSGPRs[1];
10321 }
10322
10323 return SGPRReg;
10324}
10325
10327 AMDGPU::OpName OperandName) const {
10328 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10329 return nullptr;
10330
10331 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
10332 if (Idx == -1)
10333 return nullptr;
10334
10335 return &MI.getOperand(Idx);
10336}
10337
10339 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
10340 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
10343 return (Format << 44) |
10344 (1ULL << 56) | // RESOURCE_LEVEL = 1
10345 (3ULL << 60); // OOB_SELECT = 3
10346 }
10347
10348 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
10349 if (ST.isAmdHsaOS()) {
10350 // Set ATC = 1. GFX9 doesn't have this bit.
10351 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10352 RsrcDataFormat |= (1ULL << 56);
10353
10354 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
10355 // BTW, it disables TC L2 and therefore decreases performance.
10356 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
10357 RsrcDataFormat |= (2ULL << 59);
10358 }
10359
10360 return RsrcDataFormat;
10361}
10362
10364 uint64_t Rsrc23 = getDefaultRsrcDataFormat() |
10366 0xffffffff; // Size;
10367
10368 // GFX9 doesn't have ELEMENT_SIZE.
10369 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
10370 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
10371 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
10372 }
10373
10374 // IndexStride = 64 / 32.
10375 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10376 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
10377
10378 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
10379 // Clear them unless we want a huge stride.
10380 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
10381 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
10382 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
10383
10384 return Rsrc23;
10385}
10386
10388 unsigned Opc = MI.getOpcode();
10389
10390 return isSMRD(Opc);
10391}
10392
10394 return get(Opc).mayLoad() &&
10395 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
10396}
10397
10399 TypeSize &MemBytes) const {
10400 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
10401 if (!Addr || !Addr->isFI())
10402 return Register();
10403
10404 assert(!MI.memoperands_empty() &&
10405 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
10406
10407 FrameIndex = Addr->getIndex();
10408
10409 int VDataIdx =
10410 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
10411 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
10412 return MI.getOperand(VDataIdx).getReg();
10413}
10414
10416 TypeSize &MemBytes) const {
10417 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
10418 assert(Addr && Addr->isFI());
10419 FrameIndex = Addr->getIndex();
10420
10421 int DataIdx =
10422 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
10423 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
10424 return MI.getOperand(DataIdx).getReg();
10425}
10426
10428 int &FrameIndex,
10429 TypeSize &MemBytes) const {
10430 if (!MI.mayLoad())
10431 return Register();
10432
10433 if (isMUBUF(MI) || isVGPRSpill(MI))
10434 return isStackAccess(MI, FrameIndex, MemBytes);
10435
10436 if (isSGPRSpill(MI))
10437 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10438
10439 return Register();
10440}
10441
10443 int &FrameIndex,
10444 TypeSize &MemBytes) const {
10445 if (!MI.mayStore())
10446 return Register();
10447
10448 if (isMUBUF(MI) || isVGPRSpill(MI))
10449 return isStackAccess(MI, FrameIndex, MemBytes);
10450
10451 if (isSGPRSpill(MI))
10452 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10453
10454 return Register();
10455}
10456
10458 unsigned Opc = MI.getOpcode();
10460 unsigned DescSize = Desc.getSize();
10461
10462 // If we have a definitive size, we can use it. Otherwise we need to inspect
10463 // the operands to know the size.
10464 if (isFixedSize(MI)) {
10465 unsigned Size = DescSize;
10466
10467 // If we hit the buggy offset, an extra nop will be inserted in MC so
10468 // estimate the worst case.
10469 if (MI.isBranch() && ST.hasOffset3fBug())
10470 Size += 4;
10471
10472 return Size;
10473 }
10474
10475 // Instructions may have a 32-bit literal encoded after them. Check
10476 // operands that could ever be literals.
10477 if (isVALU(MI, /*AllowLDSDMA=*/false) || isSALU(MI)) {
10478 if (isDPP(MI))
10479 return DescSize;
10480 bool HasLiteral = false;
10481 unsigned LiteralSize = 4;
10482 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
10483 const MachineOperand &Op = MI.getOperand(I);
10484 const MCOperandInfo &OpInfo = Desc.operands()[I];
10485 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
10486 HasLiteral = true;
10487 if (ST.has64BitLiterals()) {
10488 switch (OpInfo.OperandType) {
10489 default:
10490 break;
10493 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
10494 LiteralSize = 8;
10495 break;
10498 // A 32-bit literal is only valid when the value fits in BOTH signed
10499 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
10500 // emitter's getLit64Encoding logic. This is because of the lack of
10501 // abilility to tell signedness of the literal, therefore we need to
10502 // be conservative and assume values outside this range require a
10503 // 64-bit literal encoding (8 bytes).
10504 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
10505 !isUInt<32>(Op.getImm()))
10506 LiteralSize = 8;
10507 break;
10508 }
10509 }
10510 break;
10511 }
10512 }
10513 return HasLiteral ? DescSize + LiteralSize : DescSize;
10514 }
10515
10516 // Check whether we have extra NSA words.
10517 if (isMIMG(MI)) {
10518 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
10519 if (VAddr0Idx < 0)
10520 return 8;
10521
10522 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
10523 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10524 }
10525
10526 switch (Opc) {
10527 case TargetOpcode::BUNDLE:
10528 return getInstBundleSize(MI);
10529 case TargetOpcode::INLINEASM:
10530 case TargetOpcode::INLINEASM_BR: {
10531 const MachineFunction *MF = MI.getMF();
10532 const char *AsmStr = MI.getOperand(0).getSymbolName();
10533 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10534 }
10535 default:
10536 if (MI.isMetaInstruction())
10537 return 0;
10538
10539 // If D16 Pseudo inst, get correct MC code size
10540 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10541 if (D16Info) {
10542 // Assume d16_lo/hi inst are always in same size
10543 unsigned LoInstOpcode = D16Info->LoOp;
10544 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10545 DescSize = Desc.getSize();
10546 }
10547
10548 // If FMA Pseudo inst, get correct MC code size
10549 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10550 // All potential lowerings are the same size; arbitrarily pick one.
10551 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10552 DescSize = Desc.getSize();
10553 }
10554
10555 return DescSize;
10556 }
10557}
10558
10561 if (MI.isBranch() && ST.hasOffset3fBug())
10562 return InstSizeVerifyMode::NoVerify;
10563 return InstSizeVerifyMode::ExactSize;
10564}
10565
10568 static const std::pair<int, const char *> TargetIndices[] = {
10569 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10570 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10571 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10572 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10573 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10574 return ArrayRef(TargetIndices);
10575}
10576
10577/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10578/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10581 const ScheduleDAG *DAG) const {
10582 return new GCNHazardRecognizer(DAG->MF);
10583}
10584
10585/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10586/// pass.
10593
10594// Called during:
10595// - pre-RA scheduling and post-RA scheduling
10598 const ScheduleDAGMI *DAG) const {
10599 // Borrowed from Arm Target
10600 // We would like to restrict this hazard recognizer to only
10601 // post-RA scheduling; we can tell that we're post-RA because we don't
10602 // track VRegLiveness.
10603 if (!DAG->hasVRegLiveness())
10604 return new GCNHazardRecognizer(DAG->MF);
10606}
10607
10608std::pair<unsigned, unsigned>
10610 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10611}
10612
10615 static const std::pair<unsigned, const char *> TargetFlags[] = {
10616 {MO_GOTPCREL, "amdgpu-gotprel"},
10617 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10618 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10619 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10620 {MO_REL32_LO, "amdgpu-rel32-lo"},
10621 {MO_REL32_HI, "amdgpu-rel32-hi"},
10622 {MO_REL64, "amdgpu-rel64"},
10623 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10624 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10625 {MO_ABS64, "amdgpu-abs64"},
10626 };
10627
10628 return ArrayRef(TargetFlags);
10629}
10630
10633 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10634 {
10635 {MONoClobber, "amdgpu-noclobber"},
10636 {MOLastUse, "amdgpu-last-use"},
10637 {MOCooperative, "amdgpu-cooperative"},
10638 {MOThreadPrivate, "amdgpu-thread-private"},
10639 };
10640
10641 return ArrayRef(TargetFlags);
10642}
10643
10645 const MachineFunction &MF) const {
10647 assert(SrcReg.isVirtual());
10648 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10649 return AMDGPU::WWM_COPY;
10650
10651 return AMDGPU::COPY;
10652}
10653
10655 uint32_t Opcode = MI.getOpcode();
10656 // Check if it is SGPR spill or wwm-register spill Opcode.
10657 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10658 return true;
10659
10660 const MachineFunction *MF = MI.getMF();
10661 const MachineRegisterInfo &MRI = MF->getRegInfo();
10663
10664 // See if this is Liverange split instruction inserted for SGPR or
10665 // wwm-register. The implicit def inserted for wwm-registers should also be
10666 // included as they can appear at the bb begin.
10667 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10668 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10669 return false;
10670
10671 Register Reg = MI.getOperand(0).getReg();
10672 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10673 return IsLRSplitInst;
10674
10675 return MFI->isWWMReg(Reg);
10676}
10677
10679 Register Reg) const {
10680 // We need to handle instructions which may be inserted during register
10681 // allocation to handle the prolog. The initial prolog instruction may have
10682 // been separated from the start of the block by spills and copies inserted
10683 // needed by the prolog. However, the insertions for scalar registers can
10684 // always be placed at the BB top as they are independent of the exec mask
10685 // value.
10686 bool IsNullOrVectorRegister = true;
10687 if (Reg) {
10688 const MachineFunction *MF = MI.getMF();
10689 const MachineRegisterInfo &MRI = MF->getRegInfo();
10690 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10691 }
10692
10693 return IsNullOrVectorRegister &&
10694 (canAddToBBProlog(MI) ||
10695 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10696 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10697}
10698
10702 const DebugLoc &DL,
10703 Register DestReg) const {
10704 if (ST.hasAddNoCarryInsts())
10705 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10706
10707 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10708 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10709 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10710
10711 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10712 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10713}
10714
10717 const DebugLoc &DL,
10718 Register DestReg,
10719 RegScavenger &RS) const {
10720 if (ST.hasAddNoCarryInsts())
10721 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10722
10723 // If available, prefer to use vcc.
10724 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10725 ? Register(RI.getVCC())
10726 : RS.scavengeRegisterBackwards(
10727 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10728 0, /* AllowSpill */ false);
10729
10730 // TODO: Users need to deal with this.
10731 if (!UnusedCarry.isValid())
10732 return MachineInstrBuilder();
10733
10734 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10735 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10736}
10737
10738bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10739 switch (Opcode) {
10740 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10741 case AMDGPU::SI_KILL_I1_TERMINATOR:
10742 return true;
10743 default:
10744 return false;
10745 }
10746}
10747
10749 switch (Opcode) {
10750 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10751 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10752 case AMDGPU::SI_KILL_I1_PSEUDO:
10753 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10754 default:
10755 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10756 }
10757}
10758
10760 return Imm <= getMaxMUBUFImmOffset(ST);
10761}
10762
10764 // GFX12 field is non-negative 24-bit signed byte offset.
10765 const unsigned OffsetBits =
10766 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10767 return (1 << OffsetBits) - 1;
10768}
10769
10771 if (!ST.isWave32())
10772 return;
10773
10774 if (MI.isInlineAsm())
10775 return;
10776
10777 if (MI.getNumOperands() < MI.getDesc().getNumOperands())
10778 return;
10779
10780 for (auto &Op : MI.implicit_operands()) {
10781 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10782 Op.setReg(AMDGPU::VCC_LO);
10783 }
10784}
10785
10787 if (!isSMRD(MI))
10788 return false;
10789
10790 // Check that it is using a buffer resource.
10791 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10792 if (Idx == -1) // e.g. s_memtime
10793 return false;
10794
10795 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10796 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10797}
10798
10799// Given Imm, split it into the values to put into the SOffset and ImmOffset
10800// fields in an MUBUF instruction. Return false if it is not possible (due to a
10801// hardware bug needing a workaround).
10802//
10803// The required alignment ensures that individual address components remain
10804// aligned if they are aligned to begin with. It also ensures that additional
10805// offsets within the given alignment can be added to the resulting ImmOffset.
10807 uint32_t &ImmOffset, Align Alignment) const {
10808 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10809 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10810 uint32_t Overflow = 0;
10811
10812 if (Imm > MaxImm) {
10813 if (Imm <= MaxImm + 64) {
10814 // Use an SOffset inline constant for 4..64
10815 Overflow = Imm - MaxImm;
10816 Imm = MaxImm;
10817 } else {
10818 // Try to keep the same value in SOffset for adjacent loads, so that
10819 // the corresponding register contents can be re-used.
10820 //
10821 // Load values with all low-bits (except for alignment bits) set into
10822 // SOffset, so that a larger range of values can be covered using
10823 // s_movk_i32.
10824 //
10825 // Atomic operations fail to work correctly when individual address
10826 // components are unaligned, even if their sum is aligned.
10827 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10828 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10829 Imm = Low;
10830 Overflow = High - Alignment.value();
10831 }
10832 }
10833
10834 if (Overflow > 0) {
10835 // There is a hardware bug in SI and CI which prevents address clamping in
10836 // MUBUF instructions from working correctly with SOffsets. The immediate
10837 // offset is unaffected.
10838 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10839 return false;
10840
10841 // It is not possible to set immediate in SOffset field on some targets.
10842 if (ST.hasRestrictedSOffset())
10843 return false;
10844 }
10845
10846 ImmOffset = Imm;
10847 SOffset = Overflow;
10848 return true;
10849}
10850
10851// Depending on the used address space and instructions, some immediate offsets
10852// are allowed and some are not.
10853// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10854// scratch instruction offsets can also be negative. On GFX12, offsets can be
10855// negative for all variants.
10856//
10857// There are several bugs related to these offsets:
10858// On gfx10.1, flat instructions that go into the global address space cannot
10859// use an offset.
10860//
10861// For scratch instructions, the address can be either an SGPR or a VGPR.
10862// The following offsets can be used, depending on the architecture (x means
10863// cannot be used):
10864// +----------------------------+------+------+
10865// | Address-Mode | SGPR | VGPR |
10866// +----------------------------+------+------+
10867// | gfx9 | | |
10868// | negative, 4-aligned offset | x | ok |
10869// | negative, unaligned offset | x | ok |
10870// +----------------------------+------+------+
10871// | gfx10 | | |
10872// | negative, 4-aligned offset | ok | ok |
10873// | negative, unaligned offset | ok | x |
10874// +----------------------------+------+------+
10875// | gfx10.3 | | |
10876// | negative, 4-aligned offset | ok | ok |
10877// | negative, unaligned offset | ok | ok |
10878// +----------------------------+------+------+
10879//
10880// This function ignores the addressing mode, so if an offset cannot be used in
10881// one addressing mode, it is considered illegal.
10882bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10883 AMDGPU::FlatAddrSpace FlatVariant) const {
10884 // TODO: Should 0 be special cased?
10885 if (!ST.hasFlatInstOffsets())
10886 return false;
10887
10889 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10890 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10891 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10892 return false;
10893
10894 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10895 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10896 (Offset % 4) != 0) {
10897 return false;
10898 }
10899
10900 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10901 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10902 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10903}
10904
10905// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10906std::pair<int64_t, int64_t>
10907SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10908 AMDGPU::FlatAddrSpace FlatVariant) const {
10909 int64_t RemainderOffset = COffsetVal;
10910 int64_t ImmField = 0;
10911
10912 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10913 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10914
10915 if (AllowNegative) {
10916 // Use signed division by a power of two to truncate towards 0.
10917 int64_t D = 1LL << NumBits;
10918 RemainderOffset = (COffsetVal / D) * D;
10919 ImmField = COffsetVal - RemainderOffset;
10920
10921 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10922 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10923 (ImmField % 4) != 0) {
10924 // Make ImmField a multiple of 4
10925 RemainderOffset += ImmField % 4;
10926 ImmField -= ImmField % 4;
10927 }
10928 } else if (COffsetVal >= 0) {
10929 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10930 RemainderOffset = COffsetVal - ImmField;
10931 }
10932
10933 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10934 assert(RemainderOffset + ImmField == COffsetVal);
10935 return {ImmField, RemainderOffset};
10936}
10937
10939 AMDGPU::FlatAddrSpace FlatVariant) const {
10940 if (ST.hasNegativeScratchOffsetBug() &&
10942 return false;
10943
10944 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10945}
10946
10947static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10948 switch (ST.getGeneration()) {
10949 default:
10950 break;
10953 return SIEncodingFamily::SI;
10955 // The GFX80 encoding family only contains buffer instructions with unpacked
10956 // D16 data; pseudoToMCOpcode falls back on VI for everything else.
10957 // TODO: remove this when we discard GFX80 encoding.
10958 return ST.hasUnpackedD16VMem() ? SIEncodingFamily::GFX80
10961 return SIEncodingFamily::VI;
10965 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10968 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10972 }
10973 llvm_unreachable("Unknown subtarget generation!");
10974}
10975
10976bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10977 switch(MCOp) {
10978 // These opcodes use indirect register addressing so
10979 // they need special handling by codegen (currently missing).
10980 // Therefore it is too risky to allow these opcodes
10981 // to be selected by dpp combiner or sdwa peepholer.
10982 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10983 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10984 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10985 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10986 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10987 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10988 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10989 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10990 return true;
10991 default:
10992 return false;
10993 }
10994}
10995
10996#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10997 case OPCODE##_dpp: \
10998 case OPCODE##_e32: \
10999 case OPCODE##_e64:
11000
11001static bool isRenamedInGFX9(int Opcode) {
11002 switch (Opcode) {
11003 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
11004 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
11005 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
11006 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
11007 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
11008 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
11009 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
11010 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
11011 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
11012 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
11013 case AMDGPU::V_FMA_F16_gfx9_e64:
11014 case AMDGPU::V_INTERP_P2_F16:
11015 case AMDGPU::V_MAD_F16_e64:
11016 case AMDGPU::V_MAD_U16_e64:
11017 case AMDGPU::V_MAD_I16_e64:
11018 return true;
11019 default:
11020 return false;
11021 }
11022}
11023
11024int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
11025 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
11026 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
11027
11028 unsigned Gen = subtargetEncodingFamily(ST);
11029
11030 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
11032
11033 if (SIInstrFlags::isSDWA(get(Opcode))) {
11034 switch (ST.getGeneration()) {
11035 default:
11037 break;
11040 break;
11043 break;
11044 }
11045 }
11046
11047 if (isMAI(Opcode)) {
11048 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
11049 if (MFMAOp != -1)
11050 Opcode = MFMAOp;
11051 }
11052
11053 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
11054
11055 // Only buffer instructions with unpacked D16 data have a GFX80 encoding.
11056 // Anything else on such a subtarget uses the plain VI encoding.
11057 // TODO: remove this when we discard GFX80 encoding.
11058 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && Gen == SIEncodingFamily::GFX80)
11060
11061 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
11063
11064 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
11066
11067 // -1 means that Opcode is already a native instruction.
11068 if (MCOp == -1)
11069 return Opcode;
11070
11071 if (ST.hasGFX90AInsts()) {
11072 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
11073 if (ST.hasGFX940Insts())
11075 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11077 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11079 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
11080 MCOp = NMCOp;
11081 }
11082
11083 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
11084 // encoding in the given subtarget generation.
11085 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
11086 return -1;
11087
11088 if (isAsmOnlyOpcode(MCOp))
11089 return -1;
11090
11091 return MCOp;
11092}
11093
11094static
11096 assert(RegOpnd.isReg());
11097 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
11098 getRegSubRegPair(RegOpnd);
11099}
11100
11103 assert(MI.isRegSequence());
11104 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
11105 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
11106 auto &RegOp = MI.getOperand(1 + 2 * I);
11107 return getRegOrUndef(RegOp);
11108 }
11110}
11111
11112// Try to find the definition of reg:subreg in subreg-manipulation pseudos
11113// Following a subreg of reg:subreg isn't supported
11116 if (!RSR.SubReg)
11117 return false;
11118 switch (MI.getOpcode()) {
11119 default: break;
11120 case AMDGPU::REG_SEQUENCE:
11121 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
11122 return true;
11123 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
11124 case AMDGPU::INSERT_SUBREG:
11125 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
11126 // inserted the subreg we're looking for
11127 RSR = getRegOrUndef(MI.getOperand(2));
11128 else { // the subreg in the rest of the reg
11129 auto R1 = getRegOrUndef(MI.getOperand(1));
11130 if (R1.SubReg) // subreg of subreg isn't supported
11131 return false;
11132 RSR.Reg = R1.Reg;
11133 }
11134 return true;
11135 }
11136 return false;
11137}
11138
11140 const MachineRegisterInfo &MRI) {
11141 assert(MRI.isSSA());
11142 if (!P.Reg.isVirtual())
11143 return nullptr;
11144
11145 auto RSR = P;
11146 auto *DefInst = MRI.getVRegDef(RSR.Reg);
11147 while (auto *MI = DefInst) {
11148 DefInst = nullptr;
11149 switch (MI->getOpcode()) {
11150 case AMDGPU::COPY:
11151 case AMDGPU::V_MOV_B32_e32: {
11152 auto &Op1 = MI->getOperand(1);
11153 if (Op1.isReg() && Op1.getReg().isVirtual()) {
11154 if (Op1.isUndef())
11155 return nullptr;
11156 RSR = getRegSubRegPair(Op1);
11157 DefInst = MRI.getVRegDef(RSR.Reg);
11158 }
11159 break;
11160 }
11161 default:
11162 if (followSubRegDef(*MI, RSR)) {
11163 if (!RSR.Reg)
11164 return nullptr;
11165 DefInst = MRI.getVRegDef(RSR.Reg);
11166 }
11167 }
11168 if (!DefInst)
11169 return MI;
11170 }
11171 return nullptr;
11172}
11173
11175 Register VReg,
11176 const MachineInstr &DefMI,
11177 const MachineInstr &UseMI) {
11178 assert(MRI.isSSA() && "Must be run on SSA");
11179
11180 auto *TRI = MRI.getTargetRegisterInfo();
11181 auto *DefBB = DefMI.getParent();
11182
11183 // Don't bother searching between blocks, although it is possible this block
11184 // doesn't modify exec.
11185 if (UseMI.getParent() != DefBB)
11186 return true;
11187
11188 const int MaxInstScan = 20;
11189 int NumInst = 0;
11190
11191 // Stop scan at the use.
11192 auto E = UseMI.getIterator();
11193 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
11194 if (I->isDebugInstr())
11195 continue;
11196
11197 if (++NumInst > MaxInstScan)
11198 return true;
11199
11200 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
11201 return true;
11202 }
11203
11204 return false;
11205}
11206
11208 Register VReg,
11209 const MachineInstr &DefMI) {
11210 assert(MRI.isSSA() && "Must be run on SSA");
11211
11212 auto *TRI = MRI.getTargetRegisterInfo();
11213 auto *DefBB = DefMI.getParent();
11214
11215 const int MaxUseScan = 10;
11216 int NumUse = 0;
11217
11218 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
11219 auto &UseInst = *Use.getParent();
11220 // Don't bother searching between blocks, although it is possible this block
11221 // doesn't modify exec.
11222 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11223 return true;
11224
11225 if (++NumUse > MaxUseScan)
11226 return true;
11227 }
11228
11229 if (NumUse == 0)
11230 return false;
11231
11232 const int MaxInstScan = 20;
11233 int NumInst = 0;
11234
11235 // Stop scan when we have seen all the uses.
11236 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
11237 assert(I != DefBB->end());
11238
11239 if (I->isDebugInstr())
11240 continue;
11241
11242 if (++NumInst > MaxInstScan)
11243 return true;
11244
11245 for (const MachineOperand &Op : I->operands()) {
11246 // We don't check reg masks here as they're used only on calls:
11247 // 1. EXEC is only considered const within one BB
11248 // 2. Call should be a terminator instruction if present in a BB
11249
11250 if (!Op.isReg())
11251 continue;
11252
11253 Register Reg = Op.getReg();
11254 if (Op.isUse()) {
11255 if (Reg == VReg && --NumUse == 0)
11256 return false;
11257 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
11258 return true;
11259 }
11260 }
11261}
11262
11265 const DebugLoc &DL, Register Src, Register Dst) const {
11266 auto Cur = MBB.begin();
11267 if (Cur != MBB.end())
11268 do {
11269 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
11270 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
11271 ++Cur;
11272 } while (Cur != MBB.end() && Cur != LastPHIIt);
11273
11274 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
11275 Dst);
11276}
11277
11280 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
11281 if (InsPt != MBB.end() &&
11282 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11283 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11284 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11285 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
11286 InsPt++;
11287 return BuildMI(MBB, InsPt, DL,
11288 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
11289 .addReg(Src, {}, SrcSubReg)
11290 .addReg(AMDGPU::EXEC, RegState::Implicit);
11291 }
11292 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
11293 Dst);
11294}
11295
11296bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
11297
11299 const MachineInstr &SecondMI) const {
11300 for (const auto &Use : SecondMI.all_uses()) {
11301 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
11302 return true;
11303 }
11304 return false;
11305}
11306
11307/// If OpX is multicycle, anti-dependencies are not allowed.
11308/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
11309/// purpose.
11311 const MachineInstr &OpX) const {
11313}
11314
11317 ArrayRef<unsigned> Ops, int FrameIndex,
11318 MachineInstr *&CopyMI, LiveIntervals *LIS,
11319 VirtRegMap *VRM) const {
11320 // This is a bit of a hack (copied from AArch64). Consider this instruction:
11321 //
11322 // %0:sreg_32 = COPY $m0
11323 //
11324 // We explicitly chose SReg_32 for the virtual register so such a copy might
11325 // be eliminated by RegisterCoalescer. However, that may not be possible, and
11326 // %0 may even spill. We can't spill $m0 normally (it would require copying to
11327 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
11328 // TargetInstrInfo::foldMemoryOperand() is going to try.
11329 // A similar issue also exists with spilling and reloading $exec registers.
11330 //
11331 // To prevent that, constrain the %0 register class here.
11332 if (isFullCopyInstr(MI)) {
11333 Register DstReg = MI.getOperand(0).getReg();
11334 Register SrcReg = MI.getOperand(1).getReg();
11335 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
11336 (DstReg.isVirtual() != SrcReg.isVirtual())) {
11337 MachineRegisterInfo &MRI = MF.getRegInfo();
11338 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
11339 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
11340 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
11341 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11342 return nullptr;
11343 }
11344 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
11345 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11346 return nullptr;
11347 }
11348 }
11349 }
11350
11351 return nullptr;
11352}
11353
11355 const MachineInstr &MI,
11356 unsigned *PredCost) const {
11357 if (MI.isBundle()) {
11359 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
11360 unsigned Lat = 0, Count = 0;
11361 for (++I; I != E && I->isBundledWithPred(); ++I) {
11362 ++Count;
11363 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
11364 }
11365 return Lat + Count - 1;
11366 }
11367
11368 return SchedModel.computeInstrLatency(&MI);
11369}
11370
11372 if (!ST.hasGFX1250VALUBlockingCycles())
11373 return 0;
11375}
11376
11377unsigned
11379 if (const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(MI.getOpcode()))
11380 return Entry->GFX1250BlockingCycles;
11381 return 0;
11382}
11383
11384const MachineOperand &
11386 if (const MachineOperand *CallAddrOp =
11387 getNamedOperand(MI, AMDGPU::OpName::src0))
11388 return *CallAddrOp;
11390}
11391
11394 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11395 unsigned Opcode = MI.getOpcode();
11396
11397 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
11398 Register Dst = MI.getOperand(0).getReg();
11399 Register Src = MI.getOperand(1).getReg();
11400 LLT DstTy = MRI.getType(Dst);
11401 LLT SrcTy = MRI.getType(Src);
11402 unsigned DstAS = DstTy.getAddressSpace();
11403 unsigned SrcAS = SrcTy.getAddressSpace();
11404 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
11405 DstAS == AMDGPUAS::FLAT_ADDRESS &&
11406 ST.hasGloballyAddressableScratch()
11409 };
11410
11411 // If the target supports globally addressable scratch, the mapping from
11412 // scratch memory to the flat aperture changes therefore an address space cast
11413 // is no longer uniform.
11414 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11415 return HandleAddrSpaceCast(MI);
11416
11417 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
11418 auto IID = GI->getIntrinsicID();
11423
11424 switch (IID) {
11425 case Intrinsic::amdgcn_if:
11426 case Intrinsic::amdgcn_else:
11427 // FIXME: Uniform if second result
11428 break;
11429 }
11430
11432 }
11433
11434 // Loads from the private and flat address spaces are divergent, because
11435 // threads can execute the load instruction with the same inputs and get
11436 // different results.
11437 //
11438 // All other loads are not divergent, because if threads issue loads with the
11439 // same arguments, they will always get the same result.
11440 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11441 Opcode == AMDGPU::G_SEXTLOAD) {
11442 if (MI.memoperands_empty())
11443 return ValueUniformity::NeverUniform; // conservative assumption
11444
11445 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11446 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11447 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11448 })) {
11449 // At least one MMO in a non-global address space.
11451 }
11453 }
11454
11455 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11456 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11457 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11458 AMDGPU::isGenericAtomic(Opcode)) {
11460 }
11461
11462 // Result is computed from uniform SP and uniform wave-wide max size.
11463 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11465
11466 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11468
11470}
11471
11473 if (!Formatter)
11474 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11475 return Formatter.get();
11476}
11477
11479
11480 if (isNeverUniform(MI))
11482
11483 unsigned opcode = MI.getOpcode();
11484 if (opcode == AMDGPU::V_READLANE_B32 ||
11485 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11486 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11488
11489 // If any of defs is divergent, report as NeverUniform. isUniformReg will
11490 // calculate in more detail for each def from its reg class, if available.
11491 if (MI.isInlineAsm()) {
11492 for (const MachineOperand &MO : MI.operands()) {
11493 if (!MO.isReg() || !MO.isDef())
11494 continue;
11495 const TargetRegisterClass *RC =
11496 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
11497 if (!RC || !RI.isSGPRClass(RC))
11499 }
11500 }
11501
11502 if (isCopyInstr(MI)) {
11503 const MachineOperand &srcOp = MI.getOperand(1);
11504 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
11505 const TargetRegisterClass *regClass =
11506 RI.getPhysRegBaseClass(srcOp.getReg());
11507 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
11509 }
11511 }
11512
11513 // GMIR handling
11514 if (MI.isPreISelOpcode())
11516
11517 // Atomics are divergent because they are executed sequentially: when an
11518 // atomic operation refers to the same address in each thread, then each
11519 // thread after the first sees the value written by the previous thread as
11520 // original value.
11521
11522 if (isAtomic(MI))
11524
11525 // Loads from the private and flat address spaces are divergent, because
11526 // threads can execute the load instruction with the same inputs and get
11527 // different results.
11528 if (isFLAT(MI) && MI.mayLoad()) {
11529 if (MI.memoperands_empty())
11530 return ValueUniformity::NeverUniform; // conservative assumption
11531
11532 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11533 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11534 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11535 })) {
11536 // At least one MMO in a non-global address space.
11538 }
11539
11541 }
11542
11543 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11544 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11545
11546 // FIXME: It's conceptually broken to report this for an instruction, and not
11547 // a specific def operand. For inline asm in particular, there could be mixed
11548 // uniform and divergent results.
11549 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11550 const MachineOperand &SrcOp = MI.getOperand(I);
11551 if (!SrcOp.isReg())
11552 continue;
11553
11554 Register Reg = SrcOp.getReg();
11555 if (!Reg || !SrcOp.readsReg())
11556 continue;
11557
11558 // If RegBank is null, this is unassigned or an unallocatable special
11559 // register, which are all scalars.
11560 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11561 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11563 }
11564
11565 // TODO: Uniformity check condtions above can be rearranged for more
11566 // redability
11567
11568 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11569 // currently turned into no-op COPYs by SelectionDAG ISel and are
11570 // therefore no longer recognizable.
11571
11573}
11574
11576 switch (MF.getFunction().getCallingConv()) {
11578 return 1;
11580 return 2;
11582 return 3;
11586 const Function &F = MF.getFunction();
11587 F.getContext().diagnose(DiagnosticInfoUnsupported(
11588 F, "ds_ordered_count unsupported for this calling conv"));
11589 [[fallthrough]];
11590 }
11593 case CallingConv::C:
11594 case CallingConv::Fast:
11595 default:
11596 // Assume other calling conventions are various compute callable functions
11597 return 0;
11598 }
11599}
11600
11602 Register &SrcReg2, int64_t &CmpMask,
11603 int64_t &CmpValue) const {
11604 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11605 return false;
11606
11607 switch (MI.getOpcode()) {
11608 default:
11609 break;
11610 case AMDGPU::S_CMP_EQ_U32:
11611 case AMDGPU::S_CMP_EQ_I32:
11612 case AMDGPU::S_CMP_LG_U32:
11613 case AMDGPU::S_CMP_LG_I32:
11614 case AMDGPU::S_CMP_LT_U32:
11615 case AMDGPU::S_CMP_LT_I32:
11616 case AMDGPU::S_CMP_GT_U32:
11617 case AMDGPU::S_CMP_GT_I32:
11618 case AMDGPU::S_CMP_LE_U32:
11619 case AMDGPU::S_CMP_LE_I32:
11620 case AMDGPU::S_CMP_GE_U32:
11621 case AMDGPU::S_CMP_GE_I32:
11622 case AMDGPU::S_CMP_EQ_U64:
11623 case AMDGPU::S_CMP_LG_U64:
11624 SrcReg = MI.getOperand(0).getReg();
11625 if (MI.getOperand(1).isReg()) {
11626 if (MI.getOperand(1).getSubReg())
11627 return false;
11628 SrcReg2 = MI.getOperand(1).getReg();
11629 CmpValue = 0;
11630 } else if (MI.getOperand(1).isImm()) {
11631 SrcReg2 = Register();
11632 CmpValue = MI.getOperand(1).getImm();
11633 } else {
11634 return false;
11635 }
11636 CmpMask = ~0;
11637 return true;
11638 case AMDGPU::S_CMPK_EQ_U32:
11639 case AMDGPU::S_CMPK_EQ_I32:
11640 case AMDGPU::S_CMPK_LG_U32:
11641 case AMDGPU::S_CMPK_LG_I32:
11642 case AMDGPU::S_CMPK_LT_U32:
11643 case AMDGPU::S_CMPK_LT_I32:
11644 case AMDGPU::S_CMPK_GT_U32:
11645 case AMDGPU::S_CMPK_GT_I32:
11646 case AMDGPU::S_CMPK_LE_U32:
11647 case AMDGPU::S_CMPK_LE_I32:
11648 case AMDGPU::S_CMPK_GE_U32:
11649 case AMDGPU::S_CMPK_GE_I32:
11650 SrcReg = MI.getOperand(0).getReg();
11651 SrcReg2 = Register();
11652 CmpValue = MI.getOperand(1).getImm();
11653 CmpMask = ~0;
11654 return true;
11655 }
11656
11657 return false;
11658}
11659
11661 for (MachineBasicBlock *S : MBB->successors()) {
11662 if (S->isLiveIn(AMDGPU::SCC))
11663 return false;
11664 }
11665 return true;
11666}
11667
11668// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11669// (incoming SCC) = !(SCC defined by SCCDef).
11670// Return true if all uses can be re-written, false otherwise.
11671bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11672 MachineBasicBlock *MBB = SCCDef->getParent();
11673 SmallVector<MachineInstr *> InvertInstr;
11674 bool SCCIsDead = false;
11675
11676 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11677 constexpr unsigned ScanLimit = 12;
11678 unsigned Count = 0;
11679 for (MachineInstr &MI : instructionsWithoutDebug(
11680 std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11681 if (++Count > ScanLimit)
11682 return false;
11683 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11684 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11685 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11686 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11687 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11688 InvertInstr.push_back(&MI);
11689 else
11690 return false;
11691 }
11692 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11693 SCCIsDead = true;
11694 break;
11695 }
11696 }
11697 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11698 SCCIsDead = true;
11699
11700 // SCC may have more uses. Can't invert all of them.
11701 if (!SCCIsDead)
11702 return false;
11703
11704 // Invert uses
11705 for (MachineInstr *MI : InvertInstr) {
11706 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11707 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11708 swapOperands(*MI);
11709 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11710 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11711 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11712 ? AMDGPU::S_CBRANCH_SCC1
11713 : AMDGPU::S_CBRANCH_SCC0));
11714 } else {
11715 llvm_unreachable("SCC used but no inversion handling");
11716 }
11717 }
11718 return true;
11719}
11720
11721// SCC is already valid after SCCValid.
11722// SCCRedefine will redefine SCC to the same value already available after
11723// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11724// update kill/dead flags if necessary.
11725bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11726 bool NeedInversion) const {
11727 MachineInstr *KillsSCC = nullptr;
11728 if (SCCValid->getParent() != SCCRedefine->getParent())
11729 return false;
11730 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11731 SCCRedefine->getIterator())) {
11732 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11733 return false;
11734 if (MI.killsRegister(AMDGPU::SCC, &RI))
11735 KillsSCC = &MI;
11736 }
11737 if (NeedInversion && !invertSCCUse(SCCRedefine))
11738 return false;
11739 if (MachineOperand *SccDef =
11740 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11741 SccDef->setIsDead(false);
11742 if (KillsSCC)
11743 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11744 SCCRedefine->eraseFromParent();
11745 return true;
11746}
11747
11748/// If \p Sel is an S_CSELECT* of two different constants A and B, return them,
11749/// truncated to the width of the select.
11750static std::optional<std::pair<int64_t, int64_t>>
11752 const MachineInstr &Sel) {
11753 unsigned Opc = Sel.getOpcode();
11754 if (Opc != AMDGPU::S_CSELECT_B32 && Opc != AMDGPU::S_CSELECT_B64)
11755 return {};
11756 std::optional<int64_t> A =
11757 TII.getImmOrMaterializedImm(MRI, Sel.getOperand(1));
11758 if (!A)
11759 return {};
11760 std::optional<int64_t> B =
11761 TII.getImmOrMaterializedImm(MRI, Sel.getOperand(2));
11762 if (!B)
11763 return {};
11764 if (Opc == AMDGPU::S_CSELECT_B32) {
11765 A = Lo_32(*A);
11766 B = Lo_32(*B);
11767 }
11768 if (*A == *B)
11769 return {};
11770 return std::pair(*A, *B);
11771}
11772
11773static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11774 unsigned &NewDefOpc) {
11775 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11776 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11777 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11778 Def.getOpcode() != AMDGPU::S_ADD_U32)
11779 return false;
11780 const MachineOperand &AddSrc1 = Def.getOperand(1);
11781 const MachineOperand &AddSrc2 = Def.getOperand(2);
11782 const MachineRegisterInfo &MRI = Def.getMF()->getRegInfo();
11783 const SIInstrInfo *TII = static_cast<const SIInstrInfo *>(
11784 Def.getMF()->getSubtarget().getInstrInfo());
11785
11786 auto Imm1 = TII->getImmOrMaterializedImm(MRI, AddSrc1);
11787 auto Imm2 = TII->getImmOrMaterializedImm(MRI, AddSrc2);
11788 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11789 return false;
11790
11791 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11792 const MachineOperand *SccDef =
11793 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11794 if (!SccDef->isDead())
11795 return false;
11796 NewDefOpc = AMDGPU::S_ADD_U32;
11797 }
11798 NeedInversion = !NeedInversion;
11799 return true;
11800}
11801
11803 Register SrcReg2, int64_t CmpMask,
11804 int64_t CmpValue,
11805 const MachineRegisterInfo *MRI) const {
11806 if (!SrcReg || SrcReg.isPhysical())
11807 return false;
11808
11809 if (SrcReg2) {
11810 auto ImmOpt = getImmOrMaterializedImm(*MRI, SrcReg2);
11811 if (!ImmOpt)
11812 return false;
11813 CmpValue = *ImmOpt;
11814 }
11815
11816 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11817 this](bool NeedInversion) -> bool {
11818 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11819 if (!Def)
11820 return false;
11821
11822 unsigned NewDefOpc = Def->getOpcode();
11823 if (auto Consts = getSelectConstants(*this, *MRI, *Def)) {
11824 // sX = S_CSELECT* A, B with A != B, so sX == A exactly when SCC was set.
11825 // Comparing sX with A or B recomputes SCC or its inverse:
11826 //
11827 // s_cmp_eq_* sX, A => SCC s_cmp_lg_* sX, A => !SCC
11828 // s_cmp_eq_* sX, B => !SCC s_cmp_lg_* sX, B => SCC
11829 auto [A, B] = *Consts;
11830 int64_t C = Def->getOpcode() == AMDGPU::S_CSELECT_B32 ? Lo_32(CmpValue)
11831 : CmpValue;
11832 if (C == A)
11833 NeedInversion = !NeedInversion;
11834 else if (C != B)
11835 return false;
11836 } else {
11837 // For S_OP that set SCC = DST!=0, do the transformation
11838 //
11839 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11840 //
11841 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11842 // do the transformation:
11843 //
11844 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11845 if (CmpValue != 0 ||
11846 (!setsSCCIfResultIsNonZero(*Def) &&
11847 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc)))
11848 return false;
11849 }
11850
11851 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11852 return false;
11853
11854 if (NewDefOpc != Def->getOpcode())
11855 Def->setDesc(get(NewDefOpc));
11856
11857 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11858 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11859 // 64-bit select then delete s_or_b32 in the sequence:
11860 // sX = s_cselect_b64 A, B (A != B, one of them 0)
11861 // sLo = copy sX.sub0
11862 // sHi = copy sX.sub1
11863 // sY = s_or_b32 sLo, sHi
11864 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11865 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11866 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11867 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11868 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11869 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11870 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11871 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11872 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11873 Def2->getOperand(1).isReg() &&
11874 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11875 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11876 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11877 if (MachineInstr *Select =
11878 MRI->getVRegDef(Def1->getOperand(1).getReg())) {
11879 if (auto Consts = getSelectConstants(*this, *MRI, *Select)) {
11880 auto [A, B] = *Consts;
11881 if (A == 0 || B == 0)
11882 optimizeSCC(Select, Def, /*NeedInversion=*/A == 0);
11883 }
11884 }
11885 }
11886 }
11887 }
11888 return true;
11889 };
11890
11891 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11892 this](int64_t ExpectedValue, unsigned SrcSize,
11893 bool IsReversible, bool IsSigned) -> bool {
11894 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11895 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11896 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11897 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11898 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11899 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11900 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11901 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11902 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11903 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11904 //
11905 // Signed ge/gt are not used for the sign bit.
11906 //
11907 // If result of the AND is unused except in the compare:
11908 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11909 //
11910 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11911 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11912 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11913 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11914 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11915 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11916
11917 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11918 if (!Def)
11919 return false;
11920
11921 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11922 Def->getOpcode() != AMDGPU::S_AND_B64)
11923 return false;
11924
11925 int64_t Mask;
11926 const auto isMask = [&Mask, SrcSize, MRI,
11927 this](const MachineOperand *MO) -> bool {
11928 auto ImmOpt = this->getImmOrMaterializedImm(*MRI, *MO);
11929 if (!ImmOpt)
11930 return false;
11931 Mask = *ImmOpt;
11932 Mask &= maxUIntN(SrcSize);
11933 return isPowerOf2_64(Mask);
11934 };
11935
11936 MachineOperand *SrcOp = &Def->getOperand(1);
11937 if (isMask(SrcOp))
11938 SrcOp = &Def->getOperand(2);
11939 else if (isMask(&Def->getOperand(2)))
11940 SrcOp = &Def->getOperand(1);
11941 else
11942 return false;
11943
11944 // A valid Mask is required to have a single bit set, hence a non-zero and
11945 // power-of-two value. This verifies that we will not do 64-bit shift below.
11946 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11947 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11948 if (IsSigned && BitNo == SrcSize - 1)
11949 return false;
11950
11951 ExpectedValue <<= BitNo;
11952
11953 bool IsReversedCC = false;
11954 if (CmpValue != ExpectedValue) {
11955 if (!IsReversible)
11956 return false;
11957 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11958 if (!IsReversedCC)
11959 return false;
11960 }
11961
11962 Register DefReg = Def->getOperand(0).getReg();
11963 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11964 return false;
11965
11966 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11967 return false;
11968
11969 if (!MRI->use_nodbg_empty(DefReg)) {
11970 assert(!IsReversedCC);
11971 return true;
11972 }
11973
11974 // Replace AND with unused result with a S_BITCMP.
11975 MachineBasicBlock *MBB = Def->getParent();
11976
11977 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11978 : AMDGPU::S_BITCMP1_B32
11979 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11980 : AMDGPU::S_BITCMP1_B64;
11981
11982 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11983 .add(*SrcOp)
11984 .addImm(BitNo);
11985 Def->eraseFromParent();
11986
11987 return true;
11988 };
11989
11990 switch (CmpInstr.getOpcode()) {
11991 default:
11992 break;
11993 case AMDGPU::S_CMP_EQ_U32:
11994 case AMDGPU::S_CMP_EQ_I32:
11995 case AMDGPU::S_CMPK_EQ_U32:
11996 case AMDGPU::S_CMPK_EQ_I32:
11997 return optimizeCmpAnd(1, 32, true, false) ||
11998 optimizeCmpSelect(/*NeedInversion=*/true);
11999 case AMDGPU::S_CMP_GE_U32:
12000 case AMDGPU::S_CMPK_GE_U32:
12001 return optimizeCmpAnd(1, 32, false, false);
12002 case AMDGPU::S_CMP_GE_I32:
12003 case AMDGPU::S_CMPK_GE_I32:
12004 return optimizeCmpAnd(1, 32, false, true);
12005 case AMDGPU::S_CMP_EQ_U64:
12006 return optimizeCmpAnd(1, 64, true, false) ||
12007 optimizeCmpSelect(/*NeedInversion=*/true);
12008 case AMDGPU::S_CMP_LG_U32:
12009 case AMDGPU::S_CMP_LG_I32:
12010 case AMDGPU::S_CMPK_LG_U32:
12011 case AMDGPU::S_CMPK_LG_I32:
12012 return optimizeCmpAnd(0, 32, true, false) ||
12013 optimizeCmpSelect(/*NeedInversion=*/false);
12014 case AMDGPU::S_CMP_GT_U32:
12015 case AMDGPU::S_CMPK_GT_U32:
12016 return optimizeCmpAnd(0, 32, false, false);
12017 case AMDGPU::S_CMP_GT_I32:
12018 case AMDGPU::S_CMPK_GT_I32:
12019 return optimizeCmpAnd(0, 32, false, true);
12020 case AMDGPU::S_CMP_LG_U64:
12021 return optimizeCmpAnd(0, 64, true, false) ||
12022 optimizeCmpSelect(/*NeedInversion=*/false);
12023 }
12024
12025 return false;
12026}
12027
12029 AMDGPU::OpName OpName) const {
12030 if (!ST.needsAlignedVGPRs())
12031 return;
12032
12033 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
12034 if (OpNo < 0)
12035 return;
12036 MachineOperand &Op = MI.getOperand(OpNo);
12037 if (getOpSize(MI, OpNo) > 4)
12038 return;
12039
12040 // Add implicit aligned super-reg to force alignment on the data operand.
12041 const DebugLoc &DL = MI.getDebugLoc();
12042 MachineBasicBlock *BB = MI.getParent();
12044 Register DataReg = Op.getReg();
12045 bool IsAGPR = RI.isAGPR(MRI, DataReg);
12047 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
12048 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
12049 Register NewVR =
12050 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
12051 : &AMDGPU::VReg_64_Align2RegClass);
12052 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
12053 .addReg(DataReg, {}, Op.getSubReg())
12054 .addImm(AMDGPU::sub0)
12055 .addReg(Undef)
12056 .addImm(AMDGPU::sub1);
12057 Op.setReg(NewVR);
12058 Op.setSubReg(AMDGPU::sub0);
12059 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
12060}
12061
12063 if (!SchedModel.hasInstrSchedModel())
12064 return 0;
12065
12066 // The repeat rate is the throughput-limiting resource occupancy: the largest
12067 // number of cycles any written processor resource is held.
12068 const MCSchedClassDesc *SCDesc = SchedModel.resolveSchedClass(&MI);
12069 unsigned RepeatRate = 0;
12071 PI = SchedModel.getWriteProcResBegin(SCDesc),
12072 PE = SchedModel.getWriteProcResEnd(SCDesc);
12073 PI != PE; ++PI) {
12074 RepeatRate = std::max(RepeatRate, (unsigned)PI->ReleaseAtCycle);
12075 }
12076
12077 return RepeatRate;
12078}
12079
12081 if (isIGLP(*MI))
12082 return false;
12083
12085}
12086
12088 if (!isWMMA(MI) && !isSWMMAC(MI))
12089 return false;
12090
12091 if (ST.hasGFX1250Insts())
12092 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
12093
12094 return true;
12095}
12096
12098 unsigned Opcode = MI.getOpcode();
12099
12100 if (AMDGPU::isGFX12Plus(ST))
12101 return isDOT(MI) || isXDLWMMA(MI);
12102
12103 if (!isMAI(MI) || isDGEMM(Opcode) ||
12104 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
12105 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
12106 return false;
12107
12108 if (!ST.hasGFX940Insts())
12109 return true;
12110
12111 return AMDGPU::getMAIIsGFX940XDL(Opcode);
12112}
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!")
unsigned Imm
unsigned uint64_t
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
AMDGPU Register Bank Select
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static bool isUndef(const MachineInstr &MI)
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
uint64_t High
uint64_t IntrinsicInst * II
#define P(N)
R600 Clause Merge
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static cl::opt< bool > Fix16BitCopies("amdgpu-fix-16-bit-physreg-copies", cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"), cl::init(true), cl::ReallyHidden)
static void expandSGPRCopy(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RC, bool Forward)
static std::optional< std::pair< int64_t, int64_t > > getSelectConstants(const SIInstrInfo &TII, const MachineRegisterInfo &MRI, const MachineInstr &Sel)
If Sel is an S_CSELECT* of two different constants A and B, return them, truncated to the width of th...
static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc)
static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize)
static bool compareMachineOp(const MachineOperand &Op0, const MachineOperand &Op1)
static bool isStride64(unsigned Opc)
static MachineBasicBlock * generateWaterFallLoop(const SIInstrInfo &TII, MachineInstr &MI, ArrayRef< MachineOperand * > ScalarOps, MachineDominatorTree *MDT, MachineBasicBlock::iterator Begin=nullptr, MachineBasicBlock::iterator End=nullptr, ArrayRef< Register > PhySGPRs={})
#define GENERATE_RENAMED_GFX9_CASES(OPCODE)
static std::tuple< unsigned, unsigned > extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc)
static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx)
static bool followSubRegDef(MachineInstr &MI, TargetInstrInfo::RegSubRegPair &RSR)
static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize)
static MachineInstr * swapImmOperands(MachineInstr &MI, MachineOperand &NonRegOp1, MachineOperand &NonRegOp2)
static void copyFlagsToImplicitVCC(MachineInstr &MI, const MachineOperand &Orig)
static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, LocationSize WidthB, int OffsetB)
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, RegScavenger &RS, bool RegsOverlap, Register ImpUseSuperReg=Register())
Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908.
static unsigned getWWMRegSpillSaveOpcode(unsigned Size, bool IsVectorSuperClass)
static bool memOpsHaveSameBaseOperands(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getWWMRegSpillRestoreOpcode(unsigned Size, bool IsVectorSuperClass)
static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion, unsigned &NewDefOpc)
static bool isSCCDeadOnExit(MachineBasicBlock *MBB)
static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize)
static unsigned subtargetEncodingFamily(const GCNSubtarget &ST)
static void preserveCondRegFlags(MachineOperand &CondReg, const MachineOperand &OrigCond)
static Register findImplicitSGPRRead(const MachineInstr &MI)
static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc)
static cl::opt< unsigned > BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16), cl::desc("Restrict range of branch instructions (DEBUG)"))
static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getSGPRSpillRestoreOpcode(unsigned Size)
static bool isRegOrFI(const MachineOperand &MO)
static bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI)
Return true if MI is a VALU comparison, i.e.
static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static constexpr AMDGPU::OpName ModifierOpNames[]
static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const char *Msg="illegal VGPR to SGPR copy")
static MachineInstr * swapRegAndNonRegOperand(MachineInstr &MI, MachineOperand &RegOp, MachineOperand &NonRegOp)
static bool shouldReadExec(const MachineInstr &MI)
static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc)
static bool isRenamedInGFX9(int Opcode)
static TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd)
static std::tuple< unsigned, unsigned, unsigned > splitGlobalAddressRelocFlags(const GCNSubtarget &ST, const MachineOperand &SrcOp)
static bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
static bool nodesHaveSameOperandValue(SDNode *N0, SDNode *N1, AMDGPU::OpName OpName)
Returns true if both nodes have the same value for the given operand Op, or if both nodes do not have...
static unsigned getNumOperandsNoGlue(SDNode *Node)
static bool canRemat(const MachineInstr &MI)
static unsigned getAVSpillRestoreOpcode(unsigned Size)
static void emitLoadScalarOpsFromVGPRLoop(const SIInstrInfo &TII, MachineRegisterInfo &MRI, MachineBasicBlock &PredBB, MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={})
static unsigned getVGPRSpillRestoreOpcode(unsigned Size)
Interface definition for SIInstrInfo.
bool IsDead
const char * Msg
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
#define LLVM_DEBUG(...)
Definition Debug.h:119
static const LaneMaskConstants & get(const GCNSubtarget &ST)
static LLVM_ABI Semantics SemanticsToEnum(const llvm::fltSemantics &Sem)
Definition APFloat.cpp:185
Class for arbitrary precision integers.
Definition APInt.h:78
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
This class is the base class for the comparison instructions.
Definition InstrTypes.h:728
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A debug info location.
Definition DebugLoc.h:126
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:857
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:356
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:71
LiveInterval - This class represents the liveness of a register, or stack slot.
bool hasInterval(Register Reg) const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
LLVM_ABI bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
This class represents the liveness of a register, stack slot, etc.
bool hasValue() const
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:347
static const MCBinaryExpr * createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:417
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
unsigned getOpcode() const
Return the opcode number for this descriptor.
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition MCInstrDesc.h:88
uint8_t OperandType
Information about the type of the operand.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition MCInstrDesc.h:94
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void setVariableValue(const MCExpr *Value)
Definition MCSymbol.cpp:50
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
MIRFormater - Interface to format MIR operand based on target.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
void push_back(MachineInstr *MI)
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isImmutableObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an immutable object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
bool isCopy() const
const MachineBasicBlock * getParent() const
LLVM_ABI void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
bool isBundle() const
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromBundle()
Unlink 'this' from its basic block and delete it.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mop_range explicit_operands()
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just after the instruction itself.
LLVM_ABI void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo)
Clear all kill flags affecting Reg.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
const GlobalValue * getGlobal() const
LLVM_ABI void ChangeToFrameIndex(int Idx, unsigned TargetFlags=0)
Replace this operand with a frame index.
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
LLVM_ABI void ChangeToGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
ChangeToGA - Replace this operand with a new global address operand.
void setIsKill(bool Val=true)
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
void setOffset(int64_t Offset)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isTargetIndex() const
isTargetIndex - Tests if this is a MO_TargetIndex operand.
void setTargetFlags(unsigned F)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps)
Move NumOps operands from Src to Dst, updating use-def lists as needed.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
LLVM_ABI void clearVirtRegs()
clearVirtRegs - Remove all virtual registers (after physreg assignment).
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
const MachineFunction & getMF() const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI bool isConstantPhysReg(MCRegister PhysReg) const
Returns true if PhysReg is unallocatable and constant throughout the function.
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void removeRegOperandFromUseList(MachineOperand *MO)
Remove MO from its use-def list.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI void addRegOperandToUseList(MachineOperand *MO)
Add MO to the linked list of operands for its register.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
void decomposePkFMAF32(MachineInstr &MI, MachineRegisterInfo &MRI) const
Decompose a GFX950 v_pk_fma_f32 with invalid op_sel into two independent scalar V_FMA_F32_e64 instruc...
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isLegalPkFMAF32OpSel(const MachineInstr &MI) const
Check if MI has legal GFX950 v_pk_fma op_sel.
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
bool isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
unsigned getGFX1250BlockingCyclesTable(const MachineInstr &MI) const
GFX1250 blocking-cycles table lookup with no occupancy subtarget gate.
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const final
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
static bool isDOT(const MachineInstr &MI)
std::unique_ptr< PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
bool hasModifiers(unsigned Opcode) const
Return true if this instruction has any modifiers.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
static bool isSWMMAC(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
bool isWave32() const
bool isHighLatencyDef(int Opc) const override
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const
Legalize the OpIndex operand of this instruction by inserting a MOV.
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isVOPC(const MachineInstr &MI)
void removeModOperands(MachineInstr &MI) const
unsigned getRepeatRate(const MachineInstr &MI) const
Get the repeat rate for a VALU instruction from the scheduling model.
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool isLegalSingleSGPRReadInstOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for a single-SGPR-read instruction.
bool isXDL(const MachineInstr &MI) const
Register isStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
static bool isVIMAGE(const MachineInstr &MI)
void enforceOperandRCAlignment(MachineInstr &MI, AMDGPU::OpName OpName) const
static bool isSOP2(const MachineInstr &MI)
static bool isGWS(const MachineInstr &MI)
bool hasRAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI) const
bool isLegalAV64PseudoImm(uint64_t Imm) const
Check if this immediate value can be used for AV_MOV_B64_IMM_PSEUDO.
bool isNeverCoissue(MachineInstr &MI) const
static bool isBUF(const MachineInstr &MI)
bool isNonCommutableDPP(const MachineInstr &MI) const
void handleCopyToPhysHelper(SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst, MachineRegisterInfo &MRI, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
bool hasModifiersSet(const MachineInstr &MI, AMDGPU::OpName OpName) const
bool isLegalToSwap(const MachineInstr &MI, unsigned fromIdx, unsigned toIdx) const
static bool isFLATGlobal(const MachineInstr &MI)
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isGlobalMemoryObject(const MachineInstr *MI) const override
bool canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, SelectExpansion &Exp) const override
static bool isVSAMPLE(const MachineInstr &MI)
bool isBufferSMRD(const MachineInstr &MI) const
static bool isKillTerminator(unsigned Opcode)
bool isVOPDAntidependencyAllowed(const MachineInstr &MI) const
If OpX is multicycle, anti-dependencies are not allowed.
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
void insertScratchExecCopy(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, bool IsSCCLive, SlotIndexes *Indexes=nullptr) const
bool hasVALU32BitEncoding(unsigned Opcode) const
Return true if this 64-bit VALU instruction has a 32-bit encoding.
unsigned getBlockingCycles(const MachineInstr &MI) const
unsigned getMovOpcode(const TargetRegisterClass *DstRC) const
Register isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
unsigned buildExtractSubReg(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const
Legalize operands in MI by either commuting it or inserting a copy of src1.
static bool isVPermPk16(unsigned Opcode)
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const final
static bool isTRANS(const MachineInstr &MI)
static bool isImage(const MachineInstr &MI)
static bool isSOPK(const MachineInstr &MI)
const TargetRegisterClass * getOpRegClass(const MachineInstr &MI, unsigned OpNo) const
Return the correct register class for OpNo.
MachineBasicBlock * insertSimulatedTrap(MachineRegisterInfo &MRI, MachineBasicBlock &MBB, MachineInstr &MI, const DebugLoc &DL) const
Build instructions that simulate the behavior of a s_trap 2 instructions for hardware (namely,...
static unsigned getNonSoftWaitcntOpcode(unsigned Opcode)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static bool isFoldableCopy(const MachineInstr &MI)
static bool isMUBUF(const MachineInstr &MI)
bool expandPostRAPseudo(MachineInstr &MI) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
void createWaterFallForSiCall(MachineInstr *MI, MachineDominatorTree *MDT, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={}) const
Wrapper function for generating waterfall for instruction MI This function take into consideration of...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSegmentSpecificFLAT(const MachineInstr &MI)
bool isReMaterializableImpl(const MachineInstr &MI) const override
static bool isVOP3(const MCInstrDesc &Desc)
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool physRegUsesConstantBus(const MachineOperand &Reg) const
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
bool mayAccessVMEMThroughFlat(const MachineInstr &MI) const
static bool isDPP(const MachineInstr &MI)
bool analyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
static bool isMFMA(const MachineInstr &MI)
bool isLowLatencyInstruction(const MachineInstr &MI) const
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is a instruction that moves/copies value from one register to ano...
void mutateAndCleanupImplicit(MachineInstr &MI, const MCInstrDesc &NewDesc) const
ValueUniformity getGenericValueUniformity(const MachineInstr &MI) const
static bool isMAI(const MCInstrDesc &Desc)
static bool isSrc1DPPRevOpcode(const GCNSubtarget &ST, uint32_t Opcode)
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const override
static bool usesLGKM_CNT(const MachineInstr &MI)
void legalizeOperandsVALUt16(MachineInstr &Inst, MachineRegisterInfo &MRI) const
Fix operands in Inst to fix 16bit SALU to VALU lowering.
bool isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo, const MachineOperand &MO) const
bool canShrink(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
const MachineOperand & getCalleeOperand(const MachineInstr &MI) const override
bool isAsmOnlyOpcode(int MCOp) const
Check if this instruction should only be used by assembler.
bool isAlwaysGDS(uint32_t Opcode) const
static bool isVGPRSpill(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
This is used by the post-RA scheduler (SchedulePostRAList.cpp).
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
unsigned getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr &MI, unsigned *PredCost=nullptr) const override
unsigned getVectorRegSpillSaveOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI, bool NeedsCFI) const
int64_t getNamedImmOperand(const MachineInstr &MI, AMDGPU::OpName OperandName) const
Get required immediate operand.
ArrayRef< std::pair< int, const char * > > getSerializableTargetIndices() const override
bool regUsesConstantBus(const MachineOperand &Reg, const MachineRegisterInfo &MRI) const
static bool isMIMG(const MachineInstr &MI)
MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isLegalRegOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO (a register operand) is a legal register for the given operand description or operand ind...
static unsigned getNumWaitStates(const MachineInstr &MI)
Return the number of wait states that result from executing this instruction.
unsigned getVALUOp(const MachineInstr &MI) const
static bool modifiesModeRegister(const MachineInstr &MI)
Return true if the instruction modifies the mode register.q.
Register readlaneVGPRToSGPR(Register SrcReg, MachineInstr &UseMI, MachineRegisterInfo &MRI, const TargetRegisterClass *DstRC=nullptr) const
Copy a value from a VGPR (SrcReg) to SGPR.
bool hasDivergentBranch(const MachineBasicBlock *MBB) const
Return whether the block terminate with divergent branch.
std::pair< int64_t, int64_t > splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Split COffsetVal into {immediate offset field, remainder offset} values.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void fixImplicitOperands(MachineInstr &MI) const
bool moveFlatAddrToVGPR(MachineInstr &Inst) const
Change SADDR form of a FLAT Inst to its VADDR form if saddr operand was moved to VGPR.
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool isMaskedByExec(Register Reg, const MachineInstr &Use, const MachineRegisterInfo &MRI, unsigned Depth=0) const
Return true if Reg is a lane mask that already has 0 in every bit corresponding to a lane that is ina...
void createReadFirstLaneFromCopyToPhysReg(MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const
bool swapSourceModifiers(MachineInstr &MI, MachineOperand &Src0, AMDGPU::OpName Src0OpName, MachineOperand &Src1, AMDGPU::OpName Src1OpName) const
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
bool memOpsHaveSameBase(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2) const
Return true if the memory operations described by BaseOps1 and BaseOps2 (as returned by getMemOperand...
bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const
This function is used to determine if an instruction can be safely executed under EXEC = 0 without ha...
bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg, int64_t &ImmVal) const override
static bool isAtomic(const MachineInstr &MI)
bool isLiteralOperandLegal(const MCInstrDesc &InstDesc, const MCOperandInfo &OpInfo) const
static bool isWWMRegSpillOpcode(uint32_t Opcode)
static bool sopkIsZext(unsigned Opcode)
static bool isSGPRSpill(const MachineInstr &MI)
static bool isWMMA(const MachineInstr &MI)
ArrayRef< std::pair< MachineMemOperand::Flags, const char * > > getSerializableMachineMemOperandTargetFlags() const override
bool mayReadEXEC(const MachineRegisterInfo &MRI, const MachineInstr &MI) const
Returns true if the instruction could potentially depend on the value of exec.
void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
std::pair< MachineInstr *, MachineInstr * > expandMovDPP64(MachineInstr &MI) const
static bool isSOPC(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
bool isBarrier(unsigned Opcode) const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx0, unsigned OpIdx1) const override
bool mayAccessLDSThroughFlat(const MachineInstr &MI, bool TgSplit) const
int pseudoToMCOpcode(int Opcode) const
Return a target-specific opcode if Opcode is a pseudo instruction.
const MCInstrDesc & getMCOpcodeFromPseudo(unsigned Opcode) const
Return the descriptor of the target-specific machine instruction that corresponds to the specified ps...
static bool usesVM_CNT(const MachineInstr &MI)
MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const override
static bool isFixedSize(const MachineInstr &MI)
bool isSafeToSink(MachineInstr &MI, MachineBasicBlock *SuccToSinkTo, MachineCycleInfo *CI) const override
LLVM_READONLY int commuteOpcode(unsigned Opc) const
ValueUniformity getValueUniformity(const MachineInstr &MI) const final
uint64_t getScratchRsrcWords23() const
LLVM_READONLY MachineOperand * getNamedOperand(MachineInstr &MI, AMDGPU::OpName OperandName) const
Returns the operand named Op.
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveIntervals *LIS) const override
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx, const MachineOperand *MO=nullptr) const
Check if MO is a legal operand if it was the OpIdx Operand for MI.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool allowNegativeFlatOffset(AMDGPU::FlatAddrSpace FlatVariant) const
Returns true if negative offsets are allowed for the given FlatVariant.
void moveToVALUImpl(SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
static bool isLDSDMA(const MachineInstr &MI)
static bool isVOP1(const MachineInstr &MI)
SIInstrInfo(const GCNSubtarget &ST)
std::optional< int64_t > getImmOrMaterializedImm(const MachineRegisterInfo &MRI, const MachineOperand &Op, MachineInstr **DefMI=nullptr) const
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool hasAnyModifiersSet(const MachineInstr &MI) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
void setHasSpilledVGPRs(bool Spill=true)
bool isWWMReg(Register Reg) const
bool checkFlag(Register Reg, uint8_t Flag) const
void setHasSpilledSGPRs(bool Spill=true)
unsigned getScratchReservedForDynamicVGPRs() const
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:66
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndexes pass.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:293
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
int64_t getImm() const
Register getReg() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Object returned by analyzeLoopForPipelining.
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:339
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:187
self_iterator getIterator()
Definition ilist_node.h:123
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
@ OPERAND_REG_IMM_V2FP64
Definition SIDefines.h:441
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:459
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:426
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:434
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:450
@ OPERAND_REG_IMM_NOINLINE_FP16
Definition SIDefines.h:432
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:447
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:452
@ OPERAND_REG_IMM_V2INT64
Definition SIDefines.h:437
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:436
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:430
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:425
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:433
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:431
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:435
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:446
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:444
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:438
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:429
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:453
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:464
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:465
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:439
@ OPERAND_SDWA_VOPC_DST
Definition SIDefines.h:476
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:428
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:449
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:445
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:451
@ OPERAND_INLINE_C_AV64_PSEUDO
Definition SIDefines.h:470
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:440
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:466
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:448
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:427
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:456
LLVM_READONLY int32_t getBasicFromSDWAOp(uint32_t Opcode)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
@ TI_SCRATCH_RSRC_DWORD1
Definition AMDGPU.h:667
@ TI_SCRATCH_RSRC_DWORD3
Definition AMDGPU.h:669
@ TI_SCRATCH_RSRC_DWORD0
Definition AMDGPU.h:666
@ TI_SCRATCH_RSRC_DWORD2
Definition AMDGPU.h:668
@ TI_CONSTDATA_START
Definition AMDGPU.h:665
bool isSingleSGPRReadInst(unsigned Opc)
Packed instructions that read a single SGPR for SGPR operands, except for 64-bit elements which read ...
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
const uint64_t RSRC_INDEX_STRIDE_SHIFT
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition CallingConv.h:41
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ OPERAND_GENERIC_4
Definition MCInstrDesc.h:71
@ OPERAND_GENERIC_2
Definition MCInstrDesc.h:69
@ OPERAND_GENERIC_1
Definition MCInstrDesc.h:68
@ OPERAND_GENERIC_3
Definition MCInstrDesc.h:70
@ OPERAND_IMMEDIATE
Definition MCInstrDesc.h:61
@ OPERAND_GENERIC_0
Definition MCInstrDesc.h:67
@ OPERAND_GENERIC_5
Definition MCInstrDesc.h:72
Not(const Pred &P) -> Not< Pred >
constexpr bool isSDWA(const T &...O)
Definition SIDefines.h:249
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
Definition Threading.h:280
@ Offset
Definition DWP.cpp:577
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
constexpr uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
Definition MathExtras.h:208
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:541
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
Op::Description Desc
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg)
Return the SubReg component from REG_SEQUENCE.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
Definition SIInstrInfo.h:45
constexpr bool has_single_bit(T Value) noexcept
Definition bit.h:149
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
MachineInstr * getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, const MachineRegisterInfo &MRI)
Return the defining instruction for a given reg:subreg pair skipping copy like instructions and subre...
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI VirtRegInfo AnalyzeVirtRegInBundle(MachineInstr &MI, Register Reg, SmallVectorImpl< std::pair< MachineInstr *, unsigned > > *Ops=nullptr)
AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses a virtual register.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
Definition SIInstrInfo.h:53
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
Definition SIInstrInfo.h:41
constexpr unsigned BitWidth
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition SIInstrInfo.h:49
constexpr T reverseBits(T Val)
Reverse the bits in Val.
Definition MathExtras.h:119
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:567
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:267
constexpr RegState getUndefRegState(bool B)
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
Definition Uniformity.h:18
@ AlwaysUniform
The result value is always uniform.
Definition Uniformity.h:23
@ NeverUniform
The result value can never be assumed to be uniform.
Definition Uniformity.h:26
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
Definition SIInstrInfo.h:64
bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI)
Return false if EXEC is not changed between the def of VReg at DefMI and all its uses.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr bool all() const
Definition LaneBitmask.h:54
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:130
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Utility to store machine instructions worklist.
Definition SIInstrInfo.h:68
MachineInstr * top() const
Definition SIInstrInfo.h:73
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
Definition SIInstrInfo.h:91
void insert(MachineInstr *MI)
A pair composed of a register and a sub-register index.
VirtRegInfo - Information about a virtual register used by a set of operands.
bool Reads
Reads - One of the operands read the virtual register.
bool Writes
Writes - One of the operands writes the virtual register.