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_D16ImageDimIntrinsics_IMPL
49#define GET_ImageDimIntrinsicTable_IMPL
50#define GET_RsrcIntrinsics_IMPL
51#include "AMDGPUGenSearchableTables.inc"
52} // namespace llvm::AMDGPU
53
54// Must be at least 4 to be able to branch over minimum unconditional branch
55// code. This is only for making it possible to write reasonably small tests for
56// long branches.
58BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16),
59 cl::desc("Restrict range of branch instructions (DEBUG)"));
60
62 "amdgpu-fix-16-bit-physreg-copies",
63 cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"),
64 cl::init(true),
66
68 : AMDGPUGenInstrInfo(ST, RI, AMDGPU::ADJCALLSTACKUP,
69 AMDGPU::ADJCALLSTACKDOWN),
70 RI(ST), ST(ST) {
71 SchedModel.init(&ST);
72}
73
74//===----------------------------------------------------------------------===//
75// TargetInstrInfo callbacks
76//===----------------------------------------------------------------------===//
77
78static unsigned getNumOperandsNoGlue(SDNode *Node) {
79 unsigned N = Node->getNumOperands();
80 while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
81 --N;
82 return N;
83}
84
85/// Returns true if both nodes have the same value for the given
86/// operand \p Op, or if both nodes do not have this operand.
88 AMDGPU::OpName OpName) {
89 unsigned Opc0 = N0->getMachineOpcode();
90 unsigned Opc1 = N1->getMachineOpcode();
91
92 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName);
93 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName);
94
95 if (Op0Idx == -1 && Op1Idx == -1)
96 return true;
97
98
99 if ((Op0Idx == -1 && Op1Idx != -1) ||
100 (Op1Idx == -1 && Op0Idx != -1))
101 return false;
102
103 // getNamedOperandIdx returns the index for the MachineInstr's operands,
104 // which includes the result as the first operand. We are indexing into the
105 // MachineSDNode's operands, so we need to skip the result operand to get
106 // the real index.
107 --Op0Idx;
108 --Op1Idx;
109
110 return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx);
111}
112
113static bool canRemat(const MachineInstr &MI) {
114
118 return true;
119
120 if (SIInstrInfo::isSMRD(MI)) {
121 return !MI.memoperands_empty() &&
122 llvm::all_of(MI.memoperands(), [](const MachineMemOperand *MMO) {
123 return MMO->isLoad() && MMO->isInvariant();
124 });
125 }
126
127 return false;
128}
129
130// Split relocation flags for 64-bit global-address materialization into a
131// common base and the hi/lo relocation variants.
132static std::tuple<unsigned, unsigned, unsigned>
134 const MachineOperand &SrcOp) {
135 const unsigned BaseFlags = SrcOp.getTargetFlags() & ~SIInstrInfo::MO_MASK;
136 const unsigned Reloc = SrcOp.getTargetFlags() & SIInstrInfo::MO_MASK;
137
138 // Infer the relocation type from the existing flags on the global operand.
139 // The relocation type should have been determined earlier in the pipeline.
140 unsigned LoReloc, HiReloc;
141 switch (Reloc) {
145 LoReloc = SIInstrInfo::MO_REL32_LO;
146 HiReloc = SIInstrInfo::MO_REL32_HI;
147 break;
152 break;
155 // For 64-bit GOT-relative, use the 64-bit relocation.
158 break;
162 LoReloc = SIInstrInfo::MO_ABS32_LO;
163 HiReloc = SIInstrInfo::MO_ABS32_HI;
164 break;
165 default:
166 llvm_unreachable("unknown relocation type for global address");
167 break;
168 }
169
170 return {BaseFlags, LoReloc, HiReloc};
171}
172
174 const MachineInstr &MI) const {
175
176 if (canRemat(MI)) {
177 // Normally VALU use of exec would block the rematerialization, but that
178 // is OK in this case to have an implicit exec read as all VALU do.
179 // We really want all of the generic logic for this except for this.
180
181 // Another potential implicit use is mode register. The core logic of
182 // the RA will not attempt rematerialization if mode is set anywhere
183 // in the function, otherwise it is safe since mode is not changed.
184
185 // There is difference to generic method which does not allow
186 // rematerialization if there are virtual register uses. We allow this,
187 // therefore this method includes SOP instructions as well.
188 if (!MI.hasImplicitDef() &&
189 MI.getNumImplicitOperands() == MI.getDesc().implicit_uses().size() &&
190 !MI.mayRaiseFPException())
191 return true;
192 }
193
194 // Everything below copied from TargetInstrInfo::isReMaterializableImpl. The
195 // only difference is that we allow operations that perform read-modify-write
196 // on sub-registers.
197
198 // Remat clients assume operand 0 is the defined register.
199 if (!MI.getNumOperands() || !MI.getOperand(0).isReg())
200 return false;
201 Register DefReg = MI.getOperand(0).getReg();
202
203 const MachineFunction &MF = *MI.getMF();
204
205 // A load from a fixed stack slot can be rematerialized. This may be
206 // redundant with subsequent checks, but it's target-independent,
207 // simple, and a common case.
208 int FrameIdx = 0;
209 if (isLoadFromStackSlot(MI, FrameIdx) &&
211 return true;
212
213 // Avoid instructions obviously unsafe for remat.
214 if (MI.isNotDuplicable() || MI.mayStore() || MI.mayRaiseFPException() ||
215 MI.hasUnmodeledSideEffects())
216 return false;
217
218 // Don't remat inline asm. We have no idea how expensive it is
219 // even if it's side effect free.
220 if (MI.isInlineAsm())
221 return false;
222
223 // Avoid instructions which load from potentially varying memory.
224 if (MI.mayLoad() && !MI.isDereferenceableInvariantLoad())
225 return false;
226
227 const MachineRegisterInfo &MRI = MF.getRegInfo();
228
229 // If any of the registers accessed are non-constant, conservatively assume
230 // the instruction is not rematerializable.
231 for (const MachineOperand &MO : MI.operands()) {
232 if (!MO.isReg())
233 continue;
234 Register Reg = MO.getReg();
235 if (Reg == 0)
236 continue;
237
238 // Check for a well-behaved physical register.
239 if (Reg.isPhysical()) {
240 if (MO.isUse()) {
241 // If the physreg has no defs anywhere, it's just an ambient register
242 // and we can freely move its uses. Alternatively, if it's allocatable,
243 // it could get allocated to something with a def during allocation.
244 if (!MRI.isConstantPhysReg(Reg))
245 return false;
246 } else {
247 // A physreg def. We can't remat it.
248 return false;
249 }
250 continue;
251 }
252
253 // Only allow one virtual-register def. There may be multiple defs of the
254 // same virtual register, though.
255 if (MO.isDef() && Reg != DefReg)
256 return false;
257 }
258
259 return true;
260}
261
262// Returns true if the result of a VALU instruction depends on exec.
263bool SIInstrInfo::resultDependsOnExec(const MachineInstr &MI) const {
264 assert(isVALU(MI, /*AllowLDSDMA=*/true));
265
266 // If it is convergent it depends on EXEC.
267 if (MI.isConvergent())
268 return true;
269
270 // If it defines SGPR it depends on EXEC
271 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
272 for (const MachineOperand &Def : MI.defs()) {
273 if (!Def.isReg())
274 continue;
275
276 Register Reg = Def.getReg();
277 if (Reg && RI.isSGPRReg(MRI, Reg))
278 return true;
279 }
280
281 return false;
282}
283
285 // Any implicit use of exec by VALU is not a real register read.
286 return MO.getReg() == AMDGPU::EXEC && MO.isImplicit() &&
287 isVALU(*MO.getParent(), /*AllowLDSDMA=*/true) &&
288 !resultDependsOnExec(*MO.getParent());
289}
290
292 MachineBasicBlock *SuccToSinkTo,
293 MachineCycleInfo *CI) const {
294 // Allow sinking if MI edits lane mask (divergent i1 in sgpr).
295 if (MI.getOpcode() == AMDGPU::SI_IF_BREAK)
296 return true;
297
298 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
299 // Check if sinking of MI would create temporal divergent use.
300 for (auto Op : MI.uses()) {
301 if (Op.isReg() && Op.getReg().isVirtual() &&
302 RI.isSGPRClass(MRI.getRegClass(Op.getReg()))) {
303 MachineInstr *SgprDef = MRI.getVRegDef(Op.getReg());
304 if (!SgprDef)
305 continue;
306
307 // SgprDef defined inside cycle
308 CycleRef FromCycle = CI->getCycle(SgprDef->getParent());
309 if (!FromCycle)
310 continue;
311
312 CycleRef ToCycle = CI->getCycle(SuccToSinkTo);
313 // Check if there is a FromCycle that contains SgprDef's basic block but
314 // does not contain SuccToSinkTo and also has divergent exit condition.
315 while (FromCycle && !(ToCycle && CI->contains(FromCycle, ToCycle))) {
317 CI->getExitingBlocks(FromCycle, ExitingBlocks);
318
319 // FromCycle has divergent exit condition.
320 for (MachineBasicBlock *ExitingBlock : ExitingBlocks) {
321 if (hasDivergentBranch(ExitingBlock))
322 return false;
323 }
324
325 FromCycle = CI->getParentCycle(FromCycle);
326 }
327 }
328 }
329
330 return true;
331}
332
334 int64_t &Offset0,
335 int64_t &Offset1) const {
336 if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode())
337 return false;
338
339 unsigned Opc0 = Load0->getMachineOpcode();
340 unsigned Opc1 = Load1->getMachineOpcode();
341
342 // Make sure both are actually loads.
343 if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad())
344 return false;
345
346 // A mayLoad instruction without a def is not a load. Likely a prefetch.
347 if (!get(Opc0).getNumDefs() || !get(Opc1).getNumDefs())
348 return false;
349
350 if (isDS(Opc0) && isDS(Opc1)) {
351
352 // FIXME: Handle this case:
353 if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1))
354 return false;
355
356 // Check base reg.
357 if (Load0->getOperand(0) != Load1->getOperand(0))
358 return false;
359
360 // Skip read2 / write2 variants for simplicity.
361 // TODO: We should report true if the used offsets are adjacent (excluded
362 // st64 versions).
363 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
364 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
365 if (Offset0Idx == -1 || Offset1Idx == -1)
366 return false;
367
368 // XXX - be careful of dataless loads
369 // getNamedOperandIdx returns the index for MachineInstrs. Since they
370 // include the output in the operand list, but SDNodes don't, we need to
371 // subtract the index by one.
372 Offset0Idx -= get(Opc0).NumDefs;
373 Offset1Idx -= get(Opc1).NumDefs;
374 Offset0 = Load0->getConstantOperandVal(Offset0Idx);
375 Offset1 = Load1->getConstantOperandVal(Offset1Idx);
376 return true;
377 }
378
379 if (isSMRD(Opc0) && isSMRD(Opc1)) {
380 // Skip time and cache invalidation instructions.
381 if (!AMDGPU::hasNamedOperand(Opc0, AMDGPU::OpName::sbase) ||
382 !AMDGPU::hasNamedOperand(Opc1, AMDGPU::OpName::sbase))
383 return false;
384
385 unsigned NumOps = getNumOperandsNoGlue(Load0);
386 if (NumOps != getNumOperandsNoGlue(Load1))
387 return false;
388
389 // Check base reg.
390 if (Load0->getOperand(0) != Load1->getOperand(0))
391 return false;
392
393 // Match register offsets, if both register and immediate offsets present.
394 assert(NumOps == 4 || NumOps == 5);
395 if (NumOps == 5 && Load0->getOperand(1) != Load1->getOperand(1))
396 return false;
397
398 const ConstantSDNode *Load0Offset =
400 const ConstantSDNode *Load1Offset =
402
403 if (!Load0Offset || !Load1Offset)
404 return false;
405
406 Offset0 = Load0Offset->getZExtValue();
407 Offset1 = Load1Offset->getZExtValue();
408 return true;
409 }
410
411 // MUBUF and MTBUF can access the same addresses.
412 if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) {
413
414 // MUBUF and MTBUF have vaddr at different indices.
415 if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) ||
416 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) ||
417 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc))
418 return false;
419
420 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
421 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
422
423 if (OffIdx0 == -1 || OffIdx1 == -1)
424 return false;
425
426 // getNamedOperandIdx returns the index for MachineInstrs. Since they
427 // include the output in the operand list, but SDNodes don't, we need to
428 // subtract the index by one.
429 OffIdx0 -= get(Opc0).NumDefs;
430 OffIdx1 -= get(Opc1).NumDefs;
431
432 SDValue Off0 = Load0->getOperand(OffIdx0);
433 SDValue Off1 = Load1->getOperand(OffIdx1);
434
435 // The offset might be a FrameIndexSDNode.
436 if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1))
437 return false;
438
439 Offset0 = Off0->getAsZExtVal();
440 Offset1 = Off1->getAsZExtVal();
441 return true;
442 }
443
444 return false;
445}
446
447static bool isStride64(unsigned Opc) {
448 switch (Opc) {
449 case AMDGPU::DS_READ2ST64_B32:
450 case AMDGPU::DS_READ2ST64_B64:
451 case AMDGPU::DS_WRITE2ST64_B32:
452 case AMDGPU::DS_WRITE2ST64_B64:
453 return true;
454 default:
455 return false;
456 }
457}
458
461 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
462 const TargetRegisterInfo *TRI) const {
463 if (!LdSt.mayLoadOrStore())
464 return false;
465
466 unsigned Opc = LdSt.getOpcode();
467 OffsetIsScalable = false;
468 const MachineOperand *BaseOp, *OffsetOp;
469 int DataOpIdx;
470
471 if (isDS(LdSt)) {
472 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr);
473 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
474 if (OffsetOp) {
475 // Normal, single offset LDS instruction.
476 if (!BaseOp) {
477 // DS_CONSUME/DS_APPEND use M0 for the base address.
478 // TODO: find the implicit use operand for M0 and use that as BaseOp?
479 return false;
480 }
481 BaseOps.push_back(BaseOp);
482 Offset = OffsetOp->getImm();
483 // Get appropriate operand, and compute width accordingly.
484 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
485 if (DataOpIdx == -1)
486 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
487 if (Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
488 Width = LocationSize::precise(64);
489 else
490 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
491 } else {
492 // The 2 offset instructions use offset0 and offset1 instead. We can treat
493 // these as a load with a single offset if the 2 offsets are consecutive.
494 // We will use this for some partially aligned loads.
495 const MachineOperand *Offset0Op =
496 getNamedOperand(LdSt, AMDGPU::OpName::offset0);
497 const MachineOperand *Offset1Op =
498 getNamedOperand(LdSt, AMDGPU::OpName::offset1);
499
500 unsigned Offset0 = Offset0Op->getImm() & 0xff;
501 unsigned Offset1 = Offset1Op->getImm() & 0xff;
502 if (Offset0 + 1 != Offset1)
503 return false;
504
505 // Each of these offsets is in element sized units, so we need to convert
506 // to bytes of the individual reads.
507
508 unsigned EltSize;
509 if (LdSt.mayLoad())
510 EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16;
511 else {
512 assert(LdSt.mayStore());
513 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
514 EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8;
515 }
516
517 if (isStride64(Opc))
518 EltSize *= 64;
519
520 BaseOps.push_back(BaseOp);
521 Offset = EltSize * Offset0;
522 // Get appropriate operand(s), and compute width accordingly.
523 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
524 if (DataOpIdx == -1) {
525 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
526 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
527 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
528 Width = LocationSize::precise(
529 Width.getValue() + TypeSize::getFixed(getOpSize(LdSt, DataOpIdx)));
530 } else {
531 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
532 }
533 }
534 return true;
535 }
536
537 if (isMUBUF(LdSt) || isMTBUF(LdSt)) {
538 const MachineOperand *RSrc = getNamedOperand(LdSt, AMDGPU::OpName::srsrc);
539 if (!RSrc) // e.g. BUFFER_WBINVL1_VOL
540 return false;
541 BaseOps.push_back(RSrc);
542 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
543 if (BaseOp && !BaseOp->isFI())
544 BaseOps.push_back(BaseOp);
545 const MachineOperand *OffsetImm =
546 getNamedOperand(LdSt, AMDGPU::OpName::offset);
547 Offset = OffsetImm->getImm();
548 const MachineOperand *SOffset =
549 getNamedOperand(LdSt, AMDGPU::OpName::soffset);
550 if (SOffset) {
551 if (SOffset->isReg())
552 BaseOps.push_back(SOffset);
553 else
554 Offset += SOffset->getImm();
555 }
556 // Get appropriate operand, and compute width accordingly.
557 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
558 if (DataOpIdx == -1)
559 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
560 if (DataOpIdx == -1) // LDS DMA
561 return false;
562 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
563 return true;
564 }
565
566 if (isImage(LdSt)) {
567 auto RsrcOpName =
568 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
569 int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RsrcOpName);
570 BaseOps.push_back(&LdSt.getOperand(SRsrcIdx));
571 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
572 if (VAddr0Idx >= 0) {
573 // GFX10 possible NSA encoding.
574 for (int I = VAddr0Idx; I < SRsrcIdx; ++I)
575 BaseOps.push_back(&LdSt.getOperand(I));
576 } else {
577 BaseOps.push_back(getNamedOperand(LdSt, AMDGPU::OpName::vaddr));
578 }
579 Offset = 0;
580 // Get appropriate operand, and compute width accordingly.
581 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
582 if (DataOpIdx == -1)
583 return false; // no return sampler
584 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
585 return true;
586 }
587
588 if (isSMRD(LdSt)) {
589 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::sbase);
590 if (!BaseOp) // e.g. S_MEMTIME
591 return false;
592 BaseOps.push_back(BaseOp);
593 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
594 Offset = OffsetOp ? OffsetOp->getImm() : 0;
595 // Get appropriate operand, and compute width accordingly.
596 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
597 if (DataOpIdx == -1)
598 return false;
599 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
600 return true;
601 }
602
603 if (isFLAT(LdSt)) {
604 // Instructions have either vaddr or saddr or both or none.
605 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
606 if (BaseOp)
607 BaseOps.push_back(BaseOp);
608 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr);
609 if (BaseOp)
610 BaseOps.push_back(BaseOp);
611 Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm();
612 // Get appropriate operand, and compute width accordingly.
613 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
614 if (DataOpIdx == -1)
615 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
616 if (DataOpIdx == -1) // LDS DMA
617 return false;
618 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
619 return true;
620 }
621
622 return false;
623}
624
625static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
627 const MachineInstr &MI2,
629 // Only examine the first "base" operand of each instruction, on the
630 // assumption that it represents the real base address of the memory access.
631 // Other operands are typically offsets or indices from this base address.
632 if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
633 return true;
634
635 if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
636 return false;
637
638 auto *MO1 = *MI1.memoperands_begin();
639 auto *MO2 = *MI2.memoperands_begin();
640 if (MO1->getAddrSpace() != MO2->getAddrSpace())
641 return false;
642
643 const auto *Base1 = MO1->getValue();
644 const auto *Base2 = MO2->getValue();
645 if (!Base1 || !Base2)
646 return false;
647 Base1 = getUnderlyingObject(Base1);
648 Base2 = getUnderlyingObject(Base2);
649
650 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
651 return false;
652
653 return Base1 == Base2;
654}
655
657 int64_t Offset1, bool OffsetIsScalable1,
659 int64_t Offset2, bool OffsetIsScalable2,
660 unsigned ClusterSize,
661 unsigned NumBytes) const {
662 // If the mem ops (to be clustered) do not have the same base ptr, then they
663 // should not be clustered
664 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;
665 if (!BaseOps1.empty() && !BaseOps2.empty()) {
666 const MachineInstr &FirstLdSt = *BaseOps1.front()->getParent();
667 const MachineInstr &SecondLdSt = *BaseOps2.front()->getParent();
668 if (!memOpsHaveSameBasePtr(FirstLdSt, BaseOps1, SecondLdSt, BaseOps2))
669 return false;
670
671 const SIMachineFunctionInfo *MFI =
672 FirstLdSt.getMF()->getInfo<SIMachineFunctionInfo>();
673 MaxMemoryClusterDWords = MFI->getMaxMemoryClusterDWords();
674 } else if (!BaseOps1.empty() || !BaseOps2.empty()) {
675 // If only one base op is empty, they do not have the same base ptr
676 return false;
677 }
678
679 // In order to avoid register pressure, on an average, the number of DWORDS
680 // loaded together by all clustered mem ops should not exceed
681 // MaxMemoryClusterDWords. This is an empirical value based on certain
682 // observations and performance related experiments.
683 // The good thing about this heuristic is - it avoids clustering of too many
684 // sub-word loads, and also avoids clustering of wide loads. Below is the
685 // brief summary of how the heuristic behaves for various `LoadSize` when
686 // MaxMemoryClusterDWords is 8.
687 //
688 // (1) 1 <= LoadSize <= 4: cluster at max 8 mem ops
689 // (2) 5 <= LoadSize <= 8: cluster at max 4 mem ops
690 // (3) 9 <= LoadSize <= 12: cluster at max 2 mem ops
691 // (4) 13 <= LoadSize <= 16: cluster at max 2 mem ops
692 // (5) LoadSize >= 17: do not cluster
693 const unsigned LoadSize = NumBytes / ClusterSize;
694 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
695 return NumDWords <= MaxMemoryClusterDWords;
696}
697
698// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
699// the first 16 loads will be interleaved with the stores, and the next 16 will
700// be clustered as expected. It should really split into 2 16 store batches.
701//
702// Loads are clustered until this returns false, rather than trying to schedule
703// groups of stores. This also means we have to deal with saying different
704// address space loads should be clustered, and ones which might cause bank
705// conflicts.
706//
707// This might be deprecated so it might not be worth that much effort to fix.
709 int64_t Offset0, int64_t Offset1,
710 unsigned NumLoads) const {
711 assert(Offset1 > Offset0 &&
712 "Second offset should be larger than first offset!");
713 // If we have less than 16 loads in a row, and the offsets are within 64
714 // bytes, then schedule together.
715
716 // A cacheline is 64 bytes (for global memory).
717 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
718}
719
722 const DebugLoc &DL, MCRegister DestReg,
723 MCRegister SrcReg, bool KillSrc,
724 const char *Msg = "illegal VGPR to SGPR copy") {
725 MachineFunction *MF = MBB.getParent();
726
729
730 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg)
731 .addReg(SrcReg, getKillRegState(KillSrc));
732}
733
734/// Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908. It is not
735/// possible to have a direct copy in these cases on GFX908, so an intermediate
736/// VGPR copy is required.
739 const DebugLoc &DL, MCRegister DestReg,
740 MCRegister SrcReg, bool KillSrc,
741 RegScavenger &RS, bool RegsOverlap,
742 Register ImpUseSuperReg = Register()) {
743 assert((TII.getSubtarget().hasMAIInsts() &&
744 !TII.getSubtarget().hasGFX90AInsts()) &&
745 "Expected GFX908 subtarget.");
746
747 assert((AMDGPU::SReg_32RegClass.contains(SrcReg) ||
748 AMDGPU::AGPR_32RegClass.contains(SrcReg)) &&
749 "Source register of the copy should be either an SGPR or an AGPR.");
750
751 assert(AMDGPU::AGPR_32RegClass.contains(DestReg) &&
752 "Destination register of the copy should be an AGPR.");
753
754 const SIRegisterInfo &RI = TII.getRegisterInfo();
755
756 // First try to find defining accvgpr_write to avoid temporary registers.
757 // In the case of copies of overlapping AGPRs, we conservatively do not
758 // reuse previous accvgpr_writes. Otherwise, we may incorrectly pick up
759 // an accvgpr_write used for this same copy due to implicit-defs
760 if (!RegsOverlap) {
761 for (auto Def = MI, E = MBB.begin(); Def != E; ) {
762 --Def;
763
764 if (!Def->modifiesRegister(SrcReg, &RI))
765 continue;
766
767 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
768 Def->getOperand(0).getReg() != SrcReg)
769 break;
770
771 MachineOperand &DefOp = Def->getOperand(1);
772 assert(DefOp.isReg() || DefOp.isImm());
773
774 if (DefOp.isReg()) {
775 bool SafeToPropagate = true;
776 // Check that register source operand is not clobbered before MI.
777 // Immediate operands are always safe to propagate.
778 for (auto I = Def; I != MI && SafeToPropagate; ++I)
779 if (I->modifiesRegister(DefOp.getReg(), &RI))
780 SafeToPropagate = false;
781
782 if (!SafeToPropagate)
783 break;
784
785 for (auto I = Def; I != MI; ++I)
786 I->clearRegisterKills(DefOp.getReg(), &RI);
787 }
788
789 MachineInstrBuilder Builder =
790 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64),
791 DestReg)
792 .add(DefOp);
793
794 if (ImpUseSuperReg) {
795 Builder.addReg(ImpUseSuperReg,
797 }
798
799 return;
800 }
801 }
802
803 RS.enterBasicBlockEnd(MBB);
804 RS.backward(std::next(MI));
805
806 // Ideally we want to have three registers for a long reg_sequence copy
807 // to hide 2 waitstates between v_mov_b32 and accvgpr_write.
808 unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass,
809 *MBB.getParent());
810
811 // Registers in the sequence are allocated contiguously so we can just
812 // use register number to pick one of three round-robin temps.
813 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
814 Register Tmp =
815 MBB.getParent()->getInfo<SIMachineFunctionInfo>()->getVGPRForAGPRCopy();
816 assert(MBB.getParent()->getRegInfo().isReserved(Tmp) &&
817 "VGPR used for an intermediate copy should have been reserved.");
818
819 // Only loop through if there are any free registers left. We don't want to
820 // spill.
821 while (RegNo--) {
822 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI,
823 /* RestoreAfter */ false, 0,
824 /* AllowSpill */ false);
825 if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs)
826 break;
827 Tmp = Tmp2;
828 RS.setRegUsed(Tmp);
829 }
830
831 // Insert copy to temporary VGPR.
832 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
833 if (AMDGPU::AGPR_32RegClass.contains(SrcReg)) {
834 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
835 } else {
836 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
837 }
838
839 MachineInstrBuilder UseBuilder = BuildMI(MBB, MI, DL, TII.get(TmpCopyOp), Tmp)
840 .addReg(SrcReg, getKillRegState(KillSrc));
841 if (ImpUseSuperReg) {
842 UseBuilder.addReg(ImpUseSuperReg,
844 }
845
846 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
847 .addReg(Tmp, RegState::Kill);
848}
849
852 MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
853 const TargetRegisterClass *RC, bool Forward) {
854 const SIRegisterInfo &RI = TII.getRegisterInfo();
855 ArrayRef<int16_t> BaseIndices = RI.getRegSplitParts(RC, 4);
857 MachineInstr *FirstMI = nullptr, *LastMI = nullptr;
858
859 for (unsigned Idx = 0; Idx < BaseIndices.size(); ++Idx) {
860 int16_t SubIdx = BaseIndices[Idx];
861 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
862 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
863 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
864 unsigned Opcode = AMDGPU::S_MOV_B32;
865
866 // Is SGPR aligned? If so try to combine with next.
867 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
868 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
869 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.size())) {
870 // Can use SGPR64 copy
871 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
872 SubIdx = RI.getSubRegFromChannel(Channel, 2);
873 DestSubReg = RI.getSubReg(DestReg, SubIdx);
874 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
875 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
876 Opcode = AMDGPU::S_MOV_B64;
877 Idx++;
878 }
879
880 LastMI = BuildMI(MBB, I, DL, TII.get(Opcode), DestSubReg)
881 .addReg(SrcSubReg)
882 .addReg(SrcReg, RegState::Implicit);
883
884 if (!FirstMI)
885 FirstMI = LastMI;
886
887 if (!Forward)
888 I--;
889 }
890
891 assert(FirstMI && LastMI);
892 if (!Forward)
893 std::swap(FirstMI, LastMI);
894
895 if (KillSrc)
896 LastMI->addRegisterKilled(SrcReg, &RI);
897}
898
901 const DebugLoc &DL, Register DestReg,
902 Register SrcReg, bool KillSrc, bool RenamableDest,
903 bool RenamableSrc) const {
904 const TargetRegisterClass *RC = RI.getPhysRegBaseClass(DestReg);
905 unsigned Size = RI.getRegSizeInBits(*RC);
906 const TargetRegisterClass *SrcRC = RI.getPhysRegBaseClass(SrcReg);
907 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
908
909 // The rest of copyPhysReg assumes Src and Dst size are the same size.
910 // TODO-GFX11_16BIT If all true 16 bit instruction patterns are completed can
911 // we remove Fix16BitCopies and this code block?
912 if (Fix16BitCopies) {
913 if (((Size == 16) != (SrcSize == 16))) {
914 // Non-VGPR Src and Dst will later be expanded back to 32 bits.
915 assert(ST.useRealTrue16Insts());
916 Register &RegToFix = (Size == 32) ? DestReg : SrcReg;
917 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
918 RegToFix = SubReg;
919
920 if (DestReg == SrcReg) {
921 // Identity copy. Insert empty bundle since ExpandPostRA expects an
922 // instruction here.
923 BuildMI(MBB, MI, DL, get(AMDGPU::BUNDLE));
924 return;
925 }
926 RC = RI.getPhysRegBaseClass(DestReg);
927 Size = RI.getRegSizeInBits(*RC);
928 SrcRC = RI.getPhysRegBaseClass(SrcReg);
929 SrcSize = RI.getRegSizeInBits(*SrcRC);
930 }
931 }
932
933 if (RC == &AMDGPU::VGPR_32RegClass) {
934 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
935 AMDGPU::SReg_32RegClass.contains(SrcReg) ||
936 AMDGPU::AGPR_32RegClass.contains(SrcReg));
937 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
938 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
939 BuildMI(MBB, MI, DL, get(Opc), DestReg)
940 .addReg(SrcReg, getKillRegState(KillSrc));
941 return;
942 }
943
944 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
945 RC == &AMDGPU::SReg_32RegClass) {
946 if (SrcReg == AMDGPU::SCC) {
947 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg)
948 .addImm(1)
949 .addImm(0);
950 return;
951 }
952
953 if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) {
954 if (DestReg == AMDGPU::VCC_LO) {
955 // FIXME: Hack until VReg_1 removed.
956 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
957 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
958 .addImm(0)
959 .addReg(SrcReg, getKillRegState(KillSrc));
960 return;
961 }
962
963 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
964 return;
965 }
966
967 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
968 .addReg(SrcReg, getKillRegState(KillSrc));
969 return;
970 }
971
972 if (RC == &AMDGPU::SReg_64RegClass) {
973 if (SrcReg == AMDGPU::SCC) {
974 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B64), DestReg)
975 .addImm(1)
976 .addImm(0);
977 return;
978 }
979
980 if (!AMDGPU::SReg_64_EncodableRegClass.contains(SrcReg)) {
981 if (DestReg == AMDGPU::VCC) {
982 // FIXME: Hack until VReg_1 removed.
983 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
984 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
985 .addImm(0)
986 .addReg(SrcReg, getKillRegState(KillSrc));
987 return;
988 }
989
990 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
991 return;
992 }
993
994 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
995 .addReg(SrcReg, getKillRegState(KillSrc));
996 return;
997 }
998
999 if (DestReg == AMDGPU::SCC) {
1000 // Copying 64-bit or 32-bit sources to SCC barely makes sense,
1001 // but SelectionDAG emits such copies for i1 sources.
1002 if (AMDGPU::SReg_64RegClass.contains(SrcReg)) {
1003 // This copy can only be produced by patterns
1004 // with explicit SCC, which are known to be enabled
1005 // only for subtargets with S_CMP_LG_U64 present.
1006 assert(ST.hasScalarCompareEq64());
1007 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U64))
1008 .addReg(SrcReg, getKillRegState(KillSrc))
1009 .addImm(0);
1010 } else {
1011 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
1012 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32))
1013 .addReg(SrcReg, getKillRegState(KillSrc))
1014 .addImm(0);
1015 }
1016
1017 return;
1018 }
1019
1020 if (RC == &AMDGPU::AGPR_32RegClass) {
1021 if (AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
1022 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1023 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
1024 .addReg(SrcReg, getKillRegState(KillSrc));
1025 return;
1026 }
1027
1028 if (AMDGPU::AGPR_32RegClass.contains(SrcReg) && ST.hasGFX90AInsts()) {
1029 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_MOV_B32), DestReg)
1030 .addReg(SrcReg, getKillRegState(KillSrc));
1031 return;
1032 }
1033
1034 // FIXME: Pass should maintain scavenger to avoid scan through the block on
1035 // every AGPR spill.
1036 RegScavenger RS;
1037 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1038 indirectCopyToAGPR(*this, MBB, MI, DL, DestReg, SrcReg, KillSrc, RS, Overlap);
1039 return;
1040 }
1041
1042 if (Size == 16) {
1043 assert(AMDGPU::VGPR_16RegClass.contains(SrcReg) ||
1044 AMDGPU::SReg_LO16RegClass.contains(SrcReg) ||
1045 AMDGPU::AGPR_LO16RegClass.contains(SrcReg));
1046
1047 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1048 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1049 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1050 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1051 bool DstLow = !AMDGPU::isHi16Reg(DestReg, RI);
1052 bool SrcLow = !AMDGPU::isHi16Reg(SrcReg, RI);
1053 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1054 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1055
1056 if (IsSGPRDst) {
1057 if (!IsSGPRSrc) {
1058 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1059 return;
1060 }
1061
1062 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), NewDestReg)
1063 .addReg(NewSrcReg, getKillRegState(KillSrc));
1064 return;
1065 }
1066
1067 if (IsAGPRDst || IsAGPRSrc) {
1068 if (!DstLow || !SrcLow) {
1069 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1070 "Cannot use hi16 subreg with an AGPR!");
1071 }
1072
1073 copyPhysReg(MBB, MI, DL, NewDestReg, NewSrcReg, KillSrc);
1074 return;
1075 }
1076
1077 if (ST.useRealTrue16Insts()) {
1078 if (IsSGPRSrc) {
1079 assert(SrcLow);
1080 SrcReg = NewSrcReg;
1081 }
1082 // Use the smaller instruction encoding if possible.
1083 if (AMDGPU::VGPR_16_Lo128RegClass.contains(DestReg) &&
1084 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.contains(SrcReg))) {
1085 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e32), DestReg)
1086 .addReg(SrcReg);
1087 } else {
1088 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e64), DestReg)
1089 .addImm(0) // src0_modifiers
1090 .addReg(SrcReg)
1091 .addImm(0); // op_sel
1092 }
1093 return;
1094 }
1095
1096 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1097 if (!DstLow || !SrcLow) {
1098 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1099 "Cannot use hi16 subreg on VI!");
1100 }
1101
1102 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), NewDestReg)
1103 .addReg(NewSrcReg, getKillRegState(KillSrc));
1104 return;
1105 }
1106
1107 auto MIB = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_sdwa), NewDestReg)
1108 .addImm(0) // src0_modifiers
1109 .addReg(NewSrcReg)
1110 .addImm(0) // clamp
1117 // First implicit operand is $exec.
1118 MIB->tieOperands(0, MIB->getNumOperands() - 1);
1119 return;
1120 }
1121
1122 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1123 if (ST.hasVMovB64Inst()) {
1124 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_e32), DestReg)
1125 .addReg(SrcReg, getKillRegState(KillSrc));
1126 return;
1127 }
1128 if (ST.hasPkMovB32()) {
1129 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestReg)
1131 .addReg(SrcReg)
1133 .addReg(SrcReg)
1134 .addImm(0) // op_sel_lo
1135 .addImm(0) // op_sel_hi
1136 .addImm(0) // neg_lo
1137 .addImm(0) // neg_hi
1138 .addImm(0) // clamp
1139 .addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
1140 return;
1141 }
1142 }
1143
1144 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1145 if (RI.isSGPRClass(RC)) {
1146 if (!RI.isSGPRClass(SrcRC)) {
1147 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1148 return;
1149 }
1150 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1151 expandSGPRCopy(*this, MBB, MI, DL, DestReg, SrcReg, CanKillSuperReg, RC,
1152 Forward);
1153 return;
1154 }
1155
1156 unsigned EltSize = 4;
1157 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1158 if (RI.isAGPRClass(RC)) {
1159 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1160 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1161 else if (RI.hasVGPRs(SrcRC) ||
1162 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1163 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1164 else
1165 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1166 } else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1167 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1168 } else if ((Size % 64 == 0) && RI.hasVGPRs(RC) &&
1169 (RI.isProperlyAlignedRC(*RC) &&
1170 (SrcRC == RC || RI.isSGPRClass(SrcRC)))) {
1171 // TODO: In 96-bit case, could do a 64-bit mov and then a 32-bit mov.
1172 if (ST.hasVMovB64Inst()) {
1173 Opcode = AMDGPU::V_MOV_B64_e32;
1174 EltSize = 8;
1175 } else if (ST.hasPkMovB32()) {
1176 Opcode = AMDGPU::V_PK_MOV_B32;
1177 EltSize = 8;
1178 }
1179 }
1180
1181 // For the cases where we need an intermediate instruction/temporary register
1182 // (destination is an AGPR), we need a scavenger.
1183 //
1184 // FIXME: The pass should maintain this for us so we don't have to re-scan the
1185 // whole block for every handled copy.
1186 std::unique_ptr<RegScavenger> RS;
1187 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1188 RS = std::make_unique<RegScavenger>();
1189
1190 ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, EltSize);
1191
1192 // If there is an overlap, we can't kill the super-register on the last
1193 // instruction, since it will also kill the components made live by this def.
1194 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1195 const bool CanKillSuperReg = KillSrc && !Overlap;
1196
1197 for (unsigned Idx = 0; Idx < SubIndices.size(); ++Idx) {
1198 unsigned SubIdx;
1199 if (Forward)
1200 SubIdx = SubIndices[Idx];
1201 else
1202 SubIdx = SubIndices[SubIndices.size() - Idx - 1];
1203 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1204 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1205 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
1206
1207 bool UseKill = CanKillSuperReg && Idx == SubIndices.size() - 1;
1208
1209 if (Opcode == AMDGPU::INSTRUCTION_LIST_END) {
1210 Register ImpUseSuper = SrcReg;
1211 indirectCopyToAGPR(*this, MBB, MI, DL, DestSubReg, SrcSubReg, UseKill,
1212 *RS, Overlap, ImpUseSuper);
1213 } else if (Opcode == AMDGPU::V_PK_MOV_B32) {
1214 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestSubReg)
1216 .addReg(SrcSubReg)
1218 .addReg(SrcSubReg)
1219 .addImm(0) // op_sel_lo
1220 .addImm(0) // op_sel_hi
1221 .addImm(0) // neg_lo
1222 .addImm(0) // neg_hi
1223 .addImm(0) // clamp
1224 .addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1225 } else {
1226 MachineInstrBuilder Builder =
1227 BuildMI(MBB, MI, DL, get(Opcode), DestSubReg).addReg(SrcSubReg);
1228
1229 Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1230 }
1231 }
1232}
1233
1234int SIInstrInfo::commuteOpcode(unsigned Opcode) const {
1235 int32_t NewOpc;
1236
1237 // Try to map original to commuted opcode
1238 NewOpc = AMDGPU::getCommuteRev(Opcode);
1239 if (NewOpc != -1)
1240 // Check if the commuted (REV) opcode exists on the target.
1241 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1242
1243 // Try to map commuted to original opcode
1244 NewOpc = AMDGPU::getCommuteOrig(Opcode);
1245 if (NewOpc != -1)
1246 // Check if the original (non-REV) opcode exists on the target.
1247 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1248
1249 return Opcode;
1250}
1251
1253 const Register Reg,
1254 int64_t &ImmVal) const {
1255 switch (MI.getOpcode()) {
1256 case AMDGPU::V_MOV_B32_e32:
1257 case AMDGPU::S_MOV_B32:
1258 case AMDGPU::S_MOVK_I32:
1259 case AMDGPU::S_MOV_B64:
1260 case AMDGPU::V_MOV_B64_e32:
1261 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1262 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1263 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1264 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1265 case AMDGPU::V_MOV_B64_PSEUDO:
1266 case AMDGPU::V_MOV_B16_t16_e32: {
1267 const MachineOperand &Src0 = MI.getOperand(1);
1268 if (Src0.isImm()) {
1269 ImmVal = Src0.getImm();
1270 return MI.getOperand(0).getReg() == Reg;
1271 }
1272
1273 return false;
1274 }
1275 case AMDGPU::V_MOV_B16_t16_e64: {
1276 const MachineOperand &Src0 = MI.getOperand(2);
1277 if (Src0.isImm() && !MI.getOperand(1).getImm()) {
1278 ImmVal = Src0.getImm();
1279 return MI.getOperand(0).getReg() == Reg;
1280 }
1281
1282 return false;
1283 }
1284 case AMDGPU::S_BREV_B32:
1285 case AMDGPU::V_BFREV_B32_e32:
1286 case AMDGPU::V_BFREV_B32_e64: {
1287 const MachineOperand &Src0 = MI.getOperand(1);
1288 if (Src0.isImm()) {
1289 ImmVal = static_cast<int64_t>(reverseBits<int32_t>(Src0.getImm()));
1290 return MI.getOperand(0).getReg() == Reg;
1291 }
1292
1293 return false;
1294 }
1295 case AMDGPU::S_NOT_B32:
1296 case AMDGPU::V_NOT_B32_e32:
1297 case AMDGPU::V_NOT_B32_e64: {
1298 const MachineOperand &Src0 = MI.getOperand(1);
1299 if (Src0.isImm()) {
1300 ImmVal = static_cast<int64_t>(~static_cast<int32_t>(Src0.getImm()));
1301 return MI.getOperand(0).getReg() == Reg;
1302 }
1303
1304 return false;
1305 }
1306 default:
1307 return false;
1308 }
1309}
1310
1311std::optional<int64_t>
1313 if (Op.isImm())
1314 return Op.getImm();
1315
1316 if (!Op.isReg() || !Op.getReg().isVirtual())
1317 return std::nullopt;
1318 MachineRegisterInfo &MRI = Op.getParent()->getMF()->getRegInfo();
1319 const MachineInstr *Def = MRI.getVRegDef(Op.getReg());
1320 if (Def && Def->isMoveImmediate()) {
1321 const MachineOperand &ImmSrc = Def->getOperand(1);
1322 if (ImmSrc.isImm())
1323 return extractSubregFromImm(ImmSrc.getImm(), Op.getSubReg());
1324 }
1325
1326 return std::nullopt;
1327}
1328
1330
1331 if (RI.isAGPRClass(DstRC))
1332 return AMDGPU::COPY;
1333 if (RI.getRegSizeInBits(*DstRC) == 16) {
1334 // Assume hi bits are unneeded. Only _e64 true16 instructions are legal
1335 // before RA.
1336 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1337 }
1338 if (RI.getRegSizeInBits(*DstRC) == 32)
1339 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1340 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1341 return AMDGPU::S_MOV_B64;
1342 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1343 return AMDGPU::V_MOV_B64_PSEUDO;
1344 return AMDGPU::COPY;
1345}
1346
1347const MCInstrDesc &
1349 bool IsIndirectSrc) const {
1350 if (IsIndirectSrc) {
1351 if (VecSize <= 32) // 4 bytes
1352 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1353 if (VecSize <= 64) // 8 bytes
1354 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1355 if (VecSize <= 96) // 12 bytes
1356 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1357 if (VecSize <= 128) // 16 bytes
1358 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1359 if (VecSize <= 160) // 20 bytes
1360 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1361 if (VecSize <= 192) // 24 bytes
1362 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1363 if (VecSize <= 224) // 28 bytes
1364 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1365 if (VecSize <= 256) // 32 bytes
1366 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1367 if (VecSize <= 288) // 36 bytes
1368 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1369 if (VecSize <= 320) // 40 bytes
1370 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1371 if (VecSize <= 352) // 44 bytes
1372 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1373 if (VecSize <= 384) // 48 bytes
1374 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1375 if (VecSize <= 512) // 64 bytes
1376 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1377 if (VecSize <= 1024) // 128 bytes
1378 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1379
1380 llvm_unreachable("unsupported size for IndirectRegReadGPRIDX pseudos");
1381 }
1382
1383 if (VecSize <= 32) // 4 bytes
1384 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1385 if (VecSize <= 64) // 8 bytes
1386 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1387 if (VecSize <= 96) // 12 bytes
1388 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1389 if (VecSize <= 128) // 16 bytes
1390 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1391 if (VecSize <= 160) // 20 bytes
1392 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1393 if (VecSize <= 192) // 24 bytes
1394 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1395 if (VecSize <= 224) // 28 bytes
1396 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1397 if (VecSize <= 256) // 32 bytes
1398 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1399 if (VecSize <= 288) // 36 bytes
1400 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1401 if (VecSize <= 320) // 40 bytes
1402 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1403 if (VecSize <= 352) // 44 bytes
1404 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1405 if (VecSize <= 384) // 48 bytes
1406 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1407 if (VecSize <= 512) // 64 bytes
1408 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1409 if (VecSize <= 1024) // 128 bytes
1410 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1411
1412 llvm_unreachable("unsupported size for IndirectRegWriteGPRIDX pseudos");
1413}
1414
1415static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize) {
1416 if (VecSize <= 32) // 4 bytes
1417 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1418 if (VecSize <= 64) // 8 bytes
1419 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1420 if (VecSize <= 96) // 12 bytes
1421 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1422 if (VecSize <= 128) // 16 bytes
1423 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1424 if (VecSize <= 160) // 20 bytes
1425 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1426 if (VecSize <= 192) // 24 bytes
1427 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1428 if (VecSize <= 224) // 28 bytes
1429 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1430 if (VecSize <= 256) // 32 bytes
1431 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1432 if (VecSize <= 288) // 36 bytes
1433 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1434 if (VecSize <= 320) // 40 bytes
1435 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1436 if (VecSize <= 352) // 44 bytes
1437 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1438 if (VecSize <= 384) // 48 bytes
1439 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1440 if (VecSize <= 512) // 64 bytes
1441 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1442 if (VecSize <= 1024) // 128 bytes
1443 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1444
1445 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1446}
1447
1448static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize) {
1449 if (VecSize <= 32) // 4 bytes
1450 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1451 if (VecSize <= 64) // 8 bytes
1452 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1453 if (VecSize <= 96) // 12 bytes
1454 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1455 if (VecSize <= 128) // 16 bytes
1456 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1457 if (VecSize <= 160) // 20 bytes
1458 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1459 if (VecSize <= 192) // 24 bytes
1460 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1461 if (VecSize <= 224) // 28 bytes
1462 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1463 if (VecSize <= 256) // 32 bytes
1464 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1465 if (VecSize <= 288) // 36 bytes
1466 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1467 if (VecSize <= 320) // 40 bytes
1468 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1469 if (VecSize <= 352) // 44 bytes
1470 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1471 if (VecSize <= 384) // 48 bytes
1472 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1473 if (VecSize <= 512) // 64 bytes
1474 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1475 if (VecSize <= 1024) // 128 bytes
1476 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1477
1478 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1479}
1480
1481static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize) {
1482 if (VecSize <= 64) // 8 bytes
1483 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1484 if (VecSize <= 128) // 16 bytes
1485 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1486 if (VecSize <= 256) // 32 bytes
1487 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1488 if (VecSize <= 512) // 64 bytes
1489 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1490 if (VecSize <= 1024) // 128 bytes
1491 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1492
1493 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1494}
1495
1496const MCInstrDesc &
1497SIInstrInfo::getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize,
1498 bool IsSGPR) const {
1499 if (IsSGPR) {
1500 switch (EltSize) {
1501 case 32:
1502 return get(getIndirectSGPRWriteMovRelPseudo32(VecSize));
1503 case 64:
1504 return get(getIndirectSGPRWriteMovRelPseudo64(VecSize));
1505 default:
1506 llvm_unreachable("invalid reg indexing elt size");
1507 }
1508 }
1509
1510 assert(EltSize == 32 && "invalid reg indexing elt size");
1512}
1513
1514static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1515 switch (Size) {
1516 case 4:
1517 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1518 case 8:
1519 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1520 case 12:
1521 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1522 case 16:
1523 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1524 : AMDGPU::SI_SPILL_S128_SAVE;
1525 case 20:
1526 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1527 : AMDGPU::SI_SPILL_S160_SAVE;
1528 case 24:
1529 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1530 : AMDGPU::SI_SPILL_S192_SAVE;
1531 case 28:
1532 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1533 : AMDGPU::SI_SPILL_S224_SAVE;
1534 case 32:
1535 return AMDGPU::SI_SPILL_S256_SAVE;
1536 case 36:
1537 return AMDGPU::SI_SPILL_S288_SAVE;
1538 case 40:
1539 return AMDGPU::SI_SPILL_S320_SAVE;
1540 case 44:
1541 return AMDGPU::SI_SPILL_S352_SAVE;
1542 case 48:
1543 return AMDGPU::SI_SPILL_S384_SAVE;
1544 case 64:
1545 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1546 : AMDGPU::SI_SPILL_S512_SAVE;
1547 case 128:
1548 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1549 : AMDGPU::SI_SPILL_S1024_SAVE;
1550 default:
1551 llvm_unreachable("unknown register size");
1552 }
1553}
1554
1555static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1556 switch (Size) {
1557 case 2:
1558 return AMDGPU::SI_SPILL_V16_SAVE;
1559 case 4:
1560 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1561 case 8:
1562 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1563 case 12:
1564 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1565 case 16:
1566 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1567 : AMDGPU::SI_SPILL_V128_SAVE;
1568 case 20:
1569 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1570 : AMDGPU::SI_SPILL_V160_SAVE;
1571 case 24:
1572 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1573 : AMDGPU::SI_SPILL_V192_SAVE;
1574 case 28:
1575 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1576 : AMDGPU::SI_SPILL_V224_SAVE;
1577 case 32:
1578 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1579 : AMDGPU::SI_SPILL_V256_SAVE;
1580 case 36:
1581 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1582 : AMDGPU::SI_SPILL_V288_SAVE;
1583 case 40:
1584 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1585 : AMDGPU::SI_SPILL_V320_SAVE;
1586 case 44:
1587 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1588 : AMDGPU::SI_SPILL_V352_SAVE;
1589 case 48:
1590 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1591 : AMDGPU::SI_SPILL_V384_SAVE;
1592 case 64:
1593 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1594 : AMDGPU::SI_SPILL_V512_SAVE;
1595 case 128:
1596 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1597 : AMDGPU::SI_SPILL_V1024_SAVE;
1598 default:
1599 llvm_unreachable("unknown register size");
1600 }
1601}
1602
1603static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1604 switch (Size) {
1605 case 4:
1606 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1607 : AMDGPU::SI_SPILL_AV32_SAVE;
1608 case 8:
1609 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1610 : AMDGPU::SI_SPILL_AV64_SAVE;
1611 case 12:
1612 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1613 : AMDGPU::SI_SPILL_AV96_SAVE;
1614 case 16:
1615 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1616 : AMDGPU::SI_SPILL_AV128_SAVE;
1617 case 20:
1618 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1619 : AMDGPU::SI_SPILL_AV160_SAVE;
1620 case 24:
1621 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1622 : AMDGPU::SI_SPILL_AV192_SAVE;
1623 case 28:
1624 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1625 : AMDGPU::SI_SPILL_AV224_SAVE;
1626 case 32:
1627 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1628 : AMDGPU::SI_SPILL_AV256_SAVE;
1629 case 36:
1630 return AMDGPU::SI_SPILL_AV288_SAVE;
1631 case 40:
1632 return AMDGPU::SI_SPILL_AV320_SAVE;
1633 case 44:
1634 return AMDGPU::SI_SPILL_AV352_SAVE;
1635 case 48:
1636 return AMDGPU::SI_SPILL_AV384_SAVE;
1637 case 64:
1638 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1639 : AMDGPU::SI_SPILL_AV512_SAVE;
1640 case 128:
1641 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1642 : AMDGPU::SI_SPILL_AV1024_SAVE;
1643 default:
1644 llvm_unreachable("unknown register size");
1645 }
1646}
1647
1648static unsigned getWWMRegSpillSaveOpcode(unsigned Size,
1649 bool IsVectorSuperClass) {
1650 // Currently, there is only 32-bit WWM register spills needed.
1651 if (Size != 4)
1652 llvm_unreachable("unknown wwm register spill size");
1653
1654 if (IsVectorSuperClass)
1655 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1656
1657 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1658}
1659
1661 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1662 const SIMachineFunctionInfo &MFI, bool NeedsCFI) const {
1663 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1664
1665 // Choose the right opcode if spilling a WWM register.
1667 return getWWMRegSpillSaveOpcode(Size, IsVectorSuperClass);
1668
1669 // TODO: Check if AGPRs are available
1670 if (ST.hasMAIInsts())
1671 return getAVSpillSaveOpcode(Size, NeedsCFI);
1672
1673 return getVGPRSpillSaveOpcode(Size, NeedsCFI);
1674}
1675
1676void SIInstrInfo::storeRegToStackSlotImpl(
1678 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1679 MachineInstr::MIFlag Flags, bool NeedsCFI) const {
1680 MachineFunction *MF = MBB.getParent();
1682 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1683 const DebugLoc &DL = MBB.findDebugLoc(MI);
1684
1685 MachinePointerInfo PtrInfo
1686 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1688 PtrInfo, MachineMemOperand::MOStore, FrameInfo.getObjectSize(FrameIndex),
1689 FrameInfo.getObjectAlign(FrameIndex));
1690 unsigned SpillSize = RI.getSpillSize(*RC);
1691
1692 MachineRegisterInfo &MRI = MF->getRegInfo();
1693 if (RI.isSGPRClass(RC)) {
1694 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1695 MFI->setHasSpilledSGPRs();
1696 assert(SrcReg != AMDGPU::M0 && "m0 should not be spilled");
1697 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1698 SrcReg != AMDGPU::EXEC && "exec should not be spilled");
1699
1700 // We are only allowed to create one new instruction when spilling
1701 // registers, so we need to use pseudo instruction for spilling SGPRs.
1702 const MCInstrDesc &OpDesc =
1703 get(getSGPRSpillSaveOpcode(SpillSize, NeedsCFI));
1704
1705 // The SGPR spill/restore instructions only work on number sgprs, so we need
1706 // to make sure we are using the correct register class.
1707 if (SrcReg.isVirtual() && SpillSize == 4) {
1708 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1709 }
1710
1711 BuildMI(MBB, MI, DL, OpDesc)
1712 .addReg(SrcReg, getKillRegState(isKill)) // data
1713 .addFrameIndex(FrameIndex) // addr
1714 .addMemOperand(MMO)
1716
1717 return;
1718 }
1719
1720 unsigned Opcode = getVectorRegSpillSaveOpcode(VReg ? VReg : SrcReg, RC,
1721 SpillSize, *MFI, NeedsCFI);
1722 MFI->setHasSpilledVGPRs();
1723
1724 BuildMI(MBB, MI, DL, get(Opcode))
1725 .addReg(SrcReg, getKillRegState(isKill)) // data
1726 .addFrameIndex(FrameIndex) // addr
1727 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1728 .addImm(0) // offset
1729 .addMemOperand(MMO);
1730}
1731
1734 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1735 MachineInstr::MIFlag Flags) const {
1736 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1737 false);
1738}
1739
1742 Register SrcReg, bool isKill,
1743 int FrameIndex,
1744 const TargetRegisterClass *RC) const {
1745 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, Register(),
1746 MachineInstr::NoFlags, true);
1747}
1748
1749static unsigned getSGPRSpillRestoreOpcode(unsigned Size) {
1750 switch (Size) {
1751 case 4:
1752 return AMDGPU::SI_SPILL_S32_RESTORE;
1753 case 8:
1754 return AMDGPU::SI_SPILL_S64_RESTORE;
1755 case 12:
1756 return AMDGPU::SI_SPILL_S96_RESTORE;
1757 case 16:
1758 return AMDGPU::SI_SPILL_S128_RESTORE;
1759 case 20:
1760 return AMDGPU::SI_SPILL_S160_RESTORE;
1761 case 24:
1762 return AMDGPU::SI_SPILL_S192_RESTORE;
1763 case 28:
1764 return AMDGPU::SI_SPILL_S224_RESTORE;
1765 case 32:
1766 return AMDGPU::SI_SPILL_S256_RESTORE;
1767 case 36:
1768 return AMDGPU::SI_SPILL_S288_RESTORE;
1769 case 40:
1770 return AMDGPU::SI_SPILL_S320_RESTORE;
1771 case 44:
1772 return AMDGPU::SI_SPILL_S352_RESTORE;
1773 case 48:
1774 return AMDGPU::SI_SPILL_S384_RESTORE;
1775 case 64:
1776 return AMDGPU::SI_SPILL_S512_RESTORE;
1777 case 128:
1778 return AMDGPU::SI_SPILL_S1024_RESTORE;
1779 default:
1780 llvm_unreachable("unknown register size");
1781 }
1782}
1783
1784static unsigned getVGPRSpillRestoreOpcode(unsigned Size) {
1785 switch (Size) {
1786 case 2:
1787 return AMDGPU::SI_SPILL_V16_RESTORE;
1788 case 4:
1789 return AMDGPU::SI_SPILL_V32_RESTORE;
1790 case 8:
1791 return AMDGPU::SI_SPILL_V64_RESTORE;
1792 case 12:
1793 return AMDGPU::SI_SPILL_V96_RESTORE;
1794 case 16:
1795 return AMDGPU::SI_SPILL_V128_RESTORE;
1796 case 20:
1797 return AMDGPU::SI_SPILL_V160_RESTORE;
1798 case 24:
1799 return AMDGPU::SI_SPILL_V192_RESTORE;
1800 case 28:
1801 return AMDGPU::SI_SPILL_V224_RESTORE;
1802 case 32:
1803 return AMDGPU::SI_SPILL_V256_RESTORE;
1804 case 36:
1805 return AMDGPU::SI_SPILL_V288_RESTORE;
1806 case 40:
1807 return AMDGPU::SI_SPILL_V320_RESTORE;
1808 case 44:
1809 return AMDGPU::SI_SPILL_V352_RESTORE;
1810 case 48:
1811 return AMDGPU::SI_SPILL_V384_RESTORE;
1812 case 64:
1813 return AMDGPU::SI_SPILL_V512_RESTORE;
1814 case 128:
1815 return AMDGPU::SI_SPILL_V1024_RESTORE;
1816 default:
1817 llvm_unreachable("unknown register size");
1818 }
1819}
1820
1821static unsigned getAVSpillRestoreOpcode(unsigned Size) {
1822 switch (Size) {
1823 case 4:
1824 return AMDGPU::SI_SPILL_AV32_RESTORE;
1825 case 8:
1826 return AMDGPU::SI_SPILL_AV64_RESTORE;
1827 case 12:
1828 return AMDGPU::SI_SPILL_AV96_RESTORE;
1829 case 16:
1830 return AMDGPU::SI_SPILL_AV128_RESTORE;
1831 case 20:
1832 return AMDGPU::SI_SPILL_AV160_RESTORE;
1833 case 24:
1834 return AMDGPU::SI_SPILL_AV192_RESTORE;
1835 case 28:
1836 return AMDGPU::SI_SPILL_AV224_RESTORE;
1837 case 32:
1838 return AMDGPU::SI_SPILL_AV256_RESTORE;
1839 case 36:
1840 return AMDGPU::SI_SPILL_AV288_RESTORE;
1841 case 40:
1842 return AMDGPU::SI_SPILL_AV320_RESTORE;
1843 case 44:
1844 return AMDGPU::SI_SPILL_AV352_RESTORE;
1845 case 48:
1846 return AMDGPU::SI_SPILL_AV384_RESTORE;
1847 case 64:
1848 return AMDGPU::SI_SPILL_AV512_RESTORE;
1849 case 128:
1850 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1851 default:
1852 llvm_unreachable("unknown register size");
1853 }
1854}
1855
1856static unsigned getWWMRegSpillRestoreOpcode(unsigned Size,
1857 bool IsVectorSuperClass) {
1858 // Currently, there is only 32-bit WWM register spills needed.
1859 if (Size != 4)
1860 llvm_unreachable("unknown wwm register spill size");
1861
1862 if (IsVectorSuperClass) // TODO: Always use this if there are AGPRs
1863 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1864
1865 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1866}
1867
1869 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1870 const SIMachineFunctionInfo &MFI) const {
1871 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1872
1873 // Choose the right opcode if restoring a WWM register.
1875 return getWWMRegSpillRestoreOpcode(Size, IsVectorSuperClass);
1876
1877 // TODO: Check if AGPRs are available
1878 if (ST.hasMAIInsts())
1880
1881 assert(!RI.isAGPRClass(RC));
1883}
1884
1887 Register DestReg, int FrameIndex,
1888 const TargetRegisterClass *RC,
1889 Register VReg, unsigned SubReg,
1890 MachineInstr::MIFlag Flags) const {
1891 MachineFunction *MF = MBB.getParent();
1893 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1894 const DebugLoc &DL = MBB.findDebugLoc(MI);
1895 unsigned SpillSize = RI.getSpillSize(*RC);
1896
1897 MachinePointerInfo PtrInfo
1898 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1899
1901 PtrInfo, MachineMemOperand::MOLoad, FrameInfo.getObjectSize(FrameIndex),
1902 FrameInfo.getObjectAlign(FrameIndex));
1903
1904 if (RI.isSGPRClass(RC)) {
1905 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1906 MFI->setHasSpilledSGPRs();
1907 assert(DestReg != AMDGPU::M0 && "m0 should not be reloaded into");
1908 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1909 DestReg != AMDGPU::EXEC && "exec should not be spilled");
1910
1911 // FIXME: Maybe this should not include a memoperand because it will be
1912 // lowered to non-memory instructions.
1913 const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize));
1914 if (DestReg.isVirtual() && SpillSize == 4) {
1915 MachineRegisterInfo &MRI = MF->getRegInfo();
1916 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1917 }
1918
1919 BuildMI(MBB, MI, DL, OpDesc, DestReg)
1920 .addFrameIndex(FrameIndex) // addr
1921 .addMemOperand(MMO)
1923
1924 return;
1925 }
1926
1927 unsigned Opcode = getVectorRegSpillRestoreOpcode(VReg ? VReg : DestReg, RC,
1928 SpillSize, *MFI);
1929 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
1930 .addFrameIndex(FrameIndex) // vaddr
1931 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1932 .addImm(0) // offset
1933 .addMemOperand(MMO);
1934}
1935
1940
1943 unsigned Quantity) const {
1944 DebugLoc DL = MBB.findDebugLoc(MI);
1945 unsigned MaxSNopCount = 1u << ST.getSNopBits();
1946 while (Quantity > 0) {
1947 unsigned Arg = std::min(Quantity, MaxSNopCount);
1948 Quantity -= Arg;
1949 BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
1950 }
1951}
1952
1956 const DebugLoc &DL) const {
1957 MachineFunction *MF = MBB.getParent();
1958 constexpr unsigned DoorbellIDMask = 0x3ff;
1959 constexpr unsigned ECQueueWaveAbort = 0x400;
1960
1961 MachineBasicBlock *TrapBB = &MBB;
1962 MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock();
1963
1964 if (!MBB.succ_empty() || std::next(MI.getIterator()) != MBB.end()) {
1965 MBB.splitAt(MI, /*UpdateLiveIns=*/false);
1966 TrapBB = MF->CreateMachineBasicBlock();
1967 BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB);
1968 MF->push_back(TrapBB);
1969 MBB.addSuccessor(TrapBB);
1970 }
1971 // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this
1972 // will be a nop.
1973 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP))
1974 .addImm(static_cast<unsigned>(GCNSubtarget::TrapID::LLVMAMDHSATrap));
1975 Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1976 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32),
1977 DoorbellReg)
1979 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
1980 .addUse(AMDGPU::M0);
1981 Register DoorbellRegMasked =
1982 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1983 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked)
1984 .addUse(DoorbellReg)
1985 .addImm(DoorbellIDMask);
1986 Register SetWaveAbortBit =
1987 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1988 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit)
1989 .addUse(DoorbellRegMasked)
1990 .addImm(ECQueueWaveAbort);
1991 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1992 .addUse(SetWaveAbortBit);
1993 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG))
1995 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1996 .addUse(AMDGPU::TTMP2);
1997 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB);
1998 TrapBB->addSuccessor(HaltLoopBB);
1999
2000 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5);
2001 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH))
2002 .addMBB(HaltLoopBB);
2003 MF->push_back(HaltLoopBB);
2004 HaltLoopBB->addSuccessor(HaltLoopBB);
2005
2006 return MBB.getNextNode();
2007}
2008
2010 switch (MI.getOpcode()) {
2011 default:
2012 if (MI.isMetaInstruction())
2013 return 0;
2014 return 1; // FIXME: Do wait states equal cycles?
2015
2016 case AMDGPU::S_NOP:
2017 return MI.getOperand(0).getImm() + 1;
2018 // SI_RETURN_TO_EPILOG is a fallthrough to code outside of the function. The
2019 // hazard, even if one exist, won't really be visible. Should we handle it?
2020 }
2021}
2022
2024 MachineBasicBlock &MBB = *MI.getParent();
2025 DebugLoc DL = MBB.findDebugLoc(MI);
2027
2028 switch (MI.getOpcode()) {
2029 default: return TargetInstrInfo::expandPostRAPseudo(MI);
2030 case AMDGPU::S_MOV_B64_term:
2031 // This is only a terminator to get the correct spill code placement during
2032 // register allocation.
2033 MI.setDesc(get(AMDGPU::S_MOV_B64));
2034 break;
2035
2036 case AMDGPU::S_MOV_B32_term:
2037 // This is only a terminator to get the correct spill code placement during
2038 // register allocation.
2039 MI.setDesc(get(AMDGPU::S_MOV_B32));
2040 break;
2041
2042 case AMDGPU::S_XOR_B64_term:
2043 // This is only a terminator to get the correct spill code placement during
2044 // register allocation.
2045 MI.setDesc(get(AMDGPU::S_XOR_B64));
2046 break;
2047
2048 case AMDGPU::S_XOR_B32_term:
2049 // This is only a terminator to get the correct spill code placement during
2050 // register allocation.
2051 MI.setDesc(get(AMDGPU::S_XOR_B32));
2052 break;
2053 case AMDGPU::S_OR_B64_term:
2054 // This is only a terminator to get the correct spill code placement during
2055 // register allocation.
2056 MI.setDesc(get(AMDGPU::S_OR_B64));
2057 break;
2058 case AMDGPU::S_OR_B32_term:
2059 // This is only a terminator to get the correct spill code placement during
2060 // register allocation.
2061 MI.setDesc(get(AMDGPU::S_OR_B32));
2062 break;
2063
2064 case AMDGPU::S_ANDN2_B64_term:
2065 // This is only a terminator to get the correct spill code placement during
2066 // register allocation.
2067 MI.setDesc(get(AMDGPU::S_ANDN2_B64));
2068 break;
2069
2070 case AMDGPU::S_ANDN2_B32_term:
2071 // This is only a terminator to get the correct spill code placement during
2072 // register allocation.
2073 MI.setDesc(get(AMDGPU::S_ANDN2_B32));
2074 break;
2075
2076 case AMDGPU::S_AND_B64_term:
2077 // This is only a terminator to get the correct spill code placement during
2078 // register allocation.
2079 MI.setDesc(get(AMDGPU::S_AND_B64));
2080 break;
2081
2082 case AMDGPU::S_AND_B32_term:
2083 // This is only a terminator to get the correct spill code placement during
2084 // register allocation.
2085 MI.setDesc(get(AMDGPU::S_AND_B32));
2086 break;
2087
2088 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2089 // This is only a terminator to get the correct spill code placement during
2090 // register allocation.
2091 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B64));
2092 break;
2093
2094 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2095 // This is only a terminator to get the correct spill code placement during
2096 // register allocation.
2097 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B32));
2098 break;
2099
2100 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2101 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2102 break;
2103 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2104 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2105 break;
2106
2107 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2108 MI.setDesc(get(AMDGPU::V_WRITELANE_B32));
2109 break;
2110
2111 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2112 MI.setDesc(get(AMDGPU::V_READLANE_B32));
2113 break;
2114 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2115 Register Dst = MI.getOperand(0).getReg();
2116 bool IsAGPR = SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst));
2117 MI.setDesc(
2118 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2119 break;
2120 }
2121 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2122 Register Dst = MI.getOperand(0).getReg();
2123 if (SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst))) {
2124 int64_t Imm = MI.getOperand(1).getImm();
2125
2126 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2127 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2128 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstLo)
2130 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstHi)
2131 .addImm(SignExtend64<32>(Imm >> 32));
2132 MI.eraseFromParent();
2133 break;
2134 }
2135
2136 [[fallthrough]];
2137 }
2138 case AMDGPU::V_MOV_B64_PSEUDO: {
2139 Register Dst = MI.getOperand(0).getReg();
2140 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2141 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2142
2143 const MCInstrDesc &Mov64Desc = get(AMDGPU::V_MOV_B64_e32);
2144 const TargetRegisterClass *Mov64RC = getRegClass(Mov64Desc, /*OpNum=*/0);
2145
2146 const MachineOperand &SrcOp = MI.getOperand(1);
2147 // FIXME: Will this work for 64-bit floating point immediates?
2148 assert(!SrcOp.isFPImm());
2149 if (ST.hasVMovB64Inst() && Mov64RC->contains(Dst)) {
2150 MI.setDesc(Mov64Desc);
2151 if (SrcOp.isReg() || isInlineConstant(MI, 1) ||
2152 (SrcOp.isImm() &&
2153 (isUInt<32>(SrcOp.getImm()) || ST.has64BitLiterals())) ||
2154 (SrcOp.isGlobal() && ST.has64BitLiterals()))
2155 break;
2156 }
2157 if (SrcOp.isGlobal()) {
2158 // The address is unknown until link time, so the PK_MOV inline-constant
2159 // shortcut cannot apply.
2160 const GlobalValue *GV = SrcOp.getGlobal();
2161 int64_t Offset = SrcOp.getOffset();
2162 unsigned BaseFlags, LoReloc, HiReloc;
2163 std::tie(BaseFlags, LoReloc, HiReloc) =
2165
2166 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2167 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2168 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2169 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2170 } else if (SrcOp.isImm()) {
2171 APInt Imm(64, SrcOp.getImm());
2172 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2173 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2174 const MCInstrDesc &PkMovDesc = get(AMDGPU::V_PK_MOV_B32);
2175 const TargetRegisterClass *PkMovRC = getRegClass(PkMovDesc, /*OpNum=*/0);
2176
2177 if (ST.hasPkMovB32() && Lo == Hi && isInlineConstant(Lo) &&
2178 PkMovRC->contains(Dst)) {
2179 BuildMI(MBB, MI, DL, PkMovDesc, Dst)
2181 .addImm(Lo.getSExtValue())
2183 .addImm(Lo.getSExtValue())
2184 .addImm(0) // op_sel_lo
2185 .addImm(0) // op_sel_hi
2186 .addImm(0) // neg_lo
2187 .addImm(0) // neg_hi
2188 .addImm(0); // clamp
2189 } else {
2190 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2191 .addImm(Lo.getSExtValue());
2192 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2193 .addImm(Hi.getSExtValue());
2194 }
2195 } else {
2196 assert(SrcOp.isReg());
2197 if (ST.hasPkMovB32() &&
2198 !RI.isAGPR(MBB.getParent()->getRegInfo(), SrcOp.getReg())) {
2199 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), Dst)
2200 .addImm(SISrcMods::OP_SEL_1) // src0_mod
2201 .addReg(SrcOp.getReg())
2203 .addReg(SrcOp.getReg())
2204 .addImm(0) // op_sel_lo
2205 .addImm(0) // op_sel_hi
2206 .addImm(0) // neg_lo
2207 .addImm(0) // neg_hi
2208 .addImm(0); // clamp
2209 } else {
2210 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2211 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0));
2212 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2213 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1));
2214 }
2215 }
2216 MI.eraseFromParent();
2217 break;
2218 }
2219 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2221 break;
2222 }
2223 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2224 const MachineOperand &SrcOp = MI.getOperand(1);
2225 assert(!SrcOp.isFPImm());
2226
2227 if (ST.has64BitLiterals()) {
2228 MI.setDesc(get(AMDGPU::S_MOV_B64));
2229 break;
2230 }
2231
2232 if (SrcOp.isGlobal()) {
2233 Register Dst = MI.getOperand(0).getReg();
2234 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2235 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2236 const GlobalValue *GV = SrcOp.getGlobal();
2237 int64_t Offset = SrcOp.getOffset();
2238 unsigned BaseFlags, LoReloc, HiReloc;
2239 std::tie(BaseFlags, LoReloc, HiReloc) =
2241
2242 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2243 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2244 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2245 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2246 MI.eraseFromParent();
2247 break;
2248 }
2249
2250 // SrcOp is immediate
2251 APInt Imm(64, SrcOp.getImm());
2252 if (Imm.isIntN(32) || isInlineConstant(Imm)) {
2253 MI.setDesc(get(AMDGPU::S_MOV_B64));
2254 break;
2255 }
2256
2257 Register Dst = MI.getOperand(0).getReg();
2258 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2259 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2260
2261 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2262 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2263 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2264 .addImm(Lo.getSExtValue());
2265 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2266 .addImm(Hi.getSExtValue());
2267 MI.eraseFromParent();
2268 break;
2269 }
2270 case AMDGPU::V_SET_INACTIVE_B32: {
2271 // Lower V_SET_INACTIVE_B32 to V_CNDMASK_B32.
2272 Register DstReg = MI.getOperand(0).getReg();
2273 BuildMI(MBB, MI, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2274 .add(MI.getOperand(3))
2275 .add(MI.getOperand(4))
2276 .add(MI.getOperand(1))
2277 .add(MI.getOperand(2))
2278 .add(MI.getOperand(5));
2279 MI.eraseFromParent();
2280 break;
2281 }
2282 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2283 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2284 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2285 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2286 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2287 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2288 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2289 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2290 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2291 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2292 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2293 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2294 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2295 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2296 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2297 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2298 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2299 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2300 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2301 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2302 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2303 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2304 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2305 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2306 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2307 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2308 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2309 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2310 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2311 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2312 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2313 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2314 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2315 const TargetRegisterClass *EltRC = getOpRegClass(MI, 2);
2316
2317 unsigned Opc;
2318 if (RI.hasVGPRs(EltRC)) {
2319 Opc = AMDGPU::V_MOVRELD_B32_e32;
2320 } else {
2321 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2322 : AMDGPU::S_MOVRELD_B32;
2323 }
2324
2325 const MCInstrDesc &OpDesc = get(Opc);
2326 Register VecReg = MI.getOperand(0).getReg();
2327 bool IsUndef = MI.getOperand(1).isUndef();
2328 unsigned SubReg = MI.getOperand(3).getImm();
2329 assert(VecReg == MI.getOperand(1).getReg());
2330
2332 BuildMI(MBB, MI, DL, OpDesc)
2333 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2334 .add(MI.getOperand(2))
2336 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2337
2338 const int ImpDefIdx =
2339 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2340 const int ImpUseIdx = ImpDefIdx + 1;
2341 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2342 MI.eraseFromParent();
2343 break;
2344 }
2345 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2346 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2347 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2348 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2349 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2350 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2351 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2352 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2353 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2354 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2355 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2356 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2357 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2358 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2359 assert(ST.useVGPRIndexMode());
2360 Register VecReg = MI.getOperand(0).getReg();
2361 bool IsUndef = MI.getOperand(1).isUndef();
2362 MachineOperand &Idx = MI.getOperand(3);
2363 Register SubReg = MI.getOperand(4).getImm();
2364
2365 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2366 .add(Idx)
2368 SetOn->getOperand(3).setIsUndef();
2369
2370 const MCInstrDesc &OpDesc = get(AMDGPU::V_MOV_B32_indirect_write);
2372 BuildMI(MBB, MI, DL, OpDesc)
2373 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2374 .add(MI.getOperand(2))
2376 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2377
2378 const int ImpDefIdx =
2379 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2380 const int ImpUseIdx = ImpDefIdx + 1;
2381 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2382
2383 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2384
2385 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2386
2387 MI.eraseFromParent();
2388 break;
2389 }
2390 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2391 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2392 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2393 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2394 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2395 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2396 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2397 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2398 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2399 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2400 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2401 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2402 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2403 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2404 assert(ST.useVGPRIndexMode());
2405 Register Dst = MI.getOperand(0).getReg();
2406 Register VecReg = MI.getOperand(1).getReg();
2407 bool IsUndef = MI.getOperand(1).isUndef();
2408 Register SubReg = MI.getOperand(3).getImm();
2409
2410 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2411 .add(MI.getOperand(2))
2413 SetOn->getOperand(3).setIsUndef();
2414
2415 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_indirect_read))
2416 .addDef(Dst)
2417 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2418 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2419
2420 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2421
2422 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2423
2424 MI.eraseFromParent();
2425 break;
2426 }
2427 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2428 MachineFunction &MF = *MBB.getParent();
2429 Register Reg = MI.getOperand(0).getReg();
2430 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2431 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2432 MachineOperand OpLo = MI.getOperand(1);
2433 MachineOperand OpHi = MI.getOperand(2);
2434
2435 // Create a bundle so these instructions won't be re-ordered by the
2436 // post-RA scheduler.
2437 MIBundleBuilder Bundler(MBB, MI);
2438 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2439
2440 // What we want here is an offset from the value returned by s_getpc (which
2441 // is the address of the s_add_u32 instruction) to the global variable, but
2442 // since the encoding of $symbol starts 4 bytes after the start of the
2443 // s_add_u32 instruction, we end up with an offset that is 4 bytes too
2444 // small. This requires us to add 4 to the global variable offset in order
2445 // to compute the correct address. Similarly for the s_addc_u32 instruction,
2446 // the encoding of $symbol starts 12 bytes after the start of the s_add_u32
2447 // instruction.
2448
2449 int64_t Adjust = 0;
2450 if (ST.hasGetPCZeroExtension()) {
2451 // Fix up hardware that does not sign-extend the 48-bit PC value by
2452 // inserting: s_sext_i32_i16 reghi, reghi
2453 Bundler.append(
2454 BuildMI(MF, DL, get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2455 Adjust += 4;
2456 }
2457
2458 if (OpLo.isGlobal())
2459 OpLo.setOffset(OpLo.getOffset() + Adjust + 4);
2460 Bundler.append(
2461 BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2462
2463 if (OpHi.isGlobal())
2464 OpHi.setOffset(OpHi.getOffset() + Adjust + 12);
2465 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi)
2466 .addReg(RegHi)
2467 .add(OpHi));
2468
2469 finalizeBundle(MBB, Bundler.begin());
2470
2471 MI.eraseFromParent();
2472 break;
2473 }
2474 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2475 MachineFunction &MF = *MBB.getParent();
2476 Register Reg = MI.getOperand(0).getReg();
2477 MachineOperand Op = MI.getOperand(1);
2478
2479 // Create a bundle so these instructions won't be re-ordered by the
2480 // post-RA scheduler.
2481 MIBundleBuilder Bundler(MBB, MI);
2482 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2483 if (Op.isGlobal())
2484 Op.setOffset(Op.getOffset() + 4);
2485 Bundler.append(
2486 BuildMI(MF, DL, get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(Op));
2487
2488 finalizeBundle(MBB, Bundler.begin());
2489
2490 MI.eraseFromParent();
2491 break;
2492 }
2493 case AMDGPU::ENTER_STRICT_WWM: {
2494 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2495 // Whole Wave Mode is entered.
2496 MI.setDesc(get(LMC.OrSaveExecOpc));
2497 break;
2498 }
2499 case AMDGPU::ENTER_STRICT_WQM: {
2500 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2501 // STRICT_WQM is entered.
2502 BuildMI(MBB, MI, DL, get(LMC.MovOpc), MI.getOperand(0).getReg())
2503 .addReg(LMC.ExecReg);
2504 BuildMI(MBB, MI, DL, get(LMC.WQMOpc), LMC.ExecReg).addReg(LMC.ExecReg);
2505
2506 MI.eraseFromParent();
2507 break;
2508 }
2509 case AMDGPU::EXIT_STRICT_WWM:
2510 case AMDGPU::EXIT_STRICT_WQM: {
2511 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2512 // WWM/STICT_WQM is exited.
2513 MI.setDesc(get(LMC.MovOpc));
2514 break;
2515 }
2516 case AMDGPU::SI_RETURN: {
2517 const MachineFunction *MF = MBB.getParent();
2518 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2519 const SIRegisterInfo *TRI = ST.getRegisterInfo();
2520 // Hiding the return address use with SI_RETURN may lead to extra kills in
2521 // the function and missing live-ins. We are fine in practice because callee
2522 // saved register handling ensures the register value is restored before
2523 // RET, but we need the undef flag here to appease the MachineVerifier
2524 // liveness checks.
2526 BuildMI(MBB, MI, DL, get(AMDGPU::S_SETPC_B64_return))
2527 .addReg(TRI->getReturnAddressReg(*MF), RegState::Undef);
2528
2529 MIB.copyImplicitOps(MI);
2530 MI.eraseFromParent();
2531 break;
2532 }
2533
2534 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2535 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2536 MI.setDesc(get(AMDGPU::S_MUL_U64));
2537 break;
2538
2539 case AMDGPU::S_GETPC_B64_pseudo:
2540 MI.setDesc(get(AMDGPU::S_GETPC_B64));
2541 if (ST.hasGetPCZeroExtension()) {
2542 Register Dst = MI.getOperand(0).getReg();
2543 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2544 // Fix up hardware that does not sign-extend the 48-bit PC value by
2545 // inserting: s_sext_i32_i16 dsthi, dsthi
2546 BuildMI(MBB, std::next(MI.getIterator()), DL, get(AMDGPU::S_SEXT_I32_I16),
2547 DstHi)
2548 .addReg(DstHi);
2549 }
2550 break;
2551
2552 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2553 assert(ST.hasBF16PackedInsts());
2554 MI.setDesc(get(AMDGPU::V_PK_MAX_NUM_BF16));
2555 MI.addOperand(MachineOperand::CreateImm(0)); // op_sel
2556 MI.addOperand(MachineOperand::CreateImm(0)); // neg_lo
2557 MI.addOperand(MachineOperand::CreateImm(0)); // neg_hi
2558 auto Op0 = getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
2559 Op0->setImm(Op0->getImm() | SISrcMods::OP_SEL_1);
2560 auto Op1 = getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
2561 Op1->setImm(Op1->getImm() | SISrcMods::OP_SEL_1);
2562 break;
2563 }
2564
2565 case AMDGPU::GET_STACK_BASE:
2566 // The stack starts at offset 0 unless we need to reserve some space at the
2567 // bottom.
2568 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*MBB.getParent())) {
2569 // When CWSR is used in dynamic VGPR mode, the trap handler needs to save
2570 // some of the VGPRs. The size of the required scratch space has already
2571 // been computed by prolog epilog insertion.
2572 const SIMachineFunctionInfo *MFI =
2573 MBB.getParent()->getInfo<SIMachineFunctionInfo>();
2574 unsigned VGPRSize = MFI->getScratchReservedForDynamicVGPRs();
2575 Register DestReg = MI.getOperand(0).getReg();
2576 BuildMI(MBB, MI, DL, get(AMDGPU::S_GETREG_B32), DestReg)
2579 // The MicroEngine ID is 0 for the graphics queue, and 1 or 2 for compute
2580 // (3 is unused, so we ignore it). Unfortunately, S_GETREG doesn't set
2581 // SCC, so we need to check for 0 manually.
2582 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)).addImm(0).addReg(DestReg);
2583 // Change the implicif-def of SCC to an explicit use (but first remove
2584 // the dead flag if present).
2585 MI.getOperand(MI.getNumExplicitOperands()).setIsDead(false);
2586 MI.getOperand(MI.getNumExplicitOperands()).setIsUse();
2587 MI.setDesc(get(AMDGPU::S_CMOVK_I32));
2588 MI.addOperand(MachineOperand::CreateImm(VGPRSize));
2589 } else {
2590 MI.setDesc(get(AMDGPU::S_MOV_B32));
2591 MI.addOperand(MachineOperand::CreateImm(0));
2592 MI.removeOperand(
2593 MI.getNumExplicitOperands()); // Drop implicit def of SCC.
2594 }
2595 break;
2596 }
2597
2598 return true;
2599}
2600
2603 unsigned SubIdx, const MachineInstr &Orig,
2604 LaneBitmask UsedLanes) const {
2605
2606 // Try shrinking the instruction to remat only the part needed for current
2607 // context.
2608 // TODO: Handle more cases.
2609 unsigned Opcode = Orig.getOpcode();
2610 switch (Opcode) {
2611 case AMDGPU::S_MOV_B64:
2612 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2613 if (SubIdx != 0)
2614 break;
2615
2616 if (!Orig.getOperand(1).isImm())
2617 break;
2618
2619 // Shrink S_MOV_B64 to S_MOV_B32 when UsedLanes indicates only a single
2620 // 32-bit lane of the 64-bit value is live at the rematerialization point.
2621 if (UsedLanes.all())
2622 break;
2623
2624 // Determine which half of the 64-bit immediate corresponds to the use.
2625 unsigned OrigSubReg = Orig.getOperand(0).getSubReg();
2626 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2627 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2628
2629 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2630 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2631
2632 if (NeedLo && NeedHi)
2633 break;
2634
2635 int64_t Imm64 = Orig.getOperand(1).getImm();
2636 int32_t Imm32 = NeedLo ? Lo_32(Imm64) : Hi_32(Imm64);
2637
2638 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2639
2640 // Emit S_MOV_B32 defining just the needed 32-bit subreg of DestReg.
2641 BuildMI(MBB, I, Orig.getDebugLoc(), get(AMDGPU::S_MOV_B32))
2642 .addReg(DestReg, RegState::Define | RegState::Undef, UseSubReg)
2643 .addImm(Imm32);
2644 return;
2645 }
2646
2647 case AMDGPU::S_LOAD_DWORDX16_IMM:
2648 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2649 if (SubIdx != 0)
2650 break;
2651
2652 if (I == MBB.end())
2653 break;
2654
2655 if (I->isBundled())
2656 break;
2657
2658 // Look for a single use of the register that is also a subreg.
2659 Register RegToFind = Orig.getOperand(0).getReg();
2660 MachineOperand *UseMO = nullptr;
2661 for (auto &CandMO : I->operands()) {
2662 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2663 continue;
2664 if (UseMO) {
2665 UseMO = nullptr;
2666 break;
2667 }
2668 UseMO = &CandMO;
2669 }
2670 if (!UseMO || UseMO->getSubReg() == AMDGPU::NoSubRegister)
2671 break;
2672
2673 unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
2674 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());
2675
2676 MachineFunction *MF = MBB.getParent();
2677 MachineRegisterInfo &MRI = MF->getRegInfo();
2678 assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");
2679
2680 unsigned NewOpcode = -1;
2681 if (SubregSize == 256)
2682 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2683 else if (SubregSize == 128)
2684 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2685 else
2686 break;
2687
2688 const MCInstrDesc &TID = get(NewOpcode);
2689 const TargetRegisterClass *NewRC =
2690 RI.getAllocatableClass(getRegClass(TID, 0));
2691 MRI.setRegClass(DestReg, NewRC);
2692
2693 UseMO->setReg(DestReg);
2694 UseMO->setSubReg(AMDGPU::NoSubRegister);
2695
2696 // Use a smaller load with the desired size, possibly with updated offset.
2697 MachineInstr *MI = MF->CloneMachineInstr(&Orig);
2698 MI->setDesc(TID);
2699 MI->getOperand(0).setReg(DestReg);
2700 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2701 if (Offset) {
2702 MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
2703 int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
2704 OffsetMO->setImm(FinalOffset);
2705 }
2707 for (const MachineMemOperand *MemOp : Orig.memoperands())
2708 NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
2709 SubregSize / 8));
2710 MI->setMemRefs(*MF, NewMMOs);
2711
2712 MBB.insert(I, MI);
2713 return;
2714 }
2715
2716 default:
2717 break;
2718 }
2719
2720 TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
2721}
2722
2723std::pair<MachineInstr*, MachineInstr*>
2725 assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2726
2727 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2729 ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
2730 MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
2731 return std::pair(&MI, nullptr);
2732 }
2733
2734 MachineBasicBlock &MBB = *MI.getParent();
2735 DebugLoc DL = MBB.findDebugLoc(MI);
2736 MachineFunction *MF = MBB.getParent();
2737 MachineRegisterInfo &MRI = MF->getRegInfo();
2738 Register Dst = MI.getOperand(0).getReg();
2739 unsigned Part = 0;
2740 MachineInstr *Split[2];
2741
2742 for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2743 auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
2744 if (Dst.isPhysical()) {
2745 MovDPP.addDef(RI.getSubReg(Dst, Sub));
2746 } else {
2747 assert(MRI.isSSA());
2748 auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2749 MovDPP.addDef(Tmp);
2750 }
2751
2752 for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
2753 const MachineOperand &SrcOp = MI.getOperand(I);
2754 assert(!SrcOp.isFPImm());
2755 if (SrcOp.isImm()) {
2756 APInt Imm(64, SrcOp.getImm());
2757 Imm.ashrInPlace(Part * 32);
2758 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2759 } else {
2760 assert(SrcOp.isReg());
2761 Register Src = SrcOp.getReg();
2762 if (Src.isPhysical())
2763 MovDPP.addReg(RI.getSubReg(Src, Sub));
2764 else
2765 MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
2766 }
2767 }
2768
2769 for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
2770 MovDPP.addImm(MO.getImm());
2771
2772 Split[Part] = MovDPP;
2773 ++Part;
2774 }
2775
2776 if (Dst.isVirtual())
2777 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
2778 .addReg(Split[0]->getOperand(0).getReg())
2779 .addImm(AMDGPU::sub0)
2780 .addReg(Split[1]->getOperand(0).getReg())
2781 .addImm(AMDGPU::sub1);
2782
2783 MI.eraseFromParent();
2784 return std::pair(Split[0], Split[1]);
2785}
2786
2787std::optional<DestSourcePair>
2789 if (MI.getOpcode() == AMDGPU::WWM_COPY)
2790 return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
2791
2792 return std::nullopt;
2793}
2794
2796 AMDGPU::OpName Src0OpName,
2797 MachineOperand &Src1,
2798 AMDGPU::OpName Src1OpName) const {
2799 MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
2800 if (!Src0Mods)
2801 return false;
2802
2803 MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
2804 assert(Src1Mods &&
2805 "All commutable instructions have both src0 and src1 modifiers");
2806
2807 int Src0ModsVal = Src0Mods->getImm();
2808 int Src1ModsVal = Src1Mods->getImm();
2809
2810 Src1Mods->setImm(Src0ModsVal);
2811 Src0Mods->setImm(Src1ModsVal);
2812 return true;
2813}
2814
2816 MachineOperand &RegOp,
2817 MachineOperand &NonRegOp) {
2818 Register Reg = RegOp.getReg();
2819 unsigned SubReg = RegOp.getSubReg();
2820 bool IsKill = RegOp.isKill();
2821 bool IsDead = RegOp.isDead();
2822 bool IsUndef = RegOp.isUndef();
2823 bool IsDebug = RegOp.isDebug();
2824
2825 if (NonRegOp.isImm())
2826 RegOp.ChangeToImmediate(NonRegOp.getImm());
2827 else if (NonRegOp.isFI())
2828 RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
2829 else if (NonRegOp.isGlobal()) {
2830 RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
2831 NonRegOp.getTargetFlags());
2832 } else
2833 return nullptr;
2834
2835 // Make sure we don't reinterpret a subreg index in the target flags.
2836 RegOp.setTargetFlags(NonRegOp.getTargetFlags());
2837
2838 NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
2839 NonRegOp.setSubReg(SubReg);
2840
2841 return &MI;
2842}
2843
2845 MachineOperand &NonRegOp1,
2846 MachineOperand &NonRegOp2) {
2847 unsigned TargetFlags = NonRegOp1.getTargetFlags();
2848 int64_t NonRegVal = NonRegOp1.getImm();
2849
2850 NonRegOp1.setImm(NonRegOp2.getImm());
2851 NonRegOp2.setImm(NonRegVal);
2852 NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
2853 NonRegOp2.setTargetFlags(TargetFlags);
2854 return &MI;
2855}
2856
2857bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
2858 unsigned OpIdx1) const {
2859 const MCInstrDesc &InstDesc = MI.getDesc();
2860 const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
2861 const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];
2862
2863 unsigned Opc = MI.getOpcode();
2864 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2865
2866 const MachineOperand &MO0 = MI.getOperand(OpIdx0);
2867 const MachineOperand &MO1 = MI.getOperand(OpIdx1);
2868
2869 // Swap doesn't breach constant bus or literal limits
2870 // It may move literal to position other than src0, this is not allowed
2871 // pre-gfx10 However, most test cases need literals in Src0 for VOP
2872 // FIXME: After gfx9, literal can be in place other than Src0
2873 if (isVALU(MI, /*AllowLDSDMA=*/true)) {
2874 if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
2875 !isInlineConstant(MO0, OpInfo1))
2876 return false;
2877 if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
2878 !isInlineConstant(MO1, OpInfo0))
2879 return false;
2880 }
2881
2882 if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
2883 if (OpInfo1.RegClass == -1)
2884 return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
2885 return isLegalRegOperand(MI, OpIdx1, MO0) &&
2886 (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
2887 }
2888 if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
2889 if (OpInfo0.RegClass == -1)
2890 return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
2891 return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
2892 isLegalRegOperand(MI, OpIdx0, MO1);
2893 }
2894
2895 // No need to check 64-bit literals since swapping does not bring new
2896 // 64-bit literals into current instruction to fold to 32-bit
2897
2898 return isImmOperandLegal(MI, OpIdx1, MO0);
2899}
2900
2902 unsigned Src0Idx,
2903 unsigned Src1Idx) const {
2904 assert(!NewMI && "this should never be used");
2905
2906 unsigned Opc = MI.getOpcode();
2907 int CommutedOpcode = commuteOpcode(Opc);
2908 if (CommutedOpcode == -1)
2909 return nullptr;
2910
2911 if (Src0Idx > Src1Idx)
2912 std::swap(Src0Idx, Src1Idx);
2913
2914 assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
2915 static_cast<int>(Src0Idx) &&
2916 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
2917 static_cast<int>(Src1Idx) &&
2918 "inconsistency with findCommutedOpIndices");
2919
2920 if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
2921 return nullptr;
2922
2923 MachineInstr *CommutedMI = nullptr;
2924 MachineOperand &Src0 = MI.getOperand(Src0Idx);
2925 MachineOperand &Src1 = MI.getOperand(Src1Idx);
2926 if (Src0.isReg() && Src1.isReg()) {
2927 // Be sure to copy the source modifiers to the right place.
2928 CommutedMI =
2929 TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
2930 } else if (Src0.isReg() && !Src1.isReg()) {
2931 CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
2932 } else if (!Src0.isReg() && Src1.isReg()) {
2933 CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
2934 } else if (Src0.isImm() && Src1.isImm()) {
2935 CommutedMI = swapImmOperands(MI, Src0, Src1);
2936 } else {
2937 // FIXME: Found two non registers to commute. This does happen.
2938 return nullptr;
2939 }
2940
2941 if (CommutedMI) {
2942 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
2943 Src1, AMDGPU::OpName::src1_modifiers);
2944
2945 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
2946 AMDGPU::OpName::src1_sel);
2947
2948 CommutedMI->setDesc(get(CommutedOpcode));
2949 }
2950
2951 return CommutedMI;
2952}
2953
2954// This needs to be implemented because the source modifiers may be inserted
2955// between the true commutable operands, and the base
2956// TargetInstrInfo::commuteInstruction uses it.
2958 unsigned &SrcOpIdx0,
2959 unsigned &SrcOpIdx1) const {
2960 return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
2961}
2962
2964 unsigned &SrcOpIdx0,
2965 unsigned &SrcOpIdx1) const {
2966 if (!Desc.isCommutable())
2967 return false;
2968
2969 unsigned Opc = Desc.getOpcode();
2970 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2971 if (Src0Idx == -1)
2972 return false;
2973
2974 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
2975 if (Src1Idx == -1)
2976 return false;
2977
2978 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
2979}
2980
2982 int64_t BrOffset) const {
2983 // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
2984 // because its dest block is unanalyzable.
2985 assert(isSOPP(BranchOp) || isSOPK(BranchOp));
2986
2987 // Convert to dwords.
2988 BrOffset /= 4;
2989
2990 // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
2991 // from the next instruction.
2992 BrOffset -= 1;
2993
2994 return isIntN(BranchOffsetBits, BrOffset);
2995}
2996
2999 return MI.getOperand(0).getMBB();
3000}
3001
3003 for (const MachineInstr &MI : MBB->terminators()) {
3004 if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
3005 MI.getOpcode() == AMDGPU::SI_LOOP)
3006 return true;
3007 }
3008 return false;
3009}
3010
3012 MachineBasicBlock &DestBB,
3013 MachineBasicBlock &RestoreBB,
3014 const DebugLoc &DL, int64_t BrOffset,
3015 RegScavenger *RS) const {
3016 assert(MBB.empty() &&
3017 "new block should be inserted for expanding unconditional branch");
3018 assert(MBB.pred_size() == 1);
3019 assert(RestoreBB.empty() &&
3020 "restore block should be inserted for restoring clobbered registers");
3021
3022 MachineFunction *MF = MBB.getParent();
3023 MachineRegisterInfo &MRI = MF->getRegInfo();
3025 auto I = MBB.end();
3026 auto &MCCtx = MF->getContext();
3027
3028 if (ST.useAddPC64Inst()) {
3029 MCSymbol *Offset =
3030 MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
3031 auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
3033 MCSymbol *PostAddPCLabel =
3034 MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
3035 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3036 auto *OffsetExpr = MCBinaryExpr::createSub(
3037 MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
3038 MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
3039 Offset->setVariableValue(OffsetExpr);
3040 return;
3041 }
3042
3043 assert(RS && "RegScavenger required for long branching");
3044
3045 // FIXME: Virtual register workaround for RegScavenger not working with empty
3046 // blocks.
3047 Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3048
3049 // Note: as this is used after hazard recognizer we need to apply some hazard
3050 // workarounds directly.
3051 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3052 ST.hasVALUReadSGPRHazard();
3053 auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
3054 if (FlushSGPRWrites)
3055 BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
3057 };
3058
3059 // We need to compute the offset relative to the instruction immediately after
3060 // s_getpc_b64. Insert pc arithmetic code before last terminator.
3061 MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
3062 ApplyHazardWorkarounds();
3063
3064 MCSymbol *PostGetPCLabel =
3065 MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
3066 GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);
3067
3068 MCSymbol *OffsetLo =
3069 MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
3070 MCSymbol *OffsetHi =
3071 MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
3072 BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
3073 .addReg(PCReg, RegState::Define, AMDGPU::sub0)
3074 .addReg(PCReg, {}, AMDGPU::sub0)
3075 .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
3076 BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
3077 .addReg(PCReg, RegState::Define, AMDGPU::sub1)
3078 .addReg(PCReg, {}, AMDGPU::sub1)
3079 .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
3080 ApplyHazardWorkarounds();
3081
3082 // Insert the indirect branch after the other terminator.
3083 BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
3084 .addReg(PCReg);
3085
3086 // If a spill is needed for the pc register pair, we need to insert a spill
3087 // restore block right before the destination block, and insert a short branch
3088 // into the old destination block's fallthrough predecessor.
3089 // e.g.:
3090 //
3091 // s_cbranch_scc0 skip_long_branch:
3092 //
3093 // long_branch_bb:
3094 // spill s[8:9]
3095 // s_getpc_b64 s[8:9]
3096 // s_add_u32 s8, s8, restore_bb
3097 // s_addc_u32 s9, s9, 0
3098 // s_setpc_b64 s[8:9]
3099 //
3100 // skip_long_branch:
3101 // foo;
3102 //
3103 // .....
3104 //
3105 // dest_bb_fallthrough_predecessor:
3106 // bar;
3107 // s_branch dest_bb
3108 //
3109 // restore_bb:
3110 // restore s[8:9]
3111 // fallthrough dest_bb
3112 ///
3113 // dest_bb:
3114 // buzz;
3115
3116 Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
3117 Register Scav;
3118
3119 // If we've previously reserved a register for long branches
3120 // avoid running the scavenger and just use those registers
3121 if (LongBranchReservedReg) {
3122 RS->enterBasicBlock(MBB);
3123 Scav = LongBranchReservedReg;
3124 } else {
3125 RS->enterBasicBlockEnd(MBB);
3126 Scav = RS->scavengeRegisterBackwards(
3127 AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
3128 /* RestoreAfter */ false, 0, /* AllowSpill */ false);
3129 }
3130 if (Scav) {
3131 RS->setRegUsed(Scav);
3132 MRI.replaceRegWith(PCReg, Scav);
3133 MRI.clearVirtRegs();
3134 } else {
3135 // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
3136 // SGPR spill.
3137 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
3138 const SIRegisterInfo *TRI = ST.getRegisterInfo();
3139 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3140 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3141 MRI.clearVirtRegs();
3142 }
3143
3144 MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
3145 // Now, the distance could be defined.
3147 MCSymbolRefExpr::create(DestLabel, MCCtx),
3148 MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
3149 // Add offset assignments.
3150 auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
3151 OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
3152 auto *ShAmt = MCConstantExpr::create(32, MCCtx);
3153 OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
3154}
3155
3156unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
3157 switch (Cond) {
3158 case SIInstrInfo::SCC_TRUE:
3159 return AMDGPU::S_CBRANCH_SCC1;
3160 case SIInstrInfo::SCC_FALSE:
3161 return AMDGPU::S_CBRANCH_SCC0;
3162 case SIInstrInfo::VCCNZ:
3163 return AMDGPU::S_CBRANCH_VCCNZ;
3164 case SIInstrInfo::VCCZ:
3165 return AMDGPU::S_CBRANCH_VCCZ;
3166 case SIInstrInfo::EXECNZ:
3167 return AMDGPU::S_CBRANCH_EXECNZ;
3168 case SIInstrInfo::EXECZ:
3169 return AMDGPU::S_CBRANCH_EXECZ;
3170 default:
3171 llvm_unreachable("invalid branch predicate");
3172 }
3173}
3174
3175SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
3176 switch (Opcode) {
3177 case AMDGPU::S_CBRANCH_SCC0:
3178 return SCC_FALSE;
3179 case AMDGPU::S_CBRANCH_SCC1:
3180 return SCC_TRUE;
3181 case AMDGPU::S_CBRANCH_VCCNZ:
3182 return VCCNZ;
3183 case AMDGPU::S_CBRANCH_VCCZ:
3184 return VCCZ;
3185 case AMDGPU::S_CBRANCH_EXECNZ:
3186 return EXECNZ;
3187 case AMDGPU::S_CBRANCH_EXECZ:
3188 return EXECZ;
3189 default:
3190 return INVALID_BR;
3191 }
3192}
3193
3197 MachineBasicBlock *&FBB,
3199 bool AllowModify) const {
3200 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3201 // Unconditional Branch
3202 TBB = I->getOperand(0).getMBB();
3203 return false;
3204 }
3205
3206 BranchPredicate Pred = getBranchPredicate(I->getOpcode());
3207 if (Pred == INVALID_BR)
3208 return true;
3209
3210 MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
3211 Cond.push_back(MachineOperand::CreateImm(Pred));
3212 Cond.push_back(I->getOperand(1)); // Save the branch register.
3213
3214 ++I;
3215
3216 if (I == MBB.end()) {
3217 // Conditional branch followed by fall-through.
3218 TBB = CondBB;
3219 return false;
3220 }
3221
3222 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3223 TBB = CondBB;
3224 FBB = I->getOperand(0).getMBB();
3225 return false;
3226 }
3227
3228 return true;
3229}
3230
3232 MachineBasicBlock *&FBB,
3234 bool AllowModify) const {
3235 MachineBasicBlock::iterator I = MBB.getFirstTerminator();
3236 auto E = MBB.end();
3237 if (I == E)
3238 return false;
3239
3240 // Skip over the instructions that are artificially terminators for special
3241 // exec management.
3242 while (I != E && !I->isBranch() && !I->isReturn()) {
3243 switch (I->getOpcode()) {
3244 case AMDGPU::S_MOV_B64_term:
3245 case AMDGPU::S_XOR_B64_term:
3246 case AMDGPU::S_OR_B64_term:
3247 case AMDGPU::S_ANDN2_B64_term:
3248 case AMDGPU::S_AND_B64_term:
3249 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3250 case AMDGPU::S_MOV_B32_term:
3251 case AMDGPU::S_XOR_B32_term:
3252 case AMDGPU::S_OR_B32_term:
3253 case AMDGPU::S_ANDN2_B32_term:
3254 case AMDGPU::S_AND_B32_term:
3255 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3256 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3257 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3258 break;
3259 case AMDGPU::SI_IF:
3260 case AMDGPU::SI_ELSE:
3261 case AMDGPU::SI_KILL_I1_TERMINATOR:
3262 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3263 // FIXME: It's messy that these need to be considered here at all.
3264 return true;
3265 default:
3266 llvm_unreachable("unexpected non-branch terminator inst");
3267 }
3268
3269 ++I;
3270 }
3271
3272 if (I == E)
3273 return false;
3274
3275 return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
3276}
3277
3279 int *BytesRemoved) const {
3280 unsigned Count = 0;
3281 unsigned RemovedSize = 0;
3282 for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
3283 // Skip over artificial terminators when removing instructions.
3284 if (MI.isBranch() || MI.isReturn()) {
3285 RemovedSize += getInstSizeInBytes(MI);
3286 MI.eraseFromParent();
3287 ++Count;
3288 }
3289 }
3290
3291 if (BytesRemoved)
3292 *BytesRemoved = RemovedSize;
3293
3294 return Count;
3295}
3296
3297// Copy the flags onto the implicit condition register operand.
3299 const MachineOperand &OrigCond) {
3300 CondReg.setIsUndef(OrigCond.isUndef());
3301 CondReg.setIsKill(OrigCond.isKill());
3302}
3303
3306 MachineBasicBlock *FBB,
3308 const DebugLoc &DL,
3309 int *BytesAdded) const {
3310 if (!FBB && Cond.empty()) {
3311 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3312 .addMBB(TBB);
3313 if (BytesAdded)
3314 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3315 return 1;
3316 }
3317
3318 assert(TBB && Cond[0].isImm());
3319
3320 unsigned Opcode
3321 = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));
3322
3323 if (!FBB) {
3324 MachineInstr *CondBr =
3325 BuildMI(&MBB, DL, get(Opcode))
3326 .addMBB(TBB);
3327
3328 // Copy the flags onto the implicit condition register operand.
3329 preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
3330 fixImplicitOperands(*CondBr);
3331
3332 if (BytesAdded)
3333 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3334 return 1;
3335 }
3336
3337 assert(TBB && FBB);
3338
3339 MachineInstr *CondBr =
3340 BuildMI(&MBB, DL, get(Opcode))
3341 .addMBB(TBB);
3342 fixImplicitOperands(*CondBr);
3343 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3344 .addMBB(FBB);
3345
3346 MachineOperand &CondReg = CondBr->getOperand(1);
3347 CondReg.setIsUndef(Cond[1].isUndef());
3348 CondReg.setIsKill(Cond[1].isKill());
3349
3350 if (BytesAdded)
3351 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3352
3353 return 2;
3354}
3355
3358 if (Cond.size() != 2) {
3359 return true;
3360 }
3361
3362 if (Cond[0].isImm()) {
3363 Cond[0].setImm(-Cond[0].getImm());
3364 return false;
3365 }
3366
3367 return true;
3368}
3369
3372 Register DstReg, Register TrueReg,
3373 Register FalseReg, int &CondCycles,
3374 int &TrueCycles, int &FalseCycles) const {
3375 switch (Cond[0].getImm()) {
3376 case VCCNZ:
3377 case VCCZ: {
3378 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3379 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3380 if (MRI.getRegClass(FalseReg) != RC)
3381 return false;
3382
3383 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3384 CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
3385
3386 // Limit to equal cost for branch vs. N v_cndmask_b32s.
3387 return RI.hasVGPRs(RC) && NumInsts <= 6;
3388 }
3389 case SCC_TRUE:
3390 case SCC_FALSE: {
3391 // FIXME: We could insert for VGPRs if we could replace the original compare
3392 // with a vector one.
3393 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3394 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3395 if (MRI.getRegClass(FalseReg) != RC)
3396 return false;
3397
3398 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3399
3400 // Multiples of 8 can do s_cselect_b64
3401 if (NumInsts % 2 == 0)
3402 NumInsts /= 2;
3403
3404 CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
3405 return RI.isSGPRClass(RC);
3406 }
3407 default:
3408 return false;
3409 }
3410}
3411
3415 Register TrueReg, Register FalseReg) const {
3416 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3417 if (Pred == VCCZ || Pred == SCC_FALSE) {
3418 Pred = static_cast<BranchPredicate>(-Pred);
3419 std::swap(TrueReg, FalseReg);
3420 }
3421
3422 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3423 const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
3424 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3425
3426 if (DstSize == 32) {
3428 if (Pred == SCC_TRUE) {
3429 Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
3430 .addReg(TrueReg)
3431 .addReg(FalseReg);
3432 } else {
3433 // Instruction's operands are backwards from what is expected.
3434 Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
3435 .addReg(FalseReg)
3436 .addReg(TrueReg);
3437 }
3438
3439 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3440 return;
3441 }
3442
3443 if (DstSize == 64 && Pred == SCC_TRUE) {
3445 BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
3446 .addReg(TrueReg)
3447 .addReg(FalseReg);
3448
3449 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3450 return;
3451 }
3452
3453 static const int16_t Sub0_15[] = {
3454 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3455 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3456 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3457 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3458 };
3459
3460 static const int16_t Sub0_15_64[] = {
3461 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3462 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3463 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3464 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3465 };
3466
3467 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3468 const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
3469 const int16_t *SubIndices = Sub0_15;
3470 int NElts = DstSize / 32;
3471
3472 // 64-bit select is only available for SALU.
3473 // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
3474 if (Pred == SCC_TRUE) {
3475 if (NElts % 2) {
3476 SelOp = AMDGPU::S_CSELECT_B32;
3477 EltRC = &AMDGPU::SGPR_32RegClass;
3478 } else {
3479 SelOp = AMDGPU::S_CSELECT_B64;
3480 EltRC = &AMDGPU::SGPR_64RegClass;
3481 SubIndices = Sub0_15_64;
3482 NElts /= 2;
3483 }
3484 }
3485
3487 MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);
3488
3489 I = MIB->getIterator();
3490
3492 for (int Idx = 0; Idx != NElts; ++Idx) {
3493 Register DstElt = MRI.createVirtualRegister(EltRC);
3494 Regs.push_back(DstElt);
3495
3496 unsigned SubIdx = SubIndices[Idx];
3497
3499 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3500 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3501 .addReg(FalseReg, {}, SubIdx)
3502 .addReg(TrueReg, {}, SubIdx);
3503 } else {
3504 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3505 .addReg(TrueReg, {}, SubIdx)
3506 .addReg(FalseReg, {}, SubIdx);
3507 }
3508
3509 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3511
3512 MIB.addReg(DstElt)
3513 .addImm(SubIdx);
3514 }
3515}
3516
3518
3519 if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
3520 return true;
3521
3522 switch (MI.getOpcode()) {
3523 case AMDGPU::S_ENDPGM:
3524 case AMDGPU::S_ENDPGM_SAVED:
3525 case AMDGPU::S_TRAP:
3526 case AMDGPU::S_GETREG_B32:
3527 case AMDGPU::S_SETREG_B32:
3528 case AMDGPU::S_SETREG_B32_mode:
3529 case AMDGPU::S_SETREG_IMM32_B32:
3530 case AMDGPU::S_SETREG_IMM32_B32_mode:
3531 case AMDGPU::S_SENDMSG:
3532 case AMDGPU::S_SENDMSGHALT:
3533 case AMDGPU::S_SENDMSG_RTN_B32:
3534 case AMDGPU::S_SENDMSG_RTN_B64:
3535 case AMDGPU::S_BARRIER_WAIT:
3536 case AMDGPU::S_BARRIER_SIGNAL_M0:
3537 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3538 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3539 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3540 return true;
3541 default:
3542 return false;
3543 }
3544}
3545
3547 switch (MI.getOpcode()) {
3548 case AMDGPU::V_MOV_B16_t16_e32:
3549 case AMDGPU::V_MOV_B16_t16_e64:
3550 case AMDGPU::V_MOV_B32_e32:
3551 case AMDGPU::V_MOV_B32_e64:
3552 case AMDGPU::V_MOV_B64_PSEUDO:
3553 case AMDGPU::V_MOV_B64_e32:
3554 case AMDGPU::V_MOV_B64_e64:
3555 case AMDGPU::S_MOV_B32:
3556 case AMDGPU::S_MOV_B64:
3557 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3558 case AMDGPU::COPY:
3559 case AMDGPU::WWM_COPY:
3560 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3561 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3562 case AMDGPU::V_ACCVGPR_MOV_B32:
3563 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3564 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3565 return true;
3566 default:
3567 return false;
3568 }
3569}
3570
3572 switch (MI.getOpcode()) {
3573 case AMDGPU::V_MOV_B16_t16_e32:
3574 case AMDGPU::V_MOV_B16_t16_e64:
3575 return 2;
3576 case AMDGPU::V_MOV_B32_e32:
3577 case AMDGPU::V_MOV_B32_e64:
3578 case AMDGPU::V_MOV_B64_PSEUDO:
3579 case AMDGPU::V_MOV_B64_e32:
3580 case AMDGPU::V_MOV_B64_e64:
3581 case AMDGPU::S_MOV_B32:
3582 case AMDGPU::S_MOV_B64:
3583 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3584 case AMDGPU::COPY:
3585 case AMDGPU::WWM_COPY:
3586 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3587 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3588 case AMDGPU::V_ACCVGPR_MOV_B32:
3589 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3590 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3591 return 1;
3592 default:
3593 llvm_unreachable("MI is not a foldable copy");
3594 }
3595}
3596
3597static constexpr AMDGPU::OpName ModifierOpNames[] = {
3598 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3599 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3600 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3601
3603 unsigned Opc = MI.getOpcode();
3604 for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
3605 int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
3606 if (Idx >= 0)
3607 MI.removeOperand(Idx);
3608 }
3609}
3610
3612 const MCInstrDesc &NewDesc) const {
3613 MI.setDesc(NewDesc);
3614
3615 // Remove any leftover implicit operands from mutating the instruction. e.g.
3616 // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
3617 // anymore.
3618 const MCInstrDesc &Desc = MI.getDesc();
3619 unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
3620 Desc.implicit_defs().size();
3621
3622 for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
3623 MI.removeOperand(I);
3624}
3625
3626std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
3627 unsigned SubRegIndex) {
3628 switch (SubRegIndex) {
3629 case AMDGPU::NoSubRegister:
3630 return Imm;
3631 case AMDGPU::sub0:
3632 return SignExtend64<32>(Imm);
3633 case AMDGPU::sub1:
3634 return SignExtend64<32>(Imm >> 32);
3635 case AMDGPU::lo16:
3636 return SignExtend64<16>(Imm);
3637 case AMDGPU::hi16:
3638 return SignExtend64<16>(Imm >> 16);
3639 case AMDGPU::sub1_lo16:
3640 return SignExtend64<16>(Imm >> 32);
3641 case AMDGPU::sub1_hi16:
3642 return SignExtend64<16>(Imm >> 48);
3643 default:
3644 return std::nullopt;
3645 }
3646
3647 llvm_unreachable("covered subregister switch");
3648}
3649
3650static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
3651 switch (Opc) {
3652 case AMDGPU::V_MAC_F16_e32:
3653 case AMDGPU::V_MAC_F16_e64:
3654 case AMDGPU::V_MAD_F16_e64:
3655 return AMDGPU::V_MADAK_F16;
3656 case AMDGPU::V_MAC_F32_e32:
3657 case AMDGPU::V_MAC_F32_e64:
3658 case AMDGPU::V_MAD_F32_e64:
3659 return AMDGPU::V_MADAK_F32;
3660 case AMDGPU::V_FMAC_F32_e32:
3661 case AMDGPU::V_FMAC_F32_e64:
3662 case AMDGPU::V_FMA_F32_e64:
3663 return AMDGPU::V_FMAAK_F32;
3664 case AMDGPU::V_FMAC_F16_e32:
3665 case AMDGPU::V_FMAC_F16_e64:
3666 case AMDGPU::V_FMAC_F16_t16_e64:
3667 case AMDGPU::V_FMAC_F16_fake16_e64:
3668 case AMDGPU::V_FMAC_F16_t16_e32:
3669 case AMDGPU::V_FMAC_F16_fake16_e32:
3670 case AMDGPU::V_FMA_F16_e64:
3671 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3672 ? AMDGPU::V_FMAAK_F16_t16
3673 : AMDGPU::V_FMAAK_F16_fake16
3674 : AMDGPU::V_FMAAK_F16;
3675 case AMDGPU::V_FMAC_F64_e32:
3676 case AMDGPU::V_FMAC_F64_e64:
3677 case AMDGPU::V_FMA_F64_e64:
3678 return AMDGPU::V_FMAAK_F64;
3679 default:
3680 llvm_unreachable("invalid instruction");
3681 }
3682}
3683
3684static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
3685 switch (Opc) {
3686 case AMDGPU::V_MAC_F16_e32:
3687 case AMDGPU::V_MAC_F16_e64:
3688 case AMDGPU::V_MAD_F16_e64:
3689 return AMDGPU::V_MADMK_F16;
3690 case AMDGPU::V_MAC_F32_e32:
3691 case AMDGPU::V_MAC_F32_e64:
3692 case AMDGPU::V_MAD_F32_e64:
3693 return AMDGPU::V_MADMK_F32;
3694 case AMDGPU::V_FMAC_F32_e32:
3695 case AMDGPU::V_FMAC_F32_e64:
3696 case AMDGPU::V_FMA_F32_e64:
3697 return AMDGPU::V_FMAMK_F32;
3698 case AMDGPU::V_FMAC_F16_e32:
3699 case AMDGPU::V_FMAC_F16_e64:
3700 case AMDGPU::V_FMAC_F16_t16_e64:
3701 case AMDGPU::V_FMAC_F16_fake16_e64:
3702 case AMDGPU::V_FMAC_F16_t16_e32:
3703 case AMDGPU::V_FMAC_F16_fake16_e32:
3704 case AMDGPU::V_FMA_F16_e64:
3705 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3706 ? AMDGPU::V_FMAMK_F16_t16
3707 : AMDGPU::V_FMAMK_F16_fake16
3708 : AMDGPU::V_FMAMK_F16;
3709 case AMDGPU::V_FMAC_F64_e32:
3710 case AMDGPU::V_FMAC_F64_e64:
3711 case AMDGPU::V_FMA_F64_e64:
3712 return AMDGPU::V_FMAMK_F64;
3713 default:
3714 llvm_unreachable("invalid instruction");
3715 }
3716}
3717
3719 Register Reg, MachineRegisterInfo *MRI) const {
3720 int64_t Imm;
3721 if (!getConstValDefinedInReg(DefMI, Reg, Imm))
3722 return false;
3723
3724 const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);
3725
3726 assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");
3727
3728 unsigned Opc = UseMI.getOpcode();
3729 if (Opc == AMDGPU::COPY) {
3730 assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");
3731
3732 Register DstReg = UseMI.getOperand(0).getReg();
3733 Register UseSubReg = UseMI.getOperand(1).getSubReg();
3734
3735 const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);
3736
3737 if (HasMultipleUses) {
3738 // TODO: This should fold in more cases with multiple use, but we need to
3739 // more carefully consider what those uses are.
3740 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));
3741
3742 // Avoid breaking up a 64-bit inline immediate into a subregister extract.
3743 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3744 return false;
3745
3746 // Most of the time folding a 32-bit inline constant is free (though this
3747 // might not be true if we can't later fold it into a real user).
3748 //
3749 // FIXME: This isInlineConstant check is imprecise if
3750 // getConstValDefinedInReg handled the tricky non-mov cases.
3751 if (ImmDefSize == 32 &&
3753 return false;
3754 }
3755
3756 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3757 RI.getSubRegIdxSize(UseSubReg) == 16;
3758
3759 if (Is16Bit) {
3760 if (RI.hasVGPRs(DstRC))
3761 return false; // Do not clobber vgpr_hi16
3762
3763 if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
3764 return false;
3765 }
3766
3767 MachineFunction *MF = UseMI.getMF();
3768
3769 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3770 MCRegister MovDstPhysReg =
3771 DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();
3772
3773 std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);
3774
3775 // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
3776 for (unsigned MovOp :
3777 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3778 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3779 const MCInstrDesc &MovDesc = get(MovOp);
3780
3781 const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
3782 if (Is16Bit) {
3783 // We just need to find a correctly sized register class, so the
3784 // subregister index compatibility doesn't matter since we're statically
3785 // extracting the immediate value.
3786 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3787 if (!MovDstRC)
3788 continue;
3789
3790 if (MovDstPhysReg) {
3791 // FIXME: We probably should not do this. If there is a live value in
3792 // the high half of the register, it will be corrupted.
3793 MovDstPhysReg =
3794 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3795 if (!MovDstPhysReg)
3796 continue;
3797 }
3798 }
3799
3800 // Result class isn't the right size, try the next instruction.
3801 if (MovDstPhysReg) {
3802 if (!MovDstRC->contains(MovDstPhysReg))
3803 return false;
3804 } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
3805 // TODO: This will be overly conservative in the case of 16-bit virtual
3806 // SGPRs. We could hack up the virtual register uses to use a compatible
3807 // 32-bit class.
3808 continue;
3809 }
3810
3811 const MCOperandInfo &OpInfo = MovDesc.operands()[1];
3812
3813 // Ensure the interpreted immediate value is a valid operand in the new
3814 // mov.
3815 //
3816 // FIXME: isImmOperandLegal should have form that doesn't require existing
3817 // MachineInstr or MachineOperand
3818 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3819 !isInlineConstant(*SubRegImm, OpInfo.OperandType))
3820 break;
3821
3822 NewOpc = MovOp;
3823 break;
3824 }
3825
3826 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
3827 return false;
3828
3829 if (Is16Bit) {
3830 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
3831 if (MovDstPhysReg)
3832 UseMI.getOperand(0).setReg(MovDstPhysReg);
3833 assert(UseMI.getOperand(1).getReg().isVirtual());
3834 }
3835
3836 const MCInstrDesc &NewMCID = get(NewOpc);
3837 UseMI.setDesc(NewMCID);
3838 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
3839 UseMI.addImplicitDefUseOperands(*MF);
3840 return true;
3841 }
3842
3843 if (HasMultipleUses)
3844 return false;
3845
3846 if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
3847 Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
3848 Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
3849 Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
3850 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3851 Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
3852 Opc == AMDGPU::V_FMAC_F64_e64) {
3853 // Don't fold if we are using source or output modifiers. The new VOP2
3854 // instructions don't have them.
3856 return false;
3857
3858 // If this is a free constant, there's no reason to do this.
3859 // TODO: We could fold this here instead of letting SIFoldOperands do it
3860 // later.
3861 int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
3862
3863 // Any src operand can be used for the legality check.
3864 if (isInlineConstant(UseMI, Src0Idx, Imm))
3865 return false;
3866
3867 MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);
3868
3869 MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
3870 MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);
3871
3872 auto CopyRegOperandToNarrowerRC =
3873 [MRI, this](MachineInstr &MI, unsigned OpNo,
3874 const TargetRegisterClass *NewRC) -> void {
3875 if (!MI.getOperand(OpNo).isReg())
3876 return;
3877 Register Reg = MI.getOperand(OpNo).getReg();
3878 const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
3879 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
3880 return;
3881 Register Tmp = MRI->createVirtualRegister(NewRC);
3882 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
3883 get(AMDGPU::COPY), Tmp)
3884 .addReg(Reg);
3885 MI.getOperand(OpNo).setReg(Tmp);
3886 MI.getOperand(OpNo).setIsKill();
3887 };
3888
3889 // Multiplied part is the constant: Use v_madmk_{f16, f32}.
3890 if ((Src0->isReg() && Src0->getReg() == Reg) ||
3891 (Src1->isReg() && Src1->getReg() == Reg)) {
3892 MachineOperand *RegSrc =
3893 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
3894 if (!RegSrc->isReg())
3895 return false;
3896 if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
3897 ST.getConstantBusLimit(Opc) < 2)
3898 return false;
3899
3900 if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
3901 return false;
3902
3903 // If src2 is also a literal constant then we have to choose which one to
3904 // fold. In general it is better to choose madak so that the other literal
3905 // can be materialized in an sgpr instead of a vgpr:
3906 // s_mov_b32 s0, literal
3907 // v_madak_f32 v0, s0, v0, literal
3908 // Instead of:
3909 // v_mov_b32 v1, literal
3910 // v_madmk_f32 v0, v0, literal, v1
3911 MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
3912 if (Def && Def->isMoveImmediate() &&
3913 !isInlineConstant(Def->getOperand(1)))
3914 return false;
3915
3916 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
3917 if (pseudoToMCOpcode(NewOpc) == -1)
3918 return false;
3919
3920 const std::optional<int64_t> SubRegImm = extractSubregFromImm(
3921 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
3922
3923 // FIXME: This would be a lot easier if we could return a new instruction
3924 // instead of having to modify in place.
3925
3926 Register SrcReg = RegSrc->getReg();
3927 unsigned SrcSubReg = RegSrc->getSubReg();
3928 Src0->setReg(SrcReg);
3929 Src0->setSubReg(SrcSubReg);
3930 Src0->setIsKill(RegSrc->isKill());
3931
3932 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
3933 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3934 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3935 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
3936 UseMI.untieRegOperand(
3937 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
3938
3939 Src1->ChangeToImmediate(*SubRegImm);
3940
3942 UseMI.setDesc(get(NewOpc));
3943
3944 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
3945 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
3946 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
3947 Register Tmp = MRI->createVirtualRegister(NewRC);
3948 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
3949 UseMI.getDebugLoc(), get(AMDGPU::COPY),
3950 UseMI.getOperand(0).getReg())
3951 .addReg(Tmp, RegState::Kill);
3952 UseMI.getOperand(0).setReg(Tmp);
3953 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
3954 CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
3955 }
3956
3957 bool DeleteDef = MRI->use_nodbg_empty(Reg);
3958 if (DeleteDef)
3959 DefMI.eraseFromParent();
3960
3961 return true;
3962 }
3963
3964 // Added part is the constant: Use v_madak_{f16, f32}.
3965 if (Src2->isReg() && Src2->getReg() == Reg) {
3966 if (ST.getConstantBusLimit(Opc) < 2) {
3967 // Not allowed to use constant bus for another operand.
3968 // We can however allow an inline immediate as src0.
3969 bool Src0Inlined = false;
3970 if (Src0->isReg()) {
3971 // Try to inline constant if possible.
3972 // If the Def moves immediate and the use is single
3973 // We are saving VGPR here.
3974 MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
3975 if (Def && Def->isMoveImmediate() &&
3976 isInlineConstant(Def->getOperand(1)) &&
3977 MRI->hasOneNonDBGUse(Src0->getReg())) {
3978 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
3979 Src0Inlined = true;
3980 } else if (ST.getConstantBusLimit(Opc) <= 1 &&
3981 RI.isSGPRReg(*MRI, Src0->getReg())) {
3982 return false;
3983 }
3984 // VGPR is okay as Src0 - fallthrough
3985 }
3986
3987 if (Src1->isReg() && !Src0Inlined) {
3988 // We have one slot for inlinable constant so far - try to fill it
3989 MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
3990 if (Def && Def->isMoveImmediate() &&
3991 isInlineConstant(Def->getOperand(1)) &&
3992 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
3993 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
3994 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
3995 return false;
3996 // VGPR is okay as Src1 - fallthrough
3997 }
3998 }
3999
4000 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4001 if (pseudoToMCOpcode(NewOpc) == -1)
4002 return false;
4003
4004 // FIXME: This would be a lot easier if we could return a new instruction
4005 // instead of having to modify in place.
4006
4007 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4008 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4009 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4010 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4011 UseMI.untieRegOperand(
4012 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4013
4014 const std::optional<int64_t> SubRegImm =
4016
4017 // ChangingToImmediate adds Src2 back to the instruction.
4018 Src2->ChangeToImmediate(*SubRegImm);
4019
4020 // These come before src2.
4022 UseMI.setDesc(get(NewOpc));
4023
4024 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4025 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4026 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4027 Register Tmp = MRI->createVirtualRegister(NewRC);
4028 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4029 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4030 UseMI.getOperand(0).getReg())
4031 .addReg(Tmp, RegState::Kill);
4032 UseMI.getOperand(0).setReg(Tmp);
4033 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4034 CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
4035 }
4036
4037 // It might happen that UseMI was commuted
4038 // and we now have SGPR as SRC1. If so 2 inlined
4039 // constant and SGPR are illegal.
4041
4042 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4043 if (DeleteDef)
4044 DefMI.eraseFromParent();
4045
4046 return true;
4047 }
4048 }
4049
4050 return false;
4051}
4052
4053static bool
4056 if (BaseOps1.size() != BaseOps2.size())
4057 return false;
4058 for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
4059 if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
4060 return false;
4061 }
4062 return true;
4063}
4064
4065static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
4066 LocationSize WidthB, int OffsetB) {
4067 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4068 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4069 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4070 return LowWidth.hasValue() &&
4071 LowOffset + (int)LowWidth.getValue() <= HighOffset;
4072}
4073
4074bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
4075 const MachineInstr &MIb) const {
4076 SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
4077 int64_t Offset0, Offset1;
4078 LocationSize Dummy0 = LocationSize::precise(0);
4079 LocationSize Dummy1 = LocationSize::precise(0);
4080 bool Offset0IsScalable, Offset1IsScalable;
4081 if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
4082 Dummy0, &RI) ||
4083 !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
4084 Dummy1, &RI))
4085 return false;
4086
4087 if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
4088 return false;
4089
4090 if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
4091 // FIXME: Handle ds_read2 / ds_write2.
4092 return false;
4093 }
4094 LocationSize Width0 = MIa.memoperands().front()->getSize();
4095 LocationSize Width1 = MIb.memoperands().front()->getSize();
4096 return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
4097}
4098
4100 const MachineInstr &MIb) const {
4101 assert(MIa.mayLoadOrStore() &&
4102 "MIa must load from or modify a memory location");
4103 assert(MIb.mayLoadOrStore() &&
4104 "MIb must load from or modify a memory location");
4105
4107 return false;
4108
4109 // XXX - Can we relax this between address spaces?
4110 if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
4111 return false;
4112
4113 if (isLDSDMA(MIa) || isLDSDMA(MIb))
4114 return false;
4115
4116 if (MIa.isBundle() || MIb.isBundle())
4117 return false;
4118
4119 // TODO: Should we check the address space from the MachineMemOperand? That
4120 // would allow us to distinguish objects we know don't alias based on the
4121 // underlying address space, even if it was lowered to a different one,
4122 // e.g. private accesses lowered to use MUBUF instructions on a scratch
4123 // buffer.
4124 if (isDS(MIa)) {
4125 if (isDS(MIb))
4126 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4127
4128 return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
4129 }
4130
4131 if (isMUBUF(MIa) || isMTBUF(MIa)) {
4132 if (isMUBUF(MIb) || isMTBUF(MIb))
4133 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4134
4135 if (isFLAT(MIb))
4136 return isFLATScratch(MIb);
4137
4138 return !isSMRD(MIb);
4139 }
4140
4141 if (isSMRD(MIa)) {
4142 if (isSMRD(MIb))
4143 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4144
4145 if (isFLAT(MIb))
4146 return isFLATScratch(MIb);
4147
4148 return !isMUBUF(MIb) && !isMTBUF(MIb);
4149 }
4150
4151 if (isFLAT(MIa)) {
4152 if (isFLAT(MIb)) {
4153 if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
4154 (isFLATGlobal(MIa) && isFLATScratch(MIb)))
4155 return true;
4156
4157 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4158 }
4159
4160 return false;
4161 }
4162
4163 return false;
4164}
4165
4167 int64_t &Imm, MachineInstr **DefMI = nullptr) {
4168 if (Reg.isPhysical())
4169 return false;
4170 auto *Def = MRI.getUniqueVRegDef(Reg);
4171 if (Def && SIInstrInfo::isFoldableCopy(*Def) && Def->getOperand(1).isImm()) {
4172 Imm = Def->getOperand(1).getImm();
4173 if (DefMI)
4174 *DefMI = Def;
4175 return true;
4176 }
4177 return false;
4178}
4179
4180static bool getFoldableImm(const MachineOperand *MO, int64_t &Imm,
4181 MachineInstr **DefMI = nullptr) {
4182 if (!MO->isReg())
4183 return false;
4184 const MachineFunction *MF = MO->getParent()->getMF();
4185 const MachineRegisterInfo &MRI = MF->getRegInfo();
4186 return getFoldableImm(MO->getReg(), MRI, Imm, DefMI);
4187}
4188
4190 MachineInstr &NewMI) {
4191 if (LV) {
4192 unsigned NumOps = MI.getNumOperands();
4193 for (unsigned I = 1; I < NumOps; ++I) {
4194 MachineOperand &Op = MI.getOperand(I);
4195 if (Op.isReg() && Op.isKill())
4196 LV->replaceKillInstruction(Op.getReg(), MI, NewMI);
4197 }
4198 }
4199}
4200
4201static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
4202 switch (Opc) {
4203 case AMDGPU::V_MAC_F16_e32:
4204 case AMDGPU::V_MAC_F16_e64:
4205 return AMDGPU::V_MAD_F16_e64;
4206 case AMDGPU::V_MAC_F32_e32:
4207 case AMDGPU::V_MAC_F32_e64:
4208 return AMDGPU::V_MAD_F32_e64;
4209 case AMDGPU::V_MAC_LEGACY_F32_e32:
4210 case AMDGPU::V_MAC_LEGACY_F32_e64:
4211 return AMDGPU::V_MAD_LEGACY_F32_e64;
4212 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4213 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4214 return AMDGPU::V_FMA_LEGACY_F32_e64;
4215 case AMDGPU::V_FMAC_F16_e32:
4216 case AMDGPU::V_FMAC_F16_e64:
4217 case AMDGPU::V_FMAC_F16_t16_e64:
4218 case AMDGPU::V_FMAC_F16_fake16_e64:
4219 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4220 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4221 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4222 : AMDGPU::V_FMA_F16_gfx9_e64;
4223 case AMDGPU::V_FMAC_F32_e32:
4224 case AMDGPU::V_FMAC_F32_e64:
4225 return AMDGPU::V_FMA_F32_e64;
4226 case AMDGPU::V_FMAC_F64_e32:
4227 case AMDGPU::V_FMAC_F64_e64:
4228 return AMDGPU::V_FMA_F64_e64;
4229 default:
4230 llvm_unreachable("invalid instruction");
4231 }
4232}
4233
4234/// Helper struct for the implementation of 3-address conversion to communicate
4235/// updates made to instruction operands.
4237 /// Other instruction whose def is no longer used by the converted
4238 /// instruction.
4240};
4241
4243 LiveVariables *LV,
4244 LiveIntervals *LIS) const {
4245 MachineBasicBlock &MBB = *MI.getParent();
4246 MachineInstr *CandidateMI = &MI;
4247
4248 if (MI.isBundle()) {
4249 // This is a temporary placeholder for bundle handling that enables us to
4250 // exercise the relevant code paths in the two-address instruction pass.
4251 if (MI.getBundleSize() != 1)
4252 return nullptr;
4253 CandidateMI = MI.getNextNode();
4254 }
4255
4257 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4258 if (!NewMI)
4259 return nullptr;
4260
4261 if (MI.isBundle()) {
4262 CandidateMI->eraseFromBundle();
4263
4264 for (MachineOperand &MO : MI.all_defs()) {
4265 if (MO.isTied())
4266 MI.untieRegOperand(MO.getOperandNo());
4267 }
4268 } else {
4269 updateLiveVariables(LV, MI, *NewMI);
4270 if (LIS) {
4271 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
4272 // SlotIndex of defs needs to be updated when converting to early-clobber
4273 MachineOperand &Def = NewMI->getOperand(0);
4274 if (Def.isEarlyClobber() && Def.isReg() &&
4275 LIS->hasInterval(Def.getReg())) {
4276 SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
4277 SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
4278 auto &LI = LIS->getInterval(Def.getReg());
4279 auto UpdateDefIndex = [&](LiveRange &LR) {
4280 auto *S = LR.find(OldIndex);
4281 if (S != LR.end() && S->start == OldIndex) {
4282 assert(S->valno && S->valno->def == OldIndex);
4283 S->start = NewIndex;
4284 S->valno->def = NewIndex;
4285 }
4286 };
4287 UpdateDefIndex(LI);
4288 for (auto &SR : LI.subranges())
4289 UpdateDefIndex(SR);
4290 }
4291 }
4292 }
4293
4294 if (U.RemoveMIUse) {
4295 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4296 // The only user is the instruction which will be killed.
4297 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4298
4299 if (MRI.hasOneNonDBGUse(DefReg)) {
4300 // We cannot just remove the DefMI here, calling pass will crash.
4301 U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
4302 U.RemoveMIUse->getOperand(0).setIsDead(true);
4303 for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
4304 U.RemoveMIUse->removeOperand(I);
4305 if (LV)
4306 LV->getVarInfo(DefReg).AliveBlocks.clear();
4307 }
4308
4309 if (MI.isBundle()) {
4310 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4311 if (!VRI.Reads && !VRI.Writes) {
4312 for (MachineOperand &MO : MI.all_uses()) {
4313 if (MO.isReg() && MO.getReg() == DefReg) {
4314 assert(MO.getSubReg() == 0 &&
4315 "tied sub-registers in bundles currently not supported");
4316 MI.removeOperand(MO.getOperandNo());
4317 break;
4318 }
4319 }
4320
4321 if (LIS)
4322 LIS->shrinkToUses(&LIS->getInterval(DefReg));
4323 }
4324 } else if (LIS) {
4325 LiveInterval &DefLI = LIS->getInterval(DefReg);
4326
4327 // We cannot delete the original instruction here, so hack out the use
4328 // in the original instruction with a dummy register so we can use
4329 // shrinkToUses to deal with any multi-use edge cases. Other targets do
4330 // not have the complexity of deleting a use to consider here.
4331 Register DummyReg = MRI.cloneVirtualRegister(DefReg);
4332 for (MachineOperand &MIOp : MI.uses()) {
4333 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4334 MIOp.setIsUndef(true);
4335 MIOp.setReg(DummyReg);
4336 }
4337 }
4338
4339 if (MI.isBundle()) {
4340 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4341 if (!VRI.Reads && !VRI.Writes) {
4342 for (MachineOperand &MIOp : MI.uses()) {
4343 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4344 MIOp.setIsUndef(true);
4345 MIOp.setReg(DummyReg);
4346 }
4347 }
4348 }
4349
4350 MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
4351 false, /*isUndef=*/true));
4352 }
4353
4354 LIS->shrinkToUses(&DefLI);
4355 }
4356 }
4357
4358 return MI.isBundle() ? &MI : NewMI;
4359}
4360
4362SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
4363 ThreeAddressUpdates &U) const {
4364 MachineBasicBlock &MBB = *MI.getParent();
4365 unsigned Opc = MI.getOpcode();
4366
4367 // Handle MFMA.
4368 int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
4369 if (NewMFMAOpc != -1) {
4371 BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
4372 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4373 MIB.add(MI.getOperand(I));
4374 return MIB;
4375 }
4376
4377 if (SIInstrInfo::isWMMA(MI)) {
4378 unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
4379 MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4380 .setMIFlags(MI.getFlags());
4381 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4382 MIB->addOperand(MI.getOperand(I));
4383 return MIB;
4384 }
4385
4386 assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4387 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4388 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4389 "present pre-RA");
4390
4391 // Handle MAC/FMAC.
4392 bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
4393 bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4394 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4395 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4396 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4397 bool Src0Literal = false;
4398
4399 switch (Opc) {
4400 default:
4401 return nullptr;
4402 case AMDGPU::V_MAC_F16_e64:
4403 case AMDGPU::V_FMAC_F16_e64:
4404 case AMDGPU::V_FMAC_F16_t16_e64:
4405 case AMDGPU::V_FMAC_F16_fake16_e64:
4406 case AMDGPU::V_MAC_F32_e64:
4407 case AMDGPU::V_MAC_LEGACY_F32_e64:
4408 case AMDGPU::V_FMAC_F32_e64:
4409 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4410 case AMDGPU::V_FMAC_F64_e64:
4411 break;
4412 case AMDGPU::V_MAC_F16_e32:
4413 case AMDGPU::V_FMAC_F16_e32:
4414 case AMDGPU::V_MAC_F32_e32:
4415 case AMDGPU::V_MAC_LEGACY_F32_e32:
4416 case AMDGPU::V_FMAC_F32_e32:
4417 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4418 case AMDGPU::V_FMAC_F64_e32: {
4419 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
4420 AMDGPU::OpName::src0);
4421 const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
4422 if (!Src0->isReg() && !Src0->isImm())
4423 return nullptr;
4424
4425 if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
4426 Src0Literal = true;
4427
4428 break;
4429 }
4430 }
4431
4432 MachineInstrBuilder MIB;
4433 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
4434 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
4435 const MachineOperand *Src0Mods =
4436 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
4437 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4438 const MachineOperand *Src1Mods =
4439 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
4440 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4441 const MachineOperand *Src2Mods =
4442 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
4443 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
4444 const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
4445 const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);
4446
4447 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4448 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4449 // If we have an SGPR input, we will violate the constant bus restriction.
4450 (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
4451 !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
4452 MachineInstr *DefMI = nullptr;
4453
4454 int64_t Imm;
4455 if (!Src0Literal && getFoldableImm(Src2, Imm, &DefMI)) {
4456 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4457 if (pseudoToMCOpcode(NewOpc) != -1) {
4458 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4459 .add(*Dst)
4460 .add(*Src0)
4461 .add(*Src1)
4462 .addImm(Imm)
4463 .setMIFlags(MI.getFlags());
4464 U.RemoveMIUse = DefMI;
4465 return MIB;
4466 }
4467 }
4468 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4469 if (!Src0Literal && getFoldableImm(Src1, Imm, &DefMI)) {
4470 if (pseudoToMCOpcode(NewOpc) != -1) {
4471 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4472 .add(*Dst)
4473 .add(*Src0)
4474 .addImm(Imm)
4475 .add(*Src2)
4476 .setMIFlags(MI.getFlags());
4477 U.RemoveMIUse = DefMI;
4478 return MIB;
4479 }
4480 }
4481 if (Src0Literal || getFoldableImm(Src0, Imm, &DefMI)) {
4482 if (Src0Literal) {
4483 Imm = Src0->getImm();
4484 DefMI = nullptr;
4485 }
4486 if (pseudoToMCOpcode(NewOpc) != -1 &&
4488 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4489 Src1)) {
4490 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4491 .add(*Dst)
4492 .add(*Src1)
4493 .addImm(Imm)
4494 .add(*Src2)
4495 .setMIFlags(MI.getFlags());
4496 U.RemoveMIUse = DefMI;
4497 return MIB;
4498 }
4499 }
4500 }
4501
4502 // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
4503 // if VOP3 does not allow a literal operand.
4504 if (Src0Literal && !ST.hasVOP3Literal())
4505 return nullptr;
4506
4507 unsigned NewOpc = getNewFMAInst(ST, Opc);
4508
4509 if (pseudoToMCOpcode(NewOpc) == -1)
4510 return nullptr;
4511
4512 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4513 .add(*Dst)
4514 .addImm(Src0Mods ? Src0Mods->getImm() : 0)
4515 .add(*Src0)
4516 .addImm(Src1Mods ? Src1Mods->getImm() : 0)
4517 .add(*Src1)
4518 .addImm(Src2Mods ? Src2Mods->getImm() : 0)
4519 .add(*Src2)
4520 .addImm(Clamp ? Clamp->getImm() : 0)
4521 .addImm(Omod ? Omod->getImm() : 0)
4522 .setMIFlags(MI.getFlags());
4523 if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
4524 MIB.addImm(OpSel ? OpSel->getImm() : 0);
4525 return MIB;
4526}
4527
4528// It's not generally safe to move VALU instructions across these since it will
4529// start using the register as a base index rather than directly.
4530// XXX - Why isn't hasSideEffects sufficient for these?
4532 switch (MI.getOpcode()) {
4533 case AMDGPU::S_SET_GPR_IDX_ON:
4534 case AMDGPU::S_SET_GPR_IDX_MODE:
4535 case AMDGPU::S_SET_GPR_IDX_OFF:
4536 return true;
4537 default:
4538 return false;
4539 }
4540}
4541
4543 const MachineBasicBlock *MBB,
4544 const MachineFunction &MF) const {
4545 // Skipping the check for SP writes in the base implementation. The reason it
4546 // was added was apparently due to compile time concerns.
4547 //
4548 // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
4549 // but is probably avoidable.
4550
4551 // Copied from base implementation.
4552 // Terminators and labels can't be scheduled around.
4553 if (MI.isTerminator() || MI.isPosition())
4554 return true;
4555
4556 // INLINEASM_BR can jump to another block
4557 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4558 return true;
4559
4560 if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
4561 return true;
4562
4563 // Target-independent instructions do not have an implicit-use of EXEC, even
4564 // when they operate on VGPRs. Treating EXEC modifications as scheduling
4565 // boundaries prevents incorrect movements of such instructions.
4566 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4567 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4568 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4569 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4570 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4572}
4573
4575 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4576 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4577 Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
4578}
4579
4581 // Instructions that access scratch use FLAT encoding or BUF encodings.
4582 if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
4583 return false;
4584
4585 // SCRATCH instructions always access scratch.
4586 if (isFLATScratch(MI))
4587 return true;
4588
4589 // If FLAT_SCRATCH registers are not initialized, we can never access scratch
4590 // via the aperture.
4591 if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
4592 return false;
4593
4594 // If there are no memory operands then conservatively assume the flat
4595 // operation may access scratch.
4596 if (MI.memoperands_empty())
4597 return true;
4598
4599 // See if any memory operand specifies an address space that involves scratch.
4600 return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
4601 unsigned AS = Memop->getAddrSpace();
4602 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4603 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4604 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4605 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4606 }
4607 return AS == AMDGPUAS::PRIVATE_ADDRESS;
4608 });
4609}
4610
4612 assert(isFLAT(MI));
4613
4614 // All flat instructions use the VMEM counter except prefetch.
4615 if (!usesVM_CNT(MI))
4616 return false;
4617
4618 // If there are no memory operands then conservatively assume the flat
4619 // operation may access VMEM.
4620 if (MI.memoperands_empty())
4621 return true;
4622
4623 // See if any memory operand specifies an address space that involves VMEM.
4624 // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
4625 // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
4626 // (GDS) address space is not supported by flat operations. Therefore, simply
4627 // return true unless only the LDS address space is found.
4628 for (const MachineMemOperand *Memop : MI.memoperands()) {
4629 unsigned AS = Memop->getAddrSpace();
4631 if (AS != AMDGPUAS::LOCAL_ADDRESS)
4632 return true;
4633 }
4634
4635 return false;
4636}
4637
4639 bool TgSplit) const {
4640 assert(isFLAT(MI));
4641
4642 // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
4643 if (!usesLGKM_CNT(MI))
4644 return false;
4645
4646 // If in tgsplit mode then there can be no use of LDS.
4647 if (TgSplit)
4648 return false;
4649
4650 // If there are no memory operands then conservatively assume the flat
4651 // operation may access LDS.
4652 if (MI.memoperands_empty())
4653 return true;
4654
4655 // See if any memory operand specifies an address space that involves LDS.
4656 for (const MachineMemOperand *Memop : MI.memoperands()) {
4657 unsigned AS = Memop->getAddrSpace();
4659 return true;
4660 }
4661
4662 return false;
4663}
4664
4666 // Skip the full operand and register alias search modifiesRegister
4667 // does. There's only a handful of instructions that touch this, it's only an
4668 // implicit def, and doesn't alias any other registers.
4669 return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
4670}
4671
4673 unsigned Opcode = MI.getOpcode();
4674
4675 if (MI.mayStore() && isSMRD(MI))
4676 return true; // scalar store or atomic
4677
4678 // This will terminate the function when other lanes may need to continue.
4679 if (MI.isReturn())
4680 return true;
4681
4682 // These instructions cause shader I/O that may cause hardware lockups
4683 // when executed with an empty EXEC mask.
4684 //
4685 // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
4686 // EXEC = 0, but checking for that case here seems not worth it
4687 // given the typical code patterns.
4688 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4689 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4690 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4691 Opcode == AMDGPU::S_SETHALT)
4692 return true;
4693
4694 if (MI.isCall() || MI.isInlineAsm())
4695 return true; // conservative assumption
4696
4697 // Assume that barrier interactions are only intended with active lanes.
4698 if (isBarrier(Opcode))
4699 return true;
4700
4701 // A mode change is a scalar operation that influences vector instructions.
4703 return true;
4704
4705 // These are like SALU instructions in terms of effects, so it's questionable
4706 // whether we should return true for those.
4707 //
4708 // However, executing them with EXEC = 0 causes them to operate on undefined
4709 // data, which we avoid by returning true here.
4710 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4711 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4712 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4713 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4714 return true;
4715
4716 return false;
4717}
4718
4720 const MachineInstr &MI) const {
4721 if (MI.isMetaInstruction())
4722 return false;
4723
4724 // This won't read exec if this is an SGPR->SGPR copy.
4725 if (MI.isCopyLike()) {
4726 if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
4727 return true;
4728
4729 // Make sure this isn't copying exec as a normal operand
4730 return MI.readsRegister(AMDGPU::EXEC, &RI);
4731 }
4732
4733 // Make a conservative assumption about the callee.
4734 if (MI.isCall())
4735 return true;
4736
4737 // Be conservative with any unhandled generic opcodes.
4738 if (!isTargetSpecificOpcode(MI.getOpcode()))
4739 return true;
4740
4741 return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
4742}
4743
4745 switch (Imm.getBitWidth()) {
4746 case 1: // This likely will be a condition code mask.
4747 return true;
4748
4749 case 32:
4750 return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
4751 ST.hasInv2PiInlineImm());
4752 case 64:
4753 return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
4754 ST.hasInv2PiInlineImm());
4755 case 16:
4756 return ST.has16BitInsts() &&
4757 AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
4758 ST.hasInv2PiInlineImm());
4759 default:
4760 llvm_unreachable("invalid bitwidth");
4761 }
4762}
4763
4765 APInt IntImm = Imm.bitcastToAPInt();
4766 int64_t IntImmVal = IntImm.getSExtValue();
4767 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4768 switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
4769 default:
4770 llvm_unreachable("invalid fltSemantics");
4773 return isInlineConstant(IntImm);
4775 return ST.has16BitInsts() &&
4776 AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
4778 return ST.has16BitInsts() &&
4779 AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
4780 }
4781}
4782
4783bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
4784 // MachineOperand provides no way to tell the true operand size, since it only
4785 // records a 64-bit value. We need to know the size to determine if a 32-bit
4786 // floating point immediate bit pattern is legal for an integer immediate. It
4787 // would be for any 32-bit integer operand, but would not be for a 64-bit one.
4788 switch (OperandType) {
4798 int32_t Trunc = static_cast<int32_t>(Imm);
4799 return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
4800 }
4808 return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
4811 // We would expect inline immediates to not be concerned with an integer/fp
4812 // distinction. However, in the case of 16-bit integer operations, the
4813 // "floating point" values appear to not work. It seems read the low 16-bits
4814 // of 32-bit immediates, which happens to always work for the integer
4815 // values.
4816 //
4817 // See llvm bugzilla 46302.
4818 //
4819 // TODO: Theoretically we could use op-sel to use the high bits of the
4820 // 32-bit FP values.
4829 return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
4834 return false;
4837 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
4838 // A few special case instructions have 16-bit operands on subtargets
4839 // where 16-bit instructions are not legal.
4840 // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
4841 // constants in these cases
4842 int16_t Trunc = static_cast<int16_t>(Imm);
4843 return ST.has16BitInsts() &&
4844 AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
4845 }
4846
4847 return false;
4848 }
4851 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
4852 int16_t Trunc = static_cast<int16_t>(Imm);
4853 return ST.has16BitInsts() &&
4854 AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
4855 }
4856 return false;
4857 }
4861 return false;
4863 return isLegalAV64PseudoImm(Imm);
4866 // Always embedded in the instruction for free.
4867 return true;
4877 // Just ignore anything else.
4878 return false;
4879 default:
4880 llvm_unreachable("invalid operand type");
4881 }
4882}
4883
4884static bool compareMachineOp(const MachineOperand &Op0,
4885 const MachineOperand &Op1) {
4886 if (Op0.getType() != Op1.getType())
4887 return false;
4888
4889 switch (Op0.getType()) {
4891 return Op0.getReg() == Op1.getReg();
4893 return Op0.getImm() == Op1.getImm();
4894 default:
4895 llvm_unreachable("Didn't expect to be comparing these operand types");
4896 }
4897}
4898
4900 const MCOperandInfo &OpInfo) const {
4901 if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
4902 return true;
4903
4904 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
4905 return false;
4906
4907 if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
4908 return true;
4909
4910 return ST.hasVOP3Literal();
4911}
4912
4913bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
4914 int64_t ImmVal) const {
4915 const unsigned Opc = InstDesc.getOpcode();
4916 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
4917 if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
4918 OpNo == static_cast<unsigned>(Src1Idx))
4919 return false;
4920
4921 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
4922 if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
4923 if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
4924 OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
4925 AMDGPU::OpName::src2))
4926 return false;
4927
4928 if (ST.hasBF16InlineConstFromUpperFP32() && isVOP1(Opc)) {
4929 if ((OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_BF16 ||
4930 OpInfo.OperandType == AMDGPU::OPERAND_REG_INLINE_C_BF16) &&
4931 isInlineConstant(ImmVal, OpInfo.OperandType))
4932 return false;
4933 }
4934
4935 return RI.opCanUseInlineConstant(OpInfo.OperandType);
4936 }
4937
4938 return isLiteralOperandLegal(InstDesc, OpInfo);
4939}
4940
4941bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
4942 const MachineOperand &MO) const {
4943 if (MO.isImm())
4944 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
4945
4946 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
4947 "unexpected imm-like operand kind");
4948 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
4949 return isLiteralOperandLegal(InstDesc, OpInfo);
4950}
4951
4953 // 2 32-bit inline constants packed into one.
4954 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
4955 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
4956}
4957
4958bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
4959 // GFX90A does not have V_MUL_LEGACY_F32_e32.
4960 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
4961 return false;
4962
4963 int Op32 = AMDGPU::getVOPe32(Opcode);
4964 if (Op32 == -1)
4965 return false;
4966
4967 return pseudoToMCOpcode(Op32) != -1;
4968}
4969
4970bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
4971 // The src0_modifier operand is present on all instructions
4972 // that have modifiers.
4973
4974 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
4975}
4976
4978 AMDGPU::OpName OpName) const {
4979 const MachineOperand *Mods = getNamedOperand(MI, OpName);
4980 return Mods && Mods->getImm();
4981}
4982
4984 return any_of(ModifierOpNames,
4985 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
4986}
4987
4989 const MachineRegisterInfo &MRI) const {
4990 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4991 // Can't shrink instruction with three operands.
4992 if (Src2) {
4993 switch (MI.getOpcode()) {
4994 default: return false;
4995
4996 case AMDGPU::V_ADDC_U32_e64:
4997 case AMDGPU::V_SUBB_U32_e64:
4998 case AMDGPU::V_SUBBREV_U32_e64: {
4999 const MachineOperand *Src1
5000 = getNamedOperand(MI, AMDGPU::OpName::src1);
5001 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
5002 return false;
5003 // Additional verification is needed for sdst/src2.
5004 return true;
5005 }
5006 case AMDGPU::V_MAC_F16_e64:
5007 case AMDGPU::V_MAC_F32_e64:
5008 case AMDGPU::V_MAC_LEGACY_F32_e64:
5009 case AMDGPU::V_FMAC_F16_e64:
5010 case AMDGPU::V_FMAC_F16_t16_e64:
5011 case AMDGPU::V_FMAC_F16_fake16_e64:
5012 case AMDGPU::V_FMAC_F32_e64:
5013 case AMDGPU::V_FMAC_F64_e64:
5014 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5015 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
5016 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
5017 return false;
5018 break;
5019
5020 case AMDGPU::V_CNDMASK_B32_e64:
5021 break;
5022 }
5023 }
5024
5025 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
5026 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5027 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
5028 return false;
5029
5030 // Make sure src0 isn't using any modifiers.
5031 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
5032 return false;
5033
5034 // Can it be shrunk to a valid 32 bit opcode?
5035 if (!hasVALU32BitEncoding(MI.getOpcode()))
5036 return false;
5037
5038 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
5039 if (Src0 && Src0->isImm()) {
5040 unsigned Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5041 if (!isImmOperandLegal(
5042 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5043 *Src0))
5044 return false;
5045 }
5046
5047 // Check output modifiers
5048 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
5049 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
5050 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
5051 // TODO: Can we avoid checking bound_ctrl/fi here?
5052 // They are only used by permlane*_swap special case.
5053 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
5054 !hasModifiersSet(MI, AMDGPU::OpName::fi);
5055}
5056
5057// Set VCC operand with all flags from \p Orig, except for setting it as
5058// implicit.
5060 const MachineOperand &Orig) {
5061
5062 for (MachineOperand &Use : MI.implicit_operands()) {
5063 if (Use.isUse() &&
5064 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
5065 Use.setIsUndef(Orig.isUndef());
5066 Use.setIsKill(Orig.isKill());
5067 return;
5068 }
5069 }
5070}
5071
5073 unsigned Op32) const {
5074 MachineBasicBlock *MBB = MI.getParent();
5075
5076 const MCInstrDesc &Op32Desc = get(Op32);
5077 MachineInstrBuilder Inst32 =
5078 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
5079 .setMIFlags(MI.getFlags());
5080
5081 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
5082 // For VOPC instructions, this is replaced by an implicit def of vcc.
5083
5084 // We assume the defs of the shrunk opcode are in the same order, and the
5085 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
5086 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
5087 Inst32.add(MI.getOperand(I));
5088
5089 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5090
5091 int Idx = MI.getNumExplicitDefs();
5092 for (const MachineOperand &Use : MI.explicit_uses()) {
5093 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
5095 continue;
5096
5097 if (&Use == Src2) {
5098 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5099 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
5100 // replaced with an implicit read of vcc or vcc_lo. The implicit read
5101 // of vcc was already added during the initial BuildMI, but we
5102 // 1) may need to change vcc to vcc_lo to preserve the original register
5103 // 2) have to preserve the original flags.
5104 copyFlagsToImplicitVCC(*Inst32, *Src2);
5105 continue;
5106 }
5107 }
5108
5109 Inst32.add(Use);
5110 }
5111
5112 // FIXME: Losing implicit operands
5113 fixImplicitOperands(*Inst32);
5114 return Inst32;
5115}
5116
5118 // Null is free
5119 Register Reg = RegOp.getReg();
5120 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5121 return false;
5122
5123 // SGPRs use the constant bus
5124
5125 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
5126 // physical register operands should also count, except for exec.
5127 if (RegOp.isImplicit())
5128 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5129
5130 // SGPRs use the constant bus
5131 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5132 AMDGPU::SReg_64RegClass.contains(Reg);
5133}
5134
5136 const MachineRegisterInfo &MRI) const {
5137 Register Reg = RegOp.getReg();
5138 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5139 : physRegUsesConstantBus(RegOp);
5140}
5141
5143 const MachineOperand &MO,
5144 const MCOperandInfo &OpInfo) const {
5145 // Literal constants use the constant bus.
5146 if (!MO.isReg())
5147 return !isInlineConstant(MO, OpInfo);
5148
5149 Register Reg = MO.getReg();
5150 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5152}
5153
5155 for (const MachineOperand &MO : MI.implicit_operands()) {
5156 // We only care about reads.
5157 if (MO.isDef())
5158 continue;
5159
5160 switch (MO.getReg()) {
5161 case AMDGPU::VCC:
5162 case AMDGPU::VCC_LO:
5163 case AMDGPU::VCC_HI:
5164 case AMDGPU::M0:
5165 case AMDGPU::FLAT_SCR:
5166 return MO.getReg();
5167
5168 default:
5169 break;
5170 }
5171 }
5172
5173 return Register();
5174}
5175
5176static bool shouldReadExec(const MachineInstr &MI) {
5177 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5178 switch (MI.getOpcode()) {
5179 case AMDGPU::V_READLANE_B32:
5180 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5181 case AMDGPU::V_WRITELANE_B32:
5182 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5183 return false;
5184 }
5185
5186 return true;
5187 }
5188
5189 if (MI.isPreISelOpcode() ||
5190 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5193 return false;
5194
5195 return true;
5196}
5197
5198static bool isRegOrFI(const MachineOperand &MO) {
5199 return MO.isReg() || MO.isFI();
5200}
5201
5202static bool isSubRegOf(const SIRegisterInfo &TRI,
5203 const MachineOperand &SuperVec,
5204 const MachineOperand &SubReg) {
5205 if (SubReg.getReg().isPhysical())
5206 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5207
5208 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5209 SubReg.getReg() == SuperVec.getReg();
5210}
5211
5212// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5213bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5214 const MachineRegisterInfo &MRI,
5215 StringRef &ErrInfo) const {
5216 Register DstReg = MI.getOperand(0).getReg();
5217 Register SrcReg = MI.getOperand(1).getReg();
5218 // This is a check for copy from vector register to SGPR
5219 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5220 ErrInfo = "illegal copy from vector register to SGPR";
5221 return false;
5222 }
5223 return true;
5224}
5225
5227 StringRef &ErrInfo) const {
5228 uint32_t Opcode = MI.getOpcode();
5229 const MachineFunction *MF = MI.getMF();
5230 const MachineRegisterInfo &MRI = MF->getRegInfo();
5231
5232 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5233 // Find a better property to recognize the point where instruction selection
5234 // is just done.
5235 // We can only enforce this check after SIFixSGPRCopies pass so that the
5236 // illegal copies are legalized and thereafter we don't expect a pass
5237 // inserting similar copies.
5238 if (!MRI.isSSA() && MI.isCopy())
5239 return verifyCopy(MI, MRI, ErrInfo);
5240
5241 if (SIInstrInfo::isGenericOpcode(Opcode))
5242 return true;
5243
5244 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5245 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5246 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5247 int Src3Idx = -1;
5248 if (Src0Idx == -1) {
5249 // VOPD V_DUAL_* instructions use different operand names.
5250 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5251 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5252 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5253 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5254 }
5255
5256 // Make sure the number of operands is correct.
5257 const MCInstrDesc &Desc = get(Opcode);
5258 if (!Desc.isVariadic() &&
5259 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5260 ErrInfo = "Instruction has wrong number of operands.";
5261 return false;
5262 }
5263
5264 if (MI.isInlineAsm()) {
5265 // Verify register classes for inlineasm constraints.
5266 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5267 I != E; ++I) {
5268 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5269 if (!RC)
5270 continue;
5271
5272 const MachineOperand &Op = MI.getOperand(I);
5273 if (!Op.isReg())
5274 continue;
5275
5276 Register Reg = Op.getReg();
5277 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5278 ErrInfo = "inlineasm operand has incorrect register class.";
5279 return false;
5280 }
5281 }
5282
5283 return true;
5284 }
5285
5286 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5287 ErrInfo = "missing memory operand from image instruction.";
5288 return false;
5289 }
5290
5291 // Make sure the register classes are correct.
5292 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5293 const MachineOperand &MO = MI.getOperand(i);
5294 if (MO.isFPImm()) {
5295 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5296 "all fp values to integers.";
5297 return false;
5298 }
5299
5300 const MCOperandInfo &OpInfo = Desc.operands()[i];
5301 int16_t RegClass = getOpRegClassID(OpInfo);
5302
5303 switch (OpInfo.OperandType) {
5305 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5306 ErrInfo = "Illegal immediate value for operand.";
5307 return false;
5308 }
5309 break;
5321 break;
5323 break;
5324 break;
5338 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5339 ErrInfo = "Illegal immediate value for operand.";
5340 return false;
5341 }
5342 break;
5343 }
5348 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5349 !isInlineConstant(MI, i) &&
5351 OpInfo.OperandType ==
5353 ErrInfo = "illegal 64-bit immediate value for operand.";
5354 return false;
5355 }
5356 break;
5359 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5360 ErrInfo = "Expected inline constant for operand.";
5361 return false;
5362 }
5363 break;
5366 break;
5371 // Check if this operand is an immediate.
5372 // FrameIndex operands will be replaced by immediates, so they are
5373 // allowed.
5374 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5375 ErrInfo = "Expected immediate, but got non-immediate";
5376 return false;
5377 }
5378 break;
5382 break;
5383 default:
5384 if (OpInfo.isGenericType())
5385 continue;
5386 break;
5387 }
5388
5389 if (!MO.isReg())
5390 continue;
5391 Register Reg = MO.getReg();
5392 if (!Reg)
5393 continue;
5394
5395 // FIXME: Ideally we would have separate instruction definitions with the
5396 // aligned register constraint.
5397 // FIXME: We do not verify inline asm operands, but custom inline asm
5398 // verification is broken anyway
5399 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5400 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !isSpill(MI)) {
5401 const TargetRegisterClass *RC = RI.getRegClassForReg(MRI, Reg);
5402 if (RI.hasVectorRegisters(RC) && MO.getSubReg()) {
5403 if (const TargetRegisterClass *SubRC =
5404 RI.getSubRegisterClass(RC, MO.getSubReg())) {
5405 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.getSubReg());
5406 if (RC)
5407 RC = SubRC;
5408 }
5409 }
5410
5411 // Check that this is the aligned version of the class.
5412 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5413 ErrInfo = "Subtarget requires even aligned vector registers";
5414 return false;
5415 }
5416 }
5417
5418 if (RegClass != -1) {
5419 if (Reg.isVirtual())
5420 continue;
5421
5422 const TargetRegisterClass *RC = RI.getRegClass(RegClass);
5423 if (!RC->contains(Reg)) {
5424 ErrInfo = "Operand has incorrect register class.";
5425 return false;
5426 }
5427 }
5428 }
5429
5430 // Verify SDWA
5431 if (isSDWA(MI)) {
5432 if (!ST.hasSDWA()) {
5433 ErrInfo = "SDWA is not supported on this target";
5434 return false;
5435 }
5436
5437 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5438 AMDGPU::OpName::dst_sel}) {
5439 const MachineOperand *MO = getNamedOperand(MI, Op);
5440 if (!MO)
5441 continue;
5442 int64_t Imm = MO->getImm();
5444 ErrInfo = "Invalid SDWA selection";
5445 return false;
5446 }
5447 }
5448
5449 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5450
5451 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5452 if (OpIdx == -1)
5453 continue;
5454 const MachineOperand &MO = MI.getOperand(OpIdx);
5455
5456 if (!ST.hasSDWAScalar()) {
5457 // Only VGPRS on VI
5458 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5459 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5460 return false;
5461 }
5462 } else {
5463 // No immediates on GFX9
5464 if (!MO.isReg()) {
5465 ErrInfo =
5466 "Only reg allowed as operands in SDWA instructions on GFX9+";
5467 return false;
5468 }
5469 }
5470 }
5471
5472 if (!ST.hasSDWAOmod()) {
5473 // No omod allowed on VI
5474 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5475 if (OMod != nullptr &&
5476 (!OMod->isImm() || OMod->getImm() != 0)) {
5477 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5478 return false;
5479 }
5480 }
5481
5482 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5483 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5484 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5485 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5486 const MachineOperand *Src0ModsMO =
5487 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5488 unsigned Mods = Src0ModsMO->getImm();
5489 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5490 Mods & SISrcMods::SEXT) {
5491 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5492 return false;
5493 }
5494 }
5495
5496 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5497 if (isVOPC(BasicOpcode)) {
5498 if (!ST.hasSDWASdst() && DstIdx != -1) {
5499 // Only vcc allowed as dst on VI for VOPC
5500 const MachineOperand &Dst = MI.getOperand(DstIdx);
5501 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5502 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5503 return false;
5504 }
5505 } else if (!ST.hasSDWAOutModsVOPC()) {
5506 // No clamp allowed on GFX9 for VOPC
5507 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5508 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5509 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5510 return false;
5511 }
5512
5513 // No omod allowed on GFX9 for VOPC
5514 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5515 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5516 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5517 return false;
5518 }
5519 }
5520 }
5521
5522 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5523 if (DstUnused && DstUnused->isImm() &&
5524 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5525 const MachineOperand &Dst = MI.getOperand(DstIdx);
5526 if (!Dst.isReg() || !Dst.isTied()) {
5527 ErrInfo = "Dst register should have tied register";
5528 return false;
5529 }
5530
5531 const MachineOperand &TiedMO =
5532 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5533 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5534 ErrInfo =
5535 "Dst register should be tied to implicit use of preserved register";
5536 return false;
5537 }
5538 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5539 ErrInfo = "Dst register should use same physical register as preserved";
5540 return false;
5541 }
5542 }
5543 }
5544
5545 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5546 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5547 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5548 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5549 return false;
5550 }
5551 if (Src1MO.isImm()) {
5552 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5553 return false;
5554 }
5555 }
5556
5557 // Verify MIMG / VIMAGE / VSAMPLE
5558 if (isImage(Opcode) && !MI.mayStore()) {
5559 // Ensure that the return type used is large enough for all the options
5560 // being used TFE/LWE require an extra result register.
5561 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5562 if (DMask) {
5563 uint64_t DMaskImm = DMask->getImm();
5564 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5565 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5566 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5567 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5568
5569 // Adjust for packed 16 bit values
5570 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5571 RegCount = divideCeil(RegCount, 2);
5572
5573 // Adjust if using LWE or TFE
5574 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5575 RegCount += 1;
5576
5577 const uint32_t DstIdx =
5578 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5579 const MachineOperand &Dst = MI.getOperand(DstIdx);
5580 if (Dst.isReg()) {
5581 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5582 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5583 if (RegCount > DstSize) {
5584 ErrInfo = "Image instruction returns too many registers for dst "
5585 "register class";
5586 return false;
5587 }
5588 }
5589 }
5590 }
5591
5592 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5593 if (isVALU(MI, /*AllowLDSDMA=*/true) &&
5594 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5595 unsigned ConstantBusCount = 0;
5596 bool UsesLiteral = false;
5597 const MachineOperand *LiteralVal = nullptr;
5598
5599 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5600 if (ImmIdx != -1) {
5601 ++ConstantBusCount;
5602 UsesLiteral = true;
5603 LiteralVal = &MI.getOperand(ImmIdx);
5604 }
5605
5606 SmallVector<Register, 2> SGPRsUsed;
5607 Register SGPRUsed;
5608
5609 // Only look at the true operands. Only a real operand can use the constant
5610 // bus, and we don't want to check pseudo-operands like the source modifier
5611 // flags.
5612 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5613 if (OpIdx == -1)
5614 continue;
5615 const MachineOperand &MO = MI.getOperand(OpIdx);
5616 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5617 if (MO.isReg()) {
5618 SGPRUsed = MO.getReg();
5619 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5620 ++ConstantBusCount;
5621 SGPRsUsed.push_back(SGPRUsed);
5622 }
5623 } else if (!MO.isFI()) { // Treat FI like a register.
5624 if (!UsesLiteral) {
5625 ++ConstantBusCount;
5626 UsesLiteral = true;
5627 LiteralVal = &MO;
5628 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5629 assert(isVOP2(MI) || isVOP3(MI));
5630 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5631 return false;
5632 }
5633 }
5634 }
5635 }
5636
5637 SGPRUsed = findImplicitSGPRRead(MI);
5638 if (SGPRUsed) {
5639 // Implicit uses may safely overlap true operands
5640 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5641 return !RI.regsOverlap(SGPRUsed, SGPR);
5642 })) {
5643 ++ConstantBusCount;
5644 SGPRsUsed.push_back(SGPRUsed);
5645 }
5646 }
5647
5648 // v_writelane_b32 is an exception from constant bus restriction:
5649 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5650 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5651 Opcode != AMDGPU::V_WRITELANE_B32) {
5652 ErrInfo = "VOP* instruction violates constant bus restriction";
5653 return false;
5654 }
5655
5656 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5657 ErrInfo = "VOP3 instruction uses literal";
5658 return false;
5659 }
5660 }
5661
5662 // Special case for writelane - this can break the multiple constant bus rule,
5663 // but still can't use more than one SGPR register
5664 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5665 unsigned SGPRCount = 0;
5666 Register SGPRUsed;
5667
5668 for (int OpIdx : {Src0Idx, Src1Idx}) {
5669 if (OpIdx == -1)
5670 break;
5671
5672 const MachineOperand &MO = MI.getOperand(OpIdx);
5673
5674 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5675 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5676 if (MO.getReg() != SGPRUsed)
5677 ++SGPRCount;
5678 SGPRUsed = MO.getReg();
5679 }
5680 }
5681 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5682 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5683 return false;
5684 }
5685 }
5686 }
5687
5688 // Verify misc. restrictions on specific instructions.
5689 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5690 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5691 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5692 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5693 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
5694 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5695 if (!compareMachineOp(Src0, Src1) &&
5696 !compareMachineOp(Src0, Src2)) {
5697 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
5698 return false;
5699 }
5700 }
5701 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
5702 SISrcMods::ABS) ||
5703 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
5704 SISrcMods::ABS) ||
5705 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
5706 SISrcMods::ABS)) {
5707 ErrInfo = "ABS not allowed in VOP3B instructions";
5708 return false;
5709 }
5710 }
5711
5712 if (isSOP2(MI) || isSOPC(MI)) {
5713 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5714 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5715
5716 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
5717 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
5718 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
5719 !Src0.isIdenticalTo(Src1)) {
5720 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
5721 return false;
5722 }
5723 }
5724
5725 if (isSOPK(MI)) {
5726 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
5727 if (Desc.isBranch()) {
5728 if (!Op->isMBB()) {
5729 ErrInfo = "invalid branch target for SOPK instruction";
5730 return false;
5731 }
5732 } else {
5733 uint64_t Imm = Op->getImm();
5734 if (sopkIsZext(Opcode)) {
5735 if (!isUInt<16>(Imm)) {
5736 ErrInfo = "invalid immediate for SOPK instruction";
5737 return false;
5738 }
5739 } else {
5740 if (!isInt<16>(Imm)) {
5741 ErrInfo = "invalid immediate for SOPK instruction";
5742 return false;
5743 }
5744 }
5745 }
5746 }
5747
5748 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5749 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5750 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5751 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5752 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5753 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5754
5755 const unsigned StaticNumOps =
5756 Desc.getNumOperands() + Desc.implicit_uses().size();
5757 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5758
5759 // Require additional implicit operands. This allows a fixup done by the
5760 // post RA scheduler where the main implicit operand is killed and
5761 // implicit-defs are added for sub-registers that remain live after this
5762 // instruction.
5763 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5764 ErrInfo = "missing implicit register operands";
5765 return false;
5766 }
5767
5768 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5769 if (IsDst) {
5770 if (!Dst->isUse()) {
5771 ErrInfo = "v_movreld_b32 vdst should be a use operand";
5772 return false;
5773 }
5774
5775 unsigned UseOpIdx;
5776 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5777 UseOpIdx != StaticNumOps + 1) {
5778 ErrInfo = "movrel implicit operands should be tied";
5779 return false;
5780 }
5781 }
5782
5783 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5784 const MachineOperand &ImpUse
5785 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5786 if (!ImpUse.isReg() || !ImpUse.isUse() ||
5787 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5788 ErrInfo = "src0 should be subreg of implicit vector use";
5789 return false;
5790 }
5791 }
5792
5793 // Make sure we aren't losing exec uses in the td files. This mostly requires
5794 // being careful when using let Uses to try to add other use registers.
5795 if (shouldReadExec(MI)) {
5796 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5797 ErrInfo = "VALU instruction does not implicitly read exec mask";
5798 return false;
5799 }
5800 }
5801
5802 if (isSMRD(MI)) {
5803 if (MI.mayStore() &&
5804 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
5805 // The register offset form of scalar stores may only use m0 as the
5806 // soffset register.
5807 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
5808 if (Soff && Soff->getReg() != AMDGPU::M0) {
5809 ErrInfo = "scalar stores must use m0 as offset register";
5810 return false;
5811 }
5812 }
5813 }
5814
5815 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
5816 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
5817 if (Offset->getImm() != 0) {
5818 ErrInfo = "subtarget does not support offsets in flat instructions";
5819 return false;
5820 }
5821 }
5822
5823 if (isDS(MI) && !ST.hasGDS()) {
5824 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
5825 if (GDSOp && GDSOp->getImm() != 0) {
5826 ErrInfo = "GDS is not supported on this subtarget";
5827 return false;
5828 }
5829 }
5830
5831 if (isImage(MI)) {
5832 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
5833 if (DimOp) {
5834 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5835 AMDGPU::OpName::vaddr0);
5836 AMDGPU::OpName RSrcOpName =
5837 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5838 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5839 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
5840 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
5841 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
5842 const AMDGPU::MIMGDimInfo *Dim =
5844
5845 if (!Dim) {
5846 ErrInfo = "dim is out of range";
5847 return false;
5848 }
5849
5850 bool IsA16 = false;
5851 if (ST.hasR128A16()) {
5852 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
5853 IsA16 = R128A16->getImm() != 0;
5854 } else if (ST.hasA16()) {
5855 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
5856 IsA16 = A16->getImm() != 0;
5857 }
5858
5859 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5860
5861 unsigned AddrWords =
5862 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
5863
5864 unsigned VAddrWords;
5865 if (IsNSA) {
5866 VAddrWords = RsrcIdx - VAddr0Idx;
5867 if (ST.hasPartialNSAEncoding() &&
5868 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
5869 unsigned LastVAddrIdx = RsrcIdx - 1;
5870 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
5871 }
5872 } else {
5873 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
5874 if (AddrWords > 12)
5875 AddrWords = 16;
5876 }
5877
5878 if (VAddrWords != AddrWords) {
5879 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
5880 << " but got " << VAddrWords << "\n");
5881 ErrInfo = "bad vaddr size";
5882 return false;
5883 }
5884 }
5885 }
5886
5887 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
5888 if (DppCt) {
5889 using namespace AMDGPU::DPP;
5890
5891 unsigned DC = DppCt->getImm();
5892 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5893 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5894 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5895 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5896 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5897 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5898 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5899 ErrInfo = "Invalid dpp_ctrl value";
5900 return false;
5901 }
5902 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5903 !ST.hasDPPWavefrontShifts()) {
5904 ErrInfo = "Invalid dpp_ctrl value: "
5905 "wavefront shifts are not supported on GFX10+";
5906 return false;
5907 }
5908 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5909 !ST.hasDPPBroadcasts()) {
5910 ErrInfo = "Invalid dpp_ctrl value: "
5911 "broadcasts are not supported on GFX10+";
5912 return false;
5913 }
5914 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
5915 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
5916 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
5917 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
5918 !ST.hasGFX90AInsts()) {
5919 ErrInfo = "Invalid dpp_ctrl value: "
5920 "row_newbroadcast/row_share is not supported before "
5921 "GFX90A/GFX10";
5922 return false;
5923 }
5924 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
5925 ErrInfo = "Invalid dpp_ctrl value: "
5926 "row_share and row_xmask are not supported before GFX10";
5927 return false;
5928 }
5929 }
5930
5931 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
5933 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
5934 ErrInfo = "Invalid dpp_ctrl value: "
5935 "DP ALU dpp only support row_newbcast";
5936 return false;
5937 }
5938 }
5939
5940 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
5941 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5942 AMDGPU::OpName DataName =
5943 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
5944 const MachineOperand *Data = getNamedOperand(MI, DataName);
5945 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
5946 if (Data && !Data->isReg())
5947 Data = nullptr;
5948
5949 if (!ST.hasGFX90AInsts()) {
5950 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
5951 (Data && RI.isAGPR(MRI, Data->getReg())) ||
5952 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
5953 ErrInfo = "Invalid register class: "
5954 "agpr loads and stores not supported on this GPU";
5955 return false;
5956 }
5957 }
5958 }
5959
5960 if (ST.needsAlignedVGPRs()) {
5961 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
5963 if (!Op)
5964 return true;
5965 Register Reg = Op->getReg();
5966 if (Reg.isPhysical())
5967 return !(RI.getHWRegIndex(Reg) & 1);
5968 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
5969 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
5970 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
5971 };
5972
5973 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
5974 Opcode == AMDGPU::DS_GWS_BARRIER) {
5975
5976 if (!isAlignedReg(AMDGPU::OpName::data0)) {
5977 ErrInfo = "Subtarget requires even aligned vector registers "
5978 "for DS_GWS instructions";
5979 return false;
5980 }
5981 }
5982
5983 if (isMIMG(MI)) {
5984 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
5985 ErrInfo = "Subtarget requires even aligned vector registers "
5986 "for vaddr operand of image instructions";
5987 return false;
5988 }
5989 }
5990 }
5991
5992 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
5993 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
5994 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
5995 ErrInfo = "Invalid register class: "
5996 "v_accvgpr_write with an SGPR is not supported on this GPU";
5997 return false;
5998 }
5999 }
6000
6001 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6002 const MachineOperand &SrcOp = MI.getOperand(1);
6003 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
6004 ErrInfo = "pseudo expects only physical SGPRs";
6005 return false;
6006 }
6007 }
6008
6009 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
6010 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
6011 if (!ST.hasScaleOffset()) {
6012 ErrInfo = "Subtarget does not support offset scaling";
6013 return false;
6014 }
6015 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
6016 ErrInfo = "Instruction does not support offset scaling";
6017 return false;
6018 }
6019 }
6020 }
6021
6022 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6023 if (AMDGPU::isSingleSGPRReadInst(Opcode)) {
6024 for (unsigned I = 0; I < 3; ++I) {
6026 return false;
6027 }
6028 }
6029
6030 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
6031 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
6032 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
6033 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6034 &AMDGPU::SReg_64RegClass) ||
6035 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6036 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
6037 return false;
6038 }
6039 }
6040
6041 return true;
6042}
6043
6045 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
6046 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6047 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
6048 ? AMDGPU::COPY
6049 : AMDGPU::V_MOV_B32_e32;
6050 }
6051 return getVALUOp(MI.getOpcode());
6052}
6053
6054// It is more readable to list mapped opcodes on the same line.
6055// clang-format off
6056
6057unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
6058 switch (Opc) {
6059 default: return AMDGPU::INSTRUCTION_LIST_END;
6060 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
6061 case AMDGPU::COPY: return AMDGPU::COPY;
6062 case AMDGPU::PHI: return AMDGPU::PHI;
6063 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
6064 case AMDGPU::WQM: return AMDGPU::WQM;
6065 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
6066 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
6067 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
6068 case AMDGPU::S_ADD_I32:
6069 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6070 case AMDGPU::S_ADDC_U32:
6071 return AMDGPU::V_ADDC_U32_e32;
6072 case AMDGPU::S_SUB_I32:
6073 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6074 // FIXME: These are not consistently handled, and selected when the carry is
6075 // used.
6076 case AMDGPU::S_ADD_U32:
6077 return AMDGPU::V_ADD_CO_U32_e32;
6078 case AMDGPU::S_SUB_U32:
6079 return AMDGPU::V_SUB_CO_U32_e32;
6080 case AMDGPU::S_ADD_U64_PSEUDO:
6081 return AMDGPU::V_ADD_U64_PSEUDO;
6082 case AMDGPU::S_SUB_U64_PSEUDO:
6083 return AMDGPU::V_SUB_U64_PSEUDO;
6084 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
6085 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
6086 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
6087 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
6088 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
6089 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
6090 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
6091 case AMDGPU::S_XNOR_B32:
6092 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6093 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
6094 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
6095 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
6096 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
6097 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
6098 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
6099 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
6100 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
6101 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
6102 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
6103 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
6104 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
6105 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
6106 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
6107 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
6108 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
6109 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
6110 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
6111 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
6112 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
6113 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
6114 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
6115 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
6116 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
6117 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
6118 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
6119 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
6120 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
6121 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
6122 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
6123 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
6124 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
6125 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
6126 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
6127 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
6128 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
6129 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
6130 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
6131 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
6132 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
6133 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
6134 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
6135 case AMDGPU::S_CVT_F32_F16:
6136 case AMDGPU::S_CVT_HI_F32_F16:
6137 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6138 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6139 case AMDGPU::S_CVT_F16_F32:
6140 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6141 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6142 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
6143 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
6144 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
6145 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
6146 case AMDGPU::S_CEIL_F16:
6147 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6148 : AMDGPU::V_CEIL_F16_fake16_e64;
6149 case AMDGPU::S_FLOOR_F16:
6150 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6151 : AMDGPU::V_FLOOR_F16_fake16_e64;
6152 case AMDGPU::S_TRUNC_F16:
6153 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6154 : AMDGPU::V_TRUNC_F16_fake16_e64;
6155 case AMDGPU::S_RNDNE_F16:
6156 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6157 : AMDGPU::V_RNDNE_F16_fake16_e64;
6158 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6159 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6160 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6161 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6162 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6163 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6164 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6165 case AMDGPU::S_ADD_F16:
6166 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6167 : AMDGPU::V_ADD_F16_fake16_e64;
6168 case AMDGPU::S_SUB_F16:
6169 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6170 : AMDGPU::V_SUB_F16_fake16_e64;
6171 case AMDGPU::S_MIN_F16:
6172 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6173 : AMDGPU::V_MIN_F16_fake16_e64;
6174 case AMDGPU::S_MAX_F16:
6175 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6176 : AMDGPU::V_MAX_F16_fake16_e64;
6177 case AMDGPU::S_MINIMUM_F16:
6178 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6179 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6180 case AMDGPU::S_MAXIMUM_F16:
6181 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6182 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6183 case AMDGPU::S_MUL_F16:
6184 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6185 : AMDGPU::V_MUL_F16_fake16_e64;
6186 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6187 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6188 case AMDGPU::S_FMAC_F16:
6189 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6190 : AMDGPU::V_FMAC_F16_fake16_e64;
6191 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6192 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6193 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6194 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6195 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6196 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6197 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6198 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6199 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6200 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6201 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6202 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6203 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6204 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6205 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6206 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6207 case AMDGPU::S_CMP_LT_F16:
6208 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6209 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6210 case AMDGPU::S_CMP_EQ_F16:
6211 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6212 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6213 case AMDGPU::S_CMP_LE_F16:
6214 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6215 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6216 case AMDGPU::S_CMP_GT_F16:
6217 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6218 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6219 case AMDGPU::S_CMP_LG_F16:
6220 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6221 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6222 case AMDGPU::S_CMP_GE_F16:
6223 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6224 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6225 case AMDGPU::S_CMP_O_F16:
6226 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6227 : AMDGPU::V_CMP_O_F16_fake16_e64;
6228 case AMDGPU::S_CMP_U_F16:
6229 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6230 : AMDGPU::V_CMP_U_F16_fake16_e64;
6231 case AMDGPU::S_CMP_NGE_F16:
6232 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6233 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6234 case AMDGPU::S_CMP_NLG_F16:
6235 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6236 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6237 case AMDGPU::S_CMP_NGT_F16:
6238 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6239 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6240 case AMDGPU::S_CMP_NLE_F16:
6241 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6242 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6243 case AMDGPU::S_CMP_NEQ_F16:
6244 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6245 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6246 case AMDGPU::S_CMP_NLT_F16:
6247 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6248 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6249 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6250 case AMDGPU::V_S_EXP_F16_e64:
6251 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6252 : AMDGPU::V_EXP_F16_fake16_e64;
6253 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6254 case AMDGPU::V_S_LOG_F16_e64:
6255 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6256 : AMDGPU::V_LOG_F16_fake16_e64;
6257 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6258 case AMDGPU::V_S_RCP_F16_e64:
6259 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6260 : AMDGPU::V_RCP_F16_fake16_e64;
6261 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6262 case AMDGPU::V_S_RSQ_F16_e64:
6263 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6264 : AMDGPU::V_RSQ_F16_fake16_e64;
6265 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6266 case AMDGPU::V_S_SQRT_F16_e64:
6267 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6268 : AMDGPU::V_SQRT_F16_fake16_e64;
6269 }
6271 "Unexpected scalar opcode without corresponding vector one!");
6272}
6273
6274// clang-format on
6275
6279 const DebugLoc &DL, Register Reg,
6280 bool IsSCCLive,
6281 SlotIndexes *Indexes) const {
6282 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6283 const SIInstrInfo *TII = ST.getInstrInfo();
6285 if (IsSCCLive) {
6286 // Insert two move instructions, one to save the original value of EXEC and
6287 // the other to turn on all bits in EXEC. This is required as we can't use
6288 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6289 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6291 auto FlipExecMI =
6292 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6293 if (Indexes) {
6294 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6295 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6296 }
6297 } else {
6298 auto SaveExec =
6299 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6300 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6301 if (Indexes)
6302 Indexes->insertMachineInstrInMaps(*SaveExec);
6303 }
6304}
6305
6308 const DebugLoc &DL, Register Reg,
6309 SlotIndexes *Indexes) const {
6311 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6312 .addReg(Reg, RegState::Kill);
6313 if (Indexes)
6314 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6315}
6316
6320 "Not a whole wave func");
6321 MachineBasicBlock &MBB = *MF.begin();
6322 for (MachineInstr &MI : MBB)
6323 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6324 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6325 return &MI;
6326
6327 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6328}
6329
6331 unsigned OpNo) const {
6332 const MCInstrDesc &Desc = get(MI.getOpcode());
6333 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6334 Desc.operands()[OpNo].RegClass == -1) {
6335 Register Reg = MI.getOperand(OpNo).getReg();
6336
6337 if (Reg.isVirtual()) {
6338 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6339 return MRI.getRegClass(Reg);
6340 }
6341 return RI.getPhysRegBaseClass(Reg);
6342 }
6343
6344 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6345 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6346}
6347
6348// Convert VOP3 operand index to source number.
6349static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx) {
6350 constexpr AMDGPU::OpName OpNames[] = {
6351 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6352
6353 for (auto [I, OpName] : enumerate(OpNames)) {
6354 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6355 if (static_cast<unsigned>(SrcIdx) == OpIdx)
6356 return I;
6357 }
6358
6359 return UINT_MAX;
6360}
6361
6364 MachineBasicBlock *MBB = MI.getParent();
6365 MachineOperand &MO = MI.getOperand(OpIdx);
6366 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6367 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6368 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6369 unsigned Size = RI.getRegSizeInBits(*RC);
6370 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6371 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6372 : AMDGPU::V_MOV_B32_e32;
6373 if (MO.isReg())
6374 Opcode = AMDGPU::COPY;
6375 else if (RI.isSGPRClass(RC))
6376 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6377
6378 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6379 Register Reg = MRI.createVirtualRegister(VRC);
6380 DebugLoc DL = MBB->findDebugLoc(I);
6381
6382 if (Size == 128 && AMDGPU::isPackedSingleSGPR64BitInst(MI.getOpcode()) &&
6384 // Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
6385 // sources behave like OPSEL is set replicating low 64-bits into high. VGPR
6386 // sources in turn read actual 4 registers. To move operand from an SGPR to
6387 // a VGPR we need to replicate low half.
6388 // We also do not select immediates for these instructions so it always has
6389 // to be an SGPR register here.
6390 // Operands which are not legal as per isLegalSingleSGPRReadInstOperand()
6391 // sent here specifically to fix a non-splat SGPR and shall perform a full
6392 // copy.
6393
6394 const TargetRegisterClass *VRC64 = RI.getVGPRClassForBitWidth(64);
6395 Register Low64 = MRI.createVirtualRegister(VRC64);
6396 assert(MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()));
6397 BuildMI(*MBB, I, DL, get(TargetOpcode::COPY), Low64)
6398 .addReg(MO.getReg(), {}, AMDGPU::sub0_sub1);
6399 BuildMI(*MBB, I, DL, get(TargetOpcode::REG_SEQUENCE), Reg)
6400 .addReg(Low64)
6401 .addImm(AMDGPU::sub0_sub1)
6402 .addReg(Low64, RegState::Kill)
6403 .addImm(AMDGPU::sub2_sub3);
6404 } else {
6405 BuildMI(*MBB, I, DL, get(Opcode), Reg).add(MO);
6406 }
6407
6408 MO.ChangeToRegister(Reg, false);
6409}
6410
6413 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6414 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6415 if (!SuperReg.getReg().isVirtual())
6416 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6417
6418 MachineBasicBlock *MBB = MI->getParent();
6419 const DebugLoc &DL = MI->getDebugLoc();
6420 Register SubReg = MRI.createVirtualRegister(SubRC);
6421
6422 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6423 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6424 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6425 return SubReg;
6426}
6427
6430 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6431 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6432 if (Op.isImm()) {
6433 if (SubIdx == AMDGPU::sub0)
6434 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6435 if (SubIdx == AMDGPU::sub1)
6436 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6437
6438 llvm_unreachable("Unhandled register index for immediate");
6439 }
6440
6441 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6442 SubIdx, SubRC);
6443 return MachineOperand::CreateReg(SubReg, false);
6444}
6445
6446// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6447void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6448 assert(Inst.getNumExplicitOperands() == 3);
6449 MachineOperand Op1 = Inst.getOperand(1);
6450 Inst.removeOperand(1);
6451 Inst.addOperand(Op1);
6452}
6453
6455 const MCOperandInfo &OpInfo,
6456 const MachineOperand &MO) const {
6457 if (!MO.isReg())
6458 return false;
6459
6460 Register Reg = MO.getReg();
6461
6462 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6463 if (Reg.isPhysical())
6464 return DRC->contains(Reg);
6465
6466 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6467
6468 if (MO.getSubReg()) {
6469 const MachineFunction *MF = MO.getParent()->getMF();
6470 const TargetRegisterClass *SuperRC = RI.getLargestLegalSuperClass(RC, *MF);
6471 if (!SuperRC)
6472 return false;
6473 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6474 }
6475
6476 return RI.getCommonSubClass(DRC, RC) != nullptr;
6477}
6478
6480 const MachineOperand &MO) const {
6481 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6482 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6483 unsigned Opc = MI.getOpcode();
6484
6485 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6486 if (MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
6487 AMDGPU::isSingleSGPRReadInst(MI.getOpcode()) &&
6489 &MO))
6490 return false;
6491
6492 if (!isLegalRegOperand(MRI, OpInfo, MO))
6493 return false;
6494
6495 // check Accumulate GPR operand
6496 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6497 if (IsAGPR && !ST.hasMAIInsts())
6498 return false;
6499 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6500 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6501 return false;
6502 // Atomics should have both vdst and vdata either vgpr or agpr.
6503 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6504 const int DataIdx = AMDGPU::getNamedOperandIdx(
6505 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6506 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6507 MI.getOperand(DataIdx).isReg() &&
6508 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6509 return false;
6510 if ((int)OpIdx == DataIdx) {
6511 if (VDstIdx != -1 &&
6512 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6513 return false;
6514 // DS instructions with 2 src operands also must have tied RC.
6515 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6516 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6517 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6518 return false;
6519 }
6520
6521 // Check V_ACCVGPR_WRITE_B32_e64
6522 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6523 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6524 RI.isSGPRReg(MRI, MO.getReg()))
6525 return false;
6526
6527 if (ST.hasFlatScratchHiInB64InstHazard() &&
6528 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6529 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6530 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6531 64)
6532 return false;
6533 }
6534 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6535 return false;
6536 }
6537 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6538 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6539 return false;
6540
6541 return true;
6542}
6543
6545 const MCOperandInfo &OpInfo,
6546 const MachineOperand &MO) const {
6547 if (MO.isReg())
6548 return isLegalRegOperand(MRI, OpInfo, MO);
6549
6550 // Handle non-register types that are treated like immediates.
6551 assert(MO.isImm() || MO.isTargetIndex() || MO.isFI() || MO.isGlobal());
6552 return true;
6553}
6554
6556 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6557 const MachineOperand *MO) const {
6558 constexpr unsigned NumOps = 3;
6559 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6560 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6561 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6562 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6563
6564 assert(SrcN < NumOps);
6565
6566 if (!MO) {
6567 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6568 if (SrcIdx == -1)
6569 return true;
6570 MO = &MI.getOperand(SrcIdx);
6571 }
6572
6573 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6574 return true;
6575
6576 int ModsIdx =
6577 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6578 if (ModsIdx == -1)
6579 return false;
6580
6581 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6582 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6583 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6584
6585 return !OpSel && !OpSelHi;
6586}
6587
6588bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
6589 const MachineOperand *MO) const {
6590 const MachineFunction &MF = *MI.getMF();
6591 const MachineRegisterInfo &MRI = MF.getRegInfo();
6592 const MCInstrDesc &InstDesc = MI.getDesc();
6593 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6594 int64_t RegClass = getOpRegClassID(OpInfo);
6595 const TargetRegisterClass *DefinedRC =
6596 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6597 if (!MO)
6598 MO = &MI.getOperand(OpIdx);
6599
6600 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6601
6602 if (isVALU(MI, /*AllowLDSDMA=*/true) && !IsInlineConst &&
6603 usesConstantBus(MRI, *MO, OpInfo)) {
6604 const MachineOperand *UsedLiteral = nullptr;
6605
6606 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6607 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6608
6609 // TODO: Be more permissive with frame indexes.
6610 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6611 if (!LiteralLimit--)
6612 return false;
6613
6614 UsedLiteral = MO;
6615 }
6616
6618 if (MO->isReg())
6619 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6620
6621 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6622 if (i == OpIdx)
6623 continue;
6624 const MachineOperand &Op = MI.getOperand(i);
6625 if (Op.isReg()) {
6626 if (Op.isUse()) {
6627 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6628 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6629 if (--ConstantBusLimit <= 0)
6630 return false;
6631 }
6632 }
6633 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6634 !isInlineConstant(Op, InstDesc.operands()[i])) {
6635 // The same literal may be used multiple times.
6636 if (!UsedLiteral)
6637 UsedLiteral = &Op;
6638 else if (UsedLiteral->isIdenticalTo(Op))
6639 continue;
6640
6641 if (!LiteralLimit--)
6642 return false;
6643 if (--ConstantBusLimit <= 0)
6644 return false;
6645 }
6646 }
6647 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6648 // There can be at most one literal operand, but it can be repeated.
6649 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6650 if (i == OpIdx)
6651 continue;
6652 const MachineOperand &Op = MI.getOperand(i);
6653 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6654 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6655 !Op.isIdenticalTo(*MO))
6656 return false;
6657
6658 // Do not fold a non-inlineable and non-register operand into an
6659 // instruction that already has a frame index. The frame index handling
6660 // code could not handle well when a frame index co-exists with another
6661 // non-register operand, unless that operand is an inlineable immediate.
6662 if (Op.isFI())
6663 return false;
6664 }
6665 } else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6666 isF16PseudoScalarTrans(MI.getOpcode())) {
6667 return false;
6668 }
6669
6670 if (MO->isReg()) {
6671 if (!DefinedRC)
6672 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6673 return isLegalRegOperand(MI, OpIdx, *MO);
6674 }
6675
6676 if (MO->isImm()) {
6677 uint64_t Imm = MO->getImm();
6678 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6679 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6680 bool Is64BitOp = Is64BitFPOp ||
6681 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6682 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6683 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6684 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6685 if (Is64BitOp &&
6686 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6687 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6688 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6689 return false;
6690
6691 // FIXME: We can use sign extended 64-bit literals, but only for signed
6692 // operands. At the moment we do not know if an operand is signed.
6693 // Such operand will be encoded as its low 32 bits and then either
6694 // correctly sign extended or incorrectly zero extended by HW.
6695 // If 64-bit literals are supported and the literal will be encoded
6696 // as full 64 bit we still can use it.
6697 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6698 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
6699 return false;
6700 }
6701 }
6702
6703 // Handle non-register types that are treated like immediates.
6704 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
6705
6706 if (!DefinedRC) {
6707 // This operand expects an immediate.
6708 return true;
6709 }
6710
6711 return isImmOperandLegal(MI, OpIdx, *MO);
6712}
6713
6715 bool IsGFX950Only = ST.hasGFX950Insts();
6716 bool IsGFX940Only = ST.hasGFX940Insts();
6717
6718 if (!IsGFX950Only && !IsGFX940Only)
6719 return false;
6720
6721 if (!isVALU(MI, /*AllowLDSDMA=*/true))
6722 return false;
6723
6724 // V_COS, V_EXP, V_RCP, etc.
6725 if (isTRANS(MI))
6726 return true;
6727
6728 // DOT2, DOT2C, DOT4, etc.
6729 if (isDOT(MI))
6730 return true;
6731
6732 // MFMA, SMFMA
6733 if (isMFMA(MI))
6734 return true;
6735
6736 unsigned Opcode = MI.getOpcode();
6737 switch (Opcode) {
6738 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6739 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6740 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6741 case AMDGPU::V_MQSAD_U32_U8_e64:
6742 case AMDGPU::V_PK_ADD_F16:
6743 case AMDGPU::V_PK_ADD_F32:
6744 case AMDGPU::V_PK_ADD_I16:
6745 case AMDGPU::V_PK_ADD_U16:
6746 case AMDGPU::V_PK_ASHRREV_I16:
6747 case AMDGPU::V_PK_FMA_F16:
6748 case AMDGPU::V_PK_FMA_F32:
6749 case AMDGPU::V_PK_FMAC_F16_e32:
6750 case AMDGPU::V_PK_FMAC_F16_e64:
6751 case AMDGPU::V_PK_LSHLREV_B16:
6752 case AMDGPU::V_PK_LSHRREV_B16:
6753 case AMDGPU::V_PK_MAD_I16:
6754 case AMDGPU::V_PK_MAD_U16:
6755 case AMDGPU::V_PK_MAX_F16:
6756 case AMDGPU::V_PK_MAX_I16:
6757 case AMDGPU::V_PK_MAX_U16:
6758 case AMDGPU::V_PK_MIN_F16:
6759 case AMDGPU::V_PK_MIN_I16:
6760 case AMDGPU::V_PK_MIN_U16:
6761 case AMDGPU::V_PK_MOV_B32:
6762 case AMDGPU::V_PK_MUL_F16:
6763 case AMDGPU::V_PK_MUL_F32:
6764 case AMDGPU::V_PK_MUL_LO_U16:
6765 case AMDGPU::V_PK_SUB_I16:
6766 case AMDGPU::V_PK_SUB_U16:
6767 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6768 return true;
6769 default:
6770 return false;
6771 }
6772}
6773
6775 MachineInstr &MI) const {
6776 unsigned Opc = MI.getOpcode();
6777 const MCInstrDesc &InstrDesc = get(Opc);
6778
6779 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
6780 MachineOperand &Src0 = MI.getOperand(Src0Idx);
6781
6782 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
6783 MachineOperand &Src1 = MI.getOperand(Src1Idx);
6784
6785 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
6786 // we need to only have one constant bus use before GFX10.
6787 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
6788 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
6789 RI.isSGPRReg(MRI, Src0.getReg()))
6790 legalizeOpWithMove(MI, Src0Idx);
6791
6792 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
6793 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
6794 // src0/src1 with V_READFIRSTLANE.
6795 if (Opc == AMDGPU::V_WRITELANE_B32) {
6796 const DebugLoc &DL = MI.getDebugLoc();
6797 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
6798 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6799 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6800 .add(Src0);
6801 Src0.ChangeToRegister(Reg, false);
6802 }
6803 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
6804 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6805 const DebugLoc &DL = MI.getDebugLoc();
6806 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6807 .add(Src1);
6808 Src1.ChangeToRegister(Reg, false);
6809 }
6810 return;
6811 }
6812
6813 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
6814 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
6815 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
6816 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
6817 legalizeOpWithMove(MI, Src2Idx);
6818 }
6819
6820 // VOP2 src0 instructions support all operand types, so we don't need to check
6821 // their legality. If src1 is already legal, we don't need to do anything.
6822 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
6823 return;
6824
6825 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
6826 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
6827 // select is uniform.
6828 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
6829 RI.isVGPR(MRI, Src1.getReg())) {
6830 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6831 const DebugLoc &DL = MI.getDebugLoc();
6832 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6833 .add(Src1);
6834 Src1.ChangeToRegister(Reg, false);
6835 return;
6836 }
6837
6838 // We do not use commuteInstruction here because it is too aggressive and will
6839 // commute if it is possible. We only want to commute here if it improves
6840 // legality. This can be called a fairly large number of times so don't waste
6841 // compile time pointlessly swapping and checking legality again.
6842 if (HasImplicitSGPR || !MI.isCommutable()) {
6843 legalizeOpWithMove(MI, Src1Idx);
6844 return;
6845 }
6846
6847 // If src0 can be used as src1, commuting will make the operands legal.
6848 // Otherwise we have to give up and insert a move.
6849 //
6850 // TODO: Other immediate-like operand kinds could be commuted if there was a
6851 // MachineOperand::ChangeTo* for them.
6852 if ((!Src1.isImm() && !Src1.isReg()) ||
6853 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
6854 legalizeOpWithMove(MI, Src1Idx);
6855 return;
6856 }
6857
6858 int CommutedOpc = commuteOpcode(MI);
6859 if (CommutedOpc == -1) {
6860 legalizeOpWithMove(MI, Src1Idx);
6861 return;
6862 }
6863
6864 MI.setDesc(get(CommutedOpc));
6865
6866 Register Src0Reg = Src0.getReg();
6867 unsigned Src0SubReg = Src0.getSubReg();
6868 bool Src0Kill = Src0.isKill();
6869
6870 if (Src1.isImm())
6871 Src0.ChangeToImmediate(Src1.getImm());
6872 else if (Src1.isReg()) {
6873 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
6874 Src0.setSubReg(Src1.getSubReg());
6875 } else
6876 llvm_unreachable("Should only have register or immediate operands");
6877
6878 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
6879 Src1.setSubReg(Src0SubReg);
6881}
6882
6883// Legalize VOP3 operands. All operand types are supported for any operand
6884// but only one literal constant and only starting from GFX10.
6886 MachineInstr &MI) const {
6887 unsigned Opc = MI.getOpcode();
6888
6889 int VOP3Idx[3] = {
6890 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
6891 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
6892 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
6893 };
6894
6895 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6896 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6897 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6898 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6899 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6900 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6901 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6902 // src1 and src2 must be scalar
6903 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
6904 const DebugLoc &DL = MI.getDebugLoc();
6905 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
6906 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6907 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6908 .add(Src1);
6909 Src1.ChangeToRegister(Reg, false);
6910 }
6911 if (VOP3Idx[2] != -1) {
6912 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
6913 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
6914 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6915 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6916 .add(Src2);
6917 Src2.ChangeToRegister(Reg, false);
6918 }
6919 }
6920 }
6921
6922 // Find the one SGPR operand we are allowed to use.
6923 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
6924 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
6925 SmallDenseSet<unsigned> SGPRsUsed;
6926 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
6927 if (SGPRReg) {
6928 SGPRsUsed.insert(SGPRReg);
6929 --ConstantBusLimit;
6930 }
6931
6932 for (int Idx : VOP3Idx) {
6933 if (Idx == -1)
6934 break;
6935 MachineOperand &MO = MI.getOperand(Idx);
6936
6937 if (!MO.isReg()) {
6938 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
6939 continue;
6940
6941 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
6942 --LiteralLimit;
6943 --ConstantBusLimit;
6944 continue;
6945 }
6946
6947 --LiteralLimit;
6948 --ConstantBusLimit;
6949 legalizeOpWithMove(MI, Idx);
6950 continue;
6951 }
6952
6953 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
6954 continue; // VGPRs are legal
6955
6956 // We can use one SGPR in each VOP3 instruction prior to GFX10
6957 // and two starting from GFX10.
6958 if (SGPRsUsed.count(MO.getReg()))
6959 continue;
6960 if (ConstantBusLimit > 0) {
6961 SGPRsUsed.insert(MO.getReg());
6962 --ConstantBusLimit;
6963 continue;
6964 }
6965
6966 // If we make it this far, then the operand is not legal and we must
6967 // legalize it.
6968 legalizeOpWithMove(MI, Idx);
6969 }
6970
6971 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
6972 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64) &&
6973 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
6974 legalizeOpWithMove(MI, VOP3Idx[2]);
6975
6976 // Fix the register class of single-sgpr-read instructions on gfx12+. See
6977 // SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6979 for (unsigned I = 0; I < 3; ++I) {
6980 if (!isLegalSingleSGPRReadInstOperand(MRI, MI, /*SrcN=*/I))
6981 legalizeOpWithMove(MI, VOP3Idx[I]);
6982 }
6983 }
6984}
6985
6988 const TargetRegisterClass *DstRC /*=nullptr*/) const {
6989 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
6990 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
6991 if (DstRC)
6992 SRC = RI.getCommonSubClass(SRC, DstRC);
6993
6994 Register DstReg = MRI.createVirtualRegister(SRC);
6995 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
6996
6997 if (RI.hasAGPRs(VRC)) {
6998 VRC = RI.getEquivalentVGPRClass(VRC);
6999 Register NewSrcReg = MRI.createVirtualRegister(VRC);
7000 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7001 get(TargetOpcode::COPY), NewSrcReg)
7002 .addReg(SrcReg);
7003 SrcReg = NewSrcReg;
7004 }
7005
7006 if (SubRegs == 1) {
7007 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7008 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7009 .addReg(SrcReg);
7010 return DstReg;
7011 }
7012
7014 for (unsigned i = 0; i < SubRegs; ++i) {
7015 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7016 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7017 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7018 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7019 SRegs.push_back(SGPR);
7020 }
7021
7023 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7024 get(AMDGPU::REG_SEQUENCE), DstReg);
7025 for (unsigned i = 0; i < SubRegs; ++i) {
7026 MIB.addReg(SRegs[i]);
7027 MIB.addImm(RI.getSubRegFromChannel(i));
7028 }
7029 return DstReg;
7030}
7031
7033 MachineInstr &MI) const {
7034
7035 // If the pointer is store in VGPRs, then we need to move them to
7036 // SGPRs using v_readfirstlane. This is safe because we only select
7037 // loads with uniform pointers to SMRD instruction so we know the
7038 // pointer value is uniform.
7039 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
7040 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
7041 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
7042 SBase->setReg(SGPR);
7043 }
7044 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
7045 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
7046 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
7047 SOff->setReg(SGPR);
7048 }
7049}
7050
7052 unsigned Opc = Inst.getOpcode();
7053 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
7054 if (OldSAddrIdx < 0)
7055 return false;
7056
7057 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
7058
7059 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
7060 if (NewOpc < 0)
7062 if (NewOpc < 0)
7063 return false;
7064
7065 MachineRegisterInfo &MRI = Inst.getMF()->getRegInfo();
7066 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
7067 if (RI.isSGPRReg(MRI, SAddr.getReg()))
7068 return false;
7069
7070 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7071 if (NewVAddrIdx < 0)
7072 return false;
7073
7074 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
7075
7076 // Check vaddr, it shall be zero or absent.
7077 MachineInstr *VAddrDef = nullptr;
7078 if (OldVAddrIdx >= 0) {
7079 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
7080 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
7081 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
7082 !VAddrDef->getOperand(1).isImm() ||
7083 VAddrDef->getOperand(1).getImm() != 0)
7084 return false;
7085 }
7086
7087 const MCInstrDesc &NewDesc = get(NewOpc);
7088 Inst.setDesc(NewDesc);
7089
7090 // Callers expect iterator to be valid after this call, so modify the
7091 // instruction in place.
7092 if (OldVAddrIdx == NewVAddrIdx) {
7093 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
7094 // Clear use list from the old vaddr holding a zero register.
7095 MRI.removeRegOperandFromUseList(&NewVAddr);
7096 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7097 Inst.removeOperand(OldSAddrIdx);
7098 // Update the use list with the pointer we have just moved from vaddr to
7099 // saddr position. Otherwise new vaddr will be missing from the use list.
7100 MRI.removeRegOperandFromUseList(&NewVAddr);
7101 MRI.addRegOperandToUseList(&NewVAddr);
7102 } else {
7103 assert(OldSAddrIdx == NewVAddrIdx);
7104
7105 if (OldVAddrIdx >= 0) {
7106 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7107 AMDGPU::OpName::vdst_in);
7108
7109 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
7110 // it asserts. Untie the operands for now and retie them afterwards.
7111 if (NewVDstIn != -1) {
7112 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
7113 Inst.untieRegOperand(OldVDstIn);
7114 }
7115
7116 Inst.removeOperand(OldVAddrIdx);
7117
7118 if (NewVDstIn != -1) {
7119 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7120 Inst.tieOperands(NewVDst, NewVDstIn);
7121 }
7122 }
7123 }
7124
7125 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
7126 VAddrDef->eraseFromParent();
7127
7128 return true;
7129}
7130
7131// FIXME: Remove this when SelectionDAG is obsoleted.
7133 MachineInstr &MI) const {
7134 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
7135 return;
7136
7137 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
7138 // thinks they are uniform, so a readfirstlane should be valid.
7139 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
7140 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
7141 return;
7142
7144 return;
7145
7146 const TargetRegisterClass *DeclaredRC =
7147 getRegClass(MI.getDesc(), SAddr->getOperandNo());
7148
7149 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
7150 SAddr->setReg(ToSGPR);
7151}
7152
7155 const TargetRegisterClass *DstRC,
7158 const DebugLoc &DL) const {
7159 Register OpReg = Op.getReg();
7160 unsigned OpSubReg = Op.getSubReg();
7161
7162 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
7163 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7164
7165 // Check if operand is already the correct register class.
7166 if (DstRC == OpRC)
7167 return;
7168
7169 Register DstReg = MRI.createVirtualRegister(DstRC);
7170 auto Copy = BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg)
7171 .addReg(OpReg, {}, OpSubReg);
7172 Op.setReg(DstReg);
7173 Op.setSubReg(AMDGPU::NoSubRegister);
7174
7175 MachineInstr *Def = MRI.getVRegDef(OpReg);
7176 if (!Def)
7177 return;
7178
7179 // Try to eliminate the copy if it is copying an immediate value.
7180 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7181 foldImmediate(*Copy, *Def, OpReg, &MRI);
7182
7183 bool ImpDef = Def->isImplicitDef();
7184 while (!ImpDef && Def && Def->isCopy()) {
7185 if (Def->getOperand(1).getReg().isPhysical())
7186 break;
7187 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7188 ImpDef = Def && Def->isImplicitDef();
7189 }
7190 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7191 !ImpDef)
7192 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7193}
7194
7195// Emit the actual waterfall loop, executing the wrapped instruction for each
7196// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7197// iteration, in the worst case we execute 64 (once per lane).
7200 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7201 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7202 MachineFunction &MF = *LoopBB.getParent();
7204 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7206 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7207
7208 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7209 // available. Otherwise, use the previous pattern of v_cmp_eq,
7210 // s_and_saveexec, and s_xor.
7211 bool UseNewExecInstructions =
7212 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7213
7215 Register CondReg;
7216
7217 Register PhiExec;
7218 Register NewExec;
7219
7220 if (UseNewExecInstructions) {
7221 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7222 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7223 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7224 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7225 .addReg(LMC.ExecReg);
7226
7227 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7228 .addReg(InitExec)
7229 .addMBB(&PredBB)
7230 .addReg(NewExec)
7231 .addMBB(&BodyBB);
7232 }
7233
7234 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7235 // involves a trade-off between register pressure and latency:
7236 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7237 // register pressure because arguments and results of all
7238 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7239 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7240 // increase latency by placing v_readfirstlane instructions
7241 // immediately before v_cmpx instruction that directly depend on it.
7242 ///
7243 // Emitting interleaved v_cmpx and v_readfirstlane requires
7244 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7245 // v_cmpx needs to be treated as terminator until after register allocation
7246 // (spill placement) and instruction reordering.
7247 //
7248 // Current implementation defers v_cmpx and leaves other instruction
7249 // scheduling decisions to later passes, where register pressure is known or
7250 // easier to approximate.
7251 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7252 // v_cmpx instructions are inserted at the end of LoopBB.
7253 // After the first v_cmpx is emitted, I is updated to point to it
7254 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7255 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7256 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7257 unsigned NumSubRegs = RegSize / 32;
7258 Register VScalarOp = ScalarOp->getReg();
7259
7260 const TargetRegisterClass *RFLSrcRC =
7261 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7262
7263 if (NumSubRegs == 1) {
7264 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7265 if (const TargetRegisterClass *Common =
7266 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7267 Common != VScalarOpRC) {
7268 Register VRReg = MRI.createVirtualRegister(Common);
7269 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7270 VScalarOp = VRReg;
7271 }
7272 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7273
7274 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7275 .addReg(VScalarOp);
7276
7277 if (UseNewExecInstructions) {
7278 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7279 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7280 .addReg(CurReg)
7281 .addReg(VScalarOp);
7282 if (I == LoopBB.end())
7283 I = CmpxMI.getInstr()->getIterator();
7284 } else {
7285 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7286
7287 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7288 .addReg(CurReg)
7289 .addReg(VScalarOp);
7290
7291 // Combine the comparison results with AND.
7292 if (!CondReg) { // First.
7293 CondReg = NewCondReg;
7294 } else { // If not the first, we create an AND.
7295 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7296 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7297 .addReg(CondReg)
7298 .addReg(NewCondReg);
7299 CondReg = AndReg;
7300 }
7301 }
7302
7303 // Update ScalarOp operand to use the SGPR ScalarOp.
7304 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7305 ScalarOp->setReg(CurReg);
7306 else {
7307 // Insert into the same block of use
7308 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7309 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7310 .addReg(CurReg);
7311 ScalarOp->setReg(PhySGPRs[Idx]);
7312 }
7313 ScalarOp->setIsKill();
7314 } else {
7315 SmallVector<Register, 8> ReadlanePieces;
7316 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7317 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7318 "Unhandled register size");
7319
7320 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7321 Register CurRegLo =
7322 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7323 Register CurRegHi =
7324 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7325
7326 // Read the next variant <- also loop target.
7327 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7328 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7329
7330 // Read the next variant <- also loop target.
7331 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7332 .addReg(VScalarOp, VScalarOpUndef,
7333 TRI->getSubRegFromChannel(Idx + 1));
7334
7335 ReadlanePieces.push_back(CurRegLo);
7336 ReadlanePieces.push_back(CurRegHi);
7337
7338 // Comparison is to be done as 64-bit.
7339 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7340 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7341 .addReg(CurRegLo)
7342 .addImm(AMDGPU::sub0)
7343 .addReg(CurRegHi)
7344 .addImm(AMDGPU::sub1);
7345
7346 unsigned SubReg =
7347 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7348
7349 if (UseNewExecInstructions) {
7350 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7351 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7352 .addReg(CurReg)
7353 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7354 if (I == LoopBB.end())
7355 I = CmpxMI.getInstr()->getIterator();
7356 } else {
7357 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7358 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7359 .addReg(CurReg)
7360 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7361
7362 // Combine the comparison results with AND.
7363 if (!CondReg) { // First.
7364 CondReg = NewCondReg;
7365 } else { // If not the first, we create an AND.
7366 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7367 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7368 .addReg(CondReg)
7369 .addReg(NewCondReg);
7370 CondReg = AndReg;
7371 }
7372 }
7373 } // End for loop.
7374
7375 const auto *SScalarOpRC =
7376 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7377 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7378
7379 // Build scalar ScalarOp.
7380 auto Merge =
7381 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7382 unsigned Channel = 0;
7383 for (Register Piece : ReadlanePieces) {
7384 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7385 }
7386
7387 // Update ScalarOp operand to use the SGPR ScalarOp.
7388 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7389 ScalarOp->setReg(SScalarOp);
7390 else {
7391 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7392 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7393 .addReg(SScalarOp);
7394 ScalarOp->setReg(PhySGPRs[Idx]);
7395 }
7396 ScalarOp->setIsKill();
7397 }
7398 }
7399
7400 // Instructions AndSaveExecOpc and AndN2WrExecOpc that modify EXEC mask
7401 // should have isTerminator=1 but terminators that define
7402 // virtual registers are not supported.
7403 Register SaveExec;
7404 if (!UseNewExecInstructions) {
7405 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7406 MRI.setSimpleHint(SaveExec, CondReg);
7407
7408 // Update EXEC to matching lanes, saving original to SaveExec.
7409 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7410 .addReg(CondReg, RegState::Kill);
7411 }
7412
7413 // The original instruction is here; we insert the terminators after it.
7414 I = BodyBB.end();
7415
7416 if (UseNewExecInstructions) {
7417 MRI.setSimpleHint(NewExec, PhiExec);
7418 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2WrExecOpc), NewExec)
7419 .addReg(PhiExec);
7420 } else {
7421 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7422 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7423 .addReg(LMC.ExecReg)
7424 .addReg(SaveExec);
7425 }
7426
7427 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7428}
7429
7430// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7431// with SGPRs by iterating over all unique values across all lanes.
7432// Returns the loop basic block that now contains \p MI.
7433static MachineBasicBlock *
7437 MachineBasicBlock::iterator Begin = nullptr,
7438 MachineBasicBlock::iterator End = nullptr,
7439 ArrayRef<Register> PhySGPRs = {}) {
7440 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7441 "Physical SGPRs must be empty or match the number of scalar operands");
7443 MachineFunction &MF = *MBB.getParent();
7445 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7446 MachineRegisterInfo &MRI = MF.getRegInfo();
7447 if (!Begin.isValid())
7448 Begin = &MI;
7449 if (!End.isValid()) {
7450 End = &MI;
7451 ++End;
7452 }
7453 const DebugLoc &DL = MI.getDebugLoc();
7455 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7456
7457 // Save SCC. Waterfall Loop may overwrite SCC.
7458 Register SaveSCCReg;
7459
7460 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7461 // rather than unlimited scan everywhere
7462 bool SCCNotDead =
7463 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7464 std::numeric_limits<unsigned>::max()) !=
7466 if (SCCNotDead) {
7467 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7468 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7469 .addImm(1)
7470 .addImm(0);
7471 }
7472
7473 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7474
7475 // Save the EXEC mask
7476 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7477
7478 // Killed uses in the instruction we are waterfalling around will be
7479 // incorrect due to the added control-flow.
7481 ++AfterMI;
7482 for (auto I = Begin; I != AfterMI; I++) {
7483 for (auto &MO : I->all_uses())
7484 MRI.clearKillFlags(MO.getReg());
7485 }
7486
7487 // To insert the loop we need to split the block. Move everything after this
7488 // point to a new block, and insert a new empty block between the two.
7491 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7493 ++MBBI;
7494
7495 MF.insert(MBBI, LoopBB);
7496 MF.insert(MBBI, BodyBB);
7497 MF.insert(MBBI, RemainderBB);
7498
7499 LoopBB->addSuccessor(BodyBB);
7500 BodyBB->addSuccessor(LoopBB);
7501 BodyBB->addSuccessor(RemainderBB);
7502
7503 // Move Begin to MI to the BodyBB, and the remainder of the block to
7504 // RemainderBB.
7505 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7506 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7507 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7508
7509 MBB.addSuccessor(LoopBB);
7510
7511 // Update dominators. We know that MBB immediately dominates LoopBB, that
7512 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7513 // RemainderBB. RemainderBB immediately dominates all of the successors
7514 // transferred to it from MBB that MBB used to properly dominate.
7515 if (MDT) {
7516 MDT->addNewBlock(LoopBB, &MBB);
7517 MDT->addNewBlock(BodyBB, LoopBB);
7518 MDT->addNewBlock(RemainderBB, BodyBB);
7519 for (auto &Succ : RemainderBB->successors()) {
7520 if (MDT->properlyDominates(&MBB, Succ)) {
7521 MDT->changeImmediateDominator(Succ, RemainderBB);
7522 }
7523 }
7524 }
7525
7526 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7527 PhySGPRs);
7528
7529 MachineBasicBlock::iterator First = RemainderBB->begin();
7530 // Restore SCC
7531 if (SCCNotDead) {
7532 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7533 .addReg(SaveSCCReg, RegState::Kill)
7534 .addImm(0);
7535 }
7536
7537 // Restore the EXEC mask
7538 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7539 .addReg(SaveExec);
7540 return BodyBB;
7541}
7542
7543// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7544static std::tuple<unsigned, unsigned>
7546 MachineBasicBlock &MBB = *MI.getParent();
7547 MachineFunction &MF = *MBB.getParent();
7548 MachineRegisterInfo &MRI = MF.getRegInfo();
7549
7550 // Extract the ptr from the resource descriptor.
7551 unsigned RsrcPtr =
7552 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7553 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7554
7555 // Create an empty resource descriptor
7556 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7557 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7558 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7559 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7560 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7561
7562 // Zero64 = 0
7563 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7564 .addImm(0);
7565
7566 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7567 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7568 .addImm(Lo_32(RsrcDataFormat));
7569
7570 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7571 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7572 .addImm(Hi_32(RsrcDataFormat));
7573
7574 // NewSRsrc = {Zero64, SRsrcFormat}
7575 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7576 .addReg(Zero64)
7577 .addImm(AMDGPU::sub0_sub1)
7578 .addReg(SRsrcFormatLo)
7579 .addImm(AMDGPU::sub2)
7580 .addReg(SRsrcFormatHi)
7581 .addImm(AMDGPU::sub3);
7582
7583 return std::tuple(RsrcPtr, NewSRsrc);
7584}
7585
7588 MachineDominatorTree *MDT) const {
7589 MachineFunction &MF = *MI.getMF();
7590 MachineRegisterInfo &MRI = MF.getRegInfo();
7591 MachineBasicBlock *CreatedBB = nullptr;
7592
7593 // Legalize True16
7594 if (ST.useRealTrue16Insts())
7596
7597 // Legalize VOP2
7598 if (isVOP2(MI) || isVOPC(MI)) {
7600 return CreatedBB;
7601 }
7602
7603 // Legalize VOP3
7604 if (isVOP3(MI)) {
7606 return CreatedBB;
7607 }
7608
7609 // Legalize SMRD
7610 if (isSMRD(MI)) {
7612 return CreatedBB;
7613 }
7614
7615 // Legalize FLAT
7616 if (isFLAT(MI)) {
7618 return CreatedBB;
7619 }
7620
7621 // Legalize PHI
7622 // The register class of the operands must be the same type as the register
7623 // class of the output.
7624 if (MI.getOpcode() == AMDGPU::PHI) {
7625 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7626 assert(!RI.isSGPRClass(VRC));
7627
7628 // Update all the operands so they have the same type.
7629 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7630 MachineOperand &Op = MI.getOperand(I);
7631 if (!Op.isReg() || !Op.getReg().isVirtual())
7632 continue;
7633
7634 // MI is a PHI instruction.
7635 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7637
7638 // Avoid creating no-op copies with the same src and dst reg class. These
7639 // confuse some of the machine passes.
7640 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7641 }
7642 }
7643
7644 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7645 // VGPR dest type and SGPR sources, insert copies so all operands are
7646 // VGPRs. This seems to help operand folding / the register coalescer.
7647 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7648 MachineBasicBlock *MBB = MI.getParent();
7649 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7650 if (RI.hasVGPRs(DstRC)) {
7651 // Update all the operands so they are VGPR register classes. These may
7652 // not be the same register class because REG_SEQUENCE supports mixing
7653 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7654 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7655 MachineOperand &Op = MI.getOperand(I);
7656 if (!Op.isReg() || !Op.getReg().isVirtual())
7657 continue;
7658
7659 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7660 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7661 if (VRC == OpRC)
7662 continue;
7663
7664 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7665 Op.setIsKill();
7666 }
7667 }
7668
7669 return CreatedBB;
7670 }
7671
7672 // Legalize INSERT_SUBREG
7673 // src0 must have the same register class as dst
7674 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7675 Register Dst = MI.getOperand(0).getReg();
7676 Register Src0 = MI.getOperand(1).getReg();
7677 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7678 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7679 if (DstRC != Src0RC) {
7680 MachineBasicBlock *MBB = MI.getParent();
7681 MachineOperand &Op = MI.getOperand(1);
7682 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7683 }
7684 return CreatedBB;
7685 }
7686
7687 // Legalize SI_INIT_M0
7688 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7689 MachineOperand &Src = MI.getOperand(0);
7690 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7691 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7692 return CreatedBB;
7693 }
7694
7695 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
7696 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7697 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7698 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7699 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7700 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7701 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7702 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7703 MachineOperand &Src = MI.getOperand(1);
7704 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7705 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7706 return CreatedBB;
7707 }
7708
7709 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
7710 //
7711 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
7712 // scratch memory access. In both cases, the legalization never involves
7713 // conversion to the addr64 form.
7715 (isMUBUF(MI) || isMTBUF(MI)))) {
7716 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
7717 ? AMDGPU::OpName::rsrc
7718 : AMDGPU::OpName::srsrc;
7719 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
7720 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
7721 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
7722
7723 AMDGPU::OpName SampOpName =
7724 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7725 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
7726 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
7727 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
7728
7729 return CreatedBB;
7730 }
7731
7732 // Legalize SI_CALL
7733 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7734 MachineOperand *Dest = &MI.getOperand(0);
7735 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
7736 createWaterFallForSiCall(&MI, MDT, {Dest});
7737 }
7738 }
7739
7740 // Legalize s_sleep_var.
7741 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7742 const DebugLoc &DL = MI.getDebugLoc();
7743 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7744 int Src0Idx =
7745 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
7746 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7747 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7748 .add(Src0);
7749 Src0.ChangeToRegister(Reg, false);
7750 return nullptr;
7751 }
7752
7753 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
7754 // operands are scalar.
7755 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7756 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7757 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7758 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7759 for (MachineOperand &Src : MI.explicit_operands()) {
7760 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7761 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7762 }
7763 return CreatedBB;
7764 }
7765
7766 // Legalize MUBUF instructions.
7767 bool isSoffsetLegal = true;
7768 int SoffsetIdx =
7769 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
7770 if (SoffsetIdx != -1) {
7771 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
7772 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
7773 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
7774 isSoffsetLegal = false;
7775 }
7776 }
7777
7778 bool isRsrcLegal = true;
7779 int RsrcIdx =
7780 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
7781 if (RsrcIdx != -1) {
7782 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7783 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
7784 isRsrcLegal = false;
7785 }
7786
7787 // The operands are legal.
7788 if (isRsrcLegal && isSoffsetLegal)
7789 return CreatedBB;
7790
7791 if (!isRsrcLegal) {
7792 // Legalize a VGPR Rsrc
7793 //
7794 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
7795 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
7796 // a zero-value SRsrc.
7797 //
7798 // If the instruction is _OFFSET (both idxen and offen disabled), and we
7799 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
7800 // above.
7801 //
7802 // Otherwise we are on non-ADDR64 hardware, and/or we have
7803 // idxen/offen/bothen and we fall back to a waterfall loop.
7804
7805 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7806 MachineBasicBlock &MBB = *MI.getParent();
7807
7808 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
7809 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
7810 // This is already an ADDR64 instruction so we need to add the pointer
7811 // extracted from the resource descriptor to the current value of VAddr.
7812 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7813 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7814 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7815
7816 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7817 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
7818 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
7819
7820 unsigned RsrcPtr, NewSRsrc;
7821 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7822
7823 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
7824 const DebugLoc &DL = MI.getDebugLoc();
7825 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
7826 .addDef(CondReg0)
7827 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7828 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
7829 .addImm(0);
7830
7831 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
7832 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
7833 .addDef(CondReg1, RegState::Dead)
7834 .addReg(RsrcPtr, {}, AMDGPU::sub1)
7835 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
7836 .addReg(CondReg0, RegState::Kill)
7837 .addImm(0);
7838
7839 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7840 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
7841 .addReg(NewVAddrLo)
7842 .addImm(AMDGPU::sub0)
7843 .addReg(NewVAddrHi)
7844 .addImm(AMDGPU::sub1);
7845
7846 VAddr->setReg(NewVAddr);
7847 Rsrc->setReg(NewSRsrc);
7848 } else if (!VAddr && ST.hasAddr64()) {
7849 // This instructions is the _OFFSET variant, so we need to convert it to
7850 // ADDR64.
7851 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
7852 "FIXME: Need to emit flat atomics here");
7853
7854 unsigned RsrcPtr, NewSRsrc;
7855 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7856
7857 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7858 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
7859 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
7860 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7861 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
7862
7863 // Atomics with return have an additional tied operand and are
7864 // missing some of the special bits.
7865 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
7866 MachineInstr *Addr64;
7867
7868 if (!VDataIn) {
7869 // Regular buffer load / store.
7871 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7872 .add(*VData)
7873 .addReg(NewVAddr)
7874 .addReg(NewSRsrc)
7875 .add(*SOffset)
7876 .add(*Offset);
7877
7878 if (const MachineOperand *CPol =
7879 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
7880 MIB.addImm(CPol->getImm());
7881 }
7882
7883 if (const MachineOperand *TFE =
7884 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
7885 MIB.addImm(TFE->getImm());
7886 }
7887
7888 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
7889
7890 MIB.cloneMemRefs(MI);
7891 Addr64 = MIB;
7892 } else {
7893 // Atomics with return.
7894 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7895 .add(*VData)
7896 .add(*VDataIn)
7897 .addReg(NewVAddr)
7898 .addReg(NewSRsrc)
7899 .add(*SOffset)
7900 .add(*Offset)
7901 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
7902 .cloneMemRefs(MI);
7903 }
7904
7905 MI.removeFromParent();
7906
7907 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7908 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
7909 NewVAddr)
7910 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7911 .addImm(AMDGPU::sub0)
7912 .addReg(RsrcPtr, {}, AMDGPU::sub1)
7913 .addImm(AMDGPU::sub1);
7914 } else {
7915 // Legalize a VGPR Rsrc and soffset together.
7916 if (!isSoffsetLegal) {
7917 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7918 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
7919 return CreatedBB;
7920 }
7921 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
7922 return CreatedBB;
7923 }
7924 }
7925
7926 // Legalize a VGPR soffset.
7927 if (!isSoffsetLegal) {
7928 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7929 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
7930 return CreatedBB;
7931 }
7932 return CreatedBB;
7933}
7934
7936 if (InSet.insert(MI).second)
7937 InstrList.push_back(MI);
7938 // Add MBUF instructiosn to deferred list.
7939 int RsrcIdx =
7940 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
7941 if (RsrcIdx != -1) {
7942 DeferredList.insert(MI);
7943 }
7944}
7945
7947 return DeferredList.contains(MI);
7948}
7949
7950// Legalize size mismatches between 16bit and 32bit registers in v2s copy
7951// lowering (change sgpr to vgpr).
7952// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
7953// size. Need to legalize the size of the operands during the vgpr lowering
7954// chain. This can be removed after we have sgpr16 in place
7956 MachineRegisterInfo &MRI) const {
7957 if (!ST.useRealTrue16Insts())
7958 return;
7959
7960 unsigned Opcode = MI.getOpcode();
7961 MachineBasicBlock *MBB = MI.getParent();
7962 // Legalize operands and check for size mismatch
7963 if (OpIdx >= MI.getNumExplicitOperands() ||
7964 OpIdx >= get(Opcode).getNumOperands() ||
7965 get(Opcode).operands()[OpIdx].RegClass == -1)
7966 return;
7967
7968 MachineOperand &Op = MI.getOperand(OpIdx);
7969 if (!Op.isReg() || !Op.getReg().isVirtual() || Op.isDef())
7970 return;
7971
7972 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
7973 if (!RI.isVGPRClass(CurrRC))
7974 return;
7975
7976 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
7977 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
7978 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
7979 // Default to the lo16 only if the subregister is not specified.
7980 if (Op.getSubReg() == AMDGPU::NoSubRegister)
7981 Op.setSubReg(AMDGPU::lo16);
7982 return;
7983 }
7984
7985 const TargetRegisterClass *CurrSRC =
7986 RI.getSubRegisterClass(CurrRC, Op.getSubReg());
7987 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
7988 const DebugLoc &DL = MI.getDebugLoc();
7989 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7990 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
7991 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
7992 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
7993 .addReg(Op.getReg(), {}, Op.getSubReg())
7994 .addImm(AMDGPU::lo16)
7995 .addReg(Undef)
7996 .addImm(AMDGPU::hi16);
7997 Op.setReg(NewDstReg);
7998 Op.setSubReg(AMDGPU::NoSubRegister);
7999 }
8000}
8002 MachineRegisterInfo &MRI) const {
8003 for (unsigned OpIdx = 0; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
8004 legalizeOperandsVALUt16(MI, OpIdx, MRI);
8005}
8006
8010 ArrayRef<Register> PhySGPRs) const {
8011 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8012 "This only handle waterfall for SI_CALL_ISEL");
8013 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
8014 // following copies, we also need to move copies from and to physical
8015 // registers into the loop block.
8016 // Also move the copies to physical registers into the loop block
8017 MachineBasicBlock &MBB = *MI->getParent();
8019 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8020 --Start;
8022 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8023 ++End;
8024
8025 // Also include following copies of the return value
8026 ++End;
8027 while (End != MBB.end() && End->isCopy() &&
8028 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8029 ++End;
8030
8031 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
8032}
8033
8035 MachineDominatorTree *MDT) const {
8037 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
8038 while (!Worklist.empty()) {
8039 MachineInstr &Inst = *Worklist.top();
8040 Worklist.erase_top();
8041 // Skip MachineInstr in the deferred list.
8042 if (Worklist.isDeferred(&Inst))
8043 continue;
8044 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8045 }
8046
8047 // Deferred list of instructions will be processed once
8048 // all the MachineInstr in the worklist are done.
8049 for (MachineInstr *Inst : Worklist.getDeferredList()) {
8050 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8051 assert(Worklist.empty() &&
8052 "Deferred MachineInstr are not supposed to re-populate worklist");
8053 }
8054
8055 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
8056 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8057 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
8058 Entry.second.SGPRs);
8059 }
8060
8061 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8062 if (Entry.second)
8063 Entry.first->eraseFromParent();
8064}
8066 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
8067 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
8068 // hope for the best.
8069 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
8070 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
8071 if (SubRegIndices.size() <= 1) {
8072 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8073 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8074 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8075 .add(Inst.getOperand(1));
8076 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
8077 DstReg)
8078 .addReg(NewDst);
8079 } else {
8081 for (int16_t Indice : SubRegIndices) {
8082 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8083 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8084 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8085 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
8086
8087 DstRegs.push_back(NewDst);
8088 }
8090 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8091 get(AMDGPU::REG_SEQUENCE), DstReg);
8092 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
8093 MIB.addReg(DstRegs[i]);
8094 MIB.addImm(RI.getSubRegFromChannel(i));
8095 }
8096 }
8097}
8098
8100 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
8103 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8104 if (DstReg == AMDGPU::M0) {
8105 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8106 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8107 return;
8108 }
8109 Register SrcReg = Inst.getOperand(1).getReg();
8112 // Only search current block since phyreg's def & use cannot cross
8113 // blocks when MF.NoPhi = false.
8114 while (++I != E) {
8115 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
8116 // and record the operand for later waterfall loop generation.
8117 if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8118 MachineInstr *UseMI = &*I;
8119 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
8120 if (UseMI->getOperand(i).isReg() &&
8121 UseMI->getOperand(i).getReg() == DstReg) {
8122 MachineOperand *MO = &UseMI->getOperand(i);
8123 MO->setReg(SrcReg);
8124 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
8125 V2SCopyInfo.MOs.push_back(MO);
8126 V2SCopyInfo.SGPRs.push_back(DstReg);
8127 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8128 }
8129 }
8130 } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8131 I->getOperand(0).isReg() &&
8132 I->getOperand(0).getReg() == DstReg) {
8133 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8134 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8135 } else if (I->readsRegister(DstReg, &RI)) {
8136 // COPY cannot be erased if other type of inst uses it.
8137 V2SPhyCopiesToErase[&Inst] = false;
8138 }
8139 if (I->findRegisterDefOperand(DstReg, &RI))
8140 break;
8141 }
8142}
8143
8145 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
8147 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8148
8150 if (!MBB)
8151 return;
8152 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
8153 unsigned Opcode = Inst.getOpcode();
8154 unsigned NewOpcode = getVALUOp(Inst);
8155 const DebugLoc &DL = Inst.getDebugLoc();
8156
8157 // Handle some special cases
8158 switch (Opcode) {
8159 default:
8160 break;
8161 case AMDGPU::S_ADD_I32:
8162 case AMDGPU::S_SUB_I32: {
8163 // FIXME: The u32 versions currently selected use the carry.
8164 bool Changed;
8165 MachineBasicBlock *CreatedBBTmp = nullptr;
8166 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8167 if (Changed)
8168 return;
8169
8170 // Default handling
8171 break;
8172 }
8173
8174 case AMDGPU::S_MUL_U64:
8175 if (ST.hasVMulU64Inst()) {
8176 NewOpcode = AMDGPU::V_MUL_U64_e64;
8177 break;
8178 }
8179 // Split s_mul_u64 in 32-bit vector multiplications.
8180 splitScalarSMulU64(Worklist, Inst, MDT);
8181 Inst.eraseFromParent();
8182 return;
8183
8184 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8185 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8186 // This is a special case of s_mul_u64 where all the operands are either
8187 // zero extended or sign extended.
8188 splitScalarSMulPseudo(Worklist, Inst, MDT);
8189 Inst.eraseFromParent();
8190 return;
8191
8192 case AMDGPU::S_AND_B64:
8193 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8194 Inst.eraseFromParent();
8195 return;
8196
8197 case AMDGPU::S_OR_B64:
8198 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8199 Inst.eraseFromParent();
8200 return;
8201
8202 case AMDGPU::S_XOR_B64:
8203 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8204 Inst.eraseFromParent();
8205 return;
8206
8207 case AMDGPU::S_NAND_B64:
8208 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8209 Inst.eraseFromParent();
8210 return;
8211
8212 case AMDGPU::S_NOR_B64:
8213 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8214 Inst.eraseFromParent();
8215 return;
8216
8217 case AMDGPU::S_XNOR_B64:
8218 if (ST.hasDLInsts())
8219 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8220 else
8221 splitScalar64BitXnor(Worklist, Inst, MDT);
8222 Inst.eraseFromParent();
8223 return;
8224
8225 case AMDGPU::S_ANDN2_B64:
8226 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8227 Inst.eraseFromParent();
8228 return;
8229
8230 case AMDGPU::S_ORN2_B64:
8231 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8232 Inst.eraseFromParent();
8233 return;
8234
8235 case AMDGPU::S_BREV_B64:
8236 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8237 Inst.eraseFromParent();
8238 return;
8239
8240 case AMDGPU::S_NOT_B64:
8241 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8242 Inst.eraseFromParent();
8243 return;
8244
8245 case AMDGPU::S_BCNT1_I32_B64:
8246 splitScalar64BitBCNT(Worklist, Inst);
8247 Inst.eraseFromParent();
8248 return;
8249
8250 case AMDGPU::S_BFE_I64:
8251 splitScalar64BitBFE(Worklist, Inst);
8252 Inst.eraseFromParent();
8253 return;
8254
8255 case AMDGPU::S_FLBIT_I32_B64:
8256 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8257 Inst.eraseFromParent();
8258 return;
8259 case AMDGPU::S_FF1_I32_B64:
8260 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8261 Inst.eraseFromParent();
8262 return;
8263
8264 case AMDGPU::S_LSHL_B32:
8265 if (ST.hasOnlyRevVALUShifts()) {
8266 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8267 swapOperands(Inst);
8268 }
8269 break;
8270 case AMDGPU::S_ASHR_I32:
8271 if (ST.hasOnlyRevVALUShifts()) {
8272 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8273 swapOperands(Inst);
8274 }
8275 break;
8276 case AMDGPU::S_LSHR_B32:
8277 if (ST.hasOnlyRevVALUShifts()) {
8278 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8279 swapOperands(Inst);
8280 }
8281 break;
8282 case AMDGPU::S_LSHL_B64:
8283 if (ST.hasOnlyRevVALUShifts()) {
8284 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8285 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8286 : AMDGPU::V_LSHLREV_B64_e64;
8287 swapOperands(Inst);
8288 }
8289 break;
8290 case AMDGPU::S_ASHR_I64:
8291 if (ST.hasOnlyRevVALUShifts()) {
8292 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8293 swapOperands(Inst);
8294 }
8295 break;
8296 case AMDGPU::S_LSHR_B64:
8297 if (ST.hasOnlyRevVALUShifts()) {
8298 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8299 swapOperands(Inst);
8300 }
8301 break;
8302
8303 case AMDGPU::S_ABS_I32:
8304 lowerScalarAbs(Worklist, Inst);
8305 Inst.eraseFromParent();
8306 return;
8307
8308 case AMDGPU::S_ABSDIFF_I32:
8309 lowerScalarAbsDiff(Worklist, Inst);
8310 Inst.eraseFromParent();
8311 return;
8312
8313 case AMDGPU::S_CBRANCH_SCC0:
8314 case AMDGPU::S_CBRANCH_SCC1: {
8315 // Clear unused bits of vcc
8316 Register CondReg = Inst.getOperand(1).getReg();
8317 bool IsSCC = CondReg == AMDGPU::SCC;
8319 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8320 .addReg(LMC.ExecReg)
8321 .addReg(IsSCC ? LMC.VccReg : CondReg);
8322 Inst.removeOperand(1);
8323 } break;
8324
8325 case AMDGPU::S_BFE_U64:
8326 case AMDGPU::S_BFM_B64:
8327 llvm_unreachable("Moving this op to VALU not implemented");
8328
8329 case AMDGPU::S_PACK_LL_B32_B16:
8330 case AMDGPU::S_PACK_LH_B32_B16:
8331 case AMDGPU::S_PACK_HL_B32_B16:
8332 case AMDGPU::S_PACK_HH_B32_B16:
8333 movePackToVALU(Worklist, MRI, Inst);
8334 Inst.eraseFromParent();
8335 return;
8336
8337 case AMDGPU::S_XNOR_B32:
8338 lowerScalarXnor(Worklist, Inst);
8339 Inst.eraseFromParent();
8340 return;
8341
8342 case AMDGPU::S_NAND_B32:
8343 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8344 Inst.eraseFromParent();
8345 return;
8346
8347 case AMDGPU::S_NOR_B32:
8348 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8349 Inst.eraseFromParent();
8350 return;
8351
8352 case AMDGPU::S_ANDN2_B32:
8353 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8354 Inst.eraseFromParent();
8355 return;
8356
8357 case AMDGPU::S_ORN2_B32:
8358 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8359 Inst.eraseFromParent();
8360 return;
8361
8362 // TODO: remove as soon as everything is ready
8363 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8364 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8365 // can only be selected from the uniform SDNode.
8366 case AMDGPU::S_ADD_CO_PSEUDO:
8367 case AMDGPU::S_SUB_CO_PSEUDO: {
8368 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8369 ? AMDGPU::V_ADDC_U32_e64
8370 : AMDGPU::V_SUBB_U32_e64;
8371 const auto *CarryRC = RI.getWaveMaskRegClass();
8372
8373 Register CarryInReg = Inst.getOperand(4).getReg();
8374 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8375 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8376 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8377 .addReg(CarryInReg);
8378 }
8379
8380 Register CarryOutReg = Inst.getOperand(1).getReg();
8381
8382 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8383 MRI.getRegClass(Inst.getOperand(0).getReg())));
8384 MachineInstr *CarryOp =
8385 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8386 .addReg(CarryOutReg, RegState::Define)
8387 .add(Inst.getOperand(2))
8388 .add(Inst.getOperand(3))
8389 .addReg(CarryInReg)
8390 .addImm(0);
8391 legalizeOperands(*CarryOp);
8392 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8393 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8394 Inst.eraseFromParent();
8395 }
8396 return;
8397 case AMDGPU::S_UADDO_PSEUDO:
8398 case AMDGPU::S_USUBO_PSEUDO: {
8399 MachineOperand &Dest0 = Inst.getOperand(0);
8400 MachineOperand &Dest1 = Inst.getOperand(1);
8401 MachineOperand &Src0 = Inst.getOperand(2);
8402 MachineOperand &Src1 = Inst.getOperand(3);
8403
8404 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8405 ? AMDGPU::V_ADD_CO_U32_e64
8406 : AMDGPU::V_SUB_CO_U32_e64;
8407 const TargetRegisterClass *NewRC =
8408 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8409 Register DestReg = MRI.createVirtualRegister(NewRC);
8410 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8411 .addReg(Dest1.getReg(), RegState::Define)
8412 .add(Src0)
8413 .add(Src1)
8414 .addImm(0); // clamp bit
8415
8416 legalizeOperands(*NewInstr, MDT);
8417 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8418 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8419 Inst.eraseFromParent();
8420 }
8421 return;
8422 case AMDGPU::S_LSHL1_ADD_U32:
8423 case AMDGPU::S_LSHL2_ADD_U32:
8424 case AMDGPU::S_LSHL3_ADD_U32:
8425 case AMDGPU::S_LSHL4_ADD_U32: {
8426 MachineOperand &Dest = Inst.getOperand(0);
8427 MachineOperand &Src0 = Inst.getOperand(1);
8428 MachineOperand &Src1 = Inst.getOperand(2);
8429 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8430 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8431 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8432 : 4);
8433
8434 const TargetRegisterClass *NewRC =
8435 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8436 Register DestReg = MRI.createVirtualRegister(NewRC);
8437 MachineInstr *NewInstr =
8438 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8439 .add(Src0)
8440 .addImm(ShiftAmt)
8441 .add(Src1);
8442
8443 legalizeOperands(*NewInstr, MDT);
8444 MRI.replaceRegWith(Dest.getReg(), DestReg);
8445 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8446 Inst.eraseFromParent();
8447 }
8448 return;
8449 case AMDGPU::S_CSELECT_B32:
8450 case AMDGPU::S_CSELECT_B64:
8451 lowerSelect(Worklist, Inst, MDT);
8452 Inst.eraseFromParent();
8453 return;
8454 case AMDGPU::S_CMP_EQ_I32:
8455 case AMDGPU::S_CMP_LG_I32:
8456 case AMDGPU::S_CMP_GT_I32:
8457 case AMDGPU::S_CMP_GE_I32:
8458 case AMDGPU::S_CMP_LT_I32:
8459 case AMDGPU::S_CMP_LE_I32:
8460 case AMDGPU::S_CMP_EQ_U32:
8461 case AMDGPU::S_CMP_LG_U32:
8462 case AMDGPU::S_CMP_GT_U32:
8463 case AMDGPU::S_CMP_GE_U32:
8464 case AMDGPU::S_CMP_LT_U32:
8465 case AMDGPU::S_CMP_LE_U32:
8466 case AMDGPU::S_CMP_EQ_U64:
8467 case AMDGPU::S_CMP_LG_U64:
8468 case AMDGPU::S_CMP_LT_F32:
8469 case AMDGPU::S_CMP_EQ_F32:
8470 case AMDGPU::S_CMP_LE_F32:
8471 case AMDGPU::S_CMP_GT_F32:
8472 case AMDGPU::S_CMP_LG_F32:
8473 case AMDGPU::S_CMP_GE_F32:
8474 case AMDGPU::S_CMP_O_F32:
8475 case AMDGPU::S_CMP_U_F32:
8476 case AMDGPU::S_CMP_NGE_F32:
8477 case AMDGPU::S_CMP_NLG_F32:
8478 case AMDGPU::S_CMP_NGT_F32:
8479 case AMDGPU::S_CMP_NLE_F32:
8480 case AMDGPU::S_CMP_NEQ_F32:
8481 case AMDGPU::S_CMP_NLT_F32: {
8482 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8483 auto NewInstr =
8484 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8485 .setMIFlags(Inst.getFlags());
8486 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8487 0) {
8488 NewInstr
8489 .addImm(0) // src0_modifiers
8490 .add(Inst.getOperand(0)) // src0
8491 .addImm(0) // src1_modifiers
8492 .add(Inst.getOperand(1)) // src1
8493 .addImm(0); // clamp
8494 } else {
8495 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8496 }
8497 legalizeOperands(*NewInstr, MDT);
8498 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8499 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8500 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8501 Inst.eraseFromParent();
8502 return;
8503 }
8504 case AMDGPU::S_CMP_LT_F16:
8505 case AMDGPU::S_CMP_EQ_F16:
8506 case AMDGPU::S_CMP_LE_F16:
8507 case AMDGPU::S_CMP_GT_F16:
8508 case AMDGPU::S_CMP_LG_F16:
8509 case AMDGPU::S_CMP_GE_F16:
8510 case AMDGPU::S_CMP_O_F16:
8511 case AMDGPU::S_CMP_U_F16:
8512 case AMDGPU::S_CMP_NGE_F16:
8513 case AMDGPU::S_CMP_NLG_F16:
8514 case AMDGPU::S_CMP_NGT_F16:
8515 case AMDGPU::S_CMP_NLE_F16:
8516 case AMDGPU::S_CMP_NEQ_F16:
8517 case AMDGPU::S_CMP_NLT_F16: {
8518 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8519 auto NewInstr =
8520 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8521 .setMIFlags(Inst.getFlags());
8522 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8523 NewInstr
8524 .addImm(0) // src0_modifiers
8525 .add(Inst.getOperand(0)) // src0
8526 .addImm(0) // src1_modifiers
8527 .add(Inst.getOperand(1)) // src1
8528 .addImm(0); // clamp
8529 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8530 NewInstr.addImm(0); // op_sel0
8531 } else {
8532 NewInstr
8533 .add(Inst.getOperand(0))
8534 .add(Inst.getOperand(1));
8535 }
8536 legalizeOperands(*NewInstr, MDT);
8537 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8538 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8539 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8540 Inst.eraseFromParent();
8541 return;
8542 }
8543 case AMDGPU::S_CVT_HI_F32_F16: {
8544 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8545 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8546 if (ST.useRealTrue16Insts()) {
8547 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8548 .add(Inst.getOperand(1));
8549 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8550 .addImm(0) // src0_modifiers
8551 .addReg(TmpReg, {}, AMDGPU::hi16)
8552 .addImm(0) // clamp
8553 .addImm(0) // omod
8554 .addImm(0); // op_sel0
8555 } else {
8556 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8557 .addImm(16)
8558 .add(Inst.getOperand(1));
8559 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8560 .addImm(0) // src0_modifiers
8561 .addReg(TmpReg)
8562 .addImm(0) // clamp
8563 .addImm(0); // omod
8564 }
8565
8566 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8567 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8568 Inst.eraseFromParent();
8569 return;
8570 }
8571 case AMDGPU::S_MINIMUM_F32:
8572 case AMDGPU::S_MAXIMUM_F32: {
8573 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8574 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8575 .addImm(0) // src0_modifiers
8576 .add(Inst.getOperand(1))
8577 .addImm(0) // src1_modifiers
8578 .add(Inst.getOperand(2))
8579 .addImm(0) // clamp
8580 .addImm(0); // omod
8581 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8582
8583 legalizeOperands(*NewInstr, MDT);
8584 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8585 Inst.eraseFromParent();
8586 return;
8587 }
8588 case AMDGPU::S_MINIMUM_F16:
8589 case AMDGPU::S_MAXIMUM_F16: {
8590 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8591 ? &AMDGPU::VGPR_16RegClass
8592 : &AMDGPU::VGPR_32RegClass);
8593 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8594 .addImm(0) // src0_modifiers
8595 .add(Inst.getOperand(1))
8596 .addImm(0) // src1_modifiers
8597 .add(Inst.getOperand(2))
8598 .addImm(0) // clamp
8599 .addImm(0) // omod
8600 .addImm(0); // opsel0
8601 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8602 legalizeOperands(*NewInstr, MDT);
8603 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8604 Inst.eraseFromParent();
8605 return;
8606 }
8607 case AMDGPU::V_S_EXP_F16_e64:
8608 case AMDGPU::V_S_LOG_F16_e64:
8609 case AMDGPU::V_S_RCP_F16_e64:
8610 case AMDGPU::V_S_RSQ_F16_e64:
8611 case AMDGPU::V_S_SQRT_F16_e64: {
8612 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8613 ? &AMDGPU::VGPR_16RegClass
8614 : &AMDGPU::VGPR_32RegClass);
8615 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8616 .add(Inst.getOperand(1)) // src0_modifiers
8617 .add(Inst.getOperand(2))
8618 .add(Inst.getOperand(3)) // clamp
8619 .add(Inst.getOperand(4)) // omod
8620 .setMIFlags(Inst.getFlags());
8621 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8622 NewInstr.addImm(0); // opsel0
8623 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8624 legalizeOperands(*NewInstr, MDT);
8625 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8626 Inst.eraseFromParent();
8627 return;
8628 }
8629 }
8630
8631 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8632 // We cannot move this instruction to the VALU, so we should try to
8633 // legalize its operands instead.
8634 legalizeOperands(Inst, MDT);
8635 return;
8636 }
8637 // Handle converting generic instructions like COPY-to-SGPR into
8638 // COPY-to-VGPR.
8639 if (NewOpcode == Opcode) {
8640 Register DstReg = Inst.getOperand(0).getReg();
8641 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8642
8643 if (Inst.isCopy() && DstReg.isPhysical() &&
8644 Inst.getOperand(1).getReg().isVirtual()) {
8645 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8646 V2SPhyCopiesToErase);
8647 return;
8648 }
8649
8650 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8651 Register NewDstReg = Inst.getOperand(1).getReg();
8652 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8653 if (const TargetRegisterClass *CommonRC =
8654 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8655 // Instead of creating a copy where src and dst are the same register
8656 // class, we just replace all uses of dst with src. These kinds of
8657 // copies interfere with the heuristics MachineSink uses to decide
8658 // whether or not to split a critical edge. Since the pass assumes
8659 // that copies will end up as machine instructions and not be
8660 // eliminated.
8661 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8662 unsigned SrcSubReg = Inst.getOperand(1).getSubReg();
8663 bool IsUndef = Inst.getOperand(1).isUndef();
8664 for (MachineOperand &UseMO :
8665 make_early_inc_range(MRI.use_operands(DstReg))) {
8666 UseMO.setSubReg(
8667 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8668 UseMO.setReg(NewDstReg);
8669 if (IsUndef)
8670 UseMO.setIsUndef();
8671 }
8672 MRI.clearKillFlags(NewDstReg);
8673
8674 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8675 llvm_unreachable("failed to constrain register");
8676
8677 Inst.eraseFromParent();
8678
8679 for (MachineOperand &UseMO :
8680 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8681 MachineInstr &UseMI = *UseMO.getParent();
8682
8683 // Legalize t16 operands since replaceReg is called after
8684 // addUsersToVALU.
8686
8687 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
8688 if (const TargetRegisterClass *OpRC =
8689 getRegClass(UseMI.getDesc(), OpIdx))
8690 MRI.constrainRegClass(NewDstReg, OpRC);
8691 }
8692
8693 return;
8694 }
8695 }
8696
8697 // If this is a v2s copy between 16bit and 32bit reg,
8698 // replace vgpr copy to reg_sequence/extract_subreg
8699 // This can be remove after we have sgpr16 in place
8700 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
8701 Inst.getOperand(1).getReg().isVirtual() &&
8702 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
8703 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
8704 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8705 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8706 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8707 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8708 get(AMDGPU::IMPLICIT_DEF), Undef);
8709 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8710 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8711 .addReg(Inst.getOperand(1).getReg())
8712 .addImm(AMDGPU::lo16)
8713 .addReg(Undef)
8714 .addImm(AMDGPU::hi16);
8715 Inst.eraseFromParent();
8716 MRI.replaceRegWith(DstReg, NewDstReg);
8717 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8718 return;
8719 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8720 AMDGPU::lo16)) {
8721 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
8722 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8723 MRI.replaceRegWith(DstReg, NewDstReg);
8724 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8725 return;
8726 }
8727 }
8728
8729 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8730 MRI.replaceRegWith(DstReg, NewDstReg);
8731 legalizeOperands(Inst, MDT);
8732 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8733 return;
8734 }
8735
8736 // Use the new VALU Opcode.
8737 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
8738 .setMIFlags(Inst.getFlags());
8739 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
8740 // Intersperse VOP3 modifiers among the SALU operands.
8741 NewInstr->addOperand(Inst.getOperand(0));
8742 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8743 AMDGPU::OpName::src0_modifiers) >= 0)
8744 NewInstr.addImm(0);
8745 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
8746 const MachineOperand &Src = Inst.getOperand(1);
8747 NewInstr->addOperand(Src);
8748 }
8749
8750 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8751 // We are converting these to a BFE, so we need to add the missing
8752 // operands for the size and offset.
8753 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8754 NewInstr.addImm(0);
8755 NewInstr.addImm(Size);
8756 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8757 // The VALU version adds the second operand to the result, so insert an
8758 // extra 0 operand.
8759 NewInstr.addImm(0);
8760 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8761 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
8762 // If we need to move this to VGPRs, we need to unpack the second
8763 // operand back into the 2 separate ones for bit offset and width.
8764 assert(OffsetWidthOp.isImm() &&
8765 "Scalar BFE is only implemented for constant width and offset");
8766 uint32_t Imm = OffsetWidthOp.getImm();
8767
8768 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
8769 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
8770 NewInstr.addImm(Offset);
8771 NewInstr.addImm(BitWidth);
8772 } else {
8773 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8774 AMDGPU::OpName::src1_modifiers) >= 0)
8775 NewInstr.addImm(0);
8776 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8777 NewInstr->addOperand(Inst.getOperand(2));
8778 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8779 AMDGPU::OpName::src2_modifiers) >= 0)
8780 NewInstr.addImm(0);
8781 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8782 NewInstr->addOperand(Inst.getOperand(3));
8783 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8784 NewInstr.addImm(0);
8785 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8786 NewInstr.addImm(0);
8787 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8788 NewInstr.addImm(0);
8789 }
8790 } else {
8791 // Just copy the SALU operands.
8792 for (const MachineOperand &Op : Inst.explicit_operands())
8793 NewInstr->addOperand(Op);
8794 }
8795
8796 // Remove any references to SCC. Vector instructions can't read from it, and
8797 // We're just about to add the implicit use / defs of VCC, and we don't want
8798 // both.
8799 for (MachineOperand &Op : Inst.implicit_operands()) {
8800 if (Op.getReg() == AMDGPU::SCC) {
8801 // Only propagate through live-def of SCC.
8802 if (Op.isDef() && !Op.isDead())
8803 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
8804 if (Op.isUse())
8805 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8806 }
8807 }
8808 Inst.eraseFromParent();
8809 Register NewDstReg;
8810 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8811 Register DstReg = NewInstr->getOperand(0).getReg();
8812 assert(DstReg.isVirtual());
8813 // Update the destination register class.
8814 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
8815 assert(NewDstRC);
8816 NewDstReg = MRI.createVirtualRegister(NewDstRC);
8817 MRI.replaceRegWith(DstReg, NewDstReg);
8818 }
8819 fixImplicitOperands(*NewInstr);
8820
8821 // Legalize the operands
8822 legalizeOperands(*NewInstr, MDT);
8823 if (NewDstReg)
8824 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8825}
8826
8827// Add/sub require special handling to deal with carry outs.
8828std::pair<bool, MachineBasicBlock *>
8829SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
8830 MachineDominatorTree *MDT) const {
8831 if (ST.hasAddNoCarryInsts()) {
8832 // Assume there is no user of scc since we don't select this in that case.
8833 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
8834 // is used.
8835
8836 MachineBasicBlock &MBB = *Inst.getParent();
8837 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8838
8839 Register OldDstReg = Inst.getOperand(0).getReg();
8840 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8841
8842 unsigned Opc = Inst.getOpcode();
8843 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
8844
8845 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
8846 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8847
8848 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
8849 Inst.removeOperand(3);
8850
8851 Inst.setDesc(get(NewOpc));
8852 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
8853 Inst.addImplicitDefUseOperands(*MBB.getParent());
8854 MRI.replaceRegWith(OldDstReg, ResultReg);
8855 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
8856
8857 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8858 return std::pair(true, NewBB);
8859 }
8860
8861 return std::pair(false, nullptr);
8862}
8863
8864void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
8865 MachineDominatorTree *MDT) const {
8866
8867 MachineBasicBlock &MBB = *Inst.getParent();
8868 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8869 MachineBasicBlock::iterator MII = Inst;
8870 const DebugLoc &DL = Inst.getDebugLoc();
8871
8872 MachineOperand &Dest = Inst.getOperand(0);
8873 MachineOperand &Src0 = Inst.getOperand(1);
8874 MachineOperand &Src1 = Inst.getOperand(2);
8875 MachineOperand &Cond = Inst.getOperand(3);
8876
8877 Register CondReg = Cond.getReg();
8878 bool IsSCC = (CondReg == AMDGPU::SCC);
8879
8880 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
8881 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
8882 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
8883 // output directly into the V_CNDMASK.
8884 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
8885 (Src1.getImm() == 0)) {
8886 for (MachineOperand &UseMO :
8888 MachineInstr &UseMI = *UseMO.getParent();
8889 switch (UseMI.getOpcode()) {
8890 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8891 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8892 case AMDGPU::V_CNDMASK_B16_t16_e32:
8893 case AMDGPU::V_CNDMASK_B16_t16_e64:
8894 case AMDGPU::V_CNDMASK_B32_e32:
8895 case AMDGPU::V_CNDMASK_B32_e64:
8896 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8897 if (UseMO.isImplicit() ||
8898 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
8899 UseMO.setReg(CondReg);
8900 }
8901 }
8902 if (MRI.use_nodbg_empty(Dest.getReg()))
8903 return;
8904 }
8905
8906 Register NewCondReg = CondReg;
8907 if (IsSCC) {
8908 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
8909 NewCondReg = MRI.createVirtualRegister(TC);
8910
8911 // Now look for the closest SCC def if it is a copy
8912 // replacing the CondReg with the COPY source register
8913 bool CopyFound = false;
8914 for (MachineInstr &CandI :
8916 Inst.getParent()->rend())) {
8917 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
8918 -1) {
8919 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
8920 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
8921 .addReg(CandI.getOperand(1).getReg());
8922 CopyFound = true;
8923 }
8924 break;
8925 }
8926 }
8927 if (!CopyFound) {
8928 // SCC def is not a copy
8929 // Insert a trivial select instead of creating a copy, because a copy from
8930 // SCC would semantically mean just copying a single bit, but we may need
8931 // the result to be a vector condition mask that needs preserving.
8932 unsigned Opcode =
8933 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
8934 auto NewSelect =
8935 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
8936 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
8937 }
8938 }
8939
8940 Register NewDestReg = MRI.createVirtualRegister(
8941 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
8942 MachineInstr *NewInst;
8943 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
8944 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
8945 .addImm(0)
8946 .add(Src1) // False
8947 .addImm(0)
8948 .add(Src0) // True
8949 .addReg(NewCondReg);
8950 } else {
8951 NewInst =
8952 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
8953 .add(Src1) // False
8954 .add(Src0) // True
8955 .addReg(NewCondReg);
8956 }
8957 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
8958 legalizeOperands(*NewInst, MDT);
8959 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
8960}
8961
8962void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
8963 MachineInstr &Inst) const {
8964 MachineBasicBlock &MBB = *Inst.getParent();
8965 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8966 MachineBasicBlock::iterator MII = Inst;
8967 const DebugLoc &DL = Inst.getDebugLoc();
8968
8969 MachineOperand &Dest = Inst.getOperand(0);
8970 MachineOperand &Src = Inst.getOperand(1);
8971 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8972 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8973
8974 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8975 : AMDGPU::V_SUB_CO_U32_e32;
8976
8977 BuildMI(MBB, MII, DL, get(SubOp), TmpReg)
8978 .addImm(0)
8979 .addReg(Src.getReg());
8980
8981 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
8982 .addReg(Src.getReg())
8983 .addReg(TmpReg);
8984
8985 MRI.replaceRegWith(Dest.getReg(), ResultReg);
8986 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8987}
8988
8989void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
8990 MachineInstr &Inst) const {
8991 MachineBasicBlock &MBB = *Inst.getParent();
8992 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8993 MachineBasicBlock::iterator MII = Inst;
8994 const DebugLoc &DL = Inst.getDebugLoc();
8995
8996 MachineOperand &Dest = Inst.getOperand(0);
8997 MachineOperand &Src1 = Inst.getOperand(1);
8998 MachineOperand &Src2 = Inst.getOperand(2);
8999 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9000 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9001 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9002
9003 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9004 : AMDGPU::V_SUB_CO_U32_e32;
9005
9006 BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
9007 .addReg(Src1.getReg())
9008 .addReg(Src2.getReg());
9009
9010 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
9011
9012 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9013 .addReg(SubResultReg)
9014 .addReg(TmpReg);
9015
9016 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9017 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9018}
9019
9020void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
9021 MachineInstr &Inst) const {
9022 MachineBasicBlock &MBB = *Inst.getParent();
9023 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9024 MachineBasicBlock::iterator MII = Inst;
9025 const DebugLoc &DL = Inst.getDebugLoc();
9026
9027 MachineOperand &Dest = Inst.getOperand(0);
9028 MachineOperand &Src0 = Inst.getOperand(1);
9029 MachineOperand &Src1 = Inst.getOperand(2);
9030
9031 if (ST.hasDLInsts()) {
9032 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9033 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
9034 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
9035
9036 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
9037 .add(Src0)
9038 .add(Src1);
9039
9040 MRI.replaceRegWith(Dest.getReg(), NewDest);
9041 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9042 } else {
9043 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
9044 // invert either source and then perform the XOR. If either source is a
9045 // scalar register, then we can leave the inversion on the scalar unit to
9046 // achieve a better distribution of scalar and vector instructions.
9047 bool Src0IsSGPR = Src0.isReg() &&
9048 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
9049 bool Src1IsSGPR = Src1.isReg() &&
9050 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
9051 MachineInstr *Xor;
9052 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9053 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9054
9055 // Build a pair of scalar instructions and add them to the work list.
9056 // The next iteration over the work list will lower these to the vector
9057 // unit as necessary.
9058 if (Src0IsSGPR) {
9059 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
9060 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9061 .addReg(Temp)
9062 .add(Src1);
9063 } else if (Src1IsSGPR) {
9064 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
9065 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9066 .add(Src0)
9067 .addReg(Temp);
9068 } else {
9069 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
9070 .add(Src0)
9071 .add(Src1);
9072 MachineInstr *Not =
9073 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
9074 Worklist.insert(Not);
9075 }
9076
9077 MRI.replaceRegWith(Dest.getReg(), NewDest);
9078
9079 Worklist.insert(Xor);
9080
9081 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9082 }
9083}
9084
9085void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
9086 MachineInstr &Inst,
9087 unsigned Opcode) const {
9088 MachineBasicBlock &MBB = *Inst.getParent();
9089 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9090 MachineBasicBlock::iterator MII = Inst;
9091 const DebugLoc &DL = Inst.getDebugLoc();
9092
9093 MachineOperand &Dest = Inst.getOperand(0);
9094 MachineOperand &Src0 = Inst.getOperand(1);
9095 MachineOperand &Src1 = Inst.getOperand(2);
9096
9097 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9098 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9099
9100 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
9101 .add(Src0)
9102 .add(Src1);
9103
9104 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
9105 .addReg(Interm);
9106
9107 Worklist.insert(&Op);
9108 Worklist.insert(&Not);
9109
9110 MRI.replaceRegWith(Dest.getReg(), NewDest);
9111 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9112}
9113
9114void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
9115 MachineInstr &Inst,
9116 unsigned Opcode) const {
9117 MachineBasicBlock &MBB = *Inst.getParent();
9118 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9119 MachineBasicBlock::iterator MII = Inst;
9120 const DebugLoc &DL = Inst.getDebugLoc();
9121
9122 MachineOperand &Dest = Inst.getOperand(0);
9123 MachineOperand &Src0 = Inst.getOperand(1);
9124 MachineOperand &Src1 = Inst.getOperand(2);
9125
9126 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9127 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9128
9129 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
9130 .add(Src1);
9131
9132 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
9133 .add(Src0)
9134 .addReg(Interm);
9135
9136 Worklist.insert(&Not);
9137 Worklist.insert(&Op);
9138
9139 MRI.replaceRegWith(Dest.getReg(), NewDest);
9140 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9141}
9142
9143void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
9144 MachineInstr &Inst, unsigned Opcode,
9145 bool Swap) const {
9146 MachineBasicBlock &MBB = *Inst.getParent();
9147 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9148
9149 MachineOperand &Dest = Inst.getOperand(0);
9150 MachineOperand &Src0 = Inst.getOperand(1);
9151 const DebugLoc &DL = Inst.getDebugLoc();
9152
9153 MachineBasicBlock::iterator MII = Inst;
9154
9155 const MCInstrDesc &InstDesc = get(Opcode);
9156 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9157 MRI.getRegClass(Src0.getReg()) :
9158 &AMDGPU::SGPR_32RegClass;
9159
9160 const TargetRegisterClass *Src0SubRC =
9161 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9162
9163 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9164 AMDGPU::sub0, Src0SubRC);
9165
9166 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9167 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9168 const TargetRegisterClass *NewDestSubRC =
9169 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9170
9171 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9172 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
9173
9174 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9175 AMDGPU::sub1, Src0SubRC);
9176
9177 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9178 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
9179
9180 if (Swap)
9181 std::swap(DestSub0, DestSub1);
9182
9183 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9184 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9185 .addReg(DestSub0)
9186 .addImm(AMDGPU::sub0)
9187 .addReg(DestSub1)
9188 .addImm(AMDGPU::sub1);
9189
9190 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9191
9192 Worklist.insert(&LoHalf);
9193 Worklist.insert(&HiHalf);
9194
9195 // We don't need to legalizeOperands here because for a single operand, src0
9196 // will support any kind of input.
9197
9198 // Move all users of this moved value.
9199 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9200}
9201
9202// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9203// split the s_mul_u64 in 32-bit vector multiplications.
9204void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9205 MachineInstr &Inst,
9206 MachineDominatorTree *MDT) const {
9207 MachineBasicBlock &MBB = *Inst.getParent();
9208 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9209
9210 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9211 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9212 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9213
9214 MachineOperand &Dest = Inst.getOperand(0);
9215 MachineOperand &Src0 = Inst.getOperand(1);
9216 MachineOperand &Src1 = Inst.getOperand(2);
9217 const DebugLoc &DL = Inst.getDebugLoc();
9218 MachineBasicBlock::iterator MII = Inst;
9219
9220 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9221 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9222 const TargetRegisterClass *Src0SubRC =
9223 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9224 if (RI.isSGPRClass(Src0SubRC))
9225 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9226 const TargetRegisterClass *Src1SubRC =
9227 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9228 if (RI.isSGPRClass(Src1SubRC))
9229 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9230
9231 // First, we extract the low 32-bit and high 32-bit values from each of the
9232 // operands.
9233 MachineOperand Op0L =
9234 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9235 MachineOperand Op1L =
9236 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9237 MachineOperand Op0H =
9238 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9239 MachineOperand Op1H =
9240 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9241
9242 // The multilication is done as follows:
9243 //
9244 // Op1H Op1L
9245 // * Op0H Op0L
9246 // --------------------
9247 // Op1H*Op0L Op1L*Op0L
9248 // + Op1H*Op0H Op1L*Op0H
9249 // -----------------------------------------
9250 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9251 //
9252 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9253 // value and that would overflow.
9254 // The low 32-bit value is Op1L*Op0L.
9255 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9256
9257 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9258 MachineInstr *Op1L_Op0H =
9259 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9260 .add(Op1L)
9261 .add(Op0H);
9262
9263 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9264 MachineInstr *Op1H_Op0L =
9265 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9266 .add(Op1H)
9267 .add(Op0L);
9268
9269 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9270 MachineInstr *Carry =
9271 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9272 .add(Op1L)
9273 .add(Op0L);
9274
9275 MachineInstr *LoHalf =
9276 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9277 .add(Op1L)
9278 .add(Op0L);
9279
9280 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9281 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9282 .addReg(Op1L_Op0H_Reg)
9283 .addReg(Op1H_Op0L_Reg);
9284
9285 MachineInstr *HiHalf =
9286 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9287 .addReg(AddReg)
9288 .addReg(CarryReg);
9289
9290 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9291 .addReg(DestSub0)
9292 .addImm(AMDGPU::sub0)
9293 .addReg(DestSub1)
9294 .addImm(AMDGPU::sub1);
9295
9296 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9297
9298 // Try to legalize the operands in case we need to swap the order to keep it
9299 // valid.
9300 legalizeOperands(*Op1L_Op0H, MDT);
9301 legalizeOperands(*Op1H_Op0L, MDT);
9302 legalizeOperands(*Carry, MDT);
9303 legalizeOperands(*LoHalf, MDT);
9304 legalizeOperands(*Add, MDT);
9305 legalizeOperands(*HiHalf, MDT);
9306
9307 // Move all users of this moved value.
9308 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9309}
9310
9311// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9312// multiplications.
9313void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9314 MachineInstr &Inst,
9315 MachineDominatorTree *MDT) const {
9316 MachineBasicBlock &MBB = *Inst.getParent();
9317 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9318
9319 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9320 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9321 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9322
9323 MachineOperand &Dest = Inst.getOperand(0);
9324 MachineOperand &Src0 = Inst.getOperand(1);
9325 MachineOperand &Src1 = Inst.getOperand(2);
9326 const DebugLoc &DL = Inst.getDebugLoc();
9327 MachineBasicBlock::iterator MII = Inst;
9328
9329 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9330 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9331 const TargetRegisterClass *Src0SubRC =
9332 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9333 if (RI.isSGPRClass(Src0SubRC))
9334 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9335 const TargetRegisterClass *Src1SubRC =
9336 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9337 if (RI.isSGPRClass(Src1SubRC))
9338 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9339
9340 // First, we extract the low 32-bit and high 32-bit values from each of the
9341 // operands.
9342 MachineOperand Op0L =
9343 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9344 MachineOperand Op1L =
9345 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9346
9347 unsigned Opc = Inst.getOpcode();
9348 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9349 ? AMDGPU::V_MUL_HI_U32_e64
9350 : AMDGPU::V_MUL_HI_I32_e64;
9351 MachineInstr *HiHalf =
9352 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9353
9354 MachineInstr *LoHalf =
9355 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9356 .add(Op1L)
9357 .add(Op0L);
9358
9359 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9360 .addReg(DestSub0)
9361 .addImm(AMDGPU::sub0)
9362 .addReg(DestSub1)
9363 .addImm(AMDGPU::sub1);
9364
9365 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9366
9367 // Try to legalize the operands in case we need to swap the order to keep it
9368 // valid.
9369 legalizeOperands(*HiHalf, MDT);
9370 legalizeOperands(*LoHalf, MDT);
9371
9372 // Move all users of this moved value.
9373 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9374}
9375
9376void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9377 MachineInstr &Inst, unsigned Opcode,
9378 MachineDominatorTree *MDT) const {
9379 MachineBasicBlock &MBB = *Inst.getParent();
9380 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9381
9382 MachineOperand &Dest = Inst.getOperand(0);
9383 MachineOperand &Src0 = Inst.getOperand(1);
9384 MachineOperand &Src1 = Inst.getOperand(2);
9385 const DebugLoc &DL = Inst.getDebugLoc();
9386
9387 MachineBasicBlock::iterator MII = Inst;
9388
9389 const MCInstrDesc &InstDesc = get(Opcode);
9390 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9391 MRI.getRegClass(Src0.getReg()) :
9392 &AMDGPU::SGPR_32RegClass;
9393
9394 const TargetRegisterClass *Src0SubRC =
9395 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9396 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9397 MRI.getRegClass(Src1.getReg()) :
9398 &AMDGPU::SGPR_32RegClass;
9399
9400 const TargetRegisterClass *Src1SubRC =
9401 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9402
9403 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9404 AMDGPU::sub0, Src0SubRC);
9405 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9406 AMDGPU::sub0, Src1SubRC);
9407 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9408 AMDGPU::sub1, Src0SubRC);
9409 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9410 AMDGPU::sub1, Src1SubRC);
9411
9412 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9413 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9414 const TargetRegisterClass *NewDestSubRC =
9415 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9416
9417 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9418 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9419 .add(SrcReg0Sub0)
9420 .add(SrcReg1Sub0);
9421
9422 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9423 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9424 .add(SrcReg0Sub1)
9425 .add(SrcReg1Sub1);
9426
9427 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9428 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9429 .addReg(DestSub0)
9430 .addImm(AMDGPU::sub0)
9431 .addReg(DestSub1)
9432 .addImm(AMDGPU::sub1);
9433
9434 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9435
9436 Worklist.insert(&LoHalf);
9437 Worklist.insert(&HiHalf);
9438
9439 // Move all users of this moved value.
9440 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9441}
9442
9443void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9444 MachineInstr &Inst,
9445 MachineDominatorTree *MDT) const {
9446 MachineBasicBlock &MBB = *Inst.getParent();
9447 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9448
9449 MachineOperand &Dest = Inst.getOperand(0);
9450 MachineOperand &Src0 = Inst.getOperand(1);
9451 MachineOperand &Src1 = Inst.getOperand(2);
9452 const DebugLoc &DL = Inst.getDebugLoc();
9453
9454 MachineBasicBlock::iterator MII = Inst;
9455
9456 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9457
9458 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9459
9460 MachineOperand* Op0;
9461 MachineOperand* Op1;
9462
9463 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9464 Op0 = &Src0;
9465 Op1 = &Src1;
9466 } else {
9467 Op0 = &Src1;
9468 Op1 = &Src0;
9469 }
9470
9471 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9472 .add(*Op0);
9473
9474 Register NewDest = MRI.createVirtualRegister(DestRC);
9475
9476 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9477 .addReg(Interm)
9478 .add(*Op1);
9479
9480 MRI.replaceRegWith(Dest.getReg(), NewDest);
9481
9482 Worklist.insert(&Xor);
9483}
9484
9485void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9486 MachineInstr &Inst) const {
9487 MachineBasicBlock &MBB = *Inst.getParent();
9488 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9489
9490 MachineBasicBlock::iterator MII = Inst;
9491 const DebugLoc &DL = Inst.getDebugLoc();
9492
9493 MachineOperand &Dest = Inst.getOperand(0);
9494 MachineOperand &Src = Inst.getOperand(1);
9495
9496 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9497 const TargetRegisterClass *SrcRC = Src.isReg() ?
9498 MRI.getRegClass(Src.getReg()) :
9499 &AMDGPU::SGPR_32RegClass;
9500
9501 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9502 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9503
9504 const TargetRegisterClass *SrcSubRC =
9505 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9506
9507 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9508 AMDGPU::sub0, SrcSubRC);
9509 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9510 AMDGPU::sub1, SrcSubRC);
9511
9512 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9513
9514 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9515
9516 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9517
9518 // We don't need to legalize operands here. src0 for either instruction can be
9519 // an SGPR, and the second input is unused or determined here.
9520 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9521}
9522
9523void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9524 MachineInstr &Inst) const {
9525 MachineBasicBlock &MBB = *Inst.getParent();
9526 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9527 MachineBasicBlock::iterator MII = Inst;
9528 const DebugLoc &DL = Inst.getDebugLoc();
9529
9530 MachineOperand &Dest = Inst.getOperand(0);
9531 uint32_t Imm = Inst.getOperand(2).getImm();
9532 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9533 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9534
9535 (void) Offset;
9536
9537 // Only sext_inreg cases handled.
9538 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9539 Offset == 0 && "Not implemented");
9540
9541 if (BitWidth < 32) {
9542 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9543 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9544 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9545
9546 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9547 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9548 .addImm(0)
9549 .addImm(BitWidth);
9550
9551 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9552 .addImm(31)
9553 .addReg(MidRegLo);
9554
9555 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9556 .addReg(MidRegLo)
9557 .addImm(AMDGPU::sub0)
9558 .addReg(MidRegHi)
9559 .addImm(AMDGPU::sub1);
9560
9561 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9562 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9563 return;
9564 }
9565
9566 MachineOperand &Src = Inst.getOperand(1);
9567 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9568 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9569
9570 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9571 .addImm(31)
9572 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9573
9574 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9575 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9576 .addImm(AMDGPU::sub0)
9577 .addReg(TmpReg)
9578 .addImm(AMDGPU::sub1);
9579
9580 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9581 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9582}
9583
9584void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9585 MachineInstr &Inst, unsigned Opcode,
9586 MachineDominatorTree *MDT) const {
9587 // (S_FLBIT_I32_B64 hi:lo) ->
9588 // -> (umin (V_FFBH_U32_e32 hi), (uaddsat (V_FFBH_U32_e32 lo), 32))
9589 // (S_FF1_I32_B64 hi:lo) ->
9590 // ->(umin (uaddsat (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9591
9592 MachineBasicBlock &MBB = *Inst.getParent();
9593 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9594 MachineBasicBlock::iterator MII = Inst;
9595 const DebugLoc &DL = Inst.getDebugLoc();
9596
9597 MachineOperand &Dest = Inst.getOperand(0);
9598 MachineOperand &Src = Inst.getOperand(1);
9599
9600 const MCInstrDesc &InstDesc = get(Opcode);
9601
9602 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9603 unsigned OpcodeAdd = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64
9604 : AMDGPU::V_ADD_CO_U32_e32;
9605
9606 const TargetRegisterClass *SrcRC =
9607 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9608 const TargetRegisterClass *SrcSubRC =
9609 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9610
9611 MachineOperand SrcRegSub0 =
9612 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9613 MachineOperand SrcRegSub1 =
9614 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9615
9616 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9617 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9618 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9619 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9620
9621 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9622
9623 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9624
9625 BuildMI(MBB, MII, DL, get(OpcodeAdd), MidReg3)
9626 .addReg(IsCtlz ? MidReg1 : MidReg2)
9627 .addImm(32)
9628 .addImm(1); // enable clamp
9629
9630 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9631 .addReg(MidReg3)
9632 .addReg(IsCtlz ? MidReg2 : MidReg1);
9633
9634 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9635
9636 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9637}
9638
9639void SIInstrInfo::addUsersToMoveToVALUWorklist(
9640 Register DstReg, MachineRegisterInfo &MRI,
9641 SIInstrWorklist &Worklist) const {
9642 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9643 MachineInstr &UseMI = *MO.getParent();
9644
9645 unsigned OpNo = 0;
9646
9647 switch (UseMI.getOpcode()) {
9648 case AMDGPU::COPY:
9649 case AMDGPU::WQM:
9650 case AMDGPU::SOFT_WQM:
9651 case AMDGPU::STRICT_WWM:
9652 case AMDGPU::STRICT_WQM:
9653 case AMDGPU::REG_SEQUENCE:
9654 case AMDGPU::PHI:
9655 case AMDGPU::INSERT_SUBREG:
9656 break;
9657 default:
9658 OpNo = MO.getOperandNo();
9659 break;
9660 }
9661
9662 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9663 MRI.constrainRegClass(DstReg, OpRC);
9664
9665 if (!RI.hasVectorRegisters(OpRC))
9666 Worklist.insert(&UseMI);
9667 else
9668 // Legalization could change user list.
9669 legalizeOperandsVALUt16(UseMI, OpNo, MRI);
9670 }
9671}
9672
9673void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
9675 MachineInstr &Inst) const {
9676 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9677 MachineBasicBlock *MBB = Inst.getParent();
9678 MachineOperand &Src0 = Inst.getOperand(1);
9679 MachineOperand &Src1 = Inst.getOperand(2);
9680 const DebugLoc &DL = Inst.getDebugLoc();
9681
9682 if (ST.useRealTrue16Insts()) {
9683 Register SrcReg0, SrcReg1;
9684 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
9685 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9686 BuildMI(*MBB, Inst, DL,
9687 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9688 .add(Src0);
9689 } else {
9690 SrcReg0 = Src0.getReg();
9691 }
9692
9693 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
9694 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9695 BuildMI(*MBB, Inst, DL,
9696 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9697 .add(Src1);
9698 } else {
9699 SrcReg1 = Src1.getReg();
9700 }
9701
9702 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
9703 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
9704
9705 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
9706 switch (Inst.getOpcode()) {
9707 case AMDGPU::S_PACK_LL_B32_B16:
9708 NewMI
9709 .addReg(SrcReg0, {},
9710 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9711 .addImm(AMDGPU::lo16)
9712 .addReg(SrcReg1, {},
9713 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9714 .addImm(AMDGPU::hi16);
9715 break;
9716 case AMDGPU::S_PACK_LH_B32_B16:
9717 NewMI
9718 .addReg(SrcReg0, {},
9719 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9720 .addImm(AMDGPU::lo16)
9721 .addReg(SrcReg1, {}, AMDGPU::hi16)
9722 .addImm(AMDGPU::hi16);
9723 break;
9724 case AMDGPU::S_PACK_HL_B32_B16:
9725 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9726 .addImm(AMDGPU::lo16)
9727 .addReg(SrcReg1, {},
9728 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9729 .addImm(AMDGPU::hi16);
9730 break;
9731 case AMDGPU::S_PACK_HH_B32_B16:
9732 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9733 .addImm(AMDGPU::lo16)
9734 .addReg(SrcReg1, {}, AMDGPU::hi16)
9735 .addImm(AMDGPU::hi16);
9736 break;
9737 default:
9738 llvm_unreachable("unhandled s_pack_* instruction");
9739 }
9740
9741 MachineOperand &Dest = Inst.getOperand(0);
9742 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9743 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9744 return;
9745 }
9746
9747 switch (Inst.getOpcode()) {
9748 case AMDGPU::S_PACK_LL_B32_B16: {
9749 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9750 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9751
9752 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
9753 // 0.
9754 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9755 .addImm(0xffff);
9756
9757 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
9758 .addReg(ImmReg, RegState::Kill)
9759 .add(Src0);
9760
9761 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9762 .add(Src1)
9763 .addImm(16)
9764 .addReg(TmpReg, RegState::Kill);
9765 break;
9766 }
9767 case AMDGPU::S_PACK_LH_B32_B16: {
9768 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9769 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9770 .addImm(0xffff);
9771 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
9772 .addReg(ImmReg, RegState::Kill)
9773 .add(Src0)
9774 .add(Src1);
9775 break;
9776 }
9777 case AMDGPU::S_PACK_HL_B32_B16: {
9778 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9779 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9780 .addImm(16)
9781 .add(Src0);
9782 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9783 .add(Src1)
9784 .addImm(16)
9785 .addReg(TmpReg, RegState::Kill);
9786 break;
9787 }
9788 case AMDGPU::S_PACK_HH_B32_B16: {
9789 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9790 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9791 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9792 .addImm(16)
9793 .add(Src0);
9794 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9795 .addImm(0xffff0000);
9796 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
9797 .add(Src1)
9798 .addReg(ImmReg, RegState::Kill)
9799 .addReg(TmpReg, RegState::Kill);
9800 break;
9801 }
9802 default:
9803 llvm_unreachable("unhandled s_pack_* instruction");
9804 }
9805
9806 MachineOperand &Dest = Inst.getOperand(0);
9807 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9808 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9809}
9810
9811void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
9812 MachineInstr &SCCDefInst,
9813 SIInstrWorklist &Worklist,
9814 Register NewCond) const {
9815
9816 // Ensure that def inst defines SCC, which is still live.
9817 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
9818 !Op.isDead() && Op.getParent() == &SCCDefInst);
9819 SmallVector<MachineInstr *, 4> CopyToDelete;
9820 // This assumes that all the users of SCC are in the same block
9821 // as the SCC def.
9822 for (MachineInstr &MI : // Skip the def inst itself.
9823 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
9824 SCCDefInst.getParent()->end())) {
9825 // Check if SCC is used first.
9826 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
9827 if (SCCIdx != -1) {
9828 if (MI.isCopy()) {
9829 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
9830 Register DestReg = MI.getOperand(0).getReg();
9831
9832 MRI.replaceRegWith(DestReg, NewCond);
9833 CopyToDelete.push_back(&MI);
9834 } else {
9835
9836 if (NewCond.isValid())
9837 MI.getOperand(SCCIdx).setReg(NewCond);
9838
9839 Worklist.insert(&MI);
9840 }
9841 }
9842 // Exit if we find another SCC def.
9843 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
9844 break;
9845 }
9846 for (auto &Copy : CopyToDelete)
9847 Copy->eraseFromParent();
9848}
9849
9850// Instructions that use SCC may be converted to VALU instructions. When that
9851// happens, the SCC register is changed to VCC_LO. The instruction that defines
9852// SCC must be changed to an instruction that defines VCC. This function makes
9853// sure that the instruction that defines SCC is added to the moveToVALU
9854// worklist.
9855void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
9856 SIInstrWorklist &Worklist) const {
9857 // Look for a preceding instruction that either defines VCC or SCC. If VCC
9858 // then there is nothing to do because the defining instruction has been
9859 // converted to a VALU already. If SCC then that instruction needs to be
9860 // converted to a VALU.
9861 for (MachineInstr &MI :
9862 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
9863 SCCUseInst->getParent()->rend())) {
9864 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
9865 break;
9866 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
9867 Worklist.insert(&MI);
9868 break;
9869 }
9870 }
9871}
9872
9873const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
9874 const MachineInstr &Inst) const {
9875 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
9876
9877 switch (Inst.getOpcode()) {
9878 // For target instructions, getOpRegClass just returns the virtual register
9879 // class associated with the operand, so we need to find an equivalent VGPR
9880 // register class in order to move the instruction to the VALU.
9881 case AMDGPU::COPY:
9882 case AMDGPU::PHI:
9883 case AMDGPU::REG_SEQUENCE:
9884 case AMDGPU::INSERT_SUBREG:
9885 case AMDGPU::WQM:
9886 case AMDGPU::SOFT_WQM:
9887 case AMDGPU::STRICT_WWM:
9888 case AMDGPU::STRICT_WQM: {
9889 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
9890 if (RI.isAGPRClass(SrcRC)) {
9891 if (RI.isAGPRClass(NewDstRC))
9892 return nullptr;
9893
9894 switch (Inst.getOpcode()) {
9895 case AMDGPU::PHI:
9896 case AMDGPU::REG_SEQUENCE:
9897 case AMDGPU::INSERT_SUBREG:
9898 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9899 break;
9900 default:
9901 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9902 }
9903
9904 if (!NewDstRC)
9905 return nullptr;
9906 } else {
9907 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9908 return nullptr;
9909
9910 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9911 if (!NewDstRC)
9912 return nullptr;
9913 }
9914
9915 return NewDstRC;
9916 }
9917 default:
9918 return NewDstRC;
9919 }
9920}
9921
9922// Find the one SGPR operand we are allowed to use.
9923Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
9924 int OpIndices[3]) const {
9925 const MCInstrDesc &Desc = MI.getDesc();
9926
9927 // Find the one SGPR operand we are allowed to use.
9928 //
9929 // First we need to consider the instruction's operand requirements before
9930 // legalizing. Some operands are required to be SGPRs, such as implicit uses
9931 // of VCC, but we are still bound by the constant bus requirement to only use
9932 // one.
9933 //
9934 // If the operand's class is an SGPR, we can never move it.
9935
9936 Register SGPRReg = findImplicitSGPRRead(MI);
9937 if (SGPRReg)
9938 return SGPRReg;
9939
9940 Register UsedSGPRs[3] = {Register()};
9941 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
9942
9943 for (unsigned i = 0; i < 3; ++i) {
9944 int Idx = OpIndices[i];
9945 if (Idx == -1)
9946 break;
9947
9948 const MachineOperand &MO = MI.getOperand(Idx);
9949 if (!MO.isReg())
9950 continue;
9951
9952 // Is this operand statically required to be an SGPR based on the operand
9953 // constraints?
9954 const TargetRegisterClass *OpRC =
9955 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
9956 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
9957 if (IsRequiredSGPR)
9958 return MO.getReg();
9959
9960 // If this could be a VGPR or an SGPR, Check the dynamic register class.
9961 Register Reg = MO.getReg();
9962 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
9963 if (RI.isSGPRClass(RegRC))
9964 UsedSGPRs[i] = Reg;
9965 }
9966
9967 // We don't have a required SGPR operand, so we have a bit more freedom in
9968 // selecting operands to move.
9969
9970 // Try to select the most used SGPR. If an SGPR is equal to one of the
9971 // others, we choose that.
9972 //
9973 // e.g.
9974 // V_FMA_F32 v0, s0, s0, s0 -> No moves
9975 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
9976
9977 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
9978 // prefer those.
9979
9980 if (UsedSGPRs[0]) {
9981 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
9982 SGPRReg = UsedSGPRs[0];
9983 }
9984
9985 if (!SGPRReg && UsedSGPRs[1]) {
9986 if (UsedSGPRs[1] == UsedSGPRs[2])
9987 SGPRReg = UsedSGPRs[1];
9988 }
9989
9990 return SGPRReg;
9991}
9992
9994 AMDGPU::OpName OperandName) const {
9995 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
9996 return nullptr;
9997
9998 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
9999 if (Idx == -1)
10000 return nullptr;
10001
10002 return &MI.getOperand(Idx);
10003}
10004
10006 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
10007 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
10010 return (Format << 44) |
10011 (1ULL << 56) | // RESOURCE_LEVEL = 1
10012 (3ULL << 60); // OOB_SELECT = 3
10013 }
10014
10015 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
10016 if (ST.isAmdHsaOS()) {
10017 // Set ATC = 1. GFX9 doesn't have this bit.
10018 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10019 RsrcDataFormat |= (1ULL << 56);
10020
10021 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
10022 // BTW, it disables TC L2 and therefore decreases performance.
10023 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
10024 RsrcDataFormat |= (2ULL << 59);
10025 }
10026
10027 return RsrcDataFormat;
10028}
10029
10031 uint64_t Rsrc23 = getDefaultRsrcDataFormat() |
10033 0xffffffff; // Size;
10034
10035 // GFX9 doesn't have ELEMENT_SIZE.
10036 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
10037 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
10038 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
10039 }
10040
10041 // IndexStride = 64 / 32.
10042 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10043 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
10044
10045 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
10046 // Clear them unless we want a huge stride.
10047 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
10048 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
10049 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
10050
10051 return Rsrc23;
10052}
10053
10055 unsigned Opc = MI.getOpcode();
10056
10057 return isSMRD(Opc);
10058}
10059
10061 return get(Opc).mayLoad() &&
10062 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
10063}
10064
10066 TypeSize &MemBytes) const {
10067 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
10068 if (!Addr || !Addr->isFI())
10069 return Register();
10070
10071 assert(!MI.memoperands_empty() &&
10072 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
10073
10074 FrameIndex = Addr->getIndex();
10075
10076 int VDataIdx =
10077 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
10078 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
10079 return MI.getOperand(VDataIdx).getReg();
10080}
10081
10083 TypeSize &MemBytes) const {
10084 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
10085 assert(Addr && Addr->isFI());
10086 FrameIndex = Addr->getIndex();
10087
10088 int DataIdx =
10089 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
10090 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
10091 return MI.getOperand(DataIdx).getReg();
10092}
10093
10095 int &FrameIndex,
10096 TypeSize &MemBytes) const {
10097 if (!MI.mayLoad())
10098 return Register();
10099
10100 if (isMUBUF(MI) || isVGPRSpill(MI))
10101 return isStackAccess(MI, FrameIndex, MemBytes);
10102
10103 if (isSGPRSpill(MI))
10104 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10105
10106 return Register();
10107}
10108
10110 int &FrameIndex,
10111 TypeSize &MemBytes) const {
10112 if (!MI.mayStore())
10113 return Register();
10114
10115 if (isMUBUF(MI) || isVGPRSpill(MI))
10116 return isStackAccess(MI, FrameIndex, MemBytes);
10117
10118 if (isSGPRSpill(MI))
10119 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10120
10121 return Register();
10122}
10123
10125 unsigned Opc = MI.getOpcode();
10127 unsigned DescSize = Desc.getSize();
10128
10129 // If we have a definitive size, we can use it. Otherwise we need to inspect
10130 // the operands to know the size.
10131 if (isFixedSize(MI)) {
10132 unsigned Size = DescSize;
10133
10134 // If we hit the buggy offset, an extra nop will be inserted in MC so
10135 // estimate the worst case.
10136 if (MI.isBranch() && ST.hasOffset3fBug())
10137 Size += 4;
10138
10139 return Size;
10140 }
10141
10142 // Instructions may have a 32-bit literal encoded after them. Check
10143 // operands that could ever be literals.
10144 if (isVALU(MI, /*AllowLDSDMA=*/true) || isSALU(MI)) {
10145 if (isDPP(MI))
10146 return DescSize;
10147 bool HasLiteral = false;
10148 unsigned LiteralSize = 4;
10149 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
10150 const MachineOperand &Op = MI.getOperand(I);
10151 const MCOperandInfo &OpInfo = Desc.operands()[I];
10152 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
10153 HasLiteral = true;
10154 if (ST.has64BitLiterals()) {
10155 switch (OpInfo.OperandType) {
10156 default:
10157 break;
10160 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
10161 LiteralSize = 8;
10162 break;
10165 // A 32-bit literal is only valid when the value fits in BOTH signed
10166 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
10167 // emitter's getLit64Encoding logic. This is because of the lack of
10168 // abilility to tell signedness of the literal, therefore we need to
10169 // be conservative and assume values outside this range require a
10170 // 64-bit literal encoding (8 bytes).
10171 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
10172 !isUInt<32>(Op.getImm()))
10173 LiteralSize = 8;
10174 break;
10175 }
10176 }
10177 break;
10178 }
10179 }
10180 return HasLiteral ? DescSize + LiteralSize : DescSize;
10181 }
10182
10183 // Check whether we have extra NSA words.
10184 if (isMIMG(MI)) {
10185 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
10186 if (VAddr0Idx < 0)
10187 return 8;
10188
10189 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
10190 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10191 }
10192
10193 switch (Opc) {
10194 case TargetOpcode::BUNDLE:
10195 return getInstBundleSize(MI);
10196 case TargetOpcode::INLINEASM:
10197 case TargetOpcode::INLINEASM_BR: {
10198 const MachineFunction *MF = MI.getMF();
10199 const char *AsmStr = MI.getOperand(0).getSymbolName();
10200 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10201 }
10202 default:
10203 if (MI.isMetaInstruction())
10204 return 0;
10205
10206 // If D16 Pseudo inst, get correct MC code size
10207 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10208 if (D16Info) {
10209 // Assume d16_lo/hi inst are always in same size
10210 unsigned LoInstOpcode = D16Info->LoOp;
10211 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10212 DescSize = Desc.getSize();
10213 }
10214
10215 // If FMA Pseudo inst, get correct MC code size
10216 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10217 // All potential lowerings are the same size; arbitrarily pick one.
10218 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10219 DescSize = Desc.getSize();
10220 }
10221
10222 return DescSize;
10223 }
10224}
10225
10228 if (MI.isBranch() && ST.hasOffset3fBug())
10229 return InstSizeVerifyMode::NoVerify;
10230 return InstSizeVerifyMode::ExactSize;
10231}
10232
10234 if (!isFLAT(MI))
10235 return false;
10236
10237 if (MI.memoperands_empty())
10238 return true;
10239
10240 for (const MachineMemOperand *MMO : MI.memoperands()) {
10242 return true;
10243 }
10244 return false;
10245}
10246
10249 static const std::pair<int, const char *> TargetIndices[] = {
10250 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10251 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10252 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10253 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10254 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10255 return ArrayRef(TargetIndices);
10256}
10257
10258/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10259/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10262 const ScheduleDAG *DAG) const {
10263 return new GCNHazardRecognizer(DAG->MF);
10264}
10265
10266/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10267/// pass.
10274
10275// Called during:
10276// - pre-RA scheduling and post-RA scheduling
10279 const ScheduleDAGMI *DAG) const {
10280 // Borrowed from Arm Target
10281 // We would like to restrict this hazard recognizer to only
10282 // post-RA scheduling; we can tell that we're post-RA because we don't
10283 // track VRegLiveness.
10284 if (!DAG->hasVRegLiveness())
10285 return new GCNHazardRecognizer(DAG->MF);
10287}
10288
10289std::pair<unsigned, unsigned>
10291 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10292}
10293
10296 static const std::pair<unsigned, const char *> TargetFlags[] = {
10297 {MO_GOTPCREL, "amdgpu-gotprel"},
10298 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10299 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10300 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10301 {MO_REL32_LO, "amdgpu-rel32-lo"},
10302 {MO_REL32_HI, "amdgpu-rel32-hi"},
10303 {MO_REL64, "amdgpu-rel64"},
10304 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10305 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10306 {MO_ABS64, "amdgpu-abs64"},
10307 };
10308
10309 return ArrayRef(TargetFlags);
10310}
10311
10314 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10315 {
10316 {MONoClobber, "amdgpu-noclobber"},
10317 {MOLastUse, "amdgpu-last-use"},
10318 {MOCooperative, "amdgpu-cooperative"},
10319 {MOThreadPrivate, "amdgpu-thread-private"},
10320 };
10321
10322 return ArrayRef(TargetFlags);
10323}
10324
10326 const MachineFunction &MF) const {
10328 assert(SrcReg.isVirtual());
10329 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10330 return AMDGPU::WWM_COPY;
10331
10332 return AMDGPU::COPY;
10333}
10334
10336 uint32_t Opcode = MI.getOpcode();
10337 // Check if it is SGPR spill or wwm-register spill Opcode.
10338 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10339 return true;
10340
10341 const MachineFunction *MF = MI.getMF();
10342 const MachineRegisterInfo &MRI = MF->getRegInfo();
10344
10345 // See if this is Liverange split instruction inserted for SGPR or
10346 // wwm-register. The implicit def inserted for wwm-registers should also be
10347 // included as they can appear at the bb begin.
10348 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10349 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10350 return false;
10351
10352 Register Reg = MI.getOperand(0).getReg();
10353 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10354 return IsLRSplitInst;
10355
10356 return MFI->isWWMReg(Reg);
10357}
10358
10360 Register Reg) const {
10361 // We need to handle instructions which may be inserted during register
10362 // allocation to handle the prolog. The initial prolog instruction may have
10363 // been separated from the start of the block by spills and copies inserted
10364 // needed by the prolog. However, the insertions for scalar registers can
10365 // always be placed at the BB top as they are independent of the exec mask
10366 // value.
10367 bool IsNullOrVectorRegister = true;
10368 if (Reg) {
10369 const MachineFunction *MF = MI.getMF();
10370 const MachineRegisterInfo &MRI = MF->getRegInfo();
10371 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10372 }
10373
10374 return IsNullOrVectorRegister &&
10375 (canAddToBBProlog(MI) ||
10376 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10377 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10378}
10379
10383 const DebugLoc &DL,
10384 Register DestReg) const {
10385 if (ST.hasAddNoCarryInsts())
10386 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10387
10388 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10389 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10390 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10391
10392 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10393 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10394}
10395
10398 const DebugLoc &DL,
10399 Register DestReg,
10400 RegScavenger &RS) const {
10401 if (ST.hasAddNoCarryInsts())
10402 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10403
10404 // If available, prefer to use vcc.
10405 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10406 ? Register(RI.getVCC())
10407 : RS.scavengeRegisterBackwards(
10408 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10409 0, /* AllowSpill */ false);
10410
10411 // TODO: Users need to deal with this.
10412 if (!UnusedCarry.isValid())
10413 return MachineInstrBuilder();
10414
10415 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10416 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10417}
10418
10419bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10420 switch (Opcode) {
10421 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10422 case AMDGPU::SI_KILL_I1_TERMINATOR:
10423 return true;
10424 default:
10425 return false;
10426 }
10427}
10428
10430 switch (Opcode) {
10431 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10432 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10433 case AMDGPU::SI_KILL_I1_PSEUDO:
10434 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10435 default:
10436 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10437 }
10438}
10439
10441 return Imm <= getMaxMUBUFImmOffset(ST);
10442}
10443
10445 // GFX12 field is non-negative 24-bit signed byte offset.
10446 const unsigned OffsetBits =
10447 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10448 return (1 << OffsetBits) - 1;
10449}
10450
10452 if (!ST.isWave32())
10453 return;
10454
10455 if (MI.isInlineAsm())
10456 return;
10457
10458 if (MI.getNumOperands() < MI.getNumExplicitOperands())
10459 return;
10460
10461 for (auto &Op : MI.implicit_operands()) {
10462 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10463 Op.setReg(AMDGPU::VCC_LO);
10464 }
10465}
10466
10468 if (!isSMRD(MI))
10469 return false;
10470
10471 // Check that it is using a buffer resource.
10472 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10473 if (Idx == -1) // e.g. s_memtime
10474 return false;
10475
10476 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10477 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10478}
10479
10480// Given Imm, split it into the values to put into the SOffset and ImmOffset
10481// fields in an MUBUF instruction. Return false if it is not possible (due to a
10482// hardware bug needing a workaround).
10483//
10484// The required alignment ensures that individual address components remain
10485// aligned if they are aligned to begin with. It also ensures that additional
10486// offsets within the given alignment can be added to the resulting ImmOffset.
10488 uint32_t &ImmOffset, Align Alignment) const {
10489 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10490 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10491 uint32_t Overflow = 0;
10492
10493 if (Imm > MaxImm) {
10494 if (Imm <= MaxImm + 64) {
10495 // Use an SOffset inline constant for 4..64
10496 Overflow = Imm - MaxImm;
10497 Imm = MaxImm;
10498 } else {
10499 // Try to keep the same value in SOffset for adjacent loads, so that
10500 // the corresponding register contents can be re-used.
10501 //
10502 // Load values with all low-bits (except for alignment bits) set into
10503 // SOffset, so that a larger range of values can be covered using
10504 // s_movk_i32.
10505 //
10506 // Atomic operations fail to work correctly when individual address
10507 // components are unaligned, even if their sum is aligned.
10508 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10509 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10510 Imm = Low;
10511 Overflow = High - Alignment.value();
10512 }
10513 }
10514
10515 if (Overflow > 0) {
10516 // There is a hardware bug in SI and CI which prevents address clamping in
10517 // MUBUF instructions from working correctly with SOffsets. The immediate
10518 // offset is unaffected.
10519 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10520 return false;
10521
10522 // It is not possible to set immediate in SOffset field on some targets.
10523 if (ST.hasRestrictedSOffset())
10524 return false;
10525 }
10526
10527 ImmOffset = Imm;
10528 SOffset = Overflow;
10529 return true;
10530}
10531
10532// Depending on the used address space and instructions, some immediate offsets
10533// are allowed and some are not.
10534// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10535// scratch instruction offsets can also be negative. On GFX12, offsets can be
10536// negative for all variants.
10537//
10538// There are several bugs related to these offsets:
10539// On gfx10.1, flat instructions that go into the global address space cannot
10540// use an offset.
10541//
10542// For scratch instructions, the address can be either an SGPR or a VGPR.
10543// The following offsets can be used, depending on the architecture (x means
10544// cannot be used):
10545// +----------------------------+------+------+
10546// | Address-Mode | SGPR | VGPR |
10547// +----------------------------+------+------+
10548// | gfx9 | | |
10549// | negative, 4-aligned offset | x | ok |
10550// | negative, unaligned offset | x | ok |
10551// +----------------------------+------+------+
10552// | gfx10 | | |
10553// | negative, 4-aligned offset | ok | ok |
10554// | negative, unaligned offset | ok | x |
10555// +----------------------------+------+------+
10556// | gfx10.3 | | |
10557// | negative, 4-aligned offset | ok | ok |
10558// | negative, unaligned offset | ok | ok |
10559// +----------------------------+------+------+
10560//
10561// This function ignores the addressing mode, so if an offset cannot be used in
10562// one addressing mode, it is considered illegal.
10563bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10564 AMDGPU::FlatAddrSpace FlatVariant) const {
10565 // TODO: Should 0 be special cased?
10566 if (!ST.hasFlatInstOffsets())
10567 return false;
10568
10570 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10571 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10572 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10573 return false;
10574
10575 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10576 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10577 (Offset % 4) != 0) {
10578 return false;
10579 }
10580
10581 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10582 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10583 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10584}
10585
10586// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10587std::pair<int64_t, int64_t>
10588SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10589 AMDGPU::FlatAddrSpace FlatVariant) const {
10590 int64_t RemainderOffset = COffsetVal;
10591 int64_t ImmField = 0;
10592
10593 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10594 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10595
10596 if (AllowNegative) {
10597 // Use signed division by a power of two to truncate towards 0.
10598 int64_t D = 1LL << NumBits;
10599 RemainderOffset = (COffsetVal / D) * D;
10600 ImmField = COffsetVal - RemainderOffset;
10601
10602 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10603 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10604 (ImmField % 4) != 0) {
10605 // Make ImmField a multiple of 4
10606 RemainderOffset += ImmField % 4;
10607 ImmField -= ImmField % 4;
10608 }
10609 } else if (COffsetVal >= 0) {
10610 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10611 RemainderOffset = COffsetVal - ImmField;
10612 }
10613
10614 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10615 assert(RemainderOffset + ImmField == COffsetVal);
10616 return {ImmField, RemainderOffset};
10617}
10618
10620 AMDGPU::FlatAddrSpace FlatVariant) const {
10621 if (ST.hasNegativeScratchOffsetBug() &&
10623 return false;
10624
10625 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10626}
10627
10628static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10629 switch (ST.getGeneration()) {
10630 default:
10631 break;
10634 return SIEncodingFamily::SI;
10637 return SIEncodingFamily::VI;
10641 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10644 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10648 }
10649 llvm_unreachable("Unknown subtarget generation!");
10650}
10651
10652bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10653 switch(MCOp) {
10654 // These opcodes use indirect register addressing so
10655 // they need special handling by codegen (currently missing).
10656 // Therefore it is too risky to allow these opcodes
10657 // to be selected by dpp combiner or sdwa peepholer.
10658 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10659 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10660 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10661 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10662 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10663 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10664 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10665 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10666 return true;
10667 default:
10668 return false;
10669 }
10670}
10671
10672#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10673 case OPCODE##_dpp: \
10674 case OPCODE##_e32: \
10675 case OPCODE##_e64: \
10676 case OPCODE##_e64_dpp: \
10677 case OPCODE##_sdwa:
10678
10679static bool isRenamedInGFX9(int Opcode) {
10680 switch (Opcode) {
10681 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
10682 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
10683 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
10684 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
10685 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
10686 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
10687 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
10688 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
10689 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
10690 //
10691 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10692 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10693 case AMDGPU::V_FMA_F16_gfx9_e64:
10694 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10695 case AMDGPU::V_INTERP_P2_F16:
10696 case AMDGPU::V_MAD_F16_e64:
10697 case AMDGPU::V_MAD_U16_e64:
10698 case AMDGPU::V_MAD_I16_e64:
10699 return true;
10700 default:
10701 return false;
10702 }
10703}
10704
10705int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
10706 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
10707 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10708
10709 unsigned Gen = subtargetEncodingFamily(ST);
10710
10711 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
10713
10714 // Adjust the encoding family to GFX80 for D16 buffer instructions when the
10715 // subtarget has UnpackedD16VMem feature.
10716 // TODO: remove this when we discard GFX80 encoding.
10717 if (ST.hasUnpackedD16VMem() && SIInstrFlags::isD16Buf(get(Opcode)))
10719
10720 if (SIInstrFlags::isSDWA(get(Opcode))) {
10721 switch (ST.getGeneration()) {
10722 default:
10724 break;
10727 break;
10730 break;
10731 }
10732 }
10733
10734 if (isMAI(Opcode)) {
10735 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
10736 if (MFMAOp != -1)
10737 Opcode = MFMAOp;
10738 }
10739
10740 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
10741
10742 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10744
10745 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10747
10748 // -1 means that Opcode is already a native instruction.
10749 if (MCOp == -1)
10750 return Opcode;
10751
10752 if (ST.hasGFX90AInsts()) {
10753 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10754 if (ST.hasGFX940Insts())
10756 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10758 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10760 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10761 MCOp = NMCOp;
10762 }
10763
10764 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
10765 // encoding in the given subtarget generation.
10766 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10767 return -1;
10768
10769 if (isAsmOnlyOpcode(MCOp))
10770 return -1;
10771
10772 return MCOp;
10773}
10774
10775static
10777 assert(RegOpnd.isReg());
10778 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
10779 getRegSubRegPair(RegOpnd);
10780}
10781
10784 assert(MI.isRegSequence());
10785 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
10786 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
10787 auto &RegOp = MI.getOperand(1 + 2 * I);
10788 return getRegOrUndef(RegOp);
10789 }
10791}
10792
10793// Try to find the definition of reg:subreg in subreg-manipulation pseudos
10794// Following a subreg of reg:subreg isn't supported
10797 if (!RSR.SubReg)
10798 return false;
10799 switch (MI.getOpcode()) {
10800 default: break;
10801 case AMDGPU::REG_SEQUENCE:
10802 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
10803 return true;
10804 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
10805 case AMDGPU::INSERT_SUBREG:
10806 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
10807 // inserted the subreg we're looking for
10808 RSR = getRegOrUndef(MI.getOperand(2));
10809 else { // the subreg in the rest of the reg
10810 auto R1 = getRegOrUndef(MI.getOperand(1));
10811 if (R1.SubReg) // subreg of subreg isn't supported
10812 return false;
10813 RSR.Reg = R1.Reg;
10814 }
10815 return true;
10816 }
10817 return false;
10818}
10819
10821 const MachineRegisterInfo &MRI) {
10822 assert(MRI.isSSA());
10823 if (!P.Reg.isVirtual())
10824 return nullptr;
10825
10826 auto RSR = P;
10827 auto *DefInst = MRI.getVRegDef(RSR.Reg);
10828 while (auto *MI = DefInst) {
10829 DefInst = nullptr;
10830 switch (MI->getOpcode()) {
10831 case AMDGPU::COPY:
10832 case AMDGPU::V_MOV_B32_e32: {
10833 auto &Op1 = MI->getOperand(1);
10834 if (Op1.isReg() && Op1.getReg().isVirtual()) {
10835 if (Op1.isUndef())
10836 return nullptr;
10837 RSR = getRegSubRegPair(Op1);
10838 DefInst = MRI.getVRegDef(RSR.Reg);
10839 }
10840 break;
10841 }
10842 default:
10843 if (followSubRegDef(*MI, RSR)) {
10844 if (!RSR.Reg)
10845 return nullptr;
10846 DefInst = MRI.getVRegDef(RSR.Reg);
10847 }
10848 }
10849 if (!DefInst)
10850 return MI;
10851 }
10852 return nullptr;
10853}
10854
10856 Register VReg,
10857 const MachineInstr &DefMI,
10858 const MachineInstr &UseMI) {
10859 assert(MRI.isSSA() && "Must be run on SSA");
10860
10861 auto *TRI = MRI.getTargetRegisterInfo();
10862 auto *DefBB = DefMI.getParent();
10863
10864 // Don't bother searching between blocks, although it is possible this block
10865 // doesn't modify exec.
10866 if (UseMI.getParent() != DefBB)
10867 return true;
10868
10869 const int MaxInstScan = 20;
10870 int NumInst = 0;
10871
10872 // Stop scan at the use.
10873 auto E = UseMI.getIterator();
10874 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
10875 if (I->isDebugInstr())
10876 continue;
10877
10878 if (++NumInst > MaxInstScan)
10879 return true;
10880
10881 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
10882 return true;
10883 }
10884
10885 return false;
10886}
10887
10889 Register VReg,
10890 const MachineInstr &DefMI) {
10891 assert(MRI.isSSA() && "Must be run on SSA");
10892
10893 auto *TRI = MRI.getTargetRegisterInfo();
10894 auto *DefBB = DefMI.getParent();
10895
10896 const int MaxUseScan = 10;
10897 int NumUse = 0;
10898
10899 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
10900 auto &UseInst = *Use.getParent();
10901 // Don't bother searching between blocks, although it is possible this block
10902 // doesn't modify exec.
10903 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10904 return true;
10905
10906 if (++NumUse > MaxUseScan)
10907 return true;
10908 }
10909
10910 if (NumUse == 0)
10911 return false;
10912
10913 const int MaxInstScan = 20;
10914 int NumInst = 0;
10915
10916 // Stop scan when we have seen all the uses.
10917 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
10918 assert(I != DefBB->end());
10919
10920 if (I->isDebugInstr())
10921 continue;
10922
10923 if (++NumInst > MaxInstScan)
10924 return true;
10925
10926 for (const MachineOperand &Op : I->operands()) {
10927 // We don't check reg masks here as they're used only on calls:
10928 // 1. EXEC is only considered const within one BB
10929 // 2. Call should be a terminator instruction if present in a BB
10930
10931 if (!Op.isReg())
10932 continue;
10933
10934 Register Reg = Op.getReg();
10935 if (Op.isUse()) {
10936 if (Reg == VReg && --NumUse == 0)
10937 return false;
10938 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
10939 return true;
10940 }
10941 }
10942}
10943
10946 const DebugLoc &DL, Register Src, Register Dst) const {
10947 auto Cur = MBB.begin();
10948 if (Cur != MBB.end())
10949 do {
10950 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
10951 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
10952 ++Cur;
10953 } while (Cur != MBB.end() && Cur != LastPHIIt);
10954
10955 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
10956 Dst);
10957}
10958
10961 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
10962 if (InsPt != MBB.end() &&
10963 (InsPt->getOpcode() == AMDGPU::SI_IF ||
10964 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
10965 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
10966 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
10967 InsPt++;
10968 return BuildMI(MBB, InsPt, DL,
10969 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
10970 .addReg(Src, {}, SrcSubReg)
10971 .addReg(AMDGPU::EXEC, RegState::Implicit);
10972 }
10973 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
10974 Dst);
10975}
10976
10977bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
10978
10980 const MachineInstr &SecondMI) const {
10981 for (const auto &Use : SecondMI.all_uses()) {
10982 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
10983 return true;
10984 }
10985 return false;
10986}
10987
10988/// If OpX is multicycle, anti-dependencies are not allowed.
10989/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
10990/// purpose.
10992 const MachineInstr &OpX) const {
10994}
10995
10998 ArrayRef<unsigned> Ops, int FrameIndex,
10999 MachineInstr *&CopyMI, LiveIntervals *LIS,
11000 VirtRegMap *VRM) const {
11001 // This is a bit of a hack (copied from AArch64). Consider this instruction:
11002 //
11003 // %0:sreg_32 = COPY $m0
11004 //
11005 // We explicitly chose SReg_32 for the virtual register so such a copy might
11006 // be eliminated by RegisterCoalescer. However, that may not be possible, and
11007 // %0 may even spill. We can't spill $m0 normally (it would require copying to
11008 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
11009 // TargetInstrInfo::foldMemoryOperand() is going to try.
11010 // A similar issue also exists with spilling and reloading $exec registers.
11011 //
11012 // To prevent that, constrain the %0 register class here.
11013 if (isFullCopyInstr(MI)) {
11014 Register DstReg = MI.getOperand(0).getReg();
11015 Register SrcReg = MI.getOperand(1).getReg();
11016 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
11017 (DstReg.isVirtual() != SrcReg.isVirtual())) {
11018 MachineRegisterInfo &MRI = MF.getRegInfo();
11019 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
11020 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
11021 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
11022 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11023 return nullptr;
11024 }
11025 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
11026 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11027 return nullptr;
11028 }
11029 }
11030 }
11031
11032 return nullptr;
11033}
11034
11036 const MachineInstr &MI,
11037 unsigned *PredCost) const {
11038 if (MI.isBundle()) {
11040 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
11041 unsigned Lat = 0, Count = 0;
11042 for (++I; I != E && I->isBundledWithPred(); ++I) {
11043 ++Count;
11044 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
11045 }
11046 return Lat + Count - 1;
11047 }
11048
11049 return SchedModel.computeInstrLatency(&MI);
11050}
11051
11052const MachineOperand &
11054 if (const MachineOperand *CallAddrOp =
11055 getNamedOperand(MI, AMDGPU::OpName::src0))
11056 return *CallAddrOp;
11058}
11059
11062 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11063 unsigned Opcode = MI.getOpcode();
11064
11065 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
11066 Register Dst = MI.getOperand(0).getReg();
11067 Register Src = isa<GIntrinsic>(MI) ? MI.getOperand(2).getReg()
11068 : MI.getOperand(1).getReg();
11069 LLT DstTy = MRI.getType(Dst);
11070 LLT SrcTy = MRI.getType(Src);
11071 unsigned DstAS = DstTy.getAddressSpace();
11072 unsigned SrcAS = SrcTy.getAddressSpace();
11073 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
11074 DstAS == AMDGPUAS::FLAT_ADDRESS &&
11075 ST.hasGloballyAddressableScratch()
11078 };
11079
11080 // If the target supports globally addressable scratch, the mapping from
11081 // scratch memory to the flat aperture changes therefore an address space cast
11082 // is no longer uniform.
11083 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11084 return HandleAddrSpaceCast(MI);
11085
11086 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
11087 auto IID = GI->getIntrinsicID();
11092
11093 switch (IID) {
11094 case Intrinsic::amdgcn_addrspacecast_nonnull:
11095 return HandleAddrSpaceCast(MI);
11096 case Intrinsic::amdgcn_if:
11097 case Intrinsic::amdgcn_else:
11098 // FIXME: Uniform if second result
11099 break;
11100 }
11101
11103 }
11104
11105 // Loads from the private and flat address spaces are divergent, because
11106 // threads can execute the load instruction with the same inputs and get
11107 // different results.
11108 //
11109 // All other loads are not divergent, because if threads issue loads with the
11110 // same arguments, they will always get the same result.
11111 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11112 Opcode == AMDGPU::G_SEXTLOAD) {
11113 if (MI.memoperands_empty())
11114 return ValueUniformity::NeverUniform; // conservative assumption
11115
11116 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11117 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11118 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11119 })) {
11120 // At least one MMO in a non-global address space.
11122 }
11124 }
11125
11126 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11127 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11128 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11129 AMDGPU::isGenericAtomic(Opcode)) {
11131 }
11132
11133 // Result is computed from uniform SP and uniform wave-wide max size.
11134 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11136
11137 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11139
11141}
11142
11144 if (!Formatter)
11145 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11146 return Formatter.get();
11147}
11148
11150
11151 if (isNeverUniform(MI))
11153
11154 unsigned opcode = MI.getOpcode();
11155 if (opcode == AMDGPU::V_READLANE_B32 ||
11156 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11157 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11159
11160 // If any of defs is divergent, report as NeverUniform. isUniformReg will
11161 // calculate in more detail for each def from its reg class, if available.
11162 if (MI.isInlineAsm()) {
11163 for (const MachineOperand &MO : MI.operands()) {
11164 if (!MO.isReg() || !MO.isDef())
11165 continue;
11166 const TargetRegisterClass *RC =
11167 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
11168 if (!RC || !RI.isSGPRClass(RC))
11170 }
11171 }
11172
11173 if (isCopyInstr(MI)) {
11174 const MachineOperand &srcOp = MI.getOperand(1);
11175 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
11176 const TargetRegisterClass *regClass =
11177 RI.getPhysRegBaseClass(srcOp.getReg());
11178 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
11180 }
11182 }
11183
11184 // GMIR handling
11185 if (MI.isPreISelOpcode())
11187
11188 // Atomics are divergent because they are executed sequentially: when an
11189 // atomic operation refers to the same address in each thread, then each
11190 // thread after the first sees the value written by the previous thread as
11191 // original value.
11192
11193 if (isAtomic(MI))
11195
11196 // Loads from the private and flat address spaces are divergent, because
11197 // threads can execute the load instruction with the same inputs and get
11198 // different results.
11199 if (isFLAT(MI) && MI.mayLoad()) {
11200 if (MI.memoperands_empty())
11201 return ValueUniformity::NeverUniform; // conservative assumption
11202
11203 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11204 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11205 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11206 })) {
11207 // At least one MMO in a non-global address space.
11209 }
11210
11212 }
11213
11214 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11215 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11216
11217 // FIXME: It's conceptually broken to report this for an instruction, and not
11218 // a specific def operand. For inline asm in particular, there could be mixed
11219 // uniform and divergent results.
11220 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11221 const MachineOperand &SrcOp = MI.getOperand(I);
11222 if (!SrcOp.isReg())
11223 continue;
11224
11225 Register Reg = SrcOp.getReg();
11226 if (!Reg || !SrcOp.readsReg())
11227 continue;
11228
11229 // If RegBank is null, this is unassigned or an unallocatable special
11230 // register, which are all scalars.
11231 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11232 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11234 }
11235
11236 // TODO: Uniformity check condtions above can be rearranged for more
11237 // redability
11238
11239 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11240 // currently turned into no-op COPYs by SelectionDAG ISel and are
11241 // therefore no longer recognizable.
11242
11244}
11245
11247 switch (MF.getFunction().getCallingConv()) {
11249 return 1;
11251 return 2;
11253 return 3;
11257 const Function &F = MF.getFunction();
11258 F.getContext().diagnose(DiagnosticInfoUnsupported(
11259 F, "ds_ordered_count unsupported for this calling conv"));
11260 [[fallthrough]];
11261 }
11264 case CallingConv::C:
11265 case CallingConv::Fast:
11266 default:
11267 // Assume other calling conventions are various compute callable functions
11268 return 0;
11269 }
11270}
11271
11273 Register &SrcReg2, int64_t &CmpMask,
11274 int64_t &CmpValue) const {
11275 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11276 return false;
11277
11278 switch (MI.getOpcode()) {
11279 default:
11280 break;
11281 case AMDGPU::S_CMP_EQ_U32:
11282 case AMDGPU::S_CMP_EQ_I32:
11283 case AMDGPU::S_CMP_LG_U32:
11284 case AMDGPU::S_CMP_LG_I32:
11285 case AMDGPU::S_CMP_LT_U32:
11286 case AMDGPU::S_CMP_LT_I32:
11287 case AMDGPU::S_CMP_GT_U32:
11288 case AMDGPU::S_CMP_GT_I32:
11289 case AMDGPU::S_CMP_LE_U32:
11290 case AMDGPU::S_CMP_LE_I32:
11291 case AMDGPU::S_CMP_GE_U32:
11292 case AMDGPU::S_CMP_GE_I32:
11293 case AMDGPU::S_CMP_EQ_U64:
11294 case AMDGPU::S_CMP_LG_U64:
11295 SrcReg = MI.getOperand(0).getReg();
11296 if (MI.getOperand(1).isReg()) {
11297 if (MI.getOperand(1).getSubReg())
11298 return false;
11299 SrcReg2 = MI.getOperand(1).getReg();
11300 CmpValue = 0;
11301 } else if (MI.getOperand(1).isImm()) {
11302 SrcReg2 = Register();
11303 CmpValue = MI.getOperand(1).getImm();
11304 } else {
11305 return false;
11306 }
11307 CmpMask = ~0;
11308 return true;
11309 case AMDGPU::S_CMPK_EQ_U32:
11310 case AMDGPU::S_CMPK_EQ_I32:
11311 case AMDGPU::S_CMPK_LG_U32:
11312 case AMDGPU::S_CMPK_LG_I32:
11313 case AMDGPU::S_CMPK_LT_U32:
11314 case AMDGPU::S_CMPK_LT_I32:
11315 case AMDGPU::S_CMPK_GT_U32:
11316 case AMDGPU::S_CMPK_GT_I32:
11317 case AMDGPU::S_CMPK_LE_U32:
11318 case AMDGPU::S_CMPK_LE_I32:
11319 case AMDGPU::S_CMPK_GE_U32:
11320 case AMDGPU::S_CMPK_GE_I32:
11321 SrcReg = MI.getOperand(0).getReg();
11322 SrcReg2 = Register();
11323 CmpValue = MI.getOperand(1).getImm();
11324 CmpMask = ~0;
11325 return true;
11326 }
11327
11328 return false;
11329}
11330
11332 for (MachineBasicBlock *S : MBB->successors()) {
11333 if (S->isLiveIn(AMDGPU::SCC))
11334 return false;
11335 }
11336 return true;
11337}
11338
11339// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11340// (incoming SCC) = !(SCC defined by SCCDef).
11341// Return true if all uses can be re-written, false otherwise.
11342bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11343 MachineBasicBlock *MBB = SCCDef->getParent();
11344 SmallVector<MachineInstr *> InvertInstr;
11345 bool SCCIsDead = false;
11346
11347 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11348 constexpr unsigned ScanLimit = 12;
11349 unsigned Count = 0;
11350 for (MachineInstr &MI :
11351 make_range(std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11352 if (++Count > ScanLimit)
11353 return false;
11354 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11355 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11356 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11357 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11358 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11359 InvertInstr.push_back(&MI);
11360 else
11361 return false;
11362 }
11363 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11364 SCCIsDead = true;
11365 break;
11366 }
11367 }
11368 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11369 SCCIsDead = true;
11370
11371 // SCC may have more uses. Can't invert all of them.
11372 if (!SCCIsDead)
11373 return false;
11374
11375 // Invert uses
11376 for (MachineInstr *MI : InvertInstr) {
11377 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11378 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11379 swapOperands(*MI);
11380 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11381 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11382 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11383 ? AMDGPU::S_CBRANCH_SCC1
11384 : AMDGPU::S_CBRANCH_SCC0));
11385 } else {
11386 llvm_unreachable("SCC used but no inversion handling");
11387 }
11388 }
11389 return true;
11390}
11391
11392// SCC is already valid after SCCValid.
11393// SCCRedefine will redefine SCC to the same value already available after
11394// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11395// update kill/dead flags if necessary.
11396bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11397 bool NeedInversion) const {
11398 MachineInstr *KillsSCC = nullptr;
11399 if (SCCValid->getParent() != SCCRedefine->getParent())
11400 return false;
11401 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11402 SCCRedefine->getIterator())) {
11403 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11404 return false;
11405 if (MI.killsRegister(AMDGPU::SCC, &RI))
11406 KillsSCC = &MI;
11407 }
11408 if (NeedInversion && !invertSCCUse(SCCRedefine))
11409 return false;
11410 if (MachineOperand *SccDef =
11411 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11412 SccDef->setIsDead(false);
11413 if (KillsSCC)
11414 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11415 SCCRedefine->eraseFromParent();
11416 return true;
11417}
11418
11419static bool foldableSelect(const MachineInstr &Def) {
11420 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11421 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11422 return false;
11423 bool Op1IsNonZeroImm =
11424 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11425 bool Op2IsZeroImm =
11426 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11427 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11428 return false;
11429 return true;
11430}
11431
11432static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11433 unsigned &NewDefOpc) {
11434 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11435 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11436 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11437 Def.getOpcode() != AMDGPU::S_ADD_U32)
11438 return false;
11439 const MachineOperand &AddSrc1 = Def.getOperand(1);
11440 const MachineOperand &AddSrc2 = Def.getOperand(2);
11441 int64_t addend;
11442
11443 if ((!AddSrc1.isImm() || AddSrc1.getImm() != 1) &&
11444 (!AddSrc2.isImm() || AddSrc2.getImm() != 1) &&
11445 (!getFoldableImm(&AddSrc1, addend) || addend != 1) &&
11446 (!getFoldableImm(&AddSrc2, addend) || addend != 1))
11447 return false;
11448
11449 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11450 const MachineOperand *SccDef =
11451 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11452 if (!SccDef->isDead())
11453 return false;
11454 NewDefOpc = AMDGPU::S_ADD_U32;
11455 }
11456 NeedInversion = !NeedInversion;
11457 return true;
11458}
11459
11461 Register SrcReg2, int64_t CmpMask,
11462 int64_t CmpValue,
11463 const MachineRegisterInfo *MRI) const {
11464 if (!SrcReg || SrcReg.isPhysical())
11465 return false;
11466
11467 if (SrcReg2 && !getFoldableImm(SrcReg2, *MRI, CmpValue))
11468 return false;
11469
11470 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11471 this](bool NeedInversion) -> bool {
11472 if (CmpValue != 0)
11473 return false;
11474
11475 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11476 if (!Def)
11477 return false;
11478
11479 // For S_OP that set SCC = DST!=0, do the transformation
11480 //
11481 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11482 //
11483 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11484 // do the transformation:
11485 //
11486 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11487 //
11488 // If foldableSelect, s_cmp_lg_* is redundant because the SCC input value
11489 // for S_CSELECT* already has the same value that will be calculated by
11490 // s_cmp_lg_*
11491 //
11492 // s_cmp_[lg|eq]_* (S_CSELECT* (non-zero imm), 0), 0 => (S_CSELECT*
11493 // (non-zero imm), 0)
11494
11495 unsigned NewDefOpc = Def->getOpcode();
11496 if (!setsSCCIfResultIsNonZero(*Def) &&
11497 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc) &&
11498 !foldableSelect(*Def))
11499 return false;
11500
11501 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11502 return false;
11503
11504 if (NewDefOpc != Def->getOpcode())
11505 Def->setDesc(get(NewDefOpc));
11506
11507 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11508 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11509 // 64-bit foldableSelect then delete s_or_b32 in the sequence:
11510 // sX = s_cselect_b64 (non-zero imm), 0
11511 // sLo = copy sX.sub0
11512 // sHi = copy sX.sub1
11513 // sY = s_or_b32 sLo, sHi
11514 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11515 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11516 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11517 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11518 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11519 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11520 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11521 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11522 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11523 Def2->getOperand(1).isReg() &&
11524 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11525 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11526 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11527 MachineInstr *Select = MRI->getVRegDef(Def1->getOperand(1).getReg());
11528 if (Select && foldableSelect(*Select))
11529 optimizeSCC(Select, Def, /*NeedInversion=*/false);
11530 }
11531 }
11532 }
11533 return true;
11534 };
11535
11536 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11537 this](int64_t ExpectedValue, unsigned SrcSize,
11538 bool IsReversible, bool IsSigned) -> bool {
11539 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11540 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11541 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11542 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11543 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11544 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11545 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11546 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11547 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11548 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11549 //
11550 // Signed ge/gt are not used for the sign bit.
11551 //
11552 // If result of the AND is unused except in the compare:
11553 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11554 //
11555 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11556 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11557 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11558 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11559 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11560 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11561
11562 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11563 if (!Def)
11564 return false;
11565
11566 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11567 Def->getOpcode() != AMDGPU::S_AND_B64)
11568 return false;
11569
11570 int64_t Mask;
11571 const auto isMask = [&Mask, SrcSize](const MachineOperand *MO) -> bool {
11572 if (MO->isImm())
11573 Mask = MO->getImm();
11574 else if (!getFoldableImm(MO, Mask))
11575 return false;
11576 Mask &= maxUIntN(SrcSize);
11577 return isPowerOf2_64(Mask);
11578 };
11579
11580 MachineOperand *SrcOp = &Def->getOperand(1);
11581 if (isMask(SrcOp))
11582 SrcOp = &Def->getOperand(2);
11583 else if (isMask(&Def->getOperand(2)))
11584 SrcOp = &Def->getOperand(1);
11585 else
11586 return false;
11587
11588 // A valid Mask is required to have a single bit set, hence a non-zero and
11589 // power-of-two value. This verifies that we will not do 64-bit shift below.
11590 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11591 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11592 if (IsSigned && BitNo == SrcSize - 1)
11593 return false;
11594
11595 ExpectedValue <<= BitNo;
11596
11597 bool IsReversedCC = false;
11598 if (CmpValue != ExpectedValue) {
11599 if (!IsReversible)
11600 return false;
11601 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11602 if (!IsReversedCC)
11603 return false;
11604 }
11605
11606 Register DefReg = Def->getOperand(0).getReg();
11607 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11608 return false;
11609
11610 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11611 return false;
11612
11613 if (!MRI->use_nodbg_empty(DefReg)) {
11614 assert(!IsReversedCC);
11615 return true;
11616 }
11617
11618 // Replace AND with unused result with a S_BITCMP.
11619 MachineBasicBlock *MBB = Def->getParent();
11620
11621 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11622 : AMDGPU::S_BITCMP1_B32
11623 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11624 : AMDGPU::S_BITCMP1_B64;
11625
11626 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11627 .add(*SrcOp)
11628 .addImm(BitNo);
11629 Def->eraseFromParent();
11630
11631 return true;
11632 };
11633
11634 switch (CmpInstr.getOpcode()) {
11635 default:
11636 break;
11637 case AMDGPU::S_CMP_EQ_U32:
11638 case AMDGPU::S_CMP_EQ_I32:
11639 case AMDGPU::S_CMPK_EQ_U32:
11640 case AMDGPU::S_CMPK_EQ_I32:
11641 return optimizeCmpAnd(1, 32, true, false) ||
11642 optimizeCmpSelect(/*NeedInversion=*/true);
11643 case AMDGPU::S_CMP_GE_U32:
11644 case AMDGPU::S_CMPK_GE_U32:
11645 return optimizeCmpAnd(1, 32, false, false);
11646 case AMDGPU::S_CMP_GE_I32:
11647 case AMDGPU::S_CMPK_GE_I32:
11648 return optimizeCmpAnd(1, 32, false, true);
11649 case AMDGPU::S_CMP_EQ_U64:
11650 return optimizeCmpAnd(1, 64, true, false);
11651 case AMDGPU::S_CMP_LG_U32:
11652 case AMDGPU::S_CMP_LG_I32:
11653 case AMDGPU::S_CMPK_LG_U32:
11654 case AMDGPU::S_CMPK_LG_I32:
11655 return optimizeCmpAnd(0, 32, true, false) ||
11656 optimizeCmpSelect(/*NeedInversion=*/false);
11657 case AMDGPU::S_CMP_GT_U32:
11658 case AMDGPU::S_CMPK_GT_U32:
11659 return optimizeCmpAnd(0, 32, false, false);
11660 case AMDGPU::S_CMP_GT_I32:
11661 case AMDGPU::S_CMPK_GT_I32:
11662 return optimizeCmpAnd(0, 32, false, true);
11663 case AMDGPU::S_CMP_LG_U64:
11664 return optimizeCmpAnd(0, 64, true, false) ||
11665 optimizeCmpSelect(/*NeedInversion=*/false);
11666 }
11667
11668 return false;
11669}
11670
11672 AMDGPU::OpName OpName) const {
11673 if (!ST.needsAlignedVGPRs())
11674 return;
11675
11676 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
11677 if (OpNo < 0)
11678 return;
11679 MachineOperand &Op = MI.getOperand(OpNo);
11680 if (getOpSize(MI, OpNo) > 4)
11681 return;
11682
11683 // Add implicit aligned super-reg to force alignment on the data operand.
11684 const DebugLoc &DL = MI.getDebugLoc();
11685 MachineBasicBlock *BB = MI.getParent();
11687 Register DataReg = Op.getReg();
11688 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11690 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11691 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
11692 Register NewVR =
11693 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
11694 : &AMDGPU::VReg_64_Align2RegClass);
11695 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
11696 .addReg(DataReg, {}, Op.getSubReg())
11697 .addImm(AMDGPU::sub0)
11698 .addReg(Undef)
11699 .addImm(AMDGPU::sub1);
11700 Op.setReg(NewVR);
11701 Op.setSubReg(AMDGPU::sub0);
11702 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
11703}
11704
11706 if (!SchedModel.hasInstrSchedModel())
11707 return 0;
11708
11709 // The repeat rate is the throughput-limiting resource occupancy: the largest
11710 // number of cycles any written processor resource is held.
11711 const MCSchedClassDesc *SCDesc = SchedModel.resolveSchedClass(&MI);
11712 unsigned RepeatRate = 0;
11714 PI = SchedModel.getWriteProcResBegin(SCDesc),
11715 PE = SchedModel.getWriteProcResEnd(SCDesc);
11716 PI != PE; ++PI) {
11717 RepeatRate = std::max(RepeatRate, (unsigned)PI->ReleaseAtCycle);
11718 }
11719
11720 return RepeatRate;
11721}
11722
11724 if (isIGLP(*MI))
11725 return false;
11726
11728}
11729
11731 if (!isWMMA(MI) && !isSWMMAC(MI))
11732 return false;
11733
11734 if (ST.hasGFX1250Insts())
11735 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
11736
11737 return true;
11738}
11739
11741 unsigned Opcode = MI.getOpcode();
11742
11743 if (AMDGPU::isGFX12Plus(ST))
11744 return isDOT(MI) || isXDLWMMA(MI);
11745
11746 if (!isMAI(MI) || isDGEMM(Opcode) ||
11747 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11748 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11749 return false;
11750
11751 if (!ST.hasGFX940Insts())
11752 return true;
11753
11754 return AMDGPU::getMAIIsGFX940XDL(Opcode);
11755}
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 bool getFoldableImm(Register Reg, const MachineRegisterInfo &MRI, int64_t &Imm, MachineInstr **DefMI=nullptr)
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
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:299
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:272
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:353
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:86
uint8_t OperandType
Information about the type of the operand.
Definition MCInstrDesc.h:98
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition MCInstrDesc.h:92
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.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
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
bool isSpill(uint32_t Opcode) const
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
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)
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)
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)
bool isIgnorableUse(const MachineOperand &MO) const override
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
static bool isF16PseudoScalarTrans(unsigned Opcode)
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)
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.
std::optional< int64_t > getImmOrMaterializedImm(MachineOperand &Op) const
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)
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
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:343
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:433
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:440
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:456
@ 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:437
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:432
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:439
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:438
@ 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:436
@ 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:435
@ 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:434
@ 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:619
@ TI_SCRATCH_RSRC_DWORD3
Definition AMDGPU.h:621
@ TI_SCRATCH_RSRC_DWORD0
Definition AMDGPU.h:618
@ TI_SCRATCH_RSRC_DWORD2
Definition AMDGPU.h:620
@ TI_CONSTDATA_START
Definition AMDGPU.h:617
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:344
constexpr bool isSDWA(const T &...O)
Definition SIDefines.h:253
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:578
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:547
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:332
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:395
@ 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
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:573
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 uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
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.