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"
34#include "llvm/IR/IntrinsicsAMDGPU.h"
35#include "llvm/MC/MCContext.h"
38#include <tuple>
39
40using namespace llvm;
41
42#define DEBUG_TYPE "si-instr-info"
43
44#define GET_INSTRINFO_CTOR_DTOR
45#include "AMDGPUGenInstrInfo.inc"
46
47namespace llvm::AMDGPU {
48#define GET_ImageDimIntrinsicTable_IMPL
49#define GET_RsrcIntrinsics_IMPL
50#include "AMDGPUGenSearchableTables.inc"
51} // namespace llvm::AMDGPU
52
53// Must be at least 4 to be able to branch over minimum unconditional branch
54// code. This is only for making it possible to write reasonably small tests for
55// long branches.
57BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16),
58 cl::desc("Restrict range of branch instructions (DEBUG)"));
59
61 "amdgpu-fix-16-bit-physreg-copies",
62 cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"),
63 cl::init(true),
65
67 : AMDGPUGenInstrInfo(ST, RI, AMDGPU::ADJCALLSTACKUP,
68 AMDGPU::ADJCALLSTACKDOWN),
69 RI(ST), ST(ST) {
70 SchedModel.init(&ST);
71}
72
73//===----------------------------------------------------------------------===//
74// TargetInstrInfo callbacks
75//===----------------------------------------------------------------------===//
76
77static unsigned getNumOperandsNoGlue(SDNode *Node) {
78 unsigned N = Node->getNumOperands();
79 while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
80 --N;
81 return N;
82}
83
84/// Returns true if both nodes have the same value for the given
85/// operand \p Op, or if both nodes do not have this operand.
87 AMDGPU::OpName OpName) {
88 unsigned Opc0 = N0->getMachineOpcode();
89 unsigned Opc1 = N1->getMachineOpcode();
90
91 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName);
92 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName);
93
94 if (Op0Idx == -1 && Op1Idx == -1)
95 return true;
96
97
98 if ((Op0Idx == -1 && Op1Idx != -1) ||
99 (Op1Idx == -1 && Op0Idx != -1))
100 return false;
101
102 // getNamedOperandIdx returns the index for the MachineInstr's operands,
103 // which includes the result as the first operand. We are indexing into the
104 // MachineSDNode's operands, so we need to skip the result operand to get
105 // the real index.
106 --Op0Idx;
107 --Op1Idx;
108
109 return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx);
110}
111
112static bool canRemat(const MachineInstr &MI) {
113
117 return true;
118
119 if (SIInstrInfo::isSMRD(MI)) {
120 return !MI.memoperands_empty() &&
121 llvm::all_of(MI.memoperands(), [](const MachineMemOperand *MMO) {
122 return MMO->isLoad() && MMO->isInvariant();
123 });
124 }
125
126 return false;
127}
128
129// Split relocation flags for 64-bit global-address materialization into a
130// common base and the hi/lo relocation variants.
131static std::tuple<unsigned, unsigned, unsigned>
133 const MachineOperand &SrcOp) {
134 const unsigned BaseFlags = SrcOp.getTargetFlags() & ~SIInstrInfo::MO_MASK;
135 const unsigned Reloc = SrcOp.getTargetFlags() & SIInstrInfo::MO_MASK;
136
137 // Infer the relocation type from the existing flags on the global operand.
138 // The relocation type should have been determined earlier in the pipeline.
139 unsigned LoReloc, HiReloc;
140 switch (Reloc) {
144 LoReloc = SIInstrInfo::MO_REL32_LO;
145 HiReloc = SIInstrInfo::MO_REL32_HI;
146 break;
151 break;
154 // For 64-bit GOT-relative, use the 64-bit relocation.
157 break;
161 LoReloc = SIInstrInfo::MO_ABS32_LO;
162 HiReloc = SIInstrInfo::MO_ABS32_HI;
163 break;
164 default:
165 llvm_unreachable("unknown relocation type for global address");
166 break;
167 }
168
169 return {BaseFlags, LoReloc, HiReloc};
170}
171
173 const MachineInstr &MI) const {
174
175 if (canRemat(MI)) {
176 // Normally VALU use of exec would block the rematerialization, but that
177 // is OK in this case to have an implicit exec read as all VALU do.
178 // We really want all of the generic logic for this except for this.
179
180 // Another potential implicit use is mode register. The core logic of
181 // the RA will not attempt rematerialization if mode is set anywhere
182 // in the function, otherwise it is safe since mode is not changed.
183
184 // There is difference to generic method which does not allow
185 // rematerialization if there are virtual register uses. We allow this,
186 // therefore this method includes SOP instructions as well.
187 if (!MI.hasImplicitDef() &&
188 MI.getNumImplicitOperands() == MI.getDesc().implicit_uses().size() &&
189 !MI.mayRaiseFPException())
190 return true;
191 }
192
193 // Everything below copied from TargetInstrInfo::isReMaterializableImpl. The
194 // only difference is that we allow operations that perform read-modify-write
195 // on sub-registers.
196
197 // Remat clients assume operand 0 is the defined register.
198 if (!MI.getNumOperands() || !MI.getOperand(0).isReg())
199 return false;
200 Register DefReg = MI.getOperand(0).getReg();
201
202 const MachineFunction &MF = *MI.getMF();
203
204 // A load from a fixed stack slot can be rematerialized. This may be
205 // redundant with subsequent checks, but it's target-independent,
206 // simple, and a common case.
207 int FrameIdx = 0;
208 if (isLoadFromStackSlot(MI, FrameIdx) &&
210 return true;
211
212 // Avoid instructions obviously unsafe for remat.
213 if (MI.isNotDuplicable() || MI.mayStore() || MI.mayRaiseFPException() ||
214 MI.hasUnmodeledSideEffects())
215 return false;
216
217 // Don't remat inline asm. We have no idea how expensive it is
218 // even if it's side effect free.
219 if (MI.isInlineAsm())
220 return false;
221
222 // Avoid instructions which load from potentially varying memory.
223 if (MI.mayLoad() && !MI.isDereferenceableInvariantLoad())
224 return false;
225
226 const MachineRegisterInfo &MRI = MF.getRegInfo();
227
228 // If any of the registers accessed are non-constant, conservatively assume
229 // the instruction is not rematerializable.
230 for (const MachineOperand &MO : MI.operands()) {
231 if (!MO.isReg())
232 continue;
233 Register Reg = MO.getReg();
234 if (Reg == 0)
235 continue;
236
237 // Check for a well-behaved physical register.
238 if (Reg.isPhysical()) {
239 if (MO.isUse()) {
240 // If the physreg has no defs anywhere, it's just an ambient register
241 // and we can freely move its uses. Alternatively, if it's allocatable,
242 // it could get allocated to something with a def during allocation.
243 if (!MRI.isConstantPhysReg(Reg))
244 return false;
245 } else {
246 // A physreg def. We can't remat it.
247 return false;
248 }
249 continue;
250 }
251
252 // Only allow one virtual-register def. There may be multiple defs of the
253 // same virtual register, though.
254 if (MO.isDef() && Reg != DefReg)
255 return false;
256 }
257
258 return true;
259}
260
262 switch (Opcode) {
263 // v_subrev_u16 (gfx9)
264 case AMDGPU::V_SUBREV_U16_e32:
265 case AMDGPU::V_SUBREV_U16_e64:
266 // v_subrev_u32 (gfx9) / v_subrev_nc_u32 (gfx10+)
267 case AMDGPU::V_SUBREV_U32_e32:
268 case AMDGPU::V_SUBREV_U32_e64:
269 // v_subrev_co_u32
270 case AMDGPU::V_SUBREV_CO_U32_e32:
271 case AMDGPU::V_SUBREV_CO_U32_e64:
272 // v_subbrev_u32 (gfx9) / v_subrev_co_ci_u32 (gfx10+)
273 case AMDGPU::V_SUBBREV_U32_e32:
274 case AMDGPU::V_SUBBREV_U32_e64:
275 return true;
276 // REV shift opcodes worked this way before GFX11, verified on hardware
277 case AMDGPU::V_ASHRREV_I16_e32:
278 case AMDGPU::V_ASHRREV_I16_e64:
279 case AMDGPU::V_ASHRREV_I32_e32:
280 case AMDGPU::V_ASHRREV_I32_e64:
281 case AMDGPU::V_ASHRREV_I64_e64:
282 case AMDGPU::V_LSHLREV_B16_e32:
283 case AMDGPU::V_LSHLREV_B16_e64:
284 case AMDGPU::V_LSHLREV_B32_e32:
285 case AMDGPU::V_LSHLREV_B32_e64:
286 case AMDGPU::V_LSHLREV_B64_e64:
287 case AMDGPU::V_LSHRREV_B16_e32:
288 case AMDGPU::V_LSHRREV_B16_e64:
289 case AMDGPU::V_LSHRREV_B32_e32:
290 case AMDGPU::V_LSHRREV_B32_e64:
291 case AMDGPU::V_LSHRREV_B64_e64:
292 return !ST.hasGFX11Insts();
293 default:
294 return false;
295 }
296}
297
298// Returns true if the result of a VALU instruction depends on exec.
299bool SIInstrInfo::resultDependsOnExec(const MachineInstr &MI) const {
300 assert(isVALU(MI, /*AllowLDSDMA=*/true));
301
302 // If it is convergent it depends on EXEC.
303 if (MI.isConvergent())
304 return true;
305
306 // If it defines an SGPR it depends on EXEC, unless it's dead.
307 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
308 for (const MachineOperand &Def : MI.defs()) {
309 if (Def.isDead())
310 continue;
311
312 Register Reg = Def.getReg();
313 if (Reg && RI.isSGPRReg(MRI, Reg))
314 return true;
315 }
316
317 return false;
318}
319
320bool SIInstrInfo::isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const {
321 const MachineOperand &MO = MI.getOperand(OpIdx);
322 // Any implicit use of exec by VALU is not a real register read.
323 return MO.getReg() == AMDGPU::EXEC && MO.isImplicit() &&
324 isVALU(MI, /*AllowLDSDMA=*/true) && !resultDependsOnExec(MI);
325}
326
328 MachineBasicBlock *SuccToSinkTo,
329 MachineCycleInfo *CI) const {
330 // Allow sinking if MI edits lane mask (divergent i1 in sgpr).
331 if (MI.getOpcode() == AMDGPU::SI_IF_BREAK)
332 return true;
333
334 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
335 // Check if sinking of MI would create temporal divergent use.
336 for (auto Op : MI.uses()) {
337 if (Op.isReg() && Op.getReg().isVirtual() &&
338 RI.isSGPRClass(MRI.getRegClass(Op.getReg()))) {
339 MachineInstr *SgprDef = MRI.getVRegDef(Op.getReg());
340 if (!SgprDef)
341 continue;
342
343 // SgprDef defined inside cycle
344 CycleRef FromCycle = CI->getCycle(SgprDef->getParent());
345 if (!FromCycle)
346 continue;
347
348 CycleRef ToCycle = CI->getCycle(SuccToSinkTo);
349 // Check if there is a FromCycle that contains SgprDef's basic block but
350 // does not contain SuccToSinkTo and also has divergent exit condition.
351 while (FromCycle && !(ToCycle && CI->contains(FromCycle, ToCycle))) {
353 CI->getExitingBlocks(FromCycle, ExitingBlocks);
354
355 // FromCycle has divergent exit condition.
356 for (MachineBasicBlock *ExitingBlock : ExitingBlocks) {
357 if (hasDivergentBranch(ExitingBlock))
358 return false;
359 }
360
361 FromCycle = CI->getParentCycle(FromCycle);
362 }
363 }
364 }
365
366 return true;
367}
368
370 int64_t &Offset0,
371 int64_t &Offset1) const {
372 if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode())
373 return false;
374
375 unsigned Opc0 = Load0->getMachineOpcode();
376 unsigned Opc1 = Load1->getMachineOpcode();
377
378 // Make sure both are actually loads.
379 if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad())
380 return false;
381
382 // A mayLoad instruction without a def is not a load. Likely a prefetch.
383 if (!get(Opc0).getNumDefs() || !get(Opc1).getNumDefs())
384 return false;
385
386 if (isDS(Opc0) && isDS(Opc1)) {
387
388 // FIXME: Handle this case:
389 if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1))
390 return false;
391
392 // Check base reg.
393 if (Load0->getOperand(0) != Load1->getOperand(0))
394 return false;
395
396 // Skip read2 / write2 variants for simplicity.
397 // TODO: We should report true if the used offsets are adjacent (excluded
398 // st64 versions).
399 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
400 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
401 if (Offset0Idx == -1 || Offset1Idx == -1)
402 return false;
403
404 // XXX - be careful of dataless loads
405 // getNamedOperandIdx returns the index for MachineInstrs. Since they
406 // include the output in the operand list, but SDNodes don't, we need to
407 // subtract the index by one.
408 Offset0Idx -= get(Opc0).NumDefs;
409 Offset1Idx -= get(Opc1).NumDefs;
410 Offset0 = Load0->getConstantOperandVal(Offset0Idx);
411 Offset1 = Load1->getConstantOperandVal(Offset1Idx);
412 return true;
413 }
414
415 if (isSMRD(Opc0) && isSMRD(Opc1)) {
416 // Skip time and cache invalidation instructions.
417 if (!AMDGPU::hasNamedOperand(Opc0, AMDGPU::OpName::sbase) ||
418 !AMDGPU::hasNamedOperand(Opc1, AMDGPU::OpName::sbase))
419 return false;
420
421 unsigned NumOps = getNumOperandsNoGlue(Load0);
422 if (NumOps != getNumOperandsNoGlue(Load1))
423 return false;
424
425 // Check base reg.
426 if (Load0->getOperand(0) != Load1->getOperand(0))
427 return false;
428
429 // Match register offsets, if both register and immediate offsets present.
430 assert(NumOps == 4 || NumOps == 5);
431 if (NumOps == 5 && Load0->getOperand(1) != Load1->getOperand(1))
432 return false;
433
434 const ConstantSDNode *Load0Offset =
436 const ConstantSDNode *Load1Offset =
438
439 if (!Load0Offset || !Load1Offset)
440 return false;
441
442 Offset0 = Load0Offset->getZExtValue();
443 Offset1 = Load1Offset->getZExtValue();
444 return true;
445 }
446
447 // MUBUF and MTBUF can access the same addresses.
448 if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) {
449
450 // MUBUF and MTBUF have vaddr at different indices.
451 if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) ||
452 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) ||
453 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc))
454 return false;
455
456 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
457 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
458
459 if (OffIdx0 == -1 || OffIdx1 == -1)
460 return false;
461
462 // getNamedOperandIdx returns the index for MachineInstrs. Since they
463 // include the output in the operand list, but SDNodes don't, we need to
464 // subtract the index by one.
465 OffIdx0 -= get(Opc0).NumDefs;
466 OffIdx1 -= get(Opc1).NumDefs;
467
468 SDValue Off0 = Load0->getOperand(OffIdx0);
469 SDValue Off1 = Load1->getOperand(OffIdx1);
470
471 // The offset might be a FrameIndexSDNode.
472 if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1))
473 return false;
474
475 Offset0 = Off0->getAsZExtVal();
476 Offset1 = Off1->getAsZExtVal();
477 return true;
478 }
479
480 return false;
481}
482
483static bool isStride64(unsigned Opc) {
484 switch (Opc) {
485 case AMDGPU::DS_READ2ST64_B32:
486 case AMDGPU::DS_READ2ST64_B64:
487 case AMDGPU::DS_WRITE2ST64_B32:
488 case AMDGPU::DS_WRITE2ST64_B64:
489 return true;
490 default:
491 return false;
492 }
493}
494
497 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
498 const TargetRegisterInfo *TRI) const {
499 if (!LdSt.mayLoadOrStore())
500 return false;
501
502 unsigned Opc = LdSt.getOpcode();
503 OffsetIsScalable = false;
504 const MachineOperand *BaseOp, *OffsetOp;
505 int DataOpIdx;
506
507 if (isDS(LdSt)) {
508 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr);
509 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
510 if (OffsetOp) {
511 // Normal, single offset LDS instruction.
512 if (!BaseOp) {
513 // DS_CONSUME/DS_APPEND use M0 for the base address.
514 // TODO: find the implicit use operand for M0 and use that as BaseOp?
515 return false;
516 }
517 BaseOps.push_back(BaseOp);
518 Offset = OffsetOp->getImm();
519 // Get appropriate operand, and compute width accordingly.
520 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
521 if (DataOpIdx == -1)
522 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
523 if (Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
524 Width = LocationSize::precise(64);
525 else
526 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
527 } else {
528 // The 2 offset instructions use offset0 and offset1 instead. We can treat
529 // these as a load with a single offset if the 2 offsets are consecutive.
530 // We will use this for some partially aligned loads.
531 const MachineOperand *Offset0Op =
532 getNamedOperand(LdSt, AMDGPU::OpName::offset0);
533 const MachineOperand *Offset1Op =
534 getNamedOperand(LdSt, AMDGPU::OpName::offset1);
535
536 unsigned Offset0 = Offset0Op->getImm() & 0xff;
537 unsigned Offset1 = Offset1Op->getImm() & 0xff;
538 if (Offset0 + 1 != Offset1)
539 return false;
540
541 // Each of these offsets is in element sized units, so we need to convert
542 // to bytes of the individual reads.
543
544 unsigned EltSize;
545 if (LdSt.mayLoad())
546 EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16;
547 else {
548 assert(LdSt.mayStore());
549 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
550 EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8;
551 }
552
553 if (isStride64(Opc))
554 EltSize *= 64;
555
556 BaseOps.push_back(BaseOp);
557 Offset = EltSize * Offset0;
558 // Get appropriate operand(s), and compute width accordingly.
559 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
560 if (DataOpIdx == -1) {
561 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
562 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
563 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
564 Width = LocationSize::precise(
565 Width.getValue() + TypeSize::getFixed(getOpSize(LdSt, DataOpIdx)));
566 } else {
567 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
568 }
569 }
570 return true;
571 }
572
573 if (isMUBUF(LdSt) || isMTBUF(LdSt)) {
574 const MachineOperand *RSrc = getNamedOperand(LdSt, AMDGPU::OpName::srsrc);
575 if (!RSrc) // e.g. BUFFER_WBINVL1_VOL
576 return false;
577 BaseOps.push_back(RSrc);
578 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
579 if (BaseOp && !BaseOp->isFI())
580 BaseOps.push_back(BaseOp);
581 const MachineOperand *OffsetImm =
582 getNamedOperand(LdSt, AMDGPU::OpName::offset);
583 Offset = OffsetImm->getImm();
584 const MachineOperand *SOffset =
585 getNamedOperand(LdSt, AMDGPU::OpName::soffset);
586 if (SOffset) {
587 if (SOffset->isReg())
588 BaseOps.push_back(SOffset);
589 else
590 Offset += SOffset->getImm();
591 }
592 // Get appropriate operand, and compute width accordingly.
593 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
594 if (DataOpIdx == -1)
595 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
596 if (DataOpIdx == -1) // LDS DMA
597 return false;
598 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
599 return true;
600 }
601
602 if (isImage(LdSt)) {
603 auto RsrcOpName =
604 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
605 int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RsrcOpName);
606 BaseOps.push_back(&LdSt.getOperand(SRsrcIdx));
607 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
608 if (VAddr0Idx >= 0) {
609 // GFX10 possible NSA encoding.
610 for (int I = VAddr0Idx; I < SRsrcIdx; ++I)
611 BaseOps.push_back(&LdSt.getOperand(I));
612 } else {
613 BaseOps.push_back(getNamedOperand(LdSt, AMDGPU::OpName::vaddr));
614 }
615 Offset = 0;
616 // Get appropriate operand, and compute width accordingly.
617 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
618 if (DataOpIdx == -1)
619 return false; // no return sampler
620 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
621 return true;
622 }
623
624 if (isSMRD(LdSt)) {
625 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::sbase);
626 if (!BaseOp) // e.g. S_MEMTIME
627 return false;
628 BaseOps.push_back(BaseOp);
629 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
630 Offset = OffsetOp ? OffsetOp->getImm() : 0;
631 // Get appropriate operand, and compute width accordingly.
632 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
633 if (DataOpIdx == -1)
634 return false;
635 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
636 return true;
637 }
638
639 if (isFLAT(LdSt)) {
640 // Instructions have either vaddr or saddr or both or none.
641 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
642 if (BaseOp)
643 BaseOps.push_back(BaseOp);
644 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr);
645 if (BaseOp)
646 BaseOps.push_back(BaseOp);
647 Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm();
648 // Get appropriate operand, and compute width accordingly.
649 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
650 if (DataOpIdx == -1)
651 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
652 if (DataOpIdx == -1) // LDS DMA
653 return false;
654 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
655 return true;
656 }
657
658 return false;
659}
660
661static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
663 const MachineInstr &MI2,
665 // Only examine the first "base" operand of each instruction, on the
666 // assumption that it represents the real base address of the memory access.
667 // Other operands are typically offsets or indices from this base address.
668 if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
669 return true;
670
671 if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
672 return false;
673
674 auto *MO1 = *MI1.memoperands_begin();
675 auto *MO2 = *MI2.memoperands_begin();
676 if (MO1->getAddrSpace() != MO2->getAddrSpace())
677 return false;
678
679 const auto *Base1 = MO1->getValue();
680 const auto *Base2 = MO2->getValue();
681 if (!Base1 || !Base2)
682 return false;
683 Base1 = getUnderlyingObject(Base1);
684 Base2 = getUnderlyingObject(Base2);
685
686 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
687 return false;
688
689 return Base1 == Base2;
690}
691
693 int64_t Offset1, bool OffsetIsScalable1,
695 int64_t Offset2, bool OffsetIsScalable2,
696 unsigned ClusterSize,
697 unsigned NumBytes) const {
698 // If the mem ops (to be clustered) do not have the same base ptr, then they
699 // should not be clustered
700 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;
701 if (!BaseOps1.empty() && !BaseOps2.empty()) {
702 const MachineInstr &FirstLdSt = *BaseOps1.front()->getParent();
703 const MachineInstr &SecondLdSt = *BaseOps2.front()->getParent();
704 if (!memOpsHaveSameBasePtr(FirstLdSt, BaseOps1, SecondLdSt, BaseOps2))
705 return false;
706
707 const SIMachineFunctionInfo *MFI =
708 FirstLdSt.getMF()->getInfo<SIMachineFunctionInfo>();
709 MaxMemoryClusterDWords = MFI->getMaxMemoryClusterDWords();
710 } else if (!BaseOps1.empty() || !BaseOps2.empty()) {
711 // If only one base op is empty, they do not have the same base ptr
712 return false;
713 }
714
715 // In order to avoid register pressure, on an average, the number of DWORDS
716 // loaded together by all clustered mem ops should not exceed
717 // MaxMemoryClusterDWords. This is an empirical value based on certain
718 // observations and performance related experiments.
719 // The good thing about this heuristic is - it avoids clustering of too many
720 // sub-word loads, and also avoids clustering of wide loads. Below is the
721 // brief summary of how the heuristic behaves for various `LoadSize` when
722 // MaxMemoryClusterDWords is 8.
723 //
724 // (1) 1 <= LoadSize <= 4: cluster at max 8 mem ops
725 // (2) 5 <= LoadSize <= 8: cluster at max 4 mem ops
726 // (3) 9 <= LoadSize <= 12: cluster at max 2 mem ops
727 // (4) 13 <= LoadSize <= 16: cluster at max 2 mem ops
728 // (5) LoadSize >= 17: do not cluster
729 const unsigned LoadSize = NumBytes / ClusterSize;
730 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
731 return NumDWords <= MaxMemoryClusterDWords;
732}
733
734// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
735// the first 16 loads will be interleaved with the stores, and the next 16 will
736// be clustered as expected. It should really split into 2 16 store batches.
737//
738// Loads are clustered until this returns false, rather than trying to schedule
739// groups of stores. This also means we have to deal with saying different
740// address space loads should be clustered, and ones which might cause bank
741// conflicts.
742//
743// This might be deprecated so it might not be worth that much effort to fix.
745 int64_t Offset0, int64_t Offset1,
746 unsigned NumLoads) const {
747 assert(Offset1 > Offset0 &&
748 "Second offset should be larger than first offset!");
749 // If we have less than 16 loads in a row, and the offsets are within 64
750 // bytes, then schedule together.
751
752 // A cacheline is 64 bytes (for global memory).
753 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
754}
755
758 const DebugLoc &DL, MCRegister DestReg,
759 MCRegister SrcReg, bool KillSrc,
760 const char *Msg = "illegal VGPR to SGPR copy") {
761 MachineFunction *MF = MBB.getParent();
762
765
766 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg)
767 .addReg(SrcReg, getKillRegState(KillSrc));
768}
769
770/// Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908. It is not
771/// possible to have a direct copy in these cases on GFX908, so an intermediate
772/// VGPR copy is required.
775 const DebugLoc &DL, MCRegister DestReg,
776 MCRegister SrcReg, bool KillSrc,
777 RegScavenger &RS, bool RegsOverlap,
778 Register ImpUseSuperReg = Register()) {
779 assert((TII.getSubtarget().hasMAIInsts() &&
780 !TII.getSubtarget().hasGFX90AInsts()) &&
781 "Expected GFX908 subtarget.");
782
783 assert((AMDGPU::SReg_32RegClass.contains(SrcReg) ||
784 AMDGPU::AGPR_32RegClass.contains(SrcReg)) &&
785 "Source register of the copy should be either an SGPR or an AGPR.");
786
787 assert(AMDGPU::AGPR_32RegClass.contains(DestReg) &&
788 "Destination register of the copy should be an AGPR.");
789
790 const SIRegisterInfo &RI = TII.getRegisterInfo();
791
792 // First try to find defining accvgpr_write to avoid temporary registers.
793 // In the case of copies of overlapping AGPRs, we conservatively do not
794 // reuse previous accvgpr_writes. Otherwise, we may incorrectly pick up
795 // an accvgpr_write used for this same copy due to implicit-defs
796 if (!RegsOverlap) {
797 for (auto Def = MI, E = MBB.begin(); Def != E; ) {
798 --Def;
799
800 if (!Def->modifiesRegister(SrcReg, &RI))
801 continue;
802
803 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
804 Def->getOperand(0).getReg() != SrcReg)
805 break;
806
807 MachineOperand &DefOp = Def->getOperand(1);
808 assert(DefOp.isReg() || DefOp.isImm());
809
810 if (DefOp.isReg()) {
811 bool SafeToPropagate = true;
812 // Check that register source operand is not clobbered before MI.
813 // Immediate operands are always safe to propagate.
814 for (auto I = Def; I != MI && SafeToPropagate; ++I)
815 if (I->modifiesRegister(DefOp.getReg(), &RI))
816 SafeToPropagate = false;
817
818 if (!SafeToPropagate)
819 break;
820
821 for (auto I = Def; I != MI; ++I)
822 I->clearRegisterKills(DefOp.getReg(), &RI);
823 }
824
825 MachineInstrBuilder Builder =
826 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64),
827 DestReg)
828 .add(DefOp);
829
830 if (ImpUseSuperReg) {
831 Builder.addReg(ImpUseSuperReg,
833 }
834
835 return;
836 }
837 }
838
839 RS.enterBasicBlockEnd(MBB);
840 RS.backward(std::next(MI));
841
842 // Ideally we want to have three registers for a long reg_sequence copy
843 // to hide 2 waitstates between v_mov_b32 and accvgpr_write.
844 unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass,
845 *MBB.getParent());
846
847 // Registers in the sequence are allocated contiguously so we can just
848 // use register number to pick one of three round-robin temps.
849 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
850 Register Tmp =
851 MBB.getParent()->getInfo<SIMachineFunctionInfo>()->getVGPRForAGPRCopy();
852 assert(MBB.getParent()->getRegInfo().isReserved(Tmp) &&
853 "VGPR used for an intermediate copy should have been reserved.");
854
855 // Only loop through if there are any free registers left. We don't want to
856 // spill.
857 while (RegNo--) {
858 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI,
859 /* RestoreAfter */ false, 0,
860 /* AllowSpill */ false);
861 if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs)
862 break;
863 Tmp = Tmp2;
864 RS.setRegUsed(Tmp);
865 }
866
867 // Insert copy to temporary VGPR.
868 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
869 if (AMDGPU::AGPR_32RegClass.contains(SrcReg)) {
870 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
871 } else {
872 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
873 }
874
875 MachineInstrBuilder UseBuilder = BuildMI(MBB, MI, DL, TII.get(TmpCopyOp), Tmp)
876 .addReg(SrcReg, getKillRegState(KillSrc));
877 if (ImpUseSuperReg) {
878 UseBuilder.addReg(ImpUseSuperReg,
880 }
881
882 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
883 .addReg(Tmp, RegState::Kill);
884}
885
888 MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
889 const TargetRegisterClass *RC, bool Forward) {
890 const SIRegisterInfo &RI = TII.getRegisterInfo();
891 ArrayRef<int16_t> BaseIndices = RI.getRegSplitParts(RC, 4);
893 MachineInstr *FirstMI = nullptr, *LastMI = nullptr;
894
895 for (unsigned Idx = 0; Idx < BaseIndices.size(); ++Idx) {
896 int16_t SubIdx = BaseIndices[Idx];
897 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
898 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
899 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
900 unsigned Opcode = AMDGPU::S_MOV_B32;
901
902 // Is SGPR aligned? If so try to combine with next.
903 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
904 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
905 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.size())) {
906 // Can use SGPR64 copy
907 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
908 SubIdx = RI.getSubRegFromChannel(Channel, 2);
909 DestSubReg = RI.getSubReg(DestReg, SubIdx);
910 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
911 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
912 Opcode = AMDGPU::S_MOV_B64;
913 Idx++;
914 }
915
916 LastMI = BuildMI(MBB, I, DL, TII.get(Opcode), DestSubReg)
917 .addReg(SrcSubReg)
918 .addReg(SrcReg, RegState::Implicit);
919
920 if (!FirstMI)
921 FirstMI = LastMI;
922
923 if (!Forward)
924 I--;
925 }
926
927 assert(FirstMI && LastMI);
928 if (!Forward)
929 std::swap(FirstMI, LastMI);
930
931 if (KillSrc)
932 LastMI->addRegisterKilled(SrcReg, &RI);
933}
934
937 const DebugLoc &DL, Register DestReg,
938 Register SrcReg, bool KillSrc, bool RenamableDest,
939 bool RenamableSrc) const {
940 const TargetRegisterClass *RC = RI.getPhysRegBaseClass(DestReg);
941 unsigned Size = RI.getRegSizeInBits(*RC);
942 const TargetRegisterClass *SrcRC = RI.getPhysRegBaseClass(SrcReg);
943 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
944
945 // The rest of copyPhysReg assumes Src and Dst size are the same size.
946 // TODO-GFX11_16BIT If all true 16 bit instruction patterns are completed can
947 // we remove Fix16BitCopies and this code block?
948 if (Fix16BitCopies) {
949 if (((Size == 16) != (SrcSize == 16))) {
950 // Non-VGPR Src and Dst will later be expanded back to 32 bits.
951 assert(ST.useRealTrue16Insts());
952 Register &RegToFix = (Size == 32) ? DestReg : SrcReg;
953 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
954 RegToFix = SubReg;
955
956 if (DestReg == SrcReg) {
957 // Identity copy. Insert empty bundle since ExpandPostRA expects an
958 // instruction here.
959 BuildMI(MBB, MI, DL, get(AMDGPU::BUNDLE));
960 return;
961 }
962 RC = RI.getPhysRegBaseClass(DestReg);
963 Size = RI.getRegSizeInBits(*RC);
964 SrcRC = RI.getPhysRegBaseClass(SrcReg);
965 SrcSize = RI.getRegSizeInBits(*SrcRC);
966 }
967 }
968
969 if (RC == &AMDGPU::VGPR_32RegClass) {
970 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
971 AMDGPU::SReg_32RegClass.contains(SrcReg) ||
972 AMDGPU::AGPR_32RegClass.contains(SrcReg));
973 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
974 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
975 BuildMI(MBB, MI, DL, get(Opc), DestReg)
976 .addReg(SrcReg, getKillRegState(KillSrc));
977 return;
978 }
979
980 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
981 RC == &AMDGPU::SReg_32RegClass) {
982 if (SrcReg == AMDGPU::SCC) {
983 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg)
984 .addImm(1)
985 .addImm(0);
986 return;
987 }
988
989 if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) {
990 if (DestReg == AMDGPU::VCC_LO) {
991 // FIXME: Hack until VReg_1 removed.
992 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
993 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
994 .addImm(0)
995 .addReg(SrcReg, getKillRegState(KillSrc));
996 return;
997 }
998
999 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1000 return;
1001 }
1002
1003 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
1004 .addReg(SrcReg, getKillRegState(KillSrc));
1005 return;
1006 }
1007
1008 if (RC == &AMDGPU::SReg_64RegClass) {
1009 if (SrcReg == AMDGPU::SCC) {
1010 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B64), DestReg)
1011 .addImm(1)
1012 .addImm(0);
1013 return;
1014 }
1015
1016 if (!AMDGPU::SReg_64_EncodableRegClass.contains(SrcReg)) {
1017 if (DestReg == AMDGPU::VCC) {
1018 // FIXME: Hack until VReg_1 removed.
1019 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
1020 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
1021 .addImm(0)
1022 .addReg(SrcReg, getKillRegState(KillSrc));
1023 return;
1024 }
1025
1026 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1027 return;
1028 }
1029
1030 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
1031 .addReg(SrcReg, getKillRegState(KillSrc));
1032 return;
1033 }
1034
1035 if (DestReg == AMDGPU::SCC) {
1036 // Copying 64-bit or 32-bit sources to SCC barely makes sense,
1037 // but SelectionDAG emits such copies for i1 sources.
1038 if (AMDGPU::SReg_64RegClass.contains(SrcReg)) {
1039 // This copy can only be produced by patterns
1040 // with explicit SCC, which are known to be enabled
1041 // only for subtargets with S_CMP_LG_U64 present.
1042 assert(ST.hasScalarCompareEq64());
1043 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U64))
1044 .addReg(SrcReg, getKillRegState(KillSrc))
1045 .addImm(0);
1046 } else {
1047 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
1048 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32))
1049 .addReg(SrcReg, getKillRegState(KillSrc))
1050 .addImm(0);
1051 }
1052
1053 return;
1054 }
1055
1056 if (RC == &AMDGPU::AGPR_32RegClass) {
1057 if (AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
1058 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1059 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
1060 .addReg(SrcReg, getKillRegState(KillSrc));
1061 return;
1062 }
1063
1064 if (AMDGPU::AGPR_32RegClass.contains(SrcReg) && ST.hasGFX90AInsts()) {
1065 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_MOV_B32), DestReg)
1066 .addReg(SrcReg, getKillRegState(KillSrc));
1067 return;
1068 }
1069
1070 // FIXME: Pass should maintain scavenger to avoid scan through the block on
1071 // every AGPR spill.
1072 RegScavenger RS;
1073 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1074 indirectCopyToAGPR(*this, MBB, MI, DL, DestReg, SrcReg, KillSrc, RS, Overlap);
1075 return;
1076 }
1077
1078 if (Size == 16) {
1079 assert(AMDGPU::VGPR_16RegClass.contains(SrcReg) ||
1080 AMDGPU::SReg_LO16RegClass.contains(SrcReg) ||
1081 AMDGPU::AGPR_LO16RegClass.contains(SrcReg));
1082
1083 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1084 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1085 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1086 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1087 bool DstLow = !AMDGPU::isHi16Reg(DestReg, RI);
1088 bool SrcLow = !AMDGPU::isHi16Reg(SrcReg, RI);
1089 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1090 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1091
1092 if (IsSGPRDst) {
1093 if (!IsSGPRSrc) {
1094 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1095 return;
1096 }
1097
1098 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), NewDestReg)
1099 .addReg(NewSrcReg, getKillRegState(KillSrc));
1100 return;
1101 }
1102
1103 if (IsAGPRDst || IsAGPRSrc) {
1104 if (!DstLow || !SrcLow) {
1105 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1106 "Cannot use hi16 subreg with an AGPR!");
1107 }
1108
1109 copyPhysReg(MBB, MI, DL, NewDestReg, NewSrcReg, KillSrc);
1110 return;
1111 }
1112
1113 if (ST.useRealTrue16Insts()) {
1114 if (IsSGPRSrc) {
1115 assert(SrcLow);
1116 SrcReg = NewSrcReg;
1117 }
1118 // Use the smaller instruction encoding if possible.
1119 if (AMDGPU::VGPR_16_Lo128RegClass.contains(DestReg) &&
1120 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.contains(SrcReg))) {
1121 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e32), DestReg)
1122 .addReg(SrcReg);
1123 } else {
1124 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e64), DestReg)
1125 .addImm(0) // src0_modifiers
1126 .addReg(SrcReg)
1127 .addImm(0); // op_sel
1128 }
1129 return;
1130 }
1131
1132 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1133 if (!DstLow || !SrcLow) {
1134 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1135 "Cannot use hi16 subreg on VI!");
1136 }
1137
1138 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), NewDestReg)
1139 .addReg(NewSrcReg, getKillRegState(KillSrc));
1140 return;
1141 }
1142
1143 auto MIB = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_sdwa), NewDestReg)
1144 .addImm(0) // src0_modifiers
1145 .addReg(NewSrcReg)
1146 .addImm(0) // clamp
1153 // First implicit operand is $exec.
1154 MIB->tieOperands(0, MIB->getNumOperands() - 1);
1155 return;
1156 }
1157
1158 // Returns true if Dst and Src are in Opc's HwMode-resolved destination and
1159 // source operand classes.
1160 auto CanCopyWith = [&](unsigned Opc, MCRegister Dst, MCRegister Src,
1161 unsigned SrcOp = 1) {
1162 const MCInstrDesc &Desc = get(Opc);
1163 const TargetRegisterClass *DstOpRC = getRegClass(Desc, 0);
1164 const TargetRegisterClass *SrcOpRC = getRegClass(Desc, SrcOp);
1165 return DstOpRC && SrcOpRC && DstOpRC->contains(Dst) &&
1166 SrcOpRC->contains(Src);
1167 };
1168
1169 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1170 if (ST.hasVMovB64Inst() &&
1171 CanCopyWith(AMDGPU::V_MOV_B64_e32, DestReg, SrcReg)) {
1172 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_e32), DestReg)
1173 .addReg(SrcReg, getKillRegState(KillSrc));
1174 return;
1175 }
1176 if (ST.hasPkMovB32() &&
1177 CanCopyWith(AMDGPU::V_PK_MOV_B32, DestReg, SrcReg, /*SrcOp=*/2)) {
1178 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestReg)
1180 .addReg(SrcReg)
1182 .addReg(SrcReg)
1183 .addImm(0) // op_sel_lo
1184 .addImm(0) // op_sel_hi
1185 .addImm(0) // neg_lo
1186 .addImm(0) // neg_hi
1187 .addImm(0) // clamp
1188 .addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
1189 return;
1190 }
1191 }
1192
1193 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1194 if (RI.isSGPRClass(RC)) {
1195 if (!RI.isSGPRClass(SrcRC)) {
1196 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1197 return;
1198 }
1199 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1200 expandSGPRCopy(*this, MBB, MI, DL, DestReg, SrcReg, CanKillSuperReg, RC,
1201 Forward);
1202 return;
1203 }
1204
1205 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1206 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1207 if (RI.isAGPRClass(RC)) {
1208 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1209 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1210 else if (RI.hasVGPRs(SrcRC) ||
1211 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1212 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1213 else
1214 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1215 } else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1216 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1217 } else if (RI.isVGPRClass(RC)) {
1218 if (ST.hasVMovB64Inst())
1219 WideOpcode = AMDGPU::V_MOV_B64_e32;
1220 else if (ST.hasPkMovB32())
1221 WideOpcode = AMDGPU::V_PK_MOV_B32;
1222 }
1223
1224 const TargetRegisterClass *WideDstRC{}, *WideSrcRC{};
1225 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1226 const MCInstrDesc &Desc = get(WideOpcode);
1227 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1228 WideDstRC = getRegClass(Desc, 0);
1229 WideSrcRC = getRegClass(Desc, SrcOp);
1230 }
1231
1232 // If there is an overlap, we can't kill the super-register on the last
1233 // instruction, since it will also kill the components made live by this def.
1234 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1235 const bool CanKillSuperReg = KillSrc && !Overlap;
1236
1237 // For the cases where we need an intermediate instruction/temporary register
1238 // (destination is an AGPR), we need a scavenger.
1239 //
1240 // FIXME: The pass should maintain this for us so we don't have to re-scan the
1241 // whole block for every handled copy.
1242 std::unique_ptr<RegScavenger> RS;
1243 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1244 RS = std::make_unique<RegScavenger>();
1245
1246 ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, 4);
1247
1248 for (unsigned Idx{}; Idx < SubIndices.size();) {
1249 unsigned NumRegs = 1;
1250 unsigned ThisOpcode = Opcode;
1251 unsigned SubIdx =
1252 Forward ? SubIndices[Idx] : SubIndices[SubIndices.size() - Idx - 1];
1253
1254 if (WideDstRC && WideSrcRC && Idx + 1 < SubIndices.size()) {
1255 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1256 if (!Forward)
1257 --Channel;
1258
1259 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1260 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1261 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1262
1263 if (WideDst && WideSrc && WideDstRC->contains(WideDst) &&
1264 WideSrcRC->contains(WideSrc)) {
1265 SubIdx = WideSubIdx;
1266 NumRegs = 2;
1267 ThisOpcode = WideOpcode;
1268 }
1269 }
1270
1271 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1272 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1273 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
1274
1275 Idx += NumRegs;
1276 bool UseKill = CanKillSuperReg && Idx == SubIndices.size();
1277
1278 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1279 Register ImpUseSuper = SrcReg;
1280 indirectCopyToAGPR(*this, MBB, MI, DL, DestSubReg, SrcSubReg, UseKill,
1281 *RS, Overlap, ImpUseSuper);
1282 } else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1283 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestSubReg)
1285 .addReg(SrcSubReg)
1287 .addReg(SrcSubReg)
1288 .addImm(0) // op_sel_lo
1289 .addImm(0) // op_sel_hi
1290 .addImm(0) // neg_lo
1291 .addImm(0) // neg_hi
1292 .addImm(0) // clamp
1293 .addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1294 } else {
1295 MachineInstrBuilder Builder =
1296 BuildMI(MBB, MI, DL, get(ThisOpcode), DestSubReg).addReg(SrcSubReg);
1297
1298 Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1299 }
1300 }
1301}
1302
1303int SIInstrInfo::commuteOpcode(unsigned Opcode) const {
1304 int32_t NewOpc;
1305
1306 // Try to map original to commuted opcode
1307 NewOpc = AMDGPU::getCommuteRev(Opcode);
1308 if (NewOpc != -1)
1309 // Check if the commuted (REV) opcode exists on the target.
1310 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1311
1312 // Try to map commuted to original opcode
1313 NewOpc = AMDGPU::getCommuteOrig(Opcode);
1314 if (NewOpc != -1)
1315 // Check if the original (non-REV) opcode exists on the target.
1316 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1317
1318 return Opcode;
1319}
1320
1322 const Register Reg,
1323 int64_t &ImmVal) const {
1324 switch (MI.getOpcode()) {
1325 case AMDGPU::V_MOV_B32_e32:
1326 case AMDGPU::S_MOV_B32:
1327 case AMDGPU::S_MOVK_I32:
1328 case AMDGPU::S_MOV_B64:
1329 case AMDGPU::V_MOV_B64_e32:
1330 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1331 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1332 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1333 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1334 case AMDGPU::V_MOV_B64_PSEUDO:
1335 case AMDGPU::V_MOV_B16_t16_e32: {
1336 const MachineOperand &Src0 = MI.getOperand(1);
1337 if (Src0.isImm()) {
1338 ImmVal = Src0.getImm();
1339 return MI.getOperand(0).getReg() == Reg;
1340 }
1341
1342 return false;
1343 }
1344 case AMDGPU::V_MOV_B16_t16_e64: {
1345 const MachineOperand &Src0 = MI.getOperand(2);
1346 if (Src0.isImm() && !MI.getOperand(1).getImm()) {
1347 ImmVal = Src0.getImm();
1348 return MI.getOperand(0).getReg() == Reg;
1349 }
1350
1351 return false;
1352 }
1353 case AMDGPU::S_BREV_B32:
1354 case AMDGPU::V_BFREV_B32_e32:
1355 case AMDGPU::V_BFREV_B32_e64: {
1356 const MachineOperand &Src0 = MI.getOperand(1);
1357 if (Src0.isImm()) {
1358 ImmVal = static_cast<int64_t>(reverseBits<int32_t>(Src0.getImm()));
1359 return MI.getOperand(0).getReg() == Reg;
1360 }
1361
1362 return false;
1363 }
1364 case AMDGPU::S_NOT_B32:
1365 case AMDGPU::V_NOT_B32_e32:
1366 case AMDGPU::V_NOT_B32_e64: {
1367 const MachineOperand &Src0 = MI.getOperand(1);
1368 if (Src0.isImm()) {
1369 ImmVal = static_cast<int64_t>(~static_cast<int32_t>(Src0.getImm()));
1370 return MI.getOperand(0).getReg() == Reg;
1371 }
1372
1373 return false;
1374 }
1375 default:
1376 return false;
1377 }
1378}
1379
1380std::optional<int64_t>
1382 const MachineOperand &Op,
1383 MachineInstr **DefMI) const {
1384 if (DefMI)
1385 *DefMI = nullptr;
1386
1387 if (Op.isImm())
1388 return Op.getImm();
1389
1390 if (!Op.isReg() || !Op.getReg().isVirtual())
1391 return std::nullopt;
1392 MachineInstr *Def = MRI.getUniqueVRegDef(Op.getReg());
1393 if (Def && Def->isMoveImmediate()) {
1394 const MachineOperand &ImmSrc = Def->getOperand(1);
1395 if (ImmSrc.isImm()) {
1396 if (DefMI)
1397 *DefMI = Def;
1398 return extractSubregFromImm(ImmSrc.getImm(), Op.getSubReg());
1399 }
1400 }
1401
1402 return std::nullopt;
1403}
1404
1405std::optional<int64_t>
1411
1413
1414 if (RI.isAGPRClass(DstRC))
1415 return AMDGPU::COPY;
1416 if (RI.getRegSizeInBits(*DstRC) == 16) {
1417 // Assume hi bits are unneeded. Only _e64 true16 instructions are legal
1418 // before RA.
1419 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1420 }
1421 if (RI.getRegSizeInBits(*DstRC) == 32)
1422 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1423 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1424 return AMDGPU::S_MOV_B64;
1425 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1426 return AMDGPU::V_MOV_B64_PSEUDO;
1427 return AMDGPU::COPY;
1428}
1429
1430const MCInstrDesc &
1432 bool IsIndirectSrc) const {
1433 if (IsIndirectSrc) {
1434 if (VecSize <= 32) // 4 bytes
1435 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1436 if (VecSize <= 64) // 8 bytes
1437 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1438 if (VecSize <= 96) // 12 bytes
1439 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1440 if (VecSize <= 128) // 16 bytes
1441 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1442 if (VecSize <= 160) // 20 bytes
1443 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1444 if (VecSize <= 192) // 24 bytes
1445 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1446 if (VecSize <= 224) // 28 bytes
1447 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1448 if (VecSize <= 256) // 32 bytes
1449 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1450 if (VecSize <= 288) // 36 bytes
1451 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1452 if (VecSize <= 320) // 40 bytes
1453 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1454 if (VecSize <= 352) // 44 bytes
1455 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1456 if (VecSize <= 384) // 48 bytes
1457 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1458 if (VecSize <= 512) // 64 bytes
1459 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1460 if (VecSize <= 1024) // 128 bytes
1461 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1462
1463 llvm_unreachable("unsupported size for IndirectRegReadGPRIDX pseudos");
1464 }
1465
1466 if (VecSize <= 32) // 4 bytes
1467 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1468 if (VecSize <= 64) // 8 bytes
1469 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1470 if (VecSize <= 96) // 12 bytes
1471 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1472 if (VecSize <= 128) // 16 bytes
1473 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1474 if (VecSize <= 160) // 20 bytes
1475 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1476 if (VecSize <= 192) // 24 bytes
1477 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1478 if (VecSize <= 224) // 28 bytes
1479 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1480 if (VecSize <= 256) // 32 bytes
1481 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1482 if (VecSize <= 288) // 36 bytes
1483 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1484 if (VecSize <= 320) // 40 bytes
1485 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1486 if (VecSize <= 352) // 44 bytes
1487 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1488 if (VecSize <= 384) // 48 bytes
1489 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1490 if (VecSize <= 512) // 64 bytes
1491 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1492 if (VecSize <= 1024) // 128 bytes
1493 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1494
1495 llvm_unreachable("unsupported size for IndirectRegWriteGPRIDX pseudos");
1496}
1497
1498static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize) {
1499 if (VecSize <= 32) // 4 bytes
1500 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1501 if (VecSize <= 64) // 8 bytes
1502 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1503 if (VecSize <= 96) // 12 bytes
1504 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1505 if (VecSize <= 128) // 16 bytes
1506 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1507 if (VecSize <= 160) // 20 bytes
1508 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1509 if (VecSize <= 192) // 24 bytes
1510 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1511 if (VecSize <= 224) // 28 bytes
1512 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1513 if (VecSize <= 256) // 32 bytes
1514 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1515 if (VecSize <= 288) // 36 bytes
1516 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1517 if (VecSize <= 320) // 40 bytes
1518 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1519 if (VecSize <= 352) // 44 bytes
1520 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1521 if (VecSize <= 384) // 48 bytes
1522 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1523 if (VecSize <= 512) // 64 bytes
1524 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1525 if (VecSize <= 1024) // 128 bytes
1526 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1527
1528 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1529}
1530
1531static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize) {
1532 if (VecSize <= 32) // 4 bytes
1533 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1534 if (VecSize <= 64) // 8 bytes
1535 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1536 if (VecSize <= 96) // 12 bytes
1537 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1538 if (VecSize <= 128) // 16 bytes
1539 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1540 if (VecSize <= 160) // 20 bytes
1541 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1542 if (VecSize <= 192) // 24 bytes
1543 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1544 if (VecSize <= 224) // 28 bytes
1545 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1546 if (VecSize <= 256) // 32 bytes
1547 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1548 if (VecSize <= 288) // 36 bytes
1549 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1550 if (VecSize <= 320) // 40 bytes
1551 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1552 if (VecSize <= 352) // 44 bytes
1553 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1554 if (VecSize <= 384) // 48 bytes
1555 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1556 if (VecSize <= 512) // 64 bytes
1557 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1558 if (VecSize <= 1024) // 128 bytes
1559 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1560
1561 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1562}
1563
1564static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize) {
1565 if (VecSize <= 64) // 8 bytes
1566 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1567 if (VecSize <= 128) // 16 bytes
1568 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1569 if (VecSize <= 256) // 32 bytes
1570 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1571 if (VecSize <= 512) // 64 bytes
1572 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1573 if (VecSize <= 1024) // 128 bytes
1574 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1575
1576 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1577}
1578
1579const MCInstrDesc &
1580SIInstrInfo::getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize,
1581 bool IsSGPR) const {
1582 if (IsSGPR) {
1583 switch (EltSize) {
1584 case 32:
1585 return get(getIndirectSGPRWriteMovRelPseudo32(VecSize));
1586 case 64:
1587 return get(getIndirectSGPRWriteMovRelPseudo64(VecSize));
1588 default:
1589 llvm_unreachable("invalid reg indexing elt size");
1590 }
1591 }
1592
1593 assert(EltSize == 32 && "invalid reg indexing elt size");
1595}
1596
1597static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1598 switch (Size) {
1599 case 4:
1600 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1601 case 8:
1602 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1603 case 12:
1604 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1605 case 16:
1606 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1607 : AMDGPU::SI_SPILL_S128_SAVE;
1608 case 20:
1609 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1610 : AMDGPU::SI_SPILL_S160_SAVE;
1611 case 24:
1612 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1613 : AMDGPU::SI_SPILL_S192_SAVE;
1614 case 28:
1615 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1616 : AMDGPU::SI_SPILL_S224_SAVE;
1617 case 32:
1618 return AMDGPU::SI_SPILL_S256_SAVE;
1619 case 36:
1620 return AMDGPU::SI_SPILL_S288_SAVE;
1621 case 40:
1622 return AMDGPU::SI_SPILL_S320_SAVE;
1623 case 44:
1624 return AMDGPU::SI_SPILL_S352_SAVE;
1625 case 48:
1626 return AMDGPU::SI_SPILL_S384_SAVE;
1627 case 64:
1628 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1629 : AMDGPU::SI_SPILL_S512_SAVE;
1630 case 128:
1631 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1632 : AMDGPU::SI_SPILL_S1024_SAVE;
1633 default:
1634 llvm_unreachable("unknown register size");
1635 }
1636}
1637
1638static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1639 switch (Size) {
1640 case 2:
1641 return AMDGPU::SI_SPILL_V16_SAVE;
1642 case 4:
1643 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1644 case 8:
1645 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1646 case 12:
1647 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1648 case 16:
1649 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1650 : AMDGPU::SI_SPILL_V128_SAVE;
1651 case 20:
1652 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1653 : AMDGPU::SI_SPILL_V160_SAVE;
1654 case 24:
1655 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1656 : AMDGPU::SI_SPILL_V192_SAVE;
1657 case 28:
1658 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1659 : AMDGPU::SI_SPILL_V224_SAVE;
1660 case 32:
1661 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1662 : AMDGPU::SI_SPILL_V256_SAVE;
1663 case 36:
1664 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1665 : AMDGPU::SI_SPILL_V288_SAVE;
1666 case 40:
1667 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1668 : AMDGPU::SI_SPILL_V320_SAVE;
1669 case 44:
1670 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1671 : AMDGPU::SI_SPILL_V352_SAVE;
1672 case 48:
1673 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1674 : AMDGPU::SI_SPILL_V384_SAVE;
1675 case 64:
1676 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1677 : AMDGPU::SI_SPILL_V512_SAVE;
1678 case 128:
1679 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1680 : AMDGPU::SI_SPILL_V1024_SAVE;
1681 default:
1682 llvm_unreachable("unknown register size");
1683 }
1684}
1685
1686static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1687 switch (Size) {
1688 case 4:
1689 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1690 : AMDGPU::SI_SPILL_AV32_SAVE;
1691 case 8:
1692 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1693 : AMDGPU::SI_SPILL_AV64_SAVE;
1694 case 12:
1695 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1696 : AMDGPU::SI_SPILL_AV96_SAVE;
1697 case 16:
1698 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1699 : AMDGPU::SI_SPILL_AV128_SAVE;
1700 case 20:
1701 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1702 : AMDGPU::SI_SPILL_AV160_SAVE;
1703 case 24:
1704 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1705 : AMDGPU::SI_SPILL_AV192_SAVE;
1706 case 28:
1707 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1708 : AMDGPU::SI_SPILL_AV224_SAVE;
1709 case 32:
1710 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1711 : AMDGPU::SI_SPILL_AV256_SAVE;
1712 case 36:
1713 return AMDGPU::SI_SPILL_AV288_SAVE;
1714 case 40:
1715 return AMDGPU::SI_SPILL_AV320_SAVE;
1716 case 44:
1717 return AMDGPU::SI_SPILL_AV352_SAVE;
1718 case 48:
1719 return AMDGPU::SI_SPILL_AV384_SAVE;
1720 case 64:
1721 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1722 : AMDGPU::SI_SPILL_AV512_SAVE;
1723 case 128:
1724 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1725 : AMDGPU::SI_SPILL_AV1024_SAVE;
1726 default:
1727 llvm_unreachable("unknown register size");
1728 }
1729}
1730
1731static unsigned getWWMRegSpillSaveOpcode(unsigned Size,
1732 bool IsVectorSuperClass) {
1733 // Currently, there is only 32-bit WWM register spills needed.
1734 if (Size != 4)
1735 llvm_unreachable("unknown wwm register spill size");
1736
1737 if (IsVectorSuperClass)
1738 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1739
1740 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1741}
1742
1744 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1745 const SIMachineFunctionInfo &MFI, bool NeedsCFI) const {
1746 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1747
1748 // Choose the right opcode if spilling a WWM register.
1750 return getWWMRegSpillSaveOpcode(Size, IsVectorSuperClass);
1751
1752 // TODO: Check if AGPRs are available
1753 if (ST.hasMAIInsts())
1754 return getAVSpillSaveOpcode(Size, NeedsCFI);
1755
1756 return getVGPRSpillSaveOpcode(Size, NeedsCFI);
1757}
1758
1759void SIInstrInfo::storeRegToStackSlotImpl(
1761 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1762 MachineInstr::MIFlag Flags, bool NeedsCFI) const {
1763 MachineFunction *MF = MBB.getParent();
1765 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1766 const DebugLoc &DL = MBB.findDebugLoc(MI);
1767
1768 MachinePointerInfo PtrInfo
1769 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1771 PtrInfo, MachineMemOperand::MOStore, FrameInfo.getObjectSize(FrameIndex),
1772 FrameInfo.getObjectAlign(FrameIndex));
1773 unsigned SpillSize = RI.getSpillSize(*RC);
1774
1775 MachineRegisterInfo &MRI = MF->getRegInfo();
1776 if (RI.isSGPRClass(RC)) {
1777 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1778 MFI->setHasSpilledSGPRs();
1779 assert(SrcReg != AMDGPU::M0 && "m0 should not be spilled");
1780 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1781 SrcReg != AMDGPU::EXEC && "exec should not be spilled");
1782
1783 // We are only allowed to create one new instruction when spilling
1784 // registers, so we need to use pseudo instruction for spilling SGPRs.
1785 const MCInstrDesc &OpDesc =
1786 get(getSGPRSpillSaveOpcode(SpillSize, NeedsCFI));
1787
1788 // The SGPR spill/restore instructions only work on number sgprs, so we need
1789 // to make sure we are using the correct register class.
1790 if (SrcReg.isVirtual() && SpillSize == 4) {
1791 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1792 }
1793
1794 BuildMI(MBB, MI, DL, OpDesc)
1795 .addReg(SrcReg, getKillRegState(isKill)) // data
1796 .addFrameIndex(FrameIndex) // addr
1797 .addMemOperand(MMO)
1799
1800 return;
1801 }
1802
1803 unsigned Opcode = getVectorRegSpillSaveOpcode(VReg ? VReg : SrcReg, RC,
1804 SpillSize, *MFI, NeedsCFI);
1805 MFI->setHasSpilledVGPRs();
1806
1807 BuildMI(MBB, MI, DL, get(Opcode))
1808 .addReg(SrcReg, getKillRegState(isKill)) // data
1809 .addFrameIndex(FrameIndex) // addr
1810 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1811 .addImm(0) // offset
1812 .addMemOperand(MMO);
1813}
1814
1817 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1818 MachineInstr::MIFlag Flags) const {
1819 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1820 false);
1821}
1822
1825 Register SrcReg, bool isKill,
1826 int FrameIndex,
1827 const TargetRegisterClass *RC) const {
1828 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, Register(),
1829 MachineInstr::NoFlags, true);
1830}
1831
1832static unsigned getSGPRSpillRestoreOpcode(unsigned Size) {
1833 switch (Size) {
1834 case 4:
1835 return AMDGPU::SI_SPILL_S32_RESTORE;
1836 case 8:
1837 return AMDGPU::SI_SPILL_S64_RESTORE;
1838 case 12:
1839 return AMDGPU::SI_SPILL_S96_RESTORE;
1840 case 16:
1841 return AMDGPU::SI_SPILL_S128_RESTORE;
1842 case 20:
1843 return AMDGPU::SI_SPILL_S160_RESTORE;
1844 case 24:
1845 return AMDGPU::SI_SPILL_S192_RESTORE;
1846 case 28:
1847 return AMDGPU::SI_SPILL_S224_RESTORE;
1848 case 32:
1849 return AMDGPU::SI_SPILL_S256_RESTORE;
1850 case 36:
1851 return AMDGPU::SI_SPILL_S288_RESTORE;
1852 case 40:
1853 return AMDGPU::SI_SPILL_S320_RESTORE;
1854 case 44:
1855 return AMDGPU::SI_SPILL_S352_RESTORE;
1856 case 48:
1857 return AMDGPU::SI_SPILL_S384_RESTORE;
1858 case 64:
1859 return AMDGPU::SI_SPILL_S512_RESTORE;
1860 case 128:
1861 return AMDGPU::SI_SPILL_S1024_RESTORE;
1862 default:
1863 llvm_unreachable("unknown register size");
1864 }
1865}
1866
1867static unsigned getVGPRSpillRestoreOpcode(unsigned Size) {
1868 switch (Size) {
1869 case 2:
1870 return AMDGPU::SI_SPILL_V16_RESTORE;
1871 case 4:
1872 return AMDGPU::SI_SPILL_V32_RESTORE;
1873 case 8:
1874 return AMDGPU::SI_SPILL_V64_RESTORE;
1875 case 12:
1876 return AMDGPU::SI_SPILL_V96_RESTORE;
1877 case 16:
1878 return AMDGPU::SI_SPILL_V128_RESTORE;
1879 case 20:
1880 return AMDGPU::SI_SPILL_V160_RESTORE;
1881 case 24:
1882 return AMDGPU::SI_SPILL_V192_RESTORE;
1883 case 28:
1884 return AMDGPU::SI_SPILL_V224_RESTORE;
1885 case 32:
1886 return AMDGPU::SI_SPILL_V256_RESTORE;
1887 case 36:
1888 return AMDGPU::SI_SPILL_V288_RESTORE;
1889 case 40:
1890 return AMDGPU::SI_SPILL_V320_RESTORE;
1891 case 44:
1892 return AMDGPU::SI_SPILL_V352_RESTORE;
1893 case 48:
1894 return AMDGPU::SI_SPILL_V384_RESTORE;
1895 case 64:
1896 return AMDGPU::SI_SPILL_V512_RESTORE;
1897 case 128:
1898 return AMDGPU::SI_SPILL_V1024_RESTORE;
1899 default:
1900 llvm_unreachable("unknown register size");
1901 }
1902}
1903
1904static unsigned getAVSpillRestoreOpcode(unsigned Size) {
1905 switch (Size) {
1906 case 4:
1907 return AMDGPU::SI_SPILL_AV32_RESTORE;
1908 case 8:
1909 return AMDGPU::SI_SPILL_AV64_RESTORE;
1910 case 12:
1911 return AMDGPU::SI_SPILL_AV96_RESTORE;
1912 case 16:
1913 return AMDGPU::SI_SPILL_AV128_RESTORE;
1914 case 20:
1915 return AMDGPU::SI_SPILL_AV160_RESTORE;
1916 case 24:
1917 return AMDGPU::SI_SPILL_AV192_RESTORE;
1918 case 28:
1919 return AMDGPU::SI_SPILL_AV224_RESTORE;
1920 case 32:
1921 return AMDGPU::SI_SPILL_AV256_RESTORE;
1922 case 36:
1923 return AMDGPU::SI_SPILL_AV288_RESTORE;
1924 case 40:
1925 return AMDGPU::SI_SPILL_AV320_RESTORE;
1926 case 44:
1927 return AMDGPU::SI_SPILL_AV352_RESTORE;
1928 case 48:
1929 return AMDGPU::SI_SPILL_AV384_RESTORE;
1930 case 64:
1931 return AMDGPU::SI_SPILL_AV512_RESTORE;
1932 case 128:
1933 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1934 default:
1935 llvm_unreachable("unknown register size");
1936 }
1937}
1938
1939static unsigned getWWMRegSpillRestoreOpcode(unsigned Size,
1940 bool IsVectorSuperClass) {
1941 // Currently, there is only 32-bit WWM register spills needed.
1942 if (Size != 4)
1943 llvm_unreachable("unknown wwm register spill size");
1944
1945 if (IsVectorSuperClass) // TODO: Always use this if there are AGPRs
1946 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1947
1948 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1949}
1950
1952 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1953 const SIMachineFunctionInfo &MFI) const {
1954 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1955
1956 // Choose the right opcode if restoring a WWM register.
1958 return getWWMRegSpillRestoreOpcode(Size, IsVectorSuperClass);
1959
1960 // TODO: Check if AGPRs are available
1961 if (ST.hasMAIInsts())
1963
1964 assert(!RI.isAGPRClass(RC));
1966}
1967
1970 Register DestReg, int FrameIndex,
1971 const TargetRegisterClass *RC,
1972 Register VReg, unsigned SubReg,
1973 MachineInstr::MIFlag Flags) const {
1974 MachineFunction *MF = MBB.getParent();
1976 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1977 const DebugLoc &DL = MBB.findDebugLoc(MI);
1978 unsigned SpillSize = RI.getSpillSize(*RC);
1979
1980 MachinePointerInfo PtrInfo
1981 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1982
1984 PtrInfo, MachineMemOperand::MOLoad, FrameInfo.getObjectSize(FrameIndex),
1985 FrameInfo.getObjectAlign(FrameIndex));
1986
1987 if (RI.isSGPRClass(RC)) {
1988 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1989 MFI->setHasSpilledSGPRs();
1990 assert(DestReg != AMDGPU::M0 && "m0 should not be reloaded into");
1991 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1992 DestReg != AMDGPU::EXEC && "exec should not be spilled");
1993
1994 // FIXME: Maybe this should not include a memoperand because it will be
1995 // lowered to non-memory instructions.
1996 const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize));
1997 if (DestReg.isVirtual() && SpillSize == 4) {
1998 MachineRegisterInfo &MRI = MF->getRegInfo();
1999 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
2000 }
2001
2002 BuildMI(MBB, MI, DL, OpDesc, DestReg)
2003 .addFrameIndex(FrameIndex) // addr
2004 .addMemOperand(MMO)
2006
2007 return;
2008 }
2009
2010 unsigned Opcode = getVectorRegSpillRestoreOpcode(VReg ? VReg : DestReg, RC,
2011 SpillSize, *MFI);
2012 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
2013 .addFrameIndex(FrameIndex) // vaddr
2014 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
2015 .addImm(0) // offset
2016 .addMemOperand(MMO);
2017}
2018
2023
2026 unsigned Quantity) const {
2027 DebugLoc DL = MBB.findDebugLoc(MI);
2028 unsigned MaxSNopCount = 1u << ST.getSNopBits();
2029 while (Quantity > 0) {
2030 unsigned Arg = std::min(Quantity, MaxSNopCount);
2031 Quantity -= Arg;
2032 BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
2033 }
2034}
2035
2039 const DebugLoc &DL) const {
2040 MachineFunction *MF = MBB.getParent();
2041 constexpr unsigned DoorbellIDMask = 0x3ff;
2042 constexpr unsigned ECQueueWaveAbort = 0x400;
2043
2044 MachineBasicBlock *TrapBB = &MBB;
2045 MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock();
2046
2047 if (!MBB.succ_empty() || std::next(MI.getIterator()) != MBB.end()) {
2048 MBB.splitAt(MI, /*UpdateLiveIns=*/false);
2049 TrapBB = MF->CreateMachineBasicBlock();
2050 BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB);
2051 MF->push_back(TrapBB);
2052 MBB.addSuccessor(TrapBB);
2053 }
2054 // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this
2055 // will be a nop.
2056 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP))
2057 .addImm(static_cast<unsigned>(GCNSubtarget::TrapID::LLVMAMDHSATrap));
2058 Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2059 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32),
2060 DoorbellReg)
2062 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2063 .addUse(AMDGPU::M0);
2064 Register DoorbellRegMasked =
2065 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2066 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2067 .addUse(DoorbellReg)
2068 .addImm(DoorbellIDMask);
2069 Register SetWaveAbortBit =
2070 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2071 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2072 .addUse(DoorbellRegMasked)
2073 .addImm(ECQueueWaveAbort);
2074 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2075 .addUse(SetWaveAbortBit);
2076 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG))
2078 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2079 .addUse(AMDGPU::TTMP2);
2080 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB);
2081 TrapBB->addSuccessor(HaltLoopBB);
2082
2083 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5);
2084 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH))
2085 .addMBB(HaltLoopBB);
2086 MF->push_back(HaltLoopBB);
2087 HaltLoopBB->addSuccessor(HaltLoopBB);
2088
2089 return MBB.getNextNode();
2090}
2091
2093 switch (MI.getOpcode()) {
2094 default:
2095 if (MI.isMetaInstruction())
2096 return 0;
2097 return 1; // FIXME: Do wait states equal cycles?
2098
2099 case AMDGPU::S_NOP:
2100 return MI.getOperand(0).getImm() + 1;
2101 // SI_RETURN_TO_EPILOG is a fallthrough to code outside of the function. The
2102 // hazard, even if one exist, won't really be visible. Should we handle it?
2103 }
2104}
2105
2107 MachineBasicBlock &MBB = *MI.getParent();
2108 DebugLoc DL = MBB.findDebugLoc(MI);
2110
2111 switch (MI.getOpcode()) {
2112 default: return TargetInstrInfo::expandPostRAPseudo(MI);
2113 case AMDGPU::S_MOV_B64_term:
2114 // This is only a terminator to get the correct spill code placement during
2115 // register allocation.
2116 MI.setDesc(get(AMDGPU::S_MOV_B64));
2117 break;
2118
2119 case AMDGPU::S_MOV_B32_term:
2120 // This is only a terminator to get the correct spill code placement during
2121 // register allocation.
2122 MI.setDesc(get(AMDGPU::S_MOV_B32));
2123 break;
2124
2125 case AMDGPU::S_XOR_B64_term:
2126 // This is only a terminator to get the correct spill code placement during
2127 // register allocation.
2128 MI.setDesc(get(AMDGPU::S_XOR_B64));
2129 break;
2130
2131 case AMDGPU::S_XOR_B32_term:
2132 // This is only a terminator to get the correct spill code placement during
2133 // register allocation.
2134 MI.setDesc(get(AMDGPU::S_XOR_B32));
2135 break;
2136 case AMDGPU::S_OR_B64_term:
2137 // This is only a terminator to get the correct spill code placement during
2138 // register allocation.
2139 MI.setDesc(get(AMDGPU::S_OR_B64));
2140 break;
2141 case AMDGPU::S_OR_B32_term:
2142 // This is only a terminator to get the correct spill code placement during
2143 // register allocation.
2144 MI.setDesc(get(AMDGPU::S_OR_B32));
2145 break;
2146
2147 case AMDGPU::S_ANDN2_B64_term:
2148 // This is only a terminator to get the correct spill code placement during
2149 // register allocation.
2150 MI.setDesc(get(AMDGPU::S_ANDN2_B64));
2151 break;
2152
2153 case AMDGPU::S_ANDN2_B32_term:
2154 // This is only a terminator to get the correct spill code placement during
2155 // register allocation.
2156 MI.setDesc(get(AMDGPU::S_ANDN2_B32));
2157 break;
2158
2159 case AMDGPU::S_AND_B64_term:
2160 // This is only a terminator to get the correct spill code placement during
2161 // register allocation.
2162 MI.setDesc(get(AMDGPU::S_AND_B64));
2163 break;
2164
2165 case AMDGPU::S_AND_B32_term:
2166 // This is only a terminator to get the correct spill code placement during
2167 // register allocation.
2168 MI.setDesc(get(AMDGPU::S_AND_B32));
2169 break;
2170
2171 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2172 // This is only a terminator to get the correct spill code placement during
2173 // register allocation.
2174 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B64));
2175 break;
2176
2177 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2178 // This is only a terminator to get the correct spill code placement during
2179 // register allocation.
2180 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B32));
2181 break;
2182
2183 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2184 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2185 break;
2186 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2187 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2188 break;
2189
2190 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2191 MI.setDesc(get(AMDGPU::V_WRITELANE_B32));
2192 break;
2193
2194 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2195 MI.setDesc(get(AMDGPU::V_READLANE_B32));
2196 break;
2197 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2198 Register Dst = MI.getOperand(0).getReg();
2199 bool IsAGPR = SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst));
2200 MI.setDesc(
2201 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2202 break;
2203 }
2204 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2205 Register Dst = MI.getOperand(0).getReg();
2206 if (SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst))) {
2207 int64_t Imm = MI.getOperand(1).getImm();
2208
2209 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2210 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2211 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstLo)
2213 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstHi)
2214 .addImm(SignExtend64<32>(Imm >> 32));
2215 MI.eraseFromParent();
2216 break;
2217 }
2218
2219 [[fallthrough]];
2220 }
2221 case AMDGPU::V_MOV_B64_PSEUDO: {
2222 Register Dst = MI.getOperand(0).getReg();
2223 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2224 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2225
2226 const MCInstrDesc &Mov64Desc = get(AMDGPU::V_MOV_B64_e32);
2227 const TargetRegisterClass *Mov64RC = getRegClass(Mov64Desc, /*OpNum=*/0);
2228
2229 const MachineOperand &SrcOp = MI.getOperand(1);
2230 // FIXME: Will this work for 64-bit floating point immediates?
2231 assert(!SrcOp.isFPImm());
2232 if (ST.hasVMovB64Inst() && Mov64RC->contains(Dst)) {
2233 MI.setDesc(Mov64Desc);
2234 if (SrcOp.isReg() || isInlineConstant(MI, 1) ||
2235 (SrcOp.isImm() &&
2236 (isUInt<32>(SrcOp.getImm()) || ST.has64BitLiterals())) ||
2237 (SrcOp.isGlobal() && ST.has64BitLiterals()))
2238 break;
2239 }
2240 if (SrcOp.isGlobal()) {
2241 // The address is unknown until link time, so the PK_MOV inline-constant
2242 // shortcut cannot apply.
2243 const GlobalValue *GV = SrcOp.getGlobal();
2244 int64_t Offset = SrcOp.getOffset();
2245 unsigned BaseFlags, LoReloc, HiReloc;
2246 std::tie(BaseFlags, LoReloc, HiReloc) =
2248
2249 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2250 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2251 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2252 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2253 } else if (SrcOp.isImm()) {
2254 APInt Imm(64, SrcOp.getImm());
2255 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2256 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2257 const MCInstrDesc &PkMovDesc = get(AMDGPU::V_PK_MOV_B32);
2258 const TargetRegisterClass *PkMovRC = getRegClass(PkMovDesc, /*OpNum=*/0);
2259
2260 if (ST.hasPkMovB32() && Lo == Hi && isInlineConstant(Lo) &&
2261 PkMovRC->contains(Dst)) {
2262 BuildMI(MBB, MI, DL, PkMovDesc, Dst)
2264 .addImm(Lo.getSExtValue())
2266 .addImm(Lo.getSExtValue())
2267 .addImm(0) // op_sel_lo
2268 .addImm(0) // op_sel_hi
2269 .addImm(0) // neg_lo
2270 .addImm(0) // neg_hi
2271 .addImm(0); // clamp
2272 } else {
2273 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2274 .addImm(Lo.getSExtValue());
2275 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2276 .addImm(Hi.getSExtValue());
2277 }
2278 } else {
2279 assert(SrcOp.isReg());
2280 if (ST.hasPkMovB32() &&
2281 !RI.isAGPR(MBB.getParent()->getRegInfo(), SrcOp.getReg())) {
2282 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), Dst)
2283 .addImm(SISrcMods::OP_SEL_1) // src0_mod
2284 .addReg(SrcOp.getReg())
2286 .addReg(SrcOp.getReg())
2287 .addImm(0) // op_sel_lo
2288 .addImm(0) // op_sel_hi
2289 .addImm(0) // neg_lo
2290 .addImm(0) // neg_hi
2291 .addImm(0); // clamp
2292 } else {
2293 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2294 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0));
2295 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2296 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1));
2297 }
2298 }
2299 MI.eraseFromParent();
2300 break;
2301 }
2302 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2304 break;
2305 }
2306 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2307 const MachineOperand &SrcOp = MI.getOperand(1);
2308 assert(!SrcOp.isFPImm());
2309
2310 if (ST.has64BitLiterals()) {
2311 MI.setDesc(get(AMDGPU::S_MOV_B64));
2312 break;
2313 }
2314
2315 if (SrcOp.isGlobal()) {
2316 Register Dst = MI.getOperand(0).getReg();
2317 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2318 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2319 const GlobalValue *GV = SrcOp.getGlobal();
2320 int64_t Offset = SrcOp.getOffset();
2321 unsigned BaseFlags, LoReloc, HiReloc;
2322 std::tie(BaseFlags, LoReloc, HiReloc) =
2324
2325 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2326 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2327 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2328 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2329 MI.eraseFromParent();
2330 break;
2331 }
2332
2333 // SrcOp is immediate
2334 APInt Imm(64, SrcOp.getImm());
2335 if (Imm.isIntN(32) || isInlineConstant(Imm)) {
2336 MI.setDesc(get(AMDGPU::S_MOV_B64));
2337 break;
2338 }
2339
2340 Register Dst = MI.getOperand(0).getReg();
2341 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2342 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2343
2344 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2345 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2346 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2347 .addImm(Lo.getSExtValue());
2348 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2349 .addImm(Hi.getSExtValue());
2350 MI.eraseFromParent();
2351 break;
2352 }
2353 case AMDGPU::V_SET_INACTIVE_B32: {
2354 // Lower V_SET_INACTIVE_B32 to V_CNDMASK_B32.
2355 Register DstReg = MI.getOperand(0).getReg();
2356 BuildMI(MBB, MI, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2357 .add(MI.getOperand(3))
2358 .add(MI.getOperand(4))
2359 .add(MI.getOperand(1))
2360 .add(MI.getOperand(2))
2361 .add(MI.getOperand(5));
2362 MI.eraseFromParent();
2363 break;
2364 }
2365 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2366 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2367 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2368 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2369 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2370 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2371 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2372 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2373 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2374 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2375 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2376 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2377 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2378 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2379 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2380 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2381 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2382 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2383 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2384 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2385 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2386 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2387 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2388 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2389 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2390 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2391 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2392 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2393 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2394 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2395 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2396 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2397 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2398 const TargetRegisterClass *EltRC = getOpRegClass(MI, 2);
2399
2400 unsigned Opc;
2401 if (RI.hasVGPRs(EltRC)) {
2402 Opc = AMDGPU::V_MOVRELD_B32_e32;
2403 } else {
2404 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2405 : AMDGPU::S_MOVRELD_B32;
2406 }
2407
2408 const MCInstrDesc &OpDesc = get(Opc);
2409 Register VecReg = MI.getOperand(0).getReg();
2410 bool IsUndef = MI.getOperand(1).isUndef();
2411 unsigned SubReg = MI.getOperand(3).getImm();
2412 assert(VecReg == MI.getOperand(1).getReg());
2413
2415 BuildMI(MBB, MI, DL, OpDesc)
2416 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2417 .add(MI.getOperand(2))
2419 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2420
2421 const int ImpDefIdx =
2422 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2423 const int ImpUseIdx = ImpDefIdx + 1;
2424 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2425 MI.eraseFromParent();
2426 break;
2427 }
2428 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2429 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2430 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2431 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2432 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2433 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2434 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2435 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2436 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2437 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2438 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2439 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2440 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2441 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2442 assert(ST.useVGPRIndexMode());
2443 Register VecReg = MI.getOperand(0).getReg();
2444 bool IsUndef = MI.getOperand(1).isUndef();
2445 MachineOperand &Idx = MI.getOperand(3);
2446 Register SubReg = MI.getOperand(4).getImm();
2447
2448 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2449 .add(Idx)
2451 SetOn->getOperand(3).setIsUndef();
2452
2453 const MCInstrDesc &OpDesc = get(AMDGPU::V_MOV_B32_indirect_write);
2455 BuildMI(MBB, MI, DL, OpDesc)
2456 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2457 .add(MI.getOperand(2))
2459 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2460
2461 const int ImpDefIdx =
2462 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2463 const int ImpUseIdx = ImpDefIdx + 1;
2464 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2465
2466 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2467
2468 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2469
2470 MI.eraseFromParent();
2471 break;
2472 }
2473 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2474 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2475 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2476 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2477 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2478 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2479 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2480 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2481 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2482 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2483 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2484 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2485 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2486 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2487 assert(ST.useVGPRIndexMode());
2488 Register Dst = MI.getOperand(0).getReg();
2489 Register VecReg = MI.getOperand(1).getReg();
2490 bool IsUndef = MI.getOperand(1).isUndef();
2491 Register SubReg = MI.getOperand(3).getImm();
2492
2493 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2494 .add(MI.getOperand(2))
2496 SetOn->getOperand(3).setIsUndef();
2497
2498 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_indirect_read))
2499 .addDef(Dst)
2500 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2501 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2502
2503 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2504
2505 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2506
2507 MI.eraseFromParent();
2508 break;
2509 }
2510 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2511 MachineFunction &MF = *MBB.getParent();
2512 Register Reg = MI.getOperand(0).getReg();
2513 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2514 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2515 MachineOperand OpLo = MI.getOperand(1);
2516 MachineOperand OpHi = MI.getOperand(2);
2517
2518 // Create a bundle so these instructions won't be re-ordered by the
2519 // post-RA scheduler.
2520 MIBundleBuilder Bundler(MBB, MI);
2521 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2522
2523 // What we want here is an offset from the value returned by s_getpc (which
2524 // is the address of the s_add_u32 instruction) to the global variable, but
2525 // since the encoding of $symbol starts 4 bytes after the start of the
2526 // s_add_u32 instruction, we end up with an offset that is 4 bytes too
2527 // small. This requires us to add 4 to the global variable offset in order
2528 // to compute the correct address. Similarly for the s_addc_u32 instruction,
2529 // the encoding of $symbol starts 12 bytes after the start of the s_add_u32
2530 // instruction.
2531
2532 int64_t Adjust = 0;
2533 if (ST.hasGetPCZeroExtension()) {
2534 // Fix up hardware that does not sign-extend the 48-bit PC value by
2535 // inserting: s_sext_i32_i16 reghi, reghi
2536 Bundler.append(
2537 BuildMI(MF, DL, get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2538 Adjust += 4;
2539 }
2540
2541 if (OpLo.isGlobal())
2542 OpLo.setOffset(OpLo.getOffset() + Adjust + 4);
2543 Bundler.append(
2544 BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2545
2546 if (OpHi.isGlobal())
2547 OpHi.setOffset(OpHi.getOffset() + Adjust + 12);
2548 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi)
2549 .addReg(RegHi)
2550 .add(OpHi));
2551
2552 finalizeBundle(MBB, Bundler.begin());
2553
2554 MI.eraseFromParent();
2555 break;
2556 }
2557 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2558 MachineFunction &MF = *MBB.getParent();
2559 Register Reg = MI.getOperand(0).getReg();
2560 MachineOperand Op = MI.getOperand(1);
2561
2562 // Create a bundle so these instructions won't be re-ordered by the
2563 // post-RA scheduler.
2564 MIBundleBuilder Bundler(MBB, MI);
2565 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2566 if (Op.isGlobal())
2567 Op.setOffset(Op.getOffset() + 4);
2568 Bundler.append(
2569 BuildMI(MF, DL, get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(Op));
2570
2571 finalizeBundle(MBB, Bundler.begin());
2572
2573 MI.eraseFromParent();
2574 break;
2575 }
2576 case AMDGPU::ENTER_STRICT_WWM: {
2577 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2578 // Whole Wave Mode is entered.
2579 MI.setDesc(get(LMC.OrSaveExecOpc));
2580 break;
2581 }
2582 case AMDGPU::ENTER_STRICT_WQM: {
2583 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2584 // STRICT_WQM is entered.
2585 BuildMI(MBB, MI, DL, get(LMC.MovOpc), MI.getOperand(0).getReg())
2586 .addReg(LMC.ExecReg);
2587 BuildMI(MBB, MI, DL, get(LMC.WQMOpc), LMC.ExecReg).addReg(LMC.ExecReg);
2588
2589 MI.eraseFromParent();
2590 break;
2591 }
2592 case AMDGPU::EXIT_STRICT_WWM:
2593 case AMDGPU::EXIT_STRICT_WQM: {
2594 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2595 // WWM/STICT_WQM is exited.
2596 MI.setDesc(get(LMC.MovOpc));
2597 break;
2598 }
2599 case AMDGPU::SI_RETURN: {
2600 const MachineFunction *MF = MBB.getParent();
2601 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2602 const SIRegisterInfo *TRI = ST.getRegisterInfo();
2603 // Hiding the return address use with SI_RETURN may lead to extra kills in
2604 // the function and missing live-ins. We are fine in practice because callee
2605 // saved register handling ensures the register value is restored before
2606 // RET, but we need the undef flag here to appease the MachineVerifier
2607 // liveness checks.
2609 BuildMI(MBB, MI, DL, get(AMDGPU::S_SETPC_B64_return))
2610 .addReg(TRI->getReturnAddressReg(*MF), RegState::Undef);
2611
2612 MIB.copyImplicitOps(MI);
2613 MI.eraseFromParent();
2614 break;
2615 }
2616
2617 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2618 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2619 MI.setDesc(get(AMDGPU::S_MUL_U64));
2620 break;
2621
2622 case AMDGPU::S_GETPC_B64_pseudo:
2623 MI.setDesc(get(AMDGPU::S_GETPC_B64));
2624 if (ST.hasGetPCZeroExtension()) {
2625 Register Dst = MI.getOperand(0).getReg();
2626 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2627 // Fix up hardware that does not sign-extend the 48-bit PC value by
2628 // inserting: s_sext_i32_i16 dsthi, dsthi
2629 BuildMI(MBB, std::next(MI.getIterator()), DL, get(AMDGPU::S_SEXT_I32_I16),
2630 DstHi)
2631 .addReg(DstHi);
2632 }
2633 break;
2634
2635 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2636 assert(ST.hasBF16PackedInsts());
2637 MI.setDesc(get(AMDGPU::V_PK_MAX_NUM_BF16));
2638 MI.addOperand(MachineOperand::CreateImm(0)); // op_sel
2639 MI.addOperand(MachineOperand::CreateImm(0)); // neg_lo
2640 MI.addOperand(MachineOperand::CreateImm(0)); // neg_hi
2641 auto Op0 = getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
2642 Op0->setImm(Op0->getImm() | SISrcMods::OP_SEL_1);
2643 auto Op1 = getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
2644 Op1->setImm(Op1->getImm() | SISrcMods::OP_SEL_1);
2645 break;
2646 }
2647
2648 case AMDGPU::GET_STACK_BASE:
2649 // The stack starts at offset 0 unless we need to reserve some space at the
2650 // bottom.
2651 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*MBB.getParent())) {
2652 // When CWSR is used in dynamic VGPR mode, the trap handler needs to save
2653 // some of the VGPRs. The size of the required scratch space has already
2654 // been computed by prolog epilog insertion.
2655 const SIMachineFunctionInfo *MFI =
2656 MBB.getParent()->getInfo<SIMachineFunctionInfo>();
2657 unsigned VGPRSize = MFI->getScratchReservedForDynamicVGPRs();
2658 Register DestReg = MI.getOperand(0).getReg();
2659 BuildMI(MBB, MI, DL, get(AMDGPU::S_GETREG_B32), DestReg)
2662 // The MicroEngine ID is 0 for the graphics queue, and 1 or 2 for compute
2663 // (3 is unused, so we ignore it). Unfortunately, S_GETREG doesn't set
2664 // SCC, so we need to check for 0 manually.
2665 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)).addImm(0).addReg(DestReg);
2666 // Change the implicif-def of SCC to an explicit use (but first remove
2667 // the dead flag if present).
2668 MI.getOperand(MI.getNumExplicitOperands()).setIsDead(false);
2669 MI.getOperand(MI.getNumExplicitOperands()).setIsUse();
2670 MI.setDesc(get(AMDGPU::S_CMOVK_I32));
2671 MI.addOperand(MachineOperand::CreateImm(VGPRSize));
2672 } else {
2673 MI.setDesc(get(AMDGPU::S_MOV_B32));
2674 MI.addOperand(MachineOperand::CreateImm(0));
2675 MI.removeOperand(
2676 MI.getNumExplicitOperands()); // Drop implicit def of SCC.
2677 }
2678 break;
2679 }
2680
2681 return true;
2682}
2683
2686 unsigned SubIdx, const MachineInstr &Orig,
2687 LaneBitmask UsedLanes) const {
2688
2689 // Try shrinking the instruction to remat only the part needed for current
2690 // context.
2691 // TODO: Handle more cases.
2692 unsigned Opcode = Orig.getOpcode();
2693 switch (Opcode) {
2694 case AMDGPU::S_MOV_B64:
2695 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2696 if (SubIdx != 0)
2697 break;
2698
2699 if (!Orig.getOperand(1).isImm())
2700 break;
2701
2702 // Shrink S_MOV_B64 to S_MOV_B32 when UsedLanes indicates only a single
2703 // 32-bit lane of the 64-bit value is live at the rematerialization point.
2704 if (UsedLanes.all())
2705 break;
2706
2707 // Determine which half of the 64-bit immediate corresponds to the use.
2708 unsigned OrigSubReg = Orig.getOperand(0).getSubReg();
2709 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2710 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2711
2712 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2713 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2714
2715 if (NeedLo && NeedHi)
2716 break;
2717
2718 int64_t Imm64 = Orig.getOperand(1).getImm();
2719 int32_t Imm32 = NeedLo ? Lo_32(Imm64) : Hi_32(Imm64);
2720
2721 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2722
2723 // Emit S_MOV_B32 defining just the needed 32-bit subreg of DestReg.
2724 BuildMI(MBB, I, Orig.getDebugLoc(), get(AMDGPU::S_MOV_B32))
2725 .addReg(DestReg, RegState::Define | RegState::Undef, UseSubReg)
2726 .addImm(Imm32);
2727 return;
2728 }
2729
2730 case AMDGPU::S_LOAD_DWORDX16_IMM:
2731 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2732 if (SubIdx != 0)
2733 break;
2734
2735 if (I == MBB.end())
2736 break;
2737
2738 if (I->isBundled())
2739 break;
2740
2741 // Look for a single use of the register that is also a subreg.
2742 Register RegToFind = Orig.getOperand(0).getReg();
2743 MachineOperand *UseMO = nullptr;
2744 for (auto &CandMO : I->operands()) {
2745 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2746 continue;
2747 if (UseMO) {
2748 UseMO = nullptr;
2749 break;
2750 }
2751 UseMO = &CandMO;
2752 }
2753 if (!UseMO || UseMO->getSubReg() == AMDGPU::NoSubRegister)
2754 break;
2755
2756 unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
2757 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());
2758
2759 MachineFunction *MF = MBB.getParent();
2760 MachineRegisterInfo &MRI = MF->getRegInfo();
2761 assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");
2762
2763 unsigned NewOpcode = -1;
2764 if (SubregSize == 256)
2765 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2766 else if (SubregSize == 128)
2767 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2768 else
2769 break;
2770
2771 const MCInstrDesc &TID = get(NewOpcode);
2772 const TargetRegisterClass *NewRC =
2773 RI.getAllocatableClass(getRegClass(TID, 0));
2774 MRI.setRegClass(DestReg, NewRC);
2775
2776 UseMO->setReg(DestReg);
2777 UseMO->setSubReg(AMDGPU::NoSubRegister);
2778
2779 // Use a smaller load with the desired size, possibly with updated offset.
2780 MachineInstr *MI = MF->CloneMachineInstr(&Orig);
2781 MI->setDesc(TID);
2782 MI->getOperand(0).setReg(DestReg);
2783 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2784 if (Offset) {
2785 MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
2786 int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
2787 OffsetMO->setImm(FinalOffset);
2788 }
2790 for (const MachineMemOperand *MemOp : Orig.memoperands())
2791 NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
2792 SubregSize / 8));
2793 MI->setMemRefs(*MF, NewMMOs);
2794
2795 MBB.insert(I, MI);
2796 return;
2797 }
2798
2799 default:
2800 break;
2801 }
2802
2803 TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
2804}
2805
2806std::pair<MachineInstr*, MachineInstr*>
2808 assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2809
2810 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2812 ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
2813 MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
2814 return std::pair(&MI, nullptr);
2815 }
2816
2817 MachineBasicBlock &MBB = *MI.getParent();
2818 DebugLoc DL = MBB.findDebugLoc(MI);
2819 MachineFunction *MF = MBB.getParent();
2820 MachineRegisterInfo &MRI = MF->getRegInfo();
2821 Register Dst = MI.getOperand(0).getReg();
2822 unsigned Part = 0;
2823 MachineInstr *Split[2];
2824
2825 for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2826 auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
2827 if (Dst.isPhysical()) {
2828 MovDPP.addDef(RI.getSubReg(Dst, Sub));
2829 } else {
2830 assert(MRI.isSSA());
2831 auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2832 MovDPP.addDef(Tmp);
2833 }
2834
2835 for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
2836 const MachineOperand &SrcOp = MI.getOperand(I);
2837 assert(!SrcOp.isFPImm());
2838 if (SrcOp.isImm()) {
2839 APInt Imm(64, SrcOp.getImm());
2840 Imm.ashrInPlace(Part * 32);
2841 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2842 } else {
2843 assert(SrcOp.isReg());
2844 Register Src = SrcOp.getReg();
2845 if (Src.isPhysical())
2846 MovDPP.addReg(RI.getSubReg(Src, Sub));
2847 else
2848 MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
2849 }
2850 }
2851
2852 for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
2853 MovDPP.addImm(MO.getImm());
2854
2855 Split[Part] = MovDPP;
2856 ++Part;
2857 }
2858
2859 if (Dst.isVirtual())
2860 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
2861 .addReg(Split[0]->getOperand(0).getReg())
2862 .addImm(AMDGPU::sub0)
2863 .addReg(Split[1]->getOperand(0).getReg())
2864 .addImm(AMDGPU::sub1);
2865
2866 MI.eraseFromParent();
2867 return std::pair(Split[0], Split[1]);
2868}
2869
2870std::optional<DestSourcePair>
2872 if (MI.getOpcode() == AMDGPU::WWM_COPY)
2873 return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
2874
2875 return std::nullopt;
2876}
2877
2879 AMDGPU::OpName Src0OpName,
2880 MachineOperand &Src1,
2881 AMDGPU::OpName Src1OpName) const {
2882 MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
2883 if (!Src0Mods)
2884 return false;
2885
2886 MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
2887 assert(Src1Mods &&
2888 "All commutable instructions have both src0 and src1 modifiers");
2889
2890 int Src0ModsVal = Src0Mods->getImm();
2891 int Src1ModsVal = Src1Mods->getImm();
2892
2893 Src1Mods->setImm(Src0ModsVal);
2894 Src0Mods->setImm(Src1ModsVal);
2895 return true;
2896}
2897
2899 MachineOperand &RegOp,
2900 MachineOperand &NonRegOp) {
2901 Register Reg = RegOp.getReg();
2902 unsigned SubReg = RegOp.getSubReg();
2903 bool IsKill = RegOp.isKill();
2904 bool IsDead = RegOp.isDead();
2905 bool IsUndef = RegOp.isUndef();
2906 bool IsDebug = RegOp.isDebug();
2907
2908 if (NonRegOp.isImm())
2909 RegOp.ChangeToImmediate(NonRegOp.getImm());
2910 else if (NonRegOp.isFI())
2911 RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
2912 else if (NonRegOp.isGlobal()) {
2913 RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
2914 NonRegOp.getTargetFlags());
2915 } else
2916 return nullptr;
2917
2918 // Make sure we don't reinterpret a subreg index in the target flags.
2919 RegOp.setTargetFlags(NonRegOp.getTargetFlags());
2920
2921 NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
2922 NonRegOp.setSubReg(SubReg);
2923
2924 return &MI;
2925}
2926
2928 MachineOperand &NonRegOp1,
2929 MachineOperand &NonRegOp2) {
2930 unsigned TargetFlags = NonRegOp1.getTargetFlags();
2931 int64_t NonRegVal = NonRegOp1.getImm();
2932
2933 NonRegOp1.setImm(NonRegOp2.getImm());
2934 NonRegOp2.setImm(NonRegVal);
2935 NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
2936 NonRegOp2.setTargetFlags(TargetFlags);
2937 return &MI;
2938}
2939
2940bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
2941 unsigned OpIdx1) const {
2942 const MCInstrDesc &InstDesc = MI.getDesc();
2943 const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
2944 const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];
2945
2946 unsigned Opc = MI.getOpcode();
2947 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2948
2949 const MachineOperand &MO0 = MI.getOperand(OpIdx0);
2950 const MachineOperand &MO1 = MI.getOperand(OpIdx1);
2951
2952 // Swap doesn't breach constant bus or literal limits
2953 // It may move literal to position other than src0, this is not allowed
2954 // pre-gfx10 However, most test cases need literals in Src0 for VOP
2955 // FIXME: After gfx9, literal can be in place other than Src0
2956 if (isVALU(MI, /*AllowLDSDMA=*/false)) {
2957 if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
2958 !isInlineConstant(MO0, OpInfo1))
2959 return false;
2960 if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
2961 !isInlineConstant(MO1, OpInfo0))
2962 return false;
2963 }
2964
2965 if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
2966 if (OpInfo1.RegClass == -1)
2967 return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
2968 return isLegalRegOperand(MI, OpIdx1, MO0) &&
2969 (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
2970 }
2971 if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
2972 if (OpInfo0.RegClass == -1)
2973 return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
2974 return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
2975 isLegalRegOperand(MI, OpIdx0, MO1);
2976 }
2977
2978 // No need to check 64-bit literals since swapping does not bring new
2979 // 64-bit literals into current instruction to fold to 32-bit
2980
2981 return isImmOperandLegal(MI, OpIdx1, MO0);
2982}
2983
2985 if (!isDPP(MI))
2986 return false;
2987 const MachineOperand *DppCtrl = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
2988 return !DppCtrl || DppCtrl->getImm() != AMDGPU::DPP::QUAD_PERM_ID;
2989}
2990
2992 unsigned Src0Idx,
2993 unsigned Src1Idx) const {
2994 assert(!NewMI && "this should never be used");
2995
2997 return nullptr;
2998
2999 unsigned Opc = MI.getOpcode();
3000 int CommutedOpcode = commuteOpcode(Opc);
3001 if (CommutedOpcode == -1)
3002 return nullptr;
3003
3004 if (Src0Idx > Src1Idx)
3005 std::swap(Src0Idx, Src1Idx);
3006
3007 assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
3008 static_cast<int>(Src0Idx) &&
3009 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
3010 static_cast<int>(Src1Idx) &&
3011 "inconsistency with findCommutedOpIndices");
3012
3013 if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
3014 return nullptr;
3015
3016 MachineInstr *CommutedMI = nullptr;
3017 MachineOperand &Src0 = MI.getOperand(Src0Idx);
3018 MachineOperand &Src1 = MI.getOperand(Src1Idx);
3019 if (Src0.isReg() && Src1.isReg()) {
3020 // Be sure to copy the source modifiers to the right place.
3021 CommutedMI =
3022 TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
3023 } else if (Src0.isReg() && !Src1.isReg()) {
3024 CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
3025 } else if (!Src0.isReg() && Src1.isReg()) {
3026 CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
3027 } else if (Src0.isImm() && Src1.isImm()) {
3028 CommutedMI = swapImmOperands(MI, Src0, Src1);
3029 } else {
3030 // FIXME: Found two non registers to commute. This does happen.
3031 return nullptr;
3032 }
3033
3034 if (CommutedMI) {
3035 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
3036 Src1, AMDGPU::OpName::src1_modifiers);
3037
3038 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
3039 AMDGPU::OpName::src1_sel);
3040
3041 CommutedMI->setDesc(get(CommutedOpcode));
3042 }
3043
3044 return CommutedMI;
3045}
3046
3047// This needs to be implemented because the source modifiers may be inserted
3048// between the true commutable operands, and the base
3049// TargetInstrInfo::commuteInstruction uses it.
3051 unsigned &SrcOpIdx0,
3052 unsigned &SrcOpIdx1) const {
3054 return false;
3055
3056 return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
3057}
3058
3060 unsigned &SrcOpIdx0,
3061 unsigned &SrcOpIdx1) const {
3062 if (!Desc.isCommutable())
3063 return false;
3064
3065 unsigned Opc = Desc.getOpcode();
3066 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
3067 if (Src0Idx == -1)
3068 return false;
3069
3070 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
3071 if (Src1Idx == -1)
3072 return false;
3073
3074 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3075}
3076
3078 int64_t BrOffset) const {
3079 // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
3080 // because its dest block is unanalyzable.
3081 assert(isSOPP(BranchOp) || isSOPK(BranchOp));
3082
3083 // Convert to dwords.
3084 BrOffset /= 4;
3085
3086 // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
3087 // from the next instruction.
3088 BrOffset -= 1;
3089
3090 return isIntN(BranchOffsetBits, BrOffset);
3091}
3092
3095 return MI.getOperand(0).getMBB();
3096}
3097
3099 for (const MachineInstr &MI : MBB->terminators()) {
3100 if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
3101 MI.getOpcode() == AMDGPU::SI_LOOP)
3102 return true;
3103 }
3104 return false;
3105}
3106
3108 MachineBasicBlock &DestBB,
3109 MachineBasicBlock &RestoreBB,
3110 const DebugLoc &DL, int64_t BrOffset,
3111 RegScavenger *RS) const {
3112 assert(MBB.empty() &&
3113 "new block should be inserted for expanding unconditional branch");
3114 assert(MBB.pred_size() == 1);
3115 assert(RestoreBB.empty() &&
3116 "restore block should be inserted for restoring clobbered registers");
3117
3118 MachineFunction *MF = MBB.getParent();
3119 MachineRegisterInfo &MRI = MF->getRegInfo();
3121 auto I = MBB.end();
3122 auto &MCCtx = MF->getContext();
3123
3124 if (ST.useAddPC64Inst()) {
3125 MCSymbol *Offset =
3126 MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
3127 auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
3129 MCSymbol *PostAddPCLabel =
3130 MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
3131 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3132 auto *OffsetExpr = MCBinaryExpr::createSub(
3133 MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
3134 MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
3135 Offset->setVariableValue(OffsetExpr);
3136 return;
3137 }
3138
3139 assert(RS && "RegScavenger required for long branching");
3140
3141 // FIXME: Virtual register workaround for RegScavenger not working with empty
3142 // blocks.
3143 Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3144
3145 // Note: as this is used after hazard recognizer we need to apply some hazard
3146 // workarounds directly.
3147 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3148 ST.hasVALUReadSGPRHazard();
3149 auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
3150 if (FlushSGPRWrites)
3151 BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
3153 };
3154
3155 // We need to compute the offset relative to the instruction immediately after
3156 // s_getpc_b64. Insert pc arithmetic code before last terminator.
3157 MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
3158 ApplyHazardWorkarounds();
3159
3160 MCSymbol *PostGetPCLabel =
3161 MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
3162 GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);
3163
3164 MCSymbol *OffsetLo =
3165 MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
3166 MCSymbol *OffsetHi =
3167 MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
3168 BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
3169 .addReg(PCReg, RegState::Define, AMDGPU::sub0)
3170 .addReg(PCReg, {}, AMDGPU::sub0)
3171 .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
3172 BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
3173 .addReg(PCReg, RegState::Define, AMDGPU::sub1)
3174 .addReg(PCReg, {}, AMDGPU::sub1)
3175 .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
3176 ApplyHazardWorkarounds();
3177
3178 // Insert the indirect branch after the other terminator.
3179 BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
3180 .addReg(PCReg);
3181
3182 // If a spill is needed for the pc register pair, we need to insert a spill
3183 // restore block right before the destination block, and insert a short branch
3184 // into the old destination block's fallthrough predecessor.
3185 // e.g.:
3186 //
3187 // s_cbranch_scc0 skip_long_branch:
3188 //
3189 // long_branch_bb:
3190 // spill s[8:9]
3191 // s_getpc_b64 s[8:9]
3192 // s_add_u32 s8, s8, restore_bb
3193 // s_addc_u32 s9, s9, 0
3194 // s_setpc_b64 s[8:9]
3195 //
3196 // skip_long_branch:
3197 // foo;
3198 //
3199 // .....
3200 //
3201 // dest_bb_fallthrough_predecessor:
3202 // bar;
3203 // s_branch dest_bb
3204 //
3205 // restore_bb:
3206 // restore s[8:9]
3207 // fallthrough dest_bb
3208 ///
3209 // dest_bb:
3210 // buzz;
3211
3212 Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
3213 Register Scav;
3214
3215 // If we've previously reserved a register for long branches
3216 // avoid running the scavenger and just use those registers
3217 if (LongBranchReservedReg) {
3218 RS->enterBasicBlock(MBB);
3219 Scav = LongBranchReservedReg;
3220 } else {
3221 RS->enterBasicBlockEnd(MBB);
3222 Scav = RS->scavengeRegisterBackwards(
3223 AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
3224 /* RestoreAfter */ false, 0, /* AllowSpill */ false);
3225 }
3226 if (Scav) {
3227 RS->setRegUsed(Scav);
3228 MRI.replaceRegWith(PCReg, Scav);
3229 MRI.clearVirtRegs();
3230 } else {
3231 // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
3232 // SGPR spill.
3233 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
3234 const SIRegisterInfo *TRI = ST.getRegisterInfo();
3235 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3236 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3237 MRI.clearVirtRegs();
3238 }
3239
3240 MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
3241 // Now, the distance could be defined.
3243 MCSymbolRefExpr::create(DestLabel, MCCtx),
3244 MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
3245 // Add offset assignments.
3246 auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
3247 OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
3248 auto *ShAmt = MCConstantExpr::create(32, MCCtx);
3249 OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
3250}
3251
3252unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
3253 switch (Cond) {
3254 case SIInstrInfo::SCC_TRUE:
3255 return AMDGPU::S_CBRANCH_SCC1;
3256 case SIInstrInfo::SCC_FALSE:
3257 return AMDGPU::S_CBRANCH_SCC0;
3258 case SIInstrInfo::VCCNZ:
3259 return AMDGPU::S_CBRANCH_VCCNZ;
3260 case SIInstrInfo::VCCZ:
3261 return AMDGPU::S_CBRANCH_VCCZ;
3262 case SIInstrInfo::EXECNZ:
3263 return AMDGPU::S_CBRANCH_EXECNZ;
3264 case SIInstrInfo::EXECZ:
3265 return AMDGPU::S_CBRANCH_EXECZ;
3266 default:
3267 llvm_unreachable("invalid branch predicate");
3268 }
3269}
3270
3271SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
3272 switch (Opcode) {
3273 case AMDGPU::S_CBRANCH_SCC0:
3274 return SCC_FALSE;
3275 case AMDGPU::S_CBRANCH_SCC1:
3276 return SCC_TRUE;
3277 case AMDGPU::S_CBRANCH_VCCNZ:
3278 return VCCNZ;
3279 case AMDGPU::S_CBRANCH_VCCZ:
3280 return VCCZ;
3281 case AMDGPU::S_CBRANCH_EXECNZ:
3282 return EXECNZ;
3283 case AMDGPU::S_CBRANCH_EXECZ:
3284 return EXECZ;
3285 default:
3286 return INVALID_BR;
3287 }
3288}
3289
3293 MachineBasicBlock *&FBB,
3295 bool AllowModify) const {
3296 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3297 // Unconditional Branch
3298 TBB = I->getOperand(0).getMBB();
3299 return false;
3300 }
3301
3302 BranchPredicate Pred = getBranchPredicate(I->getOpcode());
3303 if (Pred == INVALID_BR)
3304 return true;
3305
3306 MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
3307 Cond.push_back(MachineOperand::CreateImm(Pred));
3308 Cond.push_back(I->getOperand(1)); // Save the branch register.
3309
3310 ++I;
3311
3312 if (I == MBB.end()) {
3313 // Conditional branch followed by fall-through.
3314 TBB = CondBB;
3315 return false;
3316 }
3317
3318 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3319 TBB = CondBB;
3320 FBB = I->getOperand(0).getMBB();
3321 return false;
3322 }
3323
3324 return true;
3325}
3326
3328 MachineBasicBlock *&FBB,
3330 bool AllowModify) const {
3331 MachineBasicBlock::iterator I = MBB.getFirstTerminator();
3332 auto E = MBB.end();
3333 if (I == E)
3334 return false;
3335
3336 // Skip over the instructions that are artificially terminators for special
3337 // exec management.
3338 while (I != E && !I->isBranch() && !I->isReturn()) {
3339 switch (I->getOpcode()) {
3340 case AMDGPU::S_MOV_B64_term:
3341 case AMDGPU::S_XOR_B64_term:
3342 case AMDGPU::S_OR_B64_term:
3343 case AMDGPU::S_ANDN2_B64_term:
3344 case AMDGPU::S_AND_B64_term:
3345 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3346 case AMDGPU::S_MOV_B32_term:
3347 case AMDGPU::S_XOR_B32_term:
3348 case AMDGPU::S_OR_B32_term:
3349 case AMDGPU::S_ANDN2_B32_term:
3350 case AMDGPU::S_AND_B32_term:
3351 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3352 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3353 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3354 break;
3355 case AMDGPU::SI_IF:
3356 case AMDGPU::SI_ELSE:
3357 case AMDGPU::SI_KILL_I1_TERMINATOR:
3358 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3359 // FIXME: It's messy that these need to be considered here at all.
3360 return true;
3361 default:
3362 llvm_unreachable("unexpected non-branch terminator inst");
3363 }
3364
3365 ++I;
3366 }
3367
3368 if (I == E)
3369 return false;
3370
3371 return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
3372}
3373
3375 int *BytesRemoved) const {
3376 unsigned Count = 0;
3377 unsigned RemovedSize = 0;
3378 for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
3379 // Skip over artificial terminators when removing instructions.
3380 if (MI.isBranch() || MI.isReturn()) {
3381 RemovedSize += getInstSizeInBytes(MI);
3382 MI.eraseFromParent();
3383 ++Count;
3384 }
3385 }
3386
3387 if (BytesRemoved)
3388 *BytesRemoved = RemovedSize;
3389
3390 return Count;
3391}
3392
3393// Copy the flags onto the implicit condition register operand.
3395 const MachineOperand &OrigCond) {
3396 CondReg.setIsUndef(OrigCond.isUndef());
3397 CondReg.setIsKill(OrigCond.isKill());
3398}
3399
3402 MachineBasicBlock *FBB,
3404 const DebugLoc &DL,
3405 int *BytesAdded) const {
3406 if (!FBB && Cond.empty()) {
3407 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3408 .addMBB(TBB);
3409 if (BytesAdded)
3410 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3411 return 1;
3412 }
3413
3414 assert(TBB && Cond[0].isImm());
3415
3416 unsigned Opcode
3417 = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));
3418
3419 if (!FBB) {
3420 MachineInstr *CondBr =
3421 BuildMI(&MBB, DL, get(Opcode))
3422 .addMBB(TBB);
3423
3424 // Copy the flags onto the implicit condition register operand.
3425 preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
3426 fixImplicitOperands(*CondBr);
3427
3428 if (BytesAdded)
3429 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3430 return 1;
3431 }
3432
3433 assert(TBB && FBB);
3434
3435 MachineInstr *CondBr =
3436 BuildMI(&MBB, DL, get(Opcode))
3437 .addMBB(TBB);
3438 fixImplicitOperands(*CondBr);
3439 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3440 .addMBB(FBB);
3441
3442 MachineOperand &CondReg = CondBr->getOperand(1);
3443 CondReg.setIsUndef(Cond[1].isUndef());
3444 CondReg.setIsKill(Cond[1].isKill());
3445
3446 if (BytesAdded)
3447 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3448
3449 return 2;
3450}
3451
3454 if (Cond.size() != 2) {
3455 return true;
3456 }
3457
3458 if (Cond[0].isImm()) {
3459 Cond[0].setImm(-Cond[0].getImm());
3460 return false;
3461 }
3462
3463 return true;
3464}
3465
3466namespace {
3467class AMDGPUPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
3468private:
3469 /// The compare instruction for loop control
3470 const MachineInstr *CmpInst = nullptr;
3471 /// The normalized condition used by createTripCountGreaterCondition()
3473
3474public:
3475 AMDGPUPipelinerLoopInfo(MachineInstr *CmpInst,
3477 : CmpInst(CmpInst), Cond(Cond.begin(), Cond.end()) {}
3478
3479 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
3480 return CmpInst && MI == CmpInst;
3481 }
3482
3483 std::optional<bool> createTripCountGreaterCondition(
3484 int TC, MachineBasicBlock &MBB,
3485 SmallVectorImpl<MachineOperand> &CondParam) override {
3486 CondParam = this->Cond;
3487 return {};
3488 }
3489
3490 void adjustTripCount(int TripCountAdjust) override {}
3491
3492 void setPreheader(MachineBasicBlock *NewPreheader) override {}
3493};
3494} // namespace
3495
3496std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3498 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
3500 // Unanalyzable terminator.
3501 if (analyzeBranch(*LoopBB, TBB, FBB, Cond, /*AllowModify=*/false))
3502 return nullptr;
3503
3504 // Infinite loops are not supported.
3505 if (TBB == LoopBB && FBB == LoopBB)
3506 return nullptr;
3507
3508 // Must be conditional branch.
3509 if (FBB == nullptr)
3510 return nullptr;
3511
3512 assert((TBB == LoopBB || FBB == LoopBB) &&
3513 "The Loop must be a single-basic-block loop");
3514
3515 // Divergent (VCC/EXEC) back-edge is not supported.
3516 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3517 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3518 return nullptr;
3519
3520 // Calls and inline assembly are not supported.
3521 for (const MachineInstr &MI : *LoopBB)
3522 if (MI.isCall() || MI.isInlineAsm())
3523 return nullptr;
3524
3525 // Normalization for createTripCountGreaterCondition(): make Cond mean
3526 // "exit the loop" so the expander emits correct prolog guard branches.
3527 if (TBB == LoopBB)
3529
3530 auto Instructions = make_range(
3532 LoopBB->rend());
3533 auto CmpI = llvm::find_if(Instructions, [&](const MachineInstr &MI) {
3534 return MI.modifiesRegister(Cond[1].getReg(), &RI);
3535 });
3536
3537 if (CmpI == Instructions.end() || CmpI->isPHI())
3538 return nullptr;
3539 MachineInstr *CmpInst = &*CmpI;
3540
3541 return std::make_unique<AMDGPUPipelinerLoopInfo>(CmpInst, Cond);
3542}
3543
3546 Register DstReg, Register TrueReg,
3547 Register FalseReg, int &CondCycles,
3548 int &TrueCycles, int &FalseCycles) const {
3549 switch (Cond[0].getImm()) {
3550 case VCCNZ:
3551 case VCCZ: {
3552 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3553 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3554 if (MRI.getRegClass(FalseReg) != RC)
3555 return false;
3556
3557 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3558 CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
3559
3560 // Limit to equal cost for branch vs. N v_cndmask_b32s.
3561 return RI.hasVGPRs(RC) && NumInsts <= 6;
3562 }
3563 case SCC_TRUE:
3564 case SCC_FALSE: {
3565 // FIXME: We could insert for VGPRs if we could replace the original compare
3566 // with a vector one.
3567 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3568 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3569 if (MRI.getRegClass(FalseReg) != RC)
3570 return false;
3571
3572 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3573
3574 // Multiples of 8 can do s_cselect_b64
3575 if (NumInsts % 2 == 0)
3576 NumInsts /= 2;
3577
3578 CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
3579 return RI.isSGPRClass(RC);
3580 }
3581 default:
3582 return false;
3583 }
3584}
3585
3589 Register TrueReg, Register FalseReg) const {
3590 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3591 if (Pred == VCCZ || Pred == SCC_FALSE) {
3592 Pred = static_cast<BranchPredicate>(-Pred);
3593 std::swap(TrueReg, FalseReg);
3594 }
3595
3596 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3597 const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
3598 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3599
3600 if (DstSize == 32) {
3602 if (Pred == SCC_TRUE) {
3603 Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
3604 .addReg(TrueReg)
3605 .addReg(FalseReg);
3606 } else {
3607 // Instruction's operands are backwards from what is expected.
3608 Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
3609 .addReg(FalseReg)
3610 .addReg(TrueReg);
3611 }
3612
3613 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3614 return;
3615 }
3616
3617 if (DstSize == 64 && Pred == SCC_TRUE) {
3619 BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
3620 .addReg(TrueReg)
3621 .addReg(FalseReg);
3622
3623 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3624 return;
3625 }
3626
3627 static const int16_t Sub0_15[] = {
3628 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3629 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3630 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3631 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3632 };
3633
3634 static const int16_t Sub0_15_64[] = {
3635 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3636 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3637 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3638 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3639 };
3640
3641 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3642 const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
3643 const int16_t *SubIndices = Sub0_15;
3644 int NElts = DstSize / 32;
3645
3646 // 64-bit select is only available for SALU.
3647 // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
3648 if (Pred == SCC_TRUE) {
3649 if (NElts % 2) {
3650 SelOp = AMDGPU::S_CSELECT_B32;
3651 EltRC = &AMDGPU::SGPR_32RegClass;
3652 } else {
3653 SelOp = AMDGPU::S_CSELECT_B64;
3654 EltRC = &AMDGPU::SGPR_64RegClass;
3655 SubIndices = Sub0_15_64;
3656 NElts /= 2;
3657 }
3658 }
3659
3661 MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);
3662
3663 I = MIB->getIterator();
3664
3666 for (int Idx = 0; Idx != NElts; ++Idx) {
3667 Register DstElt = MRI.createVirtualRegister(EltRC);
3668 Regs.push_back(DstElt);
3669
3670 unsigned SubIdx = SubIndices[Idx];
3671
3673 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3674 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3675 .addReg(FalseReg, {}, SubIdx)
3676 .addReg(TrueReg, {}, SubIdx);
3677 } else {
3678 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3679 .addReg(TrueReg, {}, SubIdx)
3680 .addReg(FalseReg, {}, SubIdx);
3681 }
3682
3683 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3685
3686 MIB.addReg(DstElt)
3687 .addImm(SubIdx);
3688 }
3689}
3690
3692
3693 if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
3694 return true;
3695
3696 switch (MI.getOpcode()) {
3697 case AMDGPU::S_ENDPGM:
3698 case AMDGPU::S_ENDPGM_SAVED:
3699 case AMDGPU::S_TRAP:
3700 case AMDGPU::S_GETREG_B32:
3701 case AMDGPU::S_SETREG_B32:
3702 case AMDGPU::S_SETREG_B32_mode:
3703 case AMDGPU::S_SETREG_IMM32_B32:
3704 case AMDGPU::S_SETREG_IMM32_B32_mode:
3705 case AMDGPU::S_SENDMSG:
3706 case AMDGPU::S_SENDMSGHALT:
3707 case AMDGPU::S_SENDMSG_RTN_B32:
3708 case AMDGPU::S_SENDMSG_RTN_B64:
3709 case AMDGPU::S_BARRIER_WAIT:
3710 case AMDGPU::S_BARRIER_SIGNAL_M0:
3711 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3712 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3713 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3714 return true;
3715 default:
3716 return false;
3717 }
3718}
3719
3721 switch (MI.getOpcode()) {
3722 case AMDGPU::V_MOV_B16_t16_e32:
3723 case AMDGPU::V_MOV_B16_t16_e64:
3724 case AMDGPU::V_MOV_B32_e32:
3725 case AMDGPU::V_MOV_B32_e64:
3726 case AMDGPU::V_MOV_B64_PSEUDO:
3727 case AMDGPU::V_MOV_B64_e32:
3728 case AMDGPU::V_MOV_B64_e64:
3729 case AMDGPU::S_MOV_B32:
3730 case AMDGPU::S_MOV_B64:
3731 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3732 case AMDGPU::COPY:
3733 case AMDGPU::WWM_COPY:
3734 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3735 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3736 case AMDGPU::V_ACCVGPR_MOV_B32:
3737 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3738 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3739 return true;
3740 default:
3741 return false;
3742 }
3743}
3744
3746 switch (MI.getOpcode()) {
3747 case AMDGPU::V_MOV_B16_t16_e32:
3748 case AMDGPU::V_MOV_B16_t16_e64:
3749 return 2;
3750 case AMDGPU::V_MOV_B32_e32:
3751 case AMDGPU::V_MOV_B32_e64:
3752 case AMDGPU::V_MOV_B64_PSEUDO:
3753 case AMDGPU::V_MOV_B64_e32:
3754 case AMDGPU::V_MOV_B64_e64:
3755 case AMDGPU::S_MOV_B32:
3756 case AMDGPU::S_MOV_B64:
3757 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3758 case AMDGPU::COPY:
3759 case AMDGPU::WWM_COPY:
3760 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3761 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3762 case AMDGPU::V_ACCVGPR_MOV_B32:
3763 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3764 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3765 return 1;
3766 default:
3767 llvm_unreachable("MI is not a foldable copy");
3768 }
3769}
3770
3771static constexpr AMDGPU::OpName ModifierOpNames[] = {
3772 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3773 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3774 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3775
3777 unsigned Opc = MI.getOpcode();
3778 for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
3779 int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
3780 if (Idx >= 0)
3781 MI.removeOperand(Idx);
3782 }
3783}
3784
3786 const MCInstrDesc &NewDesc) const {
3787 MI.setDesc(NewDesc);
3788
3789 // Remove any leftover implicit operands from mutating the instruction. e.g.
3790 // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
3791 // anymore.
3792 const MCInstrDesc &Desc = MI.getDesc();
3793 unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
3794 Desc.implicit_defs().size();
3795
3796 for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
3797 MI.removeOperand(I);
3798}
3799
3800std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
3801 unsigned SubRegIndex) {
3802 switch (SubRegIndex) {
3803 case AMDGPU::NoSubRegister:
3804 return Imm;
3805 case AMDGPU::sub0:
3806 return SignExtend64<32>(Imm);
3807 case AMDGPU::sub1:
3808 return SignExtend64<32>(Imm >> 32);
3809 case AMDGPU::lo16:
3810 return SignExtend64<16>(Imm);
3811 case AMDGPU::hi16:
3812 return SignExtend64<16>(Imm >> 16);
3813 case AMDGPU::sub1_lo16:
3814 return SignExtend64<16>(Imm >> 32);
3815 case AMDGPU::sub1_hi16:
3816 return SignExtend64<16>(Imm >> 48);
3817 default:
3818 return std::nullopt;
3819 }
3820
3821 llvm_unreachable("covered subregister switch");
3822}
3823
3824static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
3825 switch (Opc) {
3826 case AMDGPU::V_MAC_F16_e32:
3827 case AMDGPU::V_MAC_F16_e64:
3828 case AMDGPU::V_MAD_F16_e64:
3829 return AMDGPU::V_MADAK_F16;
3830 case AMDGPU::V_MAC_F32_e32:
3831 case AMDGPU::V_MAC_F32_e64:
3832 case AMDGPU::V_MAD_F32_e64:
3833 return AMDGPU::V_MADAK_F32;
3834 case AMDGPU::V_FMAC_F32_e32:
3835 case AMDGPU::V_FMAC_F32_e64:
3836 case AMDGPU::V_FMA_F32_e64:
3837 return AMDGPU::V_FMAAK_F32;
3838 case AMDGPU::V_FMAC_F16_e32:
3839 case AMDGPU::V_FMAC_F16_e64:
3840 case AMDGPU::V_FMAC_F16_t16_e64:
3841 case AMDGPU::V_FMAC_F16_fake16_e64:
3842 case AMDGPU::V_FMAC_F16_t16_e32:
3843 case AMDGPU::V_FMAC_F16_fake16_e32:
3844 case AMDGPU::V_FMA_F16_e64:
3845 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3846 ? AMDGPU::V_FMAAK_F16_t16
3847 : AMDGPU::V_FMAAK_F16_fake16
3848 : AMDGPU::V_FMAAK_F16;
3849 case AMDGPU::V_FMAC_F64_e32:
3850 case AMDGPU::V_FMAC_F64_e64:
3851 case AMDGPU::V_FMA_F64_e64:
3852 return AMDGPU::V_FMAAK_F64;
3853 default:
3854 llvm_unreachable("invalid instruction");
3855 }
3856}
3857
3858static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
3859 switch (Opc) {
3860 case AMDGPU::V_MAC_F16_e32:
3861 case AMDGPU::V_MAC_F16_e64:
3862 case AMDGPU::V_MAD_F16_e64:
3863 return AMDGPU::V_MADMK_F16;
3864 case AMDGPU::V_MAC_F32_e32:
3865 case AMDGPU::V_MAC_F32_e64:
3866 case AMDGPU::V_MAD_F32_e64:
3867 return AMDGPU::V_MADMK_F32;
3868 case AMDGPU::V_FMAC_F32_e32:
3869 case AMDGPU::V_FMAC_F32_e64:
3870 case AMDGPU::V_FMA_F32_e64:
3871 return AMDGPU::V_FMAMK_F32;
3872 case AMDGPU::V_FMAC_F16_e32:
3873 case AMDGPU::V_FMAC_F16_e64:
3874 case AMDGPU::V_FMAC_F16_t16_e64:
3875 case AMDGPU::V_FMAC_F16_fake16_e64:
3876 case AMDGPU::V_FMAC_F16_t16_e32:
3877 case AMDGPU::V_FMAC_F16_fake16_e32:
3878 case AMDGPU::V_FMA_F16_e64:
3879 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3880 ? AMDGPU::V_FMAMK_F16_t16
3881 : AMDGPU::V_FMAMK_F16_fake16
3882 : AMDGPU::V_FMAMK_F16;
3883 case AMDGPU::V_FMAC_F64_e32:
3884 case AMDGPU::V_FMAC_F64_e64:
3885 case AMDGPU::V_FMA_F64_e64:
3886 return AMDGPU::V_FMAMK_F64;
3887 default:
3888 llvm_unreachable("invalid instruction");
3889 }
3890}
3891
3893 Register Reg, MachineRegisterInfo *MRI) const {
3894 int64_t Imm;
3895 if (!getConstValDefinedInReg(DefMI, Reg, Imm))
3896 return false;
3897
3898 const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);
3899
3900 assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");
3901
3902 unsigned Opc = UseMI.getOpcode();
3903 if (Opc == AMDGPU::COPY) {
3904 assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");
3905
3906 Register DstReg = UseMI.getOperand(0).getReg();
3907 Register UseSubReg = UseMI.getOperand(1).getSubReg();
3908
3909 const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);
3910
3911 if (HasMultipleUses) {
3912 // TODO: This should fold in more cases with multiple use, but we need to
3913 // more carefully consider what those uses are.
3914 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));
3915
3916 // Avoid breaking up a 64-bit inline immediate into a subregister extract.
3917 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3918 return false;
3919
3920 // Most of the time folding a 32-bit inline constant is free (though this
3921 // might not be true if we can't later fold it into a real user).
3922 //
3923 // FIXME: This isInlineConstant check is imprecise if
3924 // getConstValDefinedInReg handled the tricky non-mov cases.
3925 if (ImmDefSize == 32 &&
3927 return false;
3928 }
3929
3930 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3931 RI.getSubRegIdxSize(UseSubReg) == 16;
3932
3933 if (Is16Bit) {
3934 if (RI.hasVGPRs(DstRC))
3935 return false; // Do not clobber vgpr_hi16
3936
3937 if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
3938 return false;
3939 }
3940
3941 MachineFunction *MF = UseMI.getMF();
3942
3943 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3944 MCRegister MovDstPhysReg =
3945 DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();
3946
3947 std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);
3948
3949 // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
3950 for (unsigned MovOp :
3951 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3952 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3953 const MCInstrDesc &MovDesc = get(MovOp);
3954
3955 const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
3956 if (Is16Bit) {
3957 // We just need to find a correctly sized register class, so the
3958 // subregister index compatibility doesn't matter since we're statically
3959 // extracting the immediate value.
3960 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3961 if (!MovDstRC)
3962 continue;
3963
3964 if (MovDstPhysReg) {
3965 // FIXME: We probably should not do this. If there is a live value in
3966 // the high half of the register, it will be corrupted.
3967 MovDstPhysReg =
3968 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3969 if (!MovDstPhysReg)
3970 continue;
3971 }
3972 }
3973
3974 // Result class isn't the right size, try the next instruction.
3975 if (MovDstPhysReg) {
3976 if (!MovDstRC->contains(MovDstPhysReg))
3977 return false;
3978 } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
3979 // TODO: This will be overly conservative in the case of 16-bit virtual
3980 // SGPRs. We could hack up the virtual register uses to use a compatible
3981 // 32-bit class.
3982 continue;
3983 }
3984
3985 const MCOperandInfo &OpInfo = MovDesc.operands()[1];
3986
3987 // Ensure the interpreted immediate value is a valid operand in the new
3988 // mov.
3989 //
3990 // FIXME: isImmOperandLegal should have form that doesn't require existing
3991 // MachineInstr or MachineOperand
3992 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3993 !isInlineConstant(*SubRegImm, OpInfo.OperandType))
3994 break;
3995
3996 NewOpc = MovOp;
3997 break;
3998 }
3999
4000 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4001 return false;
4002
4003 if (Is16Bit) {
4004 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4005 if (MovDstPhysReg)
4006 UseMI.getOperand(0).setReg(MovDstPhysReg);
4007 assert(UseMI.getOperand(1).getReg().isVirtual());
4008 }
4009
4010 const MCInstrDesc &NewMCID = get(NewOpc);
4011 UseMI.setDesc(NewMCID);
4012 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4013 UseMI.addImplicitDefUseOperands(*MF);
4014 return true;
4015 }
4016
4017 if (HasMultipleUses)
4018 return false;
4019
4020 if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
4021 Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4022 Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
4023 Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
4024 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4025 Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
4026 Opc == AMDGPU::V_FMAC_F64_e64) {
4027 // Don't fold if we are using source or output modifiers. The new VOP2
4028 // instructions don't have them.
4030 return false;
4031
4032 // If this is a free constant, there's no reason to do this.
4033 // TODO: We could fold this here instead of letting SIFoldOperands do it
4034 // later.
4035 int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4036
4037 // Any src operand can be used for the legality check.
4038 if (isInlineConstant(UseMI, Src0Idx, Imm))
4039 return false;
4040
4041 MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);
4042
4043 MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
4044 MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);
4045
4046 auto CopyRegOperandToNarrowerRC =
4047 [MRI, this](MachineInstr &MI, unsigned OpNo,
4048 const TargetRegisterClass *NewRC) -> void {
4049 if (!MI.getOperand(OpNo).isReg())
4050 return;
4051 Register Reg = MI.getOperand(OpNo).getReg();
4052 const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
4053 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4054 return;
4055 Register Tmp = MRI->createVirtualRegister(NewRC);
4056 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
4057 get(AMDGPU::COPY), Tmp)
4058 .addReg(Reg);
4059 MI.getOperand(OpNo).setReg(Tmp);
4060 MI.getOperand(OpNo).setIsKill();
4061 };
4062
4063 // Multiplied part is the constant: Use v_madmk_{f16, f32}.
4064 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4065 (Src1->isReg() && Src1->getReg() == Reg)) {
4066 MachineOperand *RegSrc =
4067 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4068 if (!RegSrc->isReg())
4069 return false;
4070 if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
4071 ST.getConstantBusLimit(Opc) < 2)
4072 return false;
4073
4074 if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
4075 return false;
4076
4077 // If src2 is also a literal constant then we have to choose which one to
4078 // fold. In general it is better to choose madak so that the other literal
4079 // can be materialized in an sgpr instead of a vgpr:
4080 // s_mov_b32 s0, literal
4081 // v_madak_f32 v0, s0, v0, literal
4082 // Instead of:
4083 // v_mov_b32 v1, literal
4084 // v_madmk_f32 v0, v0, literal, v1
4085 MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
4086 if (Def && Def->isMoveImmediate() &&
4087 !isInlineConstant(Def->getOperand(1)))
4088 return false;
4089
4090 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4091 if (pseudoToMCOpcode(NewOpc) == -1)
4092 return false;
4093
4094 const std::optional<int64_t> SubRegImm = extractSubregFromImm(
4095 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4096
4097 // FIXME: This would be a lot easier if we could return a new instruction
4098 // instead of having to modify in place.
4099
4100 Register SrcReg = RegSrc->getReg();
4101 unsigned SrcSubReg = RegSrc->getSubReg();
4102 Src0->setReg(SrcReg);
4103 Src0->setSubReg(SrcSubReg);
4104 Src0->setIsKill(RegSrc->isKill());
4105
4106 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4107 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4108 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4109 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4110 UseMI.untieRegOperand(
4111 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4112
4113 Src1->ChangeToImmediate(*SubRegImm);
4114
4116 UseMI.setDesc(get(NewOpc));
4117
4118 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4119 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4120 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4121 Register Tmp = MRI->createVirtualRegister(NewRC);
4122 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4123 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4124 UseMI.getOperand(0).getReg())
4125 .addReg(Tmp, RegState::Kill);
4126 UseMI.getOperand(0).setReg(Tmp);
4127 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4128 CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
4129 }
4130
4131 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4132 if (DeleteDef)
4133 DefMI.eraseFromParent();
4134
4135 return true;
4136 }
4137
4138 // Added part is the constant: Use v_madak_{f16, f32}.
4139 if (Src2->isReg() && Src2->getReg() == Reg) {
4140 if (ST.getConstantBusLimit(Opc) < 2) {
4141 // Not allowed to use constant bus for another operand.
4142 // We can however allow an inline immediate as src0.
4143 bool Src0Inlined = false;
4144 if (Src0->isReg()) {
4145 // Try to inline constant if possible.
4146 // If the Def moves immediate and the use is single
4147 // We are saving VGPR here.
4148 MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
4149 if (Def && Def->isMoveImmediate() &&
4150 isInlineConstant(Def->getOperand(1)) &&
4151 MRI->hasOneNonDBGUse(Src0->getReg())) {
4152 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4153 Src0Inlined = true;
4154 } else if (ST.getConstantBusLimit(Opc) <= 1 &&
4155 RI.isSGPRReg(*MRI, Src0->getReg())) {
4156 return false;
4157 }
4158 // VGPR is okay as Src0 - fallthrough
4159 }
4160
4161 if (Src1->isReg() && !Src0Inlined) {
4162 // We have one slot for inlinable constant so far - try to fill it
4163 MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
4164 if (Def && Def->isMoveImmediate() &&
4165 isInlineConstant(Def->getOperand(1)) &&
4166 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
4167 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4168 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
4169 return false;
4170 // VGPR is okay as Src1 - fallthrough
4171 }
4172 }
4173
4174 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4175 if (pseudoToMCOpcode(NewOpc) == -1)
4176 return false;
4177
4178 // FIXME: This would be a lot easier if we could return a new instruction
4179 // instead of having to modify in place.
4180
4181 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4182 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4183 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4184 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4185 UseMI.untieRegOperand(
4186 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4187
4188 const std::optional<int64_t> SubRegImm =
4190
4191 // ChangingToImmediate adds Src2 back to the instruction.
4192 Src2->ChangeToImmediate(*SubRegImm);
4193
4194 // These come before src2.
4196 UseMI.setDesc(get(NewOpc));
4197
4198 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4199 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4200 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4201 Register Tmp = MRI->createVirtualRegister(NewRC);
4202 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4203 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4204 UseMI.getOperand(0).getReg())
4205 .addReg(Tmp, RegState::Kill);
4206 UseMI.getOperand(0).setReg(Tmp);
4207 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4208 CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
4209 }
4210
4211 // It might happen that UseMI was commuted
4212 // and we now have SGPR as SRC1. If so 2 inlined
4213 // constant and SGPR are illegal.
4215
4216 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4217 if (DeleteDef)
4218 DefMI.eraseFromParent();
4219
4220 return true;
4221 }
4222 }
4223
4224 return false;
4225}
4226
4227static bool
4230 if (BaseOps1.size() != BaseOps2.size())
4231 return false;
4232 for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
4233 if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
4234 return false;
4235 }
4236 return true;
4237}
4238
4239static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
4240 LocationSize WidthB, int OffsetB) {
4241 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4242 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4243 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4244 return LowWidth.hasValue() &&
4245 LowOffset + (int)LowWidth.getValue() <= HighOffset;
4246}
4247
4248bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
4249 const MachineInstr &MIb) const {
4250 SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
4251 int64_t Offset0, Offset1;
4252 LocationSize Dummy0 = LocationSize::precise(0);
4253 LocationSize Dummy1 = LocationSize::precise(0);
4254 bool Offset0IsScalable, Offset1IsScalable;
4255 if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
4256 Dummy0, &RI) ||
4257 !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
4258 Dummy1, &RI))
4259 return false;
4260
4261 if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
4262 return false;
4263
4264 if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
4265 // FIXME: Handle ds_read2 / ds_write2.
4266 return false;
4267 }
4268 LocationSize Width0 = MIa.memoperands().front()->getSize();
4269 LocationSize Width1 = MIb.memoperands().front()->getSize();
4270 return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
4271}
4272
4274 const MachineInstr &MIb) const {
4275 assert(MIa.mayLoadOrStore() &&
4276 "MIa must load from or modify a memory location");
4277 assert(MIb.mayLoadOrStore() &&
4278 "MIb must load from or modify a memory location");
4279
4281 return false;
4282
4283 // XXX - Can we relax this between address spaces?
4284 if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
4285 return false;
4286
4287 if (isLDSDMA(MIa) || isLDSDMA(MIb))
4288 return false;
4289
4290 if (MIa.isBundle() || MIb.isBundle())
4291 return false;
4292
4293 // TODO: Should we check the address space from the MachineMemOperand? That
4294 // would allow us to distinguish objects we know don't alias based on the
4295 // underlying address space, even if it was lowered to a different one,
4296 // e.g. private accesses lowered to use MUBUF instructions on a scratch
4297 // buffer.
4298 if (isDS(MIa)) {
4299 if (isDS(MIb))
4300 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4301
4302 return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
4303 }
4304
4305 if (isMUBUF(MIa) || isMTBUF(MIa)) {
4306 if (isMUBUF(MIb) || isMTBUF(MIb))
4307 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4308
4309 if (isFLAT(MIb))
4310 return isFLATScratch(MIb);
4311
4312 return !isSMRD(MIb);
4313 }
4314
4315 if (isSMRD(MIa)) {
4316 if (isSMRD(MIb))
4317 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4318
4319 if (isFLAT(MIb))
4320 return isFLATScratch(MIb);
4321
4322 return !isMUBUF(MIb) && !isMTBUF(MIb);
4323 }
4324
4325 if (isFLAT(MIa)) {
4326 if (isFLAT(MIb)) {
4327 if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
4328 (isFLATGlobal(MIa) && isFLATScratch(MIb)))
4329 return true;
4330
4331 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4332 }
4333
4334 return false;
4335 }
4336
4337 return false;
4338}
4339
4341 MachineInstr &NewMI) {
4342 if (LV) {
4343 unsigned NumOps = MI.getNumOperands();
4344 for (unsigned I = 1; I < NumOps; ++I) {
4345 MachineOperand &Op = MI.getOperand(I);
4346 if (Op.isReg() && Op.isKill())
4347 LV->replaceKillInstruction(Op.getReg(), MI, NewMI);
4348 }
4349 }
4350}
4351
4352static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
4353 switch (Opc) {
4354 case AMDGPU::V_MAC_F16_e32:
4355 case AMDGPU::V_MAC_F16_e64:
4356 return AMDGPU::V_MAD_F16_e64;
4357 case AMDGPU::V_MAC_F32_e32:
4358 case AMDGPU::V_MAC_F32_e64:
4359 return AMDGPU::V_MAD_F32_e64;
4360 case AMDGPU::V_MAC_LEGACY_F32_e32:
4361 case AMDGPU::V_MAC_LEGACY_F32_e64:
4362 return AMDGPU::V_MAD_LEGACY_F32_e64;
4363 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4364 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4365 return AMDGPU::V_FMA_LEGACY_F32_e64;
4366 case AMDGPU::V_FMAC_F16_e32:
4367 case AMDGPU::V_FMAC_F16_e64:
4368 case AMDGPU::V_FMAC_F16_t16_e64:
4369 case AMDGPU::V_FMAC_F16_fake16_e64:
4370 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4371 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4372 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4373 : AMDGPU::V_FMA_F16_gfx9_e64;
4374 case AMDGPU::V_FMAC_F32_e32:
4375 case AMDGPU::V_FMAC_F32_e64:
4376 return AMDGPU::V_FMA_F32_e64;
4377 case AMDGPU::V_FMAC_F64_e32:
4378 case AMDGPU::V_FMAC_F64_e64:
4379 return AMDGPU::V_FMA_F64_e64;
4380 default:
4381 llvm_unreachable("invalid instruction");
4382 }
4383}
4384
4385/// Helper struct for the implementation of 3-address conversion to communicate
4386/// updates made to instruction operands.
4388 /// Other instruction whose def is no longer used by the converted
4389 /// instruction.
4391};
4392
4394 LiveVariables *LV,
4395 LiveIntervals *LIS) const {
4396 MachineBasicBlock &MBB = *MI.getParent();
4397 MachineInstr *CandidateMI = &MI;
4398
4399 if (MI.isBundle()) {
4400 // This is a temporary placeholder for bundle handling that enables us to
4401 // exercise the relevant code paths in the two-address instruction pass.
4402 if (MI.getBundleSize() != 1)
4403 return nullptr;
4404 CandidateMI = MI.getNextNode();
4405 }
4406
4408 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4409 if (!NewMI)
4410 return nullptr;
4411
4412 if (MI.isBundle()) {
4413 CandidateMI->eraseFromBundle();
4414
4415 for (MachineOperand &MO : MI.all_defs()) {
4416 if (MO.isTied())
4417 MI.untieRegOperand(MO.getOperandNo());
4418 }
4419 } else {
4420 updateLiveVariables(LV, MI, *NewMI);
4421 if (LIS) {
4422 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
4423 // SlotIndex of defs needs to be updated when converting to early-clobber
4424 MachineOperand &Def = NewMI->getOperand(0);
4425 if (Def.isEarlyClobber() && Def.isReg() &&
4426 LIS->hasInterval(Def.getReg())) {
4427 SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
4428 SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
4429 auto &LI = LIS->getInterval(Def.getReg());
4430 auto UpdateDefIndex = [&](LiveRange &LR) {
4431 auto *S = LR.find(OldIndex);
4432 if (S != LR.end() && S->start == OldIndex) {
4433 assert(S->valno && S->valno->def == OldIndex);
4434 S->start = NewIndex;
4435 S->valno->def = NewIndex;
4436 }
4437 };
4438 UpdateDefIndex(LI);
4439 for (auto &SR : LI.subranges())
4440 UpdateDefIndex(SR);
4441 }
4442 }
4443 }
4444
4445 if (U.RemoveMIUse) {
4446 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4447 // The only user is the instruction which will be killed.
4448 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4449
4450 if (MRI.hasOneNonDBGUse(DefReg)) {
4451 // We cannot just remove the DefMI here, calling pass will crash.
4452 U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
4453 U.RemoveMIUse->getOperand(0).setIsDead(true);
4454 for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
4455 U.RemoveMIUse->removeOperand(I);
4456 if (LV)
4457 LV->getVarInfo(DefReg).AliveBlocks.clear();
4458 }
4459
4460 if (MI.isBundle()) {
4461 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4462 if (!VRI.Reads && !VRI.Writes) {
4463 for (MachineOperand &MO : MI.all_uses()) {
4464 if (MO.isReg() && MO.getReg() == DefReg) {
4465 assert(MO.getSubReg() == 0 &&
4466 "tied sub-registers in bundles currently not supported");
4467 MI.removeOperand(MO.getOperandNo());
4468 break;
4469 }
4470 }
4471
4472 if (LIS)
4473 LIS->shrinkToUses(&LIS->getInterval(DefReg));
4474 }
4475 } else if (LIS) {
4476 LiveInterval &DefLI = LIS->getInterval(DefReg);
4477
4478 // We cannot delete the original instruction here, so hack out the use
4479 // in the original instruction with a dummy register so we can use
4480 // shrinkToUses to deal with any multi-use edge cases. Other targets do
4481 // not have the complexity of deleting a use to consider here.
4482 Register DummyReg = MRI.cloneVirtualRegister(DefReg);
4483 for (MachineOperand &MIOp : MI.uses()) {
4484 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4485 MIOp.setIsUndef(true);
4486 MIOp.setReg(DummyReg);
4487 }
4488 }
4489
4490 if (MI.isBundle()) {
4491 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4492 if (!VRI.Reads && !VRI.Writes) {
4493 for (MachineOperand &MIOp : MI.uses()) {
4494 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4495 MIOp.setIsUndef(true);
4496 MIOp.setReg(DummyReg);
4497 }
4498 }
4499 }
4500
4501 MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
4502 false, /*isUndef=*/true));
4503 }
4504
4505 LIS->shrinkToUses(&DefLI);
4506 }
4507 }
4508
4509 return MI.isBundle() ? &MI : NewMI;
4510}
4511
4513SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
4514 ThreeAddressUpdates &U) const {
4515 MachineBasicBlock &MBB = *MI.getParent();
4516 unsigned Opc = MI.getOpcode();
4517
4518 // Handle MFMA.
4519 int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
4520 if (NewMFMAOpc != -1) {
4522 BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
4523 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4524 MIB.add(MI.getOperand(I));
4525 return MIB;
4526 }
4527
4528 if (SIInstrInfo::isWMMA(MI)) {
4529 unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
4530 MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4531 .setMIFlags(MI.getFlags());
4532 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4533 MIB->addOperand(MI.getOperand(I));
4534 return MIB;
4535 }
4536
4537 assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4538 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4539 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4540 "present pre-RA");
4541
4542 // Handle MAC/FMAC.
4543 bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
4544 bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4545 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4546 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4547 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4548 bool Src0Literal = false;
4549
4550 switch (Opc) {
4551 default:
4552 return nullptr;
4553 case AMDGPU::V_MAC_F16_e64:
4554 case AMDGPU::V_FMAC_F16_e64:
4555 case AMDGPU::V_FMAC_F16_t16_e64:
4556 case AMDGPU::V_FMAC_F16_fake16_e64:
4557 case AMDGPU::V_MAC_F32_e64:
4558 case AMDGPU::V_MAC_LEGACY_F32_e64:
4559 case AMDGPU::V_FMAC_F32_e64:
4560 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4561 case AMDGPU::V_FMAC_F64_e64:
4562 break;
4563 case AMDGPU::V_MAC_F16_e32:
4564 case AMDGPU::V_FMAC_F16_e32:
4565 case AMDGPU::V_MAC_F32_e32:
4566 case AMDGPU::V_MAC_LEGACY_F32_e32:
4567 case AMDGPU::V_FMAC_F32_e32:
4568 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4569 case AMDGPU::V_FMAC_F64_e32: {
4570 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
4571 AMDGPU::OpName::src0);
4572 const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
4573 if (!Src0->isReg() && !Src0->isImm())
4574 return nullptr;
4575
4576 if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
4577 Src0Literal = true;
4578
4579 break;
4580 }
4581 }
4582
4583 MachineInstrBuilder MIB;
4584 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
4585 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
4586 const MachineOperand *Src0Mods =
4587 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
4588 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4589 const MachineOperand *Src1Mods =
4590 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
4591 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4592 const MachineOperand *Src2Mods =
4593 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
4594 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
4595 const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
4596 const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);
4597
4598 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4599 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4600 // If we have an SGPR input, we will violate the constant bus restriction.
4601 (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
4602 !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
4603 MachineInstr *DefMI = nullptr;
4604 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4605 std::optional<int64_t> ImmOpt;
4606 int64_t Imm;
4607
4608 if (!Src0Literal &&
4609 (ImmOpt = getImmOrMaterializedImm(MRI, *Src2, &DefMI))) {
4610 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4611 if (pseudoToMCOpcode(NewOpc) != -1) {
4612 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4613 .add(*Dst)
4614 .add(*Src0)
4615 .add(*Src1)
4616 .addImm(*ImmOpt)
4617 .setMIFlags(MI.getFlags());
4618 U.RemoveMIUse = DefMI;
4619 return MIB;
4620 }
4621 }
4622 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4623 if (!Src0Literal &&
4624 (ImmOpt = getImmOrMaterializedImm(MRI, *Src1, &DefMI))) {
4625 if (pseudoToMCOpcode(NewOpc) != -1) {
4626 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4627 .add(*Dst)
4628 .add(*Src0)
4629 .addImm(*ImmOpt)
4630 .add(*Src2)
4631 .setMIFlags(MI.getFlags());
4632 U.RemoveMIUse = DefMI;
4633 return MIB;
4634 }
4635 }
4636 if ((ImmOpt = getImmOrMaterializedImm(MRI, *Src0, &DefMI))) {
4637 Imm = *ImmOpt;
4638 if (pseudoToMCOpcode(NewOpc) != -1 &&
4640 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4641 Src1)) {
4642 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4643 .add(*Dst)
4644 .add(*Src1)
4645 .addImm(Imm)
4646 .add(*Src2)
4647 .setMIFlags(MI.getFlags());
4648 U.RemoveMIUse = DefMI;
4649 return MIB;
4650 }
4651 }
4652 }
4653
4654 // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
4655 // if VOP3 does not allow a literal operand.
4656 if (Src0Literal && !ST.hasVOP3Literal())
4657 return nullptr;
4658
4659 unsigned NewOpc = getNewFMAInst(ST, Opc);
4660
4661 if (pseudoToMCOpcode(NewOpc) == -1)
4662 return nullptr;
4663
4664 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4665 .add(*Dst)
4666 .addImm(Src0Mods ? Src0Mods->getImm() : 0)
4667 .add(*Src0)
4668 .addImm(Src1Mods ? Src1Mods->getImm() : 0)
4669 .add(*Src1)
4670 .addImm(Src2Mods ? Src2Mods->getImm() : 0)
4671 .add(*Src2)
4672 .addImm(Clamp ? Clamp->getImm() : 0)
4673 .addImm(Omod ? Omod->getImm() : 0)
4674 .setMIFlags(MI.getFlags());
4675 if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
4676 MIB.addImm(OpSel ? OpSel->getImm() : 0);
4677 return MIB;
4678}
4679
4680// It's not generally safe to move VALU instructions across these since it will
4681// start using the register as a base index rather than directly.
4682// XXX - Why isn't hasSideEffects sufficient for these?
4684 switch (MI.getOpcode()) {
4685 case AMDGPU::S_SET_GPR_IDX_ON:
4686 case AMDGPU::S_SET_GPR_IDX_MODE:
4687 case AMDGPU::S_SET_GPR_IDX_OFF:
4688 return true;
4689 default:
4690 return false;
4691 }
4692}
4693
4695 const MachineBasicBlock *MBB,
4696 const MachineFunction &MF) const {
4697 // Skipping the check for SP writes in the base implementation. The reason it
4698 // was added was apparently due to compile time concerns.
4699 //
4700 // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
4701 // but is probably avoidable.
4702
4703 // Copied from base implementation.
4704 // Terminators and labels can't be scheduled around.
4705 if (MI.isTerminator() || MI.isPosition())
4706 return true;
4707
4708 // INLINEASM_BR can jump to another block
4709 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4710 return true;
4711
4712 if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
4713 return true;
4714
4715 // Target-independent instructions do not have an implicit-use of EXEC, even
4716 // when they operate on VGPRs. Treating EXEC modifications as scheduling
4717 // boundaries prevents incorrect movements of such instructions.
4718 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4719 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4720 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4721 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4722 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4724}
4725
4727 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4728 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4729 Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
4730}
4731
4733 // Instructions that access scratch use FLAT encoding or BUF encodings.
4734 if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
4735 return false;
4736
4737 // SCRATCH instructions always access scratch.
4738 if (isFLATScratch(MI))
4739 return true;
4740
4741 // If FLAT_SCRATCH registers are not initialized, we can never access scratch
4742 // via the aperture.
4743 if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
4744 return false;
4745
4746 // If there are no memory operands then conservatively assume the flat
4747 // operation may access scratch.
4748 if (MI.memoperands_empty())
4749 return true;
4750
4751 // See if any memory operand specifies an address space that involves scratch.
4752 return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
4753 unsigned AS = Memop->getAddrSpace();
4754 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4755 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4756 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4757 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4758 }
4759 return AS == AMDGPUAS::PRIVATE_ADDRESS;
4760 });
4761}
4762
4764 assert(isFLAT(MI));
4765
4766 // All flat instructions use the VMEM counter except prefetch.
4767 if (!usesVM_CNT(MI))
4768 return false;
4769
4770 // If there are no memory operands then conservatively assume the flat
4771 // operation may access VMEM.
4772 if (MI.memoperands_empty())
4773 return true;
4774
4775 // See if any memory operand specifies an address space that involves VMEM.
4776 // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
4777 // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
4778 // (GDS) address space is not supported by flat operations. Therefore, simply
4779 // return true unless only the LDS address space is found.
4780 for (const MachineMemOperand *Memop : MI.memoperands()) {
4781 unsigned AS = Memop->getAddrSpace();
4783 if (AS != AMDGPUAS::LOCAL_ADDRESS)
4784 return true;
4785 }
4786
4787 return false;
4788}
4789
4791 bool TgSplit) const {
4792 assert(isFLAT(MI));
4793
4794 // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
4795 if (!usesLGKM_CNT(MI))
4796 return false;
4797
4798 // If in tgsplit mode then there can be no use of LDS.
4799 if (TgSplit)
4800 return false;
4801
4802 // If there are no memory operands then conservatively assume the flat
4803 // operation may access LDS.
4804 if (MI.memoperands_empty())
4805 return true;
4806
4807 // See if any memory operand specifies an address space that involves LDS.
4808 for (const MachineMemOperand *Memop : MI.memoperands()) {
4809 unsigned AS = Memop->getAddrSpace();
4811 return true;
4812 }
4813
4814 return false;
4815}
4816
4818 // Skip the full operand and register alias search modifiesRegister
4819 // does. There's only a handful of instructions that touch this, it's only an
4820 // implicit def, and doesn't alias any other registers.
4821 return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
4822}
4823
4825 unsigned Opcode = MI.getOpcode();
4826
4827 if (MI.mayStore() && isSMRD(MI))
4828 return true; // scalar store or atomic
4829
4830 // This will terminate the function when other lanes may need to continue.
4831 if (MI.isReturn())
4832 return true;
4833
4834 // These instructions cause shader I/O that may cause hardware lockups
4835 // when executed with an empty EXEC mask.
4836 //
4837 // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
4838 // EXEC = 0, but checking for that case here seems not worth it
4839 // given the typical code patterns.
4840 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4841 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4842 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4843 Opcode == AMDGPU::S_SETHALT)
4844 return true;
4845
4846 if (MI.isCall() || MI.isInlineAsm())
4847 return true; // conservative assumption
4848
4849 // Assume that barrier interactions are only intended with active lanes.
4850 if (isBarrier(Opcode))
4851 return true;
4852
4853 // A mode change is a scalar operation that influences vector instructions.
4855 return true;
4856
4857 // These are like SALU instructions in terms of effects, so it's questionable
4858 // whether we should return true for those.
4859 //
4860 // However, executing them with EXEC = 0 causes them to operate on undefined
4861 // data, which we avoid by returning true here.
4862 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4863 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4864 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4865 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4866 return true;
4867
4868 return false;
4869}
4870
4872 const MachineInstr &MI) const {
4873 if (MI.isMetaInstruction())
4874 return false;
4875
4876 // This won't read exec if this is an SGPR->SGPR copy.
4877 if (MI.isCopyLike()) {
4878 if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
4879 return true;
4880
4881 // Make sure this isn't copying exec as a normal operand
4882 return MI.readsRegister(AMDGPU::EXEC, &RI);
4883 }
4884
4885 // Make a conservative assumption about the callee.
4886 if (MI.isCall())
4887 return true;
4888
4889 // Be conservative with any unhandled generic opcodes.
4890 if (!isTargetSpecificOpcode(MI.getOpcode()))
4891 return true;
4892
4893 return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
4894}
4895
4897 switch (Imm.getBitWidth()) {
4898 case 1: // This likely will be a condition code mask.
4899 return true;
4900
4901 case 32:
4902 return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
4903 ST.hasInv2PiInlineImm());
4904 case 64:
4905 return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
4906 ST.hasInv2PiInlineImm());
4907 case 16:
4908 return ST.has16BitInsts() &&
4909 AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
4910 ST.hasInv2PiInlineImm());
4911 default:
4912 llvm_unreachable("invalid bitwidth");
4913 }
4914}
4915
4917 APInt IntImm = Imm.bitcastToAPInt();
4918 int64_t IntImmVal = IntImm.getSExtValue();
4919 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4920 switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
4921 default:
4922 llvm_unreachable("invalid fltSemantics");
4925 return isInlineConstant(IntImm);
4927 return ST.has16BitInsts() &&
4928 AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
4930 return ST.has16BitInsts() &&
4931 AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
4932 }
4933}
4934
4935bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
4936 // MachineOperand provides no way to tell the true operand size, since it only
4937 // records a 64-bit value. We need to know the size to determine if a 32-bit
4938 // floating point immediate bit pattern is legal for an integer immediate. It
4939 // would be for any 32-bit integer operand, but would not be for a 64-bit one.
4940 switch (OperandType) {
4950 int32_t Trunc = static_cast<int32_t>(Imm);
4951 return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
4952 }
4960 return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
4963 // We would expect inline immediates to not be concerned with an integer/fp
4964 // distinction. However, in the case of 16-bit integer operations, the
4965 // "floating point" values appear to not work. It seems read the low 16-bits
4966 // of 32-bit immediates, which happens to always work for the integer
4967 // values.
4968 //
4969 // See llvm bugzilla 46302.
4970 //
4971 // TODO: Theoretically we could use op-sel to use the high bits of the
4972 // 32-bit FP values.
4981 return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
4986 return false;
4989 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
4990 // A few special case instructions have 16-bit operands on subtargets
4991 // where 16-bit instructions are not legal.
4992 // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
4993 // constants in these cases
4994 int16_t Trunc = static_cast<int16_t>(Imm);
4995 return ST.has16BitInsts() &&
4996 AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
4997 }
4998
4999 return false;
5000 }
5003 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
5004 int16_t Trunc = static_cast<int16_t>(Imm);
5005 return ST.has16BitInsts() &&
5006 AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
5007 }
5008 return false;
5009 }
5014 return false;
5016 return isLegalAV64PseudoImm(Imm);
5019 // Always embedded in the instruction for free.
5020 return true;
5030 // Just ignore anything else.
5031 return false;
5032 default:
5033 llvm_unreachable("invalid operand type");
5034 }
5035}
5036
5037static bool compareMachineOp(const MachineOperand &Op0,
5038 const MachineOperand &Op1) {
5039 if (Op0.getType() != Op1.getType())
5040 return false;
5041
5042 switch (Op0.getType()) {
5044 return Op0.getReg() == Op1.getReg();
5046 return Op0.getImm() == Op1.getImm();
5047 default:
5048 llvm_unreachable("Didn't expect to be comparing these operand types");
5049 }
5050}
5051
5053 const MCOperandInfo &OpInfo) const {
5054 if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
5055 return true;
5056
5057 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5058 return false;
5059
5060 if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
5061 return true;
5062
5063 return ST.hasVOP3Literal();
5064}
5065
5066bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5067 int64_t ImmVal) const {
5068 const unsigned Opc = InstDesc.getOpcode();
5069 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
5070 if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
5071 OpNo == static_cast<unsigned>(Src1Idx))
5072 return false;
5073
5074 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5075 if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
5076 if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5077 OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
5078 AMDGPU::OpName::src2))
5079 return false;
5080
5081 if (ST.hasBF16InlineConstFromUpperFP32() && isVOP1(Opc)) {
5082 if ((OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_BF16 ||
5083 OpInfo.OperandType == AMDGPU::OPERAND_REG_INLINE_C_BF16) &&
5084 isInlineConstant(ImmVal, OpInfo.OperandType))
5085 return false;
5086 }
5087
5088 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5089 }
5090
5091 return isLiteralOperandLegal(InstDesc, OpInfo);
5092}
5093
5094bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5095 const MachineOperand &MO) const {
5096 if (MO.isImm())
5097 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
5098
5099 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
5100 "unexpected imm-like operand kind");
5101 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5102 return isLiteralOperandLegal(InstDesc, OpInfo);
5103}
5104
5106 // 2 32-bit inline constants packed into one.
5107 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
5108 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
5109}
5110
5111bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
5112 // GFX90A does not have V_MUL_LEGACY_F32_e32.
5113 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5114 return false;
5115
5116 int Op32 = AMDGPU::getVOPe32(Opcode);
5117 if (Op32 == -1)
5118 return false;
5119
5120 return pseudoToMCOpcode(Op32) != -1;
5121}
5122
5123bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
5124 // The src0_modifier operand is present on all instructions
5125 // that have modifiers.
5126
5127 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
5128}
5129
5131 AMDGPU::OpName OpName) const {
5132 const MachineOperand *Mods = getNamedOperand(MI, OpName);
5133 return Mods && Mods->getImm();
5134}
5135
5137 return any_of(ModifierOpNames,
5138 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
5139}
5140
5142 const MachineRegisterInfo &MRI) const {
5143 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5144 // Can't shrink instruction with three operands.
5145 if (Src2) {
5146 switch (MI.getOpcode()) {
5147 default: return false;
5148
5149 case AMDGPU::V_ADDC_U32_e64:
5150 case AMDGPU::V_SUBB_U32_e64:
5151 case AMDGPU::V_SUBBREV_U32_e64: {
5152 const MachineOperand *Src1
5153 = getNamedOperand(MI, AMDGPU::OpName::src1);
5154 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
5155 return false;
5156 // Additional verification is needed for sdst/src2.
5157 return true;
5158 }
5159 case AMDGPU::V_MAC_F16_e64:
5160 case AMDGPU::V_MAC_F32_e64:
5161 case AMDGPU::V_MAC_LEGACY_F32_e64:
5162 case AMDGPU::V_FMAC_F16_e64:
5163 case AMDGPU::V_FMAC_F16_t16_e64:
5164 case AMDGPU::V_FMAC_F16_fake16_e64:
5165 case AMDGPU::V_FMAC_F32_e64:
5166 case AMDGPU::V_FMAC_F64_e64:
5167 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5168 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
5169 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
5170 return false;
5171 break;
5172
5173 case AMDGPU::V_CNDMASK_B32_e64:
5174 break;
5175 }
5176 }
5177
5178 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
5179 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5180 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
5181 return false;
5182
5183 // Make sure src0 isn't using any modifiers.
5184 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
5185 return false;
5186
5187 // Can it be shrunk to a valid 32 bit opcode?
5188 if (!hasVALU32BitEncoding(MI.getOpcode()))
5189 return false;
5190
5191 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
5192 if (Src0 && Src0->isImm()) {
5193 unsigned Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5194 if (!isImmOperandLegal(
5195 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5196 *Src0))
5197 return false;
5198 }
5199
5200 // Check output modifiers
5201 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
5202 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
5203 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
5204 // TODO: Can we avoid checking bound_ctrl/fi here?
5205 // They are only used by permlane*_swap special case.
5206 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
5207 !hasModifiersSet(MI, AMDGPU::OpName::fi);
5208}
5209
5210// Set VCC operand with all flags from \p Orig, except for setting it as
5211// implicit.
5213 const MachineOperand &Orig) {
5214
5215 for (MachineOperand &Use : MI.implicit_operands()) {
5216 if (Use.isUse() &&
5217 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
5218 Use.setIsUndef(Orig.isUndef());
5219 Use.setIsKill(Orig.isKill());
5220 return;
5221 }
5222 }
5223}
5224
5226 unsigned Op32) const {
5227 MachineBasicBlock *MBB = MI.getParent();
5228
5229 const MCInstrDesc &Op32Desc = get(Op32);
5230 MachineInstrBuilder Inst32 =
5231 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
5232 .setMIFlags(MI.getFlags());
5233
5234 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
5235 // For VOPC instructions, this is replaced by an implicit def of vcc.
5236
5237 // We assume the defs of the shrunk opcode are in the same order, and the
5238 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
5239 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
5240 Inst32.add(MI.getOperand(I));
5241
5242 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5243
5244 int Idx = MI.getNumExplicitDefs();
5245 for (const MachineOperand &Use : MI.explicit_uses()) {
5246 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
5248 continue;
5249
5250 if (&Use == Src2) {
5251 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5252 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
5253 // replaced with an implicit read of vcc or vcc_lo. The implicit read
5254 // of vcc was already added during the initial BuildMI, but we
5255 // 1) may need to change vcc to vcc_lo to preserve the original register
5256 // 2) have to preserve the original flags.
5257 copyFlagsToImplicitVCC(*Inst32, *Src2);
5258 continue;
5259 }
5260 }
5261
5262 Inst32.add(Use);
5263 }
5264
5265 // FIXME: Losing implicit operands
5266 fixImplicitOperands(*Inst32);
5267 return Inst32;
5268}
5269
5271 // Null is free
5272 Register Reg = RegOp.getReg();
5273 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5274 return false;
5275
5276 // SGPRs use the constant bus
5277
5278 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
5279 // physical register operands should also count, except for exec.
5280 if (RegOp.isImplicit())
5281 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5282
5283 // SGPRs use the constant bus
5284 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5285 AMDGPU::SReg_64RegClass.contains(Reg);
5286}
5287
5289 const MachineRegisterInfo &MRI) const {
5290 Register Reg = RegOp.getReg();
5291 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5292 : physRegUsesConstantBus(RegOp);
5293}
5294
5296 const MachineOperand &MO,
5297 const MCOperandInfo &OpInfo) const {
5298 // Literal constants use the constant bus.
5299 if (!MO.isReg())
5300 return !isInlineConstant(MO, OpInfo);
5301
5302 Register Reg = MO.getReg();
5303 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5305}
5306
5308 for (const MachineOperand &MO : MI.implicit_operands()) {
5309 // We only care about reads.
5310 if (MO.isDef())
5311 continue;
5312
5313 switch (MO.getReg()) {
5314 case AMDGPU::VCC:
5315 case AMDGPU::VCC_LO:
5316 case AMDGPU::VCC_HI:
5317 case AMDGPU::M0:
5318 case AMDGPU::FLAT_SCR:
5319 return MO.getReg();
5320
5321 default:
5322 break;
5323 }
5324 }
5325
5326 return Register();
5327}
5328
5329static bool shouldReadExec(const MachineInstr &MI) {
5330 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5331 switch (MI.getOpcode()) {
5332 case AMDGPU::V_READLANE_B32:
5333 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5334 case AMDGPU::V_WRITELANE_B32:
5335 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5336 return false;
5337 }
5338
5339 return true;
5340 }
5341
5342 if (MI.isPreISelOpcode() ||
5343 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5346 return false;
5347
5348 return true;
5349}
5350
5351static bool isRegOrFI(const MachineOperand &MO) {
5352 return MO.isReg() || MO.isFI();
5353}
5354
5355static bool isSubRegOf(const SIRegisterInfo &TRI,
5356 const MachineOperand &SuperVec,
5357 const MachineOperand &SubReg) {
5358 if (SubReg.getReg().isPhysical())
5359 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5360
5361 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5362 SubReg.getReg() == SuperVec.getReg();
5363}
5364
5365// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5366bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5367 const MachineRegisterInfo &MRI,
5368 StringRef &ErrInfo) const {
5369 Register DstReg = MI.getOperand(0).getReg();
5370 Register SrcReg = MI.getOperand(1).getReg();
5371 // This is a check for copy from vector register to SGPR
5372 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5373 ErrInfo = "illegal copy from vector register to SGPR";
5374 return false;
5375 }
5376 return true;
5377}
5378
5380 StringRef &ErrInfo) const {
5381 uint32_t Opcode = MI.getOpcode();
5382 const MachineFunction *MF = MI.getMF();
5383 const MachineRegisterInfo &MRI = MF->getRegInfo();
5384
5385 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5386 // Find a better property to recognize the point where instruction selection
5387 // is just done.
5388 // We can only enforce this check after SIFixSGPRCopies pass so that the
5389 // illegal copies are legalized and thereafter we don't expect a pass
5390 // inserting similar copies.
5391 if (!MRI.isSSA() && MI.isCopy())
5392 return verifyCopy(MI, MRI, ErrInfo);
5393
5394 if (SIInstrInfo::isGenericOpcode(Opcode))
5395 return true;
5396
5397 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5398 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5399 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5400 int Src3Idx = -1;
5401 if (Src0Idx == -1) {
5402 // VOPD V_DUAL_* instructions use different operand names.
5403 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5404 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5405 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5406 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5407 }
5408
5409 // Make sure the number of operands is correct.
5410 const MCInstrDesc &Desc = get(Opcode);
5411 if (!Desc.isVariadic() &&
5412 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5413 ErrInfo = "Instruction has wrong number of operands.";
5414 return false;
5415 }
5416
5417 if (MI.isInlineAsm()) {
5418 // Verify register classes for inlineasm constraints.
5419 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5420 I != E; ++I) {
5421 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5422 if (!RC)
5423 continue;
5424
5425 const MachineOperand &Op = MI.getOperand(I);
5426 if (!Op.isReg())
5427 continue;
5428
5429 Register Reg = Op.getReg();
5430 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5431 ErrInfo = "inlineasm operand has incorrect register class.";
5432 return false;
5433 }
5434 }
5435
5436 return true;
5437 }
5438
5439 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5440 ErrInfo = "missing memory operand from image instruction.";
5441 return false;
5442 }
5443
5444 // Make sure the register classes are correct.
5445 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5446 const MachineOperand &MO = MI.getOperand(i);
5447 if (MO.isFPImm()) {
5448 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5449 "all fp values to integers.";
5450 return false;
5451 }
5452
5453 const MCOperandInfo &OpInfo = Desc.operands()[i];
5454
5455 switch (OpInfo.OperandType) {
5457 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5458 ErrInfo = "Illegal immediate value for operand.";
5459 return false;
5460 }
5461 break;
5475 break;
5489 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5490 ErrInfo = "Illegal immediate value for operand.";
5491 return false;
5492 }
5493 break;
5494 }
5499 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5500 !isInlineConstant(MI, i) &&
5502 OpInfo.OperandType ==
5504 ErrInfo = "illegal 64-bit immediate value for operand.";
5505 return false;
5506 }
5507 break;
5510 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5511 ErrInfo = "Expected inline constant for operand.";
5512 return false;
5513 }
5514 break;
5517 break;
5522 // Check if this operand is an immediate.
5523 // FrameIndex operands will be replaced by immediates, so they are
5524 // allowed.
5525 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5526 ErrInfo = "Expected immediate, but got non-immediate";
5527 return false;
5528 }
5529 break;
5533 break;
5534 default:
5535 if (OpInfo.isGenericType())
5536 continue;
5537 break;
5538 }
5539 }
5540
5541 // Verify SDWA
5542 if (isSDWA(MI)) {
5543 if (!ST.hasSDWA()) {
5544 ErrInfo = "SDWA is not supported on this target";
5545 return false;
5546 }
5547
5548 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5549 AMDGPU::OpName::dst_sel}) {
5550 const MachineOperand *MO = getNamedOperand(MI, Op);
5551 if (!MO)
5552 continue;
5553 int64_t Imm = MO->getImm();
5555 ErrInfo = "Invalid SDWA selection";
5556 return false;
5557 }
5558 }
5559
5560 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5561
5562 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5563 if (OpIdx == -1)
5564 continue;
5565 const MachineOperand &MO = MI.getOperand(OpIdx);
5566
5567 if (!ST.hasSDWAScalar()) {
5568 // Only VGPRS on VI
5569 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5570 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5571 return false;
5572 }
5573 } else {
5574 // No immediates on GFX9
5575 if (!MO.isReg()) {
5576 ErrInfo =
5577 "Only reg allowed as operands in SDWA instructions on GFX9+";
5578 return false;
5579 }
5580 }
5581 }
5582
5583 if (!ST.hasSDWAOmod()) {
5584 // No omod allowed on VI
5585 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5586 if (OMod != nullptr &&
5587 (!OMod->isImm() || OMod->getImm() != 0)) {
5588 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5589 return false;
5590 }
5591 }
5592
5593 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5594 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5595 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5596 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5597 const MachineOperand *Src0ModsMO =
5598 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5599 unsigned Mods = Src0ModsMO->getImm();
5600 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5601 Mods & SISrcMods::SEXT) {
5602 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5603 return false;
5604 }
5605 }
5606
5607 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5608 if (isVOPC(BasicOpcode)) {
5609 if (!ST.hasSDWASdst() && DstIdx != -1) {
5610 // Only vcc allowed as dst on VI for VOPC
5611 const MachineOperand &Dst = MI.getOperand(DstIdx);
5612 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5613 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5614 return false;
5615 }
5616 } else if (!ST.hasSDWAOutModsVOPC()) {
5617 // No clamp allowed on GFX9 for VOPC
5618 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5619 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5620 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5621 return false;
5622 }
5623
5624 // No omod allowed on GFX9 for VOPC
5625 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5626 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5627 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5628 return false;
5629 }
5630 }
5631 }
5632
5633 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5634 if (DstUnused && DstUnused->isImm() &&
5635 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5636 const MachineOperand &Dst = MI.getOperand(DstIdx);
5637 if (!Dst.isReg() || !Dst.isTied()) {
5638 ErrInfo = "Dst register should have tied register";
5639 return false;
5640 }
5641
5642 const MachineOperand &TiedMO =
5643 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5644 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5645 ErrInfo =
5646 "Dst register should be tied to implicit use of preserved register";
5647 return false;
5648 }
5649 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5650 ErrInfo = "Dst register should use same physical register as preserved";
5651 return false;
5652 }
5653 }
5654 }
5655
5656 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5657 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5658 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5659 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5660 return false;
5661 }
5662 if (Src1MO.isImm()) {
5663 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5664 return false;
5665 }
5666 }
5667
5668 // Verify MIMG / VIMAGE / VSAMPLE
5669 if (isImage(Opcode) && !MI.mayStore()) {
5670 // Ensure that the return type used is large enough for all the options
5671 // being used TFE/LWE require an extra result register.
5672 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5673 if (DMask) {
5674 uint64_t DMaskImm = DMask->getImm();
5675 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5676 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5677 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5678 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5679
5680 // Adjust for packed 16 bit values
5681 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5682 RegCount = divideCeil(RegCount, 2);
5683
5684 // Adjust if using LWE or TFE
5685 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5686 RegCount += 1;
5687
5688 const uint32_t DstIdx =
5689 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5690 const MachineOperand &Dst = MI.getOperand(DstIdx);
5691 if (Dst.isReg()) {
5692 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5693 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5694 if (RegCount > DstSize) {
5695 ErrInfo = "Image instruction returns too many registers for dst "
5696 "register class";
5697 return false;
5698 }
5699 }
5700 }
5701 }
5702
5703 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5704 if (isVALU(MI, /*AllowLDSDMA=*/false) &&
5705 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5706 unsigned ConstantBusCount = 0;
5707 bool UsesLiteral = false;
5708 const MachineOperand *LiteralVal = nullptr;
5709
5710 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5711 if (ImmIdx != -1) {
5712 ++ConstantBusCount;
5713 UsesLiteral = true;
5714 LiteralVal = &MI.getOperand(ImmIdx);
5715 }
5716
5717 SmallVector<Register, 2> SGPRsUsed;
5718 Register SGPRUsed;
5719
5720 // Only look at the true operands. Only a real operand can use the constant
5721 // bus, and we don't want to check pseudo-operands like the source modifier
5722 // flags.
5723 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5724 if (OpIdx == -1)
5725 continue;
5726 const MachineOperand &MO = MI.getOperand(OpIdx);
5727 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5728 if (MO.isReg()) {
5729 SGPRUsed = MO.getReg();
5730 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5731 ++ConstantBusCount;
5732 SGPRsUsed.push_back(SGPRUsed);
5733 }
5734 } else if (!MO.isFI()) { // Treat FI like a register.
5735 if (!UsesLiteral) {
5736 ++ConstantBusCount;
5737 UsesLiteral = true;
5738 LiteralVal = &MO;
5739 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5740 assert(isVOP2(MI) || isVOP3(MI));
5741 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5742 return false;
5743 }
5744 }
5745 }
5746 }
5747
5748 SGPRUsed = findImplicitSGPRRead(MI);
5749 if (SGPRUsed) {
5750 // Implicit uses may safely overlap true operands
5751 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5752 return !RI.regsOverlap(SGPRUsed, SGPR);
5753 })) {
5754 ++ConstantBusCount;
5755 SGPRsUsed.push_back(SGPRUsed);
5756 }
5757 }
5758
5759 // v_writelane_b32 is an exception from constant bus restriction:
5760 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5761 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5762 Opcode != AMDGPU::V_WRITELANE_B32) {
5763 ErrInfo = "VOP* instruction violates constant bus restriction";
5764 return false;
5765 }
5766
5767 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5768 ErrInfo = "VOP3 instruction uses literal";
5769 return false;
5770 }
5771 }
5772
5773 // Special case for writelane - this can break the multiple constant bus rule,
5774 // but still can't use more than one SGPR register
5775 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5776 unsigned SGPRCount = 0;
5777 Register SGPRUsed;
5778
5779 for (int OpIdx : {Src0Idx, Src1Idx}) {
5780 if (OpIdx == -1)
5781 break;
5782
5783 const MachineOperand &MO = MI.getOperand(OpIdx);
5784
5785 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5786 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5787 if (MO.getReg() != SGPRUsed)
5788 ++SGPRCount;
5789 SGPRUsed = MO.getReg();
5790 }
5791 }
5792 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5793 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5794 return false;
5795 }
5796 }
5797 }
5798
5799 // Verify misc. restrictions on specific instructions.
5800 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5801 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5802 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5803 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5804 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
5805 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5806 if (!compareMachineOp(Src0, Src1) &&
5807 !compareMachineOp(Src0, Src2)) {
5808 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
5809 return false;
5810 }
5811 }
5812 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
5813 SISrcMods::ABS) ||
5814 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
5815 SISrcMods::ABS) ||
5816 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
5817 SISrcMods::ABS)) {
5818 ErrInfo = "ABS not allowed in VOP3B instructions";
5819 return false;
5820 }
5821 }
5822
5823 if (isSOP2(MI) || isSOPC(MI)) {
5824 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5825 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5826
5827 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
5828 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
5829 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
5830 !Src0.isIdenticalTo(Src1)) {
5831 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
5832 return false;
5833 }
5834 }
5835
5836 if (isSOPK(MI)) {
5837 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
5838 if (Desc.isBranch()) {
5839 if (!Op->isMBB()) {
5840 ErrInfo = "invalid branch target for SOPK instruction";
5841 return false;
5842 }
5843 } else {
5844 uint64_t Imm = Op->getImm();
5845 if (sopkIsZext(Opcode)) {
5846 if (!isUInt<16>(Imm)) {
5847 ErrInfo = "invalid immediate for SOPK instruction";
5848 return false;
5849 }
5850 } else {
5851 if (!isInt<16>(Imm)) {
5852 ErrInfo = "invalid immediate for SOPK instruction";
5853 return false;
5854 }
5855 }
5856 }
5857 }
5858
5859 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5860 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5861 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5862 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5863 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5864 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5865
5866 const unsigned StaticNumOps =
5867 Desc.getNumOperands() + Desc.implicit_uses().size();
5868 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5869
5870 // Require additional implicit operands. This allows a fixup done by the
5871 // post RA scheduler where the main implicit operand is killed and
5872 // implicit-defs are added for sub-registers that remain live after this
5873 // instruction.
5874 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5875 ErrInfo = "missing implicit register operands";
5876 return false;
5877 }
5878
5879 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5880 if (IsDst) {
5881 if (!Dst->isUse()) {
5882 ErrInfo = "v_movreld_b32 vdst should be a use operand";
5883 return false;
5884 }
5885
5886 unsigned UseOpIdx;
5887 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5888 UseOpIdx != StaticNumOps + 1) {
5889 ErrInfo = "movrel implicit operands should be tied";
5890 return false;
5891 }
5892 }
5893
5894 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5895 const MachineOperand &ImpUse
5896 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5897 if (!ImpUse.isReg() || !ImpUse.isUse() ||
5898 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5899 ErrInfo = "src0 should be subreg of implicit vector use";
5900 return false;
5901 }
5902 }
5903
5904 // Make sure we aren't losing exec uses in the td files. This mostly requires
5905 // being careful when using let Uses to try to add other use registers.
5906 if (shouldReadExec(MI)) {
5907 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5908 ErrInfo = "VALU instruction does not implicitly read exec mask";
5909 return false;
5910 }
5911 }
5912
5913 if (isSMRD(MI)) {
5914 if (MI.mayStore() &&
5915 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
5916 // The register offset form of scalar stores may only use m0 as the
5917 // soffset register.
5918 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
5919 if (Soff && Soff->getReg() != AMDGPU::M0) {
5920 ErrInfo = "scalar stores must use m0 as offset register";
5921 return false;
5922 }
5923 }
5924 }
5925
5926 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
5927 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
5928 if (Offset->getImm() != 0) {
5929 ErrInfo = "subtarget does not support offsets in flat instructions";
5930 return false;
5931 }
5932 }
5933
5934 if (isDS(MI) && !ST.hasGDS()) {
5935 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
5936 if (GDSOp && GDSOp->getImm() != 0) {
5937 ErrInfo = "GDS is not supported on this subtarget";
5938 return false;
5939 }
5940 }
5941
5942 if (isImage(MI)) {
5943 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
5944 if (DimOp) {
5945 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5946 AMDGPU::OpName::vaddr0);
5947 AMDGPU::OpName RSrcOpName =
5948 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5949 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5950 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
5951 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
5952 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
5953 const AMDGPU::MIMGDimInfo *Dim =
5955
5956 if (!Dim) {
5957 ErrInfo = "dim is out of range";
5958 return false;
5959 }
5960
5961 bool IsA16 = false;
5962 if (ST.hasR128A16()) {
5963 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
5964 IsA16 = R128A16->getImm() != 0;
5965 } else if (ST.hasA16()) {
5966 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
5967 IsA16 = A16->getImm() != 0;
5968 }
5969
5970 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5971
5972 unsigned AddrWords =
5973 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
5974
5975 unsigned VAddrWords;
5976 if (IsNSA) {
5977 VAddrWords = RsrcIdx - VAddr0Idx;
5978 if (ST.hasPartialNSAEncoding() &&
5979 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
5980 unsigned LastVAddrIdx = RsrcIdx - 1;
5981 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
5982 }
5983 } else {
5984 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
5985 if (AddrWords > 12)
5986 AddrWords = 16;
5987 }
5988
5989 if (VAddrWords != AddrWords) {
5990 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
5991 << " but got " << VAddrWords << "\n");
5992 ErrInfo = "bad vaddr size";
5993 return false;
5994 }
5995 }
5996 }
5997
5998 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
5999 if (DppCt) {
6000 using namespace AMDGPU::DPP;
6001
6002 unsigned DC = DppCt->getImm();
6003 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6004 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6005 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6006 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6007 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6008 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6009 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6010 ErrInfo = "Invalid dpp_ctrl value";
6011 return false;
6012 }
6013 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6014 !ST.hasDPPWavefrontShifts()) {
6015 ErrInfo = "Invalid dpp_ctrl value: "
6016 "wavefront shifts are not supported on GFX10+";
6017 return false;
6018 }
6019 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6020 !ST.hasDPPBroadcasts()) {
6021 ErrInfo = "Invalid dpp_ctrl value: "
6022 "broadcasts are not supported on GFX10+";
6023 return false;
6024 }
6025 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6026 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
6027 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6028 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6029 !ST.hasGFX90AInsts()) {
6030 ErrInfo = "Invalid dpp_ctrl value: "
6031 "row_newbroadcast/row_share is not supported before "
6032 "GFX90A/GFX10";
6033 return false;
6034 }
6035 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6036 ErrInfo = "Invalid dpp_ctrl value: "
6037 "row_share and row_xmask are not supported before GFX10";
6038 return false;
6039 }
6040 }
6041
6042 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6044 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
6045 ErrInfo = "Invalid dpp_ctrl value: "
6046 "DP ALU dpp only support row_newbcast";
6047 return false;
6048 }
6049 }
6050
6051 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
6052 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
6053 AMDGPU::OpName DataName =
6054 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6055 const MachineOperand *Data = getNamedOperand(MI, DataName);
6056 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
6057 if (Data && !Data->isReg())
6058 Data = nullptr;
6059
6060 if (!ST.hasGFX90AInsts()) {
6061 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6062 (Data && RI.isAGPR(MRI, Data->getReg())) ||
6063 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
6064 ErrInfo = "Invalid register class: "
6065 "agpr loads and stores not supported on this GPU";
6066 return false;
6067 }
6068 }
6069 }
6070
6071 if (ST.needsAlignedVGPRs()) {
6072 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
6074 if (!Op)
6075 return true;
6076 Register Reg = Op->getReg();
6077 if (Reg.isPhysical())
6078 return !(RI.getHWRegIndex(Reg) & 1);
6079 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
6080 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6081 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
6082 };
6083
6084 if (isMIMG(MI)) {
6085 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6086 ErrInfo = "Subtarget requires even aligned vector registers "
6087 "for vaddr operand of image instructions";
6088 return false;
6089 }
6090 }
6091 }
6092
6093 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6094 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
6095 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6096 ErrInfo = "Invalid register class: "
6097 "v_accvgpr_write with an SGPR is not supported on this GPU";
6098 return false;
6099 }
6100 }
6101
6102 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6103 const MachineOperand &SrcOp = MI.getOperand(1);
6104 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
6105 ErrInfo = "pseudo expects only physical SGPRs";
6106 return false;
6107 }
6108 }
6109
6110 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
6111 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
6112 if (!ST.hasScaleOffset()) {
6113 ErrInfo = "Subtarget does not support offset scaling";
6114 return false;
6115 }
6116 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
6117 ErrInfo = "Instruction does not support offset scaling";
6118 return false;
6119 }
6120 }
6121 }
6122
6123 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6124 if (AMDGPU::isSingleSGPRReadInst(Opcode)) {
6125 for (unsigned I = 0; I < 3; ++I) {
6127 return false;
6128 }
6129 }
6130
6131 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
6132 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
6133 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
6134 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6135 &AMDGPU::SReg_64RegClass) ||
6136 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6137 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
6138 return false;
6139 }
6140 }
6141
6142 return true;
6143}
6144
6146 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
6147 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6148 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
6149 ? AMDGPU::COPY
6150 : AMDGPU::V_MOV_B32_e32;
6151 }
6152 return getVALUOp(MI.getOpcode());
6153}
6154
6155// It is more readable to list mapped opcodes on the same line.
6156// clang-format off
6157
6158unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
6159 switch (Opc) {
6160 default: return AMDGPU::INSTRUCTION_LIST_END;
6161 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
6162 case AMDGPU::COPY: return AMDGPU::COPY;
6163 case AMDGPU::PHI: return AMDGPU::PHI;
6164 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
6165 case AMDGPU::WQM: return AMDGPU::WQM;
6166 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
6167 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
6168 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
6169 case AMDGPU::S_ADD_I32:
6170 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6171 case AMDGPU::S_ADDC_U32:
6172 return AMDGPU::V_ADDC_U32_e32;
6173 case AMDGPU::S_SUB_I32:
6174 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6175 // FIXME: These are not consistently handled, and selected when the carry is
6176 // used.
6177 case AMDGPU::S_ADD_U32:
6178 return AMDGPU::V_ADD_CO_U32_e32;
6179 case AMDGPU::S_SUB_U32:
6180 return AMDGPU::V_SUB_CO_U32_e32;
6181 case AMDGPU::S_ADD_U64_PSEUDO:
6182 return AMDGPU::V_ADD_U64_PSEUDO;
6183 case AMDGPU::S_SUB_U64_PSEUDO:
6184 return AMDGPU::V_SUB_U64_PSEUDO;
6185 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
6186 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
6187 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
6188 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
6189 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
6190 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
6191 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
6192 case AMDGPU::S_XNOR_B32:
6193 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6194 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
6195 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
6196 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
6197 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
6198 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
6199 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
6200 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
6201 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
6202 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
6203 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
6204 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
6205 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
6206 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
6207 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
6208 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
6209 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
6210 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
6211 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
6212 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
6213 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
6214 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
6215 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
6216 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
6217 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
6218 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
6219 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
6220 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
6221 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
6222 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
6223 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
6224 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
6225 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
6226 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
6227 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
6228 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
6229 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
6230 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
6231 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
6232 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
6233 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
6234 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
6235 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
6236 case AMDGPU::S_CVT_F32_F16:
6237 case AMDGPU::S_CVT_HI_F32_F16:
6238 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6239 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6240 case AMDGPU::S_CVT_F16_F32:
6241 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6242 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6243 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
6244 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
6245 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
6246 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
6247 case AMDGPU::S_CEIL_F16:
6248 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6249 : AMDGPU::V_CEIL_F16_fake16_e64;
6250 case AMDGPU::S_FLOOR_F16:
6251 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6252 : AMDGPU::V_FLOOR_F16_fake16_e64;
6253 case AMDGPU::S_TRUNC_F16:
6254 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6255 : AMDGPU::V_TRUNC_F16_fake16_e64;
6256 case AMDGPU::S_RNDNE_F16:
6257 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6258 : AMDGPU::V_RNDNE_F16_fake16_e64;
6259 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6260 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6261 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6262 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6263 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6264 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6265 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6266 case AMDGPU::S_ADD_F16:
6267 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6268 : AMDGPU::V_ADD_F16_fake16_e64;
6269 case AMDGPU::S_SUB_F16:
6270 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6271 : AMDGPU::V_SUB_F16_fake16_e64;
6272 case AMDGPU::S_MIN_F16:
6273 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6274 : AMDGPU::V_MIN_F16_fake16_e64;
6275 case AMDGPU::S_MAX_F16:
6276 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6277 : AMDGPU::V_MAX_F16_fake16_e64;
6278 case AMDGPU::S_MINIMUM_F16:
6279 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6280 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6281 case AMDGPU::S_MAXIMUM_F16:
6282 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6283 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6284 case AMDGPU::S_MUL_F16:
6285 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6286 : AMDGPU::V_MUL_F16_fake16_e64;
6287 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6288 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6289 case AMDGPU::S_FMAC_F16:
6290 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6291 : AMDGPU::V_FMAC_F16_fake16_e64;
6292 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6293 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6294 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6295 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6296 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6297 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6298 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6299 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6300 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6301 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6302 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6303 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6304 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6305 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6306 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6307 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6308 case AMDGPU::S_CMP_LT_F16:
6309 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6310 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6311 case AMDGPU::S_CMP_EQ_F16:
6312 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6313 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6314 case AMDGPU::S_CMP_LE_F16:
6315 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6316 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6317 case AMDGPU::S_CMP_GT_F16:
6318 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6319 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6320 case AMDGPU::S_CMP_LG_F16:
6321 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6322 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6323 case AMDGPU::S_CMP_GE_F16:
6324 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6325 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6326 case AMDGPU::S_CMP_O_F16:
6327 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6328 : AMDGPU::V_CMP_O_F16_fake16_e64;
6329 case AMDGPU::S_CMP_U_F16:
6330 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6331 : AMDGPU::V_CMP_U_F16_fake16_e64;
6332 case AMDGPU::S_CMP_NGE_F16:
6333 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6334 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6335 case AMDGPU::S_CMP_NLG_F16:
6336 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6337 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6338 case AMDGPU::S_CMP_NGT_F16:
6339 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6340 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6341 case AMDGPU::S_CMP_NLE_F16:
6342 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6343 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6344 case AMDGPU::S_CMP_NEQ_F16:
6345 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6346 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6347 case AMDGPU::S_CMP_NLT_F16:
6348 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6349 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6350 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6351 case AMDGPU::V_S_EXP_F16_e64:
6352 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6353 : AMDGPU::V_EXP_F16_fake16_e64;
6354 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6355 case AMDGPU::V_S_LOG_F16_e64:
6356 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6357 : AMDGPU::V_LOG_F16_fake16_e64;
6358 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6359 case AMDGPU::V_S_RCP_F16_e64:
6360 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6361 : AMDGPU::V_RCP_F16_fake16_e64;
6362 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6363 case AMDGPU::V_S_RSQ_F16_e64:
6364 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6365 : AMDGPU::V_RSQ_F16_fake16_e64;
6366 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6367 case AMDGPU::V_S_SQRT_F16_e64:
6368 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6369 : AMDGPU::V_SQRT_F16_fake16_e64;
6370 }
6372 "Unexpected scalar opcode without corresponding vector one!");
6373}
6374
6375// clang-format on
6376
6380 const DebugLoc &DL, Register Reg,
6381 bool IsSCCLive,
6382 SlotIndexes *Indexes) const {
6383 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6384 const SIInstrInfo *TII = ST.getInstrInfo();
6386 if (IsSCCLive) {
6387 // Insert two move instructions, one to save the original value of EXEC and
6388 // the other to turn on all bits in EXEC. This is required as we can't use
6389 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6390 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6392 auto FlipExecMI =
6393 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6394 if (Indexes) {
6395 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6396 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6397 }
6398 } else {
6399 auto SaveExec =
6400 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6401 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6402 if (Indexes)
6403 Indexes->insertMachineInstrInMaps(*SaveExec);
6404 }
6405}
6406
6409 const DebugLoc &DL, Register Reg,
6410 SlotIndexes *Indexes) const {
6412 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6413 .addReg(Reg, RegState::Kill);
6414 if (Indexes)
6415 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6416}
6417
6421 "Not a whole wave func");
6422 MachineBasicBlock &MBB = *MF.begin();
6423 for (MachineInstr &MI : MBB)
6424 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6425 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6426 return &MI;
6427
6428 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6429}
6430
6432 unsigned OpNo) const {
6433 const MCInstrDesc &Desc = get(MI.getOpcode());
6434 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6435 Desc.operands()[OpNo].RegClass == -1) {
6436 Register Reg = MI.getOperand(OpNo).getReg();
6437
6438 if (Reg.isVirtual()) {
6439 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6440 return MRI.getRegClass(Reg);
6441 }
6442 return RI.getPhysRegBaseClass(Reg);
6443 }
6444
6445 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6446 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6447}
6448
6449// Convert VOP3 operand index to source number.
6450static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx) {
6451 constexpr AMDGPU::OpName OpNames[] = {
6452 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6453
6454 for (auto [I, OpName] : enumerate(OpNames)) {
6455 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6456 if (static_cast<unsigned>(SrcIdx) == OpIdx)
6457 return I;
6458 }
6459
6460 return UINT_MAX;
6461}
6462
6465 MachineBasicBlock *MBB = MI.getParent();
6466 MachineOperand &MO = MI.getOperand(OpIdx);
6467 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6468 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6469 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6470 unsigned Size = RI.getRegSizeInBits(*RC);
6471 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6472 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6473 : AMDGPU::V_MOV_B32_e32;
6474 if (MO.isReg())
6475 Opcode = AMDGPU::COPY;
6476 else if (RI.isSGPRClass(RC))
6477 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6478
6479 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6480 Register Reg = MRI.createVirtualRegister(VRC);
6481 DebugLoc DL = MBB->findDebugLoc(I);
6482
6483 if (Size == 128 && AMDGPU::isPackedSingleSGPR64BitInst(MI.getOpcode()) &&
6485 // Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
6486 // sources behave like OPSEL is set replicating low 64-bits into high. VGPR
6487 // sources in turn read actual 4 registers. To move operand from an SGPR to
6488 // a VGPR we need to replicate low half.
6489 // We also do not select immediates for these instructions so it always has
6490 // to be an SGPR register here.
6491 // Operands which are not legal as per isLegalSingleSGPRReadInstOperand()
6492 // sent here specifically to fix a non-splat SGPR and shall perform a full
6493 // copy.
6494
6495 const TargetRegisterClass *VRC64 = RI.getVGPRClassForBitWidth(64);
6496 Register Low64 = MRI.createVirtualRegister(VRC64);
6497 assert(MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()));
6498 BuildMI(*MBB, I, DL, get(TargetOpcode::COPY), Low64)
6499 .addReg(MO.getReg(), {}, AMDGPU::sub0_sub1);
6500 BuildMI(*MBB, I, DL, get(TargetOpcode::REG_SEQUENCE), Reg)
6501 .addReg(Low64)
6502 .addImm(AMDGPU::sub0_sub1)
6503 .addReg(Low64, RegState::Kill)
6504 .addImm(AMDGPU::sub2_sub3);
6505 } else {
6506 BuildMI(*MBB, I, DL, get(Opcode), Reg).add(MO);
6507 }
6508
6509 MO.ChangeToRegister(Reg, false);
6510}
6511
6514 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6515 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6516 if (!SuperReg.getReg().isVirtual())
6517 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6518
6519 MachineBasicBlock *MBB = MI->getParent();
6520 const DebugLoc &DL = MI->getDebugLoc();
6521 Register SubReg = MRI.createVirtualRegister(SubRC);
6522
6523 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6524 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6525 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6526 return SubReg;
6527}
6528
6531 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6532 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6533 if (Op.isImm()) {
6534 if (SubIdx == AMDGPU::sub0)
6535 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6536 if (SubIdx == AMDGPU::sub1)
6537 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6538
6539 llvm_unreachable("Unhandled register index for immediate");
6540 }
6541
6542 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6543 SubIdx, SubRC);
6544 return MachineOperand::CreateReg(SubReg, false);
6545}
6546
6547// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6548void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6549 assert(Inst.getNumExplicitOperands() == 3);
6550 MachineOperand Op1 = Inst.getOperand(1);
6551 Inst.removeOperand(1);
6552 Inst.addOperand(Op1);
6553}
6554
6556 const MCOperandInfo &OpInfo,
6557 const MachineOperand &MO) const {
6558 if (!MO.isReg())
6559 return false;
6560
6561 Register Reg = MO.getReg();
6562
6563 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6564 if (Reg.isPhysical())
6565 return DRC->contains(Reg);
6566
6567 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6568
6569 if (MO.getSubReg()) {
6570 const TargetRegisterClass *SuperRC =
6571 RI.getLargestLegalSuperClass(RC, MRI.getMF());
6572 if (!SuperRC)
6573 return false;
6574 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6575 }
6576
6577 return RI.getCommonSubClass(DRC, RC) != nullptr;
6578}
6579
6581 const MachineOperand &MO) const {
6582 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6583 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6584 unsigned Opc = MI.getOpcode();
6585
6586 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6587 if (MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
6588 AMDGPU::isSingleSGPRReadInst(MI.getOpcode()) &&
6590 &MO))
6591 return false;
6592
6593 if (!isLegalRegOperand(MRI, OpInfo, MO))
6594 return false;
6595
6596 // check Accumulate GPR operand
6597 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6598 if (IsAGPR && !ST.hasMAIInsts())
6599 return false;
6600 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6601 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6602 return false;
6603 // Atomics should have both vdst and vdata either vgpr or agpr.
6604 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6605 const int DataIdx = AMDGPU::getNamedOperandIdx(
6606 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6607 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6608 MI.getOperand(DataIdx).isReg() &&
6609 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6610 return false;
6611 if ((int)OpIdx == DataIdx) {
6612 if (VDstIdx != -1 &&
6613 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6614 return false;
6615 // DS instructions with 2 src operands also must have tied RC.
6616 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6617 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6618 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6619 return false;
6620 }
6621
6622 // Check V_ACCVGPR_WRITE_B32_e64
6623 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6624 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6625 RI.isSGPRReg(MRI, MO.getReg()))
6626 return false;
6627
6628 if (ST.hasFlatScratchHiInB64InstHazard() &&
6629 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6630 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6631 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6632 64)
6633 return false;
6634 }
6635 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6636 return false;
6637 }
6638 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6639 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6640 return false;
6641
6642 return true;
6643}
6644
6646 const MCOperandInfo &OpInfo,
6647 const MachineOperand &MO) const {
6648 if (MO.isReg())
6649 return isLegalRegOperand(MRI, OpInfo, MO);
6650
6651 // Handle non-register types that are treated like immediates.
6652 assert(MO.isImm() || MO.isTargetIndex() || MO.isFI() || MO.isGlobal());
6653 return true;
6654}
6655
6657 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6658 const MachineOperand *MO) const {
6659 constexpr unsigned NumOps = 3;
6660 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6661 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6662 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6663 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6664
6665 assert(SrcN < NumOps);
6666
6667 if (!MO) {
6668 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6669 if (SrcIdx == -1)
6670 return true;
6671 MO = &MI.getOperand(SrcIdx);
6672 }
6673
6674 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6675 return true;
6676
6677 int ModsIdx =
6678 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6679 if (ModsIdx == -1)
6680 return false;
6681
6682 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6683 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6684 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6685
6686 return !OpSel && !OpSelHi;
6687}
6688
6689bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
6690 const MachineOperand *MO) const {
6691 const MachineFunction &MF = *MI.getMF();
6692 const MachineRegisterInfo &MRI = MF.getRegInfo();
6693 const MCInstrDesc &InstDesc = MI.getDesc();
6694 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6695 int64_t RegClass = getOpRegClassID(OpInfo);
6696 const TargetRegisterClass *DefinedRC =
6697 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6698 if (!MO)
6699 MO = &MI.getOperand(OpIdx);
6700
6701 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6702
6703 if (isVALU(MI, /*AllowLDSDMA=*/false) && !IsInlineConst &&
6704 usesConstantBus(MRI, *MO, OpInfo)) {
6705 const MachineOperand *UsedLiteral = nullptr;
6706
6707 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6708 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6709
6710 // TODO: Be more permissive with frame indexes.
6711 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6712 if (!LiteralLimit--)
6713 return false;
6714
6715 UsedLiteral = MO;
6716 }
6717
6719 if (MO->isReg())
6720 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6721
6722 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6723 if (i == OpIdx)
6724 continue;
6725 const MachineOperand &Op = MI.getOperand(i);
6726 if (Op.isReg()) {
6727 if (Op.isUse()) {
6728 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6729 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6730 if (--ConstantBusLimit <= 0)
6731 return false;
6732 }
6733 }
6734 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6735 !isInlineConstant(Op, InstDesc.operands()[i])) {
6736 // The same literal may be used multiple times.
6737 if (!UsedLiteral)
6738 UsedLiteral = &Op;
6739 else if (UsedLiteral->isIdenticalTo(Op))
6740 continue;
6741
6742 if (!LiteralLimit--)
6743 return false;
6744 if (--ConstantBusLimit <= 0)
6745 return false;
6746 }
6747 }
6748 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6749 // There can be at most one literal operand, but it can be repeated.
6750 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6751 if (i == OpIdx)
6752 continue;
6753 const MachineOperand &Op = MI.getOperand(i);
6754 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6755 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6756 !Op.isIdenticalTo(*MO))
6757 return false;
6758
6759 // Do not fold a non-inlineable and non-register operand into an
6760 // instruction that already has a frame index. The frame index handling
6761 // code could not handle well when a frame index co-exists with another
6762 // non-register operand, unless that operand is an inlineable immediate.
6763 if (Op.isFI())
6764 return false;
6765 }
6766 }
6767
6768 if (MO->isReg()) {
6769 if (!DefinedRC)
6770 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6771 return isLegalRegOperand(MI, OpIdx, *MO);
6772 }
6773
6774 if (MO->isImm()) {
6775 uint64_t Imm = MO->getImm();
6776 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6777 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6778 bool Is64BitOp = Is64BitFPOp ||
6779 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6780 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6781 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6782 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6783 if (Is64BitOp &&
6784 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6785 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6786 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6787 return false;
6788
6789 // FIXME: We can use sign extended 64-bit literals, but only for signed
6790 // operands. At the moment we do not know if an operand is signed.
6791 // Such operand will be encoded as its low 32 bits and then either
6792 // correctly sign extended or incorrectly zero extended by HW.
6793 // If 64-bit literals are supported and the literal will be encoded
6794 // as full 64 bit we still can use it.
6795 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6796 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
6797 return false;
6798 }
6799 }
6800
6801 // Handle non-register types that are treated like immediates.
6802 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
6803
6804 if (!DefinedRC) {
6805 // This operand expects an immediate.
6806 return true;
6807 }
6808
6809 return isImmOperandLegal(MI, OpIdx, *MO);
6810}
6811
6813 bool IsGFX950Only = ST.hasGFX950Insts();
6814 bool IsGFX940Only = ST.hasGFX940Insts();
6815
6816 if (!IsGFX950Only && !IsGFX940Only)
6817 return false;
6818
6819 if (!isVALU(MI, /*AllowLDSDMA=*/false))
6820 return false;
6821
6822 // V_COS, V_EXP, V_RCP, etc.
6823 if (isTRANS(MI))
6824 return true;
6825
6826 // DOT2, DOT2C, DOT4, etc.
6827 if (isDOT(MI))
6828 return true;
6829
6830 // MFMA, SMFMA
6831 if (isMFMA(MI))
6832 return true;
6833
6834 unsigned Opcode = MI.getOpcode();
6835 switch (Opcode) {
6836 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6837 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6838 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6839 case AMDGPU::V_MQSAD_U32_U8_e64:
6840 case AMDGPU::V_PK_ADD_F16:
6841 case AMDGPU::V_PK_ADD_F32:
6842 case AMDGPU::V_PK_ADD_I16:
6843 case AMDGPU::V_PK_ADD_U16:
6844 case AMDGPU::V_PK_ASHRREV_I16:
6845 case AMDGPU::V_PK_FMA_F16:
6846 case AMDGPU::V_PK_FMA_F32:
6847 case AMDGPU::V_PK_FMAC_F16_e32:
6848 case AMDGPU::V_PK_FMAC_F16_e64:
6849 case AMDGPU::V_PK_LSHLREV_B16:
6850 case AMDGPU::V_PK_LSHRREV_B16:
6851 case AMDGPU::V_PK_MAD_I16:
6852 case AMDGPU::V_PK_MAD_U16:
6853 case AMDGPU::V_PK_MAX_F16:
6854 case AMDGPU::V_PK_MAX_I16:
6855 case AMDGPU::V_PK_MAX_U16:
6856 case AMDGPU::V_PK_MIN_F16:
6857 case AMDGPU::V_PK_MIN_I16:
6858 case AMDGPU::V_PK_MIN_U16:
6859 case AMDGPU::V_PK_MOV_B32:
6860 case AMDGPU::V_PK_MUL_F16:
6861 case AMDGPU::V_PK_MUL_F32:
6862 case AMDGPU::V_PK_MUL_LO_U16:
6863 case AMDGPU::V_PK_SUB_I16:
6864 case AMDGPU::V_PK_SUB_U16:
6865 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6866 return true;
6867 default:
6868 return false;
6869 }
6870}
6871
6873 MachineInstr &MI) const {
6874 unsigned Opc = MI.getOpcode();
6875 const MCInstrDesc &InstrDesc = get(Opc);
6876
6877 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
6878 MachineOperand &Src0 = MI.getOperand(Src0Idx);
6879
6880 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
6881 MachineOperand &Src1 = MI.getOperand(Src1Idx);
6882
6883 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
6884 // we need to only have one constant bus use before GFX10.
6885 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
6886 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
6887 RI.isSGPRReg(MRI, Src0.getReg()))
6888 legalizeOpWithMove(MI, Src0Idx);
6889
6890 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
6891 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
6892 // src0/src1 with V_READFIRSTLANE.
6893 if (Opc == AMDGPU::V_WRITELANE_B32) {
6894 const DebugLoc &DL = MI.getDebugLoc();
6895 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
6896 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6897 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6898 .add(Src0);
6899 Src0.ChangeToRegister(Reg, false);
6900 }
6901 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
6902 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6903 const DebugLoc &DL = MI.getDebugLoc();
6904 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6905 .add(Src1);
6906 Src1.ChangeToRegister(Reg, false);
6907 }
6908 return;
6909 }
6910
6911 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
6912 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
6913 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
6914 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
6915 legalizeOpWithMove(MI, Src2Idx);
6916 }
6917
6918 // VOP2 src0 instructions support all operand types, so we don't need to check
6919 // their legality. If src1 is already legal, we don't need to do anything.
6920 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
6921 return;
6922
6923 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
6924 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
6925 // select is uniform.
6926 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
6927 RI.isVGPR(MRI, Src1.getReg())) {
6928 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6929 const DebugLoc &DL = MI.getDebugLoc();
6930 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6931 .add(Src1);
6932 Src1.ChangeToRegister(Reg, false);
6933 return;
6934 }
6935
6936 // We do not use commuteInstruction here because it is too aggressive and will
6937 // commute if it is possible. We only want to commute here if it improves
6938 // legality. This can be called a fairly large number of times so don't waste
6939 // compile time pointlessly swapping and checking legality again.
6940 if (HasImplicitSGPR || !MI.isCommutable()) {
6941 legalizeOpWithMove(MI, Src1Idx);
6942 return;
6943 }
6944
6945 // If src0 can be used as src1, commuting will make the operands legal.
6946 // Otherwise we have to give up and insert a move.
6947 //
6948 // TODO: Other immediate-like operand kinds could be commuted if there was a
6949 // MachineOperand::ChangeTo* for them.
6950 if ((!Src1.isImm() && !Src1.isReg()) ||
6951 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
6952 legalizeOpWithMove(MI, Src1Idx);
6953 return;
6954 }
6955
6956 int CommutedOpc = commuteOpcode(MI);
6957 if (CommutedOpc == -1) {
6958 legalizeOpWithMove(MI, Src1Idx);
6959 return;
6960 }
6961
6962 MI.setDesc(get(CommutedOpc));
6963
6964 Register Src0Reg = Src0.getReg();
6965 unsigned Src0SubReg = Src0.getSubReg();
6966 bool Src0Kill = Src0.isKill();
6967
6968 if (Src1.isImm())
6969 Src0.ChangeToImmediate(Src1.getImm());
6970 else if (Src1.isReg()) {
6971 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
6972 Src0.setSubReg(Src1.getSubReg());
6973 } else
6974 llvm_unreachable("Should only have register or immediate operands");
6975
6976 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
6977 Src1.setSubReg(Src0SubReg);
6979}
6980
6981// Legalize VOP3 operands. All operand types are supported for any operand
6982// but only one literal constant and only starting from GFX10.
6984 MachineInstr &MI) const {
6985 unsigned Opc = MI.getOpcode();
6986
6987 int VOP3Idx[3] = {
6988 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
6989 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
6990 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
6991 };
6992
6993 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6994 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6995 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6996 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6997 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6998 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6999 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7000 // src1 and src2 must be scalar
7001 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
7002 const DebugLoc &DL = MI.getDebugLoc();
7003 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
7004 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7005 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7006 .add(Src1);
7007 Src1.ChangeToRegister(Reg, false);
7008 }
7009 if (VOP3Idx[2] != -1) {
7010 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
7011 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
7012 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7013 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7014 .add(Src2);
7015 Src2.ChangeToRegister(Reg, false);
7016 }
7017 }
7018 }
7019
7020 // Find the one SGPR operand we are allowed to use.
7021 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
7022 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7023 SmallDenseSet<unsigned> SGPRsUsed;
7024 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
7025 if (SGPRReg) {
7026 SGPRsUsed.insert(SGPRReg);
7027 --ConstantBusLimit;
7028 }
7029
7030 for (int Idx : VOP3Idx) {
7031 if (Idx == -1)
7032 break;
7033 MachineOperand &MO = MI.getOperand(Idx);
7034
7035 if (!MO.isReg()) {
7036 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
7037 continue;
7038
7039 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7040 --LiteralLimit;
7041 --ConstantBusLimit;
7042 continue;
7043 }
7044
7045 --LiteralLimit;
7046 --ConstantBusLimit;
7047 legalizeOpWithMove(MI, Idx);
7048 continue;
7049 }
7050
7051 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
7052 continue; // VGPRs are legal
7053
7054 // We can use one SGPR in each VOP3 instruction prior to GFX10
7055 // and two starting from GFX10.
7056 if (SGPRsUsed.count(MO.getReg()))
7057 continue;
7058 if (ConstantBusLimit > 0) {
7059 SGPRsUsed.insert(MO.getReg());
7060 --ConstantBusLimit;
7061 continue;
7062 }
7063
7064 // If we make it this far, then the operand is not legal and we must
7065 // legalize it.
7066 legalizeOpWithMove(MI, Idx);
7067 }
7068
7069 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
7070 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64) &&
7071 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
7072 legalizeOpWithMove(MI, VOP3Idx[2]);
7073
7074 // Fix the register class of single-sgpr-read instructions on gfx12+. See
7075 // SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
7077 for (unsigned I = 0; I < 3; ++I) {
7078 if (!isLegalSingleSGPRReadInstOperand(MRI, MI, /*SrcN=*/I))
7079 legalizeOpWithMove(MI, VOP3Idx[I]);
7080 }
7081 }
7082}
7083
7086 const TargetRegisterClass *DstRC /*=nullptr*/) const {
7087 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
7088 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
7089 if (DstRC)
7090 SRC = RI.getCommonSubClass(SRC, DstRC);
7091
7092 Register DstReg = MRI.createVirtualRegister(SRC);
7093 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7094
7095 if (RI.hasAGPRs(VRC)) {
7096 VRC = RI.getEquivalentVGPRClass(VRC);
7097 Register NewSrcReg = MRI.createVirtualRegister(VRC);
7098 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7099 get(TargetOpcode::COPY), NewSrcReg)
7100 .addReg(SrcReg);
7101 SrcReg = NewSrcReg;
7102 }
7103
7104 if (SubRegs == 1) {
7105 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7106 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7107 .addReg(SrcReg);
7108 return DstReg;
7109 }
7110
7112 for (unsigned i = 0; i < SubRegs; ++i) {
7113 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7114 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7115 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7116 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7117 SRegs.push_back(SGPR);
7118 }
7119
7121 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7122 get(AMDGPU::REG_SEQUENCE), DstReg);
7123 for (unsigned i = 0; i < SubRegs; ++i) {
7124 MIB.addReg(SRegs[i]);
7125 MIB.addImm(RI.getSubRegFromChannel(i));
7126 }
7127 return DstReg;
7128}
7129
7131 MachineInstr &MI) const {
7132
7133 // If the pointer is store in VGPRs, then we need to move them to
7134 // SGPRs using v_readfirstlane. This is safe because we only select
7135 // loads with uniform pointers to SMRD instruction so we know the
7136 // pointer value is uniform.
7137 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
7138 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
7139 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
7140 SBase->setReg(SGPR);
7141 }
7142 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
7143 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
7144 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
7145 SOff->setReg(SGPR);
7146 }
7147}
7148
7150 unsigned Opc = Inst.getOpcode();
7151 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
7152 if (OldSAddrIdx < 0)
7153 return false;
7154
7155 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
7156
7157 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
7158 if (NewOpc < 0)
7160 if (NewOpc < 0)
7161 return false;
7162
7163 MachineRegisterInfo &MRI = Inst.getMF()->getRegInfo();
7164 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
7165 if (RI.isSGPRReg(MRI, SAddr.getReg()))
7166 return false;
7167
7168 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7169 if (NewVAddrIdx < 0)
7170 return false;
7171
7172 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
7173
7174 // Check vaddr, it shall be zero or absent.
7175 MachineInstr *VAddrDef = nullptr;
7176 if (OldVAddrIdx >= 0) {
7177 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
7178 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
7179 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
7180 !VAddrDef->getOperand(1).isImm() ||
7181 VAddrDef->getOperand(1).getImm() != 0)
7182 return false;
7183 }
7184
7185 const MCInstrDesc &NewDesc = get(NewOpc);
7186 Inst.setDesc(NewDesc);
7187
7188 // Callers expect iterator to be valid after this call, so modify the
7189 // instruction in place.
7190 if (OldVAddrIdx == NewVAddrIdx) {
7191 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
7192 // Clear use list from the old vaddr holding a zero register.
7193 MRI.removeRegOperandFromUseList(&NewVAddr);
7194 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7195 Inst.removeOperand(OldSAddrIdx);
7196 // Update the use list with the pointer we have just moved from vaddr to
7197 // saddr position. Otherwise new vaddr will be missing from the use list.
7198 MRI.removeRegOperandFromUseList(&NewVAddr);
7199 MRI.addRegOperandToUseList(&NewVAddr);
7200 } else {
7201 assert(OldSAddrIdx == NewVAddrIdx);
7202
7203 if (OldVAddrIdx >= 0) {
7204 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7205 AMDGPU::OpName::vdst_in);
7206
7207 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
7208 // it asserts. Untie the operands for now and retie them afterwards.
7209 if (NewVDstIn != -1) {
7210 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
7211 Inst.untieRegOperand(OldVDstIn);
7212 }
7213
7214 Inst.removeOperand(OldVAddrIdx);
7215
7216 if (NewVDstIn != -1) {
7217 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7218 Inst.tieOperands(NewVDst, NewVDstIn);
7219 }
7220 }
7221 }
7222
7223 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
7224 VAddrDef->eraseFromParent();
7225
7226 return true;
7227}
7228
7229// FIXME: Remove this when SelectionDAG is obsoleted.
7231 MachineInstr &MI) const {
7232 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
7233 return;
7234
7235 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
7236 // thinks they are uniform, so a readfirstlane should be valid.
7237 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
7238 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
7239 return;
7240
7242 return;
7243
7244 const TargetRegisterClass *DeclaredRC =
7245 getRegClass(MI.getDesc(), SAddr->getOperandNo());
7246
7247 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
7248 SAddr->setReg(ToSGPR);
7249}
7250
7253 const TargetRegisterClass *DstRC,
7256 const DebugLoc &DL) const {
7257 Register OpReg = Op.getReg();
7258 unsigned OpSubReg = Op.getSubReg();
7259
7260 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
7261 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7262
7263 // Check if operand is already the correct register class.
7264 if (DstRC == OpRC)
7265 return;
7266
7267 Register DstReg = MRI.createVirtualRegister(DstRC);
7268 auto Copy = BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg)
7269 .addReg(OpReg, {}, OpSubReg);
7270 Op.setReg(DstReg);
7271 Op.setSubReg(AMDGPU::NoSubRegister);
7272
7273 MachineInstr *Def = MRI.getVRegDef(OpReg);
7274 if (!Def)
7275 return;
7276
7277 // Try to eliminate the copy if it is copying an immediate value.
7278 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7279 foldImmediate(*Copy, *Def, OpReg, &MRI);
7280
7281 bool ImpDef = Def->isImplicitDef();
7282 while (!ImpDef && Def && Def->isCopy()) {
7283 if (Def->getOperand(1).getReg().isPhysical())
7284 break;
7285 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7286 ImpDef = Def && Def->isImplicitDef();
7287 }
7288 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7289 !ImpDef)
7290 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7291}
7292
7293// Emit the actual waterfall loop, executing the wrapped instruction for each
7294// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7295// iteration, in the worst case we execute 64 (once per lane).
7298 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7299 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7300 MachineFunction &MF = *LoopBB.getParent();
7302 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7304 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7305
7306 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7307 // available. Otherwise, use the previous pattern of v_cmp_eq,
7308 // s_and_saveexec, and s_xor.
7309 bool UseNewExecInstructions =
7310 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7311
7313 Register CondReg;
7314
7315 Register PhiExec;
7316 Register NewExec;
7317
7318 if (UseNewExecInstructions) {
7319 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7320 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7321 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7322 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7323 .addReg(LMC.ExecReg);
7324
7325 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7326 .addReg(InitExec)
7327 .addMBB(&PredBB)
7328 .addReg(NewExec)
7329 .addMBB(&BodyBB);
7330 }
7331
7332 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7333 // involves a trade-off between register pressure and latency:
7334 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7335 // register pressure because arguments and results of all
7336 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7337 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7338 // increase latency by placing v_readfirstlane instructions
7339 // immediately before v_cmpx instruction that directly depend on it.
7340 ///
7341 // Emitting interleaved v_cmpx and v_readfirstlane requires
7342 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7343 // v_cmpx needs to be treated as terminator until after register allocation
7344 // (spill placement) and instruction reordering.
7345 //
7346 // Current implementation defers v_cmpx and leaves other instruction
7347 // scheduling decisions to later passes, where register pressure is known or
7348 // easier to approximate.
7349 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7350 // v_cmpx instructions are inserted at the end of LoopBB.
7351 // After the first v_cmpx is emitted, I is updated to point to it
7352 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7353 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7354 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7355 unsigned NumSubRegs = RegSize / 32;
7356 Register VScalarOp = ScalarOp->getReg();
7357
7358 const TargetRegisterClass *RFLSrcRC =
7359 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7360
7361 if (NumSubRegs == 1) {
7362 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7363 if (const TargetRegisterClass *Common =
7364 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7365 Common != VScalarOpRC) {
7366 Register VRReg = MRI.createVirtualRegister(Common);
7367 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7368 VScalarOp = VRReg;
7369 }
7370 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7371
7372 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7373 .addReg(VScalarOp);
7374
7375 if (UseNewExecInstructions) {
7376 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7377 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7378 .addReg(CurReg)
7379 .addReg(VScalarOp);
7380 if (I == LoopBB.end())
7381 I = CmpxMI.getInstr()->getIterator();
7382 } else {
7383 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7384
7385 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7386 .addReg(CurReg)
7387 .addReg(VScalarOp);
7388
7389 // Combine the comparison results with AND.
7390 if (!CondReg) { // First.
7391 CondReg = NewCondReg;
7392 } else { // If not the first, we create an AND.
7393 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7394 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7395 .addReg(CondReg)
7396 .addReg(NewCondReg);
7397 CondReg = AndReg;
7398 }
7399 }
7400
7401 // Update ScalarOp operand to use the SGPR ScalarOp.
7402 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7403 ScalarOp->setReg(CurReg);
7404 else {
7405 // Insert into the same block of use
7406 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7407 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7408 .addReg(CurReg);
7409 ScalarOp->setReg(PhySGPRs[Idx]);
7410 }
7411 ScalarOp->setIsKill();
7412 } else {
7413 SmallVector<Register, 8> ReadlanePieces;
7414 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7415 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7416 "Unhandled register size");
7417
7418 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7419 Register CurRegLo =
7420 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7421 Register CurRegHi =
7422 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7423
7424 // Read the next variant <- also loop target.
7425 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7426 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7427
7428 // Read the next variant <- also loop target.
7429 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7430 .addReg(VScalarOp, VScalarOpUndef,
7431 TRI->getSubRegFromChannel(Idx + 1));
7432
7433 ReadlanePieces.push_back(CurRegLo);
7434 ReadlanePieces.push_back(CurRegHi);
7435
7436 // Comparison is to be done as 64-bit.
7437 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7438 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7439 .addReg(CurRegLo)
7440 .addImm(AMDGPU::sub0)
7441 .addReg(CurRegHi)
7442 .addImm(AMDGPU::sub1);
7443
7444 unsigned SubReg =
7445 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7446
7447 if (UseNewExecInstructions) {
7448 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7449 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7450 .addReg(CurReg)
7451 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7452 if (I == LoopBB.end())
7453 I = CmpxMI.getInstr()->getIterator();
7454 } else {
7455 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7456 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7457 .addReg(CurReg)
7458 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7459
7460 // Combine the comparison results with AND.
7461 if (!CondReg) { // First.
7462 CondReg = NewCondReg;
7463 } else { // If not the first, we create an AND.
7464 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7465 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7466 .addReg(CondReg)
7467 .addReg(NewCondReg);
7468 CondReg = AndReg;
7469 }
7470 }
7471 } // End for loop.
7472
7473 const auto *SScalarOpRC =
7474 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7475 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7476
7477 // Build scalar ScalarOp.
7478 auto Merge =
7479 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7480 unsigned Channel = 0;
7481 for (Register Piece : ReadlanePieces) {
7482 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7483 }
7484
7485 // Update ScalarOp operand to use the SGPR ScalarOp.
7486 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7487 ScalarOp->setReg(SScalarOp);
7488 else {
7489 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7490 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7491 .addReg(SScalarOp);
7492 ScalarOp->setReg(PhySGPRs[Idx]);
7493 }
7494 ScalarOp->setIsKill();
7495 }
7496 }
7497
7498 // Instructions AndSaveExecOpc and AndN2WrExecOpc that modify EXEC mask
7499 // should have isTerminator=1 but terminators that define
7500 // virtual registers are not supported.
7501 Register SaveExec;
7502 if (!UseNewExecInstructions) {
7503 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7504 MRI.setSimpleHint(SaveExec, CondReg);
7505
7506 // Update EXEC to matching lanes, saving original to SaveExec.
7507 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7508 .addReg(CondReg, RegState::Kill);
7509 }
7510
7511 // The original instruction is here; we insert the terminators after it.
7512 I = BodyBB.end();
7513
7514 if (UseNewExecInstructions) {
7515 MRI.setSimpleHint(NewExec, PhiExec);
7516 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2WrExecOpc), NewExec)
7517 .addReg(PhiExec);
7518 } else {
7519 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7520 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7521 .addReg(LMC.ExecReg)
7522 .addReg(SaveExec);
7523 }
7524
7525 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7526}
7527
7528// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7529// with SGPRs by iterating over all unique values across all lanes.
7530// Returns the loop basic block that now contains \p MI.
7531static MachineBasicBlock *
7535 MachineBasicBlock::iterator Begin = nullptr,
7536 MachineBasicBlock::iterator End = nullptr,
7537 ArrayRef<Register> PhySGPRs = {}) {
7538 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7539 "Physical SGPRs must be empty or match the number of scalar operands");
7541 MachineFunction &MF = *MBB.getParent();
7543 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7544 MachineRegisterInfo &MRI = MF.getRegInfo();
7545 if (!Begin.isValid())
7546 Begin = &MI;
7547 if (!End.isValid()) {
7548 End = &MI;
7549 ++End;
7550 }
7551 const DebugLoc &DL = MI.getDebugLoc();
7553 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7554
7555 // Save SCC. Waterfall Loop may overwrite SCC.
7556 Register SaveSCCReg;
7557
7558 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7559 // rather than unlimited scan everywhere
7560 bool SCCNotDead =
7561 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7562 std::numeric_limits<unsigned>::max()) !=
7564 if (SCCNotDead) {
7565 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7566 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7567 .addImm(1)
7568 .addImm(0);
7569 }
7570
7571 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7572
7573 // Save the EXEC mask
7574 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7575
7576 // Killed uses in the instruction we are waterfalling around will be
7577 // incorrect due to the added control-flow.
7579 ++AfterMI;
7580 for (auto I = Begin; I != AfterMI; I++) {
7581 for (auto &MO : I->all_uses())
7582 MRI.clearKillFlags(MO.getReg());
7583 }
7584
7585 // To insert the loop we need to split the block. Move everything after this
7586 // point to a new block, and insert a new empty block between the two.
7589 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7591 ++MBBI;
7592
7593 MF.insert(MBBI, LoopBB);
7594 MF.insert(MBBI, BodyBB);
7595 MF.insert(MBBI, RemainderBB);
7596
7597 LoopBB->addSuccessor(BodyBB);
7598 BodyBB->addSuccessor(LoopBB);
7599 BodyBB->addSuccessor(RemainderBB);
7600
7601 // Move Begin to MI to the BodyBB, and the remainder of the block to
7602 // RemainderBB.
7603 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7604 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7605 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7606
7607 MBB.addSuccessor(LoopBB);
7608
7609 // Update dominators. We know that MBB immediately dominates LoopBB, that
7610 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7611 // RemainderBB. RemainderBB immediately dominates all of the successors
7612 // transferred to it from MBB that MBB used to properly dominate.
7613 if (MDT) {
7614 MDT->addNewBlock(LoopBB, &MBB);
7615 MDT->addNewBlock(BodyBB, LoopBB);
7616 MDT->addNewBlock(RemainderBB, BodyBB);
7617 for (auto &Succ : RemainderBB->successors()) {
7618 if (MDT->properlyDominates(&MBB, Succ)) {
7619 MDT->changeImmediateDominator(Succ, RemainderBB);
7620 }
7621 }
7622 }
7623
7624 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7625 PhySGPRs);
7626
7627 MachineBasicBlock::iterator First = RemainderBB->begin();
7628 // Restore SCC
7629 if (SCCNotDead) {
7630 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7631 .addReg(SaveSCCReg, RegState::Kill)
7632 .addImm(0);
7633 }
7634
7635 // Restore the EXEC mask
7636 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7637 .addReg(SaveExec);
7638 return BodyBB;
7639}
7640
7641// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7642static std::tuple<unsigned, unsigned>
7644 MachineBasicBlock &MBB = *MI.getParent();
7645 MachineFunction &MF = *MBB.getParent();
7646 MachineRegisterInfo &MRI = MF.getRegInfo();
7647
7648 // Extract the ptr from the resource descriptor.
7649 unsigned RsrcPtr =
7650 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7651 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7652
7653 // Create an empty resource descriptor
7654 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7655 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7656 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7657 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7658 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7659
7660 // Zero64 = 0
7661 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7662 .addImm(0);
7663
7664 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7665 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7666 .addImm(Lo_32(RsrcDataFormat));
7667
7668 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7669 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7670 .addImm(Hi_32(RsrcDataFormat));
7671
7672 // NewSRsrc = {Zero64, SRsrcFormat}
7673 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7674 .addReg(Zero64)
7675 .addImm(AMDGPU::sub0_sub1)
7676 .addReg(SRsrcFormatLo)
7677 .addImm(AMDGPU::sub2)
7678 .addReg(SRsrcFormatHi)
7679 .addImm(AMDGPU::sub3);
7680
7681 return std::tuple(RsrcPtr, NewSRsrc);
7682}
7683
7686 MachineDominatorTree *MDT) const {
7687 MachineFunction &MF = *MI.getMF();
7688 MachineRegisterInfo &MRI = MF.getRegInfo();
7689 MachineBasicBlock *CreatedBB = nullptr;
7690
7691 // Legalize True16
7692 if (ST.useRealTrue16Insts())
7694
7695 // Legalize VOP2
7696 if (isVOP2(MI) || isVOPC(MI)) {
7698 return CreatedBB;
7699 }
7700
7701 // Legalize VOP3
7702 if (isVOP3(MI)) {
7704 return CreatedBB;
7705 }
7706
7707 // Legalize SMRD
7708 if (isSMRD(MI)) {
7710 return CreatedBB;
7711 }
7712
7713 // Legalize FLAT
7714 if (isFLAT(MI)) {
7716 return CreatedBB;
7717 }
7718
7719 // Legalize PHI
7720 // The register class of the operands must be the same type as the register
7721 // class of the output.
7722 if (MI.getOpcode() == AMDGPU::PHI) {
7723 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7724 assert(!RI.isSGPRClass(VRC));
7725
7726 // Update all the operands so they have the same type.
7727 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7728 MachineOperand &Op = MI.getOperand(I);
7729 if (!Op.isReg() || !Op.getReg().isVirtual())
7730 continue;
7731
7732 // MI is a PHI instruction.
7733 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7735
7736 // Avoid creating no-op copies with the same src and dst reg class. These
7737 // confuse some of the machine passes.
7738 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7739 }
7740 }
7741
7742 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7743 // VGPR dest type and SGPR sources, insert copies so all operands are
7744 // VGPRs. This seems to help operand folding / the register coalescer.
7745 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7746 MachineBasicBlock *MBB = MI.getParent();
7747 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7748 if (RI.hasVGPRs(DstRC)) {
7749 // Update all the operands so they are VGPR register classes. These may
7750 // not be the same register class because REG_SEQUENCE supports mixing
7751 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7752 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7753 MachineOperand &Op = MI.getOperand(I);
7754 if (!Op.isReg() || !Op.getReg().isVirtual())
7755 continue;
7756
7757 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7758 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7759 if (VRC == OpRC)
7760 continue;
7761
7762 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7763 Op.setIsKill();
7764 }
7765 }
7766
7767 return CreatedBB;
7768 }
7769
7770 // Legalize INSERT_SUBREG
7771 // src0 must have the same register class as dst
7772 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7773 Register Dst = MI.getOperand(0).getReg();
7774 Register Src0 = MI.getOperand(1).getReg();
7775 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7776 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7777 if (DstRC != Src0RC) {
7778 MachineBasicBlock *MBB = MI.getParent();
7779 MachineOperand &Op = MI.getOperand(1);
7780 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7781 }
7782 return CreatedBB;
7783 }
7784
7785 // Legalize SI_INIT_M0
7786 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7787 MachineOperand &Src = MI.getOperand(0);
7788 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7789 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7790 return CreatedBB;
7791 }
7792
7793 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
7794 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7795 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7796 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7797 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7798 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7799 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7800 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7801 MachineOperand &Src = MI.getOperand(1);
7802 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7803 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7804 return CreatedBB;
7805 }
7806
7807 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
7808 //
7809 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
7810 // scratch memory access. In both cases, the legalization never involves
7811 // conversion to the addr64 form.
7813 (isMUBUF(MI) || isMTBUF(MI)))) {
7814 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
7815 ? AMDGPU::OpName::rsrc
7816 : AMDGPU::OpName::srsrc;
7817 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
7818 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
7819 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
7820
7821 AMDGPU::OpName SampOpName =
7822 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7823 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
7824 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
7825 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
7826
7827 return CreatedBB;
7828 }
7829
7830 // Legalize SI_CALL
7831 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7832 MachineOperand *Dest = &MI.getOperand(0);
7833 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
7834 createWaterFallForSiCall(&MI, MDT, {Dest});
7835 }
7836 }
7837
7838 // Legalize s_sleep_var.
7839 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7840 const DebugLoc &DL = MI.getDebugLoc();
7841 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7842 int Src0Idx =
7843 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
7844 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7845 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7846 .add(Src0);
7847 Src0.ChangeToRegister(Reg, false);
7848 return nullptr;
7849 }
7850
7851 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
7852 // operands are scalar.
7853 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7854 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7855 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7856 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7857 for (MachineOperand &Src : MI.explicit_operands()) {
7858 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7859 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7860 }
7861 return CreatedBB;
7862 }
7863
7864 // Legalize MUBUF instructions.
7865 bool isSoffsetLegal = true;
7866 int SoffsetIdx =
7867 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
7868 if (SoffsetIdx != -1) {
7869 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
7870 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
7871 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
7872 isSoffsetLegal = false;
7873 }
7874 }
7875
7876 bool isRsrcLegal = true;
7877 int RsrcIdx =
7878 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
7879 if (RsrcIdx != -1) {
7880 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7881 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
7882 isRsrcLegal = false;
7883 }
7884
7885 // The operands are legal.
7886 if (isRsrcLegal && isSoffsetLegal)
7887 return CreatedBB;
7888
7889 if (!isRsrcLegal) {
7890 // Legalize a VGPR Rsrc
7891 //
7892 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
7893 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
7894 // a zero-value SRsrc.
7895 //
7896 // If the instruction is _OFFSET (both idxen and offen disabled), and we
7897 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
7898 // above.
7899 //
7900 // Otherwise we are on non-ADDR64 hardware, and/or we have
7901 // idxen/offen/bothen and we fall back to a waterfall loop.
7902
7903 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7904 MachineBasicBlock &MBB = *MI.getParent();
7905
7906 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
7907 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
7908 // This is already an ADDR64 instruction so we need to add the pointer
7909 // extracted from the resource descriptor to the current value of VAddr.
7910 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7911 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7912 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7913
7914 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7915 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
7916 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
7917
7918 unsigned RsrcPtr, NewSRsrc;
7919 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7920
7921 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
7922 const DebugLoc &DL = MI.getDebugLoc();
7923 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
7924 .addDef(CondReg0)
7925 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7926 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
7927 .addImm(0);
7928
7929 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
7930 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
7931 .addDef(CondReg1, RegState::Dead)
7932 .addReg(RsrcPtr, {}, AMDGPU::sub1)
7933 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
7934 .addReg(CondReg0, RegState::Kill)
7935 .addImm(0);
7936
7937 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7938 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
7939 .addReg(NewVAddrLo)
7940 .addImm(AMDGPU::sub0)
7941 .addReg(NewVAddrHi)
7942 .addImm(AMDGPU::sub1);
7943
7944 VAddr->setReg(NewVAddr);
7945 Rsrc->setReg(NewSRsrc);
7946 } else if (!VAddr && ST.hasAddr64()) {
7947 // This instructions is the _OFFSET variant, so we need to convert it to
7948 // ADDR64.
7949 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
7950 "FIXME: Need to emit flat atomics here");
7951
7952 unsigned RsrcPtr, NewSRsrc;
7953 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7954
7955 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7956 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
7957 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
7958 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7959 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
7960
7961 // Atomics with return have an additional tied operand and are
7962 // missing some of the special bits.
7963 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
7964 MachineInstr *Addr64;
7965
7966 if (!VDataIn) {
7967 // Regular buffer load / store.
7969 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7970 .add(*VData)
7971 .addReg(NewVAddr)
7972 .addReg(NewSRsrc)
7973 .add(*SOffset)
7974 .add(*Offset);
7975
7976 if (const MachineOperand *CPol =
7977 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
7978 MIB.addImm(CPol->getImm());
7979 }
7980
7981 if (const MachineOperand *TFE =
7982 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
7983 MIB.addImm(TFE->getImm());
7984 }
7985
7986 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
7987
7988 MIB.cloneMemRefs(MI);
7989 Addr64 = MIB;
7990 } else {
7991 // Atomics with return.
7992 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7993 .add(*VData)
7994 .add(*VDataIn)
7995 .addReg(NewVAddr)
7996 .addReg(NewSRsrc)
7997 .add(*SOffset)
7998 .add(*Offset)
7999 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
8000 .cloneMemRefs(MI);
8001 }
8002
8003 MI.removeFromParent();
8004
8005 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8006 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
8007 NewVAddr)
8008 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8009 .addImm(AMDGPU::sub0)
8010 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8011 .addImm(AMDGPU::sub1);
8012 } else {
8013 // Legalize a VGPR Rsrc and soffset together.
8014 if (!isSoffsetLegal) {
8015 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8016 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
8017 return CreatedBB;
8018 }
8019 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
8020 return CreatedBB;
8021 }
8022 }
8023
8024 // Legalize a VGPR soffset.
8025 if (!isSoffsetLegal) {
8026 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8027 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
8028 return CreatedBB;
8029 }
8030 return CreatedBB;
8031}
8032
8034 if (InSet.insert(MI).second)
8035 InstrList.push_back(MI);
8036 // Add MBUF instructiosn to deferred list.
8037 int RsrcIdx =
8038 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
8039 if (RsrcIdx != -1) {
8040 DeferredList.insert(MI);
8041 }
8042}
8043
8045 return DeferredList.contains(MI);
8046}
8047
8048// Legalize size mismatches between 16bit and 32bit registers in v2s copy
8049// lowering (change sgpr to vgpr).
8050// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
8051// size. Need to legalize the size of the operands during the vgpr lowering
8052// chain. This can be removed after we have sgpr16 in place
8054 MachineRegisterInfo &MRI) const {
8055 if (!ST.useRealTrue16Insts())
8056 return;
8057
8058 unsigned Opcode = MI.getOpcode();
8059 MachineBasicBlock *MBB = MI.getParent();
8060 // Legalize operands and check for size mismatch
8061 if (OpIdx >= MI.getNumExplicitOperands() ||
8062 OpIdx >= get(Opcode).getNumOperands() ||
8063 get(Opcode).operands()[OpIdx].RegClass == -1)
8064 return;
8065
8066 MachineOperand &Op = MI.getOperand(OpIdx);
8067 if (!Op.isReg() || !Op.getReg().isVirtual() || Op.isDef())
8068 return;
8069
8070 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
8071 if (!RI.isVGPRClass(CurrRC))
8072 return;
8073
8074 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
8075 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
8076 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8077 // Default to the lo16 only if the subregister is not specified.
8078 if (Op.getSubReg() == AMDGPU::NoSubRegister)
8079 Op.setSubReg(AMDGPU::lo16);
8080 return;
8081 }
8082
8083 const TargetRegisterClass *CurrSRC =
8084 RI.getSubRegisterClass(CurrRC, Op.getSubReg());
8085 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8086 const DebugLoc &DL = MI.getDebugLoc();
8087 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8088 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8089 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
8090 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
8091 .addReg(Op.getReg(), {}, Op.getSubReg())
8092 .addImm(AMDGPU::lo16)
8093 .addReg(Undef)
8094 .addImm(AMDGPU::hi16);
8095 Op.setReg(NewDstReg);
8096 Op.setSubReg(AMDGPU::NoSubRegister);
8097 }
8098}
8100 MachineRegisterInfo &MRI) const {
8101 for (unsigned OpIdx = 0; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
8102 legalizeOperandsVALUt16(MI, OpIdx, MRI);
8103}
8104
8108 ArrayRef<Register> PhySGPRs) const {
8109 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8110 "This only handle waterfall for SI_CALL_ISEL");
8111 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
8112 // following copies, we also need to move copies from and to physical
8113 // registers into the loop block.
8114 // Also move the copies to physical registers into the loop block
8115 MachineBasicBlock &MBB = *MI->getParent();
8117 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8118 --Start;
8120 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8121 ++End;
8122
8123 // Also include following copies of the return value
8124 ++End;
8125 while (End != MBB.end() && End->isCopy() &&
8126 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8127 ++End;
8128
8129 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
8130}
8131
8133 MachineDominatorTree *MDT) const {
8135 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
8136 while (!Worklist.empty()) {
8137 MachineInstr &Inst = *Worklist.top();
8138 Worklist.erase_top();
8139 // Skip MachineInstr in the deferred list.
8140 if (Worklist.isDeferred(&Inst))
8141 continue;
8142 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8143 }
8144
8145 // Deferred list of instructions will be processed once
8146 // all the MachineInstr in the worklist are done.
8147 for (MachineInstr *Inst : Worklist.getDeferredList()) {
8148 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8149 assert(Worklist.empty() &&
8150 "Deferred MachineInstr are not supposed to re-populate worklist");
8151 }
8152
8153 for (auto &Entry : WaterFalls) {
8154 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8155 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
8156 Entry.second.SGPRs);
8157 }
8158
8159 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8160 if (Entry.second)
8161 Entry.first->eraseFromParent();
8162}
8164 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
8165 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
8166 // hope for the best.
8167 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
8168 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
8169 if (SubRegIndices.size() <= 1) {
8170 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8171 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8172 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8173 .add(Inst.getOperand(1));
8174 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
8175 DstReg)
8176 .addReg(NewDst);
8177 } else {
8179 for (int16_t Indice : SubRegIndices) {
8180 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8181 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8182 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8183 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
8184
8185 DstRegs.push_back(NewDst);
8186 }
8188 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8189 get(AMDGPU::REG_SEQUENCE), DstReg);
8190 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
8191 MIB.addReg(DstRegs[i]);
8192 MIB.addImm(RI.getSubRegFromChannel(i));
8193 }
8194 }
8195}
8196
8198 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
8201 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8202 if (DstReg == AMDGPU::M0) {
8203 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8204 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8205 return;
8206 }
8207 Register SrcReg = Inst.getOperand(1).getReg();
8210 // Only search current block since phyreg's def & use cannot cross
8211 // blocks when MF.NoPhi = false.
8212 while (++I != E) {
8213 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
8214 // and record the operand for later waterfall loop generation.
8215 if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8216 MachineInstr *UseMI = &*I;
8217 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
8218 if (UseMI->getOperand(i).isReg() &&
8219 UseMI->getOperand(i).getReg() == DstReg) {
8220 MachineOperand *MO = &UseMI->getOperand(i);
8221 MO->setReg(SrcReg);
8222 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
8223 V2SCopyInfo.MOs.push_back(MO);
8224 V2SCopyInfo.SGPRs.push_back(DstReg);
8225 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8226 }
8227 }
8228 } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8229 I->getOperand(0).isReg() &&
8230 I->getOperand(0).getReg() == DstReg) {
8231 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8232 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8233 } else if (I->readsRegister(DstReg, &RI)) {
8234 // COPY cannot be erased if other type of inst uses it.
8235 V2SPhyCopiesToErase[&Inst] = false;
8236 }
8237 if (I->findRegisterDefOperand(DstReg, &RI))
8238 break;
8239 }
8240}
8241
8243 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
8245 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8246
8248 if (!MBB)
8249 return;
8250 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
8251 unsigned Opcode = Inst.getOpcode();
8252 unsigned NewOpcode = getVALUOp(Inst);
8253 const DebugLoc &DL = Inst.getDebugLoc();
8254
8255 // Handle some special cases
8256 switch (Opcode) {
8257 default:
8258 break;
8259 case AMDGPU::S_ADD_I32:
8260 case AMDGPU::S_SUB_I32: {
8261 // FIXME: The u32 versions currently selected use the carry.
8262 bool Changed;
8263 MachineBasicBlock *CreatedBBTmp = nullptr;
8264 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8265 if (Changed)
8266 return;
8267
8268 // Default handling
8269 break;
8270 }
8271
8272 case AMDGPU::S_MUL_U64:
8273 if (ST.useVMulU64Inst()) {
8274 NewOpcode = AMDGPU::V_MUL_U64_e64;
8275 break;
8276 }
8277 // Split s_mul_u64 in 32-bit vector multiplications.
8278 splitScalarSMulU64(Worklist, Inst, MDT);
8279 Inst.eraseFromParent();
8280 return;
8281
8282 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8283 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8284 // This is a special case of s_mul_u64 where all the operands are either
8285 // zero extended or sign extended.
8286 splitScalarSMulPseudo(Worklist, Inst, MDT);
8287 Inst.eraseFromParent();
8288 return;
8289
8290 case AMDGPU::S_AND_B64:
8291 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8292 Inst.eraseFromParent();
8293 return;
8294
8295 case AMDGPU::S_OR_B64:
8296 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8297 Inst.eraseFromParent();
8298 return;
8299
8300 case AMDGPU::S_XOR_B64:
8301 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8302 Inst.eraseFromParent();
8303 return;
8304
8305 case AMDGPU::S_NAND_B64:
8306 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8307 Inst.eraseFromParent();
8308 return;
8309
8310 case AMDGPU::S_NOR_B64:
8311 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8312 Inst.eraseFromParent();
8313 return;
8314
8315 case AMDGPU::S_XNOR_B64:
8316 if (ST.hasDLInsts())
8317 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8318 else
8319 splitScalar64BitXnor(Worklist, Inst, MDT);
8320 Inst.eraseFromParent();
8321 return;
8322
8323 case AMDGPU::S_ANDN2_B64:
8324 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8325 Inst.eraseFromParent();
8326 return;
8327
8328 case AMDGPU::S_ORN2_B64:
8329 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8330 Inst.eraseFromParent();
8331 return;
8332
8333 case AMDGPU::S_BREV_B64:
8334 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8335 Inst.eraseFromParent();
8336 return;
8337
8338 case AMDGPU::S_NOT_B64:
8339 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8340 Inst.eraseFromParent();
8341 return;
8342
8343 case AMDGPU::S_BCNT1_I32_B64:
8344 splitScalar64BitBCNT(Worklist, Inst);
8345 Inst.eraseFromParent();
8346 return;
8347
8348 case AMDGPU::S_BFE_I64:
8349 splitScalar64BitBFE(Worklist, Inst);
8350 Inst.eraseFromParent();
8351 return;
8352
8353 case AMDGPU::S_FLBIT_I32_B64:
8354 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8355 Inst.eraseFromParent();
8356 return;
8357 case AMDGPU::S_FF1_I32_B64:
8358 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8359 Inst.eraseFromParent();
8360 return;
8361
8362 case AMDGPU::S_LSHL_B32:
8363 if (ST.hasOnlyRevVALUShifts()) {
8364 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8365 swapOperands(Inst);
8366 }
8367 break;
8368 case AMDGPU::S_ASHR_I32:
8369 if (ST.hasOnlyRevVALUShifts()) {
8370 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8371 swapOperands(Inst);
8372 }
8373 break;
8374 case AMDGPU::S_LSHR_B32:
8375 if (ST.hasOnlyRevVALUShifts()) {
8376 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8377 swapOperands(Inst);
8378 }
8379 break;
8380 case AMDGPU::S_LSHL_B64:
8381 if (ST.hasOnlyRevVALUShifts()) {
8382 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8383 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8384 : AMDGPU::V_LSHLREV_B64_e64;
8385 swapOperands(Inst);
8386 }
8387 break;
8388 case AMDGPU::S_ASHR_I64:
8389 if (ST.hasOnlyRevVALUShifts()) {
8390 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8391 swapOperands(Inst);
8392 }
8393 break;
8394 case AMDGPU::S_LSHR_B64:
8395 if (ST.hasOnlyRevVALUShifts()) {
8396 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8397 swapOperands(Inst);
8398 }
8399 break;
8400
8401 case AMDGPU::S_ABS_I32:
8402 lowerScalarAbs(Worklist, Inst);
8403 Inst.eraseFromParent();
8404 return;
8405
8406 case AMDGPU::S_ABSDIFF_I32:
8407 lowerScalarAbsDiff(Worklist, Inst);
8408 Inst.eraseFromParent();
8409 return;
8410
8411 case AMDGPU::S_CBRANCH_SCC0:
8412 case AMDGPU::S_CBRANCH_SCC1: {
8413 // Clear unused bits of vcc
8414 Register CondReg = Inst.getOperand(1).getReg();
8415 bool IsSCC = CondReg == AMDGPU::SCC;
8417 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8418 .addReg(LMC.ExecReg)
8419 .addReg(IsSCC ? LMC.VccReg : CondReg);
8420 Inst.removeOperand(1);
8421 } break;
8422
8423 case AMDGPU::S_BFE_U64:
8424 case AMDGPU::S_BFM_B64:
8425 llvm_unreachable("Moving this op to VALU not implemented");
8426
8427 case AMDGPU::S_PACK_LL_B32_B16:
8428 case AMDGPU::S_PACK_LH_B32_B16:
8429 case AMDGPU::S_PACK_HL_B32_B16:
8430 case AMDGPU::S_PACK_HH_B32_B16:
8431 movePackToVALU(Worklist, MRI, Inst);
8432 Inst.eraseFromParent();
8433 return;
8434
8435 case AMDGPU::S_XNOR_B32:
8436 lowerScalarXnor(Worklist, Inst);
8437 Inst.eraseFromParent();
8438 return;
8439
8440 case AMDGPU::S_NAND_B32:
8441 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8442 Inst.eraseFromParent();
8443 return;
8444
8445 case AMDGPU::S_NOR_B32:
8446 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8447 Inst.eraseFromParent();
8448 return;
8449
8450 case AMDGPU::S_ANDN2_B32:
8451 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8452 Inst.eraseFromParent();
8453 return;
8454
8455 case AMDGPU::S_ORN2_B32:
8456 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8457 Inst.eraseFromParent();
8458 return;
8459
8460 // TODO: remove as soon as everything is ready
8461 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8462 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8463 // can only be selected from the uniform SDNode.
8464 case AMDGPU::S_ADD_CO_PSEUDO:
8465 case AMDGPU::S_SUB_CO_PSEUDO: {
8466 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8467 ? AMDGPU::V_ADDC_U32_e64
8468 : AMDGPU::V_SUBB_U32_e64;
8469 const auto *CarryRC = RI.getWaveMaskRegClass();
8470
8471 Register CarryInReg = Inst.getOperand(4).getReg();
8472 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8473 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8474 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8475 .addReg(CarryInReg);
8476 }
8477
8478 Register CarryOutReg = Inst.getOperand(1).getReg();
8479
8480 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8481 MRI.getRegClass(Inst.getOperand(0).getReg())));
8482 MachineInstr *CarryOp =
8483 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8484 .addReg(CarryOutReg, RegState::Define)
8485 .add(Inst.getOperand(2))
8486 .add(Inst.getOperand(3))
8487 .addReg(CarryInReg)
8488 .addImm(0);
8489 legalizeOperands(*CarryOp);
8490 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8491 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8492 Inst.eraseFromParent();
8493 }
8494 return;
8495 case AMDGPU::S_UADDO_PSEUDO:
8496 case AMDGPU::S_USUBO_PSEUDO: {
8497 MachineOperand &Dest0 = Inst.getOperand(0);
8498 MachineOperand &Dest1 = Inst.getOperand(1);
8499 MachineOperand &Src0 = Inst.getOperand(2);
8500 MachineOperand &Src1 = Inst.getOperand(3);
8501
8502 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8503 ? AMDGPU::V_ADD_CO_U32_e64
8504 : AMDGPU::V_SUB_CO_U32_e64;
8505 const TargetRegisterClass *NewRC =
8506 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8507 Register DestReg = MRI.createVirtualRegister(NewRC);
8508 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8509 .addReg(Dest1.getReg(), RegState::Define)
8510 .add(Src0)
8511 .add(Src1)
8512 .addImm(0); // clamp bit
8513
8514 legalizeOperands(*NewInstr, MDT);
8515 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8516 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8517 Inst.eraseFromParent();
8518 }
8519 return;
8520 case AMDGPU::S_LSHL1_ADD_U32:
8521 case AMDGPU::S_LSHL2_ADD_U32:
8522 case AMDGPU::S_LSHL3_ADD_U32:
8523 case AMDGPU::S_LSHL4_ADD_U32: {
8524 MachineOperand &Dest = Inst.getOperand(0);
8525 MachineOperand &Src0 = Inst.getOperand(1);
8526 MachineOperand &Src1 = Inst.getOperand(2);
8527 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8528 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8529 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8530 : 4);
8531
8532 const TargetRegisterClass *NewRC =
8533 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8534 Register DestReg = MRI.createVirtualRegister(NewRC);
8535 MachineInstr *NewInstr =
8536 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8537 .add(Src0)
8538 .addImm(ShiftAmt)
8539 .add(Src1);
8540
8541 legalizeOperands(*NewInstr, MDT);
8542 MRI.replaceRegWith(Dest.getReg(), DestReg);
8543 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8544 Inst.eraseFromParent();
8545 }
8546 return;
8547 case AMDGPU::S_CSELECT_B32:
8548 case AMDGPU::S_CSELECT_B64:
8549 lowerSelect(Worklist, Inst, MDT);
8550 Inst.eraseFromParent();
8551 return;
8552 case AMDGPU::S_CMP_EQ_I32:
8553 case AMDGPU::S_CMP_LG_I32:
8554 case AMDGPU::S_CMP_GT_I32:
8555 case AMDGPU::S_CMP_GE_I32:
8556 case AMDGPU::S_CMP_LT_I32:
8557 case AMDGPU::S_CMP_LE_I32:
8558 case AMDGPU::S_CMP_EQ_U32:
8559 case AMDGPU::S_CMP_LG_U32:
8560 case AMDGPU::S_CMP_GT_U32:
8561 case AMDGPU::S_CMP_GE_U32:
8562 case AMDGPU::S_CMP_LT_U32:
8563 case AMDGPU::S_CMP_LE_U32:
8564 case AMDGPU::S_CMP_EQ_U64:
8565 case AMDGPU::S_CMP_LG_U64:
8566 case AMDGPU::S_CMP_LT_F32:
8567 case AMDGPU::S_CMP_EQ_F32:
8568 case AMDGPU::S_CMP_LE_F32:
8569 case AMDGPU::S_CMP_GT_F32:
8570 case AMDGPU::S_CMP_LG_F32:
8571 case AMDGPU::S_CMP_GE_F32:
8572 case AMDGPU::S_CMP_O_F32:
8573 case AMDGPU::S_CMP_U_F32:
8574 case AMDGPU::S_CMP_NGE_F32:
8575 case AMDGPU::S_CMP_NLG_F32:
8576 case AMDGPU::S_CMP_NGT_F32:
8577 case AMDGPU::S_CMP_NLE_F32:
8578 case AMDGPU::S_CMP_NEQ_F32:
8579 case AMDGPU::S_CMP_NLT_F32: {
8580 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8581 auto NewInstr =
8582 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8583 .setMIFlags(Inst.getFlags());
8584 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8585 0) {
8586 NewInstr
8587 .addImm(0) // src0_modifiers
8588 .add(Inst.getOperand(0)) // src0
8589 .addImm(0) // src1_modifiers
8590 .add(Inst.getOperand(1)) // src1
8591 .addImm(0); // clamp
8592 } else {
8593 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8594 }
8595 legalizeOperands(*NewInstr, MDT);
8596 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8597 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8598 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8599 Inst.eraseFromParent();
8600 return;
8601 }
8602 case AMDGPU::S_CMP_LT_F16:
8603 case AMDGPU::S_CMP_EQ_F16:
8604 case AMDGPU::S_CMP_LE_F16:
8605 case AMDGPU::S_CMP_GT_F16:
8606 case AMDGPU::S_CMP_LG_F16:
8607 case AMDGPU::S_CMP_GE_F16:
8608 case AMDGPU::S_CMP_O_F16:
8609 case AMDGPU::S_CMP_U_F16:
8610 case AMDGPU::S_CMP_NGE_F16:
8611 case AMDGPU::S_CMP_NLG_F16:
8612 case AMDGPU::S_CMP_NGT_F16:
8613 case AMDGPU::S_CMP_NLE_F16:
8614 case AMDGPU::S_CMP_NEQ_F16:
8615 case AMDGPU::S_CMP_NLT_F16: {
8616 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8617 auto NewInstr =
8618 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8619 .setMIFlags(Inst.getFlags());
8620 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8621 NewInstr
8622 .addImm(0) // src0_modifiers
8623 .add(Inst.getOperand(0)) // src0
8624 .addImm(0) // src1_modifiers
8625 .add(Inst.getOperand(1)) // src1
8626 .addImm(0); // clamp
8627 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8628 NewInstr.addImm(0); // op_sel0
8629 } else {
8630 NewInstr
8631 .add(Inst.getOperand(0))
8632 .add(Inst.getOperand(1));
8633 }
8634 legalizeOperands(*NewInstr, MDT);
8635 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8636 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8637 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8638 Inst.eraseFromParent();
8639 return;
8640 }
8641 case AMDGPU::S_CVT_HI_F32_F16: {
8642 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8643 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8644 if (ST.useRealTrue16Insts()) {
8645 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8646 .add(Inst.getOperand(1));
8647 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8648 .addImm(0) // src0_modifiers
8649 .addReg(TmpReg, {}, AMDGPU::hi16)
8650 .addImm(0) // clamp
8651 .addImm(0) // omod
8652 .addImm(0); // op_sel0
8653 } else {
8654 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8655 .addImm(16)
8656 .add(Inst.getOperand(1));
8657 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8658 .addImm(0) // src0_modifiers
8659 .addReg(TmpReg)
8660 .addImm(0) // clamp
8661 .addImm(0); // omod
8662 }
8663
8664 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8665 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8666 Inst.eraseFromParent();
8667 return;
8668 }
8669 case AMDGPU::S_MINIMUM_F32:
8670 case AMDGPU::S_MAXIMUM_F32: {
8671 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8672 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8673 .addImm(0) // src0_modifiers
8674 .add(Inst.getOperand(1))
8675 .addImm(0) // src1_modifiers
8676 .add(Inst.getOperand(2))
8677 .addImm(0) // clamp
8678 .addImm(0); // omod
8679 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8680
8681 legalizeOperands(*NewInstr, MDT);
8682 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8683 Inst.eraseFromParent();
8684 return;
8685 }
8686 case AMDGPU::S_MINIMUM_F16:
8687 case AMDGPU::S_MAXIMUM_F16: {
8688 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8689 ? &AMDGPU::VGPR_16RegClass
8690 : &AMDGPU::VGPR_32RegClass);
8691 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8692 .addImm(0) // src0_modifiers
8693 .add(Inst.getOperand(1))
8694 .addImm(0) // src1_modifiers
8695 .add(Inst.getOperand(2))
8696 .addImm(0) // clamp
8697 .addImm(0) // omod
8698 .addImm(0); // opsel0
8699 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8700 legalizeOperands(*NewInstr, MDT);
8701 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8702 Inst.eraseFromParent();
8703 return;
8704 }
8705 case AMDGPU::V_S_EXP_F16_e64:
8706 case AMDGPU::V_S_LOG_F16_e64:
8707 case AMDGPU::V_S_RCP_F16_e64:
8708 case AMDGPU::V_S_RSQ_F16_e64:
8709 case AMDGPU::V_S_SQRT_F16_e64: {
8710 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8711 ? &AMDGPU::VGPR_16RegClass
8712 : &AMDGPU::VGPR_32RegClass);
8713 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8714 .add(Inst.getOperand(1)) // src0_modifiers
8715 .add(Inst.getOperand(2))
8716 .add(Inst.getOperand(3)) // clamp
8717 .add(Inst.getOperand(4)) // omod
8718 .setMIFlags(Inst.getFlags());
8719 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8720 NewInstr.addImm(0); // opsel0
8721 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8722 legalizeOperands(*NewInstr, MDT);
8723 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8724 Inst.eraseFromParent();
8725 return;
8726 }
8727 }
8728
8729 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8730 // We cannot move this instruction to the VALU, so we should try to
8731 // legalize its operands instead.
8732 legalizeOperands(Inst, MDT);
8733 return;
8734 }
8735 // Handle converting generic instructions like COPY-to-SGPR into
8736 // COPY-to-VGPR.
8737 if (NewOpcode == Opcode) {
8738 Register DstReg = Inst.getOperand(0).getReg();
8739 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8740
8741 if (Inst.isCopy() && DstReg.isPhysical() &&
8742 Inst.getOperand(1).getReg().isVirtual()) {
8743 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8744 V2SPhyCopiesToErase);
8745 return;
8746 }
8747
8748 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8749 Register NewDstReg = Inst.getOperand(1).getReg();
8750 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8751 if (const TargetRegisterClass *CommonRC =
8752 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8753 // Instead of creating a copy where src and dst are the same register
8754 // class, we just replace all uses of dst with src. These kinds of
8755 // copies interfere with the heuristics MachineSink uses to decide
8756 // whether or not to split a critical edge. Since the pass assumes
8757 // that copies will end up as machine instructions and not be
8758 // eliminated.
8759 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8760 unsigned SrcSubReg = Inst.getOperand(1).getSubReg();
8761 bool IsUndef = Inst.getOperand(1).isUndef();
8762 for (MachineOperand &UseMO :
8763 make_early_inc_range(MRI.use_operands(DstReg))) {
8764 UseMO.setSubReg(
8765 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8766 UseMO.setReg(NewDstReg);
8767 if (IsUndef)
8768 UseMO.setIsUndef();
8769 }
8770 MRI.clearKillFlags(NewDstReg);
8771
8772 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8773 llvm_unreachable("failed to constrain register");
8774
8775 Inst.eraseFromParent();
8776
8777 for (MachineOperand &UseMO :
8778 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8779 MachineInstr &UseMI = *UseMO.getParent();
8780
8781 // Legalize t16 operands since replaceReg is called after
8782 // addUsersToVALU.
8784
8785 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
8786 if (const TargetRegisterClass *OpRC =
8787 getRegClass(UseMI.getDesc(), OpIdx))
8788 MRI.constrainRegClass(NewDstReg, OpRC);
8789 }
8790
8791 return;
8792 }
8793 }
8794
8795 // If this is a v2s copy between 16bit and 32bit reg,
8796 // replace vgpr copy to reg_sequence/extract_subreg
8797 // This can be remove after we have sgpr16 in place
8798 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
8799 Inst.getOperand(1).getReg().isVirtual() &&
8800 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
8801 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
8802 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8803 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8804 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8805 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8806 get(AMDGPU::IMPLICIT_DEF), Undef);
8807 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8808 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8809 .addReg(Inst.getOperand(1).getReg())
8810 .addImm(AMDGPU::lo16)
8811 .addReg(Undef)
8812 .addImm(AMDGPU::hi16);
8813 Inst.eraseFromParent();
8814 MRI.replaceRegWith(DstReg, NewDstReg);
8815 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8816 return;
8817 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8818 AMDGPU::lo16)) {
8819 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
8820 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8821 MRI.replaceRegWith(DstReg, NewDstReg);
8822 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8823 return;
8824 }
8825 }
8826
8827 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8828 MRI.replaceRegWith(DstReg, NewDstReg);
8829 legalizeOperands(Inst, MDT);
8830 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8831 return;
8832 }
8833
8834 // Use the new VALU Opcode.
8835 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
8836 .setMIFlags(Inst.getFlags());
8837 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
8838 // Intersperse VOP3 modifiers among the SALU operands.
8839 NewInstr->addOperand(Inst.getOperand(0));
8840 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8841 AMDGPU::OpName::src0_modifiers) >= 0)
8842 NewInstr.addImm(0);
8843 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
8844 const MachineOperand &Src = Inst.getOperand(1);
8845 NewInstr->addOperand(Src);
8846 }
8847
8848 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8849 // We are converting these to a BFE, so we need to add the missing
8850 // operands for the size and offset.
8851 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8852 NewInstr.addImm(0);
8853 NewInstr.addImm(Size);
8854 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8855 // The VALU version adds the second operand to the result, so insert an
8856 // extra 0 operand.
8857 NewInstr.addImm(0);
8858 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8859 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
8860 // If we need to move this to VGPRs, we need to unpack the second
8861 // operand back into the 2 separate ones for bit offset and width.
8862 assert(OffsetWidthOp.isImm() &&
8863 "Scalar BFE is only implemented for constant width and offset");
8864 uint32_t Imm = OffsetWidthOp.getImm();
8865
8866 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
8867 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
8868 NewInstr.addImm(Offset);
8869 NewInstr.addImm(BitWidth);
8870 } else {
8871 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8872 AMDGPU::OpName::src1_modifiers) >= 0)
8873 NewInstr.addImm(0);
8874 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8875 NewInstr->addOperand(Inst.getOperand(2));
8876 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8877 AMDGPU::OpName::src2_modifiers) >= 0)
8878 NewInstr.addImm(0);
8879 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8880 NewInstr->addOperand(Inst.getOperand(3));
8881 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8882 NewInstr.addImm(0);
8883 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8884 NewInstr.addImm(0);
8885 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8886 NewInstr.addImm(0);
8887 }
8888 } else {
8889 // Just copy the SALU operands.
8890 for (const MachineOperand &Op : Inst.explicit_operands())
8891 NewInstr->addOperand(Op);
8892 }
8893
8894 // Remove any references to SCC. Vector instructions can't read from it, and
8895 // We're just about to add the implicit use / defs of VCC, and we don't want
8896 // both.
8897 for (MachineOperand &Op : Inst.implicit_operands()) {
8898 if (Op.getReg() == AMDGPU::SCC) {
8899 // Only propagate through live-def of SCC.
8900 if (Op.isDef() && !Op.isDead())
8901 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
8902 if (Op.isUse())
8903 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8904 }
8905 }
8906 Inst.eraseFromParent();
8907 Register NewDstReg;
8908 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8909 Register DstReg = NewInstr->getOperand(0).getReg();
8910 assert(DstReg.isVirtual());
8911 // Update the destination register class.
8912 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
8913 assert(NewDstRC);
8914 NewDstReg = MRI.createVirtualRegister(NewDstRC);
8915 MRI.replaceRegWith(DstReg, NewDstReg);
8916 }
8917 fixImplicitOperands(*NewInstr);
8918
8919 // Legalize the operands
8920 legalizeOperands(*NewInstr, MDT);
8921 if (NewDstReg)
8922 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8923}
8924
8925// Add/sub require special handling to deal with carry outs.
8926std::pair<bool, MachineBasicBlock *>
8927SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
8928 MachineDominatorTree *MDT) const {
8929 if (ST.hasAddNoCarryInsts()) {
8930 // Assume there is no user of scc since we don't select this in that case.
8931 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
8932 // is used.
8933
8934 MachineBasicBlock &MBB = *Inst.getParent();
8935 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8936
8937 Register OldDstReg = Inst.getOperand(0).getReg();
8938 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8939
8940 unsigned Opc = Inst.getOpcode();
8941 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
8942
8943 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
8944 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8945
8946 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
8947 Inst.removeOperand(3);
8948
8949 Inst.setDesc(get(NewOpc));
8950 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
8951 Inst.addImplicitDefUseOperands(*MBB.getParent());
8952 MRI.replaceRegWith(OldDstReg, ResultReg);
8953 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
8954
8955 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8956 return std::pair(true, NewBB);
8957 }
8958
8959 return std::pair(false, nullptr);
8960}
8961
8962void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
8963 MachineDominatorTree *MDT) const {
8964
8965 MachineBasicBlock &MBB = *Inst.getParent();
8966 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8967 MachineBasicBlock::iterator MII = Inst;
8968 const DebugLoc &DL = Inst.getDebugLoc();
8969
8970 MachineOperand &Dest = Inst.getOperand(0);
8971 MachineOperand &Src0 = Inst.getOperand(1);
8972 MachineOperand &Src1 = Inst.getOperand(2);
8973 MachineOperand &Cond = Inst.getOperand(3);
8974
8975 Register CondReg = Cond.getReg();
8976 bool IsSCC = (CondReg == AMDGPU::SCC);
8977
8978 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
8979 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
8980 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
8981 // output directly into the V_CNDMASK.
8982 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
8983 (Src1.getImm() == 0)) {
8984 for (MachineOperand &UseMO :
8986 MachineInstr &UseMI = *UseMO.getParent();
8987 switch (UseMI.getOpcode()) {
8988 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8989 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8990 case AMDGPU::V_CNDMASK_B16_t16_e32:
8991 case AMDGPU::V_CNDMASK_B16_t16_e64:
8992 case AMDGPU::V_CNDMASK_B32_e32:
8993 case AMDGPU::V_CNDMASK_B32_e64:
8994 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8995 if (UseMO.isImplicit() ||
8996 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
8997 UseMO.setReg(CondReg);
8998 }
8999 }
9000 if (MRI.use_nodbg_empty(Dest.getReg()))
9001 return;
9002 }
9003
9004 Register NewCondReg = CondReg;
9005 if (IsSCC) {
9006 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
9007 NewCondReg = MRI.createVirtualRegister(TC);
9008
9009 // Now look for the closest SCC def if it is a copy
9010 // replacing the CondReg with the COPY source register
9011 bool CopyFound = false;
9012 for (MachineInstr &CandI :
9014 Inst.getParent()->rend())) {
9015 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
9016 -1) {
9017 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9018 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
9019 .addReg(CandI.getOperand(1).getReg());
9020 CopyFound = true;
9021 }
9022 break;
9023 }
9024 }
9025 if (!CopyFound) {
9026 // SCC def is not a copy
9027 // Insert a trivial select instead of creating a copy, because a copy from
9028 // SCC would semantically mean just copying a single bit, but we may need
9029 // the result to be a vector condition mask that needs preserving.
9030 unsigned Opcode =
9031 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9032 auto NewSelect =
9033 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
9034 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
9035 }
9036 }
9037
9038 Register NewDestReg = MRI.createVirtualRegister(
9039 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
9040 MachineInstr *NewInst;
9041 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
9042 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9043 .addImm(0)
9044 .add(Src1) // False
9045 .addImm(0)
9046 .add(Src0) // True
9047 .addReg(NewCondReg);
9048 } else {
9049 NewInst =
9050 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
9051 .add(Src1) // False
9052 .add(Src0) // True
9053 .addReg(NewCondReg);
9054 }
9055 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
9056 legalizeOperands(*NewInst, MDT);
9057 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9058}
9059
9060void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
9061 MachineInstr &Inst) const {
9062 MachineBasicBlock &MBB = *Inst.getParent();
9063 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9064 MachineBasicBlock::iterator MII = Inst;
9065 const DebugLoc &DL = Inst.getDebugLoc();
9066
9067 MachineOperand &Dest = Inst.getOperand(0);
9068 MachineOperand &Src = Inst.getOperand(1);
9069 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9070 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9071
9072 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9073 : AMDGPU::V_SUB_CO_U32_e32;
9074
9075 BuildMI(MBB, MII, DL, get(SubOp), TmpReg)
9076 .addImm(0)
9077 .addReg(Src.getReg());
9078
9079 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9080 .addReg(Src.getReg())
9081 .addReg(TmpReg);
9082
9083 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9084 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9085}
9086
9087void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
9088 MachineInstr &Inst) const {
9089 MachineBasicBlock &MBB = *Inst.getParent();
9090 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9091 MachineBasicBlock::iterator MII = Inst;
9092 const DebugLoc &DL = Inst.getDebugLoc();
9093
9094 MachineOperand &Dest = Inst.getOperand(0);
9095 MachineOperand &Src1 = Inst.getOperand(1);
9096 MachineOperand &Src2 = Inst.getOperand(2);
9097 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9098 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9099 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9100
9101 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9102 : AMDGPU::V_SUB_CO_U32_e32;
9103
9104 BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
9105 .addReg(Src1.getReg())
9106 .addReg(Src2.getReg());
9107
9108 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
9109
9110 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9111 .addReg(SubResultReg)
9112 .addReg(TmpReg);
9113
9114 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9115 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9116}
9117
9118void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
9119 MachineInstr &Inst) const {
9120 MachineBasicBlock &MBB = *Inst.getParent();
9121 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9122 MachineBasicBlock::iterator MII = Inst;
9123 const DebugLoc &DL = Inst.getDebugLoc();
9124
9125 MachineOperand &Dest = Inst.getOperand(0);
9126 MachineOperand &Src0 = Inst.getOperand(1);
9127 MachineOperand &Src1 = Inst.getOperand(2);
9128
9129 if (ST.hasDLInsts()) {
9130 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9131 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
9132 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
9133
9134 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
9135 .add(Src0)
9136 .add(Src1);
9137
9138 MRI.replaceRegWith(Dest.getReg(), NewDest);
9139 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9140 } else {
9141 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
9142 // invert either source and then perform the XOR. If either source is a
9143 // scalar register, then we can leave the inversion on the scalar unit to
9144 // achieve a better distribution of scalar and vector instructions.
9145 bool Src0IsSGPR = Src0.isReg() &&
9146 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
9147 bool Src1IsSGPR = Src1.isReg() &&
9148 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
9149 MachineInstr *Xor;
9150 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9151 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9152
9153 // Build a pair of scalar instructions and add them to the work list.
9154 // The next iteration over the work list will lower these to the vector
9155 // unit as necessary.
9156 if (Src0IsSGPR) {
9157 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
9158 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9159 .addReg(Temp)
9160 .add(Src1);
9161 } else if (Src1IsSGPR) {
9162 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
9163 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9164 .add(Src0)
9165 .addReg(Temp);
9166 } else {
9167 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
9168 .add(Src0)
9169 .add(Src1);
9170 MachineInstr *Not =
9171 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
9172 Worklist.insert(Not);
9173 }
9174
9175 MRI.replaceRegWith(Dest.getReg(), NewDest);
9176
9177 Worklist.insert(Xor);
9178
9179 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9180 }
9181}
9182
9183void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
9184 MachineInstr &Inst,
9185 unsigned Opcode) const {
9186 MachineBasicBlock &MBB = *Inst.getParent();
9187 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9188 MachineBasicBlock::iterator MII = Inst;
9189 const DebugLoc &DL = Inst.getDebugLoc();
9190
9191 MachineOperand &Dest = Inst.getOperand(0);
9192 MachineOperand &Src0 = Inst.getOperand(1);
9193 MachineOperand &Src1 = Inst.getOperand(2);
9194
9195 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9196 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9197
9198 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
9199 .add(Src0)
9200 .add(Src1);
9201
9202 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
9203 .addReg(Interm);
9204
9205 Worklist.insert(&Op);
9206 Worklist.insert(&Not);
9207
9208 MRI.replaceRegWith(Dest.getReg(), NewDest);
9209 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9210}
9211
9212void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
9213 MachineInstr &Inst,
9214 unsigned Opcode) const {
9215 MachineBasicBlock &MBB = *Inst.getParent();
9216 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9217 MachineBasicBlock::iterator MII = Inst;
9218 const DebugLoc &DL = Inst.getDebugLoc();
9219
9220 MachineOperand &Dest = Inst.getOperand(0);
9221 MachineOperand &Src0 = Inst.getOperand(1);
9222 MachineOperand &Src1 = Inst.getOperand(2);
9223
9224 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9225 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9226
9227 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
9228 .add(Src1);
9229
9230 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
9231 .add(Src0)
9232 .addReg(Interm);
9233
9234 Worklist.insert(&Not);
9235 Worklist.insert(&Op);
9236
9237 MRI.replaceRegWith(Dest.getReg(), NewDest);
9238 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9239}
9240
9241void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
9242 MachineInstr &Inst, unsigned Opcode,
9243 bool Swap) const {
9244 MachineBasicBlock &MBB = *Inst.getParent();
9245 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9246
9247 MachineOperand &Dest = Inst.getOperand(0);
9248 MachineOperand &Src0 = Inst.getOperand(1);
9249 const DebugLoc &DL = Inst.getDebugLoc();
9250
9251 MachineBasicBlock::iterator MII = Inst;
9252
9253 const MCInstrDesc &InstDesc = get(Opcode);
9254 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9255 MRI.getRegClass(Src0.getReg()) :
9256 &AMDGPU::SGPR_32RegClass;
9257
9258 const TargetRegisterClass *Src0SubRC =
9259 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9260
9261 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9262 AMDGPU::sub0, Src0SubRC);
9263
9264 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9265 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9266 const TargetRegisterClass *NewDestSubRC =
9267 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9268
9269 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9270 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
9271
9272 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9273 AMDGPU::sub1, Src0SubRC);
9274
9275 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9276 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
9277
9278 if (Swap)
9279 std::swap(DestSub0, DestSub1);
9280
9281 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9282 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9283 .addReg(DestSub0)
9284 .addImm(AMDGPU::sub0)
9285 .addReg(DestSub1)
9286 .addImm(AMDGPU::sub1);
9287
9288 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9289
9290 Worklist.insert(&LoHalf);
9291 Worklist.insert(&HiHalf);
9292
9293 // We don't need to legalizeOperands here because for a single operand, src0
9294 // will support any kind of input.
9295
9296 // Move all users of this moved value.
9297 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9298}
9299
9300// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9301// split the s_mul_u64 in 32-bit vector multiplications.
9302void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9303 MachineInstr &Inst,
9304 MachineDominatorTree *MDT) const {
9305 MachineBasicBlock &MBB = *Inst.getParent();
9306 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9307
9308 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9309 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9310 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9311
9312 MachineOperand &Dest = Inst.getOperand(0);
9313 MachineOperand &Src0 = Inst.getOperand(1);
9314 MachineOperand &Src1 = Inst.getOperand(2);
9315 const DebugLoc &DL = Inst.getDebugLoc();
9316 MachineBasicBlock::iterator MII = Inst;
9317
9318 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9319 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9320 const TargetRegisterClass *Src0SubRC =
9321 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9322 if (RI.isSGPRClass(Src0SubRC))
9323 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9324 const TargetRegisterClass *Src1SubRC =
9325 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9326 if (RI.isSGPRClass(Src1SubRC))
9327 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9328
9329 // First, we extract the low 32-bit and high 32-bit values from each of the
9330 // operands.
9331 MachineOperand Op0L =
9332 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9333 MachineOperand Op1L =
9334 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9335 MachineOperand Op0H =
9336 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9337 MachineOperand Op1H =
9338 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9339
9340 // The multilication is done as follows:
9341 //
9342 // Op1H Op1L
9343 // * Op0H Op0L
9344 // --------------------
9345 // Op1H*Op0L Op1L*Op0L
9346 // + Op1H*Op0H Op1L*Op0H
9347 // -----------------------------------------
9348 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9349 //
9350 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9351 // value and that would overflow.
9352 // The low 32-bit value is Op1L*Op0L.
9353 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9354
9355 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9356 MachineInstr *Op1L_Op0H =
9357 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9358 .add(Op1L)
9359 .add(Op0H);
9360
9361 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9362 MachineInstr *Op1H_Op0L =
9363 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9364 .add(Op1H)
9365 .add(Op0L);
9366
9367 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9368 MachineInstr *Carry =
9369 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9370 .add(Op1L)
9371 .add(Op0L);
9372
9373 MachineInstr *LoHalf =
9374 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9375 .add(Op1L)
9376 .add(Op0L);
9377
9378 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9379 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9380 .addReg(Op1L_Op0H_Reg)
9381 .addReg(Op1H_Op0L_Reg);
9382
9383 MachineInstr *HiHalf =
9384 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9385 .addReg(AddReg)
9386 .addReg(CarryReg);
9387
9388 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9389 .addReg(DestSub0)
9390 .addImm(AMDGPU::sub0)
9391 .addReg(DestSub1)
9392 .addImm(AMDGPU::sub1);
9393
9394 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9395
9396 // Try to legalize the operands in case we need to swap the order to keep it
9397 // valid.
9398 legalizeOperands(*Op1L_Op0H, MDT);
9399 legalizeOperands(*Op1H_Op0L, MDT);
9400 legalizeOperands(*Carry, MDT);
9401 legalizeOperands(*LoHalf, MDT);
9402 legalizeOperands(*Add, MDT);
9403 legalizeOperands(*HiHalf, MDT);
9404
9405 // Move all users of this moved value.
9406 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9407}
9408
9409// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9410// multiplications.
9411void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9412 MachineInstr &Inst,
9413 MachineDominatorTree *MDT) const {
9414 MachineBasicBlock &MBB = *Inst.getParent();
9415 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9416
9417 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9418 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9419 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9420
9421 MachineOperand &Dest = Inst.getOperand(0);
9422 MachineOperand &Src0 = Inst.getOperand(1);
9423 MachineOperand &Src1 = Inst.getOperand(2);
9424 const DebugLoc &DL = Inst.getDebugLoc();
9425 MachineBasicBlock::iterator MII = Inst;
9426
9427 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9428 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9429 const TargetRegisterClass *Src0SubRC =
9430 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9431 if (RI.isSGPRClass(Src0SubRC))
9432 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9433 const TargetRegisterClass *Src1SubRC =
9434 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9435 if (RI.isSGPRClass(Src1SubRC))
9436 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9437
9438 // First, we extract the low 32-bit and high 32-bit values from each of the
9439 // operands.
9440 MachineOperand Op0L =
9441 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9442 MachineOperand Op1L =
9443 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9444
9445 unsigned Opc = Inst.getOpcode();
9446 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9447 ? AMDGPU::V_MUL_HI_U32_e64
9448 : AMDGPU::V_MUL_HI_I32_e64;
9449 MachineInstr *HiHalf =
9450 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9451
9452 MachineInstr *LoHalf =
9453 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9454 .add(Op1L)
9455 .add(Op0L);
9456
9457 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9458 .addReg(DestSub0)
9459 .addImm(AMDGPU::sub0)
9460 .addReg(DestSub1)
9461 .addImm(AMDGPU::sub1);
9462
9463 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9464
9465 // Try to legalize the operands in case we need to swap the order to keep it
9466 // valid.
9467 legalizeOperands(*HiHalf, MDT);
9468 legalizeOperands(*LoHalf, MDT);
9469
9470 // Move all users of this moved value.
9471 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9472}
9473
9474void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9475 MachineInstr &Inst, unsigned Opcode,
9476 MachineDominatorTree *MDT) const {
9477 MachineBasicBlock &MBB = *Inst.getParent();
9478 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9479
9480 MachineOperand &Dest = Inst.getOperand(0);
9481 MachineOperand &Src0 = Inst.getOperand(1);
9482 MachineOperand &Src1 = Inst.getOperand(2);
9483 const DebugLoc &DL = Inst.getDebugLoc();
9484
9485 MachineBasicBlock::iterator MII = Inst;
9486
9487 const MCInstrDesc &InstDesc = get(Opcode);
9488 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9489 MRI.getRegClass(Src0.getReg()) :
9490 &AMDGPU::SGPR_32RegClass;
9491
9492 const TargetRegisterClass *Src0SubRC =
9493 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9494 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9495 MRI.getRegClass(Src1.getReg()) :
9496 &AMDGPU::SGPR_32RegClass;
9497
9498 const TargetRegisterClass *Src1SubRC =
9499 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9500
9501 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9502 AMDGPU::sub0, Src0SubRC);
9503 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9504 AMDGPU::sub0, Src1SubRC);
9505 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9506 AMDGPU::sub1, Src0SubRC);
9507 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9508 AMDGPU::sub1, Src1SubRC);
9509
9510 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9511 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9512 const TargetRegisterClass *NewDestSubRC =
9513 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9514
9515 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9516 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9517 .add(SrcReg0Sub0)
9518 .add(SrcReg1Sub0);
9519
9520 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9521 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9522 .add(SrcReg0Sub1)
9523 .add(SrcReg1Sub1);
9524
9525 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9526 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9527 .addReg(DestSub0)
9528 .addImm(AMDGPU::sub0)
9529 .addReg(DestSub1)
9530 .addImm(AMDGPU::sub1);
9531
9532 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9533
9534 Worklist.insert(&LoHalf);
9535 Worklist.insert(&HiHalf);
9536
9537 // Move all users of this moved value.
9538 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9539}
9540
9541void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9542 MachineInstr &Inst,
9543 MachineDominatorTree *MDT) const {
9544 MachineBasicBlock &MBB = *Inst.getParent();
9545 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9546
9547 MachineOperand &Dest = Inst.getOperand(0);
9548 MachineOperand &Src0 = Inst.getOperand(1);
9549 MachineOperand &Src1 = Inst.getOperand(2);
9550 const DebugLoc &DL = Inst.getDebugLoc();
9551
9552 MachineBasicBlock::iterator MII = Inst;
9553
9554 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9555
9556 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9557
9558 MachineOperand* Op0;
9559 MachineOperand* Op1;
9560
9561 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9562 Op0 = &Src0;
9563 Op1 = &Src1;
9564 } else {
9565 Op0 = &Src1;
9566 Op1 = &Src0;
9567 }
9568
9569 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9570 .add(*Op0);
9571
9572 Register NewDest = MRI.createVirtualRegister(DestRC);
9573
9574 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9575 .addReg(Interm)
9576 .add(*Op1);
9577
9578 MRI.replaceRegWith(Dest.getReg(), NewDest);
9579
9580 Worklist.insert(&Xor);
9581}
9582
9583void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9584 MachineInstr &Inst) const {
9585 MachineBasicBlock &MBB = *Inst.getParent();
9586 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9587
9588 MachineBasicBlock::iterator MII = Inst;
9589 const DebugLoc &DL = Inst.getDebugLoc();
9590
9591 MachineOperand &Dest = Inst.getOperand(0);
9592 MachineOperand &Src = Inst.getOperand(1);
9593
9594 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9595 const TargetRegisterClass *SrcRC = Src.isReg() ?
9596 MRI.getRegClass(Src.getReg()) :
9597 &AMDGPU::SGPR_32RegClass;
9598
9599 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9600 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9601
9602 const TargetRegisterClass *SrcSubRC =
9603 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9604
9605 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9606 AMDGPU::sub0, SrcSubRC);
9607 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9608 AMDGPU::sub1, SrcSubRC);
9609
9610 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9611
9612 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9613
9614 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9615
9616 // We don't need to legalize operands here. src0 for either instruction can be
9617 // an SGPR, and the second input is unused or determined here.
9618 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9619}
9620
9621void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9622 MachineInstr &Inst) const {
9623 MachineBasicBlock &MBB = *Inst.getParent();
9624 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9625 MachineBasicBlock::iterator MII = Inst;
9626 const DebugLoc &DL = Inst.getDebugLoc();
9627
9628 MachineOperand &Dest = Inst.getOperand(0);
9629 uint32_t Imm = Inst.getOperand(2).getImm();
9630 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9631 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9632
9633 (void) Offset;
9634
9635 // Only sext_inreg cases handled.
9636 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9637 Offset == 0 && "Not implemented");
9638
9639 if (BitWidth < 32) {
9640 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9641 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9642 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9643
9644 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9645 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9646 .addImm(0)
9647 .addImm(BitWidth);
9648
9649 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9650 .addImm(31)
9651 .addReg(MidRegLo);
9652
9653 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9654 .addReg(MidRegLo)
9655 .addImm(AMDGPU::sub0)
9656 .addReg(MidRegHi)
9657 .addImm(AMDGPU::sub1);
9658
9659 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9660 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9661 return;
9662 }
9663
9664 MachineOperand &Src = Inst.getOperand(1);
9665 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9666 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9667
9668 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9669 .addImm(31)
9670 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9671
9672 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9673 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9674 .addImm(AMDGPU::sub0)
9675 .addReg(TmpReg)
9676 .addImm(AMDGPU::sub1);
9677
9678 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9679 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9680}
9681
9682void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9683 MachineInstr &Inst, unsigned Opcode,
9684 MachineDominatorTree *MDT) const {
9685 // (S_FLBIT_I32_B64 hi:lo) ->
9686 // -> (umin (V_FFBH_U32_e32 hi), (or (V_FFBH_U32_e32 lo), 32))
9687 // (S_FF1_I32_B64 hi:lo) ->
9688 // ->(umin (or (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9689
9690 MachineBasicBlock &MBB = *Inst.getParent();
9691 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9692 MachineBasicBlock::iterator MII = Inst;
9693 const DebugLoc &DL = Inst.getDebugLoc();
9694
9695 MachineOperand &Dest = Inst.getOperand(0);
9696 MachineOperand &Src = Inst.getOperand(1);
9697
9698 const MCInstrDesc &InstDesc = get(Opcode);
9699
9700 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9701
9702 const TargetRegisterClass *SrcRC =
9703 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9704 const TargetRegisterClass *SrcSubRC =
9705 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9706
9707 MachineOperand SrcRegSub0 =
9708 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9709 MachineOperand SrcRegSub1 =
9710 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9711
9712 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9713 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9714 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9715 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9716
9717 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9718
9719 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9720
9721 BuildMI(MBB, MII, DL, get(AMDGPU::V_OR_B32_e32), MidReg3)
9722 .addImm(32)
9723 .addReg(IsCtlz ? MidReg1 : MidReg2);
9724
9725 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9726 .addReg(MidReg3)
9727 .addReg(IsCtlz ? MidReg2 : MidReg1);
9728
9729 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9730
9731 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9732}
9733
9734void SIInstrInfo::addUsersToMoveToVALUWorklist(
9735 Register DstReg, MachineRegisterInfo &MRI,
9736 SIInstrWorklist &Worklist) const {
9737 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9738 MachineInstr &UseMI = *MO.getParent();
9739
9740 unsigned OpNo = 0;
9741
9742 switch (UseMI.getOpcode()) {
9743 case AMDGPU::COPY:
9744 case AMDGPU::WQM:
9745 case AMDGPU::SOFT_WQM:
9746 case AMDGPU::STRICT_WWM:
9747 case AMDGPU::STRICT_WQM:
9748 case AMDGPU::REG_SEQUENCE:
9749 case AMDGPU::PHI:
9750 case AMDGPU::INSERT_SUBREG:
9751 break;
9752 default:
9753 OpNo = MO.getOperandNo();
9754 break;
9755 }
9756
9757 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9758 MRI.constrainRegClass(DstReg, OpRC);
9759
9760 if (!RI.hasVectorRegisters(OpRC))
9761 Worklist.insert(&UseMI);
9762 else
9763 // Legalization could change user list.
9764 legalizeOperandsVALUt16(UseMI, OpNo, MRI);
9765 }
9766}
9767
9768void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
9770 MachineInstr &Inst) const {
9771 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9772 MachineBasicBlock *MBB = Inst.getParent();
9773 MachineOperand &Src0 = Inst.getOperand(1);
9774 MachineOperand &Src1 = Inst.getOperand(2);
9775 const DebugLoc &DL = Inst.getDebugLoc();
9776
9777 if (ST.useRealTrue16Insts()) {
9778 Register SrcReg0, SrcReg1;
9779 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
9780 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9781 BuildMI(*MBB, Inst, DL,
9782 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9783 .add(Src0);
9784 } else {
9785 SrcReg0 = Src0.getReg();
9786 }
9787
9788 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
9789 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9790 BuildMI(*MBB, Inst, DL,
9791 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9792 .add(Src1);
9793 } else {
9794 SrcReg1 = Src1.getReg();
9795 }
9796
9797 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
9798 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
9799
9800 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
9801 switch (Inst.getOpcode()) {
9802 case AMDGPU::S_PACK_LL_B32_B16:
9803 NewMI
9804 .addReg(SrcReg0, {},
9805 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9806 .addImm(AMDGPU::lo16)
9807 .addReg(SrcReg1, {},
9808 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9809 .addImm(AMDGPU::hi16);
9810 break;
9811 case AMDGPU::S_PACK_LH_B32_B16:
9812 NewMI
9813 .addReg(SrcReg0, {},
9814 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9815 .addImm(AMDGPU::lo16)
9816 .addReg(SrcReg1, {}, AMDGPU::hi16)
9817 .addImm(AMDGPU::hi16);
9818 break;
9819 case AMDGPU::S_PACK_HL_B32_B16:
9820 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9821 .addImm(AMDGPU::lo16)
9822 .addReg(SrcReg1, {},
9823 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9824 .addImm(AMDGPU::hi16);
9825 break;
9826 case AMDGPU::S_PACK_HH_B32_B16:
9827 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9828 .addImm(AMDGPU::lo16)
9829 .addReg(SrcReg1, {}, AMDGPU::hi16)
9830 .addImm(AMDGPU::hi16);
9831 break;
9832 default:
9833 llvm_unreachable("unhandled s_pack_* instruction");
9834 }
9835
9836 MachineOperand &Dest = Inst.getOperand(0);
9837 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9838 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9839 return;
9840 }
9841
9842 switch (Inst.getOpcode()) {
9843 case AMDGPU::S_PACK_LL_B32_B16: {
9844 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9845 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9846
9847 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
9848 // 0.
9849 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9850 .addImm(0xffff);
9851
9852 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
9853 .addReg(ImmReg, RegState::Kill)
9854 .add(Src0);
9855
9856 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9857 .add(Src1)
9858 .addImm(16)
9859 .addReg(TmpReg, RegState::Kill);
9860 break;
9861 }
9862 case AMDGPU::S_PACK_LH_B32_B16: {
9863 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9864 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9865 .addImm(0xffff);
9866 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
9867 .addReg(ImmReg, RegState::Kill)
9868 .add(Src0)
9869 .add(Src1);
9870 break;
9871 }
9872 case AMDGPU::S_PACK_HL_B32_B16: {
9873 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9874 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9875 .addImm(16)
9876 .add(Src0);
9877 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9878 .add(Src1)
9879 .addImm(16)
9880 .addReg(TmpReg, RegState::Kill);
9881 break;
9882 }
9883 case AMDGPU::S_PACK_HH_B32_B16: {
9884 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9885 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9886 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9887 .addImm(16)
9888 .add(Src0);
9889 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9890 .addImm(0xffff0000);
9891 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
9892 .add(Src1)
9893 .addReg(ImmReg, RegState::Kill)
9894 .addReg(TmpReg, RegState::Kill);
9895 break;
9896 }
9897 default:
9898 llvm_unreachable("unhandled s_pack_* instruction");
9899 }
9900
9901 MachineOperand &Dest = Inst.getOperand(0);
9902 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9903 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9904}
9905
9906void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
9907 MachineInstr &SCCDefInst,
9908 SIInstrWorklist &Worklist,
9909 Register NewCond) const {
9910
9911 // Ensure that def inst defines SCC, which is still live.
9912 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
9913 !Op.isDead() && Op.getParent() == &SCCDefInst);
9914 SmallVector<MachineInstr *, 4> CopyToDelete;
9915 // This assumes that all the users of SCC are in the same block
9916 // as the SCC def.
9917 for (MachineInstr &MI : // Skip the def inst itself.
9918 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
9919 SCCDefInst.getParent()->end())) {
9920 // Check if SCC is used first.
9921 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
9922 if (SCCIdx != -1) {
9923 if (MI.isCopy()) {
9924 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
9925 Register DestReg = MI.getOperand(0).getReg();
9926
9927 MRI.replaceRegWith(DestReg, NewCond);
9928 CopyToDelete.push_back(&MI);
9929 } else {
9930
9931 if (NewCond.isValid())
9932 MI.getOperand(SCCIdx).setReg(NewCond);
9933
9934 Worklist.insert(&MI);
9935 }
9936 }
9937 // Exit if we find another SCC def.
9938 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
9939 break;
9940 }
9941 for (auto &Copy : CopyToDelete)
9942 Copy->eraseFromParent();
9943}
9944
9945// Instructions that use SCC may be converted to VALU instructions. When that
9946// happens, the SCC register is changed to VCC_LO. The instruction that defines
9947// SCC must be changed to an instruction that defines VCC. This function makes
9948// sure that the instruction that defines SCC is added to the moveToVALU
9949// worklist.
9950void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
9951 SIInstrWorklist &Worklist) const {
9952 // Look for a preceding instruction that either defines VCC or SCC. If VCC
9953 // then there is nothing to do because the defining instruction has been
9954 // converted to a VALU already. If SCC then that instruction needs to be
9955 // converted to a VALU.
9956 for (MachineInstr &MI :
9957 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
9958 SCCUseInst->getParent()->rend())) {
9959 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
9960 break;
9961 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
9962 Worklist.insert(&MI);
9963 break;
9964 }
9965 }
9966}
9967
9968const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
9969 const MachineInstr &Inst) const {
9970 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
9971
9972 switch (Inst.getOpcode()) {
9973 // For target instructions, getOpRegClass just returns the virtual register
9974 // class associated with the operand, so we need to find an equivalent VGPR
9975 // register class in order to move the instruction to the VALU.
9976 case AMDGPU::COPY:
9977 case AMDGPU::PHI:
9978 case AMDGPU::REG_SEQUENCE:
9979 case AMDGPU::INSERT_SUBREG:
9980 case AMDGPU::WQM:
9981 case AMDGPU::SOFT_WQM:
9982 case AMDGPU::STRICT_WWM:
9983 case AMDGPU::STRICT_WQM: {
9984 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
9985 if (RI.isAGPRClass(SrcRC)) {
9986 if (RI.isAGPRClass(NewDstRC))
9987 return nullptr;
9988
9989 switch (Inst.getOpcode()) {
9990 case AMDGPU::PHI:
9991 case AMDGPU::REG_SEQUENCE:
9992 case AMDGPU::INSERT_SUBREG:
9993 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9994 break;
9995 default:
9996 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9997 }
9998
9999 if (!NewDstRC)
10000 return nullptr;
10001 } else {
10002 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10003 return nullptr;
10004
10005 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10006 if (!NewDstRC)
10007 return nullptr;
10008 }
10009
10010 return NewDstRC;
10011 }
10012 default:
10013 return NewDstRC;
10014 }
10015}
10016
10017// Find the one SGPR operand we are allowed to use.
10018Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
10019 int OpIndices[3]) const {
10020 const MCInstrDesc &Desc = MI.getDesc();
10021
10022 // Find the one SGPR operand we are allowed to use.
10023 //
10024 // First we need to consider the instruction's operand requirements before
10025 // legalizing. Some operands are required to be SGPRs, such as implicit uses
10026 // of VCC, but we are still bound by the constant bus requirement to only use
10027 // one.
10028 //
10029 // If the operand's class is an SGPR, we can never move it.
10030
10031 Register SGPRReg = findImplicitSGPRRead(MI);
10032 if (SGPRReg)
10033 return SGPRReg;
10034
10035 Register UsedSGPRs[3] = {Register()};
10036 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10037
10038 for (unsigned i = 0; i < 3; ++i) {
10039 int Idx = OpIndices[i];
10040 if (Idx == -1)
10041 break;
10042
10043 const MachineOperand &MO = MI.getOperand(Idx);
10044 if (!MO.isReg())
10045 continue;
10046
10047 // Is this operand statically required to be an SGPR based on the operand
10048 // constraints?
10049 const TargetRegisterClass *OpRC =
10050 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
10051 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10052 if (IsRequiredSGPR)
10053 return MO.getReg();
10054
10055 // If this could be a VGPR or an SGPR, Check the dynamic register class.
10056 Register Reg = MO.getReg();
10057 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
10058 if (RI.isSGPRClass(RegRC))
10059 UsedSGPRs[i] = Reg;
10060 }
10061
10062 // We don't have a required SGPR operand, so we have a bit more freedom in
10063 // selecting operands to move.
10064
10065 // Try to select the most used SGPR. If an SGPR is equal to one of the
10066 // others, we choose that.
10067 //
10068 // e.g.
10069 // V_FMA_F32 v0, s0, s0, s0 -> No moves
10070 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
10071
10072 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
10073 // prefer those.
10074
10075 if (UsedSGPRs[0]) {
10076 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10077 SGPRReg = UsedSGPRs[0];
10078 }
10079
10080 if (!SGPRReg && UsedSGPRs[1]) {
10081 if (UsedSGPRs[1] == UsedSGPRs[2])
10082 SGPRReg = UsedSGPRs[1];
10083 }
10084
10085 return SGPRReg;
10086}
10087
10089 AMDGPU::OpName OperandName) const {
10090 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10091 return nullptr;
10092
10093 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
10094 if (Idx == -1)
10095 return nullptr;
10096
10097 return &MI.getOperand(Idx);
10098}
10099
10101 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
10102 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
10105 return (Format << 44) |
10106 (1ULL << 56) | // RESOURCE_LEVEL = 1
10107 (3ULL << 60); // OOB_SELECT = 3
10108 }
10109
10110 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
10111 if (ST.isAmdHsaOS()) {
10112 // Set ATC = 1. GFX9 doesn't have this bit.
10113 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10114 RsrcDataFormat |= (1ULL << 56);
10115
10116 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
10117 // BTW, it disables TC L2 and therefore decreases performance.
10118 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
10119 RsrcDataFormat |= (2ULL << 59);
10120 }
10121
10122 return RsrcDataFormat;
10123}
10124
10126 uint64_t Rsrc23 = getDefaultRsrcDataFormat() |
10128 0xffffffff; // Size;
10129
10130 // GFX9 doesn't have ELEMENT_SIZE.
10131 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
10132 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
10133 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
10134 }
10135
10136 // IndexStride = 64 / 32.
10137 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10138 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
10139
10140 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
10141 // Clear them unless we want a huge stride.
10142 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
10143 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
10144 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
10145
10146 return Rsrc23;
10147}
10148
10150 unsigned Opc = MI.getOpcode();
10151
10152 return isSMRD(Opc);
10153}
10154
10156 return get(Opc).mayLoad() &&
10157 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
10158}
10159
10161 TypeSize &MemBytes) const {
10162 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
10163 if (!Addr || !Addr->isFI())
10164 return Register();
10165
10166 assert(!MI.memoperands_empty() &&
10167 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
10168
10169 FrameIndex = Addr->getIndex();
10170
10171 int VDataIdx =
10172 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
10173 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
10174 return MI.getOperand(VDataIdx).getReg();
10175}
10176
10178 TypeSize &MemBytes) const {
10179 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
10180 assert(Addr && Addr->isFI());
10181 FrameIndex = Addr->getIndex();
10182
10183 int DataIdx =
10184 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
10185 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
10186 return MI.getOperand(DataIdx).getReg();
10187}
10188
10190 int &FrameIndex,
10191 TypeSize &MemBytes) const {
10192 if (!MI.mayLoad())
10193 return Register();
10194
10195 if (isMUBUF(MI) || isVGPRSpill(MI))
10196 return isStackAccess(MI, FrameIndex, MemBytes);
10197
10198 if (isSGPRSpill(MI))
10199 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10200
10201 return Register();
10202}
10203
10205 int &FrameIndex,
10206 TypeSize &MemBytes) const {
10207 if (!MI.mayStore())
10208 return Register();
10209
10210 if (isMUBUF(MI) || isVGPRSpill(MI))
10211 return isStackAccess(MI, FrameIndex, MemBytes);
10212
10213 if (isSGPRSpill(MI))
10214 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10215
10216 return Register();
10217}
10218
10220 unsigned Opc = MI.getOpcode();
10222 unsigned DescSize = Desc.getSize();
10223
10224 // If we have a definitive size, we can use it. Otherwise we need to inspect
10225 // the operands to know the size.
10226 if (isFixedSize(MI)) {
10227 unsigned Size = DescSize;
10228
10229 // If we hit the buggy offset, an extra nop will be inserted in MC so
10230 // estimate the worst case.
10231 if (MI.isBranch() && ST.hasOffset3fBug())
10232 Size += 4;
10233
10234 return Size;
10235 }
10236
10237 // Instructions may have a 32-bit literal encoded after them. Check
10238 // operands that could ever be literals.
10239 if (isVALU(MI, /*AllowLDSDMA=*/false) || isSALU(MI)) {
10240 if (isDPP(MI))
10241 return DescSize;
10242 bool HasLiteral = false;
10243 unsigned LiteralSize = 4;
10244 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
10245 const MachineOperand &Op = MI.getOperand(I);
10246 const MCOperandInfo &OpInfo = Desc.operands()[I];
10247 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
10248 HasLiteral = true;
10249 if (ST.has64BitLiterals()) {
10250 switch (OpInfo.OperandType) {
10251 default:
10252 break;
10255 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
10256 LiteralSize = 8;
10257 break;
10260 // A 32-bit literal is only valid when the value fits in BOTH signed
10261 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
10262 // emitter's getLit64Encoding logic. This is because of the lack of
10263 // abilility to tell signedness of the literal, therefore we need to
10264 // be conservative and assume values outside this range require a
10265 // 64-bit literal encoding (8 bytes).
10266 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
10267 !isUInt<32>(Op.getImm()))
10268 LiteralSize = 8;
10269 break;
10270 }
10271 }
10272 break;
10273 }
10274 }
10275 return HasLiteral ? DescSize + LiteralSize : DescSize;
10276 }
10277
10278 // Check whether we have extra NSA words.
10279 if (isMIMG(MI)) {
10280 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
10281 if (VAddr0Idx < 0)
10282 return 8;
10283
10284 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
10285 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10286 }
10287
10288 switch (Opc) {
10289 case TargetOpcode::BUNDLE:
10290 return getInstBundleSize(MI);
10291 case TargetOpcode::INLINEASM:
10292 case TargetOpcode::INLINEASM_BR: {
10293 const MachineFunction *MF = MI.getMF();
10294 const char *AsmStr = MI.getOperand(0).getSymbolName();
10295 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10296 }
10297 default:
10298 if (MI.isMetaInstruction())
10299 return 0;
10300
10301 // If D16 Pseudo inst, get correct MC code size
10302 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10303 if (D16Info) {
10304 // Assume d16_lo/hi inst are always in same size
10305 unsigned LoInstOpcode = D16Info->LoOp;
10306 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10307 DescSize = Desc.getSize();
10308 }
10309
10310 // If FMA Pseudo inst, get correct MC code size
10311 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10312 // All potential lowerings are the same size; arbitrarily pick one.
10313 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10314 DescSize = Desc.getSize();
10315 }
10316
10317 return DescSize;
10318 }
10319}
10320
10323 if (MI.isBranch() && ST.hasOffset3fBug())
10324 return InstSizeVerifyMode::NoVerify;
10325 return InstSizeVerifyMode::ExactSize;
10326}
10327
10329 if (!isFLAT(MI))
10330 return false;
10331
10332 if (MI.memoperands_empty())
10333 return true;
10334
10335 for (const MachineMemOperand *MMO : MI.memoperands()) {
10337 return true;
10338 }
10339 return false;
10340}
10341
10344 static const std::pair<int, const char *> TargetIndices[] = {
10345 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10346 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10347 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10348 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10349 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10350 return ArrayRef(TargetIndices);
10351}
10352
10353/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10354/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10357 const ScheduleDAG *DAG) const {
10358 return new GCNHazardRecognizer(DAG->MF);
10359}
10360
10361/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10362/// pass.
10369
10370// Called during:
10371// - pre-RA scheduling and post-RA scheduling
10374 const ScheduleDAGMI *DAG) const {
10375 // Borrowed from Arm Target
10376 // We would like to restrict this hazard recognizer to only
10377 // post-RA scheduling; we can tell that we're post-RA because we don't
10378 // track VRegLiveness.
10379 if (!DAG->hasVRegLiveness())
10380 return new GCNHazardRecognizer(DAG->MF);
10382}
10383
10384std::pair<unsigned, unsigned>
10386 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10387}
10388
10391 static const std::pair<unsigned, const char *> TargetFlags[] = {
10392 {MO_GOTPCREL, "amdgpu-gotprel"},
10393 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10394 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10395 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10396 {MO_REL32_LO, "amdgpu-rel32-lo"},
10397 {MO_REL32_HI, "amdgpu-rel32-hi"},
10398 {MO_REL64, "amdgpu-rel64"},
10399 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10400 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10401 {MO_ABS64, "amdgpu-abs64"},
10402 };
10403
10404 return ArrayRef(TargetFlags);
10405}
10406
10409 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10410 {
10411 {MONoClobber, "amdgpu-noclobber"},
10412 {MOLastUse, "amdgpu-last-use"},
10413 {MOCooperative, "amdgpu-cooperative"},
10414 {MOThreadPrivate, "amdgpu-thread-private"},
10415 };
10416
10417 return ArrayRef(TargetFlags);
10418}
10419
10421 const MachineFunction &MF) const {
10423 assert(SrcReg.isVirtual());
10424 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10425 return AMDGPU::WWM_COPY;
10426
10427 return AMDGPU::COPY;
10428}
10429
10431 uint32_t Opcode = MI.getOpcode();
10432 // Check if it is SGPR spill or wwm-register spill Opcode.
10433 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10434 return true;
10435
10436 const MachineFunction *MF = MI.getMF();
10437 const MachineRegisterInfo &MRI = MF->getRegInfo();
10439
10440 // See if this is Liverange split instruction inserted for SGPR or
10441 // wwm-register. The implicit def inserted for wwm-registers should also be
10442 // included as they can appear at the bb begin.
10443 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10444 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10445 return false;
10446
10447 Register Reg = MI.getOperand(0).getReg();
10448 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10449 return IsLRSplitInst;
10450
10451 return MFI->isWWMReg(Reg);
10452}
10453
10455 Register Reg) const {
10456 // We need to handle instructions which may be inserted during register
10457 // allocation to handle the prolog. The initial prolog instruction may have
10458 // been separated from the start of the block by spills and copies inserted
10459 // needed by the prolog. However, the insertions for scalar registers can
10460 // always be placed at the BB top as they are independent of the exec mask
10461 // value.
10462 bool IsNullOrVectorRegister = true;
10463 if (Reg) {
10464 const MachineFunction *MF = MI.getMF();
10465 const MachineRegisterInfo &MRI = MF->getRegInfo();
10466 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10467 }
10468
10469 return IsNullOrVectorRegister &&
10470 (canAddToBBProlog(MI) ||
10471 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10472 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10473}
10474
10478 const DebugLoc &DL,
10479 Register DestReg) const {
10480 if (ST.hasAddNoCarryInsts())
10481 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10482
10483 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10484 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10485 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10486
10487 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10488 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10489}
10490
10493 const DebugLoc &DL,
10494 Register DestReg,
10495 RegScavenger &RS) const {
10496 if (ST.hasAddNoCarryInsts())
10497 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10498
10499 // If available, prefer to use vcc.
10500 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10501 ? Register(RI.getVCC())
10502 : RS.scavengeRegisterBackwards(
10503 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10504 0, /* AllowSpill */ false);
10505
10506 // TODO: Users need to deal with this.
10507 if (!UnusedCarry.isValid())
10508 return MachineInstrBuilder();
10509
10510 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10511 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10512}
10513
10514bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10515 switch (Opcode) {
10516 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10517 case AMDGPU::SI_KILL_I1_TERMINATOR:
10518 return true;
10519 default:
10520 return false;
10521 }
10522}
10523
10525 switch (Opcode) {
10526 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10527 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10528 case AMDGPU::SI_KILL_I1_PSEUDO:
10529 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10530 default:
10531 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10532 }
10533}
10534
10536 return Imm <= getMaxMUBUFImmOffset(ST);
10537}
10538
10540 // GFX12 field is non-negative 24-bit signed byte offset.
10541 const unsigned OffsetBits =
10542 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10543 return (1 << OffsetBits) - 1;
10544}
10545
10547 if (!ST.isWave32())
10548 return;
10549
10550 if (MI.isInlineAsm())
10551 return;
10552
10553 if (MI.getNumOperands() < MI.getDesc().getNumOperands())
10554 return;
10555
10556 for (auto &Op : MI.implicit_operands()) {
10557 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10558 Op.setReg(AMDGPU::VCC_LO);
10559 }
10560}
10561
10563 if (!isSMRD(MI))
10564 return false;
10565
10566 // Check that it is using a buffer resource.
10567 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10568 if (Idx == -1) // e.g. s_memtime
10569 return false;
10570
10571 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10572 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10573}
10574
10575// Given Imm, split it into the values to put into the SOffset and ImmOffset
10576// fields in an MUBUF instruction. Return false if it is not possible (due to a
10577// hardware bug needing a workaround).
10578//
10579// The required alignment ensures that individual address components remain
10580// aligned if they are aligned to begin with. It also ensures that additional
10581// offsets within the given alignment can be added to the resulting ImmOffset.
10583 uint32_t &ImmOffset, Align Alignment) const {
10584 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10585 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10586 uint32_t Overflow = 0;
10587
10588 if (Imm > MaxImm) {
10589 if (Imm <= MaxImm + 64) {
10590 // Use an SOffset inline constant for 4..64
10591 Overflow = Imm - MaxImm;
10592 Imm = MaxImm;
10593 } else {
10594 // Try to keep the same value in SOffset for adjacent loads, so that
10595 // the corresponding register contents can be re-used.
10596 //
10597 // Load values with all low-bits (except for alignment bits) set into
10598 // SOffset, so that a larger range of values can be covered using
10599 // s_movk_i32.
10600 //
10601 // Atomic operations fail to work correctly when individual address
10602 // components are unaligned, even if their sum is aligned.
10603 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10604 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10605 Imm = Low;
10606 Overflow = High - Alignment.value();
10607 }
10608 }
10609
10610 if (Overflow > 0) {
10611 // There is a hardware bug in SI and CI which prevents address clamping in
10612 // MUBUF instructions from working correctly with SOffsets. The immediate
10613 // offset is unaffected.
10614 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10615 return false;
10616
10617 // It is not possible to set immediate in SOffset field on some targets.
10618 if (ST.hasRestrictedSOffset())
10619 return false;
10620 }
10621
10622 ImmOffset = Imm;
10623 SOffset = Overflow;
10624 return true;
10625}
10626
10627// Depending on the used address space and instructions, some immediate offsets
10628// are allowed and some are not.
10629// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10630// scratch instruction offsets can also be negative. On GFX12, offsets can be
10631// negative for all variants.
10632//
10633// There are several bugs related to these offsets:
10634// On gfx10.1, flat instructions that go into the global address space cannot
10635// use an offset.
10636//
10637// For scratch instructions, the address can be either an SGPR or a VGPR.
10638// The following offsets can be used, depending on the architecture (x means
10639// cannot be used):
10640// +----------------------------+------+------+
10641// | Address-Mode | SGPR | VGPR |
10642// +----------------------------+------+------+
10643// | gfx9 | | |
10644// | negative, 4-aligned offset | x | ok |
10645// | negative, unaligned offset | x | ok |
10646// +----------------------------+------+------+
10647// | gfx10 | | |
10648// | negative, 4-aligned offset | ok | ok |
10649// | negative, unaligned offset | ok | x |
10650// +----------------------------+------+------+
10651// | gfx10.3 | | |
10652// | negative, 4-aligned offset | ok | ok |
10653// | negative, unaligned offset | ok | ok |
10654// +----------------------------+------+------+
10655//
10656// This function ignores the addressing mode, so if an offset cannot be used in
10657// one addressing mode, it is considered illegal.
10658bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10659 AMDGPU::FlatAddrSpace FlatVariant) const {
10660 // TODO: Should 0 be special cased?
10661 if (!ST.hasFlatInstOffsets())
10662 return false;
10663
10665 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10666 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10667 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10668 return false;
10669
10670 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10671 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10672 (Offset % 4) != 0) {
10673 return false;
10674 }
10675
10676 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10677 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10678 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10679}
10680
10681// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10682std::pair<int64_t, int64_t>
10683SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10684 AMDGPU::FlatAddrSpace FlatVariant) const {
10685 int64_t RemainderOffset = COffsetVal;
10686 int64_t ImmField = 0;
10687
10688 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10689 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10690
10691 if (AllowNegative) {
10692 // Use signed division by a power of two to truncate towards 0.
10693 int64_t D = 1LL << NumBits;
10694 RemainderOffset = (COffsetVal / D) * D;
10695 ImmField = COffsetVal - RemainderOffset;
10696
10697 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10698 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10699 (ImmField % 4) != 0) {
10700 // Make ImmField a multiple of 4
10701 RemainderOffset += ImmField % 4;
10702 ImmField -= ImmField % 4;
10703 }
10704 } else if (COffsetVal >= 0) {
10705 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10706 RemainderOffset = COffsetVal - ImmField;
10707 }
10708
10709 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10710 assert(RemainderOffset + ImmField == COffsetVal);
10711 return {ImmField, RemainderOffset};
10712}
10713
10715 AMDGPU::FlatAddrSpace FlatVariant) const {
10716 if (ST.hasNegativeScratchOffsetBug() &&
10718 return false;
10719
10720 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10721}
10722
10723static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10724 switch (ST.getGeneration()) {
10725 default:
10726 break;
10729 return SIEncodingFamily::SI;
10732 return SIEncodingFamily::VI;
10736 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10739 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10743 }
10744 llvm_unreachable("Unknown subtarget generation!");
10745}
10746
10747bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10748 switch(MCOp) {
10749 // These opcodes use indirect register addressing so
10750 // they need special handling by codegen (currently missing).
10751 // Therefore it is too risky to allow these opcodes
10752 // to be selected by dpp combiner or sdwa peepholer.
10753 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10754 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10755 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10756 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10757 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10758 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10759 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10760 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10761 return true;
10762 default:
10763 return false;
10764 }
10765}
10766
10767#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10768 case OPCODE##_dpp: \
10769 case OPCODE##_e32: \
10770 case OPCODE##_e64: \
10771 case OPCODE##_e64_dpp: \
10772 case OPCODE##_sdwa:
10773
10774static bool isRenamedInGFX9(int Opcode) {
10775 switch (Opcode) {
10776 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
10777 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
10778 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
10779 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
10780 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
10781 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
10782 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
10783 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
10784 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
10785 //
10786 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10787 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10788 case AMDGPU::V_FMA_F16_gfx9_e64:
10789 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10790 case AMDGPU::V_INTERP_P2_F16:
10791 case AMDGPU::V_MAD_F16_e64:
10792 case AMDGPU::V_MAD_U16_e64:
10793 case AMDGPU::V_MAD_I16_e64:
10794 return true;
10795 default:
10796 return false;
10797 }
10798}
10799
10800int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
10801 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
10802 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10803
10804 unsigned Gen = subtargetEncodingFamily(ST);
10805
10806 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
10808
10809 // Adjust the encoding family to GFX80 for D16 buffer instructions when the
10810 // subtarget has UnpackedD16VMem feature.
10811 // TODO: remove this when we discard GFX80 encoding.
10812 if (ST.hasUnpackedD16VMem() && SIInstrFlags::isD16Buf(get(Opcode)))
10814
10815 if (SIInstrFlags::isSDWA(get(Opcode))) {
10816 switch (ST.getGeneration()) {
10817 default:
10819 break;
10822 break;
10825 break;
10826 }
10827 }
10828
10829 if (isMAI(Opcode)) {
10830 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
10831 if (MFMAOp != -1)
10832 Opcode = MFMAOp;
10833 }
10834
10835 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
10836
10837 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10839
10840 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10842
10843 // -1 means that Opcode is already a native instruction.
10844 if (MCOp == -1)
10845 return Opcode;
10846
10847 if (ST.hasGFX90AInsts()) {
10848 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10849 if (ST.hasGFX940Insts())
10851 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10853 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10855 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10856 MCOp = NMCOp;
10857 }
10858
10859 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
10860 // encoding in the given subtarget generation.
10861 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10862 return -1;
10863
10864 if (isAsmOnlyOpcode(MCOp))
10865 return -1;
10866
10867 return MCOp;
10868}
10869
10870static
10872 assert(RegOpnd.isReg());
10873 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
10874 getRegSubRegPair(RegOpnd);
10875}
10876
10879 assert(MI.isRegSequence());
10880 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
10881 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
10882 auto &RegOp = MI.getOperand(1 + 2 * I);
10883 return getRegOrUndef(RegOp);
10884 }
10886}
10887
10888// Try to find the definition of reg:subreg in subreg-manipulation pseudos
10889// Following a subreg of reg:subreg isn't supported
10892 if (!RSR.SubReg)
10893 return false;
10894 switch (MI.getOpcode()) {
10895 default: break;
10896 case AMDGPU::REG_SEQUENCE:
10897 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
10898 return true;
10899 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
10900 case AMDGPU::INSERT_SUBREG:
10901 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
10902 // inserted the subreg we're looking for
10903 RSR = getRegOrUndef(MI.getOperand(2));
10904 else { // the subreg in the rest of the reg
10905 auto R1 = getRegOrUndef(MI.getOperand(1));
10906 if (R1.SubReg) // subreg of subreg isn't supported
10907 return false;
10908 RSR.Reg = R1.Reg;
10909 }
10910 return true;
10911 }
10912 return false;
10913}
10914
10916 const MachineRegisterInfo &MRI) {
10917 assert(MRI.isSSA());
10918 if (!P.Reg.isVirtual())
10919 return nullptr;
10920
10921 auto RSR = P;
10922 auto *DefInst = MRI.getVRegDef(RSR.Reg);
10923 while (auto *MI = DefInst) {
10924 DefInst = nullptr;
10925 switch (MI->getOpcode()) {
10926 case AMDGPU::COPY:
10927 case AMDGPU::V_MOV_B32_e32: {
10928 auto &Op1 = MI->getOperand(1);
10929 if (Op1.isReg() && Op1.getReg().isVirtual()) {
10930 if (Op1.isUndef())
10931 return nullptr;
10932 RSR = getRegSubRegPair(Op1);
10933 DefInst = MRI.getVRegDef(RSR.Reg);
10934 }
10935 break;
10936 }
10937 default:
10938 if (followSubRegDef(*MI, RSR)) {
10939 if (!RSR.Reg)
10940 return nullptr;
10941 DefInst = MRI.getVRegDef(RSR.Reg);
10942 }
10943 }
10944 if (!DefInst)
10945 return MI;
10946 }
10947 return nullptr;
10948}
10949
10951 Register VReg,
10952 const MachineInstr &DefMI,
10953 const MachineInstr &UseMI) {
10954 assert(MRI.isSSA() && "Must be run on SSA");
10955
10956 auto *TRI = MRI.getTargetRegisterInfo();
10957 auto *DefBB = DefMI.getParent();
10958
10959 // Don't bother searching between blocks, although it is possible this block
10960 // doesn't modify exec.
10961 if (UseMI.getParent() != DefBB)
10962 return true;
10963
10964 const int MaxInstScan = 20;
10965 int NumInst = 0;
10966
10967 // Stop scan at the use.
10968 auto E = UseMI.getIterator();
10969 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
10970 if (I->isDebugInstr())
10971 continue;
10972
10973 if (++NumInst > MaxInstScan)
10974 return true;
10975
10976 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
10977 return true;
10978 }
10979
10980 return false;
10981}
10982
10984 Register VReg,
10985 const MachineInstr &DefMI) {
10986 assert(MRI.isSSA() && "Must be run on SSA");
10987
10988 auto *TRI = MRI.getTargetRegisterInfo();
10989 auto *DefBB = DefMI.getParent();
10990
10991 const int MaxUseScan = 10;
10992 int NumUse = 0;
10993
10994 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
10995 auto &UseInst = *Use.getParent();
10996 // Don't bother searching between blocks, although it is possible this block
10997 // doesn't modify exec.
10998 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10999 return true;
11000
11001 if (++NumUse > MaxUseScan)
11002 return true;
11003 }
11004
11005 if (NumUse == 0)
11006 return false;
11007
11008 const int MaxInstScan = 20;
11009 int NumInst = 0;
11010
11011 // Stop scan when we have seen all the uses.
11012 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
11013 assert(I != DefBB->end());
11014
11015 if (I->isDebugInstr())
11016 continue;
11017
11018 if (++NumInst > MaxInstScan)
11019 return true;
11020
11021 for (const MachineOperand &Op : I->operands()) {
11022 // We don't check reg masks here as they're used only on calls:
11023 // 1. EXEC is only considered const within one BB
11024 // 2. Call should be a terminator instruction if present in a BB
11025
11026 if (!Op.isReg())
11027 continue;
11028
11029 Register Reg = Op.getReg();
11030 if (Op.isUse()) {
11031 if (Reg == VReg && --NumUse == 0)
11032 return false;
11033 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
11034 return true;
11035 }
11036 }
11037}
11038
11041 const DebugLoc &DL, Register Src, Register Dst) const {
11042 auto Cur = MBB.begin();
11043 if (Cur != MBB.end())
11044 do {
11045 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
11046 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
11047 ++Cur;
11048 } while (Cur != MBB.end() && Cur != LastPHIIt);
11049
11050 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
11051 Dst);
11052}
11053
11056 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
11057 if (InsPt != MBB.end() &&
11058 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11059 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11060 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11061 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
11062 InsPt++;
11063 return BuildMI(MBB, InsPt, DL,
11064 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
11065 .addReg(Src, {}, SrcSubReg)
11066 .addReg(AMDGPU::EXEC, RegState::Implicit);
11067 }
11068 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
11069 Dst);
11070}
11071
11072bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
11073
11075 const MachineInstr &SecondMI) const {
11076 for (const auto &Use : SecondMI.all_uses()) {
11077 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
11078 return true;
11079 }
11080 return false;
11081}
11082
11083/// If OpX is multicycle, anti-dependencies are not allowed.
11084/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
11085/// purpose.
11087 const MachineInstr &OpX) const {
11089}
11090
11093 ArrayRef<unsigned> Ops, int FrameIndex,
11094 MachineInstr *&CopyMI, LiveIntervals *LIS,
11095 VirtRegMap *VRM) const {
11096 // This is a bit of a hack (copied from AArch64). Consider this instruction:
11097 //
11098 // %0:sreg_32 = COPY $m0
11099 //
11100 // We explicitly chose SReg_32 for the virtual register so such a copy might
11101 // be eliminated by RegisterCoalescer. However, that may not be possible, and
11102 // %0 may even spill. We can't spill $m0 normally (it would require copying to
11103 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
11104 // TargetInstrInfo::foldMemoryOperand() is going to try.
11105 // A similar issue also exists with spilling and reloading $exec registers.
11106 //
11107 // To prevent that, constrain the %0 register class here.
11108 if (isFullCopyInstr(MI)) {
11109 Register DstReg = MI.getOperand(0).getReg();
11110 Register SrcReg = MI.getOperand(1).getReg();
11111 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
11112 (DstReg.isVirtual() != SrcReg.isVirtual())) {
11113 MachineRegisterInfo &MRI = MF.getRegInfo();
11114 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
11115 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
11116 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
11117 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11118 return nullptr;
11119 }
11120 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
11121 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11122 return nullptr;
11123 }
11124 }
11125 }
11126
11127 return nullptr;
11128}
11129
11131 const MachineInstr &MI,
11132 unsigned *PredCost) const {
11133 if (MI.isBundle()) {
11135 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
11136 unsigned Lat = 0, Count = 0;
11137 for (++I; I != E && I->isBundledWithPred(); ++I) {
11138 ++Count;
11139 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
11140 }
11141 return Lat + Count - 1;
11142 }
11143
11144 return SchedModel.computeInstrLatency(&MI);
11145}
11146
11147const MachineOperand &
11149 if (const MachineOperand *CallAddrOp =
11150 getNamedOperand(MI, AMDGPU::OpName::src0))
11151 return *CallAddrOp;
11153}
11154
11157 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11158 unsigned Opcode = MI.getOpcode();
11159
11160 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
11161 Register Dst = MI.getOperand(0).getReg();
11162 Register Src = MI.getOperand(1).getReg();
11163 LLT DstTy = MRI.getType(Dst);
11164 LLT SrcTy = MRI.getType(Src);
11165 unsigned DstAS = DstTy.getAddressSpace();
11166 unsigned SrcAS = SrcTy.getAddressSpace();
11167 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
11168 DstAS == AMDGPUAS::FLAT_ADDRESS &&
11169 ST.hasGloballyAddressableScratch()
11172 };
11173
11174 // If the target supports globally addressable scratch, the mapping from
11175 // scratch memory to the flat aperture changes therefore an address space cast
11176 // is no longer uniform.
11177 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11178 return HandleAddrSpaceCast(MI);
11179
11180 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
11181 auto IID = GI->getIntrinsicID();
11186
11187 switch (IID) {
11188 case Intrinsic::amdgcn_if:
11189 case Intrinsic::amdgcn_else:
11190 // FIXME: Uniform if second result
11191 break;
11192 }
11193
11195 }
11196
11197 // Loads from the private and flat address spaces are divergent, because
11198 // threads can execute the load instruction with the same inputs and get
11199 // different results.
11200 //
11201 // All other loads are not divergent, because if threads issue loads with the
11202 // same arguments, they will always get the same result.
11203 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11204 Opcode == AMDGPU::G_SEXTLOAD) {
11205 if (MI.memoperands_empty())
11206 return ValueUniformity::NeverUniform; // conservative assumption
11207
11208 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11209 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11210 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11211 })) {
11212 // At least one MMO in a non-global address space.
11214 }
11216 }
11217
11218 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11219 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11220 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11221 AMDGPU::isGenericAtomic(Opcode)) {
11223 }
11224
11225 // Result is computed from uniform SP and uniform wave-wide max size.
11226 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11228
11229 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11231
11233}
11234
11236 if (!Formatter)
11237 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11238 return Formatter.get();
11239}
11240
11242
11243 if (isNeverUniform(MI))
11245
11246 unsigned opcode = MI.getOpcode();
11247 if (opcode == AMDGPU::V_READLANE_B32 ||
11248 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11249 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11251
11252 // If any of defs is divergent, report as NeverUniform. isUniformReg will
11253 // calculate in more detail for each def from its reg class, if available.
11254 if (MI.isInlineAsm()) {
11255 for (const MachineOperand &MO : MI.operands()) {
11256 if (!MO.isReg() || !MO.isDef())
11257 continue;
11258 const TargetRegisterClass *RC =
11259 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
11260 if (!RC || !RI.isSGPRClass(RC))
11262 }
11263 }
11264
11265 if (isCopyInstr(MI)) {
11266 const MachineOperand &srcOp = MI.getOperand(1);
11267 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
11268 const TargetRegisterClass *regClass =
11269 RI.getPhysRegBaseClass(srcOp.getReg());
11270 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
11272 }
11274 }
11275
11276 // GMIR handling
11277 if (MI.isPreISelOpcode())
11279
11280 // Atomics are divergent because they are executed sequentially: when an
11281 // atomic operation refers to the same address in each thread, then each
11282 // thread after the first sees the value written by the previous thread as
11283 // original value.
11284
11285 if (isAtomic(MI))
11287
11288 // Loads from the private and flat address spaces are divergent, because
11289 // threads can execute the load instruction with the same inputs and get
11290 // different results.
11291 if (isFLAT(MI) && MI.mayLoad()) {
11292 if (MI.memoperands_empty())
11293 return ValueUniformity::NeverUniform; // conservative assumption
11294
11295 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11296 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11297 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11298 })) {
11299 // At least one MMO in a non-global address space.
11301 }
11302
11304 }
11305
11306 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11307 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11308
11309 // FIXME: It's conceptually broken to report this for an instruction, and not
11310 // a specific def operand. For inline asm in particular, there could be mixed
11311 // uniform and divergent results.
11312 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11313 const MachineOperand &SrcOp = MI.getOperand(I);
11314 if (!SrcOp.isReg())
11315 continue;
11316
11317 Register Reg = SrcOp.getReg();
11318 if (!Reg || !SrcOp.readsReg())
11319 continue;
11320
11321 // If RegBank is null, this is unassigned or an unallocatable special
11322 // register, which are all scalars.
11323 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11324 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11326 }
11327
11328 // TODO: Uniformity check condtions above can be rearranged for more
11329 // redability
11330
11331 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11332 // currently turned into no-op COPYs by SelectionDAG ISel and are
11333 // therefore no longer recognizable.
11334
11336}
11337
11339 switch (MF.getFunction().getCallingConv()) {
11341 return 1;
11343 return 2;
11345 return 3;
11349 const Function &F = MF.getFunction();
11350 F.getContext().diagnose(DiagnosticInfoUnsupported(
11351 F, "ds_ordered_count unsupported for this calling conv"));
11352 [[fallthrough]];
11353 }
11356 case CallingConv::C:
11357 case CallingConv::Fast:
11358 default:
11359 // Assume other calling conventions are various compute callable functions
11360 return 0;
11361 }
11362}
11363
11365 Register &SrcReg2, int64_t &CmpMask,
11366 int64_t &CmpValue) const {
11367 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11368 return false;
11369
11370 switch (MI.getOpcode()) {
11371 default:
11372 break;
11373 case AMDGPU::S_CMP_EQ_U32:
11374 case AMDGPU::S_CMP_EQ_I32:
11375 case AMDGPU::S_CMP_LG_U32:
11376 case AMDGPU::S_CMP_LG_I32:
11377 case AMDGPU::S_CMP_LT_U32:
11378 case AMDGPU::S_CMP_LT_I32:
11379 case AMDGPU::S_CMP_GT_U32:
11380 case AMDGPU::S_CMP_GT_I32:
11381 case AMDGPU::S_CMP_LE_U32:
11382 case AMDGPU::S_CMP_LE_I32:
11383 case AMDGPU::S_CMP_GE_U32:
11384 case AMDGPU::S_CMP_GE_I32:
11385 case AMDGPU::S_CMP_EQ_U64:
11386 case AMDGPU::S_CMP_LG_U64:
11387 SrcReg = MI.getOperand(0).getReg();
11388 if (MI.getOperand(1).isReg()) {
11389 if (MI.getOperand(1).getSubReg())
11390 return false;
11391 SrcReg2 = MI.getOperand(1).getReg();
11392 CmpValue = 0;
11393 } else if (MI.getOperand(1).isImm()) {
11394 SrcReg2 = Register();
11395 CmpValue = MI.getOperand(1).getImm();
11396 } else {
11397 return false;
11398 }
11399 CmpMask = ~0;
11400 return true;
11401 case AMDGPU::S_CMPK_EQ_U32:
11402 case AMDGPU::S_CMPK_EQ_I32:
11403 case AMDGPU::S_CMPK_LG_U32:
11404 case AMDGPU::S_CMPK_LG_I32:
11405 case AMDGPU::S_CMPK_LT_U32:
11406 case AMDGPU::S_CMPK_LT_I32:
11407 case AMDGPU::S_CMPK_GT_U32:
11408 case AMDGPU::S_CMPK_GT_I32:
11409 case AMDGPU::S_CMPK_LE_U32:
11410 case AMDGPU::S_CMPK_LE_I32:
11411 case AMDGPU::S_CMPK_GE_U32:
11412 case AMDGPU::S_CMPK_GE_I32:
11413 SrcReg = MI.getOperand(0).getReg();
11414 SrcReg2 = Register();
11415 CmpValue = MI.getOperand(1).getImm();
11416 CmpMask = ~0;
11417 return true;
11418 }
11419
11420 return false;
11421}
11422
11424 for (MachineBasicBlock *S : MBB->successors()) {
11425 if (S->isLiveIn(AMDGPU::SCC))
11426 return false;
11427 }
11428 return true;
11429}
11430
11431// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11432// (incoming SCC) = !(SCC defined by SCCDef).
11433// Return true if all uses can be re-written, false otherwise.
11434bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11435 MachineBasicBlock *MBB = SCCDef->getParent();
11436 SmallVector<MachineInstr *> InvertInstr;
11437 bool SCCIsDead = false;
11438
11439 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11440 constexpr unsigned ScanLimit = 12;
11441 unsigned Count = 0;
11442 for (MachineInstr &MI :
11443 make_range(std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11444 if (++Count > ScanLimit)
11445 return false;
11446 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11447 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11448 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11449 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11450 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11451 InvertInstr.push_back(&MI);
11452 else
11453 return false;
11454 }
11455 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11456 SCCIsDead = true;
11457 break;
11458 }
11459 }
11460 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11461 SCCIsDead = true;
11462
11463 // SCC may have more uses. Can't invert all of them.
11464 if (!SCCIsDead)
11465 return false;
11466
11467 // Invert uses
11468 for (MachineInstr *MI : InvertInstr) {
11469 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11470 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11471 swapOperands(*MI);
11472 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11473 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11474 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11475 ? AMDGPU::S_CBRANCH_SCC1
11476 : AMDGPU::S_CBRANCH_SCC0));
11477 } else {
11478 llvm_unreachable("SCC used but no inversion handling");
11479 }
11480 }
11481 return true;
11482}
11483
11484// SCC is already valid after SCCValid.
11485// SCCRedefine will redefine SCC to the same value already available after
11486// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11487// update kill/dead flags if necessary.
11488bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11489 bool NeedInversion) const {
11490 MachineInstr *KillsSCC = nullptr;
11491 if (SCCValid->getParent() != SCCRedefine->getParent())
11492 return false;
11493 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11494 SCCRedefine->getIterator())) {
11495 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11496 return false;
11497 if (MI.killsRegister(AMDGPU::SCC, &RI))
11498 KillsSCC = &MI;
11499 }
11500 if (NeedInversion && !invertSCCUse(SCCRedefine))
11501 return false;
11502 if (MachineOperand *SccDef =
11503 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11504 SccDef->setIsDead(false);
11505 if (KillsSCC)
11506 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11507 SCCRedefine->eraseFromParent();
11508 return true;
11509}
11510
11511static bool foldableSelect(const MachineInstr &Def) {
11512 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11513 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11514 return false;
11515 bool Op1IsNonZeroImm =
11516 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11517 bool Op2IsZeroImm =
11518 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11519 return Op1IsNonZeroImm && Op2IsZeroImm;
11520}
11521
11522static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11523 unsigned &NewDefOpc) {
11524 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11525 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11526 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11527 Def.getOpcode() != AMDGPU::S_ADD_U32)
11528 return false;
11529 const MachineOperand &AddSrc1 = Def.getOperand(1);
11530 const MachineOperand &AddSrc2 = Def.getOperand(2);
11531 const MachineRegisterInfo &MRI = Def.getMF()->getRegInfo();
11532 const SIInstrInfo *TII = static_cast<const SIInstrInfo *>(
11533 Def.getMF()->getSubtarget().getInstrInfo());
11534
11535 auto Imm1 = TII->getImmOrMaterializedImm(MRI, AddSrc1);
11536 auto Imm2 = TII->getImmOrMaterializedImm(MRI, AddSrc2);
11537 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11538 return false;
11539
11540 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11541 const MachineOperand *SccDef =
11542 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11543 if (!SccDef->isDead())
11544 return false;
11545 NewDefOpc = AMDGPU::S_ADD_U32;
11546 }
11547 NeedInversion = !NeedInversion;
11548 return true;
11549}
11550
11552 Register SrcReg2, int64_t CmpMask,
11553 int64_t CmpValue,
11554 const MachineRegisterInfo *MRI) const {
11555 if (!SrcReg || SrcReg.isPhysical())
11556 return false;
11557
11558 if (SrcReg2) {
11559 auto ImmOpt = getImmOrMaterializedImm(*MRI, SrcReg2);
11560 if (!ImmOpt)
11561 return false;
11562 CmpValue = *ImmOpt;
11563 }
11564
11565 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11566 this](bool NeedInversion) -> bool {
11567 if (CmpValue != 0)
11568 return false;
11569
11570 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11571 if (!Def)
11572 return false;
11573
11574 // For S_OP that set SCC = DST!=0, do the transformation
11575 //
11576 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11577 //
11578 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11579 // do the transformation:
11580 //
11581 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11582 //
11583 // If foldableSelect, s_cmp_lg_* is redundant because the SCC input value
11584 // for S_CSELECT* already has the same value that will be calculated by
11585 // s_cmp_lg_*
11586 //
11587 // s_cmp_[lg|eq]_* (S_CSELECT* (non-zero imm), 0), 0 => (S_CSELECT*
11588 // (non-zero imm), 0)
11589
11590 unsigned NewDefOpc = Def->getOpcode();
11591 if (!setsSCCIfResultIsNonZero(*Def) &&
11592 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc) &&
11593 !foldableSelect(*Def))
11594 return false;
11595
11596 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11597 return false;
11598
11599 if (NewDefOpc != Def->getOpcode())
11600 Def->setDesc(get(NewDefOpc));
11601
11602 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11603 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11604 // 64-bit foldableSelect then delete s_or_b32 in the sequence:
11605 // sX = s_cselect_b64 (non-zero imm), 0
11606 // sLo = copy sX.sub0
11607 // sHi = copy sX.sub1
11608 // sY = s_or_b32 sLo, sHi
11609 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11610 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11611 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11612 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11613 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11614 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11615 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11616 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11617 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11618 Def2->getOperand(1).isReg() &&
11619 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11620 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11621 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11622 MachineInstr *Select = MRI->getVRegDef(Def1->getOperand(1).getReg());
11623 if (Select && foldableSelect(*Select))
11624 optimizeSCC(Select, Def, /*NeedInversion=*/false);
11625 }
11626 }
11627 }
11628 return true;
11629 };
11630
11631 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11632 this](int64_t ExpectedValue, unsigned SrcSize,
11633 bool IsReversible, bool IsSigned) -> bool {
11634 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11635 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11636 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11637 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11638 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11639 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11640 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11641 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11642 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11643 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11644 //
11645 // Signed ge/gt are not used for the sign bit.
11646 //
11647 // If result of the AND is unused except in the compare:
11648 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11649 //
11650 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11651 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11652 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11653 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11654 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11655 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11656
11657 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11658 if (!Def)
11659 return false;
11660
11661 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11662 Def->getOpcode() != AMDGPU::S_AND_B64)
11663 return false;
11664
11665 int64_t Mask;
11666 const auto isMask = [&Mask, SrcSize, MRI,
11667 this](const MachineOperand *MO) -> bool {
11668 auto ImmOpt = this->getImmOrMaterializedImm(*MRI, *MO);
11669 if (!ImmOpt)
11670 return false;
11671 Mask = *ImmOpt;
11672 Mask &= maxUIntN(SrcSize);
11673 return isPowerOf2_64(Mask);
11674 };
11675
11676 MachineOperand *SrcOp = &Def->getOperand(1);
11677 if (isMask(SrcOp))
11678 SrcOp = &Def->getOperand(2);
11679 else if (isMask(&Def->getOperand(2)))
11680 SrcOp = &Def->getOperand(1);
11681 else
11682 return false;
11683
11684 // A valid Mask is required to have a single bit set, hence a non-zero and
11685 // power-of-two value. This verifies that we will not do 64-bit shift below.
11686 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11687 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11688 if (IsSigned && BitNo == SrcSize - 1)
11689 return false;
11690
11691 ExpectedValue <<= BitNo;
11692
11693 bool IsReversedCC = false;
11694 if (CmpValue != ExpectedValue) {
11695 if (!IsReversible)
11696 return false;
11697 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11698 if (!IsReversedCC)
11699 return false;
11700 }
11701
11702 Register DefReg = Def->getOperand(0).getReg();
11703 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11704 return false;
11705
11706 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11707 return false;
11708
11709 if (!MRI->use_nodbg_empty(DefReg)) {
11710 assert(!IsReversedCC);
11711 return true;
11712 }
11713
11714 // Replace AND with unused result with a S_BITCMP.
11715 MachineBasicBlock *MBB = Def->getParent();
11716
11717 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11718 : AMDGPU::S_BITCMP1_B32
11719 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11720 : AMDGPU::S_BITCMP1_B64;
11721
11722 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11723 .add(*SrcOp)
11724 .addImm(BitNo);
11725 Def->eraseFromParent();
11726
11727 return true;
11728 };
11729
11730 switch (CmpInstr.getOpcode()) {
11731 default:
11732 break;
11733 case AMDGPU::S_CMP_EQ_U32:
11734 case AMDGPU::S_CMP_EQ_I32:
11735 case AMDGPU::S_CMPK_EQ_U32:
11736 case AMDGPU::S_CMPK_EQ_I32:
11737 return optimizeCmpAnd(1, 32, true, false) ||
11738 optimizeCmpSelect(/*NeedInversion=*/true);
11739 case AMDGPU::S_CMP_GE_U32:
11740 case AMDGPU::S_CMPK_GE_U32:
11741 return optimizeCmpAnd(1, 32, false, false);
11742 case AMDGPU::S_CMP_GE_I32:
11743 case AMDGPU::S_CMPK_GE_I32:
11744 return optimizeCmpAnd(1, 32, false, true);
11745 case AMDGPU::S_CMP_EQ_U64:
11746 return optimizeCmpAnd(1, 64, true, false);
11747 case AMDGPU::S_CMP_LG_U32:
11748 case AMDGPU::S_CMP_LG_I32:
11749 case AMDGPU::S_CMPK_LG_U32:
11750 case AMDGPU::S_CMPK_LG_I32:
11751 return optimizeCmpAnd(0, 32, true, false) ||
11752 optimizeCmpSelect(/*NeedInversion=*/false);
11753 case AMDGPU::S_CMP_GT_U32:
11754 case AMDGPU::S_CMPK_GT_U32:
11755 return optimizeCmpAnd(0, 32, false, false);
11756 case AMDGPU::S_CMP_GT_I32:
11757 case AMDGPU::S_CMPK_GT_I32:
11758 return optimizeCmpAnd(0, 32, false, true);
11759 case AMDGPU::S_CMP_LG_U64:
11760 return optimizeCmpAnd(0, 64, true, false) ||
11761 optimizeCmpSelect(/*NeedInversion=*/false);
11762 }
11763
11764 return false;
11765}
11766
11768 AMDGPU::OpName OpName) const {
11769 if (!ST.needsAlignedVGPRs())
11770 return;
11771
11772 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
11773 if (OpNo < 0)
11774 return;
11775 MachineOperand &Op = MI.getOperand(OpNo);
11776 if (getOpSize(MI, OpNo) > 4)
11777 return;
11778
11779 // Add implicit aligned super-reg to force alignment on the data operand.
11780 const DebugLoc &DL = MI.getDebugLoc();
11781 MachineBasicBlock *BB = MI.getParent();
11783 Register DataReg = Op.getReg();
11784 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11786 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11787 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
11788 Register NewVR =
11789 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
11790 : &AMDGPU::VReg_64_Align2RegClass);
11791 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
11792 .addReg(DataReg, {}, Op.getSubReg())
11793 .addImm(AMDGPU::sub0)
11794 .addReg(Undef)
11795 .addImm(AMDGPU::sub1);
11796 Op.setReg(NewVR);
11797 Op.setSubReg(AMDGPU::sub0);
11798 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
11799}
11800
11802 if (!SchedModel.hasInstrSchedModel())
11803 return 0;
11804
11805 // The repeat rate is the throughput-limiting resource occupancy: the largest
11806 // number of cycles any written processor resource is held.
11807 const MCSchedClassDesc *SCDesc = SchedModel.resolveSchedClass(&MI);
11808 unsigned RepeatRate = 0;
11810 PI = SchedModel.getWriteProcResBegin(SCDesc),
11811 PE = SchedModel.getWriteProcResEnd(SCDesc);
11812 PI != PE; ++PI) {
11813 RepeatRate = std::max(RepeatRate, (unsigned)PI->ReleaseAtCycle);
11814 }
11815
11816 return RepeatRate;
11817}
11818
11820 if (isIGLP(*MI))
11821 return false;
11822
11824}
11825
11827 if (!isWMMA(MI) && !isSWMMAC(MI))
11828 return false;
11829
11830 if (ST.hasGFX1250Insts())
11831 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
11832
11833 return true;
11834}
11835
11837 unsigned Opcode = MI.getOpcode();
11838
11839 if (AMDGPU::isGFX12Plus(ST))
11840 return isDOT(MI) || isXDLWMMA(MI);
11841
11842 if (!isMAI(MI) || isDGEMM(Opcode) ||
11843 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11844 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11845 return false;
11846
11847 if (!ST.hasGFX940Insts())
11848 return true;
11849
11850 return AMDGPU::getMAIIsGFX940XDL(Opcode);
11851}
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< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static bool isUndef(const MachineInstr &MI)
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t High
uint64_t IntrinsicInst * II
#define P(N)
R600 Clause Merge
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 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 void updateLiveVariables(LiveVariables *LV, MachineInstr &MI, MachineInstr &NewMI)
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 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 foldableSelect(const MachineInstr &Def)
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:183
Class for arbitrary precision integers.
Definition APInt.h:78
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1583
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:341
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:68
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.
LLVM_ABI void replaceKillInstruction(Register Reg, MachineInstr &OldMI, MachineInstr &NewMI)
replaceKillInstruction - Update register kill info by replacing a kill instruction with a new one.
LLVM_ABI VarInfo & getVarInfo(Register Reg)
getVarInfo - Return the VarInfo structure for the specified VIRTUAL register.
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 & 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.
unsigned getAddrSpace() const
@ 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
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const final
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool mayAccessFlatAddressSpace(const MachineInstr &MI) const
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)
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
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
bool isLegalVSrcOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO would be a valid operand for the given operand definition OpInfo.
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
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 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 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
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 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 canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, int &CondCycles, int &TrueCycles, int &FalseCycles) const override
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
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, LiveIntervals *LIS) 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.
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.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
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)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
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 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:447
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:465
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:432
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:440
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:456
@ OPERAND_REG_IMM_NOINLINE_FP16
Definition SIDefines.h:438
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:453
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:458
@ OPERAND_REG_IMM_V2INT64
Definition SIDefines.h:443
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:442
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:436
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:431
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:439
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:437
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:441
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:452
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:450
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:444
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:435
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:459
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:470
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:471
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:445
@ OPERAND_SDWA_VOPC_DST
Definition SIDefines.h:482
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:434
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:455
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:451
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:457
@ OPERAND_INLINE_C_AV64_PSEUDO
Definition SIDefines.h:476
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:446
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:472
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:454
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:433
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:462
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:678
@ TI_SCRATCH_RSRC_DWORD3
Definition AMDGPU.h:680
@ TI_SCRATCH_RSRC_DWORD0
Definition AMDGPU.h:677
@ TI_SCRATCH_RSRC_DWORD2
Definition AMDGPU.h:679
@ TI_CONSTDATA_START
Definition AMDGPU.h:676
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 isD16Buf(const T &...O)
Definition SIDefines.h:343
constexpr bool isSDWA(const T &...O)
Definition SIDefines.h:252
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:315
@ 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:1739
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:2554
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:633
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:46
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:1746
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:407
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
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:54
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:42
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:1772
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:50
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:1947
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
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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:65
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
SparseBitVector AliveBlocks
AliveBlocks - Set of blocks in which this value is alive completely through.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:129
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:69
MachineInstr * top() const
Definition SIInstrInfo.h:74
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
Definition SIInstrInfo.h:92
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.