LLVM 24.0.0git
SIInstrInfo.cpp
Go to the documentation of this file.
1//===- SIInstrInfo.cpp - SI Instruction Information ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// SI Implementation of TargetInstrInfo.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SIInstrInfo.h"
15#include "AMDGPU.h"
16#include "AMDGPUInstrInfo.h"
17#include "AMDGPULaneMaskUtils.h"
18#include "GCNHazardRecognizer.h"
19#include "GCNSubtarget.h"
22#include "llvm/ADT/STLExtras.h"
34#include "llvm/IR/IntrinsicsAMDGPU.h"
35#include "llvm/MC/MCContext.h"
38#include <tuple>
39
40using namespace llvm;
41
42#define DEBUG_TYPE "si-instr-info"
43
44#define GET_INSTRINFO_CTOR_DTOR
45#include "AMDGPUGenInstrInfo.inc"
46
47namespace llvm::AMDGPU {
48#define GET_ImageDimIntrinsicTable_IMPL
49#define GET_RsrcIntrinsics_IMPL
50#include "AMDGPUGenSearchableTables.inc"
51} // namespace llvm::AMDGPU
52
53// Must be at least 4 to be able to branch over minimum unconditional branch
54// code. This is only for making it possible to write reasonably small tests for
55// long branches.
57BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16),
58 cl::desc("Restrict range of branch instructions (DEBUG)"));
59
61 "amdgpu-fix-16-bit-physreg-copies",
62 cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"),
63 cl::init(true),
65
67 : AMDGPUGenInstrInfo(ST, RI, AMDGPU::ADJCALLSTACKUP,
68 AMDGPU::ADJCALLSTACKDOWN),
69 RI(ST), ST(ST) {
70 SchedModel.init(&ST);
71}
72
73//===----------------------------------------------------------------------===//
74// TargetInstrInfo callbacks
75//===----------------------------------------------------------------------===//
76
77static unsigned getNumOperandsNoGlue(SDNode *Node) {
78 unsigned N = Node->getNumOperands();
79 while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
80 --N;
81 return N;
82}
83
84/// Returns true if both nodes have the same value for the given
85/// operand \p Op, or if both nodes do not have this operand.
87 AMDGPU::OpName OpName) {
88 unsigned Opc0 = N0->getMachineOpcode();
89 unsigned Opc1 = N1->getMachineOpcode();
90
91 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName);
92 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName);
93
94 if (Op0Idx == -1 && Op1Idx == -1)
95 return true;
96
97
98 if ((Op0Idx == -1 && Op1Idx != -1) ||
99 (Op1Idx == -1 && Op0Idx != -1))
100 return false;
101
102 // getNamedOperandIdx returns the index for the MachineInstr's operands,
103 // which includes the result as the first operand. We are indexing into the
104 // MachineSDNode's operands, so we need to skip the result operand to get
105 // the real index.
106 --Op0Idx;
107 --Op1Idx;
108
109 return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx);
110}
111
112static bool canRemat(const MachineInstr &MI) {
113
117 return true;
118
119 if (SIInstrInfo::isSMRD(MI)) {
120 return !MI.memoperands_empty() &&
121 llvm::all_of(MI.memoperands(), [](const MachineMemOperand *MMO) {
122 return MMO->isLoad() && MMO->isInvariant();
123 });
124 }
125
126 return false;
127}
128
129// Split relocation flags for 64-bit global-address materialization into a
130// common base and the hi/lo relocation variants.
131static std::tuple<unsigned, unsigned, unsigned>
133 const MachineOperand &SrcOp) {
134 const unsigned BaseFlags = SrcOp.getTargetFlags() & ~SIInstrInfo::MO_MASK;
135 const unsigned Reloc = SrcOp.getTargetFlags() & SIInstrInfo::MO_MASK;
136
137 // Infer the relocation type from the existing flags on the global operand.
138 // The relocation type should have been determined earlier in the pipeline.
139 unsigned LoReloc, HiReloc;
140 switch (Reloc) {
144 LoReloc = SIInstrInfo::MO_REL32_LO;
145 HiReloc = SIInstrInfo::MO_REL32_HI;
146 break;
151 break;
154 // For 64-bit GOT-relative, use the 64-bit relocation.
157 break;
161 LoReloc = SIInstrInfo::MO_ABS32_LO;
162 HiReloc = SIInstrInfo::MO_ABS32_HI;
163 break;
164 default:
165 llvm_unreachable("unknown relocation type for global address");
166 break;
167 }
168
169 return {BaseFlags, LoReloc, HiReloc};
170}
171
173 const MachineInstr &MI) const {
174
175 if (canRemat(MI)) {
176 // Normally VALU use of exec would block the rematerialization, but that
177 // is OK in this case to have an implicit exec read as all VALU do.
178 // We really want all of the generic logic for this except for this.
179
180 // Another potential implicit use is mode register. The core logic of
181 // the RA will not attempt rematerialization if mode is set anywhere
182 // in the function, otherwise it is safe since mode is not changed.
183
184 // There is difference to generic method which does not allow
185 // rematerialization if there are virtual register uses. We allow this,
186 // therefore this method includes SOP instructions as well.
187 if (!MI.hasImplicitDef() &&
188 MI.getNumImplicitOperands() == MI.getDesc().implicit_uses().size() &&
189 !MI.mayRaiseFPException())
190 return true;
191 }
192
193 // Everything below copied from TargetInstrInfo::isReMaterializableImpl. The
194 // only difference is that we allow operations that perform read-modify-write
195 // on sub-registers.
196
197 // Remat clients assume operand 0 is the defined register.
198 if (!MI.getNumOperands() || !MI.getOperand(0).isReg())
199 return false;
200 Register DefReg = MI.getOperand(0).getReg();
201
202 const MachineFunction &MF = *MI.getMF();
203
204 // A load from a fixed stack slot can be rematerialized. This may be
205 // redundant with subsequent checks, but it's target-independent,
206 // simple, and a common case.
207 int FrameIdx = 0;
208 if (isLoadFromStackSlot(MI, FrameIdx) &&
210 return true;
211
212 // Avoid instructions obviously unsafe for remat.
213 if (MI.isNotDuplicable() || MI.mayStore() || MI.mayRaiseFPException() ||
214 MI.hasUnmodeledSideEffects())
215 return false;
216
217 // Don't remat inline asm. We have no idea how expensive it is
218 // even if it's side effect free.
219 if (MI.isInlineAsm())
220 return false;
221
222 // Avoid instructions which load from potentially varying memory.
223 if (MI.mayLoad() && !MI.isDereferenceableInvariantLoad())
224 return false;
225
226 const MachineRegisterInfo &MRI = MF.getRegInfo();
227
228 // If any of the registers accessed are non-constant, conservatively assume
229 // the instruction is not rematerializable.
230 for (const MachineOperand &MO : MI.operands()) {
231 if (!MO.isReg())
232 continue;
233 Register Reg = MO.getReg();
234 if (Reg == 0)
235 continue;
236
237 // Check for a well-behaved physical register.
238 if (Reg.isPhysical()) {
239 if (MO.isUse()) {
240 // If the physreg has no defs anywhere, it's just an ambient register
241 // and we can freely move its uses. Alternatively, if it's allocatable,
242 // it could get allocated to something with a def during allocation.
243 if (!MRI.isConstantPhysReg(Reg))
244 return false;
245 } else {
246 // A physreg def. We can't remat it.
247 return false;
248 }
249 continue;
250 }
251
252 // Only allow one virtual-register def. There may be multiple defs of the
253 // same virtual register, though.
254 if (MO.isDef() && Reg != DefReg)
255 return false;
256 }
257
258 return true;
259}
260
261// Returns true if the result of a VALU instruction depends on exec.
262bool SIInstrInfo::resultDependsOnExec(const MachineInstr &MI) const {
263 assert(isVALU(MI, /*AllowLDSDMA=*/true));
264
265 // If it is convergent it depends on EXEC.
266 if (MI.isConvergent())
267 return true;
268
269 // If it defines an SGPR it depends on EXEC, unless it's dead.
270 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
271 for (const MachineOperand &Def : MI.defs()) {
272 if (Def.isDead())
273 continue;
274
275 Register Reg = Def.getReg();
276 if (Reg && RI.isSGPRReg(MRI, Reg))
277 return true;
278 }
279
280 return false;
281}
282
283bool SIInstrInfo::isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const {
284 const MachineOperand &MO = MI.getOperand(OpIdx);
285 // Any implicit use of exec by VALU is not a real register read.
286 return MO.getReg() == AMDGPU::EXEC && MO.isImplicit() &&
287 isVALU(MI, /*AllowLDSDMA=*/true) && !resultDependsOnExec(MI);
288}
289
291 MachineBasicBlock *SuccToSinkTo,
292 MachineCycleInfo *CI) const {
293 // Allow sinking if MI edits lane mask (divergent i1 in sgpr).
294 if (MI.getOpcode() == AMDGPU::SI_IF_BREAK)
295 return true;
296
297 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
298 // Check if sinking of MI would create temporal divergent use.
299 for (auto Op : MI.uses()) {
300 if (Op.isReg() && Op.getReg().isVirtual() &&
301 RI.isSGPRClass(MRI.getRegClass(Op.getReg()))) {
302 MachineInstr *SgprDef = MRI.getVRegDef(Op.getReg());
303 if (!SgprDef)
304 continue;
305
306 // SgprDef defined inside cycle
307 CycleRef FromCycle = CI->getCycle(SgprDef->getParent());
308 if (!FromCycle)
309 continue;
310
311 CycleRef ToCycle = CI->getCycle(SuccToSinkTo);
312 // Check if there is a FromCycle that contains SgprDef's basic block but
313 // does not contain SuccToSinkTo and also has divergent exit condition.
314 while (FromCycle && !(ToCycle && CI->contains(FromCycle, ToCycle))) {
316 CI->getExitingBlocks(FromCycle, ExitingBlocks);
317
318 // FromCycle has divergent exit condition.
319 for (MachineBasicBlock *ExitingBlock : ExitingBlocks) {
320 if (hasDivergentBranch(ExitingBlock))
321 return false;
322 }
323
324 FromCycle = CI->getParentCycle(FromCycle);
325 }
326 }
327 }
328
329 return true;
330}
331
333 int64_t &Offset0,
334 int64_t &Offset1) const {
335 if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode())
336 return false;
337
338 unsigned Opc0 = Load0->getMachineOpcode();
339 unsigned Opc1 = Load1->getMachineOpcode();
340
341 // Make sure both are actually loads.
342 if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad())
343 return false;
344
345 // A mayLoad instruction without a def is not a load. Likely a prefetch.
346 if (!get(Opc0).getNumDefs() || !get(Opc1).getNumDefs())
347 return false;
348
349 if (isDS(Opc0) && isDS(Opc1)) {
350
351 // FIXME: Handle this case:
352 if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1))
353 return false;
354
355 // Check base reg.
356 if (Load0->getOperand(0) != Load1->getOperand(0))
357 return false;
358
359 // Skip read2 / write2 variants for simplicity.
360 // TODO: We should report true if the used offsets are adjacent (excluded
361 // st64 versions).
362 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
363 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
364 if (Offset0Idx == -1 || Offset1Idx == -1)
365 return false;
366
367 // XXX - be careful of dataless loads
368 // getNamedOperandIdx returns the index for MachineInstrs. Since they
369 // include the output in the operand list, but SDNodes don't, we need to
370 // subtract the index by one.
371 Offset0Idx -= get(Opc0).NumDefs;
372 Offset1Idx -= get(Opc1).NumDefs;
373 Offset0 = Load0->getConstantOperandVal(Offset0Idx);
374 Offset1 = Load1->getConstantOperandVal(Offset1Idx);
375 return true;
376 }
377
378 if (isSMRD(Opc0) && isSMRD(Opc1)) {
379 // Skip time and cache invalidation instructions.
380 if (!AMDGPU::hasNamedOperand(Opc0, AMDGPU::OpName::sbase) ||
381 !AMDGPU::hasNamedOperand(Opc1, AMDGPU::OpName::sbase))
382 return false;
383
384 unsigned NumOps = getNumOperandsNoGlue(Load0);
385 if (NumOps != getNumOperandsNoGlue(Load1))
386 return false;
387
388 // Check base reg.
389 if (Load0->getOperand(0) != Load1->getOperand(0))
390 return false;
391
392 // Match register offsets, if both register and immediate offsets present.
393 assert(NumOps == 4 || NumOps == 5);
394 if (NumOps == 5 && Load0->getOperand(1) != Load1->getOperand(1))
395 return false;
396
397 const ConstantSDNode *Load0Offset =
399 const ConstantSDNode *Load1Offset =
401
402 if (!Load0Offset || !Load1Offset)
403 return false;
404
405 Offset0 = Load0Offset->getZExtValue();
406 Offset1 = Load1Offset->getZExtValue();
407 return true;
408 }
409
410 // MUBUF and MTBUF can access the same addresses.
411 if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) {
412
413 // MUBUF and MTBUF have vaddr at different indices.
414 if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) ||
415 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) ||
416 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc))
417 return false;
418
419 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
420 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
421
422 if (OffIdx0 == -1 || OffIdx1 == -1)
423 return false;
424
425 // getNamedOperandIdx returns the index for MachineInstrs. Since they
426 // include the output in the operand list, but SDNodes don't, we need to
427 // subtract the index by one.
428 OffIdx0 -= get(Opc0).NumDefs;
429 OffIdx1 -= get(Opc1).NumDefs;
430
431 SDValue Off0 = Load0->getOperand(OffIdx0);
432 SDValue Off1 = Load1->getOperand(OffIdx1);
433
434 // The offset might be a FrameIndexSDNode.
435 if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1))
436 return false;
437
438 Offset0 = Off0->getAsZExtVal();
439 Offset1 = Off1->getAsZExtVal();
440 return true;
441 }
442
443 return false;
444}
445
446static bool isStride64(unsigned Opc) {
447 switch (Opc) {
448 case AMDGPU::DS_READ2ST64_B32:
449 case AMDGPU::DS_READ2ST64_B64:
450 case AMDGPU::DS_WRITE2ST64_B32:
451 case AMDGPU::DS_WRITE2ST64_B64:
452 return true;
453 default:
454 return false;
455 }
456}
457
460 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
461 const TargetRegisterInfo *TRI) const {
462 if (!LdSt.mayLoadOrStore())
463 return false;
464
465 unsigned Opc = LdSt.getOpcode();
466 OffsetIsScalable = false;
467 const MachineOperand *BaseOp, *OffsetOp;
468 int DataOpIdx;
469
470 if (isDS(LdSt)) {
471 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr);
472 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
473 if (OffsetOp) {
474 // Normal, single offset LDS instruction.
475 if (!BaseOp) {
476 // DS_CONSUME/DS_APPEND use M0 for the base address.
477 // TODO: find the implicit use operand for M0 and use that as BaseOp?
478 return false;
479 }
480 BaseOps.push_back(BaseOp);
481 Offset = OffsetOp->getImm();
482 // Get appropriate operand, and compute width accordingly.
483 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
484 if (DataOpIdx == -1)
485 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
486 if (Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
487 Width = LocationSize::precise(64);
488 else
489 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
490 } else {
491 // The 2 offset instructions use offset0 and offset1 instead. We can treat
492 // these as a load with a single offset if the 2 offsets are consecutive.
493 // We will use this for some partially aligned loads.
494 const MachineOperand *Offset0Op =
495 getNamedOperand(LdSt, AMDGPU::OpName::offset0);
496 const MachineOperand *Offset1Op =
497 getNamedOperand(LdSt, AMDGPU::OpName::offset1);
498
499 unsigned Offset0 = Offset0Op->getImm() & 0xff;
500 unsigned Offset1 = Offset1Op->getImm() & 0xff;
501 if (Offset0 + 1 != Offset1)
502 return false;
503
504 // Each of these offsets is in element sized units, so we need to convert
505 // to bytes of the individual reads.
506
507 unsigned EltSize;
508 if (LdSt.mayLoad())
509 EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16;
510 else {
511 assert(LdSt.mayStore());
512 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
513 EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8;
514 }
515
516 if (isStride64(Opc))
517 EltSize *= 64;
518
519 BaseOps.push_back(BaseOp);
520 Offset = EltSize * Offset0;
521 // Get appropriate operand(s), and compute width accordingly.
522 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
523 if (DataOpIdx == -1) {
524 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
525 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
526 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
527 Width = LocationSize::precise(
528 Width.getValue() + TypeSize::getFixed(getOpSize(LdSt, DataOpIdx)));
529 } else {
530 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
531 }
532 }
533 return true;
534 }
535
536 if (isMUBUF(LdSt) || isMTBUF(LdSt)) {
537 const MachineOperand *RSrc = getNamedOperand(LdSt, AMDGPU::OpName::srsrc);
538 if (!RSrc) // e.g. BUFFER_WBINVL1_VOL
539 return false;
540 BaseOps.push_back(RSrc);
541 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
542 if (BaseOp && !BaseOp->isFI())
543 BaseOps.push_back(BaseOp);
544 const MachineOperand *OffsetImm =
545 getNamedOperand(LdSt, AMDGPU::OpName::offset);
546 Offset = OffsetImm->getImm();
547 const MachineOperand *SOffset =
548 getNamedOperand(LdSt, AMDGPU::OpName::soffset);
549 if (SOffset) {
550 if (SOffset->isReg())
551 BaseOps.push_back(SOffset);
552 else
553 Offset += SOffset->getImm();
554 }
555 // Get appropriate operand, and compute width accordingly.
556 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
557 if (DataOpIdx == -1)
558 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
559 if (DataOpIdx == -1) // LDS DMA
560 return false;
561 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
562 return true;
563 }
564
565 if (isImage(LdSt)) {
566 auto RsrcOpName =
567 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
568 int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RsrcOpName);
569 BaseOps.push_back(&LdSt.getOperand(SRsrcIdx));
570 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
571 if (VAddr0Idx >= 0) {
572 // GFX10 possible NSA encoding.
573 for (int I = VAddr0Idx; I < SRsrcIdx; ++I)
574 BaseOps.push_back(&LdSt.getOperand(I));
575 } else {
576 BaseOps.push_back(getNamedOperand(LdSt, AMDGPU::OpName::vaddr));
577 }
578 Offset = 0;
579 // Get appropriate operand, and compute width accordingly.
580 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
581 if (DataOpIdx == -1)
582 return false; // no return sampler
583 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
584 return true;
585 }
586
587 if (isSMRD(LdSt)) {
588 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::sbase);
589 if (!BaseOp) // e.g. S_MEMTIME
590 return false;
591 BaseOps.push_back(BaseOp);
592 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
593 Offset = OffsetOp ? OffsetOp->getImm() : 0;
594 // Get appropriate operand, and compute width accordingly.
595 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
596 if (DataOpIdx == -1)
597 return false;
598 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
599 return true;
600 }
601
602 if (isFLAT(LdSt)) {
603 // Instructions have either vaddr or saddr or both or none.
604 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
605 if (BaseOp)
606 BaseOps.push_back(BaseOp);
607 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr);
608 if (BaseOp)
609 BaseOps.push_back(BaseOp);
610 Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm();
611 // Get appropriate operand, and compute width accordingly.
612 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
613 if (DataOpIdx == -1)
614 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
615 if (DataOpIdx == -1) // LDS DMA
616 return false;
617 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
618 return true;
619 }
620
621 return false;
622}
623
624static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
626 const MachineInstr &MI2,
628 // Only examine the first "base" operand of each instruction, on the
629 // assumption that it represents the real base address of the memory access.
630 // Other operands are typically offsets or indices from this base address.
631 if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
632 return true;
633
634 if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
635 return false;
636
637 auto *MO1 = *MI1.memoperands_begin();
638 auto *MO2 = *MI2.memoperands_begin();
639 if (MO1->getAddrSpace() != MO2->getAddrSpace())
640 return false;
641
642 const auto *Base1 = MO1->getValue();
643 const auto *Base2 = MO2->getValue();
644 if (!Base1 || !Base2)
645 return false;
646 Base1 = getUnderlyingObject(Base1);
647 Base2 = getUnderlyingObject(Base2);
648
649 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
650 return false;
651
652 return Base1 == Base2;
653}
654
656 int64_t Offset1, bool OffsetIsScalable1,
658 int64_t Offset2, bool OffsetIsScalable2,
659 unsigned ClusterSize,
660 unsigned NumBytes) const {
661 // If the mem ops (to be clustered) do not have the same base ptr, then they
662 // should not be clustered
663 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;
664 if (!BaseOps1.empty() && !BaseOps2.empty()) {
665 const MachineInstr &FirstLdSt = *BaseOps1.front()->getParent();
666 const MachineInstr &SecondLdSt = *BaseOps2.front()->getParent();
667 if (!memOpsHaveSameBasePtr(FirstLdSt, BaseOps1, SecondLdSt, BaseOps2))
668 return false;
669
670 const SIMachineFunctionInfo *MFI =
671 FirstLdSt.getMF()->getInfo<SIMachineFunctionInfo>();
672 MaxMemoryClusterDWords = MFI->getMaxMemoryClusterDWords();
673 } else if (!BaseOps1.empty() || !BaseOps2.empty()) {
674 // If only one base op is empty, they do not have the same base ptr
675 return false;
676 }
677
678 // In order to avoid register pressure, on an average, the number of DWORDS
679 // loaded together by all clustered mem ops should not exceed
680 // MaxMemoryClusterDWords. This is an empirical value based on certain
681 // observations and performance related experiments.
682 // The good thing about this heuristic is - it avoids clustering of too many
683 // sub-word loads, and also avoids clustering of wide loads. Below is the
684 // brief summary of how the heuristic behaves for various `LoadSize` when
685 // MaxMemoryClusterDWords is 8.
686 //
687 // (1) 1 <= LoadSize <= 4: cluster at max 8 mem ops
688 // (2) 5 <= LoadSize <= 8: cluster at max 4 mem ops
689 // (3) 9 <= LoadSize <= 12: cluster at max 2 mem ops
690 // (4) 13 <= LoadSize <= 16: cluster at max 2 mem ops
691 // (5) LoadSize >= 17: do not cluster
692 const unsigned LoadSize = NumBytes / ClusterSize;
693 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
694 return NumDWords <= MaxMemoryClusterDWords;
695}
696
697// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
698// the first 16 loads will be interleaved with the stores, and the next 16 will
699// be clustered as expected. It should really split into 2 16 store batches.
700//
701// Loads are clustered until this returns false, rather than trying to schedule
702// groups of stores. This also means we have to deal with saying different
703// address space loads should be clustered, and ones which might cause bank
704// conflicts.
705//
706// This might be deprecated so it might not be worth that much effort to fix.
708 int64_t Offset0, int64_t Offset1,
709 unsigned NumLoads) const {
710 assert(Offset1 > Offset0 &&
711 "Second offset should be larger than first offset!");
712 // If we have less than 16 loads in a row, and the offsets are within 64
713 // bytes, then schedule together.
714
715 // A cacheline is 64 bytes (for global memory).
716 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
717}
718
721 const DebugLoc &DL, MCRegister DestReg,
722 MCRegister SrcReg, bool KillSrc,
723 const char *Msg = "illegal VGPR to SGPR copy") {
724 MachineFunction *MF = MBB.getParent();
725
728
729 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg)
730 .addReg(SrcReg, getKillRegState(KillSrc));
731}
732
733/// Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908. It is not
734/// possible to have a direct copy in these cases on GFX908, so an intermediate
735/// VGPR copy is required.
738 const DebugLoc &DL, MCRegister DestReg,
739 MCRegister SrcReg, bool KillSrc,
740 RegScavenger &RS, bool RegsOverlap,
741 Register ImpUseSuperReg = Register()) {
742 assert((TII.getSubtarget().hasMAIInsts() &&
743 !TII.getSubtarget().hasGFX90AInsts()) &&
744 "Expected GFX908 subtarget.");
745
746 assert((AMDGPU::SReg_32RegClass.contains(SrcReg) ||
747 AMDGPU::AGPR_32RegClass.contains(SrcReg)) &&
748 "Source register of the copy should be either an SGPR or an AGPR.");
749
750 assert(AMDGPU::AGPR_32RegClass.contains(DestReg) &&
751 "Destination register of the copy should be an AGPR.");
752
753 const SIRegisterInfo &RI = TII.getRegisterInfo();
754
755 // First try to find defining accvgpr_write to avoid temporary registers.
756 // In the case of copies of overlapping AGPRs, we conservatively do not
757 // reuse previous accvgpr_writes. Otherwise, we may incorrectly pick up
758 // an accvgpr_write used for this same copy due to implicit-defs
759 if (!RegsOverlap) {
760 for (auto Def = MI, E = MBB.begin(); Def != E; ) {
761 --Def;
762
763 if (!Def->modifiesRegister(SrcReg, &RI))
764 continue;
765
766 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
767 Def->getOperand(0).getReg() != SrcReg)
768 break;
769
770 MachineOperand &DefOp = Def->getOperand(1);
771 assert(DefOp.isReg() || DefOp.isImm());
772
773 if (DefOp.isReg()) {
774 bool SafeToPropagate = true;
775 // Check that register source operand is not clobbered before MI.
776 // Immediate operands are always safe to propagate.
777 for (auto I = Def; I != MI && SafeToPropagate; ++I)
778 if (I->modifiesRegister(DefOp.getReg(), &RI))
779 SafeToPropagate = false;
780
781 if (!SafeToPropagate)
782 break;
783
784 for (auto I = Def; I != MI; ++I)
785 I->clearRegisterKills(DefOp.getReg(), &RI);
786 }
787
788 MachineInstrBuilder Builder =
789 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64),
790 DestReg)
791 .add(DefOp);
792
793 if (ImpUseSuperReg) {
794 Builder.addReg(ImpUseSuperReg,
796 }
797
798 return;
799 }
800 }
801
802 RS.enterBasicBlockEnd(MBB);
803 RS.backward(std::next(MI));
804
805 // Ideally we want to have three registers for a long reg_sequence copy
806 // to hide 2 waitstates between v_mov_b32 and accvgpr_write.
807 unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass,
808 *MBB.getParent());
809
810 // Registers in the sequence are allocated contiguously so we can just
811 // use register number to pick one of three round-robin temps.
812 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
813 Register Tmp =
814 MBB.getParent()->getInfo<SIMachineFunctionInfo>()->getVGPRForAGPRCopy();
815 assert(MBB.getParent()->getRegInfo().isReserved(Tmp) &&
816 "VGPR used for an intermediate copy should have been reserved.");
817
818 // Only loop through if there are any free registers left. We don't want to
819 // spill.
820 while (RegNo--) {
821 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI,
822 /* RestoreAfter */ false, 0,
823 /* AllowSpill */ false);
824 if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs)
825 break;
826 Tmp = Tmp2;
827 RS.setRegUsed(Tmp);
828 }
829
830 // Insert copy to temporary VGPR.
831 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
832 if (AMDGPU::AGPR_32RegClass.contains(SrcReg)) {
833 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
834 } else {
835 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
836 }
837
838 MachineInstrBuilder UseBuilder = BuildMI(MBB, MI, DL, TII.get(TmpCopyOp), Tmp)
839 .addReg(SrcReg, getKillRegState(KillSrc));
840 if (ImpUseSuperReg) {
841 UseBuilder.addReg(ImpUseSuperReg,
843 }
844
845 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
846 .addReg(Tmp, RegState::Kill);
847}
848
851 MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
852 const TargetRegisterClass *RC, bool Forward) {
853 const SIRegisterInfo &RI = TII.getRegisterInfo();
854 ArrayRef<int16_t> BaseIndices = RI.getRegSplitParts(RC, 4);
856 MachineInstr *FirstMI = nullptr, *LastMI = nullptr;
857
858 for (unsigned Idx = 0; Idx < BaseIndices.size(); ++Idx) {
859 int16_t SubIdx = BaseIndices[Idx];
860 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
861 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
862 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
863 unsigned Opcode = AMDGPU::S_MOV_B32;
864
865 // Is SGPR aligned? If so try to combine with next.
866 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
867 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
868 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.size())) {
869 // Can use SGPR64 copy
870 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
871 SubIdx = RI.getSubRegFromChannel(Channel, 2);
872 DestSubReg = RI.getSubReg(DestReg, SubIdx);
873 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
874 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
875 Opcode = AMDGPU::S_MOV_B64;
876 Idx++;
877 }
878
879 LastMI = BuildMI(MBB, I, DL, TII.get(Opcode), DestSubReg)
880 .addReg(SrcSubReg)
881 .addReg(SrcReg, RegState::Implicit);
882
883 if (!FirstMI)
884 FirstMI = LastMI;
885
886 if (!Forward)
887 I--;
888 }
889
890 assert(FirstMI && LastMI);
891 if (!Forward)
892 std::swap(FirstMI, LastMI);
893
894 if (KillSrc)
895 LastMI->addRegisterKilled(SrcReg, &RI);
896}
897
900 const DebugLoc &DL, Register DestReg,
901 Register SrcReg, bool KillSrc, bool RenamableDest,
902 bool RenamableSrc) const {
903 const TargetRegisterClass *RC = RI.getPhysRegBaseClass(DestReg);
904 unsigned Size = RI.getRegSizeInBits(*RC);
905 const TargetRegisterClass *SrcRC = RI.getPhysRegBaseClass(SrcReg);
906 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
907
908 // The rest of copyPhysReg assumes Src and Dst size are the same size.
909 // TODO-GFX11_16BIT If all true 16 bit instruction patterns are completed can
910 // we remove Fix16BitCopies and this code block?
911 if (Fix16BitCopies) {
912 if (((Size == 16) != (SrcSize == 16))) {
913 // Non-VGPR Src and Dst will later be expanded back to 32 bits.
914 assert(ST.useRealTrue16Insts());
915 Register &RegToFix = (Size == 32) ? DestReg : SrcReg;
916 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
917 RegToFix = SubReg;
918
919 if (DestReg == SrcReg) {
920 // Identity copy. Insert empty bundle since ExpandPostRA expects an
921 // instruction here.
922 BuildMI(MBB, MI, DL, get(AMDGPU::BUNDLE));
923 return;
924 }
925 RC = RI.getPhysRegBaseClass(DestReg);
926 Size = RI.getRegSizeInBits(*RC);
927 SrcRC = RI.getPhysRegBaseClass(SrcReg);
928 SrcSize = RI.getRegSizeInBits(*SrcRC);
929 }
930 }
931
932 if (RC == &AMDGPU::VGPR_32RegClass) {
933 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
934 AMDGPU::SReg_32RegClass.contains(SrcReg) ||
935 AMDGPU::AGPR_32RegClass.contains(SrcReg));
936 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
937 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
938 BuildMI(MBB, MI, DL, get(Opc), DestReg)
939 .addReg(SrcReg, getKillRegState(KillSrc));
940 return;
941 }
942
943 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
944 RC == &AMDGPU::SReg_32RegClass) {
945 if (SrcReg == AMDGPU::SCC) {
946 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg)
947 .addImm(1)
948 .addImm(0);
949 return;
950 }
951
952 if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) {
953 if (DestReg == AMDGPU::VCC_LO) {
954 // FIXME: Hack until VReg_1 removed.
955 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
956 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
957 .addImm(0)
958 .addReg(SrcReg, getKillRegState(KillSrc));
959 return;
960 }
961
962 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
963 return;
964 }
965
966 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
967 .addReg(SrcReg, getKillRegState(KillSrc));
968 return;
969 }
970
971 if (RC == &AMDGPU::SReg_64RegClass) {
972 if (SrcReg == AMDGPU::SCC) {
973 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B64), DestReg)
974 .addImm(1)
975 .addImm(0);
976 return;
977 }
978
979 if (!AMDGPU::SReg_64_EncodableRegClass.contains(SrcReg)) {
980 if (DestReg == AMDGPU::VCC) {
981 // FIXME: Hack until VReg_1 removed.
982 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
983 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
984 .addImm(0)
985 .addReg(SrcReg, getKillRegState(KillSrc));
986 return;
987 }
988
989 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
990 return;
991 }
992
993 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
994 .addReg(SrcReg, getKillRegState(KillSrc));
995 return;
996 }
997
998 if (DestReg == AMDGPU::SCC) {
999 // Copying 64-bit or 32-bit sources to SCC barely makes sense,
1000 // but SelectionDAG emits such copies for i1 sources.
1001 if (AMDGPU::SReg_64RegClass.contains(SrcReg)) {
1002 // This copy can only be produced by patterns
1003 // with explicit SCC, which are known to be enabled
1004 // only for subtargets with S_CMP_LG_U64 present.
1005 assert(ST.hasScalarCompareEq64());
1006 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U64))
1007 .addReg(SrcReg, getKillRegState(KillSrc))
1008 .addImm(0);
1009 } else {
1010 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
1011 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32))
1012 .addReg(SrcReg, getKillRegState(KillSrc))
1013 .addImm(0);
1014 }
1015
1016 return;
1017 }
1018
1019 if (RC == &AMDGPU::AGPR_32RegClass) {
1020 if (AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
1021 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1022 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
1023 .addReg(SrcReg, getKillRegState(KillSrc));
1024 return;
1025 }
1026
1027 if (AMDGPU::AGPR_32RegClass.contains(SrcReg) && ST.hasGFX90AInsts()) {
1028 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_MOV_B32), DestReg)
1029 .addReg(SrcReg, getKillRegState(KillSrc));
1030 return;
1031 }
1032
1033 // FIXME: Pass should maintain scavenger to avoid scan through the block on
1034 // every AGPR spill.
1035 RegScavenger RS;
1036 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1037 indirectCopyToAGPR(*this, MBB, MI, DL, DestReg, SrcReg, KillSrc, RS, Overlap);
1038 return;
1039 }
1040
1041 if (Size == 16) {
1042 assert(AMDGPU::VGPR_16RegClass.contains(SrcReg) ||
1043 AMDGPU::SReg_LO16RegClass.contains(SrcReg) ||
1044 AMDGPU::AGPR_LO16RegClass.contains(SrcReg));
1045
1046 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1047 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1048 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1049 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1050 bool DstLow = !AMDGPU::isHi16Reg(DestReg, RI);
1051 bool SrcLow = !AMDGPU::isHi16Reg(SrcReg, RI);
1052 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1053 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1054
1055 if (IsSGPRDst) {
1056 if (!IsSGPRSrc) {
1057 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1058 return;
1059 }
1060
1061 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), NewDestReg)
1062 .addReg(NewSrcReg, getKillRegState(KillSrc));
1063 return;
1064 }
1065
1066 if (IsAGPRDst || IsAGPRSrc) {
1067 if (!DstLow || !SrcLow) {
1068 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1069 "Cannot use hi16 subreg with an AGPR!");
1070 }
1071
1072 copyPhysReg(MBB, MI, DL, NewDestReg, NewSrcReg, KillSrc);
1073 return;
1074 }
1075
1076 if (ST.useRealTrue16Insts()) {
1077 if (IsSGPRSrc) {
1078 assert(SrcLow);
1079 SrcReg = NewSrcReg;
1080 }
1081 // Use the smaller instruction encoding if possible.
1082 if (AMDGPU::VGPR_16_Lo128RegClass.contains(DestReg) &&
1083 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.contains(SrcReg))) {
1084 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e32), DestReg)
1085 .addReg(SrcReg);
1086 } else {
1087 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e64), DestReg)
1088 .addImm(0) // src0_modifiers
1089 .addReg(SrcReg)
1090 .addImm(0); // op_sel
1091 }
1092 return;
1093 }
1094
1095 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1096 if (!DstLow || !SrcLow) {
1097 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1098 "Cannot use hi16 subreg on VI!");
1099 }
1100
1101 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), NewDestReg)
1102 .addReg(NewSrcReg, getKillRegState(KillSrc));
1103 return;
1104 }
1105
1106 auto MIB = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_sdwa), NewDestReg)
1107 .addImm(0) // src0_modifiers
1108 .addReg(NewSrcReg)
1109 .addImm(0) // clamp
1116 // First implicit operand is $exec.
1117 MIB->tieOperands(0, MIB->getNumOperands() - 1);
1118 return;
1119 }
1120
1121 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1122 if (ST.hasVMovB64Inst()) {
1123 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_e32), DestReg)
1124 .addReg(SrcReg, getKillRegState(KillSrc));
1125 return;
1126 }
1127 if (ST.hasPkMovB32()) {
1128 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestReg)
1130 .addReg(SrcReg)
1132 .addReg(SrcReg)
1133 .addImm(0) // op_sel_lo
1134 .addImm(0) // op_sel_hi
1135 .addImm(0) // neg_lo
1136 .addImm(0) // neg_hi
1137 .addImm(0) // clamp
1138 .addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
1139 return;
1140 }
1141 }
1142
1143 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1144 if (RI.isSGPRClass(RC)) {
1145 if (!RI.isSGPRClass(SrcRC)) {
1146 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1147 return;
1148 }
1149 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1150 expandSGPRCopy(*this, MBB, MI, DL, DestReg, SrcReg, CanKillSuperReg, RC,
1151 Forward);
1152 return;
1153 }
1154
1155 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1156 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1157 if (RI.isAGPRClass(RC)) {
1158 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1159 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1160 else if (RI.hasVGPRs(SrcRC) ||
1161 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1162 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1163 else
1164 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1165 } else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1166 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1167 } else if (RI.isVGPRClass(RC)) {
1168 if (ST.hasVMovB64Inst())
1169 WideOpcode = AMDGPU::V_MOV_B64_e32;
1170 else if (ST.hasPkMovB32())
1171 WideOpcode = AMDGPU::V_PK_MOV_B32;
1172 }
1173
1174 const TargetRegisterClass *WideRC{};
1175 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1176 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1177 WideRC = getRegClass(get(WideOpcode), SrcOp);
1178 }
1179
1180 // If there is an overlap, we can't kill the super-register on the last
1181 // instruction, since it will also kill the components made live by this def.
1182 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1183 const bool CanKillSuperReg = KillSrc && !Overlap;
1184
1185 // For the cases where we need an intermediate instruction/temporary register
1186 // (destination is an AGPR), we need a scavenger.
1187 //
1188 // FIXME: The pass should maintain this for us so we don't have to re-scan the
1189 // whole block for every handled copy.
1190 std::unique_ptr<RegScavenger> RS;
1191 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1192 RS = std::make_unique<RegScavenger>();
1193
1194 ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, 4);
1195
1196 for (unsigned Idx{}; Idx < SubIndices.size();) {
1197 unsigned NumRegs = 1;
1198 unsigned ThisOpcode = Opcode;
1199 unsigned SubIdx =
1200 Forward ? SubIndices[Idx] : SubIndices[SubIndices.size() - Idx - 1];
1201
1202 if (WideRC && Idx + 1 < SubIndices.size()) {
1203 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1204 if (!Forward)
1205 --Channel;
1206
1207 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1208 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1209 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1210
1211 if (WideDst && WideSrc && WideRC->contains(WideDst) &&
1212 WideRC->contains(WideSrc)) {
1213 SubIdx = WideSubIdx;
1214 NumRegs = 2;
1215 ThisOpcode = WideOpcode;
1216 }
1217 }
1218
1219 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1220 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1221 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
1222
1223 Idx += NumRegs;
1224 bool UseKill = CanKillSuperReg && Idx == SubIndices.size();
1225
1226 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1227 Register ImpUseSuper = SrcReg;
1228 indirectCopyToAGPR(*this, MBB, MI, DL, DestSubReg, SrcSubReg, UseKill,
1229 *RS, Overlap, ImpUseSuper);
1230 } else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1231 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestSubReg)
1233 .addReg(SrcSubReg)
1235 .addReg(SrcSubReg)
1236 .addImm(0) // op_sel_lo
1237 .addImm(0) // op_sel_hi
1238 .addImm(0) // neg_lo
1239 .addImm(0) // neg_hi
1240 .addImm(0) // clamp
1241 .addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1242 } else {
1243 MachineInstrBuilder Builder =
1244 BuildMI(MBB, MI, DL, get(ThisOpcode), DestSubReg).addReg(SrcSubReg);
1245
1246 Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1247 }
1248 }
1249}
1250
1251int SIInstrInfo::commuteOpcode(unsigned Opcode) const {
1252 int32_t NewOpc;
1253
1254 // Try to map original to commuted opcode
1255 NewOpc = AMDGPU::getCommuteRev(Opcode);
1256 if (NewOpc != -1)
1257 // Check if the commuted (REV) opcode exists on the target.
1258 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1259
1260 // Try to map commuted to original opcode
1261 NewOpc = AMDGPU::getCommuteOrig(Opcode);
1262 if (NewOpc != -1)
1263 // Check if the original (non-REV) opcode exists on the target.
1264 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1265
1266 return Opcode;
1267}
1268
1270 const Register Reg,
1271 int64_t &ImmVal) const {
1272 switch (MI.getOpcode()) {
1273 case AMDGPU::V_MOV_B32_e32:
1274 case AMDGPU::S_MOV_B32:
1275 case AMDGPU::S_MOVK_I32:
1276 case AMDGPU::S_MOV_B64:
1277 case AMDGPU::V_MOV_B64_e32:
1278 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1279 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1280 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1281 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1282 case AMDGPU::V_MOV_B64_PSEUDO:
1283 case AMDGPU::V_MOV_B16_t16_e32: {
1284 const MachineOperand &Src0 = MI.getOperand(1);
1285 if (Src0.isImm()) {
1286 ImmVal = Src0.getImm();
1287 return MI.getOperand(0).getReg() == Reg;
1288 }
1289
1290 return false;
1291 }
1292 case AMDGPU::V_MOV_B16_t16_e64: {
1293 const MachineOperand &Src0 = MI.getOperand(2);
1294 if (Src0.isImm() && !MI.getOperand(1).getImm()) {
1295 ImmVal = Src0.getImm();
1296 return MI.getOperand(0).getReg() == Reg;
1297 }
1298
1299 return false;
1300 }
1301 case AMDGPU::S_BREV_B32:
1302 case AMDGPU::V_BFREV_B32_e32:
1303 case AMDGPU::V_BFREV_B32_e64: {
1304 const MachineOperand &Src0 = MI.getOperand(1);
1305 if (Src0.isImm()) {
1306 ImmVal = static_cast<int64_t>(reverseBits<int32_t>(Src0.getImm()));
1307 return MI.getOperand(0).getReg() == Reg;
1308 }
1309
1310 return false;
1311 }
1312 case AMDGPU::S_NOT_B32:
1313 case AMDGPU::V_NOT_B32_e32:
1314 case AMDGPU::V_NOT_B32_e64: {
1315 const MachineOperand &Src0 = MI.getOperand(1);
1316 if (Src0.isImm()) {
1317 ImmVal = static_cast<int64_t>(~static_cast<int32_t>(Src0.getImm()));
1318 return MI.getOperand(0).getReg() == Reg;
1319 }
1320
1321 return false;
1322 }
1323 default:
1324 return false;
1325 }
1326}
1327
1328std::optional<int64_t>
1330 const MachineOperand &Op,
1331 MachineInstr **DefMI) const {
1332 if (DefMI)
1333 *DefMI = nullptr;
1334
1335 if (Op.isImm())
1336 return Op.getImm();
1337
1338 if (!Op.isReg() || !Op.getReg().isVirtual())
1339 return std::nullopt;
1340 MachineInstr *Def = MRI.getUniqueVRegDef(Op.getReg());
1341 if (Def && Def->isMoveImmediate()) {
1342 const MachineOperand &ImmSrc = Def->getOperand(1);
1343 if (ImmSrc.isImm()) {
1344 if (DefMI)
1345 *DefMI = Def;
1346 return extractSubregFromImm(ImmSrc.getImm(), Op.getSubReg());
1347 }
1348 }
1349
1350 return std::nullopt;
1351}
1352
1353std::optional<int64_t>
1359
1361
1362 if (RI.isAGPRClass(DstRC))
1363 return AMDGPU::COPY;
1364 if (RI.getRegSizeInBits(*DstRC) == 16) {
1365 // Assume hi bits are unneeded. Only _e64 true16 instructions are legal
1366 // before RA.
1367 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1368 }
1369 if (RI.getRegSizeInBits(*DstRC) == 32)
1370 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1371 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1372 return AMDGPU::S_MOV_B64;
1373 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1374 return AMDGPU::V_MOV_B64_PSEUDO;
1375 return AMDGPU::COPY;
1376}
1377
1378const MCInstrDesc &
1380 bool IsIndirectSrc) const {
1381 if (IsIndirectSrc) {
1382 if (VecSize <= 32) // 4 bytes
1383 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1384 if (VecSize <= 64) // 8 bytes
1385 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1386 if (VecSize <= 96) // 12 bytes
1387 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1388 if (VecSize <= 128) // 16 bytes
1389 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1390 if (VecSize <= 160) // 20 bytes
1391 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1392 if (VecSize <= 192) // 24 bytes
1393 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1394 if (VecSize <= 224) // 28 bytes
1395 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1396 if (VecSize <= 256) // 32 bytes
1397 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1398 if (VecSize <= 288) // 36 bytes
1399 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1400 if (VecSize <= 320) // 40 bytes
1401 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1402 if (VecSize <= 352) // 44 bytes
1403 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1404 if (VecSize <= 384) // 48 bytes
1405 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1406 if (VecSize <= 512) // 64 bytes
1407 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1408 if (VecSize <= 1024) // 128 bytes
1409 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1410
1411 llvm_unreachable("unsupported size for IndirectRegReadGPRIDX pseudos");
1412 }
1413
1414 if (VecSize <= 32) // 4 bytes
1415 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1416 if (VecSize <= 64) // 8 bytes
1417 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1418 if (VecSize <= 96) // 12 bytes
1419 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1420 if (VecSize <= 128) // 16 bytes
1421 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1422 if (VecSize <= 160) // 20 bytes
1423 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1424 if (VecSize <= 192) // 24 bytes
1425 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1426 if (VecSize <= 224) // 28 bytes
1427 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1428 if (VecSize <= 256) // 32 bytes
1429 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1430 if (VecSize <= 288) // 36 bytes
1431 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1432 if (VecSize <= 320) // 40 bytes
1433 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1434 if (VecSize <= 352) // 44 bytes
1435 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1436 if (VecSize <= 384) // 48 bytes
1437 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1438 if (VecSize <= 512) // 64 bytes
1439 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1440 if (VecSize <= 1024) // 128 bytes
1441 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1442
1443 llvm_unreachable("unsupported size for IndirectRegWriteGPRIDX pseudos");
1444}
1445
1446static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize) {
1447 if (VecSize <= 32) // 4 bytes
1448 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1449 if (VecSize <= 64) // 8 bytes
1450 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1451 if (VecSize <= 96) // 12 bytes
1452 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1453 if (VecSize <= 128) // 16 bytes
1454 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1455 if (VecSize <= 160) // 20 bytes
1456 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1457 if (VecSize <= 192) // 24 bytes
1458 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1459 if (VecSize <= 224) // 28 bytes
1460 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1461 if (VecSize <= 256) // 32 bytes
1462 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1463 if (VecSize <= 288) // 36 bytes
1464 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1465 if (VecSize <= 320) // 40 bytes
1466 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1467 if (VecSize <= 352) // 44 bytes
1468 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1469 if (VecSize <= 384) // 48 bytes
1470 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1471 if (VecSize <= 512) // 64 bytes
1472 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1473 if (VecSize <= 1024) // 128 bytes
1474 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1475
1476 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1477}
1478
1479static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize) {
1480 if (VecSize <= 32) // 4 bytes
1481 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1482 if (VecSize <= 64) // 8 bytes
1483 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1484 if (VecSize <= 96) // 12 bytes
1485 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1486 if (VecSize <= 128) // 16 bytes
1487 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1488 if (VecSize <= 160) // 20 bytes
1489 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1490 if (VecSize <= 192) // 24 bytes
1491 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1492 if (VecSize <= 224) // 28 bytes
1493 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1494 if (VecSize <= 256) // 32 bytes
1495 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1496 if (VecSize <= 288) // 36 bytes
1497 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1498 if (VecSize <= 320) // 40 bytes
1499 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1500 if (VecSize <= 352) // 44 bytes
1501 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1502 if (VecSize <= 384) // 48 bytes
1503 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1504 if (VecSize <= 512) // 64 bytes
1505 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1506 if (VecSize <= 1024) // 128 bytes
1507 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1508
1509 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1510}
1511
1512static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize) {
1513 if (VecSize <= 64) // 8 bytes
1514 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1515 if (VecSize <= 128) // 16 bytes
1516 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1517 if (VecSize <= 256) // 32 bytes
1518 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1519 if (VecSize <= 512) // 64 bytes
1520 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1521 if (VecSize <= 1024) // 128 bytes
1522 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1523
1524 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1525}
1526
1527const MCInstrDesc &
1528SIInstrInfo::getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize,
1529 bool IsSGPR) const {
1530 if (IsSGPR) {
1531 switch (EltSize) {
1532 case 32:
1533 return get(getIndirectSGPRWriteMovRelPseudo32(VecSize));
1534 case 64:
1535 return get(getIndirectSGPRWriteMovRelPseudo64(VecSize));
1536 default:
1537 llvm_unreachable("invalid reg indexing elt size");
1538 }
1539 }
1540
1541 assert(EltSize == 32 && "invalid reg indexing elt size");
1543}
1544
1545static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1546 switch (Size) {
1547 case 4:
1548 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1549 case 8:
1550 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1551 case 12:
1552 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1553 case 16:
1554 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1555 : AMDGPU::SI_SPILL_S128_SAVE;
1556 case 20:
1557 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1558 : AMDGPU::SI_SPILL_S160_SAVE;
1559 case 24:
1560 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1561 : AMDGPU::SI_SPILL_S192_SAVE;
1562 case 28:
1563 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1564 : AMDGPU::SI_SPILL_S224_SAVE;
1565 case 32:
1566 return AMDGPU::SI_SPILL_S256_SAVE;
1567 case 36:
1568 return AMDGPU::SI_SPILL_S288_SAVE;
1569 case 40:
1570 return AMDGPU::SI_SPILL_S320_SAVE;
1571 case 44:
1572 return AMDGPU::SI_SPILL_S352_SAVE;
1573 case 48:
1574 return AMDGPU::SI_SPILL_S384_SAVE;
1575 case 64:
1576 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1577 : AMDGPU::SI_SPILL_S512_SAVE;
1578 case 128:
1579 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1580 : AMDGPU::SI_SPILL_S1024_SAVE;
1581 default:
1582 llvm_unreachable("unknown register size");
1583 }
1584}
1585
1586static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1587 switch (Size) {
1588 case 2:
1589 return AMDGPU::SI_SPILL_V16_SAVE;
1590 case 4:
1591 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1592 case 8:
1593 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1594 case 12:
1595 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1596 case 16:
1597 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1598 : AMDGPU::SI_SPILL_V128_SAVE;
1599 case 20:
1600 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1601 : AMDGPU::SI_SPILL_V160_SAVE;
1602 case 24:
1603 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1604 : AMDGPU::SI_SPILL_V192_SAVE;
1605 case 28:
1606 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1607 : AMDGPU::SI_SPILL_V224_SAVE;
1608 case 32:
1609 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1610 : AMDGPU::SI_SPILL_V256_SAVE;
1611 case 36:
1612 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1613 : AMDGPU::SI_SPILL_V288_SAVE;
1614 case 40:
1615 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1616 : AMDGPU::SI_SPILL_V320_SAVE;
1617 case 44:
1618 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1619 : AMDGPU::SI_SPILL_V352_SAVE;
1620 case 48:
1621 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1622 : AMDGPU::SI_SPILL_V384_SAVE;
1623 case 64:
1624 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1625 : AMDGPU::SI_SPILL_V512_SAVE;
1626 case 128:
1627 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1628 : AMDGPU::SI_SPILL_V1024_SAVE;
1629 default:
1630 llvm_unreachable("unknown register size");
1631 }
1632}
1633
1634static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1635 switch (Size) {
1636 case 4:
1637 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1638 : AMDGPU::SI_SPILL_AV32_SAVE;
1639 case 8:
1640 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1641 : AMDGPU::SI_SPILL_AV64_SAVE;
1642 case 12:
1643 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1644 : AMDGPU::SI_SPILL_AV96_SAVE;
1645 case 16:
1646 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1647 : AMDGPU::SI_SPILL_AV128_SAVE;
1648 case 20:
1649 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1650 : AMDGPU::SI_SPILL_AV160_SAVE;
1651 case 24:
1652 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1653 : AMDGPU::SI_SPILL_AV192_SAVE;
1654 case 28:
1655 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1656 : AMDGPU::SI_SPILL_AV224_SAVE;
1657 case 32:
1658 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1659 : AMDGPU::SI_SPILL_AV256_SAVE;
1660 case 36:
1661 return AMDGPU::SI_SPILL_AV288_SAVE;
1662 case 40:
1663 return AMDGPU::SI_SPILL_AV320_SAVE;
1664 case 44:
1665 return AMDGPU::SI_SPILL_AV352_SAVE;
1666 case 48:
1667 return AMDGPU::SI_SPILL_AV384_SAVE;
1668 case 64:
1669 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1670 : AMDGPU::SI_SPILL_AV512_SAVE;
1671 case 128:
1672 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1673 : AMDGPU::SI_SPILL_AV1024_SAVE;
1674 default:
1675 llvm_unreachable("unknown register size");
1676 }
1677}
1678
1679static unsigned getWWMRegSpillSaveOpcode(unsigned Size,
1680 bool IsVectorSuperClass) {
1681 // Currently, there is only 32-bit WWM register spills needed.
1682 if (Size != 4)
1683 llvm_unreachable("unknown wwm register spill size");
1684
1685 if (IsVectorSuperClass)
1686 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1687
1688 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1689}
1690
1692 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1693 const SIMachineFunctionInfo &MFI, bool NeedsCFI) const {
1694 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1695
1696 // Choose the right opcode if spilling a WWM register.
1698 return getWWMRegSpillSaveOpcode(Size, IsVectorSuperClass);
1699
1700 // TODO: Check if AGPRs are available
1701 if (ST.hasMAIInsts())
1702 return getAVSpillSaveOpcode(Size, NeedsCFI);
1703
1704 return getVGPRSpillSaveOpcode(Size, NeedsCFI);
1705}
1706
1707void SIInstrInfo::storeRegToStackSlotImpl(
1709 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1710 MachineInstr::MIFlag Flags, bool NeedsCFI) const {
1711 MachineFunction *MF = MBB.getParent();
1713 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1714 const DebugLoc &DL = MBB.findDebugLoc(MI);
1715
1716 MachinePointerInfo PtrInfo
1717 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1719 PtrInfo, MachineMemOperand::MOStore, FrameInfo.getObjectSize(FrameIndex),
1720 FrameInfo.getObjectAlign(FrameIndex));
1721 unsigned SpillSize = RI.getSpillSize(*RC);
1722
1723 MachineRegisterInfo &MRI = MF->getRegInfo();
1724 if (RI.isSGPRClass(RC)) {
1725 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1726 MFI->setHasSpilledSGPRs();
1727 assert(SrcReg != AMDGPU::M0 && "m0 should not be spilled");
1728 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1729 SrcReg != AMDGPU::EXEC && "exec should not be spilled");
1730
1731 // We are only allowed to create one new instruction when spilling
1732 // registers, so we need to use pseudo instruction for spilling SGPRs.
1733 const MCInstrDesc &OpDesc =
1734 get(getSGPRSpillSaveOpcode(SpillSize, NeedsCFI));
1735
1736 // The SGPR spill/restore instructions only work on number sgprs, so we need
1737 // to make sure we are using the correct register class.
1738 if (SrcReg.isVirtual() && SpillSize == 4) {
1739 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1740 }
1741
1742 BuildMI(MBB, MI, DL, OpDesc)
1743 .addReg(SrcReg, getKillRegState(isKill)) // data
1744 .addFrameIndex(FrameIndex) // addr
1745 .addMemOperand(MMO)
1747
1748 return;
1749 }
1750
1751 unsigned Opcode = getVectorRegSpillSaveOpcode(VReg ? VReg : SrcReg, RC,
1752 SpillSize, *MFI, NeedsCFI);
1753 MFI->setHasSpilledVGPRs();
1754
1755 BuildMI(MBB, MI, DL, get(Opcode))
1756 .addReg(SrcReg, getKillRegState(isKill)) // data
1757 .addFrameIndex(FrameIndex) // addr
1758 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1759 .addImm(0) // offset
1760 .addMemOperand(MMO);
1761}
1762
1765 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1766 MachineInstr::MIFlag Flags) const {
1767 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1768 false);
1769}
1770
1773 Register SrcReg, bool isKill,
1774 int FrameIndex,
1775 const TargetRegisterClass *RC) const {
1776 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, Register(),
1777 MachineInstr::NoFlags, true);
1778}
1779
1780static unsigned getSGPRSpillRestoreOpcode(unsigned Size) {
1781 switch (Size) {
1782 case 4:
1783 return AMDGPU::SI_SPILL_S32_RESTORE;
1784 case 8:
1785 return AMDGPU::SI_SPILL_S64_RESTORE;
1786 case 12:
1787 return AMDGPU::SI_SPILL_S96_RESTORE;
1788 case 16:
1789 return AMDGPU::SI_SPILL_S128_RESTORE;
1790 case 20:
1791 return AMDGPU::SI_SPILL_S160_RESTORE;
1792 case 24:
1793 return AMDGPU::SI_SPILL_S192_RESTORE;
1794 case 28:
1795 return AMDGPU::SI_SPILL_S224_RESTORE;
1796 case 32:
1797 return AMDGPU::SI_SPILL_S256_RESTORE;
1798 case 36:
1799 return AMDGPU::SI_SPILL_S288_RESTORE;
1800 case 40:
1801 return AMDGPU::SI_SPILL_S320_RESTORE;
1802 case 44:
1803 return AMDGPU::SI_SPILL_S352_RESTORE;
1804 case 48:
1805 return AMDGPU::SI_SPILL_S384_RESTORE;
1806 case 64:
1807 return AMDGPU::SI_SPILL_S512_RESTORE;
1808 case 128:
1809 return AMDGPU::SI_SPILL_S1024_RESTORE;
1810 default:
1811 llvm_unreachable("unknown register size");
1812 }
1813}
1814
1815static unsigned getVGPRSpillRestoreOpcode(unsigned Size) {
1816 switch (Size) {
1817 case 2:
1818 return AMDGPU::SI_SPILL_V16_RESTORE;
1819 case 4:
1820 return AMDGPU::SI_SPILL_V32_RESTORE;
1821 case 8:
1822 return AMDGPU::SI_SPILL_V64_RESTORE;
1823 case 12:
1824 return AMDGPU::SI_SPILL_V96_RESTORE;
1825 case 16:
1826 return AMDGPU::SI_SPILL_V128_RESTORE;
1827 case 20:
1828 return AMDGPU::SI_SPILL_V160_RESTORE;
1829 case 24:
1830 return AMDGPU::SI_SPILL_V192_RESTORE;
1831 case 28:
1832 return AMDGPU::SI_SPILL_V224_RESTORE;
1833 case 32:
1834 return AMDGPU::SI_SPILL_V256_RESTORE;
1835 case 36:
1836 return AMDGPU::SI_SPILL_V288_RESTORE;
1837 case 40:
1838 return AMDGPU::SI_SPILL_V320_RESTORE;
1839 case 44:
1840 return AMDGPU::SI_SPILL_V352_RESTORE;
1841 case 48:
1842 return AMDGPU::SI_SPILL_V384_RESTORE;
1843 case 64:
1844 return AMDGPU::SI_SPILL_V512_RESTORE;
1845 case 128:
1846 return AMDGPU::SI_SPILL_V1024_RESTORE;
1847 default:
1848 llvm_unreachable("unknown register size");
1849 }
1850}
1851
1852static unsigned getAVSpillRestoreOpcode(unsigned Size) {
1853 switch (Size) {
1854 case 4:
1855 return AMDGPU::SI_SPILL_AV32_RESTORE;
1856 case 8:
1857 return AMDGPU::SI_SPILL_AV64_RESTORE;
1858 case 12:
1859 return AMDGPU::SI_SPILL_AV96_RESTORE;
1860 case 16:
1861 return AMDGPU::SI_SPILL_AV128_RESTORE;
1862 case 20:
1863 return AMDGPU::SI_SPILL_AV160_RESTORE;
1864 case 24:
1865 return AMDGPU::SI_SPILL_AV192_RESTORE;
1866 case 28:
1867 return AMDGPU::SI_SPILL_AV224_RESTORE;
1868 case 32:
1869 return AMDGPU::SI_SPILL_AV256_RESTORE;
1870 case 36:
1871 return AMDGPU::SI_SPILL_AV288_RESTORE;
1872 case 40:
1873 return AMDGPU::SI_SPILL_AV320_RESTORE;
1874 case 44:
1875 return AMDGPU::SI_SPILL_AV352_RESTORE;
1876 case 48:
1877 return AMDGPU::SI_SPILL_AV384_RESTORE;
1878 case 64:
1879 return AMDGPU::SI_SPILL_AV512_RESTORE;
1880 case 128:
1881 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1882 default:
1883 llvm_unreachable("unknown register size");
1884 }
1885}
1886
1887static unsigned getWWMRegSpillRestoreOpcode(unsigned Size,
1888 bool IsVectorSuperClass) {
1889 // Currently, there is only 32-bit WWM register spills needed.
1890 if (Size != 4)
1891 llvm_unreachable("unknown wwm register spill size");
1892
1893 if (IsVectorSuperClass) // TODO: Always use this if there are AGPRs
1894 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1895
1896 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1897}
1898
1900 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1901 const SIMachineFunctionInfo &MFI) const {
1902 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1903
1904 // Choose the right opcode if restoring a WWM register.
1906 return getWWMRegSpillRestoreOpcode(Size, IsVectorSuperClass);
1907
1908 // TODO: Check if AGPRs are available
1909 if (ST.hasMAIInsts())
1911
1912 assert(!RI.isAGPRClass(RC));
1914}
1915
1918 Register DestReg, int FrameIndex,
1919 const TargetRegisterClass *RC,
1920 Register VReg, unsigned SubReg,
1921 MachineInstr::MIFlag Flags) const {
1922 MachineFunction *MF = MBB.getParent();
1924 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1925 const DebugLoc &DL = MBB.findDebugLoc(MI);
1926 unsigned SpillSize = RI.getSpillSize(*RC);
1927
1928 MachinePointerInfo PtrInfo
1929 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1930
1932 PtrInfo, MachineMemOperand::MOLoad, FrameInfo.getObjectSize(FrameIndex),
1933 FrameInfo.getObjectAlign(FrameIndex));
1934
1935 if (RI.isSGPRClass(RC)) {
1936 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1937 MFI->setHasSpilledSGPRs();
1938 assert(DestReg != AMDGPU::M0 && "m0 should not be reloaded into");
1939 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1940 DestReg != AMDGPU::EXEC && "exec should not be spilled");
1941
1942 // FIXME: Maybe this should not include a memoperand because it will be
1943 // lowered to non-memory instructions.
1944 const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize));
1945 if (DestReg.isVirtual() && SpillSize == 4) {
1946 MachineRegisterInfo &MRI = MF->getRegInfo();
1947 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1948 }
1949
1950 BuildMI(MBB, MI, DL, OpDesc, DestReg)
1951 .addFrameIndex(FrameIndex) // addr
1952 .addMemOperand(MMO)
1954
1955 return;
1956 }
1957
1958 unsigned Opcode = getVectorRegSpillRestoreOpcode(VReg ? VReg : DestReg, RC,
1959 SpillSize, *MFI);
1960 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
1961 .addFrameIndex(FrameIndex) // vaddr
1962 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1963 .addImm(0) // offset
1964 .addMemOperand(MMO);
1965}
1966
1971
1974 unsigned Quantity) const {
1975 DebugLoc DL = MBB.findDebugLoc(MI);
1976 unsigned MaxSNopCount = 1u << ST.getSNopBits();
1977 while (Quantity > 0) {
1978 unsigned Arg = std::min(Quantity, MaxSNopCount);
1979 Quantity -= Arg;
1980 BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
1981 }
1982}
1983
1987 const DebugLoc &DL) const {
1988 MachineFunction *MF = MBB.getParent();
1989 constexpr unsigned DoorbellIDMask = 0x3ff;
1990 constexpr unsigned ECQueueWaveAbort = 0x400;
1991
1992 MachineBasicBlock *TrapBB = &MBB;
1993 MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock();
1994
1995 if (!MBB.succ_empty() || std::next(MI.getIterator()) != MBB.end()) {
1996 MBB.splitAt(MI, /*UpdateLiveIns=*/false);
1997 TrapBB = MF->CreateMachineBasicBlock();
1998 BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB);
1999 MF->push_back(TrapBB);
2000 MBB.addSuccessor(TrapBB);
2001 }
2002 // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this
2003 // will be a nop.
2004 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP))
2005 .addImm(static_cast<unsigned>(GCNSubtarget::TrapID::LLVMAMDHSATrap));
2006 Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2007 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32),
2008 DoorbellReg)
2010 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2011 .addUse(AMDGPU::M0);
2012 Register DoorbellRegMasked =
2013 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2014 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2015 .addUse(DoorbellReg)
2016 .addImm(DoorbellIDMask);
2017 Register SetWaveAbortBit =
2018 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2019 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2020 .addUse(DoorbellRegMasked)
2021 .addImm(ECQueueWaveAbort);
2022 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2023 .addUse(SetWaveAbortBit);
2024 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG))
2026 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2027 .addUse(AMDGPU::TTMP2);
2028 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB);
2029 TrapBB->addSuccessor(HaltLoopBB);
2030
2031 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5);
2032 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH))
2033 .addMBB(HaltLoopBB);
2034 MF->push_back(HaltLoopBB);
2035 HaltLoopBB->addSuccessor(HaltLoopBB);
2036
2037 return MBB.getNextNode();
2038}
2039
2041 switch (MI.getOpcode()) {
2042 default:
2043 if (MI.isMetaInstruction())
2044 return 0;
2045 return 1; // FIXME: Do wait states equal cycles?
2046
2047 case AMDGPU::S_NOP:
2048 return MI.getOperand(0).getImm() + 1;
2049 // SI_RETURN_TO_EPILOG is a fallthrough to code outside of the function. The
2050 // hazard, even if one exist, won't really be visible. Should we handle it?
2051 }
2052}
2053
2055 MachineBasicBlock &MBB = *MI.getParent();
2056 DebugLoc DL = MBB.findDebugLoc(MI);
2058
2059 switch (MI.getOpcode()) {
2060 default: return TargetInstrInfo::expandPostRAPseudo(MI);
2061 case AMDGPU::S_MOV_B64_term:
2062 // This is only a terminator to get the correct spill code placement during
2063 // register allocation.
2064 MI.setDesc(get(AMDGPU::S_MOV_B64));
2065 break;
2066
2067 case AMDGPU::S_MOV_B32_term:
2068 // This is only a terminator to get the correct spill code placement during
2069 // register allocation.
2070 MI.setDesc(get(AMDGPU::S_MOV_B32));
2071 break;
2072
2073 case AMDGPU::S_XOR_B64_term:
2074 // This is only a terminator to get the correct spill code placement during
2075 // register allocation.
2076 MI.setDesc(get(AMDGPU::S_XOR_B64));
2077 break;
2078
2079 case AMDGPU::S_XOR_B32_term:
2080 // This is only a terminator to get the correct spill code placement during
2081 // register allocation.
2082 MI.setDesc(get(AMDGPU::S_XOR_B32));
2083 break;
2084 case AMDGPU::S_OR_B64_term:
2085 // This is only a terminator to get the correct spill code placement during
2086 // register allocation.
2087 MI.setDesc(get(AMDGPU::S_OR_B64));
2088 break;
2089 case AMDGPU::S_OR_B32_term:
2090 // This is only a terminator to get the correct spill code placement during
2091 // register allocation.
2092 MI.setDesc(get(AMDGPU::S_OR_B32));
2093 break;
2094
2095 case AMDGPU::S_ANDN2_B64_term:
2096 // This is only a terminator to get the correct spill code placement during
2097 // register allocation.
2098 MI.setDesc(get(AMDGPU::S_ANDN2_B64));
2099 break;
2100
2101 case AMDGPU::S_ANDN2_B32_term:
2102 // This is only a terminator to get the correct spill code placement during
2103 // register allocation.
2104 MI.setDesc(get(AMDGPU::S_ANDN2_B32));
2105 break;
2106
2107 case AMDGPU::S_AND_B64_term:
2108 // This is only a terminator to get the correct spill code placement during
2109 // register allocation.
2110 MI.setDesc(get(AMDGPU::S_AND_B64));
2111 break;
2112
2113 case AMDGPU::S_AND_B32_term:
2114 // This is only a terminator to get the correct spill code placement during
2115 // register allocation.
2116 MI.setDesc(get(AMDGPU::S_AND_B32));
2117 break;
2118
2119 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2120 // This is only a terminator to get the correct spill code placement during
2121 // register allocation.
2122 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B64));
2123 break;
2124
2125 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2126 // This is only a terminator to get the correct spill code placement during
2127 // register allocation.
2128 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B32));
2129 break;
2130
2131 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2132 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2133 break;
2134 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2135 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2136 break;
2137
2138 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2139 MI.setDesc(get(AMDGPU::V_WRITELANE_B32));
2140 break;
2141
2142 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2143 MI.setDesc(get(AMDGPU::V_READLANE_B32));
2144 break;
2145 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2146 Register Dst = MI.getOperand(0).getReg();
2147 bool IsAGPR = SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst));
2148 MI.setDesc(
2149 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2150 break;
2151 }
2152 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2153 Register Dst = MI.getOperand(0).getReg();
2154 if (SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst))) {
2155 int64_t Imm = MI.getOperand(1).getImm();
2156
2157 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2158 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2159 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstLo)
2161 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstHi)
2162 .addImm(SignExtend64<32>(Imm >> 32));
2163 MI.eraseFromParent();
2164 break;
2165 }
2166
2167 [[fallthrough]];
2168 }
2169 case AMDGPU::V_MOV_B64_PSEUDO: {
2170 Register Dst = MI.getOperand(0).getReg();
2171 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2172 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2173
2174 const MCInstrDesc &Mov64Desc = get(AMDGPU::V_MOV_B64_e32);
2175 const TargetRegisterClass *Mov64RC = getRegClass(Mov64Desc, /*OpNum=*/0);
2176
2177 const MachineOperand &SrcOp = MI.getOperand(1);
2178 // FIXME: Will this work for 64-bit floating point immediates?
2179 assert(!SrcOp.isFPImm());
2180 if (ST.hasVMovB64Inst() && Mov64RC->contains(Dst)) {
2181 MI.setDesc(Mov64Desc);
2182 if (SrcOp.isReg() || isInlineConstant(MI, 1) ||
2183 (SrcOp.isImm() &&
2184 (isUInt<32>(SrcOp.getImm()) || ST.has64BitLiterals())) ||
2185 (SrcOp.isGlobal() && ST.has64BitLiterals()))
2186 break;
2187 }
2188 if (SrcOp.isGlobal()) {
2189 // The address is unknown until link time, so the PK_MOV inline-constant
2190 // shortcut cannot apply.
2191 const GlobalValue *GV = SrcOp.getGlobal();
2192 int64_t Offset = SrcOp.getOffset();
2193 unsigned BaseFlags, LoReloc, HiReloc;
2194 std::tie(BaseFlags, LoReloc, HiReloc) =
2196
2197 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2198 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2199 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2200 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2201 } else if (SrcOp.isImm()) {
2202 APInt Imm(64, SrcOp.getImm());
2203 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2204 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2205 const MCInstrDesc &PkMovDesc = get(AMDGPU::V_PK_MOV_B32);
2206 const TargetRegisterClass *PkMovRC = getRegClass(PkMovDesc, /*OpNum=*/0);
2207
2208 if (ST.hasPkMovB32() && Lo == Hi && isInlineConstant(Lo) &&
2209 PkMovRC->contains(Dst)) {
2210 BuildMI(MBB, MI, DL, PkMovDesc, Dst)
2212 .addImm(Lo.getSExtValue())
2214 .addImm(Lo.getSExtValue())
2215 .addImm(0) // op_sel_lo
2216 .addImm(0) // op_sel_hi
2217 .addImm(0) // neg_lo
2218 .addImm(0) // neg_hi
2219 .addImm(0); // clamp
2220 } else {
2221 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2222 .addImm(Lo.getSExtValue());
2223 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2224 .addImm(Hi.getSExtValue());
2225 }
2226 } else {
2227 assert(SrcOp.isReg());
2228 if (ST.hasPkMovB32() &&
2229 !RI.isAGPR(MBB.getParent()->getRegInfo(), SrcOp.getReg())) {
2230 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), Dst)
2231 .addImm(SISrcMods::OP_SEL_1) // src0_mod
2232 .addReg(SrcOp.getReg())
2234 .addReg(SrcOp.getReg())
2235 .addImm(0) // op_sel_lo
2236 .addImm(0) // op_sel_hi
2237 .addImm(0) // neg_lo
2238 .addImm(0) // neg_hi
2239 .addImm(0); // clamp
2240 } else {
2241 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2242 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0));
2243 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2244 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1));
2245 }
2246 }
2247 MI.eraseFromParent();
2248 break;
2249 }
2250 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2252 break;
2253 }
2254 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2255 const MachineOperand &SrcOp = MI.getOperand(1);
2256 assert(!SrcOp.isFPImm());
2257
2258 if (ST.has64BitLiterals()) {
2259 MI.setDesc(get(AMDGPU::S_MOV_B64));
2260 break;
2261 }
2262
2263 if (SrcOp.isGlobal()) {
2264 Register Dst = MI.getOperand(0).getReg();
2265 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2266 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2267 const GlobalValue *GV = SrcOp.getGlobal();
2268 int64_t Offset = SrcOp.getOffset();
2269 unsigned BaseFlags, LoReloc, HiReloc;
2270 std::tie(BaseFlags, LoReloc, HiReloc) =
2272
2273 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2274 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2275 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2276 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2277 MI.eraseFromParent();
2278 break;
2279 }
2280
2281 // SrcOp is immediate
2282 APInt Imm(64, SrcOp.getImm());
2283 if (Imm.isIntN(32) || isInlineConstant(Imm)) {
2284 MI.setDesc(get(AMDGPU::S_MOV_B64));
2285 break;
2286 }
2287
2288 Register Dst = MI.getOperand(0).getReg();
2289 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2290 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2291
2292 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2293 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2294 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2295 .addImm(Lo.getSExtValue());
2296 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2297 .addImm(Hi.getSExtValue());
2298 MI.eraseFromParent();
2299 break;
2300 }
2301 case AMDGPU::V_SET_INACTIVE_B32: {
2302 // Lower V_SET_INACTIVE_B32 to V_CNDMASK_B32.
2303 Register DstReg = MI.getOperand(0).getReg();
2304 BuildMI(MBB, MI, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2305 .add(MI.getOperand(3))
2306 .add(MI.getOperand(4))
2307 .add(MI.getOperand(1))
2308 .add(MI.getOperand(2))
2309 .add(MI.getOperand(5));
2310 MI.eraseFromParent();
2311 break;
2312 }
2313 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2314 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2315 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2316 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2317 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2318 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2319 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2320 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2321 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2322 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2323 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2324 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2325 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2326 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2327 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2328 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2329 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2330 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2331 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2332 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2333 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2334 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2335 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2336 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2337 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2338 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2339 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2340 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2341 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2342 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2343 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2344 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2345 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2346 const TargetRegisterClass *EltRC = getOpRegClass(MI, 2);
2347
2348 unsigned Opc;
2349 if (RI.hasVGPRs(EltRC)) {
2350 Opc = AMDGPU::V_MOVRELD_B32_e32;
2351 } else {
2352 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2353 : AMDGPU::S_MOVRELD_B32;
2354 }
2355
2356 const MCInstrDesc &OpDesc = get(Opc);
2357 Register VecReg = MI.getOperand(0).getReg();
2358 bool IsUndef = MI.getOperand(1).isUndef();
2359 unsigned SubReg = MI.getOperand(3).getImm();
2360 assert(VecReg == MI.getOperand(1).getReg());
2361
2363 BuildMI(MBB, MI, DL, OpDesc)
2364 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2365 .add(MI.getOperand(2))
2367 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2368
2369 const int ImpDefIdx =
2370 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2371 const int ImpUseIdx = ImpDefIdx + 1;
2372 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2373 MI.eraseFromParent();
2374 break;
2375 }
2376 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2377 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2378 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2379 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2380 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2381 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2382 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2383 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2384 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2385 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2386 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2387 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2388 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2389 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2390 assert(ST.useVGPRIndexMode());
2391 Register VecReg = MI.getOperand(0).getReg();
2392 bool IsUndef = MI.getOperand(1).isUndef();
2393 MachineOperand &Idx = MI.getOperand(3);
2394 Register SubReg = MI.getOperand(4).getImm();
2395
2396 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2397 .add(Idx)
2399 SetOn->getOperand(3).setIsUndef();
2400
2401 const MCInstrDesc &OpDesc = get(AMDGPU::V_MOV_B32_indirect_write);
2403 BuildMI(MBB, MI, DL, OpDesc)
2404 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2405 .add(MI.getOperand(2))
2407 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2408
2409 const int ImpDefIdx =
2410 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2411 const int ImpUseIdx = ImpDefIdx + 1;
2412 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2413
2414 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2415
2416 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2417
2418 MI.eraseFromParent();
2419 break;
2420 }
2421 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2422 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2423 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2424 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2425 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2426 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2427 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2428 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2429 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2430 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2431 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2432 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2433 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2434 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2435 assert(ST.useVGPRIndexMode());
2436 Register Dst = MI.getOperand(0).getReg();
2437 Register VecReg = MI.getOperand(1).getReg();
2438 bool IsUndef = MI.getOperand(1).isUndef();
2439 Register SubReg = MI.getOperand(3).getImm();
2440
2441 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2442 .add(MI.getOperand(2))
2444 SetOn->getOperand(3).setIsUndef();
2445
2446 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_indirect_read))
2447 .addDef(Dst)
2448 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2449 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2450
2451 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2452
2453 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2454
2455 MI.eraseFromParent();
2456 break;
2457 }
2458 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2459 MachineFunction &MF = *MBB.getParent();
2460 Register Reg = MI.getOperand(0).getReg();
2461 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2462 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2463 MachineOperand OpLo = MI.getOperand(1);
2464 MachineOperand OpHi = MI.getOperand(2);
2465
2466 // Create a bundle so these instructions won't be re-ordered by the
2467 // post-RA scheduler.
2468 MIBundleBuilder Bundler(MBB, MI);
2469 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2470
2471 // What we want here is an offset from the value returned by s_getpc (which
2472 // is the address of the s_add_u32 instruction) to the global variable, but
2473 // since the encoding of $symbol starts 4 bytes after the start of the
2474 // s_add_u32 instruction, we end up with an offset that is 4 bytes too
2475 // small. This requires us to add 4 to the global variable offset in order
2476 // to compute the correct address. Similarly for the s_addc_u32 instruction,
2477 // the encoding of $symbol starts 12 bytes after the start of the s_add_u32
2478 // instruction.
2479
2480 int64_t Adjust = 0;
2481 if (ST.hasGetPCZeroExtension()) {
2482 // Fix up hardware that does not sign-extend the 48-bit PC value by
2483 // inserting: s_sext_i32_i16 reghi, reghi
2484 Bundler.append(
2485 BuildMI(MF, DL, get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2486 Adjust += 4;
2487 }
2488
2489 if (OpLo.isGlobal())
2490 OpLo.setOffset(OpLo.getOffset() + Adjust + 4);
2491 Bundler.append(
2492 BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2493
2494 if (OpHi.isGlobal())
2495 OpHi.setOffset(OpHi.getOffset() + Adjust + 12);
2496 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi)
2497 .addReg(RegHi)
2498 .add(OpHi));
2499
2500 finalizeBundle(MBB, Bundler.begin());
2501
2502 MI.eraseFromParent();
2503 break;
2504 }
2505 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2506 MachineFunction &MF = *MBB.getParent();
2507 Register Reg = MI.getOperand(0).getReg();
2508 MachineOperand Op = MI.getOperand(1);
2509
2510 // Create a bundle so these instructions won't be re-ordered by the
2511 // post-RA scheduler.
2512 MIBundleBuilder Bundler(MBB, MI);
2513 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2514 if (Op.isGlobal())
2515 Op.setOffset(Op.getOffset() + 4);
2516 Bundler.append(
2517 BuildMI(MF, DL, get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(Op));
2518
2519 finalizeBundle(MBB, Bundler.begin());
2520
2521 MI.eraseFromParent();
2522 break;
2523 }
2524 case AMDGPU::ENTER_STRICT_WWM: {
2525 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2526 // Whole Wave Mode is entered.
2527 MI.setDesc(get(LMC.OrSaveExecOpc));
2528 break;
2529 }
2530 case AMDGPU::ENTER_STRICT_WQM: {
2531 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2532 // STRICT_WQM is entered.
2533 BuildMI(MBB, MI, DL, get(LMC.MovOpc), MI.getOperand(0).getReg())
2534 .addReg(LMC.ExecReg);
2535 BuildMI(MBB, MI, DL, get(LMC.WQMOpc), LMC.ExecReg).addReg(LMC.ExecReg);
2536
2537 MI.eraseFromParent();
2538 break;
2539 }
2540 case AMDGPU::EXIT_STRICT_WWM:
2541 case AMDGPU::EXIT_STRICT_WQM: {
2542 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2543 // WWM/STICT_WQM is exited.
2544 MI.setDesc(get(LMC.MovOpc));
2545 break;
2546 }
2547 case AMDGPU::SI_RETURN: {
2548 const MachineFunction *MF = MBB.getParent();
2549 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2550 const SIRegisterInfo *TRI = ST.getRegisterInfo();
2551 // Hiding the return address use with SI_RETURN may lead to extra kills in
2552 // the function and missing live-ins. We are fine in practice because callee
2553 // saved register handling ensures the register value is restored before
2554 // RET, but we need the undef flag here to appease the MachineVerifier
2555 // liveness checks.
2557 BuildMI(MBB, MI, DL, get(AMDGPU::S_SETPC_B64_return))
2558 .addReg(TRI->getReturnAddressReg(*MF), RegState::Undef);
2559
2560 MIB.copyImplicitOps(MI);
2561 MI.eraseFromParent();
2562 break;
2563 }
2564
2565 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2566 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2567 MI.setDesc(get(AMDGPU::S_MUL_U64));
2568 break;
2569
2570 case AMDGPU::S_GETPC_B64_pseudo:
2571 MI.setDesc(get(AMDGPU::S_GETPC_B64));
2572 if (ST.hasGetPCZeroExtension()) {
2573 Register Dst = MI.getOperand(0).getReg();
2574 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2575 // Fix up hardware that does not sign-extend the 48-bit PC value by
2576 // inserting: s_sext_i32_i16 dsthi, dsthi
2577 BuildMI(MBB, std::next(MI.getIterator()), DL, get(AMDGPU::S_SEXT_I32_I16),
2578 DstHi)
2579 .addReg(DstHi);
2580 }
2581 break;
2582
2583 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2584 assert(ST.hasBF16PackedInsts());
2585 MI.setDesc(get(AMDGPU::V_PK_MAX_NUM_BF16));
2586 MI.addOperand(MachineOperand::CreateImm(0)); // op_sel
2587 MI.addOperand(MachineOperand::CreateImm(0)); // neg_lo
2588 MI.addOperand(MachineOperand::CreateImm(0)); // neg_hi
2589 auto Op0 = getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
2590 Op0->setImm(Op0->getImm() | SISrcMods::OP_SEL_1);
2591 auto Op1 = getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
2592 Op1->setImm(Op1->getImm() | SISrcMods::OP_SEL_1);
2593 break;
2594 }
2595
2596 case AMDGPU::GET_STACK_BASE:
2597 // The stack starts at offset 0 unless we need to reserve some space at the
2598 // bottom.
2599 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*MBB.getParent())) {
2600 // When CWSR is used in dynamic VGPR mode, the trap handler needs to save
2601 // some of the VGPRs. The size of the required scratch space has already
2602 // been computed by prolog epilog insertion.
2603 const SIMachineFunctionInfo *MFI =
2604 MBB.getParent()->getInfo<SIMachineFunctionInfo>();
2605 unsigned VGPRSize = MFI->getScratchReservedForDynamicVGPRs();
2606 Register DestReg = MI.getOperand(0).getReg();
2607 BuildMI(MBB, MI, DL, get(AMDGPU::S_GETREG_B32), DestReg)
2610 // The MicroEngine ID is 0 for the graphics queue, and 1 or 2 for compute
2611 // (3 is unused, so we ignore it). Unfortunately, S_GETREG doesn't set
2612 // SCC, so we need to check for 0 manually.
2613 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)).addImm(0).addReg(DestReg);
2614 // Change the implicif-def of SCC to an explicit use (but first remove
2615 // the dead flag if present).
2616 MI.getOperand(MI.getNumExplicitOperands()).setIsDead(false);
2617 MI.getOperand(MI.getNumExplicitOperands()).setIsUse();
2618 MI.setDesc(get(AMDGPU::S_CMOVK_I32));
2619 MI.addOperand(MachineOperand::CreateImm(VGPRSize));
2620 } else {
2621 MI.setDesc(get(AMDGPU::S_MOV_B32));
2622 MI.addOperand(MachineOperand::CreateImm(0));
2623 MI.removeOperand(
2624 MI.getNumExplicitOperands()); // Drop implicit def of SCC.
2625 }
2626 break;
2627 }
2628
2629 return true;
2630}
2631
2634 unsigned SubIdx, const MachineInstr &Orig,
2635 LaneBitmask UsedLanes) const {
2636
2637 // Try shrinking the instruction to remat only the part needed for current
2638 // context.
2639 // TODO: Handle more cases.
2640 unsigned Opcode = Orig.getOpcode();
2641 switch (Opcode) {
2642 case AMDGPU::S_MOV_B64:
2643 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2644 if (SubIdx != 0)
2645 break;
2646
2647 if (!Orig.getOperand(1).isImm())
2648 break;
2649
2650 // Shrink S_MOV_B64 to S_MOV_B32 when UsedLanes indicates only a single
2651 // 32-bit lane of the 64-bit value is live at the rematerialization point.
2652 if (UsedLanes.all())
2653 break;
2654
2655 // Determine which half of the 64-bit immediate corresponds to the use.
2656 unsigned OrigSubReg = Orig.getOperand(0).getSubReg();
2657 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2658 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2659
2660 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2661 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2662
2663 if (NeedLo && NeedHi)
2664 break;
2665
2666 int64_t Imm64 = Orig.getOperand(1).getImm();
2667 int32_t Imm32 = NeedLo ? Lo_32(Imm64) : Hi_32(Imm64);
2668
2669 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2670
2671 // Emit S_MOV_B32 defining just the needed 32-bit subreg of DestReg.
2672 BuildMI(MBB, I, Orig.getDebugLoc(), get(AMDGPU::S_MOV_B32))
2673 .addReg(DestReg, RegState::Define | RegState::Undef, UseSubReg)
2674 .addImm(Imm32);
2675 return;
2676 }
2677
2678 case AMDGPU::S_LOAD_DWORDX16_IMM:
2679 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2680 if (SubIdx != 0)
2681 break;
2682
2683 if (I == MBB.end())
2684 break;
2685
2686 if (I->isBundled())
2687 break;
2688
2689 // Look for a single use of the register that is also a subreg.
2690 Register RegToFind = Orig.getOperand(0).getReg();
2691 MachineOperand *UseMO = nullptr;
2692 for (auto &CandMO : I->operands()) {
2693 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2694 continue;
2695 if (UseMO) {
2696 UseMO = nullptr;
2697 break;
2698 }
2699 UseMO = &CandMO;
2700 }
2701 if (!UseMO || UseMO->getSubReg() == AMDGPU::NoSubRegister)
2702 break;
2703
2704 unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
2705 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());
2706
2707 MachineFunction *MF = MBB.getParent();
2708 MachineRegisterInfo &MRI = MF->getRegInfo();
2709 assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");
2710
2711 unsigned NewOpcode = -1;
2712 if (SubregSize == 256)
2713 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2714 else if (SubregSize == 128)
2715 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2716 else
2717 break;
2718
2719 const MCInstrDesc &TID = get(NewOpcode);
2720 const TargetRegisterClass *NewRC =
2721 RI.getAllocatableClass(getRegClass(TID, 0));
2722 MRI.setRegClass(DestReg, NewRC);
2723
2724 UseMO->setReg(DestReg);
2725 UseMO->setSubReg(AMDGPU::NoSubRegister);
2726
2727 // Use a smaller load with the desired size, possibly with updated offset.
2728 MachineInstr *MI = MF->CloneMachineInstr(&Orig);
2729 MI->setDesc(TID);
2730 MI->getOperand(0).setReg(DestReg);
2731 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2732 if (Offset) {
2733 MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
2734 int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
2735 OffsetMO->setImm(FinalOffset);
2736 }
2738 for (const MachineMemOperand *MemOp : Orig.memoperands())
2739 NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
2740 SubregSize / 8));
2741 MI->setMemRefs(*MF, NewMMOs);
2742
2743 MBB.insert(I, MI);
2744 return;
2745 }
2746
2747 default:
2748 break;
2749 }
2750
2751 TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
2752}
2753
2754std::pair<MachineInstr*, MachineInstr*>
2756 assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2757
2758 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2760 ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
2761 MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
2762 return std::pair(&MI, nullptr);
2763 }
2764
2765 MachineBasicBlock &MBB = *MI.getParent();
2766 DebugLoc DL = MBB.findDebugLoc(MI);
2767 MachineFunction *MF = MBB.getParent();
2768 MachineRegisterInfo &MRI = MF->getRegInfo();
2769 Register Dst = MI.getOperand(0).getReg();
2770 unsigned Part = 0;
2771 MachineInstr *Split[2];
2772
2773 for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2774 auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
2775 if (Dst.isPhysical()) {
2776 MovDPP.addDef(RI.getSubReg(Dst, Sub));
2777 } else {
2778 assert(MRI.isSSA());
2779 auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2780 MovDPP.addDef(Tmp);
2781 }
2782
2783 for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
2784 const MachineOperand &SrcOp = MI.getOperand(I);
2785 assert(!SrcOp.isFPImm());
2786 if (SrcOp.isImm()) {
2787 APInt Imm(64, SrcOp.getImm());
2788 Imm.ashrInPlace(Part * 32);
2789 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2790 } else {
2791 assert(SrcOp.isReg());
2792 Register Src = SrcOp.getReg();
2793 if (Src.isPhysical())
2794 MovDPP.addReg(RI.getSubReg(Src, Sub));
2795 else
2796 MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
2797 }
2798 }
2799
2800 for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
2801 MovDPP.addImm(MO.getImm());
2802
2803 Split[Part] = MovDPP;
2804 ++Part;
2805 }
2806
2807 if (Dst.isVirtual())
2808 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
2809 .addReg(Split[0]->getOperand(0).getReg())
2810 .addImm(AMDGPU::sub0)
2811 .addReg(Split[1]->getOperand(0).getReg())
2812 .addImm(AMDGPU::sub1);
2813
2814 MI.eraseFromParent();
2815 return std::pair(Split[0], Split[1]);
2816}
2817
2818std::optional<DestSourcePair>
2820 if (MI.getOpcode() == AMDGPU::WWM_COPY)
2821 return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
2822
2823 return std::nullopt;
2824}
2825
2827 AMDGPU::OpName Src0OpName,
2828 MachineOperand &Src1,
2829 AMDGPU::OpName Src1OpName) const {
2830 MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
2831 if (!Src0Mods)
2832 return false;
2833
2834 MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
2835 assert(Src1Mods &&
2836 "All commutable instructions have both src0 and src1 modifiers");
2837
2838 int Src0ModsVal = Src0Mods->getImm();
2839 int Src1ModsVal = Src1Mods->getImm();
2840
2841 Src1Mods->setImm(Src0ModsVal);
2842 Src0Mods->setImm(Src1ModsVal);
2843 return true;
2844}
2845
2847 MachineOperand &RegOp,
2848 MachineOperand &NonRegOp) {
2849 Register Reg = RegOp.getReg();
2850 unsigned SubReg = RegOp.getSubReg();
2851 bool IsKill = RegOp.isKill();
2852 bool IsDead = RegOp.isDead();
2853 bool IsUndef = RegOp.isUndef();
2854 bool IsDebug = RegOp.isDebug();
2855
2856 if (NonRegOp.isImm())
2857 RegOp.ChangeToImmediate(NonRegOp.getImm());
2858 else if (NonRegOp.isFI())
2859 RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
2860 else if (NonRegOp.isGlobal()) {
2861 RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
2862 NonRegOp.getTargetFlags());
2863 } else
2864 return nullptr;
2865
2866 // Make sure we don't reinterpret a subreg index in the target flags.
2867 RegOp.setTargetFlags(NonRegOp.getTargetFlags());
2868
2869 NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
2870 NonRegOp.setSubReg(SubReg);
2871
2872 return &MI;
2873}
2874
2876 MachineOperand &NonRegOp1,
2877 MachineOperand &NonRegOp2) {
2878 unsigned TargetFlags = NonRegOp1.getTargetFlags();
2879 int64_t NonRegVal = NonRegOp1.getImm();
2880
2881 NonRegOp1.setImm(NonRegOp2.getImm());
2882 NonRegOp2.setImm(NonRegVal);
2883 NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
2884 NonRegOp2.setTargetFlags(TargetFlags);
2885 return &MI;
2886}
2887
2888bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
2889 unsigned OpIdx1) const {
2890 const MCInstrDesc &InstDesc = MI.getDesc();
2891 const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
2892 const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];
2893
2894 unsigned Opc = MI.getOpcode();
2895 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2896
2897 const MachineOperand &MO0 = MI.getOperand(OpIdx0);
2898 const MachineOperand &MO1 = MI.getOperand(OpIdx1);
2899
2900 // Swap doesn't breach constant bus or literal limits
2901 // It may move literal to position other than src0, this is not allowed
2902 // pre-gfx10 However, most test cases need literals in Src0 for VOP
2903 // FIXME: After gfx9, literal can be in place other than Src0
2904 if (isVALU(MI, /*AllowLDSDMA=*/true)) {
2905 if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
2906 !isInlineConstant(MO0, OpInfo1))
2907 return false;
2908 if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
2909 !isInlineConstant(MO1, OpInfo0))
2910 return false;
2911 }
2912
2913 if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
2914 if (OpInfo1.RegClass == -1)
2915 return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
2916 return isLegalRegOperand(MI, OpIdx1, MO0) &&
2917 (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
2918 }
2919 if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
2920 if (OpInfo0.RegClass == -1)
2921 return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
2922 return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
2923 isLegalRegOperand(MI, OpIdx0, MO1);
2924 }
2925
2926 // No need to check 64-bit literals since swapping does not bring new
2927 // 64-bit literals into current instruction to fold to 32-bit
2928
2929 return isImmOperandLegal(MI, OpIdx1, MO0);
2930}
2931
2933 unsigned Src0Idx,
2934 unsigned Src1Idx) const {
2935 assert(!NewMI && "this should never be used");
2936
2937 unsigned Opc = MI.getOpcode();
2938 int CommutedOpcode = commuteOpcode(Opc);
2939 if (CommutedOpcode == -1)
2940 return nullptr;
2941
2942 if (Src0Idx > Src1Idx)
2943 std::swap(Src0Idx, Src1Idx);
2944
2945 assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
2946 static_cast<int>(Src0Idx) &&
2947 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
2948 static_cast<int>(Src1Idx) &&
2949 "inconsistency with findCommutedOpIndices");
2950
2951 if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
2952 return nullptr;
2953
2954 MachineInstr *CommutedMI = nullptr;
2955 MachineOperand &Src0 = MI.getOperand(Src0Idx);
2956 MachineOperand &Src1 = MI.getOperand(Src1Idx);
2957 if (Src0.isReg() && Src1.isReg()) {
2958 // Be sure to copy the source modifiers to the right place.
2959 CommutedMI =
2960 TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
2961 } else if (Src0.isReg() && !Src1.isReg()) {
2962 CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
2963 } else if (!Src0.isReg() && Src1.isReg()) {
2964 CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
2965 } else if (Src0.isImm() && Src1.isImm()) {
2966 CommutedMI = swapImmOperands(MI, Src0, Src1);
2967 } else {
2968 // FIXME: Found two non registers to commute. This does happen.
2969 return nullptr;
2970 }
2971
2972 if (CommutedMI) {
2973 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
2974 Src1, AMDGPU::OpName::src1_modifiers);
2975
2976 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
2977 AMDGPU::OpName::src1_sel);
2978
2979 CommutedMI->setDesc(get(CommutedOpcode));
2980 }
2981
2982 return CommutedMI;
2983}
2984
2985// This needs to be implemented because the source modifiers may be inserted
2986// between the true commutable operands, and the base
2987// TargetInstrInfo::commuteInstruction uses it.
2989 unsigned &SrcOpIdx0,
2990 unsigned &SrcOpIdx1) const {
2991 return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
2992}
2993
2995 unsigned &SrcOpIdx0,
2996 unsigned &SrcOpIdx1) const {
2997 if (!Desc.isCommutable())
2998 return false;
2999
3000 unsigned Opc = Desc.getOpcode();
3001 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
3002 if (Src0Idx == -1)
3003 return false;
3004
3005 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
3006 if (Src1Idx == -1)
3007 return false;
3008
3009 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3010}
3011
3013 int64_t BrOffset) const {
3014 // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
3015 // because its dest block is unanalyzable.
3016 assert(isSOPP(BranchOp) || isSOPK(BranchOp));
3017
3018 // Convert to dwords.
3019 BrOffset /= 4;
3020
3021 // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
3022 // from the next instruction.
3023 BrOffset -= 1;
3024
3025 return isIntN(BranchOffsetBits, BrOffset);
3026}
3027
3030 return MI.getOperand(0).getMBB();
3031}
3032
3034 for (const MachineInstr &MI : MBB->terminators()) {
3035 if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
3036 MI.getOpcode() == AMDGPU::SI_LOOP)
3037 return true;
3038 }
3039 return false;
3040}
3041
3043 MachineBasicBlock &DestBB,
3044 MachineBasicBlock &RestoreBB,
3045 const DebugLoc &DL, int64_t BrOffset,
3046 RegScavenger *RS) const {
3047 assert(MBB.empty() &&
3048 "new block should be inserted for expanding unconditional branch");
3049 assert(MBB.pred_size() == 1);
3050 assert(RestoreBB.empty() &&
3051 "restore block should be inserted for restoring clobbered registers");
3052
3053 MachineFunction *MF = MBB.getParent();
3054 MachineRegisterInfo &MRI = MF->getRegInfo();
3056 auto I = MBB.end();
3057 auto &MCCtx = MF->getContext();
3058
3059 if (ST.useAddPC64Inst()) {
3060 MCSymbol *Offset =
3061 MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
3062 auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
3064 MCSymbol *PostAddPCLabel =
3065 MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
3066 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3067 auto *OffsetExpr = MCBinaryExpr::createSub(
3068 MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
3069 MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
3070 Offset->setVariableValue(OffsetExpr);
3071 return;
3072 }
3073
3074 assert(RS && "RegScavenger required for long branching");
3075
3076 // FIXME: Virtual register workaround for RegScavenger not working with empty
3077 // blocks.
3078 Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3079
3080 // Note: as this is used after hazard recognizer we need to apply some hazard
3081 // workarounds directly.
3082 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3083 ST.hasVALUReadSGPRHazard();
3084 auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
3085 if (FlushSGPRWrites)
3086 BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
3088 };
3089
3090 // We need to compute the offset relative to the instruction immediately after
3091 // s_getpc_b64. Insert pc arithmetic code before last terminator.
3092 MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
3093 ApplyHazardWorkarounds();
3094
3095 MCSymbol *PostGetPCLabel =
3096 MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
3097 GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);
3098
3099 MCSymbol *OffsetLo =
3100 MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
3101 MCSymbol *OffsetHi =
3102 MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
3103 BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
3104 .addReg(PCReg, RegState::Define, AMDGPU::sub0)
3105 .addReg(PCReg, {}, AMDGPU::sub0)
3106 .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
3107 BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
3108 .addReg(PCReg, RegState::Define, AMDGPU::sub1)
3109 .addReg(PCReg, {}, AMDGPU::sub1)
3110 .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
3111 ApplyHazardWorkarounds();
3112
3113 // Insert the indirect branch after the other terminator.
3114 BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
3115 .addReg(PCReg);
3116
3117 // If a spill is needed for the pc register pair, we need to insert a spill
3118 // restore block right before the destination block, and insert a short branch
3119 // into the old destination block's fallthrough predecessor.
3120 // e.g.:
3121 //
3122 // s_cbranch_scc0 skip_long_branch:
3123 //
3124 // long_branch_bb:
3125 // spill s[8:9]
3126 // s_getpc_b64 s[8:9]
3127 // s_add_u32 s8, s8, restore_bb
3128 // s_addc_u32 s9, s9, 0
3129 // s_setpc_b64 s[8:9]
3130 //
3131 // skip_long_branch:
3132 // foo;
3133 //
3134 // .....
3135 //
3136 // dest_bb_fallthrough_predecessor:
3137 // bar;
3138 // s_branch dest_bb
3139 //
3140 // restore_bb:
3141 // restore s[8:9]
3142 // fallthrough dest_bb
3143 ///
3144 // dest_bb:
3145 // buzz;
3146
3147 Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
3148 Register Scav;
3149
3150 // If we've previously reserved a register for long branches
3151 // avoid running the scavenger and just use those registers
3152 if (LongBranchReservedReg) {
3153 RS->enterBasicBlock(MBB);
3154 Scav = LongBranchReservedReg;
3155 } else {
3156 RS->enterBasicBlockEnd(MBB);
3157 Scav = RS->scavengeRegisterBackwards(
3158 AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
3159 /* RestoreAfter */ false, 0, /* AllowSpill */ false);
3160 }
3161 if (Scav) {
3162 RS->setRegUsed(Scav);
3163 MRI.replaceRegWith(PCReg, Scav);
3164 MRI.clearVirtRegs();
3165 } else {
3166 // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
3167 // SGPR spill.
3168 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
3169 const SIRegisterInfo *TRI = ST.getRegisterInfo();
3170 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3171 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3172 MRI.clearVirtRegs();
3173 }
3174
3175 MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
3176 // Now, the distance could be defined.
3178 MCSymbolRefExpr::create(DestLabel, MCCtx),
3179 MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
3180 // Add offset assignments.
3181 auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
3182 OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
3183 auto *ShAmt = MCConstantExpr::create(32, MCCtx);
3184 OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
3185}
3186
3187unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
3188 switch (Cond) {
3189 case SIInstrInfo::SCC_TRUE:
3190 return AMDGPU::S_CBRANCH_SCC1;
3191 case SIInstrInfo::SCC_FALSE:
3192 return AMDGPU::S_CBRANCH_SCC0;
3193 case SIInstrInfo::VCCNZ:
3194 return AMDGPU::S_CBRANCH_VCCNZ;
3195 case SIInstrInfo::VCCZ:
3196 return AMDGPU::S_CBRANCH_VCCZ;
3197 case SIInstrInfo::EXECNZ:
3198 return AMDGPU::S_CBRANCH_EXECNZ;
3199 case SIInstrInfo::EXECZ:
3200 return AMDGPU::S_CBRANCH_EXECZ;
3201 default:
3202 llvm_unreachable("invalid branch predicate");
3203 }
3204}
3205
3206SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
3207 switch (Opcode) {
3208 case AMDGPU::S_CBRANCH_SCC0:
3209 return SCC_FALSE;
3210 case AMDGPU::S_CBRANCH_SCC1:
3211 return SCC_TRUE;
3212 case AMDGPU::S_CBRANCH_VCCNZ:
3213 return VCCNZ;
3214 case AMDGPU::S_CBRANCH_VCCZ:
3215 return VCCZ;
3216 case AMDGPU::S_CBRANCH_EXECNZ:
3217 return EXECNZ;
3218 case AMDGPU::S_CBRANCH_EXECZ:
3219 return EXECZ;
3220 default:
3221 return INVALID_BR;
3222 }
3223}
3224
3228 MachineBasicBlock *&FBB,
3230 bool AllowModify) const {
3231 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3232 // Unconditional Branch
3233 TBB = I->getOperand(0).getMBB();
3234 return false;
3235 }
3236
3237 BranchPredicate Pred = getBranchPredicate(I->getOpcode());
3238 if (Pred == INVALID_BR)
3239 return true;
3240
3241 MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
3242 Cond.push_back(MachineOperand::CreateImm(Pred));
3243 Cond.push_back(I->getOperand(1)); // Save the branch register.
3244
3245 ++I;
3246
3247 if (I == MBB.end()) {
3248 // Conditional branch followed by fall-through.
3249 TBB = CondBB;
3250 return false;
3251 }
3252
3253 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3254 TBB = CondBB;
3255 FBB = I->getOperand(0).getMBB();
3256 return false;
3257 }
3258
3259 return true;
3260}
3261
3263 MachineBasicBlock *&FBB,
3265 bool AllowModify) const {
3266 MachineBasicBlock::iterator I = MBB.getFirstTerminator();
3267 auto E = MBB.end();
3268 if (I == E)
3269 return false;
3270
3271 // Skip over the instructions that are artificially terminators for special
3272 // exec management.
3273 while (I != E && !I->isBranch() && !I->isReturn()) {
3274 switch (I->getOpcode()) {
3275 case AMDGPU::S_MOV_B64_term:
3276 case AMDGPU::S_XOR_B64_term:
3277 case AMDGPU::S_OR_B64_term:
3278 case AMDGPU::S_ANDN2_B64_term:
3279 case AMDGPU::S_AND_B64_term:
3280 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3281 case AMDGPU::S_MOV_B32_term:
3282 case AMDGPU::S_XOR_B32_term:
3283 case AMDGPU::S_OR_B32_term:
3284 case AMDGPU::S_ANDN2_B32_term:
3285 case AMDGPU::S_AND_B32_term:
3286 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3287 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3288 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3289 break;
3290 case AMDGPU::SI_IF:
3291 case AMDGPU::SI_ELSE:
3292 case AMDGPU::SI_KILL_I1_TERMINATOR:
3293 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3294 // FIXME: It's messy that these need to be considered here at all.
3295 return true;
3296 default:
3297 llvm_unreachable("unexpected non-branch terminator inst");
3298 }
3299
3300 ++I;
3301 }
3302
3303 if (I == E)
3304 return false;
3305
3306 return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
3307}
3308
3310 int *BytesRemoved) const {
3311 unsigned Count = 0;
3312 unsigned RemovedSize = 0;
3313 for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
3314 // Skip over artificial terminators when removing instructions.
3315 if (MI.isBranch() || MI.isReturn()) {
3316 RemovedSize += getInstSizeInBytes(MI);
3317 MI.eraseFromParent();
3318 ++Count;
3319 }
3320 }
3321
3322 if (BytesRemoved)
3323 *BytesRemoved = RemovedSize;
3324
3325 return Count;
3326}
3327
3328// Copy the flags onto the implicit condition register operand.
3330 const MachineOperand &OrigCond) {
3331 CondReg.setIsUndef(OrigCond.isUndef());
3332 CondReg.setIsKill(OrigCond.isKill());
3333}
3334
3337 MachineBasicBlock *FBB,
3339 const DebugLoc &DL,
3340 int *BytesAdded) const {
3341 if (!FBB && Cond.empty()) {
3342 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3343 .addMBB(TBB);
3344 if (BytesAdded)
3345 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3346 return 1;
3347 }
3348
3349 assert(TBB && Cond[0].isImm());
3350
3351 unsigned Opcode
3352 = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));
3353
3354 if (!FBB) {
3355 MachineInstr *CondBr =
3356 BuildMI(&MBB, DL, get(Opcode))
3357 .addMBB(TBB);
3358
3359 // Copy the flags onto the implicit condition register operand.
3360 preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
3361 fixImplicitOperands(*CondBr);
3362
3363 if (BytesAdded)
3364 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3365 return 1;
3366 }
3367
3368 assert(TBB && FBB);
3369
3370 MachineInstr *CondBr =
3371 BuildMI(&MBB, DL, get(Opcode))
3372 .addMBB(TBB);
3373 fixImplicitOperands(*CondBr);
3374 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3375 .addMBB(FBB);
3376
3377 MachineOperand &CondReg = CondBr->getOperand(1);
3378 CondReg.setIsUndef(Cond[1].isUndef());
3379 CondReg.setIsKill(Cond[1].isKill());
3380
3381 if (BytesAdded)
3382 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3383
3384 return 2;
3385}
3386
3389 if (Cond.size() != 2) {
3390 return true;
3391 }
3392
3393 if (Cond[0].isImm()) {
3394 Cond[0].setImm(-Cond[0].getImm());
3395 return false;
3396 }
3397
3398 return true;
3399}
3400
3401namespace {
3402class AMDGPUPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
3403private:
3404 /// The compare instruction for loop control
3405 const MachineInstr *CmpInst = nullptr;
3406 /// The normalized condition used by createTripCountGreaterCondition()
3408
3409public:
3410 AMDGPUPipelinerLoopInfo(MachineInstr *CmpInst,
3412 : CmpInst(CmpInst), Cond(Cond.begin(), Cond.end()) {}
3413
3414 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
3415 return CmpInst && MI == CmpInst;
3416 }
3417
3418 std::optional<bool> createTripCountGreaterCondition(
3419 int TC, MachineBasicBlock &MBB,
3420 SmallVectorImpl<MachineOperand> &CondParam) override {
3421 CondParam = this->Cond;
3422 return {};
3423 }
3424
3425 void adjustTripCount(int TripCountAdjust) override {}
3426
3427 void setPreheader(MachineBasicBlock *NewPreheader) override {}
3428};
3429} // namespace
3430
3431std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3433 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
3435 // Unanalyzable terminator.
3436 if (analyzeBranch(*LoopBB, TBB, FBB, Cond, /*AllowModify=*/false))
3437 return nullptr;
3438
3439 // Infinite loops are not supported.
3440 if (TBB == LoopBB && FBB == LoopBB)
3441 return nullptr;
3442
3443 // Must be conditional branch.
3444 if (FBB == nullptr)
3445 return nullptr;
3446
3447 assert((TBB == LoopBB || FBB == LoopBB) &&
3448 "The Loop must be a single-basic-block loop");
3449
3450 // Divergent (VCC/EXEC) back-edge is not supported.
3451 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3452 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3453 return nullptr;
3454
3455 // Calls and inline assembly are not supported.
3456 for (const MachineInstr &MI : *LoopBB)
3457 if (MI.isCall() || MI.isInlineAsm())
3458 return nullptr;
3459
3460 // Normalization for createTripCountGreaterCondition(): make Cond mean
3461 // "exit the loop" so the expander emits correct prolog guard branches.
3462 if (TBB == LoopBB)
3464
3465 auto Instructions = make_range(
3467 LoopBB->rend());
3468 auto CmpI = llvm::find_if(Instructions, [&](const MachineInstr &MI) {
3469 return MI.modifiesRegister(Cond[1].getReg(), &RI);
3470 });
3471
3472 if (CmpI == Instructions.end() || CmpI->isPHI())
3473 return nullptr;
3474 MachineInstr *CmpInst = &*CmpI;
3475
3476 return std::make_unique<AMDGPUPipelinerLoopInfo>(CmpInst, Cond);
3477}
3478
3481 Register DstReg, Register TrueReg,
3482 Register FalseReg, int &CondCycles,
3483 int &TrueCycles, int &FalseCycles) const {
3484 switch (Cond[0].getImm()) {
3485 case VCCNZ:
3486 case VCCZ: {
3487 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3488 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3489 if (MRI.getRegClass(FalseReg) != RC)
3490 return false;
3491
3492 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3493 CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
3494
3495 // Limit to equal cost for branch vs. N v_cndmask_b32s.
3496 return RI.hasVGPRs(RC) && NumInsts <= 6;
3497 }
3498 case SCC_TRUE:
3499 case SCC_FALSE: {
3500 // FIXME: We could insert for VGPRs if we could replace the original compare
3501 // with a vector one.
3502 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3503 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3504 if (MRI.getRegClass(FalseReg) != RC)
3505 return false;
3506
3507 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3508
3509 // Multiples of 8 can do s_cselect_b64
3510 if (NumInsts % 2 == 0)
3511 NumInsts /= 2;
3512
3513 CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
3514 return RI.isSGPRClass(RC);
3515 }
3516 default:
3517 return false;
3518 }
3519}
3520
3524 Register TrueReg, Register FalseReg) const {
3525 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3526 if (Pred == VCCZ || Pred == SCC_FALSE) {
3527 Pred = static_cast<BranchPredicate>(-Pred);
3528 std::swap(TrueReg, FalseReg);
3529 }
3530
3531 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3532 const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
3533 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3534
3535 if (DstSize == 32) {
3537 if (Pred == SCC_TRUE) {
3538 Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
3539 .addReg(TrueReg)
3540 .addReg(FalseReg);
3541 } else {
3542 // Instruction's operands are backwards from what is expected.
3543 Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
3544 .addReg(FalseReg)
3545 .addReg(TrueReg);
3546 }
3547
3548 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3549 return;
3550 }
3551
3552 if (DstSize == 64 && Pred == SCC_TRUE) {
3554 BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
3555 .addReg(TrueReg)
3556 .addReg(FalseReg);
3557
3558 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3559 return;
3560 }
3561
3562 static const int16_t Sub0_15[] = {
3563 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3564 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3565 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3566 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3567 };
3568
3569 static const int16_t Sub0_15_64[] = {
3570 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3571 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3572 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3573 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3574 };
3575
3576 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3577 const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
3578 const int16_t *SubIndices = Sub0_15;
3579 int NElts = DstSize / 32;
3580
3581 // 64-bit select is only available for SALU.
3582 // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
3583 if (Pred == SCC_TRUE) {
3584 if (NElts % 2) {
3585 SelOp = AMDGPU::S_CSELECT_B32;
3586 EltRC = &AMDGPU::SGPR_32RegClass;
3587 } else {
3588 SelOp = AMDGPU::S_CSELECT_B64;
3589 EltRC = &AMDGPU::SGPR_64RegClass;
3590 SubIndices = Sub0_15_64;
3591 NElts /= 2;
3592 }
3593 }
3594
3596 MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);
3597
3598 I = MIB->getIterator();
3599
3601 for (int Idx = 0; Idx != NElts; ++Idx) {
3602 Register DstElt = MRI.createVirtualRegister(EltRC);
3603 Regs.push_back(DstElt);
3604
3605 unsigned SubIdx = SubIndices[Idx];
3606
3608 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3609 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3610 .addReg(FalseReg, {}, SubIdx)
3611 .addReg(TrueReg, {}, SubIdx);
3612 } else {
3613 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3614 .addReg(TrueReg, {}, SubIdx)
3615 .addReg(FalseReg, {}, SubIdx);
3616 }
3617
3618 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3620
3621 MIB.addReg(DstElt)
3622 .addImm(SubIdx);
3623 }
3624}
3625
3627
3628 if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
3629 return true;
3630
3631 switch (MI.getOpcode()) {
3632 case AMDGPU::S_ENDPGM:
3633 case AMDGPU::S_ENDPGM_SAVED:
3634 case AMDGPU::S_TRAP:
3635 case AMDGPU::S_GETREG_B32:
3636 case AMDGPU::S_SETREG_B32:
3637 case AMDGPU::S_SETREG_B32_mode:
3638 case AMDGPU::S_SETREG_IMM32_B32:
3639 case AMDGPU::S_SETREG_IMM32_B32_mode:
3640 case AMDGPU::S_SENDMSG:
3641 case AMDGPU::S_SENDMSGHALT:
3642 case AMDGPU::S_SENDMSG_RTN_B32:
3643 case AMDGPU::S_SENDMSG_RTN_B64:
3644 case AMDGPU::S_BARRIER_WAIT:
3645 case AMDGPU::S_BARRIER_SIGNAL_M0:
3646 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3647 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3648 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3649 return true;
3650 default:
3651 return false;
3652 }
3653}
3654
3656 switch (MI.getOpcode()) {
3657 case AMDGPU::V_MOV_B16_t16_e32:
3658 case AMDGPU::V_MOV_B16_t16_e64:
3659 case AMDGPU::V_MOV_B32_e32:
3660 case AMDGPU::V_MOV_B32_e64:
3661 case AMDGPU::V_MOV_B64_PSEUDO:
3662 case AMDGPU::V_MOV_B64_e32:
3663 case AMDGPU::V_MOV_B64_e64:
3664 case AMDGPU::S_MOV_B32:
3665 case AMDGPU::S_MOV_B64:
3666 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3667 case AMDGPU::COPY:
3668 case AMDGPU::WWM_COPY:
3669 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3670 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3671 case AMDGPU::V_ACCVGPR_MOV_B32:
3672 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3673 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3674 return true;
3675 default:
3676 return false;
3677 }
3678}
3679
3681 switch (MI.getOpcode()) {
3682 case AMDGPU::V_MOV_B16_t16_e32:
3683 case AMDGPU::V_MOV_B16_t16_e64:
3684 return 2;
3685 case AMDGPU::V_MOV_B32_e32:
3686 case AMDGPU::V_MOV_B32_e64:
3687 case AMDGPU::V_MOV_B64_PSEUDO:
3688 case AMDGPU::V_MOV_B64_e32:
3689 case AMDGPU::V_MOV_B64_e64:
3690 case AMDGPU::S_MOV_B32:
3691 case AMDGPU::S_MOV_B64:
3692 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3693 case AMDGPU::COPY:
3694 case AMDGPU::WWM_COPY:
3695 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3696 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3697 case AMDGPU::V_ACCVGPR_MOV_B32:
3698 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3699 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3700 return 1;
3701 default:
3702 llvm_unreachable("MI is not a foldable copy");
3703 }
3704}
3705
3706static constexpr AMDGPU::OpName ModifierOpNames[] = {
3707 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3708 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3709 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3710
3712 unsigned Opc = MI.getOpcode();
3713 for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
3714 int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
3715 if (Idx >= 0)
3716 MI.removeOperand(Idx);
3717 }
3718}
3719
3721 const MCInstrDesc &NewDesc) const {
3722 MI.setDesc(NewDesc);
3723
3724 // Remove any leftover implicit operands from mutating the instruction. e.g.
3725 // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
3726 // anymore.
3727 const MCInstrDesc &Desc = MI.getDesc();
3728 unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
3729 Desc.implicit_defs().size();
3730
3731 for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
3732 MI.removeOperand(I);
3733}
3734
3735std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
3736 unsigned SubRegIndex) {
3737 switch (SubRegIndex) {
3738 case AMDGPU::NoSubRegister:
3739 return Imm;
3740 case AMDGPU::sub0:
3741 return SignExtend64<32>(Imm);
3742 case AMDGPU::sub1:
3743 return SignExtend64<32>(Imm >> 32);
3744 case AMDGPU::lo16:
3745 return SignExtend64<16>(Imm);
3746 case AMDGPU::hi16:
3747 return SignExtend64<16>(Imm >> 16);
3748 case AMDGPU::sub1_lo16:
3749 return SignExtend64<16>(Imm >> 32);
3750 case AMDGPU::sub1_hi16:
3751 return SignExtend64<16>(Imm >> 48);
3752 default:
3753 return std::nullopt;
3754 }
3755
3756 llvm_unreachable("covered subregister switch");
3757}
3758
3759static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
3760 switch (Opc) {
3761 case AMDGPU::V_MAC_F16_e32:
3762 case AMDGPU::V_MAC_F16_e64:
3763 case AMDGPU::V_MAD_F16_e64:
3764 return AMDGPU::V_MADAK_F16;
3765 case AMDGPU::V_MAC_F32_e32:
3766 case AMDGPU::V_MAC_F32_e64:
3767 case AMDGPU::V_MAD_F32_e64:
3768 return AMDGPU::V_MADAK_F32;
3769 case AMDGPU::V_FMAC_F32_e32:
3770 case AMDGPU::V_FMAC_F32_e64:
3771 case AMDGPU::V_FMA_F32_e64:
3772 return AMDGPU::V_FMAAK_F32;
3773 case AMDGPU::V_FMAC_F16_e32:
3774 case AMDGPU::V_FMAC_F16_e64:
3775 case AMDGPU::V_FMAC_F16_t16_e64:
3776 case AMDGPU::V_FMAC_F16_fake16_e64:
3777 case AMDGPU::V_FMAC_F16_t16_e32:
3778 case AMDGPU::V_FMAC_F16_fake16_e32:
3779 case AMDGPU::V_FMA_F16_e64:
3780 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3781 ? AMDGPU::V_FMAAK_F16_t16
3782 : AMDGPU::V_FMAAK_F16_fake16
3783 : AMDGPU::V_FMAAK_F16;
3784 case AMDGPU::V_FMAC_F64_e32:
3785 case AMDGPU::V_FMAC_F64_e64:
3786 case AMDGPU::V_FMA_F64_e64:
3787 return AMDGPU::V_FMAAK_F64;
3788 default:
3789 llvm_unreachable("invalid instruction");
3790 }
3791}
3792
3793static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
3794 switch (Opc) {
3795 case AMDGPU::V_MAC_F16_e32:
3796 case AMDGPU::V_MAC_F16_e64:
3797 case AMDGPU::V_MAD_F16_e64:
3798 return AMDGPU::V_MADMK_F16;
3799 case AMDGPU::V_MAC_F32_e32:
3800 case AMDGPU::V_MAC_F32_e64:
3801 case AMDGPU::V_MAD_F32_e64:
3802 return AMDGPU::V_MADMK_F32;
3803 case AMDGPU::V_FMAC_F32_e32:
3804 case AMDGPU::V_FMAC_F32_e64:
3805 case AMDGPU::V_FMA_F32_e64:
3806 return AMDGPU::V_FMAMK_F32;
3807 case AMDGPU::V_FMAC_F16_e32:
3808 case AMDGPU::V_FMAC_F16_e64:
3809 case AMDGPU::V_FMAC_F16_t16_e64:
3810 case AMDGPU::V_FMAC_F16_fake16_e64:
3811 case AMDGPU::V_FMAC_F16_t16_e32:
3812 case AMDGPU::V_FMAC_F16_fake16_e32:
3813 case AMDGPU::V_FMA_F16_e64:
3814 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3815 ? AMDGPU::V_FMAMK_F16_t16
3816 : AMDGPU::V_FMAMK_F16_fake16
3817 : AMDGPU::V_FMAMK_F16;
3818 case AMDGPU::V_FMAC_F64_e32:
3819 case AMDGPU::V_FMAC_F64_e64:
3820 case AMDGPU::V_FMA_F64_e64:
3821 return AMDGPU::V_FMAMK_F64;
3822 default:
3823 llvm_unreachable("invalid instruction");
3824 }
3825}
3826
3828 Register Reg, MachineRegisterInfo *MRI) const {
3829 int64_t Imm;
3830 if (!getConstValDefinedInReg(DefMI, Reg, Imm))
3831 return false;
3832
3833 const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);
3834
3835 assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");
3836
3837 unsigned Opc = UseMI.getOpcode();
3838 if (Opc == AMDGPU::COPY) {
3839 assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");
3840
3841 Register DstReg = UseMI.getOperand(0).getReg();
3842 Register UseSubReg = UseMI.getOperand(1).getSubReg();
3843
3844 const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);
3845
3846 if (HasMultipleUses) {
3847 // TODO: This should fold in more cases with multiple use, but we need to
3848 // more carefully consider what those uses are.
3849 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));
3850
3851 // Avoid breaking up a 64-bit inline immediate into a subregister extract.
3852 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3853 return false;
3854
3855 // Most of the time folding a 32-bit inline constant is free (though this
3856 // might not be true if we can't later fold it into a real user).
3857 //
3858 // FIXME: This isInlineConstant check is imprecise if
3859 // getConstValDefinedInReg handled the tricky non-mov cases.
3860 if (ImmDefSize == 32 &&
3862 return false;
3863 }
3864
3865 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3866 RI.getSubRegIdxSize(UseSubReg) == 16;
3867
3868 if (Is16Bit) {
3869 if (RI.hasVGPRs(DstRC))
3870 return false; // Do not clobber vgpr_hi16
3871
3872 if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
3873 return false;
3874 }
3875
3876 MachineFunction *MF = UseMI.getMF();
3877
3878 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3879 MCRegister MovDstPhysReg =
3880 DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();
3881
3882 std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);
3883
3884 // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
3885 for (unsigned MovOp :
3886 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3887 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3888 const MCInstrDesc &MovDesc = get(MovOp);
3889
3890 const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
3891 if (Is16Bit) {
3892 // We just need to find a correctly sized register class, so the
3893 // subregister index compatibility doesn't matter since we're statically
3894 // extracting the immediate value.
3895 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3896 if (!MovDstRC)
3897 continue;
3898
3899 if (MovDstPhysReg) {
3900 // FIXME: We probably should not do this. If there is a live value in
3901 // the high half of the register, it will be corrupted.
3902 MovDstPhysReg =
3903 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3904 if (!MovDstPhysReg)
3905 continue;
3906 }
3907 }
3908
3909 // Result class isn't the right size, try the next instruction.
3910 if (MovDstPhysReg) {
3911 if (!MovDstRC->contains(MovDstPhysReg))
3912 return false;
3913 } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
3914 // TODO: This will be overly conservative in the case of 16-bit virtual
3915 // SGPRs. We could hack up the virtual register uses to use a compatible
3916 // 32-bit class.
3917 continue;
3918 }
3919
3920 const MCOperandInfo &OpInfo = MovDesc.operands()[1];
3921
3922 // Ensure the interpreted immediate value is a valid operand in the new
3923 // mov.
3924 //
3925 // FIXME: isImmOperandLegal should have form that doesn't require existing
3926 // MachineInstr or MachineOperand
3927 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3928 !isInlineConstant(*SubRegImm, OpInfo.OperandType))
3929 break;
3930
3931 NewOpc = MovOp;
3932 break;
3933 }
3934
3935 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
3936 return false;
3937
3938 if (Is16Bit) {
3939 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
3940 if (MovDstPhysReg)
3941 UseMI.getOperand(0).setReg(MovDstPhysReg);
3942 assert(UseMI.getOperand(1).getReg().isVirtual());
3943 }
3944
3945 const MCInstrDesc &NewMCID = get(NewOpc);
3946 UseMI.setDesc(NewMCID);
3947 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
3948 UseMI.addImplicitDefUseOperands(*MF);
3949 return true;
3950 }
3951
3952 if (HasMultipleUses)
3953 return false;
3954
3955 if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
3956 Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
3957 Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
3958 Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
3959 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3960 Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
3961 Opc == AMDGPU::V_FMAC_F64_e64) {
3962 // Don't fold if we are using source or output modifiers. The new VOP2
3963 // instructions don't have them.
3965 return false;
3966
3967 // If this is a free constant, there's no reason to do this.
3968 // TODO: We could fold this here instead of letting SIFoldOperands do it
3969 // later.
3970 int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
3971
3972 // Any src operand can be used for the legality check.
3973 if (isInlineConstant(UseMI, Src0Idx, Imm))
3974 return false;
3975
3976 MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);
3977
3978 MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
3979 MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);
3980
3981 auto CopyRegOperandToNarrowerRC =
3982 [MRI, this](MachineInstr &MI, unsigned OpNo,
3983 const TargetRegisterClass *NewRC) -> void {
3984 if (!MI.getOperand(OpNo).isReg())
3985 return;
3986 Register Reg = MI.getOperand(OpNo).getReg();
3987 const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
3988 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
3989 return;
3990 Register Tmp = MRI->createVirtualRegister(NewRC);
3991 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
3992 get(AMDGPU::COPY), Tmp)
3993 .addReg(Reg);
3994 MI.getOperand(OpNo).setReg(Tmp);
3995 MI.getOperand(OpNo).setIsKill();
3996 };
3997
3998 // Multiplied part is the constant: Use v_madmk_{f16, f32}.
3999 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4000 (Src1->isReg() && Src1->getReg() == Reg)) {
4001 MachineOperand *RegSrc =
4002 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4003 if (!RegSrc->isReg())
4004 return false;
4005 if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
4006 ST.getConstantBusLimit(Opc) < 2)
4007 return false;
4008
4009 if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
4010 return false;
4011
4012 // If src2 is also a literal constant then we have to choose which one to
4013 // fold. In general it is better to choose madak so that the other literal
4014 // can be materialized in an sgpr instead of a vgpr:
4015 // s_mov_b32 s0, literal
4016 // v_madak_f32 v0, s0, v0, literal
4017 // Instead of:
4018 // v_mov_b32 v1, literal
4019 // v_madmk_f32 v0, v0, literal, v1
4020 MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
4021 if (Def && Def->isMoveImmediate() &&
4022 !isInlineConstant(Def->getOperand(1)))
4023 return false;
4024
4025 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4026 if (pseudoToMCOpcode(NewOpc) == -1)
4027 return false;
4028
4029 const std::optional<int64_t> SubRegImm = extractSubregFromImm(
4030 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4031
4032 // FIXME: This would be a lot easier if we could return a new instruction
4033 // instead of having to modify in place.
4034
4035 Register SrcReg = RegSrc->getReg();
4036 unsigned SrcSubReg = RegSrc->getSubReg();
4037 Src0->setReg(SrcReg);
4038 Src0->setSubReg(SrcSubReg);
4039 Src0->setIsKill(RegSrc->isKill());
4040
4041 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4042 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4043 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4044 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4045 UseMI.untieRegOperand(
4046 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4047
4048 Src1->ChangeToImmediate(*SubRegImm);
4049
4051 UseMI.setDesc(get(NewOpc));
4052
4053 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4054 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4055 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4056 Register Tmp = MRI->createVirtualRegister(NewRC);
4057 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4058 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4059 UseMI.getOperand(0).getReg())
4060 .addReg(Tmp, RegState::Kill);
4061 UseMI.getOperand(0).setReg(Tmp);
4062 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4063 CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
4064 }
4065
4066 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4067 if (DeleteDef)
4068 DefMI.eraseFromParent();
4069
4070 return true;
4071 }
4072
4073 // Added part is the constant: Use v_madak_{f16, f32}.
4074 if (Src2->isReg() && Src2->getReg() == Reg) {
4075 if (ST.getConstantBusLimit(Opc) < 2) {
4076 // Not allowed to use constant bus for another operand.
4077 // We can however allow an inline immediate as src0.
4078 bool Src0Inlined = false;
4079 if (Src0->isReg()) {
4080 // Try to inline constant if possible.
4081 // If the Def moves immediate and the use is single
4082 // We are saving VGPR here.
4083 MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
4084 if (Def && Def->isMoveImmediate() &&
4085 isInlineConstant(Def->getOperand(1)) &&
4086 MRI->hasOneNonDBGUse(Src0->getReg())) {
4087 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4088 Src0Inlined = true;
4089 } else if (ST.getConstantBusLimit(Opc) <= 1 &&
4090 RI.isSGPRReg(*MRI, Src0->getReg())) {
4091 return false;
4092 }
4093 // VGPR is okay as Src0 - fallthrough
4094 }
4095
4096 if (Src1->isReg() && !Src0Inlined) {
4097 // We have one slot for inlinable constant so far - try to fill it
4098 MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
4099 if (Def && Def->isMoveImmediate() &&
4100 isInlineConstant(Def->getOperand(1)) &&
4101 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
4102 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4103 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
4104 return false;
4105 // VGPR is okay as Src1 - fallthrough
4106 }
4107 }
4108
4109 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4110 if (pseudoToMCOpcode(NewOpc) == -1)
4111 return false;
4112
4113 // FIXME: This would be a lot easier if we could return a new instruction
4114 // instead of having to modify in place.
4115
4116 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4117 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4118 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4119 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4120 UseMI.untieRegOperand(
4121 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4122
4123 const std::optional<int64_t> SubRegImm =
4125
4126 // ChangingToImmediate adds Src2 back to the instruction.
4127 Src2->ChangeToImmediate(*SubRegImm);
4128
4129 // These come before src2.
4131 UseMI.setDesc(get(NewOpc));
4132
4133 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4134 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4135 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4136 Register Tmp = MRI->createVirtualRegister(NewRC);
4137 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4138 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4139 UseMI.getOperand(0).getReg())
4140 .addReg(Tmp, RegState::Kill);
4141 UseMI.getOperand(0).setReg(Tmp);
4142 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4143 CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
4144 }
4145
4146 // It might happen that UseMI was commuted
4147 // and we now have SGPR as SRC1. If so 2 inlined
4148 // constant and SGPR are illegal.
4150
4151 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4152 if (DeleteDef)
4153 DefMI.eraseFromParent();
4154
4155 return true;
4156 }
4157 }
4158
4159 return false;
4160}
4161
4162static bool
4165 if (BaseOps1.size() != BaseOps2.size())
4166 return false;
4167 for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
4168 if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
4169 return false;
4170 }
4171 return true;
4172}
4173
4174static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
4175 LocationSize WidthB, int OffsetB) {
4176 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4177 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4178 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4179 return LowWidth.hasValue() &&
4180 LowOffset + (int)LowWidth.getValue() <= HighOffset;
4181}
4182
4183bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
4184 const MachineInstr &MIb) const {
4185 SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
4186 int64_t Offset0, Offset1;
4187 LocationSize Dummy0 = LocationSize::precise(0);
4188 LocationSize Dummy1 = LocationSize::precise(0);
4189 bool Offset0IsScalable, Offset1IsScalable;
4190 if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
4191 Dummy0, &RI) ||
4192 !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
4193 Dummy1, &RI))
4194 return false;
4195
4196 if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
4197 return false;
4198
4199 if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
4200 // FIXME: Handle ds_read2 / ds_write2.
4201 return false;
4202 }
4203 LocationSize Width0 = MIa.memoperands().front()->getSize();
4204 LocationSize Width1 = MIb.memoperands().front()->getSize();
4205 return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
4206}
4207
4209 const MachineInstr &MIb) const {
4210 assert(MIa.mayLoadOrStore() &&
4211 "MIa must load from or modify a memory location");
4212 assert(MIb.mayLoadOrStore() &&
4213 "MIb must load from or modify a memory location");
4214
4216 return false;
4217
4218 // XXX - Can we relax this between address spaces?
4219 if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
4220 return false;
4221
4222 if (isLDSDMA(MIa) || isLDSDMA(MIb))
4223 return false;
4224
4225 if (MIa.isBundle() || MIb.isBundle())
4226 return false;
4227
4228 // TODO: Should we check the address space from the MachineMemOperand? That
4229 // would allow us to distinguish objects we know don't alias based on the
4230 // underlying address space, even if it was lowered to a different one,
4231 // e.g. private accesses lowered to use MUBUF instructions on a scratch
4232 // buffer.
4233 if (isDS(MIa)) {
4234 if (isDS(MIb))
4235 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4236
4237 return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
4238 }
4239
4240 if (isMUBUF(MIa) || isMTBUF(MIa)) {
4241 if (isMUBUF(MIb) || isMTBUF(MIb))
4242 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4243
4244 if (isFLAT(MIb))
4245 return isFLATScratch(MIb);
4246
4247 return !isSMRD(MIb);
4248 }
4249
4250 if (isSMRD(MIa)) {
4251 if (isSMRD(MIb))
4252 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4253
4254 if (isFLAT(MIb))
4255 return isFLATScratch(MIb);
4256
4257 return !isMUBUF(MIb) && !isMTBUF(MIb);
4258 }
4259
4260 if (isFLAT(MIa)) {
4261 if (isFLAT(MIb)) {
4262 if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
4263 (isFLATGlobal(MIa) && isFLATScratch(MIb)))
4264 return true;
4265
4266 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4267 }
4268
4269 return false;
4270 }
4271
4272 return false;
4273}
4274
4276 MachineInstr &NewMI) {
4277 if (LV) {
4278 unsigned NumOps = MI.getNumOperands();
4279 for (unsigned I = 1; I < NumOps; ++I) {
4280 MachineOperand &Op = MI.getOperand(I);
4281 if (Op.isReg() && Op.isKill())
4282 LV->replaceKillInstruction(Op.getReg(), MI, NewMI);
4283 }
4284 }
4285}
4286
4287static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
4288 switch (Opc) {
4289 case AMDGPU::V_MAC_F16_e32:
4290 case AMDGPU::V_MAC_F16_e64:
4291 return AMDGPU::V_MAD_F16_e64;
4292 case AMDGPU::V_MAC_F32_e32:
4293 case AMDGPU::V_MAC_F32_e64:
4294 return AMDGPU::V_MAD_F32_e64;
4295 case AMDGPU::V_MAC_LEGACY_F32_e32:
4296 case AMDGPU::V_MAC_LEGACY_F32_e64:
4297 return AMDGPU::V_MAD_LEGACY_F32_e64;
4298 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4299 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4300 return AMDGPU::V_FMA_LEGACY_F32_e64;
4301 case AMDGPU::V_FMAC_F16_e32:
4302 case AMDGPU::V_FMAC_F16_e64:
4303 case AMDGPU::V_FMAC_F16_t16_e64:
4304 case AMDGPU::V_FMAC_F16_fake16_e64:
4305 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4306 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4307 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4308 : AMDGPU::V_FMA_F16_gfx9_e64;
4309 case AMDGPU::V_FMAC_F32_e32:
4310 case AMDGPU::V_FMAC_F32_e64:
4311 return AMDGPU::V_FMA_F32_e64;
4312 case AMDGPU::V_FMAC_F64_e32:
4313 case AMDGPU::V_FMAC_F64_e64:
4314 return AMDGPU::V_FMA_F64_e64;
4315 default:
4316 llvm_unreachable("invalid instruction");
4317 }
4318}
4319
4320/// Helper struct for the implementation of 3-address conversion to communicate
4321/// updates made to instruction operands.
4323 /// Other instruction whose def is no longer used by the converted
4324 /// instruction.
4326};
4327
4329 LiveVariables *LV,
4330 LiveIntervals *LIS) const {
4331 MachineBasicBlock &MBB = *MI.getParent();
4332 MachineInstr *CandidateMI = &MI;
4333
4334 if (MI.isBundle()) {
4335 // This is a temporary placeholder for bundle handling that enables us to
4336 // exercise the relevant code paths in the two-address instruction pass.
4337 if (MI.getBundleSize() != 1)
4338 return nullptr;
4339 CandidateMI = MI.getNextNode();
4340 }
4341
4343 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4344 if (!NewMI)
4345 return nullptr;
4346
4347 if (MI.isBundle()) {
4348 CandidateMI->eraseFromBundle();
4349
4350 for (MachineOperand &MO : MI.all_defs()) {
4351 if (MO.isTied())
4352 MI.untieRegOperand(MO.getOperandNo());
4353 }
4354 } else {
4355 updateLiveVariables(LV, MI, *NewMI);
4356 if (LIS) {
4357 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
4358 // SlotIndex of defs needs to be updated when converting to early-clobber
4359 MachineOperand &Def = NewMI->getOperand(0);
4360 if (Def.isEarlyClobber() && Def.isReg() &&
4361 LIS->hasInterval(Def.getReg())) {
4362 SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
4363 SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
4364 auto &LI = LIS->getInterval(Def.getReg());
4365 auto UpdateDefIndex = [&](LiveRange &LR) {
4366 auto *S = LR.find(OldIndex);
4367 if (S != LR.end() && S->start == OldIndex) {
4368 assert(S->valno && S->valno->def == OldIndex);
4369 S->start = NewIndex;
4370 S->valno->def = NewIndex;
4371 }
4372 };
4373 UpdateDefIndex(LI);
4374 for (auto &SR : LI.subranges())
4375 UpdateDefIndex(SR);
4376 }
4377 }
4378 }
4379
4380 if (U.RemoveMIUse) {
4381 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4382 // The only user is the instruction which will be killed.
4383 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4384
4385 if (MRI.hasOneNonDBGUse(DefReg)) {
4386 // We cannot just remove the DefMI here, calling pass will crash.
4387 U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
4388 U.RemoveMIUse->getOperand(0).setIsDead(true);
4389 for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
4390 U.RemoveMIUse->removeOperand(I);
4391 if (LV)
4392 LV->getVarInfo(DefReg).AliveBlocks.clear();
4393 }
4394
4395 if (MI.isBundle()) {
4396 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4397 if (!VRI.Reads && !VRI.Writes) {
4398 for (MachineOperand &MO : MI.all_uses()) {
4399 if (MO.isReg() && MO.getReg() == DefReg) {
4400 assert(MO.getSubReg() == 0 &&
4401 "tied sub-registers in bundles currently not supported");
4402 MI.removeOperand(MO.getOperandNo());
4403 break;
4404 }
4405 }
4406
4407 if (LIS)
4408 LIS->shrinkToUses(&LIS->getInterval(DefReg));
4409 }
4410 } else if (LIS) {
4411 LiveInterval &DefLI = LIS->getInterval(DefReg);
4412
4413 // We cannot delete the original instruction here, so hack out the use
4414 // in the original instruction with a dummy register so we can use
4415 // shrinkToUses to deal with any multi-use edge cases. Other targets do
4416 // not have the complexity of deleting a use to consider here.
4417 Register DummyReg = MRI.cloneVirtualRegister(DefReg);
4418 for (MachineOperand &MIOp : MI.uses()) {
4419 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4420 MIOp.setIsUndef(true);
4421 MIOp.setReg(DummyReg);
4422 }
4423 }
4424
4425 if (MI.isBundle()) {
4426 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4427 if (!VRI.Reads && !VRI.Writes) {
4428 for (MachineOperand &MIOp : MI.uses()) {
4429 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4430 MIOp.setIsUndef(true);
4431 MIOp.setReg(DummyReg);
4432 }
4433 }
4434 }
4435
4436 MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
4437 false, /*isUndef=*/true));
4438 }
4439
4440 LIS->shrinkToUses(&DefLI);
4441 }
4442 }
4443
4444 return MI.isBundle() ? &MI : NewMI;
4445}
4446
4448SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
4449 ThreeAddressUpdates &U) const {
4450 MachineBasicBlock &MBB = *MI.getParent();
4451 unsigned Opc = MI.getOpcode();
4452
4453 // Handle MFMA.
4454 int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
4455 if (NewMFMAOpc != -1) {
4457 BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
4458 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4459 MIB.add(MI.getOperand(I));
4460 return MIB;
4461 }
4462
4463 if (SIInstrInfo::isWMMA(MI)) {
4464 unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
4465 MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4466 .setMIFlags(MI.getFlags());
4467 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4468 MIB->addOperand(MI.getOperand(I));
4469 return MIB;
4470 }
4471
4472 assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4473 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4474 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4475 "present pre-RA");
4476
4477 // Handle MAC/FMAC.
4478 bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
4479 bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4480 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4481 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4482 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4483 bool Src0Literal = false;
4484
4485 switch (Opc) {
4486 default:
4487 return nullptr;
4488 case AMDGPU::V_MAC_F16_e64:
4489 case AMDGPU::V_FMAC_F16_e64:
4490 case AMDGPU::V_FMAC_F16_t16_e64:
4491 case AMDGPU::V_FMAC_F16_fake16_e64:
4492 case AMDGPU::V_MAC_F32_e64:
4493 case AMDGPU::V_MAC_LEGACY_F32_e64:
4494 case AMDGPU::V_FMAC_F32_e64:
4495 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4496 case AMDGPU::V_FMAC_F64_e64:
4497 break;
4498 case AMDGPU::V_MAC_F16_e32:
4499 case AMDGPU::V_FMAC_F16_e32:
4500 case AMDGPU::V_MAC_F32_e32:
4501 case AMDGPU::V_MAC_LEGACY_F32_e32:
4502 case AMDGPU::V_FMAC_F32_e32:
4503 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4504 case AMDGPU::V_FMAC_F64_e32: {
4505 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
4506 AMDGPU::OpName::src0);
4507 const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
4508 if (!Src0->isReg() && !Src0->isImm())
4509 return nullptr;
4510
4511 if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
4512 Src0Literal = true;
4513
4514 break;
4515 }
4516 }
4517
4518 MachineInstrBuilder MIB;
4519 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
4520 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
4521 const MachineOperand *Src0Mods =
4522 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
4523 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4524 const MachineOperand *Src1Mods =
4525 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
4526 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4527 const MachineOperand *Src2Mods =
4528 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
4529 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
4530 const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
4531 const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);
4532
4533 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4534 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4535 // If we have an SGPR input, we will violate the constant bus restriction.
4536 (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
4537 !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
4538 MachineInstr *DefMI = nullptr;
4539 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4540 std::optional<int64_t> ImmOpt;
4541 int64_t Imm;
4542
4543 if (!Src0Literal &&
4544 (ImmOpt = getImmOrMaterializedImm(MRI, *Src2, &DefMI))) {
4545 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4546 if (pseudoToMCOpcode(NewOpc) != -1) {
4547 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4548 .add(*Dst)
4549 .add(*Src0)
4550 .add(*Src1)
4551 .addImm(*ImmOpt)
4552 .setMIFlags(MI.getFlags());
4553 U.RemoveMIUse = DefMI;
4554 return MIB;
4555 }
4556 }
4557 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4558 if (!Src0Literal &&
4559 (ImmOpt = getImmOrMaterializedImm(MRI, *Src1, &DefMI))) {
4560 if (pseudoToMCOpcode(NewOpc) != -1) {
4561 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4562 .add(*Dst)
4563 .add(*Src0)
4564 .addImm(*ImmOpt)
4565 .add(*Src2)
4566 .setMIFlags(MI.getFlags());
4567 U.RemoveMIUse = DefMI;
4568 return MIB;
4569 }
4570 }
4571 if ((ImmOpt = getImmOrMaterializedImm(MRI, *Src0, &DefMI))) {
4572 Imm = *ImmOpt;
4573 if (pseudoToMCOpcode(NewOpc) != -1 &&
4575 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4576 Src1)) {
4577 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4578 .add(*Dst)
4579 .add(*Src1)
4580 .addImm(Imm)
4581 .add(*Src2)
4582 .setMIFlags(MI.getFlags());
4583 U.RemoveMIUse = DefMI;
4584 return MIB;
4585 }
4586 }
4587 }
4588
4589 // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
4590 // if VOP3 does not allow a literal operand.
4591 if (Src0Literal && !ST.hasVOP3Literal())
4592 return nullptr;
4593
4594 unsigned NewOpc = getNewFMAInst(ST, Opc);
4595
4596 if (pseudoToMCOpcode(NewOpc) == -1)
4597 return nullptr;
4598
4599 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4600 .add(*Dst)
4601 .addImm(Src0Mods ? Src0Mods->getImm() : 0)
4602 .add(*Src0)
4603 .addImm(Src1Mods ? Src1Mods->getImm() : 0)
4604 .add(*Src1)
4605 .addImm(Src2Mods ? Src2Mods->getImm() : 0)
4606 .add(*Src2)
4607 .addImm(Clamp ? Clamp->getImm() : 0)
4608 .addImm(Omod ? Omod->getImm() : 0)
4609 .setMIFlags(MI.getFlags());
4610 if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
4611 MIB.addImm(OpSel ? OpSel->getImm() : 0);
4612 return MIB;
4613}
4614
4615// It's not generally safe to move VALU instructions across these since it will
4616// start using the register as a base index rather than directly.
4617// XXX - Why isn't hasSideEffects sufficient for these?
4619 switch (MI.getOpcode()) {
4620 case AMDGPU::S_SET_GPR_IDX_ON:
4621 case AMDGPU::S_SET_GPR_IDX_MODE:
4622 case AMDGPU::S_SET_GPR_IDX_OFF:
4623 return true;
4624 default:
4625 return false;
4626 }
4627}
4628
4630 const MachineBasicBlock *MBB,
4631 const MachineFunction &MF) const {
4632 // Skipping the check for SP writes in the base implementation. The reason it
4633 // was added was apparently due to compile time concerns.
4634 //
4635 // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
4636 // but is probably avoidable.
4637
4638 // Copied from base implementation.
4639 // Terminators and labels can't be scheduled around.
4640 if (MI.isTerminator() || MI.isPosition())
4641 return true;
4642
4643 // INLINEASM_BR can jump to another block
4644 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4645 return true;
4646
4647 if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
4648 return true;
4649
4650 // Target-independent instructions do not have an implicit-use of EXEC, even
4651 // when they operate on VGPRs. Treating EXEC modifications as scheduling
4652 // boundaries prevents incorrect movements of such instructions.
4653 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4654 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4655 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4656 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4657 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4659}
4660
4662 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4663 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4664 Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
4665}
4666
4668 // Instructions that access scratch use FLAT encoding or BUF encodings.
4669 if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
4670 return false;
4671
4672 // SCRATCH instructions always access scratch.
4673 if (isFLATScratch(MI))
4674 return true;
4675
4676 // If FLAT_SCRATCH registers are not initialized, we can never access scratch
4677 // via the aperture.
4678 if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
4679 return false;
4680
4681 // If there are no memory operands then conservatively assume the flat
4682 // operation may access scratch.
4683 if (MI.memoperands_empty())
4684 return true;
4685
4686 // See if any memory operand specifies an address space that involves scratch.
4687 return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
4688 unsigned AS = Memop->getAddrSpace();
4689 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4690 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4691 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4692 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4693 }
4694 return AS == AMDGPUAS::PRIVATE_ADDRESS;
4695 });
4696}
4697
4699 assert(isFLAT(MI));
4700
4701 // All flat instructions use the VMEM counter except prefetch.
4702 if (!usesVM_CNT(MI))
4703 return false;
4704
4705 // If there are no memory operands then conservatively assume the flat
4706 // operation may access VMEM.
4707 if (MI.memoperands_empty())
4708 return true;
4709
4710 // See if any memory operand specifies an address space that involves VMEM.
4711 // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
4712 // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
4713 // (GDS) address space is not supported by flat operations. Therefore, simply
4714 // return true unless only the LDS address space is found.
4715 for (const MachineMemOperand *Memop : MI.memoperands()) {
4716 unsigned AS = Memop->getAddrSpace();
4718 if (AS != AMDGPUAS::LOCAL_ADDRESS)
4719 return true;
4720 }
4721
4722 return false;
4723}
4724
4726 bool TgSplit) const {
4727 assert(isFLAT(MI));
4728
4729 // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
4730 if (!usesLGKM_CNT(MI))
4731 return false;
4732
4733 // If in tgsplit mode then there can be no use of LDS.
4734 if (TgSplit)
4735 return false;
4736
4737 // If there are no memory operands then conservatively assume the flat
4738 // operation may access LDS.
4739 if (MI.memoperands_empty())
4740 return true;
4741
4742 // See if any memory operand specifies an address space that involves LDS.
4743 for (const MachineMemOperand *Memop : MI.memoperands()) {
4744 unsigned AS = Memop->getAddrSpace();
4746 return true;
4747 }
4748
4749 return false;
4750}
4751
4753 // Skip the full operand and register alias search modifiesRegister
4754 // does. There's only a handful of instructions that touch this, it's only an
4755 // implicit def, and doesn't alias any other registers.
4756 return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
4757}
4758
4760 unsigned Opcode = MI.getOpcode();
4761
4762 if (MI.mayStore() && isSMRD(MI))
4763 return true; // scalar store or atomic
4764
4765 // This will terminate the function when other lanes may need to continue.
4766 if (MI.isReturn())
4767 return true;
4768
4769 // These instructions cause shader I/O that may cause hardware lockups
4770 // when executed with an empty EXEC mask.
4771 //
4772 // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
4773 // EXEC = 0, but checking for that case here seems not worth it
4774 // given the typical code patterns.
4775 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4776 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4777 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4778 Opcode == AMDGPU::S_SETHALT)
4779 return true;
4780
4781 if (MI.isCall() || MI.isInlineAsm())
4782 return true; // conservative assumption
4783
4784 // Assume that barrier interactions are only intended with active lanes.
4785 if (isBarrier(Opcode))
4786 return true;
4787
4788 // A mode change is a scalar operation that influences vector instructions.
4790 return true;
4791
4792 // These are like SALU instructions in terms of effects, so it's questionable
4793 // whether we should return true for those.
4794 //
4795 // However, executing them with EXEC = 0 causes them to operate on undefined
4796 // data, which we avoid by returning true here.
4797 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4798 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4799 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4800 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4801 return true;
4802
4803 return false;
4804}
4805
4807 const MachineInstr &MI) const {
4808 if (MI.isMetaInstruction())
4809 return false;
4810
4811 // This won't read exec if this is an SGPR->SGPR copy.
4812 if (MI.isCopyLike()) {
4813 if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
4814 return true;
4815
4816 // Make sure this isn't copying exec as a normal operand
4817 return MI.readsRegister(AMDGPU::EXEC, &RI);
4818 }
4819
4820 // Make a conservative assumption about the callee.
4821 if (MI.isCall())
4822 return true;
4823
4824 // Be conservative with any unhandled generic opcodes.
4825 if (!isTargetSpecificOpcode(MI.getOpcode()))
4826 return true;
4827
4828 return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
4829}
4830
4832 switch (Imm.getBitWidth()) {
4833 case 1: // This likely will be a condition code mask.
4834 return true;
4835
4836 case 32:
4837 return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
4838 ST.hasInv2PiInlineImm());
4839 case 64:
4840 return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
4841 ST.hasInv2PiInlineImm());
4842 case 16:
4843 return ST.has16BitInsts() &&
4844 AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
4845 ST.hasInv2PiInlineImm());
4846 default:
4847 llvm_unreachable("invalid bitwidth");
4848 }
4849}
4850
4852 APInt IntImm = Imm.bitcastToAPInt();
4853 int64_t IntImmVal = IntImm.getSExtValue();
4854 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4855 switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
4856 default:
4857 llvm_unreachable("invalid fltSemantics");
4860 return isInlineConstant(IntImm);
4862 return ST.has16BitInsts() &&
4863 AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
4865 return ST.has16BitInsts() &&
4866 AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
4867 }
4868}
4869
4870bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
4871 // MachineOperand provides no way to tell the true operand size, since it only
4872 // records a 64-bit value. We need to know the size to determine if a 32-bit
4873 // floating point immediate bit pattern is legal for an integer immediate. It
4874 // would be for any 32-bit integer operand, but would not be for a 64-bit one.
4875 switch (OperandType) {
4885 int32_t Trunc = static_cast<int32_t>(Imm);
4886 return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
4887 }
4895 return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
4898 // We would expect inline immediates to not be concerned with an integer/fp
4899 // distinction. However, in the case of 16-bit integer operations, the
4900 // "floating point" values appear to not work. It seems read the low 16-bits
4901 // of 32-bit immediates, which happens to always work for the integer
4902 // values.
4903 //
4904 // See llvm bugzilla 46302.
4905 //
4906 // TODO: Theoretically we could use op-sel to use the high bits of the
4907 // 32-bit FP values.
4916 return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
4921 return false;
4924 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
4925 // A few special case instructions have 16-bit operands on subtargets
4926 // where 16-bit instructions are not legal.
4927 // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
4928 // constants in these cases
4929 int16_t Trunc = static_cast<int16_t>(Imm);
4930 return ST.has16BitInsts() &&
4931 AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
4932 }
4933
4934 return false;
4935 }
4938 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
4939 int16_t Trunc = static_cast<int16_t>(Imm);
4940 return ST.has16BitInsts() &&
4941 AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
4942 }
4943 return false;
4944 }
4948 return false;
4950 return isLegalAV64PseudoImm(Imm);
4953 // Always embedded in the instruction for free.
4954 return true;
4964 // Just ignore anything else.
4965 return false;
4966 default:
4967 llvm_unreachable("invalid operand type");
4968 }
4969}
4970
4971static bool compareMachineOp(const MachineOperand &Op0,
4972 const MachineOperand &Op1) {
4973 if (Op0.getType() != Op1.getType())
4974 return false;
4975
4976 switch (Op0.getType()) {
4978 return Op0.getReg() == Op1.getReg();
4980 return Op0.getImm() == Op1.getImm();
4981 default:
4982 llvm_unreachable("Didn't expect to be comparing these operand types");
4983 }
4984}
4985
4987 const MCOperandInfo &OpInfo) const {
4988 if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
4989 return true;
4990
4991 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
4992 return false;
4993
4994 if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
4995 return true;
4996
4997 return ST.hasVOP3Literal();
4998}
4999
5000bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5001 int64_t ImmVal) const {
5002 const unsigned Opc = InstDesc.getOpcode();
5003 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
5004 if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
5005 OpNo == static_cast<unsigned>(Src1Idx))
5006 return false;
5007
5008 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5009 if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
5010 if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5011 OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
5012 AMDGPU::OpName::src2))
5013 return false;
5014
5015 if (ST.hasBF16InlineConstFromUpperFP32() && isVOP1(Opc)) {
5016 if ((OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_BF16 ||
5017 OpInfo.OperandType == AMDGPU::OPERAND_REG_INLINE_C_BF16) &&
5018 isInlineConstant(ImmVal, OpInfo.OperandType))
5019 return false;
5020 }
5021
5022 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5023 }
5024
5025 return isLiteralOperandLegal(InstDesc, OpInfo);
5026}
5027
5028bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5029 const MachineOperand &MO) const {
5030 if (MO.isImm())
5031 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
5032
5033 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
5034 "unexpected imm-like operand kind");
5035 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5036 return isLiteralOperandLegal(InstDesc, OpInfo);
5037}
5038
5040 // 2 32-bit inline constants packed into one.
5041 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
5042 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
5043}
5044
5045bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
5046 // GFX90A does not have V_MUL_LEGACY_F32_e32.
5047 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5048 return false;
5049
5050 int Op32 = AMDGPU::getVOPe32(Opcode);
5051 if (Op32 == -1)
5052 return false;
5053
5054 return pseudoToMCOpcode(Op32) != -1;
5055}
5056
5057bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
5058 // The src0_modifier operand is present on all instructions
5059 // that have modifiers.
5060
5061 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
5062}
5063
5065 AMDGPU::OpName OpName) const {
5066 const MachineOperand *Mods = getNamedOperand(MI, OpName);
5067 return Mods && Mods->getImm();
5068}
5069
5071 return any_of(ModifierOpNames,
5072 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
5073}
5074
5076 const MachineRegisterInfo &MRI) const {
5077 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5078 // Can't shrink instruction with three operands.
5079 if (Src2) {
5080 switch (MI.getOpcode()) {
5081 default: return false;
5082
5083 case AMDGPU::V_ADDC_U32_e64:
5084 case AMDGPU::V_SUBB_U32_e64:
5085 case AMDGPU::V_SUBBREV_U32_e64: {
5086 const MachineOperand *Src1
5087 = getNamedOperand(MI, AMDGPU::OpName::src1);
5088 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
5089 return false;
5090 // Additional verification is needed for sdst/src2.
5091 return true;
5092 }
5093 case AMDGPU::V_MAC_F16_e64:
5094 case AMDGPU::V_MAC_F32_e64:
5095 case AMDGPU::V_MAC_LEGACY_F32_e64:
5096 case AMDGPU::V_FMAC_F16_e64:
5097 case AMDGPU::V_FMAC_F16_t16_e64:
5098 case AMDGPU::V_FMAC_F16_fake16_e64:
5099 case AMDGPU::V_FMAC_F32_e64:
5100 case AMDGPU::V_FMAC_F64_e64:
5101 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5102 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
5103 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
5104 return false;
5105 break;
5106
5107 case AMDGPU::V_CNDMASK_B32_e64:
5108 break;
5109 }
5110 }
5111
5112 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
5113 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5114 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
5115 return false;
5116
5117 // Make sure src0 isn't using any modifiers.
5118 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
5119 return false;
5120
5121 // Can it be shrunk to a valid 32 bit opcode?
5122 if (!hasVALU32BitEncoding(MI.getOpcode()))
5123 return false;
5124
5125 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
5126 if (Src0 && Src0->isImm()) {
5127 unsigned Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5128 if (!isImmOperandLegal(
5129 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5130 *Src0))
5131 return false;
5132 }
5133
5134 // Check output modifiers
5135 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
5136 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
5137 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
5138 // TODO: Can we avoid checking bound_ctrl/fi here?
5139 // They are only used by permlane*_swap special case.
5140 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
5141 !hasModifiersSet(MI, AMDGPU::OpName::fi);
5142}
5143
5144// Set VCC operand with all flags from \p Orig, except for setting it as
5145// implicit.
5147 const MachineOperand &Orig) {
5148
5149 for (MachineOperand &Use : MI.implicit_operands()) {
5150 if (Use.isUse() &&
5151 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
5152 Use.setIsUndef(Orig.isUndef());
5153 Use.setIsKill(Orig.isKill());
5154 return;
5155 }
5156 }
5157}
5158
5160 unsigned Op32) const {
5161 MachineBasicBlock *MBB = MI.getParent();
5162
5163 const MCInstrDesc &Op32Desc = get(Op32);
5164 MachineInstrBuilder Inst32 =
5165 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
5166 .setMIFlags(MI.getFlags());
5167
5168 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
5169 // For VOPC instructions, this is replaced by an implicit def of vcc.
5170
5171 // We assume the defs of the shrunk opcode are in the same order, and the
5172 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
5173 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
5174 Inst32.add(MI.getOperand(I));
5175
5176 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5177
5178 int Idx = MI.getNumExplicitDefs();
5179 for (const MachineOperand &Use : MI.explicit_uses()) {
5180 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
5182 continue;
5183
5184 if (&Use == Src2) {
5185 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5186 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
5187 // replaced with an implicit read of vcc or vcc_lo. The implicit read
5188 // of vcc was already added during the initial BuildMI, but we
5189 // 1) may need to change vcc to vcc_lo to preserve the original register
5190 // 2) have to preserve the original flags.
5191 copyFlagsToImplicitVCC(*Inst32, *Src2);
5192 continue;
5193 }
5194 }
5195
5196 Inst32.add(Use);
5197 }
5198
5199 // FIXME: Losing implicit operands
5200 fixImplicitOperands(*Inst32);
5201 return Inst32;
5202}
5203
5205 // Null is free
5206 Register Reg = RegOp.getReg();
5207 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5208 return false;
5209
5210 // SGPRs use the constant bus
5211
5212 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
5213 // physical register operands should also count, except for exec.
5214 if (RegOp.isImplicit())
5215 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5216
5217 // SGPRs use the constant bus
5218 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5219 AMDGPU::SReg_64RegClass.contains(Reg);
5220}
5221
5223 const MachineRegisterInfo &MRI) const {
5224 Register Reg = RegOp.getReg();
5225 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5226 : physRegUsesConstantBus(RegOp);
5227}
5228
5230 const MachineOperand &MO,
5231 const MCOperandInfo &OpInfo) const {
5232 // Literal constants use the constant bus.
5233 if (!MO.isReg())
5234 return !isInlineConstant(MO, OpInfo);
5235
5236 Register Reg = MO.getReg();
5237 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5239}
5240
5242 for (const MachineOperand &MO : MI.implicit_operands()) {
5243 // We only care about reads.
5244 if (MO.isDef())
5245 continue;
5246
5247 switch (MO.getReg()) {
5248 case AMDGPU::VCC:
5249 case AMDGPU::VCC_LO:
5250 case AMDGPU::VCC_HI:
5251 case AMDGPU::M0:
5252 case AMDGPU::FLAT_SCR:
5253 return MO.getReg();
5254
5255 default:
5256 break;
5257 }
5258 }
5259
5260 return Register();
5261}
5262
5263static bool shouldReadExec(const MachineInstr &MI) {
5264 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5265 switch (MI.getOpcode()) {
5266 case AMDGPU::V_READLANE_B32:
5267 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5268 case AMDGPU::V_WRITELANE_B32:
5269 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5270 return false;
5271 }
5272
5273 return true;
5274 }
5275
5276 if (MI.isPreISelOpcode() ||
5277 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5280 return false;
5281
5282 return true;
5283}
5284
5285static bool isRegOrFI(const MachineOperand &MO) {
5286 return MO.isReg() || MO.isFI();
5287}
5288
5289static bool isSubRegOf(const SIRegisterInfo &TRI,
5290 const MachineOperand &SuperVec,
5291 const MachineOperand &SubReg) {
5292 if (SubReg.getReg().isPhysical())
5293 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5294
5295 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5296 SubReg.getReg() == SuperVec.getReg();
5297}
5298
5299// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5300bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5301 const MachineRegisterInfo &MRI,
5302 StringRef &ErrInfo) const {
5303 Register DstReg = MI.getOperand(0).getReg();
5304 Register SrcReg = MI.getOperand(1).getReg();
5305 // This is a check for copy from vector register to SGPR
5306 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5307 ErrInfo = "illegal copy from vector register to SGPR";
5308 return false;
5309 }
5310 return true;
5311}
5312
5314 StringRef &ErrInfo) const {
5315 uint32_t Opcode = MI.getOpcode();
5316 const MachineFunction *MF = MI.getMF();
5317 const MachineRegisterInfo &MRI = MF->getRegInfo();
5318
5319 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5320 // Find a better property to recognize the point where instruction selection
5321 // is just done.
5322 // We can only enforce this check after SIFixSGPRCopies pass so that the
5323 // illegal copies are legalized and thereafter we don't expect a pass
5324 // inserting similar copies.
5325 if (!MRI.isSSA() && MI.isCopy())
5326 return verifyCopy(MI, MRI, ErrInfo);
5327
5328 if (SIInstrInfo::isGenericOpcode(Opcode))
5329 return true;
5330
5331 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5332 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5333 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5334 int Src3Idx = -1;
5335 if (Src0Idx == -1) {
5336 // VOPD V_DUAL_* instructions use different operand names.
5337 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5338 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5339 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5340 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5341 }
5342
5343 // Make sure the number of operands is correct.
5344 const MCInstrDesc &Desc = get(Opcode);
5345 if (!Desc.isVariadic() &&
5346 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5347 ErrInfo = "Instruction has wrong number of operands.";
5348 return false;
5349 }
5350
5351 if (MI.isInlineAsm()) {
5352 // Verify register classes for inlineasm constraints.
5353 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5354 I != E; ++I) {
5355 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5356 if (!RC)
5357 continue;
5358
5359 const MachineOperand &Op = MI.getOperand(I);
5360 if (!Op.isReg())
5361 continue;
5362
5363 Register Reg = Op.getReg();
5364 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5365 ErrInfo = "inlineasm operand has incorrect register class.";
5366 return false;
5367 }
5368 }
5369
5370 return true;
5371 }
5372
5373 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5374 ErrInfo = "missing memory operand from image instruction.";
5375 return false;
5376 }
5377
5378 // Make sure the register classes are correct.
5379 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5380 const MachineOperand &MO = MI.getOperand(i);
5381 if (MO.isFPImm()) {
5382 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5383 "all fp values to integers.";
5384 return false;
5385 }
5386
5387 const MCOperandInfo &OpInfo = Desc.operands()[i];
5388 int16_t RegClass = getOpRegClassID(OpInfo);
5389
5390 switch (OpInfo.OperandType) {
5392 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5393 ErrInfo = "Illegal immediate value for operand.";
5394 return false;
5395 }
5396 break;
5408 break;
5410 break;
5411 break;
5425 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5426 ErrInfo = "Illegal immediate value for operand.";
5427 return false;
5428 }
5429 break;
5430 }
5435 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5436 !isInlineConstant(MI, i) &&
5438 OpInfo.OperandType ==
5440 ErrInfo = "illegal 64-bit immediate value for operand.";
5441 return false;
5442 }
5443 break;
5446 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5447 ErrInfo = "Expected inline constant for operand.";
5448 return false;
5449 }
5450 break;
5453 break;
5458 // Check if this operand is an immediate.
5459 // FrameIndex operands will be replaced by immediates, so they are
5460 // allowed.
5461 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5462 ErrInfo = "Expected immediate, but got non-immediate";
5463 return false;
5464 }
5465 break;
5469 break;
5470 default:
5471 if (OpInfo.isGenericType())
5472 continue;
5473 break;
5474 }
5475
5476 if (!MO.isReg())
5477 continue;
5478 Register Reg = MO.getReg();
5479 if (!Reg)
5480 continue;
5481
5482 // FIXME: Ideally we would have separate instruction definitions with the
5483 // aligned register constraint.
5484 // FIXME: We do not verify inline asm operands, but custom inline asm
5485 // verification is broken anyway
5486 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5487 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !isSpill(MI)) {
5488 const TargetRegisterClass *RC = RI.getRegClassForReg(MRI, Reg);
5489 if (RI.hasVectorRegisters(RC) && MO.getSubReg()) {
5490 if (const TargetRegisterClass *SubRC =
5491 RI.getSubRegisterClass(RC, MO.getSubReg())) {
5492 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.getSubReg());
5493 if (RC)
5494 RC = SubRC;
5495 }
5496 }
5497
5498 // Check that this is the aligned version of the class.
5499 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5500 ErrInfo = "Subtarget requires even aligned vector registers";
5501 return false;
5502 }
5503 }
5504
5505 if (RegClass != -1) {
5506 if (Reg.isVirtual())
5507 continue;
5508
5509 const TargetRegisterClass *RC = RI.getRegClass(RegClass);
5510 if (!RC->contains(Reg)) {
5511 ErrInfo = "Operand has incorrect register class.";
5512 return false;
5513 }
5514 }
5515 }
5516
5517 // Verify SDWA
5518 if (isSDWA(MI)) {
5519 if (!ST.hasSDWA()) {
5520 ErrInfo = "SDWA is not supported on this target";
5521 return false;
5522 }
5523
5524 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5525 AMDGPU::OpName::dst_sel}) {
5526 const MachineOperand *MO = getNamedOperand(MI, Op);
5527 if (!MO)
5528 continue;
5529 int64_t Imm = MO->getImm();
5531 ErrInfo = "Invalid SDWA selection";
5532 return false;
5533 }
5534 }
5535
5536 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5537
5538 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5539 if (OpIdx == -1)
5540 continue;
5541 const MachineOperand &MO = MI.getOperand(OpIdx);
5542
5543 if (!ST.hasSDWAScalar()) {
5544 // Only VGPRS on VI
5545 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5546 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5547 return false;
5548 }
5549 } else {
5550 // No immediates on GFX9
5551 if (!MO.isReg()) {
5552 ErrInfo =
5553 "Only reg allowed as operands in SDWA instructions on GFX9+";
5554 return false;
5555 }
5556 }
5557 }
5558
5559 if (!ST.hasSDWAOmod()) {
5560 // No omod allowed on VI
5561 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5562 if (OMod != nullptr &&
5563 (!OMod->isImm() || OMod->getImm() != 0)) {
5564 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5565 return false;
5566 }
5567 }
5568
5569 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5570 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5571 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5572 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5573 const MachineOperand *Src0ModsMO =
5574 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5575 unsigned Mods = Src0ModsMO->getImm();
5576 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5577 Mods & SISrcMods::SEXT) {
5578 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5579 return false;
5580 }
5581 }
5582
5583 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5584 if (isVOPC(BasicOpcode)) {
5585 if (!ST.hasSDWASdst() && DstIdx != -1) {
5586 // Only vcc allowed as dst on VI for VOPC
5587 const MachineOperand &Dst = MI.getOperand(DstIdx);
5588 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5589 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5590 return false;
5591 }
5592 } else if (!ST.hasSDWAOutModsVOPC()) {
5593 // No clamp allowed on GFX9 for VOPC
5594 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5595 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5596 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5597 return false;
5598 }
5599
5600 // No omod allowed on GFX9 for VOPC
5601 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5602 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5603 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5604 return false;
5605 }
5606 }
5607 }
5608
5609 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5610 if (DstUnused && DstUnused->isImm() &&
5611 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5612 const MachineOperand &Dst = MI.getOperand(DstIdx);
5613 if (!Dst.isReg() || !Dst.isTied()) {
5614 ErrInfo = "Dst register should have tied register";
5615 return false;
5616 }
5617
5618 const MachineOperand &TiedMO =
5619 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5620 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5621 ErrInfo =
5622 "Dst register should be tied to implicit use of preserved register";
5623 return false;
5624 }
5625 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5626 ErrInfo = "Dst register should use same physical register as preserved";
5627 return false;
5628 }
5629 }
5630 }
5631
5632 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5633 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5634 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5635 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5636 return false;
5637 }
5638 if (Src1MO.isImm()) {
5639 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5640 return false;
5641 }
5642 }
5643
5644 // Verify MIMG / VIMAGE / VSAMPLE
5645 if (isImage(Opcode) && !MI.mayStore()) {
5646 // Ensure that the return type used is large enough for all the options
5647 // being used TFE/LWE require an extra result register.
5648 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5649 if (DMask) {
5650 uint64_t DMaskImm = DMask->getImm();
5651 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5652 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5653 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5654 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5655
5656 // Adjust for packed 16 bit values
5657 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5658 RegCount = divideCeil(RegCount, 2);
5659
5660 // Adjust if using LWE or TFE
5661 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5662 RegCount += 1;
5663
5664 const uint32_t DstIdx =
5665 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5666 const MachineOperand &Dst = MI.getOperand(DstIdx);
5667 if (Dst.isReg()) {
5668 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5669 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5670 if (RegCount > DstSize) {
5671 ErrInfo = "Image instruction returns too many registers for dst "
5672 "register class";
5673 return false;
5674 }
5675 }
5676 }
5677 }
5678
5679 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5680 if (isVALU(MI, /*AllowLDSDMA=*/true) &&
5681 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5682 unsigned ConstantBusCount = 0;
5683 bool UsesLiteral = false;
5684 const MachineOperand *LiteralVal = nullptr;
5685
5686 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5687 if (ImmIdx != -1) {
5688 ++ConstantBusCount;
5689 UsesLiteral = true;
5690 LiteralVal = &MI.getOperand(ImmIdx);
5691 }
5692
5693 SmallVector<Register, 2> SGPRsUsed;
5694 Register SGPRUsed;
5695
5696 // Only look at the true operands. Only a real operand can use the constant
5697 // bus, and we don't want to check pseudo-operands like the source modifier
5698 // flags.
5699 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5700 if (OpIdx == -1)
5701 continue;
5702 const MachineOperand &MO = MI.getOperand(OpIdx);
5703 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5704 if (MO.isReg()) {
5705 SGPRUsed = MO.getReg();
5706 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5707 ++ConstantBusCount;
5708 SGPRsUsed.push_back(SGPRUsed);
5709 }
5710 } else if (!MO.isFI()) { // Treat FI like a register.
5711 if (!UsesLiteral) {
5712 ++ConstantBusCount;
5713 UsesLiteral = true;
5714 LiteralVal = &MO;
5715 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5716 assert(isVOP2(MI) || isVOP3(MI));
5717 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5718 return false;
5719 }
5720 }
5721 }
5722 }
5723
5724 SGPRUsed = findImplicitSGPRRead(MI);
5725 if (SGPRUsed) {
5726 // Implicit uses may safely overlap true operands
5727 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5728 return !RI.regsOverlap(SGPRUsed, SGPR);
5729 })) {
5730 ++ConstantBusCount;
5731 SGPRsUsed.push_back(SGPRUsed);
5732 }
5733 }
5734
5735 // v_writelane_b32 is an exception from constant bus restriction:
5736 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5737 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5738 Opcode != AMDGPU::V_WRITELANE_B32) {
5739 ErrInfo = "VOP* instruction violates constant bus restriction";
5740 return false;
5741 }
5742
5743 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5744 ErrInfo = "VOP3 instruction uses literal";
5745 return false;
5746 }
5747 }
5748
5749 // Special case for writelane - this can break the multiple constant bus rule,
5750 // but still can't use more than one SGPR register
5751 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5752 unsigned SGPRCount = 0;
5753 Register SGPRUsed;
5754
5755 for (int OpIdx : {Src0Idx, Src1Idx}) {
5756 if (OpIdx == -1)
5757 break;
5758
5759 const MachineOperand &MO = MI.getOperand(OpIdx);
5760
5761 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5762 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5763 if (MO.getReg() != SGPRUsed)
5764 ++SGPRCount;
5765 SGPRUsed = MO.getReg();
5766 }
5767 }
5768 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5769 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5770 return false;
5771 }
5772 }
5773 }
5774
5775 // Verify misc. restrictions on specific instructions.
5776 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5777 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5778 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5779 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5780 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
5781 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5782 if (!compareMachineOp(Src0, Src1) &&
5783 !compareMachineOp(Src0, Src2)) {
5784 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
5785 return false;
5786 }
5787 }
5788 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
5789 SISrcMods::ABS) ||
5790 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
5791 SISrcMods::ABS) ||
5792 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
5793 SISrcMods::ABS)) {
5794 ErrInfo = "ABS not allowed in VOP3B instructions";
5795 return false;
5796 }
5797 }
5798
5799 if (isSOP2(MI) || isSOPC(MI)) {
5800 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5801 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5802
5803 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
5804 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
5805 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
5806 !Src0.isIdenticalTo(Src1)) {
5807 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
5808 return false;
5809 }
5810 }
5811
5812 if (isSOPK(MI)) {
5813 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
5814 if (Desc.isBranch()) {
5815 if (!Op->isMBB()) {
5816 ErrInfo = "invalid branch target for SOPK instruction";
5817 return false;
5818 }
5819 } else {
5820 uint64_t Imm = Op->getImm();
5821 if (sopkIsZext(Opcode)) {
5822 if (!isUInt<16>(Imm)) {
5823 ErrInfo = "invalid immediate for SOPK instruction";
5824 return false;
5825 }
5826 } else {
5827 if (!isInt<16>(Imm)) {
5828 ErrInfo = "invalid immediate for SOPK instruction";
5829 return false;
5830 }
5831 }
5832 }
5833 }
5834
5835 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5836 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5837 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5838 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5839 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5840 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5841
5842 const unsigned StaticNumOps =
5843 Desc.getNumOperands() + Desc.implicit_uses().size();
5844 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5845
5846 // Require additional implicit operands. This allows a fixup done by the
5847 // post RA scheduler where the main implicit operand is killed and
5848 // implicit-defs are added for sub-registers that remain live after this
5849 // instruction.
5850 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5851 ErrInfo = "missing implicit register operands";
5852 return false;
5853 }
5854
5855 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5856 if (IsDst) {
5857 if (!Dst->isUse()) {
5858 ErrInfo = "v_movreld_b32 vdst should be a use operand";
5859 return false;
5860 }
5861
5862 unsigned UseOpIdx;
5863 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5864 UseOpIdx != StaticNumOps + 1) {
5865 ErrInfo = "movrel implicit operands should be tied";
5866 return false;
5867 }
5868 }
5869
5870 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5871 const MachineOperand &ImpUse
5872 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5873 if (!ImpUse.isReg() || !ImpUse.isUse() ||
5874 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5875 ErrInfo = "src0 should be subreg of implicit vector use";
5876 return false;
5877 }
5878 }
5879
5880 // Make sure we aren't losing exec uses in the td files. This mostly requires
5881 // being careful when using let Uses to try to add other use registers.
5882 if (shouldReadExec(MI)) {
5883 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5884 ErrInfo = "VALU instruction does not implicitly read exec mask";
5885 return false;
5886 }
5887 }
5888
5889 if (isSMRD(MI)) {
5890 if (MI.mayStore() &&
5891 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
5892 // The register offset form of scalar stores may only use m0 as the
5893 // soffset register.
5894 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
5895 if (Soff && Soff->getReg() != AMDGPU::M0) {
5896 ErrInfo = "scalar stores must use m0 as offset register";
5897 return false;
5898 }
5899 }
5900 }
5901
5902 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
5903 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
5904 if (Offset->getImm() != 0) {
5905 ErrInfo = "subtarget does not support offsets in flat instructions";
5906 return false;
5907 }
5908 }
5909
5910 if (isDS(MI) && !ST.hasGDS()) {
5911 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
5912 if (GDSOp && GDSOp->getImm() != 0) {
5913 ErrInfo = "GDS is not supported on this subtarget";
5914 return false;
5915 }
5916 }
5917
5918 if (isImage(MI)) {
5919 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
5920 if (DimOp) {
5921 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5922 AMDGPU::OpName::vaddr0);
5923 AMDGPU::OpName RSrcOpName =
5924 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5925 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5926 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
5927 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
5928 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
5929 const AMDGPU::MIMGDimInfo *Dim =
5931
5932 if (!Dim) {
5933 ErrInfo = "dim is out of range";
5934 return false;
5935 }
5936
5937 bool IsA16 = false;
5938 if (ST.hasR128A16()) {
5939 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
5940 IsA16 = R128A16->getImm() != 0;
5941 } else if (ST.hasA16()) {
5942 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
5943 IsA16 = A16->getImm() != 0;
5944 }
5945
5946 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5947
5948 unsigned AddrWords =
5949 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
5950
5951 unsigned VAddrWords;
5952 if (IsNSA) {
5953 VAddrWords = RsrcIdx - VAddr0Idx;
5954 if (ST.hasPartialNSAEncoding() &&
5955 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
5956 unsigned LastVAddrIdx = RsrcIdx - 1;
5957 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
5958 }
5959 } else {
5960 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
5961 if (AddrWords > 12)
5962 AddrWords = 16;
5963 }
5964
5965 if (VAddrWords != AddrWords) {
5966 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
5967 << " but got " << VAddrWords << "\n");
5968 ErrInfo = "bad vaddr size";
5969 return false;
5970 }
5971 }
5972 }
5973
5974 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
5975 if (DppCt) {
5976 using namespace AMDGPU::DPP;
5977
5978 unsigned DC = DppCt->getImm();
5979 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5980 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5981 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5982 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5983 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5984 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5985 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5986 ErrInfo = "Invalid dpp_ctrl value";
5987 return false;
5988 }
5989 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5990 !ST.hasDPPWavefrontShifts()) {
5991 ErrInfo = "Invalid dpp_ctrl value: "
5992 "wavefront shifts are not supported on GFX10+";
5993 return false;
5994 }
5995 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5996 !ST.hasDPPBroadcasts()) {
5997 ErrInfo = "Invalid dpp_ctrl value: "
5998 "broadcasts are not supported on GFX10+";
5999 return false;
6000 }
6001 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6002 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
6003 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6004 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6005 !ST.hasGFX90AInsts()) {
6006 ErrInfo = "Invalid dpp_ctrl value: "
6007 "row_newbroadcast/row_share is not supported before "
6008 "GFX90A/GFX10";
6009 return false;
6010 }
6011 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6012 ErrInfo = "Invalid dpp_ctrl value: "
6013 "row_share and row_xmask are not supported before GFX10";
6014 return false;
6015 }
6016 }
6017
6018 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6020 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
6021 ErrInfo = "Invalid dpp_ctrl value: "
6022 "DP ALU dpp only support row_newbcast";
6023 return false;
6024 }
6025 }
6026
6027 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
6028 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
6029 AMDGPU::OpName DataName =
6030 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6031 const MachineOperand *Data = getNamedOperand(MI, DataName);
6032 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
6033 if (Data && !Data->isReg())
6034 Data = nullptr;
6035
6036 if (!ST.hasGFX90AInsts()) {
6037 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6038 (Data && RI.isAGPR(MRI, Data->getReg())) ||
6039 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
6040 ErrInfo = "Invalid register class: "
6041 "agpr loads and stores not supported on this GPU";
6042 return false;
6043 }
6044 }
6045 }
6046
6047 if (ST.needsAlignedVGPRs()) {
6048 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
6050 if (!Op)
6051 return true;
6052 Register Reg = Op->getReg();
6053 if (Reg.isPhysical())
6054 return !(RI.getHWRegIndex(Reg) & 1);
6055 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
6056 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6057 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
6058 };
6059
6060 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
6061 Opcode == AMDGPU::DS_GWS_BARRIER) {
6062
6063 if (!isAlignedReg(AMDGPU::OpName::data0)) {
6064 ErrInfo = "Subtarget requires even aligned vector registers "
6065 "for DS_GWS instructions";
6066 return false;
6067 }
6068 }
6069
6070 if (isMIMG(MI)) {
6071 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6072 ErrInfo = "Subtarget requires even aligned vector registers "
6073 "for vaddr operand of image instructions";
6074 return false;
6075 }
6076 }
6077 }
6078
6079 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6080 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
6081 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6082 ErrInfo = "Invalid register class: "
6083 "v_accvgpr_write with an SGPR is not supported on this GPU";
6084 return false;
6085 }
6086 }
6087
6088 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6089 const MachineOperand &SrcOp = MI.getOperand(1);
6090 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
6091 ErrInfo = "pseudo expects only physical SGPRs";
6092 return false;
6093 }
6094 }
6095
6096 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
6097 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
6098 if (!ST.hasScaleOffset()) {
6099 ErrInfo = "Subtarget does not support offset scaling";
6100 return false;
6101 }
6102 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
6103 ErrInfo = "Instruction does not support offset scaling";
6104 return false;
6105 }
6106 }
6107 }
6108
6109 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6110 if (AMDGPU::isSingleSGPRReadInst(Opcode)) {
6111 for (unsigned I = 0; I < 3; ++I) {
6113 return false;
6114 }
6115 }
6116
6117 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
6118 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
6119 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
6120 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6121 &AMDGPU::SReg_64RegClass) ||
6122 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6123 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
6124 return false;
6125 }
6126 }
6127
6128 return true;
6129}
6130
6132 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
6133 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6134 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
6135 ? AMDGPU::COPY
6136 : AMDGPU::V_MOV_B32_e32;
6137 }
6138 return getVALUOp(MI.getOpcode());
6139}
6140
6141// It is more readable to list mapped opcodes on the same line.
6142// clang-format off
6143
6144unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
6145 switch (Opc) {
6146 default: return AMDGPU::INSTRUCTION_LIST_END;
6147 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
6148 case AMDGPU::COPY: return AMDGPU::COPY;
6149 case AMDGPU::PHI: return AMDGPU::PHI;
6150 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
6151 case AMDGPU::WQM: return AMDGPU::WQM;
6152 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
6153 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
6154 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
6155 case AMDGPU::S_ADD_I32:
6156 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6157 case AMDGPU::S_ADDC_U32:
6158 return AMDGPU::V_ADDC_U32_e32;
6159 case AMDGPU::S_SUB_I32:
6160 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6161 // FIXME: These are not consistently handled, and selected when the carry is
6162 // used.
6163 case AMDGPU::S_ADD_U32:
6164 return AMDGPU::V_ADD_CO_U32_e32;
6165 case AMDGPU::S_SUB_U32:
6166 return AMDGPU::V_SUB_CO_U32_e32;
6167 case AMDGPU::S_ADD_U64_PSEUDO:
6168 return AMDGPU::V_ADD_U64_PSEUDO;
6169 case AMDGPU::S_SUB_U64_PSEUDO:
6170 return AMDGPU::V_SUB_U64_PSEUDO;
6171 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
6172 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
6173 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
6174 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
6175 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
6176 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
6177 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
6178 case AMDGPU::S_XNOR_B32:
6179 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6180 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
6181 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
6182 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
6183 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
6184 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
6185 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
6186 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
6187 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
6188 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
6189 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
6190 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
6191 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
6192 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
6193 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
6194 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
6195 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
6196 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
6197 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
6198 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
6199 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
6200 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
6201 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
6202 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
6203 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
6204 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
6205 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
6206 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
6207 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
6208 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
6209 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
6210 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
6211 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
6212 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
6213 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
6214 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
6215 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
6216 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
6217 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
6218 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
6219 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
6220 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
6221 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
6222 case AMDGPU::S_CVT_F32_F16:
6223 case AMDGPU::S_CVT_HI_F32_F16:
6224 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6225 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6226 case AMDGPU::S_CVT_F16_F32:
6227 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6228 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6229 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
6230 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
6231 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
6232 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
6233 case AMDGPU::S_CEIL_F16:
6234 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6235 : AMDGPU::V_CEIL_F16_fake16_e64;
6236 case AMDGPU::S_FLOOR_F16:
6237 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6238 : AMDGPU::V_FLOOR_F16_fake16_e64;
6239 case AMDGPU::S_TRUNC_F16:
6240 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6241 : AMDGPU::V_TRUNC_F16_fake16_e64;
6242 case AMDGPU::S_RNDNE_F16:
6243 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6244 : AMDGPU::V_RNDNE_F16_fake16_e64;
6245 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6246 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6247 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6248 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6249 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6250 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6251 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6252 case AMDGPU::S_ADD_F16:
6253 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6254 : AMDGPU::V_ADD_F16_fake16_e64;
6255 case AMDGPU::S_SUB_F16:
6256 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6257 : AMDGPU::V_SUB_F16_fake16_e64;
6258 case AMDGPU::S_MIN_F16:
6259 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6260 : AMDGPU::V_MIN_F16_fake16_e64;
6261 case AMDGPU::S_MAX_F16:
6262 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6263 : AMDGPU::V_MAX_F16_fake16_e64;
6264 case AMDGPU::S_MINIMUM_F16:
6265 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6266 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6267 case AMDGPU::S_MAXIMUM_F16:
6268 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6269 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6270 case AMDGPU::S_MUL_F16:
6271 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6272 : AMDGPU::V_MUL_F16_fake16_e64;
6273 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6274 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6275 case AMDGPU::S_FMAC_F16:
6276 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6277 : AMDGPU::V_FMAC_F16_fake16_e64;
6278 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6279 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6280 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6281 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6282 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6283 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6284 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6285 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6286 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6287 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6288 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6289 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6290 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6291 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6292 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6293 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6294 case AMDGPU::S_CMP_LT_F16:
6295 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6296 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6297 case AMDGPU::S_CMP_EQ_F16:
6298 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6299 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6300 case AMDGPU::S_CMP_LE_F16:
6301 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6302 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6303 case AMDGPU::S_CMP_GT_F16:
6304 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6305 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6306 case AMDGPU::S_CMP_LG_F16:
6307 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6308 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6309 case AMDGPU::S_CMP_GE_F16:
6310 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6311 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6312 case AMDGPU::S_CMP_O_F16:
6313 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6314 : AMDGPU::V_CMP_O_F16_fake16_e64;
6315 case AMDGPU::S_CMP_U_F16:
6316 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6317 : AMDGPU::V_CMP_U_F16_fake16_e64;
6318 case AMDGPU::S_CMP_NGE_F16:
6319 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6320 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6321 case AMDGPU::S_CMP_NLG_F16:
6322 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6323 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6324 case AMDGPU::S_CMP_NGT_F16:
6325 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6326 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6327 case AMDGPU::S_CMP_NLE_F16:
6328 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6329 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6330 case AMDGPU::S_CMP_NEQ_F16:
6331 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6332 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6333 case AMDGPU::S_CMP_NLT_F16:
6334 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6335 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6336 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6337 case AMDGPU::V_S_EXP_F16_e64:
6338 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6339 : AMDGPU::V_EXP_F16_fake16_e64;
6340 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6341 case AMDGPU::V_S_LOG_F16_e64:
6342 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6343 : AMDGPU::V_LOG_F16_fake16_e64;
6344 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6345 case AMDGPU::V_S_RCP_F16_e64:
6346 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6347 : AMDGPU::V_RCP_F16_fake16_e64;
6348 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6349 case AMDGPU::V_S_RSQ_F16_e64:
6350 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6351 : AMDGPU::V_RSQ_F16_fake16_e64;
6352 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6353 case AMDGPU::V_S_SQRT_F16_e64:
6354 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6355 : AMDGPU::V_SQRT_F16_fake16_e64;
6356 }
6358 "Unexpected scalar opcode without corresponding vector one!");
6359}
6360
6361// clang-format on
6362
6366 const DebugLoc &DL, Register Reg,
6367 bool IsSCCLive,
6368 SlotIndexes *Indexes) const {
6369 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6370 const SIInstrInfo *TII = ST.getInstrInfo();
6372 if (IsSCCLive) {
6373 // Insert two move instructions, one to save the original value of EXEC and
6374 // the other to turn on all bits in EXEC. This is required as we can't use
6375 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6376 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6378 auto FlipExecMI =
6379 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6380 if (Indexes) {
6381 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6382 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6383 }
6384 } else {
6385 auto SaveExec =
6386 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6387 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6388 if (Indexes)
6389 Indexes->insertMachineInstrInMaps(*SaveExec);
6390 }
6391}
6392
6395 const DebugLoc &DL, Register Reg,
6396 SlotIndexes *Indexes) const {
6398 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6399 .addReg(Reg, RegState::Kill);
6400 if (Indexes)
6401 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6402}
6403
6407 "Not a whole wave func");
6408 MachineBasicBlock &MBB = *MF.begin();
6409 for (MachineInstr &MI : MBB)
6410 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6411 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6412 return &MI;
6413
6414 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6415}
6416
6418 unsigned OpNo) const {
6419 const MCInstrDesc &Desc = get(MI.getOpcode());
6420 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6421 Desc.operands()[OpNo].RegClass == -1) {
6422 Register Reg = MI.getOperand(OpNo).getReg();
6423
6424 if (Reg.isVirtual()) {
6425 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6426 return MRI.getRegClass(Reg);
6427 }
6428 return RI.getPhysRegBaseClass(Reg);
6429 }
6430
6431 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6432 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6433}
6434
6435// Convert VOP3 operand index to source number.
6436static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx) {
6437 constexpr AMDGPU::OpName OpNames[] = {
6438 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6439
6440 for (auto [I, OpName] : enumerate(OpNames)) {
6441 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6442 if (static_cast<unsigned>(SrcIdx) == OpIdx)
6443 return I;
6444 }
6445
6446 return UINT_MAX;
6447}
6448
6451 MachineBasicBlock *MBB = MI.getParent();
6452 MachineOperand &MO = MI.getOperand(OpIdx);
6453 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6454 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6455 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6456 unsigned Size = RI.getRegSizeInBits(*RC);
6457 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6458 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6459 : AMDGPU::V_MOV_B32_e32;
6460 if (MO.isReg())
6461 Opcode = AMDGPU::COPY;
6462 else if (RI.isSGPRClass(RC))
6463 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6464
6465 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6466 Register Reg = MRI.createVirtualRegister(VRC);
6467 DebugLoc DL = MBB->findDebugLoc(I);
6468
6469 if (Size == 128 && AMDGPU::isPackedSingleSGPR64BitInst(MI.getOpcode()) &&
6471 // Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
6472 // sources behave like OPSEL is set replicating low 64-bits into high. VGPR
6473 // sources in turn read actual 4 registers. To move operand from an SGPR to
6474 // a VGPR we need to replicate low half.
6475 // We also do not select immediates for these instructions so it always has
6476 // to be an SGPR register here.
6477 // Operands which are not legal as per isLegalSingleSGPRReadInstOperand()
6478 // sent here specifically to fix a non-splat SGPR and shall perform a full
6479 // copy.
6480
6481 const TargetRegisterClass *VRC64 = RI.getVGPRClassForBitWidth(64);
6482 Register Low64 = MRI.createVirtualRegister(VRC64);
6483 assert(MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()));
6484 BuildMI(*MBB, I, DL, get(TargetOpcode::COPY), Low64)
6485 .addReg(MO.getReg(), {}, AMDGPU::sub0_sub1);
6486 BuildMI(*MBB, I, DL, get(TargetOpcode::REG_SEQUENCE), Reg)
6487 .addReg(Low64)
6488 .addImm(AMDGPU::sub0_sub1)
6489 .addReg(Low64, RegState::Kill)
6490 .addImm(AMDGPU::sub2_sub3);
6491 } else {
6492 BuildMI(*MBB, I, DL, get(Opcode), Reg).add(MO);
6493 }
6494
6495 MO.ChangeToRegister(Reg, false);
6496}
6497
6500 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6501 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6502 if (!SuperReg.getReg().isVirtual())
6503 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6504
6505 MachineBasicBlock *MBB = MI->getParent();
6506 const DebugLoc &DL = MI->getDebugLoc();
6507 Register SubReg = MRI.createVirtualRegister(SubRC);
6508
6509 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6510 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6511 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6512 return SubReg;
6513}
6514
6517 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6518 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6519 if (Op.isImm()) {
6520 if (SubIdx == AMDGPU::sub0)
6521 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6522 if (SubIdx == AMDGPU::sub1)
6523 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6524
6525 llvm_unreachable("Unhandled register index for immediate");
6526 }
6527
6528 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6529 SubIdx, SubRC);
6530 return MachineOperand::CreateReg(SubReg, false);
6531}
6532
6533// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6534void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6535 assert(Inst.getNumExplicitOperands() == 3);
6536 MachineOperand Op1 = Inst.getOperand(1);
6537 Inst.removeOperand(1);
6538 Inst.addOperand(Op1);
6539}
6540
6542 const MCOperandInfo &OpInfo,
6543 const MachineOperand &MO) const {
6544 if (!MO.isReg())
6545 return false;
6546
6547 Register Reg = MO.getReg();
6548
6549 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6550 if (Reg.isPhysical())
6551 return DRC->contains(Reg);
6552
6553 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6554
6555 if (MO.getSubReg()) {
6556 const TargetRegisterClass *SuperRC =
6557 RI.getLargestLegalSuperClass(RC, MRI.getMF());
6558 if (!SuperRC)
6559 return false;
6560 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6561 }
6562
6563 return RI.getCommonSubClass(DRC, RC) != nullptr;
6564}
6565
6567 const MachineOperand &MO) const {
6568 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6569 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6570 unsigned Opc = MI.getOpcode();
6571
6572 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6573 if (MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
6574 AMDGPU::isSingleSGPRReadInst(MI.getOpcode()) &&
6576 &MO))
6577 return false;
6578
6579 if (!isLegalRegOperand(MRI, OpInfo, MO))
6580 return false;
6581
6582 // check Accumulate GPR operand
6583 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6584 if (IsAGPR && !ST.hasMAIInsts())
6585 return false;
6586 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6587 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6588 return false;
6589 // Atomics should have both vdst and vdata either vgpr or agpr.
6590 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6591 const int DataIdx = AMDGPU::getNamedOperandIdx(
6592 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6593 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6594 MI.getOperand(DataIdx).isReg() &&
6595 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6596 return false;
6597 if ((int)OpIdx == DataIdx) {
6598 if (VDstIdx != -1 &&
6599 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6600 return false;
6601 // DS instructions with 2 src operands also must have tied RC.
6602 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6603 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6604 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6605 return false;
6606 }
6607
6608 // Check V_ACCVGPR_WRITE_B32_e64
6609 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6610 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6611 RI.isSGPRReg(MRI, MO.getReg()))
6612 return false;
6613
6614 if (ST.hasFlatScratchHiInB64InstHazard() &&
6615 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6616 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6617 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6618 64)
6619 return false;
6620 }
6621 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6622 return false;
6623 }
6624 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6625 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6626 return false;
6627
6628 return true;
6629}
6630
6632 const MCOperandInfo &OpInfo,
6633 const MachineOperand &MO) const {
6634 if (MO.isReg())
6635 return isLegalRegOperand(MRI, OpInfo, MO);
6636
6637 // Handle non-register types that are treated like immediates.
6638 assert(MO.isImm() || MO.isTargetIndex() || MO.isFI() || MO.isGlobal());
6639 return true;
6640}
6641
6643 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6644 const MachineOperand *MO) const {
6645 constexpr unsigned NumOps = 3;
6646 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6647 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6648 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6649 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6650
6651 assert(SrcN < NumOps);
6652
6653 if (!MO) {
6654 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6655 if (SrcIdx == -1)
6656 return true;
6657 MO = &MI.getOperand(SrcIdx);
6658 }
6659
6660 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6661 return true;
6662
6663 int ModsIdx =
6664 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6665 if (ModsIdx == -1)
6666 return false;
6667
6668 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6669 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6670 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6671
6672 return !OpSel && !OpSelHi;
6673}
6674
6675bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
6676 const MachineOperand *MO) const {
6677 const MachineFunction &MF = *MI.getMF();
6678 const MachineRegisterInfo &MRI = MF.getRegInfo();
6679 const MCInstrDesc &InstDesc = MI.getDesc();
6680 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6681 int64_t RegClass = getOpRegClassID(OpInfo);
6682 const TargetRegisterClass *DefinedRC =
6683 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6684 if (!MO)
6685 MO = &MI.getOperand(OpIdx);
6686
6687 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6688
6689 if (isVALU(MI, /*AllowLDSDMA=*/true) && !IsInlineConst &&
6690 usesConstantBus(MRI, *MO, OpInfo)) {
6691 const MachineOperand *UsedLiteral = nullptr;
6692
6693 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6694 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6695
6696 // TODO: Be more permissive with frame indexes.
6697 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6698 if (!LiteralLimit--)
6699 return false;
6700
6701 UsedLiteral = MO;
6702 }
6703
6705 if (MO->isReg())
6706 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6707
6708 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6709 if (i == OpIdx)
6710 continue;
6711 const MachineOperand &Op = MI.getOperand(i);
6712 if (Op.isReg()) {
6713 if (Op.isUse()) {
6714 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6715 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6716 if (--ConstantBusLimit <= 0)
6717 return false;
6718 }
6719 }
6720 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6721 !isInlineConstant(Op, InstDesc.operands()[i])) {
6722 // The same literal may be used multiple times.
6723 if (!UsedLiteral)
6724 UsedLiteral = &Op;
6725 else if (UsedLiteral->isIdenticalTo(Op))
6726 continue;
6727
6728 if (!LiteralLimit--)
6729 return false;
6730 if (--ConstantBusLimit <= 0)
6731 return false;
6732 }
6733 }
6734 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6735 // There can be at most one literal operand, but it can be repeated.
6736 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6737 if (i == OpIdx)
6738 continue;
6739 const MachineOperand &Op = MI.getOperand(i);
6740 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6741 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6742 !Op.isIdenticalTo(*MO))
6743 return false;
6744
6745 // Do not fold a non-inlineable and non-register operand into an
6746 // instruction that already has a frame index. The frame index handling
6747 // code could not handle well when a frame index co-exists with another
6748 // non-register operand, unless that operand is an inlineable immediate.
6749 if (Op.isFI())
6750 return false;
6751 }
6752 } else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6753 isF16PseudoScalarTrans(MI.getOpcode())) {
6754 return false;
6755 }
6756
6757 if (MO->isReg()) {
6758 if (!DefinedRC)
6759 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6760 return isLegalRegOperand(MI, OpIdx, *MO);
6761 }
6762
6763 if (MO->isImm()) {
6764 uint64_t Imm = MO->getImm();
6765 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6766 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6767 bool Is64BitOp = Is64BitFPOp ||
6768 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6769 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6770 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6771 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6772 if (Is64BitOp &&
6773 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6774 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6775 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6776 return false;
6777
6778 // FIXME: We can use sign extended 64-bit literals, but only for signed
6779 // operands. At the moment we do not know if an operand is signed.
6780 // Such operand will be encoded as its low 32 bits and then either
6781 // correctly sign extended or incorrectly zero extended by HW.
6782 // If 64-bit literals are supported and the literal will be encoded
6783 // as full 64 bit we still can use it.
6784 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6785 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
6786 return false;
6787 }
6788 }
6789
6790 // Handle non-register types that are treated like immediates.
6791 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
6792
6793 if (!DefinedRC) {
6794 // This operand expects an immediate.
6795 return true;
6796 }
6797
6798 return isImmOperandLegal(MI, OpIdx, *MO);
6799}
6800
6802 bool IsGFX950Only = ST.hasGFX950Insts();
6803 bool IsGFX940Only = ST.hasGFX940Insts();
6804
6805 if (!IsGFX950Only && !IsGFX940Only)
6806 return false;
6807
6808 if (!isVALU(MI, /*AllowLDSDMA=*/true))
6809 return false;
6810
6811 // V_COS, V_EXP, V_RCP, etc.
6812 if (isTRANS(MI))
6813 return true;
6814
6815 // DOT2, DOT2C, DOT4, etc.
6816 if (isDOT(MI))
6817 return true;
6818
6819 // MFMA, SMFMA
6820 if (isMFMA(MI))
6821 return true;
6822
6823 unsigned Opcode = MI.getOpcode();
6824 switch (Opcode) {
6825 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6826 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6827 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6828 case AMDGPU::V_MQSAD_U32_U8_e64:
6829 case AMDGPU::V_PK_ADD_F16:
6830 case AMDGPU::V_PK_ADD_F32:
6831 case AMDGPU::V_PK_ADD_I16:
6832 case AMDGPU::V_PK_ADD_U16:
6833 case AMDGPU::V_PK_ASHRREV_I16:
6834 case AMDGPU::V_PK_FMA_F16:
6835 case AMDGPU::V_PK_FMA_F32:
6836 case AMDGPU::V_PK_FMAC_F16_e32:
6837 case AMDGPU::V_PK_FMAC_F16_e64:
6838 case AMDGPU::V_PK_LSHLREV_B16:
6839 case AMDGPU::V_PK_LSHRREV_B16:
6840 case AMDGPU::V_PK_MAD_I16:
6841 case AMDGPU::V_PK_MAD_U16:
6842 case AMDGPU::V_PK_MAX_F16:
6843 case AMDGPU::V_PK_MAX_I16:
6844 case AMDGPU::V_PK_MAX_U16:
6845 case AMDGPU::V_PK_MIN_F16:
6846 case AMDGPU::V_PK_MIN_I16:
6847 case AMDGPU::V_PK_MIN_U16:
6848 case AMDGPU::V_PK_MOV_B32:
6849 case AMDGPU::V_PK_MUL_F16:
6850 case AMDGPU::V_PK_MUL_F32:
6851 case AMDGPU::V_PK_MUL_LO_U16:
6852 case AMDGPU::V_PK_SUB_I16:
6853 case AMDGPU::V_PK_SUB_U16:
6854 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6855 return true;
6856 default:
6857 return false;
6858 }
6859}
6860
6862 MachineInstr &MI) const {
6863 unsigned Opc = MI.getOpcode();
6864 const MCInstrDesc &InstrDesc = get(Opc);
6865
6866 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
6867 MachineOperand &Src0 = MI.getOperand(Src0Idx);
6868
6869 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
6870 MachineOperand &Src1 = MI.getOperand(Src1Idx);
6871
6872 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
6873 // we need to only have one constant bus use before GFX10.
6874 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
6875 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
6876 RI.isSGPRReg(MRI, Src0.getReg()))
6877 legalizeOpWithMove(MI, Src0Idx);
6878
6879 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
6880 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
6881 // src0/src1 with V_READFIRSTLANE.
6882 if (Opc == AMDGPU::V_WRITELANE_B32) {
6883 const DebugLoc &DL = MI.getDebugLoc();
6884 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
6885 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6886 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6887 .add(Src0);
6888 Src0.ChangeToRegister(Reg, false);
6889 }
6890 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
6891 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6892 const DebugLoc &DL = MI.getDebugLoc();
6893 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6894 .add(Src1);
6895 Src1.ChangeToRegister(Reg, false);
6896 }
6897 return;
6898 }
6899
6900 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
6901 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
6902 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
6903 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
6904 legalizeOpWithMove(MI, Src2Idx);
6905 }
6906
6907 // VOP2 src0 instructions support all operand types, so we don't need to check
6908 // their legality. If src1 is already legal, we don't need to do anything.
6909 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
6910 return;
6911
6912 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
6913 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
6914 // select is uniform.
6915 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
6916 RI.isVGPR(MRI, Src1.getReg())) {
6917 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6918 const DebugLoc &DL = MI.getDebugLoc();
6919 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6920 .add(Src1);
6921 Src1.ChangeToRegister(Reg, false);
6922 return;
6923 }
6924
6925 // We do not use commuteInstruction here because it is too aggressive and will
6926 // commute if it is possible. We only want to commute here if it improves
6927 // legality. This can be called a fairly large number of times so don't waste
6928 // compile time pointlessly swapping and checking legality again.
6929 if (HasImplicitSGPR || !MI.isCommutable()) {
6930 legalizeOpWithMove(MI, Src1Idx);
6931 return;
6932 }
6933
6934 // If src0 can be used as src1, commuting will make the operands legal.
6935 // Otherwise we have to give up and insert a move.
6936 //
6937 // TODO: Other immediate-like operand kinds could be commuted if there was a
6938 // MachineOperand::ChangeTo* for them.
6939 if ((!Src1.isImm() && !Src1.isReg()) ||
6940 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
6941 legalizeOpWithMove(MI, Src1Idx);
6942 return;
6943 }
6944
6945 int CommutedOpc = commuteOpcode(MI);
6946 if (CommutedOpc == -1) {
6947 legalizeOpWithMove(MI, Src1Idx);
6948 return;
6949 }
6950
6951 MI.setDesc(get(CommutedOpc));
6952
6953 Register Src0Reg = Src0.getReg();
6954 unsigned Src0SubReg = Src0.getSubReg();
6955 bool Src0Kill = Src0.isKill();
6956
6957 if (Src1.isImm())
6958 Src0.ChangeToImmediate(Src1.getImm());
6959 else if (Src1.isReg()) {
6960 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
6961 Src0.setSubReg(Src1.getSubReg());
6962 } else
6963 llvm_unreachable("Should only have register or immediate operands");
6964
6965 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
6966 Src1.setSubReg(Src0SubReg);
6968}
6969
6970// Legalize VOP3 operands. All operand types are supported for any operand
6971// but only one literal constant and only starting from GFX10.
6973 MachineInstr &MI) const {
6974 unsigned Opc = MI.getOpcode();
6975
6976 int VOP3Idx[3] = {
6977 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
6978 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
6979 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
6980 };
6981
6982 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6983 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6984 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6985 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6986 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6987 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6988 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6989 // src1 and src2 must be scalar
6990 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
6991 const DebugLoc &DL = MI.getDebugLoc();
6992 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
6993 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6994 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6995 .add(Src1);
6996 Src1.ChangeToRegister(Reg, false);
6997 }
6998 if (VOP3Idx[2] != -1) {
6999 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
7000 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
7001 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7002 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7003 .add(Src2);
7004 Src2.ChangeToRegister(Reg, false);
7005 }
7006 }
7007 }
7008
7009 // Find the one SGPR operand we are allowed to use.
7010 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
7011 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7012 SmallDenseSet<unsigned> SGPRsUsed;
7013 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
7014 if (SGPRReg) {
7015 SGPRsUsed.insert(SGPRReg);
7016 --ConstantBusLimit;
7017 }
7018
7019 for (int Idx : VOP3Idx) {
7020 if (Idx == -1)
7021 break;
7022 MachineOperand &MO = MI.getOperand(Idx);
7023
7024 if (!MO.isReg()) {
7025 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
7026 continue;
7027
7028 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7029 --LiteralLimit;
7030 --ConstantBusLimit;
7031 continue;
7032 }
7033
7034 --LiteralLimit;
7035 --ConstantBusLimit;
7036 legalizeOpWithMove(MI, Idx);
7037 continue;
7038 }
7039
7040 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
7041 continue; // VGPRs are legal
7042
7043 // We can use one SGPR in each VOP3 instruction prior to GFX10
7044 // and two starting from GFX10.
7045 if (SGPRsUsed.count(MO.getReg()))
7046 continue;
7047 if (ConstantBusLimit > 0) {
7048 SGPRsUsed.insert(MO.getReg());
7049 --ConstantBusLimit;
7050 continue;
7051 }
7052
7053 // If we make it this far, then the operand is not legal and we must
7054 // legalize it.
7055 legalizeOpWithMove(MI, Idx);
7056 }
7057
7058 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
7059 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64) &&
7060 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
7061 legalizeOpWithMove(MI, VOP3Idx[2]);
7062
7063 // Fix the register class of single-sgpr-read instructions on gfx12+. See
7064 // SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
7066 for (unsigned I = 0; I < 3; ++I) {
7067 if (!isLegalSingleSGPRReadInstOperand(MRI, MI, /*SrcN=*/I))
7068 legalizeOpWithMove(MI, VOP3Idx[I]);
7069 }
7070 }
7071}
7072
7075 const TargetRegisterClass *DstRC /*=nullptr*/) const {
7076 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
7077 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
7078 if (DstRC)
7079 SRC = RI.getCommonSubClass(SRC, DstRC);
7080
7081 Register DstReg = MRI.createVirtualRegister(SRC);
7082 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7083
7084 if (RI.hasAGPRs(VRC)) {
7085 VRC = RI.getEquivalentVGPRClass(VRC);
7086 Register NewSrcReg = MRI.createVirtualRegister(VRC);
7087 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7088 get(TargetOpcode::COPY), NewSrcReg)
7089 .addReg(SrcReg);
7090 SrcReg = NewSrcReg;
7091 }
7092
7093 if (SubRegs == 1) {
7094 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7095 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7096 .addReg(SrcReg);
7097 return DstReg;
7098 }
7099
7101 for (unsigned i = 0; i < SubRegs; ++i) {
7102 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7103 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7104 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7105 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7106 SRegs.push_back(SGPR);
7107 }
7108
7110 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7111 get(AMDGPU::REG_SEQUENCE), DstReg);
7112 for (unsigned i = 0; i < SubRegs; ++i) {
7113 MIB.addReg(SRegs[i]);
7114 MIB.addImm(RI.getSubRegFromChannel(i));
7115 }
7116 return DstReg;
7117}
7118
7120 MachineInstr &MI) const {
7121
7122 // If the pointer is store in VGPRs, then we need to move them to
7123 // SGPRs using v_readfirstlane. This is safe because we only select
7124 // loads with uniform pointers to SMRD instruction so we know the
7125 // pointer value is uniform.
7126 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
7127 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
7128 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
7129 SBase->setReg(SGPR);
7130 }
7131 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
7132 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
7133 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
7134 SOff->setReg(SGPR);
7135 }
7136}
7137
7139 unsigned Opc = Inst.getOpcode();
7140 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
7141 if (OldSAddrIdx < 0)
7142 return false;
7143
7144 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
7145
7146 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
7147 if (NewOpc < 0)
7149 if (NewOpc < 0)
7150 return false;
7151
7152 MachineRegisterInfo &MRI = Inst.getMF()->getRegInfo();
7153 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
7154 if (RI.isSGPRReg(MRI, SAddr.getReg()))
7155 return false;
7156
7157 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7158 if (NewVAddrIdx < 0)
7159 return false;
7160
7161 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
7162
7163 // Check vaddr, it shall be zero or absent.
7164 MachineInstr *VAddrDef = nullptr;
7165 if (OldVAddrIdx >= 0) {
7166 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
7167 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
7168 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
7169 !VAddrDef->getOperand(1).isImm() ||
7170 VAddrDef->getOperand(1).getImm() != 0)
7171 return false;
7172 }
7173
7174 const MCInstrDesc &NewDesc = get(NewOpc);
7175 Inst.setDesc(NewDesc);
7176
7177 // Callers expect iterator to be valid after this call, so modify the
7178 // instruction in place.
7179 if (OldVAddrIdx == NewVAddrIdx) {
7180 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
7181 // Clear use list from the old vaddr holding a zero register.
7182 MRI.removeRegOperandFromUseList(&NewVAddr);
7183 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7184 Inst.removeOperand(OldSAddrIdx);
7185 // Update the use list with the pointer we have just moved from vaddr to
7186 // saddr position. Otherwise new vaddr will be missing from the use list.
7187 MRI.removeRegOperandFromUseList(&NewVAddr);
7188 MRI.addRegOperandToUseList(&NewVAddr);
7189 } else {
7190 assert(OldSAddrIdx == NewVAddrIdx);
7191
7192 if (OldVAddrIdx >= 0) {
7193 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7194 AMDGPU::OpName::vdst_in);
7195
7196 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
7197 // it asserts. Untie the operands for now and retie them afterwards.
7198 if (NewVDstIn != -1) {
7199 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
7200 Inst.untieRegOperand(OldVDstIn);
7201 }
7202
7203 Inst.removeOperand(OldVAddrIdx);
7204
7205 if (NewVDstIn != -1) {
7206 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7207 Inst.tieOperands(NewVDst, NewVDstIn);
7208 }
7209 }
7210 }
7211
7212 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
7213 VAddrDef->eraseFromParent();
7214
7215 return true;
7216}
7217
7218// FIXME: Remove this when SelectionDAG is obsoleted.
7220 MachineInstr &MI) const {
7221 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
7222 return;
7223
7224 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
7225 // thinks they are uniform, so a readfirstlane should be valid.
7226 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
7227 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
7228 return;
7229
7231 return;
7232
7233 const TargetRegisterClass *DeclaredRC =
7234 getRegClass(MI.getDesc(), SAddr->getOperandNo());
7235
7236 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
7237 SAddr->setReg(ToSGPR);
7238}
7239
7242 const TargetRegisterClass *DstRC,
7245 const DebugLoc &DL) const {
7246 Register OpReg = Op.getReg();
7247 unsigned OpSubReg = Op.getSubReg();
7248
7249 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
7250 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7251
7252 // Check if operand is already the correct register class.
7253 if (DstRC == OpRC)
7254 return;
7255
7256 Register DstReg = MRI.createVirtualRegister(DstRC);
7257 auto Copy = BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg)
7258 .addReg(OpReg, {}, OpSubReg);
7259 Op.setReg(DstReg);
7260 Op.setSubReg(AMDGPU::NoSubRegister);
7261
7262 MachineInstr *Def = MRI.getVRegDef(OpReg);
7263 if (!Def)
7264 return;
7265
7266 // Try to eliminate the copy if it is copying an immediate value.
7267 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7268 foldImmediate(*Copy, *Def, OpReg, &MRI);
7269
7270 bool ImpDef = Def->isImplicitDef();
7271 while (!ImpDef && Def && Def->isCopy()) {
7272 if (Def->getOperand(1).getReg().isPhysical())
7273 break;
7274 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7275 ImpDef = Def && Def->isImplicitDef();
7276 }
7277 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7278 !ImpDef)
7279 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7280}
7281
7282// Emit the actual waterfall loop, executing the wrapped instruction for each
7283// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7284// iteration, in the worst case we execute 64 (once per lane).
7287 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7288 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7289 MachineFunction &MF = *LoopBB.getParent();
7291 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7293 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7294
7295 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7296 // available. Otherwise, use the previous pattern of v_cmp_eq,
7297 // s_and_saveexec, and s_xor.
7298 bool UseNewExecInstructions =
7299 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7300
7302 Register CondReg;
7303
7304 Register PhiExec;
7305 Register NewExec;
7306
7307 if (UseNewExecInstructions) {
7308 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7309 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7310 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7311 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7312 .addReg(LMC.ExecReg);
7313
7314 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7315 .addReg(InitExec)
7316 .addMBB(&PredBB)
7317 .addReg(NewExec)
7318 .addMBB(&BodyBB);
7319 }
7320
7321 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7322 // involves a trade-off between register pressure and latency:
7323 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7324 // register pressure because arguments and results of all
7325 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7326 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7327 // increase latency by placing v_readfirstlane instructions
7328 // immediately before v_cmpx instruction that directly depend on it.
7329 ///
7330 // Emitting interleaved v_cmpx and v_readfirstlane requires
7331 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7332 // v_cmpx needs to be treated as terminator until after register allocation
7333 // (spill placement) and instruction reordering.
7334 //
7335 // Current implementation defers v_cmpx and leaves other instruction
7336 // scheduling decisions to later passes, where register pressure is known or
7337 // easier to approximate.
7338 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7339 // v_cmpx instructions are inserted at the end of LoopBB.
7340 // After the first v_cmpx is emitted, I is updated to point to it
7341 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7342 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7343 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7344 unsigned NumSubRegs = RegSize / 32;
7345 Register VScalarOp = ScalarOp->getReg();
7346
7347 const TargetRegisterClass *RFLSrcRC =
7348 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7349
7350 if (NumSubRegs == 1) {
7351 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7352 if (const TargetRegisterClass *Common =
7353 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7354 Common != VScalarOpRC) {
7355 Register VRReg = MRI.createVirtualRegister(Common);
7356 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7357 VScalarOp = VRReg;
7358 }
7359 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7360
7361 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7362 .addReg(VScalarOp);
7363
7364 if (UseNewExecInstructions) {
7365 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7366 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7367 .addReg(CurReg)
7368 .addReg(VScalarOp);
7369 if (I == LoopBB.end())
7370 I = CmpxMI.getInstr()->getIterator();
7371 } else {
7372 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7373
7374 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7375 .addReg(CurReg)
7376 .addReg(VScalarOp);
7377
7378 // Combine the comparison results with AND.
7379 if (!CondReg) { // First.
7380 CondReg = NewCondReg;
7381 } else { // If not the first, we create an AND.
7382 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7383 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7384 .addReg(CondReg)
7385 .addReg(NewCondReg);
7386 CondReg = AndReg;
7387 }
7388 }
7389
7390 // Update ScalarOp operand to use the SGPR ScalarOp.
7391 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7392 ScalarOp->setReg(CurReg);
7393 else {
7394 // Insert into the same block of use
7395 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7396 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7397 .addReg(CurReg);
7398 ScalarOp->setReg(PhySGPRs[Idx]);
7399 }
7400 ScalarOp->setIsKill();
7401 } else {
7402 SmallVector<Register, 8> ReadlanePieces;
7403 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7404 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7405 "Unhandled register size");
7406
7407 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7408 Register CurRegLo =
7409 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7410 Register CurRegHi =
7411 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7412
7413 // Read the next variant <- also loop target.
7414 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7415 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7416
7417 // Read the next variant <- also loop target.
7418 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7419 .addReg(VScalarOp, VScalarOpUndef,
7420 TRI->getSubRegFromChannel(Idx + 1));
7421
7422 ReadlanePieces.push_back(CurRegLo);
7423 ReadlanePieces.push_back(CurRegHi);
7424
7425 // Comparison is to be done as 64-bit.
7426 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7427 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7428 .addReg(CurRegLo)
7429 .addImm(AMDGPU::sub0)
7430 .addReg(CurRegHi)
7431 .addImm(AMDGPU::sub1);
7432
7433 unsigned SubReg =
7434 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7435
7436 if (UseNewExecInstructions) {
7437 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7438 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7439 .addReg(CurReg)
7440 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7441 if (I == LoopBB.end())
7442 I = CmpxMI.getInstr()->getIterator();
7443 } else {
7444 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7445 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7446 .addReg(CurReg)
7447 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7448
7449 // Combine the comparison results with AND.
7450 if (!CondReg) { // First.
7451 CondReg = NewCondReg;
7452 } else { // If not the first, we create an AND.
7453 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7454 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7455 .addReg(CondReg)
7456 .addReg(NewCondReg);
7457 CondReg = AndReg;
7458 }
7459 }
7460 } // End for loop.
7461
7462 const auto *SScalarOpRC =
7463 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7464 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7465
7466 // Build scalar ScalarOp.
7467 auto Merge =
7468 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7469 unsigned Channel = 0;
7470 for (Register Piece : ReadlanePieces) {
7471 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7472 }
7473
7474 // Update ScalarOp operand to use the SGPR ScalarOp.
7475 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7476 ScalarOp->setReg(SScalarOp);
7477 else {
7478 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7479 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7480 .addReg(SScalarOp);
7481 ScalarOp->setReg(PhySGPRs[Idx]);
7482 }
7483 ScalarOp->setIsKill();
7484 }
7485 }
7486
7487 // Instructions AndSaveExecOpc and AndN2WrExecOpc that modify EXEC mask
7488 // should have isTerminator=1 but terminators that define
7489 // virtual registers are not supported.
7490 Register SaveExec;
7491 if (!UseNewExecInstructions) {
7492 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7493 MRI.setSimpleHint(SaveExec, CondReg);
7494
7495 // Update EXEC to matching lanes, saving original to SaveExec.
7496 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7497 .addReg(CondReg, RegState::Kill);
7498 }
7499
7500 // The original instruction is here; we insert the terminators after it.
7501 I = BodyBB.end();
7502
7503 if (UseNewExecInstructions) {
7504 MRI.setSimpleHint(NewExec, PhiExec);
7505 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2WrExecOpc), NewExec)
7506 .addReg(PhiExec);
7507 } else {
7508 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7509 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7510 .addReg(LMC.ExecReg)
7511 .addReg(SaveExec);
7512 }
7513
7514 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7515}
7516
7517// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7518// with SGPRs by iterating over all unique values across all lanes.
7519// Returns the loop basic block that now contains \p MI.
7520static MachineBasicBlock *
7524 MachineBasicBlock::iterator Begin = nullptr,
7525 MachineBasicBlock::iterator End = nullptr,
7526 ArrayRef<Register> PhySGPRs = {}) {
7527 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7528 "Physical SGPRs must be empty or match the number of scalar operands");
7530 MachineFunction &MF = *MBB.getParent();
7532 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7533 MachineRegisterInfo &MRI = MF.getRegInfo();
7534 if (!Begin.isValid())
7535 Begin = &MI;
7536 if (!End.isValid()) {
7537 End = &MI;
7538 ++End;
7539 }
7540 const DebugLoc &DL = MI.getDebugLoc();
7542 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7543
7544 // Save SCC. Waterfall Loop may overwrite SCC.
7545 Register SaveSCCReg;
7546
7547 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7548 // rather than unlimited scan everywhere
7549 bool SCCNotDead =
7550 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7551 std::numeric_limits<unsigned>::max()) !=
7553 if (SCCNotDead) {
7554 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7555 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7556 .addImm(1)
7557 .addImm(0);
7558 }
7559
7560 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7561
7562 // Save the EXEC mask
7563 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7564
7565 // Killed uses in the instruction we are waterfalling around will be
7566 // incorrect due to the added control-flow.
7568 ++AfterMI;
7569 for (auto I = Begin; I != AfterMI; I++) {
7570 for (auto &MO : I->all_uses())
7571 MRI.clearKillFlags(MO.getReg());
7572 }
7573
7574 // To insert the loop we need to split the block. Move everything after this
7575 // point to a new block, and insert a new empty block between the two.
7578 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7580 ++MBBI;
7581
7582 MF.insert(MBBI, LoopBB);
7583 MF.insert(MBBI, BodyBB);
7584 MF.insert(MBBI, RemainderBB);
7585
7586 LoopBB->addSuccessor(BodyBB);
7587 BodyBB->addSuccessor(LoopBB);
7588 BodyBB->addSuccessor(RemainderBB);
7589
7590 // Move Begin to MI to the BodyBB, and the remainder of the block to
7591 // RemainderBB.
7592 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7593 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7594 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7595
7596 MBB.addSuccessor(LoopBB);
7597
7598 // Update dominators. We know that MBB immediately dominates LoopBB, that
7599 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7600 // RemainderBB. RemainderBB immediately dominates all of the successors
7601 // transferred to it from MBB that MBB used to properly dominate.
7602 if (MDT) {
7603 MDT->addNewBlock(LoopBB, &MBB);
7604 MDT->addNewBlock(BodyBB, LoopBB);
7605 MDT->addNewBlock(RemainderBB, BodyBB);
7606 for (auto &Succ : RemainderBB->successors()) {
7607 if (MDT->properlyDominates(&MBB, Succ)) {
7608 MDT->changeImmediateDominator(Succ, RemainderBB);
7609 }
7610 }
7611 }
7612
7613 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7614 PhySGPRs);
7615
7616 MachineBasicBlock::iterator First = RemainderBB->begin();
7617 // Restore SCC
7618 if (SCCNotDead) {
7619 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7620 .addReg(SaveSCCReg, RegState::Kill)
7621 .addImm(0);
7622 }
7623
7624 // Restore the EXEC mask
7625 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7626 .addReg(SaveExec);
7627 return BodyBB;
7628}
7629
7630// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7631static std::tuple<unsigned, unsigned>
7633 MachineBasicBlock &MBB = *MI.getParent();
7634 MachineFunction &MF = *MBB.getParent();
7635 MachineRegisterInfo &MRI = MF.getRegInfo();
7636
7637 // Extract the ptr from the resource descriptor.
7638 unsigned RsrcPtr =
7639 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7640 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7641
7642 // Create an empty resource descriptor
7643 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7644 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7645 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7646 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7647 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7648
7649 // Zero64 = 0
7650 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7651 .addImm(0);
7652
7653 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7654 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7655 .addImm(Lo_32(RsrcDataFormat));
7656
7657 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7658 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7659 .addImm(Hi_32(RsrcDataFormat));
7660
7661 // NewSRsrc = {Zero64, SRsrcFormat}
7662 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7663 .addReg(Zero64)
7664 .addImm(AMDGPU::sub0_sub1)
7665 .addReg(SRsrcFormatLo)
7666 .addImm(AMDGPU::sub2)
7667 .addReg(SRsrcFormatHi)
7668 .addImm(AMDGPU::sub3);
7669
7670 return std::tuple(RsrcPtr, NewSRsrc);
7671}
7672
7675 MachineDominatorTree *MDT) const {
7676 MachineFunction &MF = *MI.getMF();
7677 MachineRegisterInfo &MRI = MF.getRegInfo();
7678 MachineBasicBlock *CreatedBB = nullptr;
7679
7680 // Legalize True16
7681 if (ST.useRealTrue16Insts())
7683
7684 // Legalize VOP2
7685 if (isVOP2(MI) || isVOPC(MI)) {
7687 return CreatedBB;
7688 }
7689
7690 // Legalize VOP3
7691 if (isVOP3(MI)) {
7693 return CreatedBB;
7694 }
7695
7696 // Legalize SMRD
7697 if (isSMRD(MI)) {
7699 return CreatedBB;
7700 }
7701
7702 // Legalize FLAT
7703 if (isFLAT(MI)) {
7705 return CreatedBB;
7706 }
7707
7708 // Legalize PHI
7709 // The register class of the operands must be the same type as the register
7710 // class of the output.
7711 if (MI.getOpcode() == AMDGPU::PHI) {
7712 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7713 assert(!RI.isSGPRClass(VRC));
7714
7715 // Update all the operands so they have the same type.
7716 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7717 MachineOperand &Op = MI.getOperand(I);
7718 if (!Op.isReg() || !Op.getReg().isVirtual())
7719 continue;
7720
7721 // MI is a PHI instruction.
7722 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7724
7725 // Avoid creating no-op copies with the same src and dst reg class. These
7726 // confuse some of the machine passes.
7727 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7728 }
7729 }
7730
7731 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7732 // VGPR dest type and SGPR sources, insert copies so all operands are
7733 // VGPRs. This seems to help operand folding / the register coalescer.
7734 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7735 MachineBasicBlock *MBB = MI.getParent();
7736 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7737 if (RI.hasVGPRs(DstRC)) {
7738 // Update all the operands so they are VGPR register classes. These may
7739 // not be the same register class because REG_SEQUENCE supports mixing
7740 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7741 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7742 MachineOperand &Op = MI.getOperand(I);
7743 if (!Op.isReg() || !Op.getReg().isVirtual())
7744 continue;
7745
7746 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7747 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7748 if (VRC == OpRC)
7749 continue;
7750
7751 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7752 Op.setIsKill();
7753 }
7754 }
7755
7756 return CreatedBB;
7757 }
7758
7759 // Legalize INSERT_SUBREG
7760 // src0 must have the same register class as dst
7761 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7762 Register Dst = MI.getOperand(0).getReg();
7763 Register Src0 = MI.getOperand(1).getReg();
7764 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7765 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7766 if (DstRC != Src0RC) {
7767 MachineBasicBlock *MBB = MI.getParent();
7768 MachineOperand &Op = MI.getOperand(1);
7769 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7770 }
7771 return CreatedBB;
7772 }
7773
7774 // Legalize SI_INIT_M0
7775 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7776 MachineOperand &Src = MI.getOperand(0);
7777 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7778 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7779 return CreatedBB;
7780 }
7781
7782 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
7783 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7784 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7785 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7786 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7787 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7788 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7789 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7790 MachineOperand &Src = MI.getOperand(1);
7791 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7792 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7793 return CreatedBB;
7794 }
7795
7796 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
7797 //
7798 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
7799 // scratch memory access. In both cases, the legalization never involves
7800 // conversion to the addr64 form.
7802 (isMUBUF(MI) || isMTBUF(MI)))) {
7803 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
7804 ? AMDGPU::OpName::rsrc
7805 : AMDGPU::OpName::srsrc;
7806 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
7807 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
7808 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
7809
7810 AMDGPU::OpName SampOpName =
7811 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7812 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
7813 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
7814 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
7815
7816 return CreatedBB;
7817 }
7818
7819 // Legalize SI_CALL
7820 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7821 MachineOperand *Dest = &MI.getOperand(0);
7822 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
7823 createWaterFallForSiCall(&MI, MDT, {Dest});
7824 }
7825 }
7826
7827 // Legalize s_sleep_var.
7828 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7829 const DebugLoc &DL = MI.getDebugLoc();
7830 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7831 int Src0Idx =
7832 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
7833 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7834 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7835 .add(Src0);
7836 Src0.ChangeToRegister(Reg, false);
7837 return nullptr;
7838 }
7839
7840 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
7841 // operands are scalar.
7842 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7843 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7844 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7845 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7846 for (MachineOperand &Src : MI.explicit_operands()) {
7847 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7848 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7849 }
7850 return CreatedBB;
7851 }
7852
7853 // Legalize MUBUF instructions.
7854 bool isSoffsetLegal = true;
7855 int SoffsetIdx =
7856 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
7857 if (SoffsetIdx != -1) {
7858 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
7859 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
7860 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
7861 isSoffsetLegal = false;
7862 }
7863 }
7864
7865 bool isRsrcLegal = true;
7866 int RsrcIdx =
7867 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
7868 if (RsrcIdx != -1) {
7869 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7870 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
7871 isRsrcLegal = false;
7872 }
7873
7874 // The operands are legal.
7875 if (isRsrcLegal && isSoffsetLegal)
7876 return CreatedBB;
7877
7878 if (!isRsrcLegal) {
7879 // Legalize a VGPR Rsrc
7880 //
7881 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
7882 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
7883 // a zero-value SRsrc.
7884 //
7885 // If the instruction is _OFFSET (both idxen and offen disabled), and we
7886 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
7887 // above.
7888 //
7889 // Otherwise we are on non-ADDR64 hardware, and/or we have
7890 // idxen/offen/bothen and we fall back to a waterfall loop.
7891
7892 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7893 MachineBasicBlock &MBB = *MI.getParent();
7894
7895 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
7896 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
7897 // This is already an ADDR64 instruction so we need to add the pointer
7898 // extracted from the resource descriptor to the current value of VAddr.
7899 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7900 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7901 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7902
7903 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7904 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
7905 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
7906
7907 unsigned RsrcPtr, NewSRsrc;
7908 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7909
7910 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
7911 const DebugLoc &DL = MI.getDebugLoc();
7912 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
7913 .addDef(CondReg0)
7914 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7915 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
7916 .addImm(0);
7917
7918 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
7919 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
7920 .addDef(CondReg1, RegState::Dead)
7921 .addReg(RsrcPtr, {}, AMDGPU::sub1)
7922 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
7923 .addReg(CondReg0, RegState::Kill)
7924 .addImm(0);
7925
7926 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7927 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
7928 .addReg(NewVAddrLo)
7929 .addImm(AMDGPU::sub0)
7930 .addReg(NewVAddrHi)
7931 .addImm(AMDGPU::sub1);
7932
7933 VAddr->setReg(NewVAddr);
7934 Rsrc->setReg(NewSRsrc);
7935 } else if (!VAddr && ST.hasAddr64()) {
7936 // This instructions is the _OFFSET variant, so we need to convert it to
7937 // ADDR64.
7938 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
7939 "FIXME: Need to emit flat atomics here");
7940
7941 unsigned RsrcPtr, NewSRsrc;
7942 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7943
7944 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7945 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
7946 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
7947 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7948 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
7949
7950 // Atomics with return have an additional tied operand and are
7951 // missing some of the special bits.
7952 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
7953 MachineInstr *Addr64;
7954
7955 if (!VDataIn) {
7956 // Regular buffer load / store.
7958 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7959 .add(*VData)
7960 .addReg(NewVAddr)
7961 .addReg(NewSRsrc)
7962 .add(*SOffset)
7963 .add(*Offset);
7964
7965 if (const MachineOperand *CPol =
7966 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
7967 MIB.addImm(CPol->getImm());
7968 }
7969
7970 if (const MachineOperand *TFE =
7971 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
7972 MIB.addImm(TFE->getImm());
7973 }
7974
7975 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
7976
7977 MIB.cloneMemRefs(MI);
7978 Addr64 = MIB;
7979 } else {
7980 // Atomics with return.
7981 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7982 .add(*VData)
7983 .add(*VDataIn)
7984 .addReg(NewVAddr)
7985 .addReg(NewSRsrc)
7986 .add(*SOffset)
7987 .add(*Offset)
7988 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
7989 .cloneMemRefs(MI);
7990 }
7991
7992 MI.removeFromParent();
7993
7994 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7995 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
7996 NewVAddr)
7997 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7998 .addImm(AMDGPU::sub0)
7999 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8000 .addImm(AMDGPU::sub1);
8001 } else {
8002 // Legalize a VGPR Rsrc and soffset together.
8003 if (!isSoffsetLegal) {
8004 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8005 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
8006 return CreatedBB;
8007 }
8008 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
8009 return CreatedBB;
8010 }
8011 }
8012
8013 // Legalize a VGPR soffset.
8014 if (!isSoffsetLegal) {
8015 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8016 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
8017 return CreatedBB;
8018 }
8019 return CreatedBB;
8020}
8021
8023 if (InSet.insert(MI).second)
8024 InstrList.push_back(MI);
8025 // Add MBUF instructiosn to deferred list.
8026 int RsrcIdx =
8027 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
8028 if (RsrcIdx != -1) {
8029 DeferredList.insert(MI);
8030 }
8031}
8032
8034 return DeferredList.contains(MI);
8035}
8036
8037// Legalize size mismatches between 16bit and 32bit registers in v2s copy
8038// lowering (change sgpr to vgpr).
8039// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
8040// size. Need to legalize the size of the operands during the vgpr lowering
8041// chain. This can be removed after we have sgpr16 in place
8043 MachineRegisterInfo &MRI) const {
8044 if (!ST.useRealTrue16Insts())
8045 return;
8046
8047 unsigned Opcode = MI.getOpcode();
8048 MachineBasicBlock *MBB = MI.getParent();
8049 // Legalize operands and check for size mismatch
8050 if (OpIdx >= MI.getNumExplicitOperands() ||
8051 OpIdx >= get(Opcode).getNumOperands() ||
8052 get(Opcode).operands()[OpIdx].RegClass == -1)
8053 return;
8054
8055 MachineOperand &Op = MI.getOperand(OpIdx);
8056 if (!Op.isReg() || !Op.getReg().isVirtual() || Op.isDef())
8057 return;
8058
8059 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
8060 if (!RI.isVGPRClass(CurrRC))
8061 return;
8062
8063 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
8064 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
8065 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8066 // Default to the lo16 only if the subregister is not specified.
8067 if (Op.getSubReg() == AMDGPU::NoSubRegister)
8068 Op.setSubReg(AMDGPU::lo16);
8069 return;
8070 }
8071
8072 const TargetRegisterClass *CurrSRC =
8073 RI.getSubRegisterClass(CurrRC, Op.getSubReg());
8074 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8075 const DebugLoc &DL = MI.getDebugLoc();
8076 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8077 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8078 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
8079 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
8080 .addReg(Op.getReg(), {}, Op.getSubReg())
8081 .addImm(AMDGPU::lo16)
8082 .addReg(Undef)
8083 .addImm(AMDGPU::hi16);
8084 Op.setReg(NewDstReg);
8085 Op.setSubReg(AMDGPU::NoSubRegister);
8086 }
8087}
8089 MachineRegisterInfo &MRI) const {
8090 for (unsigned OpIdx = 0; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
8091 legalizeOperandsVALUt16(MI, OpIdx, MRI);
8092}
8093
8097 ArrayRef<Register> PhySGPRs) const {
8098 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8099 "This only handle waterfall for SI_CALL_ISEL");
8100 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
8101 // following copies, we also need to move copies from and to physical
8102 // registers into the loop block.
8103 // Also move the copies to physical registers into the loop block
8104 MachineBasicBlock &MBB = *MI->getParent();
8106 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8107 --Start;
8109 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8110 ++End;
8111
8112 // Also include following copies of the return value
8113 ++End;
8114 while (End != MBB.end() && End->isCopy() &&
8115 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8116 ++End;
8117
8118 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
8119}
8120
8122 MachineDominatorTree *MDT) const {
8124 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
8125 while (!Worklist.empty()) {
8126 MachineInstr &Inst = *Worklist.top();
8127 Worklist.erase_top();
8128 // Skip MachineInstr in the deferred list.
8129 if (Worklist.isDeferred(&Inst))
8130 continue;
8131 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8132 }
8133
8134 // Deferred list of instructions will be processed once
8135 // all the MachineInstr in the worklist are done.
8136 for (MachineInstr *Inst : Worklist.getDeferredList()) {
8137 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8138 assert(Worklist.empty() &&
8139 "Deferred MachineInstr are not supposed to re-populate worklist");
8140 }
8141
8142 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
8143 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8144 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
8145 Entry.second.SGPRs);
8146 }
8147
8148 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8149 if (Entry.second)
8150 Entry.first->eraseFromParent();
8151}
8153 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
8154 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
8155 // hope for the best.
8156 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
8157 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
8158 if (SubRegIndices.size() <= 1) {
8159 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8160 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8161 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8162 .add(Inst.getOperand(1));
8163 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
8164 DstReg)
8165 .addReg(NewDst);
8166 } else {
8168 for (int16_t Indice : SubRegIndices) {
8169 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8170 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8171 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8172 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
8173
8174 DstRegs.push_back(NewDst);
8175 }
8177 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8178 get(AMDGPU::REG_SEQUENCE), DstReg);
8179 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
8180 MIB.addReg(DstRegs[i]);
8181 MIB.addImm(RI.getSubRegFromChannel(i));
8182 }
8183 }
8184}
8185
8187 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
8190 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8191 if (DstReg == AMDGPU::M0) {
8192 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8193 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8194 return;
8195 }
8196 Register SrcReg = Inst.getOperand(1).getReg();
8199 // Only search current block since phyreg's def & use cannot cross
8200 // blocks when MF.NoPhi = false.
8201 while (++I != E) {
8202 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
8203 // and record the operand for later waterfall loop generation.
8204 if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8205 MachineInstr *UseMI = &*I;
8206 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
8207 if (UseMI->getOperand(i).isReg() &&
8208 UseMI->getOperand(i).getReg() == DstReg) {
8209 MachineOperand *MO = &UseMI->getOperand(i);
8210 MO->setReg(SrcReg);
8211 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
8212 V2SCopyInfo.MOs.push_back(MO);
8213 V2SCopyInfo.SGPRs.push_back(DstReg);
8214 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8215 }
8216 }
8217 } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8218 I->getOperand(0).isReg() &&
8219 I->getOperand(0).getReg() == DstReg) {
8220 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8221 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8222 } else if (I->readsRegister(DstReg, &RI)) {
8223 // COPY cannot be erased if other type of inst uses it.
8224 V2SPhyCopiesToErase[&Inst] = false;
8225 }
8226 if (I->findRegisterDefOperand(DstReg, &RI))
8227 break;
8228 }
8229}
8230
8232 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
8234 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8235
8237 if (!MBB)
8238 return;
8239 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
8240 unsigned Opcode = Inst.getOpcode();
8241 unsigned NewOpcode = getVALUOp(Inst);
8242 const DebugLoc &DL = Inst.getDebugLoc();
8243
8244 // Handle some special cases
8245 switch (Opcode) {
8246 default:
8247 break;
8248 case AMDGPU::S_ADD_I32:
8249 case AMDGPU::S_SUB_I32: {
8250 // FIXME: The u32 versions currently selected use the carry.
8251 bool Changed;
8252 MachineBasicBlock *CreatedBBTmp = nullptr;
8253 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8254 if (Changed)
8255 return;
8256
8257 // Default handling
8258 break;
8259 }
8260
8261 case AMDGPU::S_MUL_U64:
8262 if (ST.useVMulU64Inst()) {
8263 NewOpcode = AMDGPU::V_MUL_U64_e64;
8264 break;
8265 }
8266 // Split s_mul_u64 in 32-bit vector multiplications.
8267 splitScalarSMulU64(Worklist, Inst, MDT);
8268 Inst.eraseFromParent();
8269 return;
8270
8271 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8272 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8273 // This is a special case of s_mul_u64 where all the operands are either
8274 // zero extended or sign extended.
8275 splitScalarSMulPseudo(Worklist, Inst, MDT);
8276 Inst.eraseFromParent();
8277 return;
8278
8279 case AMDGPU::S_AND_B64:
8280 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8281 Inst.eraseFromParent();
8282 return;
8283
8284 case AMDGPU::S_OR_B64:
8285 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8286 Inst.eraseFromParent();
8287 return;
8288
8289 case AMDGPU::S_XOR_B64:
8290 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8291 Inst.eraseFromParent();
8292 return;
8293
8294 case AMDGPU::S_NAND_B64:
8295 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8296 Inst.eraseFromParent();
8297 return;
8298
8299 case AMDGPU::S_NOR_B64:
8300 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8301 Inst.eraseFromParent();
8302 return;
8303
8304 case AMDGPU::S_XNOR_B64:
8305 if (ST.hasDLInsts())
8306 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8307 else
8308 splitScalar64BitXnor(Worklist, Inst, MDT);
8309 Inst.eraseFromParent();
8310 return;
8311
8312 case AMDGPU::S_ANDN2_B64:
8313 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8314 Inst.eraseFromParent();
8315 return;
8316
8317 case AMDGPU::S_ORN2_B64:
8318 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8319 Inst.eraseFromParent();
8320 return;
8321
8322 case AMDGPU::S_BREV_B64:
8323 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8324 Inst.eraseFromParent();
8325 return;
8326
8327 case AMDGPU::S_NOT_B64:
8328 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8329 Inst.eraseFromParent();
8330 return;
8331
8332 case AMDGPU::S_BCNT1_I32_B64:
8333 splitScalar64BitBCNT(Worklist, Inst);
8334 Inst.eraseFromParent();
8335 return;
8336
8337 case AMDGPU::S_BFE_I64:
8338 splitScalar64BitBFE(Worklist, Inst);
8339 Inst.eraseFromParent();
8340 return;
8341
8342 case AMDGPU::S_FLBIT_I32_B64:
8343 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8344 Inst.eraseFromParent();
8345 return;
8346 case AMDGPU::S_FF1_I32_B64:
8347 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8348 Inst.eraseFromParent();
8349 return;
8350
8351 case AMDGPU::S_LSHL_B32:
8352 if (ST.hasOnlyRevVALUShifts()) {
8353 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8354 swapOperands(Inst);
8355 }
8356 break;
8357 case AMDGPU::S_ASHR_I32:
8358 if (ST.hasOnlyRevVALUShifts()) {
8359 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8360 swapOperands(Inst);
8361 }
8362 break;
8363 case AMDGPU::S_LSHR_B32:
8364 if (ST.hasOnlyRevVALUShifts()) {
8365 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8366 swapOperands(Inst);
8367 }
8368 break;
8369 case AMDGPU::S_LSHL_B64:
8370 if (ST.hasOnlyRevVALUShifts()) {
8371 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8372 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8373 : AMDGPU::V_LSHLREV_B64_e64;
8374 swapOperands(Inst);
8375 }
8376 break;
8377 case AMDGPU::S_ASHR_I64:
8378 if (ST.hasOnlyRevVALUShifts()) {
8379 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8380 swapOperands(Inst);
8381 }
8382 break;
8383 case AMDGPU::S_LSHR_B64:
8384 if (ST.hasOnlyRevVALUShifts()) {
8385 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8386 swapOperands(Inst);
8387 }
8388 break;
8389
8390 case AMDGPU::S_ABS_I32:
8391 lowerScalarAbs(Worklist, Inst);
8392 Inst.eraseFromParent();
8393 return;
8394
8395 case AMDGPU::S_ABSDIFF_I32:
8396 lowerScalarAbsDiff(Worklist, Inst);
8397 Inst.eraseFromParent();
8398 return;
8399
8400 case AMDGPU::S_CBRANCH_SCC0:
8401 case AMDGPU::S_CBRANCH_SCC1: {
8402 // Clear unused bits of vcc
8403 Register CondReg = Inst.getOperand(1).getReg();
8404 bool IsSCC = CondReg == AMDGPU::SCC;
8406 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8407 .addReg(LMC.ExecReg)
8408 .addReg(IsSCC ? LMC.VccReg : CondReg);
8409 Inst.removeOperand(1);
8410 } break;
8411
8412 case AMDGPU::S_BFE_U64:
8413 case AMDGPU::S_BFM_B64:
8414 llvm_unreachable("Moving this op to VALU not implemented");
8415
8416 case AMDGPU::S_PACK_LL_B32_B16:
8417 case AMDGPU::S_PACK_LH_B32_B16:
8418 case AMDGPU::S_PACK_HL_B32_B16:
8419 case AMDGPU::S_PACK_HH_B32_B16:
8420 movePackToVALU(Worklist, MRI, Inst);
8421 Inst.eraseFromParent();
8422 return;
8423
8424 case AMDGPU::S_XNOR_B32:
8425 lowerScalarXnor(Worklist, Inst);
8426 Inst.eraseFromParent();
8427 return;
8428
8429 case AMDGPU::S_NAND_B32:
8430 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8431 Inst.eraseFromParent();
8432 return;
8433
8434 case AMDGPU::S_NOR_B32:
8435 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8436 Inst.eraseFromParent();
8437 return;
8438
8439 case AMDGPU::S_ANDN2_B32:
8440 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8441 Inst.eraseFromParent();
8442 return;
8443
8444 case AMDGPU::S_ORN2_B32:
8445 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8446 Inst.eraseFromParent();
8447 return;
8448
8449 // TODO: remove as soon as everything is ready
8450 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8451 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8452 // can only be selected from the uniform SDNode.
8453 case AMDGPU::S_ADD_CO_PSEUDO:
8454 case AMDGPU::S_SUB_CO_PSEUDO: {
8455 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8456 ? AMDGPU::V_ADDC_U32_e64
8457 : AMDGPU::V_SUBB_U32_e64;
8458 const auto *CarryRC = RI.getWaveMaskRegClass();
8459
8460 Register CarryInReg = Inst.getOperand(4).getReg();
8461 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8462 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8463 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8464 .addReg(CarryInReg);
8465 }
8466
8467 Register CarryOutReg = Inst.getOperand(1).getReg();
8468
8469 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8470 MRI.getRegClass(Inst.getOperand(0).getReg())));
8471 MachineInstr *CarryOp =
8472 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8473 .addReg(CarryOutReg, RegState::Define)
8474 .add(Inst.getOperand(2))
8475 .add(Inst.getOperand(3))
8476 .addReg(CarryInReg)
8477 .addImm(0);
8478 legalizeOperands(*CarryOp);
8479 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8480 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8481 Inst.eraseFromParent();
8482 }
8483 return;
8484 case AMDGPU::S_UADDO_PSEUDO:
8485 case AMDGPU::S_USUBO_PSEUDO: {
8486 MachineOperand &Dest0 = Inst.getOperand(0);
8487 MachineOperand &Dest1 = Inst.getOperand(1);
8488 MachineOperand &Src0 = Inst.getOperand(2);
8489 MachineOperand &Src1 = Inst.getOperand(3);
8490
8491 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8492 ? AMDGPU::V_ADD_CO_U32_e64
8493 : AMDGPU::V_SUB_CO_U32_e64;
8494 const TargetRegisterClass *NewRC =
8495 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8496 Register DestReg = MRI.createVirtualRegister(NewRC);
8497 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8498 .addReg(Dest1.getReg(), RegState::Define)
8499 .add(Src0)
8500 .add(Src1)
8501 .addImm(0); // clamp bit
8502
8503 legalizeOperands(*NewInstr, MDT);
8504 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8505 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8506 Inst.eraseFromParent();
8507 }
8508 return;
8509 case AMDGPU::S_LSHL1_ADD_U32:
8510 case AMDGPU::S_LSHL2_ADD_U32:
8511 case AMDGPU::S_LSHL3_ADD_U32:
8512 case AMDGPU::S_LSHL4_ADD_U32: {
8513 MachineOperand &Dest = Inst.getOperand(0);
8514 MachineOperand &Src0 = Inst.getOperand(1);
8515 MachineOperand &Src1 = Inst.getOperand(2);
8516 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8517 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8518 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8519 : 4);
8520
8521 const TargetRegisterClass *NewRC =
8522 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8523 Register DestReg = MRI.createVirtualRegister(NewRC);
8524 MachineInstr *NewInstr =
8525 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8526 .add(Src0)
8527 .addImm(ShiftAmt)
8528 .add(Src1);
8529
8530 legalizeOperands(*NewInstr, MDT);
8531 MRI.replaceRegWith(Dest.getReg(), DestReg);
8532 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8533 Inst.eraseFromParent();
8534 }
8535 return;
8536 case AMDGPU::S_CSELECT_B32:
8537 case AMDGPU::S_CSELECT_B64:
8538 lowerSelect(Worklist, Inst, MDT);
8539 Inst.eraseFromParent();
8540 return;
8541 case AMDGPU::S_CMP_EQ_I32:
8542 case AMDGPU::S_CMP_LG_I32:
8543 case AMDGPU::S_CMP_GT_I32:
8544 case AMDGPU::S_CMP_GE_I32:
8545 case AMDGPU::S_CMP_LT_I32:
8546 case AMDGPU::S_CMP_LE_I32:
8547 case AMDGPU::S_CMP_EQ_U32:
8548 case AMDGPU::S_CMP_LG_U32:
8549 case AMDGPU::S_CMP_GT_U32:
8550 case AMDGPU::S_CMP_GE_U32:
8551 case AMDGPU::S_CMP_LT_U32:
8552 case AMDGPU::S_CMP_LE_U32:
8553 case AMDGPU::S_CMP_EQ_U64:
8554 case AMDGPU::S_CMP_LG_U64:
8555 case AMDGPU::S_CMP_LT_F32:
8556 case AMDGPU::S_CMP_EQ_F32:
8557 case AMDGPU::S_CMP_LE_F32:
8558 case AMDGPU::S_CMP_GT_F32:
8559 case AMDGPU::S_CMP_LG_F32:
8560 case AMDGPU::S_CMP_GE_F32:
8561 case AMDGPU::S_CMP_O_F32:
8562 case AMDGPU::S_CMP_U_F32:
8563 case AMDGPU::S_CMP_NGE_F32:
8564 case AMDGPU::S_CMP_NLG_F32:
8565 case AMDGPU::S_CMP_NGT_F32:
8566 case AMDGPU::S_CMP_NLE_F32:
8567 case AMDGPU::S_CMP_NEQ_F32:
8568 case AMDGPU::S_CMP_NLT_F32: {
8569 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8570 auto NewInstr =
8571 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8572 .setMIFlags(Inst.getFlags());
8573 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8574 0) {
8575 NewInstr
8576 .addImm(0) // src0_modifiers
8577 .add(Inst.getOperand(0)) // src0
8578 .addImm(0) // src1_modifiers
8579 .add(Inst.getOperand(1)) // src1
8580 .addImm(0); // clamp
8581 } else {
8582 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8583 }
8584 legalizeOperands(*NewInstr, MDT);
8585 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8586 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8587 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8588 Inst.eraseFromParent();
8589 return;
8590 }
8591 case AMDGPU::S_CMP_LT_F16:
8592 case AMDGPU::S_CMP_EQ_F16:
8593 case AMDGPU::S_CMP_LE_F16:
8594 case AMDGPU::S_CMP_GT_F16:
8595 case AMDGPU::S_CMP_LG_F16:
8596 case AMDGPU::S_CMP_GE_F16:
8597 case AMDGPU::S_CMP_O_F16:
8598 case AMDGPU::S_CMP_U_F16:
8599 case AMDGPU::S_CMP_NGE_F16:
8600 case AMDGPU::S_CMP_NLG_F16:
8601 case AMDGPU::S_CMP_NGT_F16:
8602 case AMDGPU::S_CMP_NLE_F16:
8603 case AMDGPU::S_CMP_NEQ_F16:
8604 case AMDGPU::S_CMP_NLT_F16: {
8605 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8606 auto NewInstr =
8607 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8608 .setMIFlags(Inst.getFlags());
8609 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8610 NewInstr
8611 .addImm(0) // src0_modifiers
8612 .add(Inst.getOperand(0)) // src0
8613 .addImm(0) // src1_modifiers
8614 .add(Inst.getOperand(1)) // src1
8615 .addImm(0); // clamp
8616 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8617 NewInstr.addImm(0); // op_sel0
8618 } else {
8619 NewInstr
8620 .add(Inst.getOperand(0))
8621 .add(Inst.getOperand(1));
8622 }
8623 legalizeOperands(*NewInstr, MDT);
8624 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8625 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8626 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8627 Inst.eraseFromParent();
8628 return;
8629 }
8630 case AMDGPU::S_CVT_HI_F32_F16: {
8631 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8632 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8633 if (ST.useRealTrue16Insts()) {
8634 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8635 .add(Inst.getOperand(1));
8636 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8637 .addImm(0) // src0_modifiers
8638 .addReg(TmpReg, {}, AMDGPU::hi16)
8639 .addImm(0) // clamp
8640 .addImm(0) // omod
8641 .addImm(0); // op_sel0
8642 } else {
8643 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8644 .addImm(16)
8645 .add(Inst.getOperand(1));
8646 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8647 .addImm(0) // src0_modifiers
8648 .addReg(TmpReg)
8649 .addImm(0) // clamp
8650 .addImm(0); // omod
8651 }
8652
8653 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8654 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8655 Inst.eraseFromParent();
8656 return;
8657 }
8658 case AMDGPU::S_MINIMUM_F32:
8659 case AMDGPU::S_MAXIMUM_F32: {
8660 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8661 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8662 .addImm(0) // src0_modifiers
8663 .add(Inst.getOperand(1))
8664 .addImm(0) // src1_modifiers
8665 .add(Inst.getOperand(2))
8666 .addImm(0) // clamp
8667 .addImm(0); // omod
8668 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8669
8670 legalizeOperands(*NewInstr, MDT);
8671 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8672 Inst.eraseFromParent();
8673 return;
8674 }
8675 case AMDGPU::S_MINIMUM_F16:
8676 case AMDGPU::S_MAXIMUM_F16: {
8677 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8678 ? &AMDGPU::VGPR_16RegClass
8679 : &AMDGPU::VGPR_32RegClass);
8680 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8681 .addImm(0) // src0_modifiers
8682 .add(Inst.getOperand(1))
8683 .addImm(0) // src1_modifiers
8684 .add(Inst.getOperand(2))
8685 .addImm(0) // clamp
8686 .addImm(0) // omod
8687 .addImm(0); // opsel0
8688 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8689 legalizeOperands(*NewInstr, MDT);
8690 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8691 Inst.eraseFromParent();
8692 return;
8693 }
8694 case AMDGPU::V_S_EXP_F16_e64:
8695 case AMDGPU::V_S_LOG_F16_e64:
8696 case AMDGPU::V_S_RCP_F16_e64:
8697 case AMDGPU::V_S_RSQ_F16_e64:
8698 case AMDGPU::V_S_SQRT_F16_e64: {
8699 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8700 ? &AMDGPU::VGPR_16RegClass
8701 : &AMDGPU::VGPR_32RegClass);
8702 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8703 .add(Inst.getOperand(1)) // src0_modifiers
8704 .add(Inst.getOperand(2))
8705 .add(Inst.getOperand(3)) // clamp
8706 .add(Inst.getOperand(4)) // omod
8707 .setMIFlags(Inst.getFlags());
8708 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8709 NewInstr.addImm(0); // opsel0
8710 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8711 legalizeOperands(*NewInstr, MDT);
8712 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8713 Inst.eraseFromParent();
8714 return;
8715 }
8716 }
8717
8718 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8719 // We cannot move this instruction to the VALU, so we should try to
8720 // legalize its operands instead.
8721 legalizeOperands(Inst, MDT);
8722 return;
8723 }
8724 // Handle converting generic instructions like COPY-to-SGPR into
8725 // COPY-to-VGPR.
8726 if (NewOpcode == Opcode) {
8727 Register DstReg = Inst.getOperand(0).getReg();
8728 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8729
8730 if (Inst.isCopy() && DstReg.isPhysical() &&
8731 Inst.getOperand(1).getReg().isVirtual()) {
8732 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8733 V2SPhyCopiesToErase);
8734 return;
8735 }
8736
8737 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8738 Register NewDstReg = Inst.getOperand(1).getReg();
8739 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8740 if (const TargetRegisterClass *CommonRC =
8741 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8742 // Instead of creating a copy where src and dst are the same register
8743 // class, we just replace all uses of dst with src. These kinds of
8744 // copies interfere with the heuristics MachineSink uses to decide
8745 // whether or not to split a critical edge. Since the pass assumes
8746 // that copies will end up as machine instructions and not be
8747 // eliminated.
8748 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8749 unsigned SrcSubReg = Inst.getOperand(1).getSubReg();
8750 bool IsUndef = Inst.getOperand(1).isUndef();
8751 for (MachineOperand &UseMO :
8752 make_early_inc_range(MRI.use_operands(DstReg))) {
8753 UseMO.setSubReg(
8754 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8755 UseMO.setReg(NewDstReg);
8756 if (IsUndef)
8757 UseMO.setIsUndef();
8758 }
8759 MRI.clearKillFlags(NewDstReg);
8760
8761 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8762 llvm_unreachable("failed to constrain register");
8763
8764 Inst.eraseFromParent();
8765
8766 for (MachineOperand &UseMO :
8767 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8768 MachineInstr &UseMI = *UseMO.getParent();
8769
8770 // Legalize t16 operands since replaceReg is called after
8771 // addUsersToVALU.
8773
8774 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
8775 if (const TargetRegisterClass *OpRC =
8776 getRegClass(UseMI.getDesc(), OpIdx))
8777 MRI.constrainRegClass(NewDstReg, OpRC);
8778 }
8779
8780 return;
8781 }
8782 }
8783
8784 // If this is a v2s copy between 16bit and 32bit reg,
8785 // replace vgpr copy to reg_sequence/extract_subreg
8786 // This can be remove after we have sgpr16 in place
8787 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
8788 Inst.getOperand(1).getReg().isVirtual() &&
8789 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
8790 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
8791 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8792 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8793 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8794 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8795 get(AMDGPU::IMPLICIT_DEF), Undef);
8796 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8797 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8798 .addReg(Inst.getOperand(1).getReg())
8799 .addImm(AMDGPU::lo16)
8800 .addReg(Undef)
8801 .addImm(AMDGPU::hi16);
8802 Inst.eraseFromParent();
8803 MRI.replaceRegWith(DstReg, NewDstReg);
8804 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8805 return;
8806 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8807 AMDGPU::lo16)) {
8808 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
8809 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8810 MRI.replaceRegWith(DstReg, NewDstReg);
8811 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8812 return;
8813 }
8814 }
8815
8816 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8817 MRI.replaceRegWith(DstReg, NewDstReg);
8818 legalizeOperands(Inst, MDT);
8819 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8820 return;
8821 }
8822
8823 // Use the new VALU Opcode.
8824 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
8825 .setMIFlags(Inst.getFlags());
8826 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
8827 // Intersperse VOP3 modifiers among the SALU operands.
8828 NewInstr->addOperand(Inst.getOperand(0));
8829 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8830 AMDGPU::OpName::src0_modifiers) >= 0)
8831 NewInstr.addImm(0);
8832 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
8833 const MachineOperand &Src = Inst.getOperand(1);
8834 NewInstr->addOperand(Src);
8835 }
8836
8837 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8838 // We are converting these to a BFE, so we need to add the missing
8839 // operands for the size and offset.
8840 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8841 NewInstr.addImm(0);
8842 NewInstr.addImm(Size);
8843 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8844 // The VALU version adds the second operand to the result, so insert an
8845 // extra 0 operand.
8846 NewInstr.addImm(0);
8847 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8848 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
8849 // If we need to move this to VGPRs, we need to unpack the second
8850 // operand back into the 2 separate ones for bit offset and width.
8851 assert(OffsetWidthOp.isImm() &&
8852 "Scalar BFE is only implemented for constant width and offset");
8853 uint32_t Imm = OffsetWidthOp.getImm();
8854
8855 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
8856 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
8857 NewInstr.addImm(Offset);
8858 NewInstr.addImm(BitWidth);
8859 } else {
8860 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8861 AMDGPU::OpName::src1_modifiers) >= 0)
8862 NewInstr.addImm(0);
8863 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8864 NewInstr->addOperand(Inst.getOperand(2));
8865 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8866 AMDGPU::OpName::src2_modifiers) >= 0)
8867 NewInstr.addImm(0);
8868 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8869 NewInstr->addOperand(Inst.getOperand(3));
8870 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8871 NewInstr.addImm(0);
8872 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8873 NewInstr.addImm(0);
8874 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8875 NewInstr.addImm(0);
8876 }
8877 } else {
8878 // Just copy the SALU operands.
8879 for (const MachineOperand &Op : Inst.explicit_operands())
8880 NewInstr->addOperand(Op);
8881 }
8882
8883 // Remove any references to SCC. Vector instructions can't read from it, and
8884 // We're just about to add the implicit use / defs of VCC, and we don't want
8885 // both.
8886 for (MachineOperand &Op : Inst.implicit_operands()) {
8887 if (Op.getReg() == AMDGPU::SCC) {
8888 // Only propagate through live-def of SCC.
8889 if (Op.isDef() && !Op.isDead())
8890 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
8891 if (Op.isUse())
8892 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8893 }
8894 }
8895 Inst.eraseFromParent();
8896 Register NewDstReg;
8897 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8898 Register DstReg = NewInstr->getOperand(0).getReg();
8899 assert(DstReg.isVirtual());
8900 // Update the destination register class.
8901 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
8902 assert(NewDstRC);
8903 NewDstReg = MRI.createVirtualRegister(NewDstRC);
8904 MRI.replaceRegWith(DstReg, NewDstReg);
8905 }
8906 fixImplicitOperands(*NewInstr);
8907
8908 // Legalize the operands
8909 legalizeOperands(*NewInstr, MDT);
8910 if (NewDstReg)
8911 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8912}
8913
8914// Add/sub require special handling to deal with carry outs.
8915std::pair<bool, MachineBasicBlock *>
8916SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
8917 MachineDominatorTree *MDT) const {
8918 if (ST.hasAddNoCarryInsts()) {
8919 // Assume there is no user of scc since we don't select this in that case.
8920 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
8921 // is used.
8922
8923 MachineBasicBlock &MBB = *Inst.getParent();
8924 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8925
8926 Register OldDstReg = Inst.getOperand(0).getReg();
8927 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8928
8929 unsigned Opc = Inst.getOpcode();
8930 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
8931
8932 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
8933 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8934
8935 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
8936 Inst.removeOperand(3);
8937
8938 Inst.setDesc(get(NewOpc));
8939 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
8940 Inst.addImplicitDefUseOperands(*MBB.getParent());
8941 MRI.replaceRegWith(OldDstReg, ResultReg);
8942 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
8943
8944 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8945 return std::pair(true, NewBB);
8946 }
8947
8948 return std::pair(false, nullptr);
8949}
8950
8951void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
8952 MachineDominatorTree *MDT) const {
8953
8954 MachineBasicBlock &MBB = *Inst.getParent();
8955 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8956 MachineBasicBlock::iterator MII = Inst;
8957 const DebugLoc &DL = Inst.getDebugLoc();
8958
8959 MachineOperand &Dest = Inst.getOperand(0);
8960 MachineOperand &Src0 = Inst.getOperand(1);
8961 MachineOperand &Src1 = Inst.getOperand(2);
8962 MachineOperand &Cond = Inst.getOperand(3);
8963
8964 Register CondReg = Cond.getReg();
8965 bool IsSCC = (CondReg == AMDGPU::SCC);
8966
8967 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
8968 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
8969 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
8970 // output directly into the V_CNDMASK.
8971 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
8972 (Src1.getImm() == 0)) {
8973 for (MachineOperand &UseMO :
8975 MachineInstr &UseMI = *UseMO.getParent();
8976 switch (UseMI.getOpcode()) {
8977 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8978 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8979 case AMDGPU::V_CNDMASK_B16_t16_e32:
8980 case AMDGPU::V_CNDMASK_B16_t16_e64:
8981 case AMDGPU::V_CNDMASK_B32_e32:
8982 case AMDGPU::V_CNDMASK_B32_e64:
8983 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8984 if (UseMO.isImplicit() ||
8985 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
8986 UseMO.setReg(CondReg);
8987 }
8988 }
8989 if (MRI.use_nodbg_empty(Dest.getReg()))
8990 return;
8991 }
8992
8993 Register NewCondReg = CondReg;
8994 if (IsSCC) {
8995 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
8996 NewCondReg = MRI.createVirtualRegister(TC);
8997
8998 // Now look for the closest SCC def if it is a copy
8999 // replacing the CondReg with the COPY source register
9000 bool CopyFound = false;
9001 for (MachineInstr &CandI :
9003 Inst.getParent()->rend())) {
9004 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
9005 -1) {
9006 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9007 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
9008 .addReg(CandI.getOperand(1).getReg());
9009 CopyFound = true;
9010 }
9011 break;
9012 }
9013 }
9014 if (!CopyFound) {
9015 // SCC def is not a copy
9016 // Insert a trivial select instead of creating a copy, because a copy from
9017 // SCC would semantically mean just copying a single bit, but we may need
9018 // the result to be a vector condition mask that needs preserving.
9019 unsigned Opcode =
9020 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9021 auto NewSelect =
9022 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
9023 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
9024 }
9025 }
9026
9027 Register NewDestReg = MRI.createVirtualRegister(
9028 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
9029 MachineInstr *NewInst;
9030 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
9031 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9032 .addImm(0)
9033 .add(Src1) // False
9034 .addImm(0)
9035 .add(Src0) // True
9036 .addReg(NewCondReg);
9037 } else {
9038 NewInst =
9039 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
9040 .add(Src1) // False
9041 .add(Src0) // True
9042 .addReg(NewCondReg);
9043 }
9044 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
9045 legalizeOperands(*NewInst, MDT);
9046 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9047}
9048
9049void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
9050 MachineInstr &Inst) const {
9051 MachineBasicBlock &MBB = *Inst.getParent();
9052 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9053 MachineBasicBlock::iterator MII = Inst;
9054 const DebugLoc &DL = Inst.getDebugLoc();
9055
9056 MachineOperand &Dest = Inst.getOperand(0);
9057 MachineOperand &Src = Inst.getOperand(1);
9058 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9059 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9060
9061 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9062 : AMDGPU::V_SUB_CO_U32_e32;
9063
9064 BuildMI(MBB, MII, DL, get(SubOp), TmpReg)
9065 .addImm(0)
9066 .addReg(Src.getReg());
9067
9068 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9069 .addReg(Src.getReg())
9070 .addReg(TmpReg);
9071
9072 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9073 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9074}
9075
9076void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
9077 MachineInstr &Inst) const {
9078 MachineBasicBlock &MBB = *Inst.getParent();
9079 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9080 MachineBasicBlock::iterator MII = Inst;
9081 const DebugLoc &DL = Inst.getDebugLoc();
9082
9083 MachineOperand &Dest = Inst.getOperand(0);
9084 MachineOperand &Src1 = Inst.getOperand(1);
9085 MachineOperand &Src2 = Inst.getOperand(2);
9086 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9087 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9088 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9089
9090 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9091 : AMDGPU::V_SUB_CO_U32_e32;
9092
9093 BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
9094 .addReg(Src1.getReg())
9095 .addReg(Src2.getReg());
9096
9097 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
9098
9099 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9100 .addReg(SubResultReg)
9101 .addReg(TmpReg);
9102
9103 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9104 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9105}
9106
9107void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
9108 MachineInstr &Inst) const {
9109 MachineBasicBlock &MBB = *Inst.getParent();
9110 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9111 MachineBasicBlock::iterator MII = Inst;
9112 const DebugLoc &DL = Inst.getDebugLoc();
9113
9114 MachineOperand &Dest = Inst.getOperand(0);
9115 MachineOperand &Src0 = Inst.getOperand(1);
9116 MachineOperand &Src1 = Inst.getOperand(2);
9117
9118 if (ST.hasDLInsts()) {
9119 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9120 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
9121 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
9122
9123 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
9124 .add(Src0)
9125 .add(Src1);
9126
9127 MRI.replaceRegWith(Dest.getReg(), NewDest);
9128 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9129 } else {
9130 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
9131 // invert either source and then perform the XOR. If either source is a
9132 // scalar register, then we can leave the inversion on the scalar unit to
9133 // achieve a better distribution of scalar and vector instructions.
9134 bool Src0IsSGPR = Src0.isReg() &&
9135 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
9136 bool Src1IsSGPR = Src1.isReg() &&
9137 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
9138 MachineInstr *Xor;
9139 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9140 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9141
9142 // Build a pair of scalar instructions and add them to the work list.
9143 // The next iteration over the work list will lower these to the vector
9144 // unit as necessary.
9145 if (Src0IsSGPR) {
9146 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
9147 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9148 .addReg(Temp)
9149 .add(Src1);
9150 } else if (Src1IsSGPR) {
9151 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
9152 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9153 .add(Src0)
9154 .addReg(Temp);
9155 } else {
9156 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
9157 .add(Src0)
9158 .add(Src1);
9159 MachineInstr *Not =
9160 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
9161 Worklist.insert(Not);
9162 }
9163
9164 MRI.replaceRegWith(Dest.getReg(), NewDest);
9165
9166 Worklist.insert(Xor);
9167
9168 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9169 }
9170}
9171
9172void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
9173 MachineInstr &Inst,
9174 unsigned Opcode) const {
9175 MachineBasicBlock &MBB = *Inst.getParent();
9176 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9177 MachineBasicBlock::iterator MII = Inst;
9178 const DebugLoc &DL = Inst.getDebugLoc();
9179
9180 MachineOperand &Dest = Inst.getOperand(0);
9181 MachineOperand &Src0 = Inst.getOperand(1);
9182 MachineOperand &Src1 = Inst.getOperand(2);
9183
9184 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9185 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9186
9187 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
9188 .add(Src0)
9189 .add(Src1);
9190
9191 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
9192 .addReg(Interm);
9193
9194 Worklist.insert(&Op);
9195 Worklist.insert(&Not);
9196
9197 MRI.replaceRegWith(Dest.getReg(), NewDest);
9198 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9199}
9200
9201void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
9202 MachineInstr &Inst,
9203 unsigned Opcode) const {
9204 MachineBasicBlock &MBB = *Inst.getParent();
9205 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9206 MachineBasicBlock::iterator MII = Inst;
9207 const DebugLoc &DL = Inst.getDebugLoc();
9208
9209 MachineOperand &Dest = Inst.getOperand(0);
9210 MachineOperand &Src0 = Inst.getOperand(1);
9211 MachineOperand &Src1 = Inst.getOperand(2);
9212
9213 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9214 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9215
9216 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
9217 .add(Src1);
9218
9219 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
9220 .add(Src0)
9221 .addReg(Interm);
9222
9223 Worklist.insert(&Not);
9224 Worklist.insert(&Op);
9225
9226 MRI.replaceRegWith(Dest.getReg(), NewDest);
9227 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9228}
9229
9230void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
9231 MachineInstr &Inst, unsigned Opcode,
9232 bool Swap) const {
9233 MachineBasicBlock &MBB = *Inst.getParent();
9234 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9235
9236 MachineOperand &Dest = Inst.getOperand(0);
9237 MachineOperand &Src0 = Inst.getOperand(1);
9238 const DebugLoc &DL = Inst.getDebugLoc();
9239
9240 MachineBasicBlock::iterator MII = Inst;
9241
9242 const MCInstrDesc &InstDesc = get(Opcode);
9243 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9244 MRI.getRegClass(Src0.getReg()) :
9245 &AMDGPU::SGPR_32RegClass;
9246
9247 const TargetRegisterClass *Src0SubRC =
9248 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9249
9250 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9251 AMDGPU::sub0, Src0SubRC);
9252
9253 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9254 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9255 const TargetRegisterClass *NewDestSubRC =
9256 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9257
9258 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9259 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
9260
9261 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9262 AMDGPU::sub1, Src0SubRC);
9263
9264 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9265 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
9266
9267 if (Swap)
9268 std::swap(DestSub0, DestSub1);
9269
9270 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9271 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9272 .addReg(DestSub0)
9273 .addImm(AMDGPU::sub0)
9274 .addReg(DestSub1)
9275 .addImm(AMDGPU::sub1);
9276
9277 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9278
9279 Worklist.insert(&LoHalf);
9280 Worklist.insert(&HiHalf);
9281
9282 // We don't need to legalizeOperands here because for a single operand, src0
9283 // will support any kind of input.
9284
9285 // Move all users of this moved value.
9286 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9287}
9288
9289// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9290// split the s_mul_u64 in 32-bit vector multiplications.
9291void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9292 MachineInstr &Inst,
9293 MachineDominatorTree *MDT) const {
9294 MachineBasicBlock &MBB = *Inst.getParent();
9295 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9296
9297 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9298 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9299 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9300
9301 MachineOperand &Dest = Inst.getOperand(0);
9302 MachineOperand &Src0 = Inst.getOperand(1);
9303 MachineOperand &Src1 = Inst.getOperand(2);
9304 const DebugLoc &DL = Inst.getDebugLoc();
9305 MachineBasicBlock::iterator MII = Inst;
9306
9307 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9308 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9309 const TargetRegisterClass *Src0SubRC =
9310 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9311 if (RI.isSGPRClass(Src0SubRC))
9312 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9313 const TargetRegisterClass *Src1SubRC =
9314 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9315 if (RI.isSGPRClass(Src1SubRC))
9316 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9317
9318 // First, we extract the low 32-bit and high 32-bit values from each of the
9319 // operands.
9320 MachineOperand Op0L =
9321 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9322 MachineOperand Op1L =
9323 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9324 MachineOperand Op0H =
9325 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9326 MachineOperand Op1H =
9327 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9328
9329 // The multilication is done as follows:
9330 //
9331 // Op1H Op1L
9332 // * Op0H Op0L
9333 // --------------------
9334 // Op1H*Op0L Op1L*Op0L
9335 // + Op1H*Op0H Op1L*Op0H
9336 // -----------------------------------------
9337 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9338 //
9339 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9340 // value and that would overflow.
9341 // The low 32-bit value is Op1L*Op0L.
9342 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9343
9344 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9345 MachineInstr *Op1L_Op0H =
9346 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9347 .add(Op1L)
9348 .add(Op0H);
9349
9350 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9351 MachineInstr *Op1H_Op0L =
9352 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9353 .add(Op1H)
9354 .add(Op0L);
9355
9356 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9357 MachineInstr *Carry =
9358 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9359 .add(Op1L)
9360 .add(Op0L);
9361
9362 MachineInstr *LoHalf =
9363 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9364 .add(Op1L)
9365 .add(Op0L);
9366
9367 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9368 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9369 .addReg(Op1L_Op0H_Reg)
9370 .addReg(Op1H_Op0L_Reg);
9371
9372 MachineInstr *HiHalf =
9373 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9374 .addReg(AddReg)
9375 .addReg(CarryReg);
9376
9377 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9378 .addReg(DestSub0)
9379 .addImm(AMDGPU::sub0)
9380 .addReg(DestSub1)
9381 .addImm(AMDGPU::sub1);
9382
9383 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9384
9385 // Try to legalize the operands in case we need to swap the order to keep it
9386 // valid.
9387 legalizeOperands(*Op1L_Op0H, MDT);
9388 legalizeOperands(*Op1H_Op0L, MDT);
9389 legalizeOperands(*Carry, MDT);
9390 legalizeOperands(*LoHalf, MDT);
9391 legalizeOperands(*Add, MDT);
9392 legalizeOperands(*HiHalf, MDT);
9393
9394 // Move all users of this moved value.
9395 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9396}
9397
9398// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9399// multiplications.
9400void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9401 MachineInstr &Inst,
9402 MachineDominatorTree *MDT) const {
9403 MachineBasicBlock &MBB = *Inst.getParent();
9404 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9405
9406 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9407 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9408 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9409
9410 MachineOperand &Dest = Inst.getOperand(0);
9411 MachineOperand &Src0 = Inst.getOperand(1);
9412 MachineOperand &Src1 = Inst.getOperand(2);
9413 const DebugLoc &DL = Inst.getDebugLoc();
9414 MachineBasicBlock::iterator MII = Inst;
9415
9416 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9417 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9418 const TargetRegisterClass *Src0SubRC =
9419 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9420 if (RI.isSGPRClass(Src0SubRC))
9421 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9422 const TargetRegisterClass *Src1SubRC =
9423 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9424 if (RI.isSGPRClass(Src1SubRC))
9425 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9426
9427 // First, we extract the low 32-bit and high 32-bit values from each of the
9428 // operands.
9429 MachineOperand Op0L =
9430 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9431 MachineOperand Op1L =
9432 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9433
9434 unsigned Opc = Inst.getOpcode();
9435 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9436 ? AMDGPU::V_MUL_HI_U32_e64
9437 : AMDGPU::V_MUL_HI_I32_e64;
9438 MachineInstr *HiHalf =
9439 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9440
9441 MachineInstr *LoHalf =
9442 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9443 .add(Op1L)
9444 .add(Op0L);
9445
9446 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9447 .addReg(DestSub0)
9448 .addImm(AMDGPU::sub0)
9449 .addReg(DestSub1)
9450 .addImm(AMDGPU::sub1);
9451
9452 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9453
9454 // Try to legalize the operands in case we need to swap the order to keep it
9455 // valid.
9456 legalizeOperands(*HiHalf, MDT);
9457 legalizeOperands(*LoHalf, MDT);
9458
9459 // Move all users of this moved value.
9460 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9461}
9462
9463void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9464 MachineInstr &Inst, unsigned Opcode,
9465 MachineDominatorTree *MDT) const {
9466 MachineBasicBlock &MBB = *Inst.getParent();
9467 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9468
9469 MachineOperand &Dest = Inst.getOperand(0);
9470 MachineOperand &Src0 = Inst.getOperand(1);
9471 MachineOperand &Src1 = Inst.getOperand(2);
9472 const DebugLoc &DL = Inst.getDebugLoc();
9473
9474 MachineBasicBlock::iterator MII = Inst;
9475
9476 const MCInstrDesc &InstDesc = get(Opcode);
9477 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9478 MRI.getRegClass(Src0.getReg()) :
9479 &AMDGPU::SGPR_32RegClass;
9480
9481 const TargetRegisterClass *Src0SubRC =
9482 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9483 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9484 MRI.getRegClass(Src1.getReg()) :
9485 &AMDGPU::SGPR_32RegClass;
9486
9487 const TargetRegisterClass *Src1SubRC =
9488 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9489
9490 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9491 AMDGPU::sub0, Src0SubRC);
9492 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9493 AMDGPU::sub0, Src1SubRC);
9494 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9495 AMDGPU::sub1, Src0SubRC);
9496 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9497 AMDGPU::sub1, Src1SubRC);
9498
9499 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9500 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9501 const TargetRegisterClass *NewDestSubRC =
9502 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9503
9504 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9505 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9506 .add(SrcReg0Sub0)
9507 .add(SrcReg1Sub0);
9508
9509 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9510 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9511 .add(SrcReg0Sub1)
9512 .add(SrcReg1Sub1);
9513
9514 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9515 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9516 .addReg(DestSub0)
9517 .addImm(AMDGPU::sub0)
9518 .addReg(DestSub1)
9519 .addImm(AMDGPU::sub1);
9520
9521 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9522
9523 Worklist.insert(&LoHalf);
9524 Worklist.insert(&HiHalf);
9525
9526 // Move all users of this moved value.
9527 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9528}
9529
9530void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9531 MachineInstr &Inst,
9532 MachineDominatorTree *MDT) const {
9533 MachineBasicBlock &MBB = *Inst.getParent();
9534 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9535
9536 MachineOperand &Dest = Inst.getOperand(0);
9537 MachineOperand &Src0 = Inst.getOperand(1);
9538 MachineOperand &Src1 = Inst.getOperand(2);
9539 const DebugLoc &DL = Inst.getDebugLoc();
9540
9541 MachineBasicBlock::iterator MII = Inst;
9542
9543 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9544
9545 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9546
9547 MachineOperand* Op0;
9548 MachineOperand* Op1;
9549
9550 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9551 Op0 = &Src0;
9552 Op1 = &Src1;
9553 } else {
9554 Op0 = &Src1;
9555 Op1 = &Src0;
9556 }
9557
9558 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9559 .add(*Op0);
9560
9561 Register NewDest = MRI.createVirtualRegister(DestRC);
9562
9563 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9564 .addReg(Interm)
9565 .add(*Op1);
9566
9567 MRI.replaceRegWith(Dest.getReg(), NewDest);
9568
9569 Worklist.insert(&Xor);
9570}
9571
9572void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9573 MachineInstr &Inst) const {
9574 MachineBasicBlock &MBB = *Inst.getParent();
9575 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9576
9577 MachineBasicBlock::iterator MII = Inst;
9578 const DebugLoc &DL = Inst.getDebugLoc();
9579
9580 MachineOperand &Dest = Inst.getOperand(0);
9581 MachineOperand &Src = Inst.getOperand(1);
9582
9583 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9584 const TargetRegisterClass *SrcRC = Src.isReg() ?
9585 MRI.getRegClass(Src.getReg()) :
9586 &AMDGPU::SGPR_32RegClass;
9587
9588 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9589 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9590
9591 const TargetRegisterClass *SrcSubRC =
9592 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9593
9594 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9595 AMDGPU::sub0, SrcSubRC);
9596 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9597 AMDGPU::sub1, SrcSubRC);
9598
9599 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9600
9601 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9602
9603 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9604
9605 // We don't need to legalize operands here. src0 for either instruction can be
9606 // an SGPR, and the second input is unused or determined here.
9607 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9608}
9609
9610void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9611 MachineInstr &Inst) const {
9612 MachineBasicBlock &MBB = *Inst.getParent();
9613 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9614 MachineBasicBlock::iterator MII = Inst;
9615 const DebugLoc &DL = Inst.getDebugLoc();
9616
9617 MachineOperand &Dest = Inst.getOperand(0);
9618 uint32_t Imm = Inst.getOperand(2).getImm();
9619 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9620 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9621
9622 (void) Offset;
9623
9624 // Only sext_inreg cases handled.
9625 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9626 Offset == 0 && "Not implemented");
9627
9628 if (BitWidth < 32) {
9629 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9630 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9631 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9632
9633 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9634 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9635 .addImm(0)
9636 .addImm(BitWidth);
9637
9638 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9639 .addImm(31)
9640 .addReg(MidRegLo);
9641
9642 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9643 .addReg(MidRegLo)
9644 .addImm(AMDGPU::sub0)
9645 .addReg(MidRegHi)
9646 .addImm(AMDGPU::sub1);
9647
9648 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9649 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9650 return;
9651 }
9652
9653 MachineOperand &Src = Inst.getOperand(1);
9654 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9655 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9656
9657 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9658 .addImm(31)
9659 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9660
9661 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9662 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9663 .addImm(AMDGPU::sub0)
9664 .addReg(TmpReg)
9665 .addImm(AMDGPU::sub1);
9666
9667 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9668 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9669}
9670
9671void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9672 MachineInstr &Inst, unsigned Opcode,
9673 MachineDominatorTree *MDT) const {
9674 // (S_FLBIT_I32_B64 hi:lo) ->
9675 // -> (umin (V_FFBH_U32_e32 hi), (or (V_FFBH_U32_e32 lo), 32))
9676 // (S_FF1_I32_B64 hi:lo) ->
9677 // ->(umin (or (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9678
9679 MachineBasicBlock &MBB = *Inst.getParent();
9680 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9681 MachineBasicBlock::iterator MII = Inst;
9682 const DebugLoc &DL = Inst.getDebugLoc();
9683
9684 MachineOperand &Dest = Inst.getOperand(0);
9685 MachineOperand &Src = Inst.getOperand(1);
9686
9687 const MCInstrDesc &InstDesc = get(Opcode);
9688
9689 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9690
9691 const TargetRegisterClass *SrcRC =
9692 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9693 const TargetRegisterClass *SrcSubRC =
9694 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9695
9696 MachineOperand SrcRegSub0 =
9697 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9698 MachineOperand SrcRegSub1 =
9699 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9700
9701 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9702 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9703 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9704 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9705
9706 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9707
9708 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9709
9710 BuildMI(MBB, MII, DL, get(AMDGPU::V_OR_B32_e32), MidReg3)
9711 .addImm(32)
9712 .addReg(IsCtlz ? MidReg1 : MidReg2);
9713
9714 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9715 .addReg(MidReg3)
9716 .addReg(IsCtlz ? MidReg2 : MidReg1);
9717
9718 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9719
9720 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9721}
9722
9723void SIInstrInfo::addUsersToMoveToVALUWorklist(
9724 Register DstReg, MachineRegisterInfo &MRI,
9725 SIInstrWorklist &Worklist) const {
9726 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9727 MachineInstr &UseMI = *MO.getParent();
9728
9729 unsigned OpNo = 0;
9730
9731 switch (UseMI.getOpcode()) {
9732 case AMDGPU::COPY:
9733 case AMDGPU::WQM:
9734 case AMDGPU::SOFT_WQM:
9735 case AMDGPU::STRICT_WWM:
9736 case AMDGPU::STRICT_WQM:
9737 case AMDGPU::REG_SEQUENCE:
9738 case AMDGPU::PHI:
9739 case AMDGPU::INSERT_SUBREG:
9740 break;
9741 default:
9742 OpNo = MO.getOperandNo();
9743 break;
9744 }
9745
9746 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9747 MRI.constrainRegClass(DstReg, OpRC);
9748
9749 if (!RI.hasVectorRegisters(OpRC))
9750 Worklist.insert(&UseMI);
9751 else
9752 // Legalization could change user list.
9753 legalizeOperandsVALUt16(UseMI, OpNo, MRI);
9754 }
9755}
9756
9757void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
9759 MachineInstr &Inst) const {
9760 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9761 MachineBasicBlock *MBB = Inst.getParent();
9762 MachineOperand &Src0 = Inst.getOperand(1);
9763 MachineOperand &Src1 = Inst.getOperand(2);
9764 const DebugLoc &DL = Inst.getDebugLoc();
9765
9766 if (ST.useRealTrue16Insts()) {
9767 Register SrcReg0, SrcReg1;
9768 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
9769 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9770 BuildMI(*MBB, Inst, DL,
9771 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9772 .add(Src0);
9773 } else {
9774 SrcReg0 = Src0.getReg();
9775 }
9776
9777 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
9778 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9779 BuildMI(*MBB, Inst, DL,
9780 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9781 .add(Src1);
9782 } else {
9783 SrcReg1 = Src1.getReg();
9784 }
9785
9786 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
9787 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
9788
9789 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
9790 switch (Inst.getOpcode()) {
9791 case AMDGPU::S_PACK_LL_B32_B16:
9792 NewMI
9793 .addReg(SrcReg0, {},
9794 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9795 .addImm(AMDGPU::lo16)
9796 .addReg(SrcReg1, {},
9797 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9798 .addImm(AMDGPU::hi16);
9799 break;
9800 case AMDGPU::S_PACK_LH_B32_B16:
9801 NewMI
9802 .addReg(SrcReg0, {},
9803 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9804 .addImm(AMDGPU::lo16)
9805 .addReg(SrcReg1, {}, AMDGPU::hi16)
9806 .addImm(AMDGPU::hi16);
9807 break;
9808 case AMDGPU::S_PACK_HL_B32_B16:
9809 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9810 .addImm(AMDGPU::lo16)
9811 .addReg(SrcReg1, {},
9812 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9813 .addImm(AMDGPU::hi16);
9814 break;
9815 case AMDGPU::S_PACK_HH_B32_B16:
9816 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9817 .addImm(AMDGPU::lo16)
9818 .addReg(SrcReg1, {}, AMDGPU::hi16)
9819 .addImm(AMDGPU::hi16);
9820 break;
9821 default:
9822 llvm_unreachable("unhandled s_pack_* instruction");
9823 }
9824
9825 MachineOperand &Dest = Inst.getOperand(0);
9826 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9827 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9828 return;
9829 }
9830
9831 switch (Inst.getOpcode()) {
9832 case AMDGPU::S_PACK_LL_B32_B16: {
9833 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9834 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9835
9836 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
9837 // 0.
9838 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9839 .addImm(0xffff);
9840
9841 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
9842 .addReg(ImmReg, RegState::Kill)
9843 .add(Src0);
9844
9845 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9846 .add(Src1)
9847 .addImm(16)
9848 .addReg(TmpReg, RegState::Kill);
9849 break;
9850 }
9851 case AMDGPU::S_PACK_LH_B32_B16: {
9852 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9853 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9854 .addImm(0xffff);
9855 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
9856 .addReg(ImmReg, RegState::Kill)
9857 .add(Src0)
9858 .add(Src1);
9859 break;
9860 }
9861 case AMDGPU::S_PACK_HL_B32_B16: {
9862 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9863 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9864 .addImm(16)
9865 .add(Src0);
9866 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9867 .add(Src1)
9868 .addImm(16)
9869 .addReg(TmpReg, RegState::Kill);
9870 break;
9871 }
9872 case AMDGPU::S_PACK_HH_B32_B16: {
9873 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9874 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9875 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9876 .addImm(16)
9877 .add(Src0);
9878 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9879 .addImm(0xffff0000);
9880 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
9881 .add(Src1)
9882 .addReg(ImmReg, RegState::Kill)
9883 .addReg(TmpReg, RegState::Kill);
9884 break;
9885 }
9886 default:
9887 llvm_unreachable("unhandled s_pack_* instruction");
9888 }
9889
9890 MachineOperand &Dest = Inst.getOperand(0);
9891 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9892 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9893}
9894
9895void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
9896 MachineInstr &SCCDefInst,
9897 SIInstrWorklist &Worklist,
9898 Register NewCond) const {
9899
9900 // Ensure that def inst defines SCC, which is still live.
9901 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
9902 !Op.isDead() && Op.getParent() == &SCCDefInst);
9903 SmallVector<MachineInstr *, 4> CopyToDelete;
9904 // This assumes that all the users of SCC are in the same block
9905 // as the SCC def.
9906 for (MachineInstr &MI : // Skip the def inst itself.
9907 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
9908 SCCDefInst.getParent()->end())) {
9909 // Check if SCC is used first.
9910 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
9911 if (SCCIdx != -1) {
9912 if (MI.isCopy()) {
9913 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
9914 Register DestReg = MI.getOperand(0).getReg();
9915
9916 MRI.replaceRegWith(DestReg, NewCond);
9917 CopyToDelete.push_back(&MI);
9918 } else {
9919
9920 if (NewCond.isValid())
9921 MI.getOperand(SCCIdx).setReg(NewCond);
9922
9923 Worklist.insert(&MI);
9924 }
9925 }
9926 // Exit if we find another SCC def.
9927 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
9928 break;
9929 }
9930 for (auto &Copy : CopyToDelete)
9931 Copy->eraseFromParent();
9932}
9933
9934// Instructions that use SCC may be converted to VALU instructions. When that
9935// happens, the SCC register is changed to VCC_LO. The instruction that defines
9936// SCC must be changed to an instruction that defines VCC. This function makes
9937// sure that the instruction that defines SCC is added to the moveToVALU
9938// worklist.
9939void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
9940 SIInstrWorklist &Worklist) const {
9941 // Look for a preceding instruction that either defines VCC or SCC. If VCC
9942 // then there is nothing to do because the defining instruction has been
9943 // converted to a VALU already. If SCC then that instruction needs to be
9944 // converted to a VALU.
9945 for (MachineInstr &MI :
9946 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
9947 SCCUseInst->getParent()->rend())) {
9948 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
9949 break;
9950 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
9951 Worklist.insert(&MI);
9952 break;
9953 }
9954 }
9955}
9956
9957const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
9958 const MachineInstr &Inst) const {
9959 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
9960
9961 switch (Inst.getOpcode()) {
9962 // For target instructions, getOpRegClass just returns the virtual register
9963 // class associated with the operand, so we need to find an equivalent VGPR
9964 // register class in order to move the instruction to the VALU.
9965 case AMDGPU::COPY:
9966 case AMDGPU::PHI:
9967 case AMDGPU::REG_SEQUENCE:
9968 case AMDGPU::INSERT_SUBREG:
9969 case AMDGPU::WQM:
9970 case AMDGPU::SOFT_WQM:
9971 case AMDGPU::STRICT_WWM:
9972 case AMDGPU::STRICT_WQM: {
9973 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
9974 if (RI.isAGPRClass(SrcRC)) {
9975 if (RI.isAGPRClass(NewDstRC))
9976 return nullptr;
9977
9978 switch (Inst.getOpcode()) {
9979 case AMDGPU::PHI:
9980 case AMDGPU::REG_SEQUENCE:
9981 case AMDGPU::INSERT_SUBREG:
9982 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9983 break;
9984 default:
9985 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9986 }
9987
9988 if (!NewDstRC)
9989 return nullptr;
9990 } else {
9991 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9992 return nullptr;
9993
9994 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9995 if (!NewDstRC)
9996 return nullptr;
9997 }
9998
9999 return NewDstRC;
10000 }
10001 default:
10002 return NewDstRC;
10003 }
10004}
10005
10006// Find the one SGPR operand we are allowed to use.
10007Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
10008 int OpIndices[3]) const {
10009 const MCInstrDesc &Desc = MI.getDesc();
10010
10011 // Find the one SGPR operand we are allowed to use.
10012 //
10013 // First we need to consider the instruction's operand requirements before
10014 // legalizing. Some operands are required to be SGPRs, such as implicit uses
10015 // of VCC, but we are still bound by the constant bus requirement to only use
10016 // one.
10017 //
10018 // If the operand's class is an SGPR, we can never move it.
10019
10020 Register SGPRReg = findImplicitSGPRRead(MI);
10021 if (SGPRReg)
10022 return SGPRReg;
10023
10024 Register UsedSGPRs[3] = {Register()};
10025 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10026
10027 for (unsigned i = 0; i < 3; ++i) {
10028 int Idx = OpIndices[i];
10029 if (Idx == -1)
10030 break;
10031
10032 const MachineOperand &MO = MI.getOperand(Idx);
10033 if (!MO.isReg())
10034 continue;
10035
10036 // Is this operand statically required to be an SGPR based on the operand
10037 // constraints?
10038 const TargetRegisterClass *OpRC =
10039 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
10040 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10041 if (IsRequiredSGPR)
10042 return MO.getReg();
10043
10044 // If this could be a VGPR or an SGPR, Check the dynamic register class.
10045 Register Reg = MO.getReg();
10046 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
10047 if (RI.isSGPRClass(RegRC))
10048 UsedSGPRs[i] = Reg;
10049 }
10050
10051 // We don't have a required SGPR operand, so we have a bit more freedom in
10052 // selecting operands to move.
10053
10054 // Try to select the most used SGPR. If an SGPR is equal to one of the
10055 // others, we choose that.
10056 //
10057 // e.g.
10058 // V_FMA_F32 v0, s0, s0, s0 -> No moves
10059 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
10060
10061 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
10062 // prefer those.
10063
10064 if (UsedSGPRs[0]) {
10065 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10066 SGPRReg = UsedSGPRs[0];
10067 }
10068
10069 if (!SGPRReg && UsedSGPRs[1]) {
10070 if (UsedSGPRs[1] == UsedSGPRs[2])
10071 SGPRReg = UsedSGPRs[1];
10072 }
10073
10074 return SGPRReg;
10075}
10076
10078 AMDGPU::OpName OperandName) const {
10079 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10080 return nullptr;
10081
10082 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
10083 if (Idx == -1)
10084 return nullptr;
10085
10086 return &MI.getOperand(Idx);
10087}
10088
10090 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
10091 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
10094 return (Format << 44) |
10095 (1ULL << 56) | // RESOURCE_LEVEL = 1
10096 (3ULL << 60); // OOB_SELECT = 3
10097 }
10098
10099 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
10100 if (ST.isAmdHsaOS()) {
10101 // Set ATC = 1. GFX9 doesn't have this bit.
10102 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10103 RsrcDataFormat |= (1ULL << 56);
10104
10105 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
10106 // BTW, it disables TC L2 and therefore decreases performance.
10107 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
10108 RsrcDataFormat |= (2ULL << 59);
10109 }
10110
10111 return RsrcDataFormat;
10112}
10113
10115 uint64_t Rsrc23 = getDefaultRsrcDataFormat() |
10117 0xffffffff; // Size;
10118
10119 // GFX9 doesn't have ELEMENT_SIZE.
10120 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
10121 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
10122 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
10123 }
10124
10125 // IndexStride = 64 / 32.
10126 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10127 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
10128
10129 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
10130 // Clear them unless we want a huge stride.
10131 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
10132 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
10133 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
10134
10135 return Rsrc23;
10136}
10137
10139 unsigned Opc = MI.getOpcode();
10140
10141 return isSMRD(Opc);
10142}
10143
10145 return get(Opc).mayLoad() &&
10146 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
10147}
10148
10150 TypeSize &MemBytes) const {
10151 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
10152 if (!Addr || !Addr->isFI())
10153 return Register();
10154
10155 assert(!MI.memoperands_empty() &&
10156 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
10157
10158 FrameIndex = Addr->getIndex();
10159
10160 int VDataIdx =
10161 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
10162 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
10163 return MI.getOperand(VDataIdx).getReg();
10164}
10165
10167 TypeSize &MemBytes) const {
10168 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
10169 assert(Addr && Addr->isFI());
10170 FrameIndex = Addr->getIndex();
10171
10172 int DataIdx =
10173 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
10174 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
10175 return MI.getOperand(DataIdx).getReg();
10176}
10177
10179 int &FrameIndex,
10180 TypeSize &MemBytes) const {
10181 if (!MI.mayLoad())
10182 return Register();
10183
10184 if (isMUBUF(MI) || isVGPRSpill(MI))
10185 return isStackAccess(MI, FrameIndex, MemBytes);
10186
10187 if (isSGPRSpill(MI))
10188 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10189
10190 return Register();
10191}
10192
10194 int &FrameIndex,
10195 TypeSize &MemBytes) const {
10196 if (!MI.mayStore())
10197 return Register();
10198
10199 if (isMUBUF(MI) || isVGPRSpill(MI))
10200 return isStackAccess(MI, FrameIndex, MemBytes);
10201
10202 if (isSGPRSpill(MI))
10203 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10204
10205 return Register();
10206}
10207
10209 unsigned Opc = MI.getOpcode();
10211 unsigned DescSize = Desc.getSize();
10212
10213 // If we have a definitive size, we can use it. Otherwise we need to inspect
10214 // the operands to know the size.
10215 if (isFixedSize(MI)) {
10216 unsigned Size = DescSize;
10217
10218 // If we hit the buggy offset, an extra nop will be inserted in MC so
10219 // estimate the worst case.
10220 if (MI.isBranch() && ST.hasOffset3fBug())
10221 Size += 4;
10222
10223 return Size;
10224 }
10225
10226 // Instructions may have a 32-bit literal encoded after them. Check
10227 // operands that could ever be literals.
10228 if (isVALU(MI, /*AllowLDSDMA=*/true) || isSALU(MI)) {
10229 if (isDPP(MI))
10230 return DescSize;
10231 bool HasLiteral = false;
10232 unsigned LiteralSize = 4;
10233 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
10234 const MachineOperand &Op = MI.getOperand(I);
10235 const MCOperandInfo &OpInfo = Desc.operands()[I];
10236 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
10237 HasLiteral = true;
10238 if (ST.has64BitLiterals()) {
10239 switch (OpInfo.OperandType) {
10240 default:
10241 break;
10244 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
10245 LiteralSize = 8;
10246 break;
10249 // A 32-bit literal is only valid when the value fits in BOTH signed
10250 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
10251 // emitter's getLit64Encoding logic. This is because of the lack of
10252 // abilility to tell signedness of the literal, therefore we need to
10253 // be conservative and assume values outside this range require a
10254 // 64-bit literal encoding (8 bytes).
10255 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
10256 !isUInt<32>(Op.getImm()))
10257 LiteralSize = 8;
10258 break;
10259 }
10260 }
10261 break;
10262 }
10263 }
10264 return HasLiteral ? DescSize + LiteralSize : DescSize;
10265 }
10266
10267 // Check whether we have extra NSA words.
10268 if (isMIMG(MI)) {
10269 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
10270 if (VAddr0Idx < 0)
10271 return 8;
10272
10273 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
10274 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10275 }
10276
10277 switch (Opc) {
10278 case TargetOpcode::BUNDLE:
10279 return getInstBundleSize(MI);
10280 case TargetOpcode::INLINEASM:
10281 case TargetOpcode::INLINEASM_BR: {
10282 const MachineFunction *MF = MI.getMF();
10283 const char *AsmStr = MI.getOperand(0).getSymbolName();
10284 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10285 }
10286 default:
10287 if (MI.isMetaInstruction())
10288 return 0;
10289
10290 // If D16 Pseudo inst, get correct MC code size
10291 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10292 if (D16Info) {
10293 // Assume d16_lo/hi inst are always in same size
10294 unsigned LoInstOpcode = D16Info->LoOp;
10295 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10296 DescSize = Desc.getSize();
10297 }
10298
10299 // If FMA Pseudo inst, get correct MC code size
10300 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10301 // All potential lowerings are the same size; arbitrarily pick one.
10302 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10303 DescSize = Desc.getSize();
10304 }
10305
10306 return DescSize;
10307 }
10308}
10309
10312 if (MI.isBranch() && ST.hasOffset3fBug())
10313 return InstSizeVerifyMode::NoVerify;
10314 return InstSizeVerifyMode::ExactSize;
10315}
10316
10318 if (!isFLAT(MI))
10319 return false;
10320
10321 if (MI.memoperands_empty())
10322 return true;
10323
10324 for (const MachineMemOperand *MMO : MI.memoperands()) {
10326 return true;
10327 }
10328 return false;
10329}
10330
10333 static const std::pair<int, const char *> TargetIndices[] = {
10334 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10335 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10336 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10337 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10338 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10339 return ArrayRef(TargetIndices);
10340}
10341
10342/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10343/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10346 const ScheduleDAG *DAG) const {
10347 return new GCNHazardRecognizer(DAG->MF);
10348}
10349
10350/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10351/// pass.
10358
10359// Called during:
10360// - pre-RA scheduling and post-RA scheduling
10363 const ScheduleDAGMI *DAG) const {
10364 // Borrowed from Arm Target
10365 // We would like to restrict this hazard recognizer to only
10366 // post-RA scheduling; we can tell that we're post-RA because we don't
10367 // track VRegLiveness.
10368 if (!DAG->hasVRegLiveness())
10369 return new GCNHazardRecognizer(DAG->MF);
10371}
10372
10373std::pair<unsigned, unsigned>
10375 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10376}
10377
10380 static const std::pair<unsigned, const char *> TargetFlags[] = {
10381 {MO_GOTPCREL, "amdgpu-gotprel"},
10382 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10383 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10384 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10385 {MO_REL32_LO, "amdgpu-rel32-lo"},
10386 {MO_REL32_HI, "amdgpu-rel32-hi"},
10387 {MO_REL64, "amdgpu-rel64"},
10388 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10389 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10390 {MO_ABS64, "amdgpu-abs64"},
10391 };
10392
10393 return ArrayRef(TargetFlags);
10394}
10395
10398 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10399 {
10400 {MONoClobber, "amdgpu-noclobber"},
10401 {MOLastUse, "amdgpu-last-use"},
10402 {MOCooperative, "amdgpu-cooperative"},
10403 {MOThreadPrivate, "amdgpu-thread-private"},
10404 };
10405
10406 return ArrayRef(TargetFlags);
10407}
10408
10410 const MachineFunction &MF) const {
10412 assert(SrcReg.isVirtual());
10413 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10414 return AMDGPU::WWM_COPY;
10415
10416 return AMDGPU::COPY;
10417}
10418
10420 uint32_t Opcode = MI.getOpcode();
10421 // Check if it is SGPR spill or wwm-register spill Opcode.
10422 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10423 return true;
10424
10425 const MachineFunction *MF = MI.getMF();
10426 const MachineRegisterInfo &MRI = MF->getRegInfo();
10428
10429 // See if this is Liverange split instruction inserted for SGPR or
10430 // wwm-register. The implicit def inserted for wwm-registers should also be
10431 // included as they can appear at the bb begin.
10432 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10433 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10434 return false;
10435
10436 Register Reg = MI.getOperand(0).getReg();
10437 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10438 return IsLRSplitInst;
10439
10440 return MFI->isWWMReg(Reg);
10441}
10442
10444 Register Reg) const {
10445 // We need to handle instructions which may be inserted during register
10446 // allocation to handle the prolog. The initial prolog instruction may have
10447 // been separated from the start of the block by spills and copies inserted
10448 // needed by the prolog. However, the insertions for scalar registers can
10449 // always be placed at the BB top as they are independent of the exec mask
10450 // value.
10451 bool IsNullOrVectorRegister = true;
10452 if (Reg) {
10453 const MachineFunction *MF = MI.getMF();
10454 const MachineRegisterInfo &MRI = MF->getRegInfo();
10455 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10456 }
10457
10458 return IsNullOrVectorRegister &&
10459 (canAddToBBProlog(MI) ||
10460 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10461 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10462}
10463
10467 const DebugLoc &DL,
10468 Register DestReg) const {
10469 if (ST.hasAddNoCarryInsts())
10470 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10471
10472 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10473 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10474 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10475
10476 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10477 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10478}
10479
10482 const DebugLoc &DL,
10483 Register DestReg,
10484 RegScavenger &RS) const {
10485 if (ST.hasAddNoCarryInsts())
10486 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10487
10488 // If available, prefer to use vcc.
10489 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10490 ? Register(RI.getVCC())
10491 : RS.scavengeRegisterBackwards(
10492 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10493 0, /* AllowSpill */ false);
10494
10495 // TODO: Users need to deal with this.
10496 if (!UnusedCarry.isValid())
10497 return MachineInstrBuilder();
10498
10499 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10500 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10501}
10502
10503bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10504 switch (Opcode) {
10505 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10506 case AMDGPU::SI_KILL_I1_TERMINATOR:
10507 return true;
10508 default:
10509 return false;
10510 }
10511}
10512
10514 switch (Opcode) {
10515 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10516 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10517 case AMDGPU::SI_KILL_I1_PSEUDO:
10518 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10519 default:
10520 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10521 }
10522}
10523
10525 return Imm <= getMaxMUBUFImmOffset(ST);
10526}
10527
10529 // GFX12 field is non-negative 24-bit signed byte offset.
10530 const unsigned OffsetBits =
10531 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10532 return (1 << OffsetBits) - 1;
10533}
10534
10536 if (!ST.isWave32())
10537 return;
10538
10539 if (MI.isInlineAsm())
10540 return;
10541
10542 if (MI.getNumOperands() < MI.getDesc().getNumOperands())
10543 return;
10544
10545 for (auto &Op : MI.implicit_operands()) {
10546 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10547 Op.setReg(AMDGPU::VCC_LO);
10548 }
10549}
10550
10552 if (!isSMRD(MI))
10553 return false;
10554
10555 // Check that it is using a buffer resource.
10556 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10557 if (Idx == -1) // e.g. s_memtime
10558 return false;
10559
10560 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10561 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10562}
10563
10564// Given Imm, split it into the values to put into the SOffset and ImmOffset
10565// fields in an MUBUF instruction. Return false if it is not possible (due to a
10566// hardware bug needing a workaround).
10567//
10568// The required alignment ensures that individual address components remain
10569// aligned if they are aligned to begin with. It also ensures that additional
10570// offsets within the given alignment can be added to the resulting ImmOffset.
10572 uint32_t &ImmOffset, Align Alignment) const {
10573 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10574 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10575 uint32_t Overflow = 0;
10576
10577 if (Imm > MaxImm) {
10578 if (Imm <= MaxImm + 64) {
10579 // Use an SOffset inline constant for 4..64
10580 Overflow = Imm - MaxImm;
10581 Imm = MaxImm;
10582 } else {
10583 // Try to keep the same value in SOffset for adjacent loads, so that
10584 // the corresponding register contents can be re-used.
10585 //
10586 // Load values with all low-bits (except for alignment bits) set into
10587 // SOffset, so that a larger range of values can be covered using
10588 // s_movk_i32.
10589 //
10590 // Atomic operations fail to work correctly when individual address
10591 // components are unaligned, even if their sum is aligned.
10592 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10593 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10594 Imm = Low;
10595 Overflow = High - Alignment.value();
10596 }
10597 }
10598
10599 if (Overflow > 0) {
10600 // There is a hardware bug in SI and CI which prevents address clamping in
10601 // MUBUF instructions from working correctly with SOffsets. The immediate
10602 // offset is unaffected.
10603 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10604 return false;
10605
10606 // It is not possible to set immediate in SOffset field on some targets.
10607 if (ST.hasRestrictedSOffset())
10608 return false;
10609 }
10610
10611 ImmOffset = Imm;
10612 SOffset = Overflow;
10613 return true;
10614}
10615
10616// Depending on the used address space and instructions, some immediate offsets
10617// are allowed and some are not.
10618// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10619// scratch instruction offsets can also be negative. On GFX12, offsets can be
10620// negative for all variants.
10621//
10622// There are several bugs related to these offsets:
10623// On gfx10.1, flat instructions that go into the global address space cannot
10624// use an offset.
10625//
10626// For scratch instructions, the address can be either an SGPR or a VGPR.
10627// The following offsets can be used, depending on the architecture (x means
10628// cannot be used):
10629// +----------------------------+------+------+
10630// | Address-Mode | SGPR | VGPR |
10631// +----------------------------+------+------+
10632// | gfx9 | | |
10633// | negative, 4-aligned offset | x | ok |
10634// | negative, unaligned offset | x | ok |
10635// +----------------------------+------+------+
10636// | gfx10 | | |
10637// | negative, 4-aligned offset | ok | ok |
10638// | negative, unaligned offset | ok | x |
10639// +----------------------------+------+------+
10640// | gfx10.3 | | |
10641// | negative, 4-aligned offset | ok | ok |
10642// | negative, unaligned offset | ok | ok |
10643// +----------------------------+------+------+
10644//
10645// This function ignores the addressing mode, so if an offset cannot be used in
10646// one addressing mode, it is considered illegal.
10647bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10648 AMDGPU::FlatAddrSpace FlatVariant) const {
10649 // TODO: Should 0 be special cased?
10650 if (!ST.hasFlatInstOffsets())
10651 return false;
10652
10654 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10655 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10656 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10657 return false;
10658
10659 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10660 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10661 (Offset % 4) != 0) {
10662 return false;
10663 }
10664
10665 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10666 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10667 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10668}
10669
10670// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10671std::pair<int64_t, int64_t>
10672SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10673 AMDGPU::FlatAddrSpace FlatVariant) const {
10674 int64_t RemainderOffset = COffsetVal;
10675 int64_t ImmField = 0;
10676
10677 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10678 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10679
10680 if (AllowNegative) {
10681 // Use signed division by a power of two to truncate towards 0.
10682 int64_t D = 1LL << NumBits;
10683 RemainderOffset = (COffsetVal / D) * D;
10684 ImmField = COffsetVal - RemainderOffset;
10685
10686 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10687 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10688 (ImmField % 4) != 0) {
10689 // Make ImmField a multiple of 4
10690 RemainderOffset += ImmField % 4;
10691 ImmField -= ImmField % 4;
10692 }
10693 } else if (COffsetVal >= 0) {
10694 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10695 RemainderOffset = COffsetVal - ImmField;
10696 }
10697
10698 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10699 assert(RemainderOffset + ImmField == COffsetVal);
10700 return {ImmField, RemainderOffset};
10701}
10702
10704 AMDGPU::FlatAddrSpace FlatVariant) const {
10705 if (ST.hasNegativeScratchOffsetBug() &&
10707 return false;
10708
10709 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10710}
10711
10712static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10713 switch (ST.getGeneration()) {
10714 default:
10715 break;
10718 return SIEncodingFamily::SI;
10721 return SIEncodingFamily::VI;
10725 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10728 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10732 }
10733 llvm_unreachable("Unknown subtarget generation!");
10734}
10735
10736bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10737 switch(MCOp) {
10738 // These opcodes use indirect register addressing so
10739 // they need special handling by codegen (currently missing).
10740 // Therefore it is too risky to allow these opcodes
10741 // to be selected by dpp combiner or sdwa peepholer.
10742 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10743 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10744 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10745 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10746 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10747 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10748 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10749 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10750 return true;
10751 default:
10752 return false;
10753 }
10754}
10755
10756#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10757 case OPCODE##_dpp: \
10758 case OPCODE##_e32: \
10759 case OPCODE##_e64: \
10760 case OPCODE##_e64_dpp: \
10761 case OPCODE##_sdwa:
10762
10763static bool isRenamedInGFX9(int Opcode) {
10764 switch (Opcode) {
10765 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
10766 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
10767 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
10768 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
10769 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
10770 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
10771 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
10772 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
10773 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
10774 //
10775 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10776 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10777 case AMDGPU::V_FMA_F16_gfx9_e64:
10778 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10779 case AMDGPU::V_INTERP_P2_F16:
10780 case AMDGPU::V_MAD_F16_e64:
10781 case AMDGPU::V_MAD_U16_e64:
10782 case AMDGPU::V_MAD_I16_e64:
10783 return true;
10784 default:
10785 return false;
10786 }
10787}
10788
10789int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
10790 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
10791 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10792
10793 unsigned Gen = subtargetEncodingFamily(ST);
10794
10795 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
10797
10798 // Adjust the encoding family to GFX80 for D16 buffer instructions when the
10799 // subtarget has UnpackedD16VMem feature.
10800 // TODO: remove this when we discard GFX80 encoding.
10801 if (ST.hasUnpackedD16VMem() && SIInstrFlags::isD16Buf(get(Opcode)))
10803
10804 if (SIInstrFlags::isSDWA(get(Opcode))) {
10805 switch (ST.getGeneration()) {
10806 default:
10808 break;
10811 break;
10814 break;
10815 }
10816 }
10817
10818 if (isMAI(Opcode)) {
10819 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
10820 if (MFMAOp != -1)
10821 Opcode = MFMAOp;
10822 }
10823
10824 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
10825
10826 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10828
10829 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10831
10832 // -1 means that Opcode is already a native instruction.
10833 if (MCOp == -1)
10834 return Opcode;
10835
10836 if (ST.hasGFX90AInsts()) {
10837 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10838 if (ST.hasGFX940Insts())
10840 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10842 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10844 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10845 MCOp = NMCOp;
10846 }
10847
10848 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
10849 // encoding in the given subtarget generation.
10850 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10851 return -1;
10852
10853 if (isAsmOnlyOpcode(MCOp))
10854 return -1;
10855
10856 return MCOp;
10857}
10858
10859static
10861 assert(RegOpnd.isReg());
10862 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
10863 getRegSubRegPair(RegOpnd);
10864}
10865
10868 assert(MI.isRegSequence());
10869 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
10870 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
10871 auto &RegOp = MI.getOperand(1 + 2 * I);
10872 return getRegOrUndef(RegOp);
10873 }
10875}
10876
10877// Try to find the definition of reg:subreg in subreg-manipulation pseudos
10878// Following a subreg of reg:subreg isn't supported
10881 if (!RSR.SubReg)
10882 return false;
10883 switch (MI.getOpcode()) {
10884 default: break;
10885 case AMDGPU::REG_SEQUENCE:
10886 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
10887 return true;
10888 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
10889 case AMDGPU::INSERT_SUBREG:
10890 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
10891 // inserted the subreg we're looking for
10892 RSR = getRegOrUndef(MI.getOperand(2));
10893 else { // the subreg in the rest of the reg
10894 auto R1 = getRegOrUndef(MI.getOperand(1));
10895 if (R1.SubReg) // subreg of subreg isn't supported
10896 return false;
10897 RSR.Reg = R1.Reg;
10898 }
10899 return true;
10900 }
10901 return false;
10902}
10903
10905 const MachineRegisterInfo &MRI) {
10906 assert(MRI.isSSA());
10907 if (!P.Reg.isVirtual())
10908 return nullptr;
10909
10910 auto RSR = P;
10911 auto *DefInst = MRI.getVRegDef(RSR.Reg);
10912 while (auto *MI = DefInst) {
10913 DefInst = nullptr;
10914 switch (MI->getOpcode()) {
10915 case AMDGPU::COPY:
10916 case AMDGPU::V_MOV_B32_e32: {
10917 auto &Op1 = MI->getOperand(1);
10918 if (Op1.isReg() && Op1.getReg().isVirtual()) {
10919 if (Op1.isUndef())
10920 return nullptr;
10921 RSR = getRegSubRegPair(Op1);
10922 DefInst = MRI.getVRegDef(RSR.Reg);
10923 }
10924 break;
10925 }
10926 default:
10927 if (followSubRegDef(*MI, RSR)) {
10928 if (!RSR.Reg)
10929 return nullptr;
10930 DefInst = MRI.getVRegDef(RSR.Reg);
10931 }
10932 }
10933 if (!DefInst)
10934 return MI;
10935 }
10936 return nullptr;
10937}
10938
10940 Register VReg,
10941 const MachineInstr &DefMI,
10942 const MachineInstr &UseMI) {
10943 assert(MRI.isSSA() && "Must be run on SSA");
10944
10945 auto *TRI = MRI.getTargetRegisterInfo();
10946 auto *DefBB = DefMI.getParent();
10947
10948 // Don't bother searching between blocks, although it is possible this block
10949 // doesn't modify exec.
10950 if (UseMI.getParent() != DefBB)
10951 return true;
10952
10953 const int MaxInstScan = 20;
10954 int NumInst = 0;
10955
10956 // Stop scan at the use.
10957 auto E = UseMI.getIterator();
10958 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
10959 if (I->isDebugInstr())
10960 continue;
10961
10962 if (++NumInst > MaxInstScan)
10963 return true;
10964
10965 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
10966 return true;
10967 }
10968
10969 return false;
10970}
10971
10973 Register VReg,
10974 const MachineInstr &DefMI) {
10975 assert(MRI.isSSA() && "Must be run on SSA");
10976
10977 auto *TRI = MRI.getTargetRegisterInfo();
10978 auto *DefBB = DefMI.getParent();
10979
10980 const int MaxUseScan = 10;
10981 int NumUse = 0;
10982
10983 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
10984 auto &UseInst = *Use.getParent();
10985 // Don't bother searching between blocks, although it is possible this block
10986 // doesn't modify exec.
10987 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10988 return true;
10989
10990 if (++NumUse > MaxUseScan)
10991 return true;
10992 }
10993
10994 if (NumUse == 0)
10995 return false;
10996
10997 const int MaxInstScan = 20;
10998 int NumInst = 0;
10999
11000 // Stop scan when we have seen all the uses.
11001 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
11002 assert(I != DefBB->end());
11003
11004 if (I->isDebugInstr())
11005 continue;
11006
11007 if (++NumInst > MaxInstScan)
11008 return true;
11009
11010 for (const MachineOperand &Op : I->operands()) {
11011 // We don't check reg masks here as they're used only on calls:
11012 // 1. EXEC is only considered const within one BB
11013 // 2. Call should be a terminator instruction if present in a BB
11014
11015 if (!Op.isReg())
11016 continue;
11017
11018 Register Reg = Op.getReg();
11019 if (Op.isUse()) {
11020 if (Reg == VReg && --NumUse == 0)
11021 return false;
11022 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
11023 return true;
11024 }
11025 }
11026}
11027
11030 const DebugLoc &DL, Register Src, Register Dst) const {
11031 auto Cur = MBB.begin();
11032 if (Cur != MBB.end())
11033 do {
11034 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
11035 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
11036 ++Cur;
11037 } while (Cur != MBB.end() && Cur != LastPHIIt);
11038
11039 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
11040 Dst);
11041}
11042
11045 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
11046 if (InsPt != MBB.end() &&
11047 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11048 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11049 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11050 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
11051 InsPt++;
11052 return BuildMI(MBB, InsPt, DL,
11053 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
11054 .addReg(Src, {}, SrcSubReg)
11055 .addReg(AMDGPU::EXEC, RegState::Implicit);
11056 }
11057 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
11058 Dst);
11059}
11060
11061bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
11062
11064 const MachineInstr &SecondMI) const {
11065 for (const auto &Use : SecondMI.all_uses()) {
11066 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
11067 return true;
11068 }
11069 return false;
11070}
11071
11072/// If OpX is multicycle, anti-dependencies are not allowed.
11073/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
11074/// purpose.
11076 const MachineInstr &OpX) const {
11078}
11079
11082 ArrayRef<unsigned> Ops, int FrameIndex,
11083 MachineInstr *&CopyMI, LiveIntervals *LIS,
11084 VirtRegMap *VRM) const {
11085 // This is a bit of a hack (copied from AArch64). Consider this instruction:
11086 //
11087 // %0:sreg_32 = COPY $m0
11088 //
11089 // We explicitly chose SReg_32 for the virtual register so such a copy might
11090 // be eliminated by RegisterCoalescer. However, that may not be possible, and
11091 // %0 may even spill. We can't spill $m0 normally (it would require copying to
11092 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
11093 // TargetInstrInfo::foldMemoryOperand() is going to try.
11094 // A similar issue also exists with spilling and reloading $exec registers.
11095 //
11096 // To prevent that, constrain the %0 register class here.
11097 if (isFullCopyInstr(MI)) {
11098 Register DstReg = MI.getOperand(0).getReg();
11099 Register SrcReg = MI.getOperand(1).getReg();
11100 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
11101 (DstReg.isVirtual() != SrcReg.isVirtual())) {
11102 MachineRegisterInfo &MRI = MF.getRegInfo();
11103 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
11104 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
11105 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
11106 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11107 return nullptr;
11108 }
11109 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
11110 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11111 return nullptr;
11112 }
11113 }
11114 }
11115
11116 return nullptr;
11117}
11118
11120 const MachineInstr &MI,
11121 unsigned *PredCost) const {
11122 if (MI.isBundle()) {
11124 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
11125 unsigned Lat = 0, Count = 0;
11126 for (++I; I != E && I->isBundledWithPred(); ++I) {
11127 ++Count;
11128 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
11129 }
11130 return Lat + Count - 1;
11131 }
11132
11133 return SchedModel.computeInstrLatency(&MI);
11134}
11135
11136const MachineOperand &
11138 if (const MachineOperand *CallAddrOp =
11139 getNamedOperand(MI, AMDGPU::OpName::src0))
11140 return *CallAddrOp;
11142}
11143
11146 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11147 unsigned Opcode = MI.getOpcode();
11148
11149 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
11150 Register Dst = MI.getOperand(0).getReg();
11151 Register Src = MI.getOperand(1).getReg();
11152 LLT DstTy = MRI.getType(Dst);
11153 LLT SrcTy = MRI.getType(Src);
11154 unsigned DstAS = DstTy.getAddressSpace();
11155 unsigned SrcAS = SrcTy.getAddressSpace();
11156 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
11157 DstAS == AMDGPUAS::FLAT_ADDRESS &&
11158 ST.hasGloballyAddressableScratch()
11161 };
11162
11163 // If the target supports globally addressable scratch, the mapping from
11164 // scratch memory to the flat aperture changes therefore an address space cast
11165 // is no longer uniform.
11166 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11167 return HandleAddrSpaceCast(MI);
11168
11169 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
11170 auto IID = GI->getIntrinsicID();
11175
11176 switch (IID) {
11177 case Intrinsic::amdgcn_if:
11178 case Intrinsic::amdgcn_else:
11179 // FIXME: Uniform if second result
11180 break;
11181 }
11182
11184 }
11185
11186 // Loads from the private and flat address spaces are divergent, because
11187 // threads can execute the load instruction with the same inputs and get
11188 // different results.
11189 //
11190 // All other loads are not divergent, because if threads issue loads with the
11191 // same arguments, they will always get the same result.
11192 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11193 Opcode == AMDGPU::G_SEXTLOAD) {
11194 if (MI.memoperands_empty())
11195 return ValueUniformity::NeverUniform; // conservative assumption
11196
11197 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11198 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11199 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11200 })) {
11201 // At least one MMO in a non-global address space.
11203 }
11205 }
11206
11207 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11208 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11209 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11210 AMDGPU::isGenericAtomic(Opcode)) {
11212 }
11213
11214 // Result is computed from uniform SP and uniform wave-wide max size.
11215 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11217
11218 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11220
11222}
11223
11225 if (!Formatter)
11226 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11227 return Formatter.get();
11228}
11229
11231
11232 if (isNeverUniform(MI))
11234
11235 unsigned opcode = MI.getOpcode();
11236 if (opcode == AMDGPU::V_READLANE_B32 ||
11237 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11238 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11240
11241 // If any of defs is divergent, report as NeverUniform. isUniformReg will
11242 // calculate in more detail for each def from its reg class, if available.
11243 if (MI.isInlineAsm()) {
11244 for (const MachineOperand &MO : MI.operands()) {
11245 if (!MO.isReg() || !MO.isDef())
11246 continue;
11247 const TargetRegisterClass *RC =
11248 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
11249 if (!RC || !RI.isSGPRClass(RC))
11251 }
11252 }
11253
11254 if (isCopyInstr(MI)) {
11255 const MachineOperand &srcOp = MI.getOperand(1);
11256 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
11257 const TargetRegisterClass *regClass =
11258 RI.getPhysRegBaseClass(srcOp.getReg());
11259 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
11261 }
11263 }
11264
11265 // GMIR handling
11266 if (MI.isPreISelOpcode())
11268
11269 // Atomics are divergent because they are executed sequentially: when an
11270 // atomic operation refers to the same address in each thread, then each
11271 // thread after the first sees the value written by the previous thread as
11272 // original value.
11273
11274 if (isAtomic(MI))
11276
11277 // Loads from the private and flat address spaces are divergent, because
11278 // threads can execute the load instruction with the same inputs and get
11279 // different results.
11280 if (isFLAT(MI) && MI.mayLoad()) {
11281 if (MI.memoperands_empty())
11282 return ValueUniformity::NeverUniform; // conservative assumption
11283
11284 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11285 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11286 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11287 })) {
11288 // At least one MMO in a non-global address space.
11290 }
11291
11293 }
11294
11295 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11296 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11297
11298 // FIXME: It's conceptually broken to report this for an instruction, and not
11299 // a specific def operand. For inline asm in particular, there could be mixed
11300 // uniform and divergent results.
11301 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11302 const MachineOperand &SrcOp = MI.getOperand(I);
11303 if (!SrcOp.isReg())
11304 continue;
11305
11306 Register Reg = SrcOp.getReg();
11307 if (!Reg || !SrcOp.readsReg())
11308 continue;
11309
11310 // If RegBank is null, this is unassigned or an unallocatable special
11311 // register, which are all scalars.
11312 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11313 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11315 }
11316
11317 // TODO: Uniformity check condtions above can be rearranged for more
11318 // redability
11319
11320 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11321 // currently turned into no-op COPYs by SelectionDAG ISel and are
11322 // therefore no longer recognizable.
11323
11325}
11326
11328 switch (MF.getFunction().getCallingConv()) {
11330 return 1;
11332 return 2;
11334 return 3;
11338 const Function &F = MF.getFunction();
11339 F.getContext().diagnose(DiagnosticInfoUnsupported(
11340 F, "ds_ordered_count unsupported for this calling conv"));
11341 [[fallthrough]];
11342 }
11345 case CallingConv::C:
11346 case CallingConv::Fast:
11347 default:
11348 // Assume other calling conventions are various compute callable functions
11349 return 0;
11350 }
11351}
11352
11354 Register &SrcReg2, int64_t &CmpMask,
11355 int64_t &CmpValue) const {
11356 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11357 return false;
11358
11359 switch (MI.getOpcode()) {
11360 default:
11361 break;
11362 case AMDGPU::S_CMP_EQ_U32:
11363 case AMDGPU::S_CMP_EQ_I32:
11364 case AMDGPU::S_CMP_LG_U32:
11365 case AMDGPU::S_CMP_LG_I32:
11366 case AMDGPU::S_CMP_LT_U32:
11367 case AMDGPU::S_CMP_LT_I32:
11368 case AMDGPU::S_CMP_GT_U32:
11369 case AMDGPU::S_CMP_GT_I32:
11370 case AMDGPU::S_CMP_LE_U32:
11371 case AMDGPU::S_CMP_LE_I32:
11372 case AMDGPU::S_CMP_GE_U32:
11373 case AMDGPU::S_CMP_GE_I32:
11374 case AMDGPU::S_CMP_EQ_U64:
11375 case AMDGPU::S_CMP_LG_U64:
11376 SrcReg = MI.getOperand(0).getReg();
11377 if (MI.getOperand(1).isReg()) {
11378 if (MI.getOperand(1).getSubReg())
11379 return false;
11380 SrcReg2 = MI.getOperand(1).getReg();
11381 CmpValue = 0;
11382 } else if (MI.getOperand(1).isImm()) {
11383 SrcReg2 = Register();
11384 CmpValue = MI.getOperand(1).getImm();
11385 } else {
11386 return false;
11387 }
11388 CmpMask = ~0;
11389 return true;
11390 case AMDGPU::S_CMPK_EQ_U32:
11391 case AMDGPU::S_CMPK_EQ_I32:
11392 case AMDGPU::S_CMPK_LG_U32:
11393 case AMDGPU::S_CMPK_LG_I32:
11394 case AMDGPU::S_CMPK_LT_U32:
11395 case AMDGPU::S_CMPK_LT_I32:
11396 case AMDGPU::S_CMPK_GT_U32:
11397 case AMDGPU::S_CMPK_GT_I32:
11398 case AMDGPU::S_CMPK_LE_U32:
11399 case AMDGPU::S_CMPK_LE_I32:
11400 case AMDGPU::S_CMPK_GE_U32:
11401 case AMDGPU::S_CMPK_GE_I32:
11402 SrcReg = MI.getOperand(0).getReg();
11403 SrcReg2 = Register();
11404 CmpValue = MI.getOperand(1).getImm();
11405 CmpMask = ~0;
11406 return true;
11407 }
11408
11409 return false;
11410}
11411
11413 for (MachineBasicBlock *S : MBB->successors()) {
11414 if (S->isLiveIn(AMDGPU::SCC))
11415 return false;
11416 }
11417 return true;
11418}
11419
11420// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11421// (incoming SCC) = !(SCC defined by SCCDef).
11422// Return true if all uses can be re-written, false otherwise.
11423bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11424 MachineBasicBlock *MBB = SCCDef->getParent();
11425 SmallVector<MachineInstr *> InvertInstr;
11426 bool SCCIsDead = false;
11427
11428 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11429 constexpr unsigned ScanLimit = 12;
11430 unsigned Count = 0;
11431 for (MachineInstr &MI :
11432 make_range(std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11433 if (++Count > ScanLimit)
11434 return false;
11435 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11436 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11437 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11438 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11439 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11440 InvertInstr.push_back(&MI);
11441 else
11442 return false;
11443 }
11444 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11445 SCCIsDead = true;
11446 break;
11447 }
11448 }
11449 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11450 SCCIsDead = true;
11451
11452 // SCC may have more uses. Can't invert all of them.
11453 if (!SCCIsDead)
11454 return false;
11455
11456 // Invert uses
11457 for (MachineInstr *MI : InvertInstr) {
11458 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11459 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11460 swapOperands(*MI);
11461 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11462 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11463 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11464 ? AMDGPU::S_CBRANCH_SCC1
11465 : AMDGPU::S_CBRANCH_SCC0));
11466 } else {
11467 llvm_unreachable("SCC used but no inversion handling");
11468 }
11469 }
11470 return true;
11471}
11472
11473// SCC is already valid after SCCValid.
11474// SCCRedefine will redefine SCC to the same value already available after
11475// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11476// update kill/dead flags if necessary.
11477bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11478 bool NeedInversion) const {
11479 MachineInstr *KillsSCC = nullptr;
11480 if (SCCValid->getParent() != SCCRedefine->getParent())
11481 return false;
11482 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11483 SCCRedefine->getIterator())) {
11484 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11485 return false;
11486 if (MI.killsRegister(AMDGPU::SCC, &RI))
11487 KillsSCC = &MI;
11488 }
11489 if (NeedInversion && !invertSCCUse(SCCRedefine))
11490 return false;
11491 if (MachineOperand *SccDef =
11492 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11493 SccDef->setIsDead(false);
11494 if (KillsSCC)
11495 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11496 SCCRedefine->eraseFromParent();
11497 return true;
11498}
11499
11500static bool foldableSelect(const MachineInstr &Def) {
11501 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11502 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11503 return false;
11504 bool Op1IsNonZeroImm =
11505 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11506 bool Op2IsZeroImm =
11507 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11508 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11509 return false;
11510 return true;
11511}
11512
11513static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11514 unsigned &NewDefOpc) {
11515 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11516 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11517 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11518 Def.getOpcode() != AMDGPU::S_ADD_U32)
11519 return false;
11520 const MachineOperand &AddSrc1 = Def.getOperand(1);
11521 const MachineOperand &AddSrc2 = Def.getOperand(2);
11522 const MachineRegisterInfo &MRI = Def.getMF()->getRegInfo();
11523 const SIInstrInfo *TII = static_cast<const SIInstrInfo *>(
11524 Def.getMF()->getSubtarget().getInstrInfo());
11525
11526 auto Imm1 = TII->getImmOrMaterializedImm(MRI, AddSrc1);
11527 auto Imm2 = TII->getImmOrMaterializedImm(MRI, AddSrc2);
11528 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11529 return false;
11530
11531 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11532 const MachineOperand *SccDef =
11533 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11534 if (!SccDef->isDead())
11535 return false;
11536 NewDefOpc = AMDGPU::S_ADD_U32;
11537 }
11538 NeedInversion = !NeedInversion;
11539 return true;
11540}
11541
11543 Register SrcReg2, int64_t CmpMask,
11544 int64_t CmpValue,
11545 const MachineRegisterInfo *MRI) const {
11546 if (!SrcReg || SrcReg.isPhysical())
11547 return false;
11548
11549 if (SrcReg2) {
11550 auto ImmOpt = getImmOrMaterializedImm(*MRI, SrcReg2);
11551 if (!ImmOpt)
11552 return false;
11553 CmpValue = *ImmOpt;
11554 }
11555
11556 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11557 this](bool NeedInversion) -> bool {
11558 if (CmpValue != 0)
11559 return false;
11560
11561 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11562 if (!Def)
11563 return false;
11564
11565 // For S_OP that set SCC = DST!=0, do the transformation
11566 //
11567 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11568 //
11569 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11570 // do the transformation:
11571 //
11572 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11573 //
11574 // If foldableSelect, s_cmp_lg_* is redundant because the SCC input value
11575 // for S_CSELECT* already has the same value that will be calculated by
11576 // s_cmp_lg_*
11577 //
11578 // s_cmp_[lg|eq]_* (S_CSELECT* (non-zero imm), 0), 0 => (S_CSELECT*
11579 // (non-zero imm), 0)
11580
11581 unsigned NewDefOpc = Def->getOpcode();
11582 if (!setsSCCIfResultIsNonZero(*Def) &&
11583 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc) &&
11584 !foldableSelect(*Def))
11585 return false;
11586
11587 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11588 return false;
11589
11590 if (NewDefOpc != Def->getOpcode())
11591 Def->setDesc(get(NewDefOpc));
11592
11593 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11594 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11595 // 64-bit foldableSelect then delete s_or_b32 in the sequence:
11596 // sX = s_cselect_b64 (non-zero imm), 0
11597 // sLo = copy sX.sub0
11598 // sHi = copy sX.sub1
11599 // sY = s_or_b32 sLo, sHi
11600 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11601 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11602 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11603 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11604 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11605 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11606 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11607 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11608 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11609 Def2->getOperand(1).isReg() &&
11610 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11611 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11612 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11613 MachineInstr *Select = MRI->getVRegDef(Def1->getOperand(1).getReg());
11614 if (Select && foldableSelect(*Select))
11615 optimizeSCC(Select, Def, /*NeedInversion=*/false);
11616 }
11617 }
11618 }
11619 return true;
11620 };
11621
11622 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11623 this](int64_t ExpectedValue, unsigned SrcSize,
11624 bool IsReversible, bool IsSigned) -> bool {
11625 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11626 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11627 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11628 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11629 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11630 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11631 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11632 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11633 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11634 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11635 //
11636 // Signed ge/gt are not used for the sign bit.
11637 //
11638 // If result of the AND is unused except in the compare:
11639 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11640 //
11641 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11642 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11643 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11644 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11645 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11646 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11647
11648 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11649 if (!Def)
11650 return false;
11651
11652 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11653 Def->getOpcode() != AMDGPU::S_AND_B64)
11654 return false;
11655
11656 int64_t Mask;
11657 const auto isMask = [&Mask, SrcSize, MRI,
11658 this](const MachineOperand *MO) -> bool {
11659 auto ImmOpt = this->getImmOrMaterializedImm(*MRI, *MO);
11660 if (!ImmOpt)
11661 return false;
11662 Mask = *ImmOpt;
11663 Mask &= maxUIntN(SrcSize);
11664 return isPowerOf2_64(Mask);
11665 };
11666
11667 MachineOperand *SrcOp = &Def->getOperand(1);
11668 if (isMask(SrcOp))
11669 SrcOp = &Def->getOperand(2);
11670 else if (isMask(&Def->getOperand(2)))
11671 SrcOp = &Def->getOperand(1);
11672 else
11673 return false;
11674
11675 // A valid Mask is required to have a single bit set, hence a non-zero and
11676 // power-of-two value. This verifies that we will not do 64-bit shift below.
11677 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11678 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11679 if (IsSigned && BitNo == SrcSize - 1)
11680 return false;
11681
11682 ExpectedValue <<= BitNo;
11683
11684 bool IsReversedCC = false;
11685 if (CmpValue != ExpectedValue) {
11686 if (!IsReversible)
11687 return false;
11688 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11689 if (!IsReversedCC)
11690 return false;
11691 }
11692
11693 Register DefReg = Def->getOperand(0).getReg();
11694 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11695 return false;
11696
11697 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11698 return false;
11699
11700 if (!MRI->use_nodbg_empty(DefReg)) {
11701 assert(!IsReversedCC);
11702 return true;
11703 }
11704
11705 // Replace AND with unused result with a S_BITCMP.
11706 MachineBasicBlock *MBB = Def->getParent();
11707
11708 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11709 : AMDGPU::S_BITCMP1_B32
11710 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11711 : AMDGPU::S_BITCMP1_B64;
11712
11713 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11714 .add(*SrcOp)
11715 .addImm(BitNo);
11716 Def->eraseFromParent();
11717
11718 return true;
11719 };
11720
11721 switch (CmpInstr.getOpcode()) {
11722 default:
11723 break;
11724 case AMDGPU::S_CMP_EQ_U32:
11725 case AMDGPU::S_CMP_EQ_I32:
11726 case AMDGPU::S_CMPK_EQ_U32:
11727 case AMDGPU::S_CMPK_EQ_I32:
11728 return optimizeCmpAnd(1, 32, true, false) ||
11729 optimizeCmpSelect(/*NeedInversion=*/true);
11730 case AMDGPU::S_CMP_GE_U32:
11731 case AMDGPU::S_CMPK_GE_U32:
11732 return optimizeCmpAnd(1, 32, false, false);
11733 case AMDGPU::S_CMP_GE_I32:
11734 case AMDGPU::S_CMPK_GE_I32:
11735 return optimizeCmpAnd(1, 32, false, true);
11736 case AMDGPU::S_CMP_EQ_U64:
11737 return optimizeCmpAnd(1, 64, true, false);
11738 case AMDGPU::S_CMP_LG_U32:
11739 case AMDGPU::S_CMP_LG_I32:
11740 case AMDGPU::S_CMPK_LG_U32:
11741 case AMDGPU::S_CMPK_LG_I32:
11742 return optimizeCmpAnd(0, 32, true, false) ||
11743 optimizeCmpSelect(/*NeedInversion=*/false);
11744 case AMDGPU::S_CMP_GT_U32:
11745 case AMDGPU::S_CMPK_GT_U32:
11746 return optimizeCmpAnd(0, 32, false, false);
11747 case AMDGPU::S_CMP_GT_I32:
11748 case AMDGPU::S_CMPK_GT_I32:
11749 return optimizeCmpAnd(0, 32, false, true);
11750 case AMDGPU::S_CMP_LG_U64:
11751 return optimizeCmpAnd(0, 64, true, false) ||
11752 optimizeCmpSelect(/*NeedInversion=*/false);
11753 }
11754
11755 return false;
11756}
11757
11759 AMDGPU::OpName OpName) const {
11760 if (!ST.needsAlignedVGPRs())
11761 return;
11762
11763 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
11764 if (OpNo < 0)
11765 return;
11766 MachineOperand &Op = MI.getOperand(OpNo);
11767 if (getOpSize(MI, OpNo) > 4)
11768 return;
11769
11770 // Add implicit aligned super-reg to force alignment on the data operand.
11771 const DebugLoc &DL = MI.getDebugLoc();
11772 MachineBasicBlock *BB = MI.getParent();
11774 Register DataReg = Op.getReg();
11775 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11777 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11778 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
11779 Register NewVR =
11780 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
11781 : &AMDGPU::VReg_64_Align2RegClass);
11782 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
11783 .addReg(DataReg, {}, Op.getSubReg())
11784 .addImm(AMDGPU::sub0)
11785 .addReg(Undef)
11786 .addImm(AMDGPU::sub1);
11787 Op.setReg(NewVR);
11788 Op.setSubReg(AMDGPU::sub0);
11789 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
11790}
11791
11793 if (!SchedModel.hasInstrSchedModel())
11794 return 0;
11795
11796 // The repeat rate is the throughput-limiting resource occupancy: the largest
11797 // number of cycles any written processor resource is held.
11798 const MCSchedClassDesc *SCDesc = SchedModel.resolveSchedClass(&MI);
11799 unsigned RepeatRate = 0;
11801 PI = SchedModel.getWriteProcResBegin(SCDesc),
11802 PE = SchedModel.getWriteProcResEnd(SCDesc);
11803 PI != PE; ++PI) {
11804 RepeatRate = std::max(RepeatRate, (unsigned)PI->ReleaseAtCycle);
11805 }
11806
11807 return RepeatRate;
11808}
11809
11811 if (isIGLP(*MI))
11812 return false;
11813
11815}
11816
11818 if (!isWMMA(MI) && !isSWMMAC(MI))
11819 return false;
11820
11821 if (ST.hasGFX1250Insts())
11822 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
11823
11824 return true;
11825}
11826
11828 unsigned Opcode = MI.getOpcode();
11829
11830 if (AMDGPU::isGFX12Plus(ST))
11831 return isDOT(MI) || isXDLWMMA(MI);
11832
11833 if (!isMAI(MI) || isDGEMM(Opcode) ||
11834 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11835 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11836 return false;
11837
11838 if (!ST.hasGFX940Insts())
11839 return true;
11840
11841 return AMDGPU::getMAIIsGFX940XDL(Opcode);
11842}
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
unsigned uint64_t
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
AMDGPU Register Bank Select
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static bool isUndef(const MachineInstr &MI)
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t High
uint64_t IntrinsicInst * II
#define P(N)
R600 Clause Merge
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static cl::opt< bool > Fix16BitCopies("amdgpu-fix-16-bit-physreg-copies", cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"), cl::init(true), cl::ReallyHidden)
static void expandSGPRCopy(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RC, bool Forward)
static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc)
static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize)
static bool compareMachineOp(const MachineOperand &Op0, const MachineOperand &Op1)
static bool isStride64(unsigned Opc)
static MachineBasicBlock * generateWaterFallLoop(const SIInstrInfo &TII, MachineInstr &MI, ArrayRef< MachineOperand * > ScalarOps, MachineDominatorTree *MDT, MachineBasicBlock::iterator Begin=nullptr, MachineBasicBlock::iterator End=nullptr, ArrayRef< Register > PhySGPRs={})
#define GENERATE_RENAMED_GFX9_CASES(OPCODE)
static std::tuple< unsigned, unsigned > extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc)
static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx)
static bool followSubRegDef(MachineInstr &MI, TargetInstrInfo::RegSubRegPair &RSR)
static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize)
static MachineInstr * swapImmOperands(MachineInstr &MI, MachineOperand &NonRegOp1, MachineOperand &NonRegOp2)
static void copyFlagsToImplicitVCC(MachineInstr &MI, const MachineOperand &Orig)
static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, LocationSize WidthB, int OffsetB)
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, RegScavenger &RS, bool RegsOverlap, Register ImpUseSuperReg=Register())
Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908.
static unsigned getWWMRegSpillSaveOpcode(unsigned Size, bool IsVectorSuperClass)
static bool memOpsHaveSameBaseOperands(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getWWMRegSpillRestoreOpcode(unsigned Size, bool IsVectorSuperClass)
static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion, unsigned &NewDefOpc)
static bool isSCCDeadOnExit(MachineBasicBlock *MBB)
static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize)
static unsigned subtargetEncodingFamily(const GCNSubtarget &ST)
static void preserveCondRegFlags(MachineOperand &CondReg, const MachineOperand &OrigCond)
static Register findImplicitSGPRRead(const MachineInstr &MI)
static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc)
static cl::opt< unsigned > BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16), cl::desc("Restrict range of branch instructions (DEBUG)"))
static void updateLiveVariables(LiveVariables *LV, MachineInstr &MI, MachineInstr &NewMI)
static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getSGPRSpillRestoreOpcode(unsigned Size)
static bool isRegOrFI(const MachineOperand &MO)
static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static constexpr AMDGPU::OpName ModifierOpNames[]
static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const char *Msg="illegal VGPR to SGPR copy")
static MachineInstr * swapRegAndNonRegOperand(MachineInstr &MI, MachineOperand &RegOp, MachineOperand &NonRegOp)
static bool shouldReadExec(const MachineInstr &MI)
static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc)
static bool isRenamedInGFX9(int Opcode)
static TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd)
static std::tuple< unsigned, unsigned, unsigned > splitGlobalAddressRelocFlags(const GCNSubtarget &ST, const MachineOperand &SrcOp)
static bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
static bool foldableSelect(const MachineInstr &Def)
static bool nodesHaveSameOperandValue(SDNode *N0, SDNode *N1, AMDGPU::OpName OpName)
Returns true if both nodes have the same value for the given operand Op, or if both nodes do not have...
static unsigned getNumOperandsNoGlue(SDNode *Node)
static bool canRemat(const MachineInstr &MI)
static unsigned getAVSpillRestoreOpcode(unsigned Size)
static void emitLoadScalarOpsFromVGPRLoop(const SIInstrInfo &TII, MachineRegisterInfo &MRI, MachineBasicBlock &PredBB, MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={})
static unsigned getVGPRSpillRestoreOpcode(unsigned Size)
Interface definition for SIInstrInfo.
bool IsDead
const char * Msg
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
#define LLVM_DEBUG(...)
Definition Debug.h:119
static const LaneMaskConstants & get(const GCNSubtarget &ST)
static LLVM_ABI Semantics SemanticsToEnum(const llvm::fltSemantics &Sem)
Definition APFloat.cpp:183
Class for arbitrary precision integers.
Definition APInt.h:78
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1583
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
This class is the base class for the comparison instructions.
Definition InstrTypes.h:728
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A debug info location.
Definition DebugLoc.h:126
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h: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:273
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:356
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
CycleRef getParentCycle(CycleRef C) const
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
Itinerary data supplied by a subtarget to be used by a target.
constexpr unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LiveInterval - This class represents the liveness of a register, or stack slot.
bool hasInterval(Register Reg) const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
LLVM_ABI bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
This class represents the liveness of a register, stack slot, etc.
LLVM_ABI void replaceKillInstruction(Register Reg, MachineInstr &OldMI, MachineInstr &NewMI)
replaceKillInstruction - Update register kill info by replacing a kill instruction with a new one.
LLVM_ABI VarInfo & getVarInfo(Register Reg)
getVarInfo - Return the VarInfo structure for the specified VIRTUAL register.
bool hasValue() const
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:347
static const MCBinaryExpr * createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:417
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
unsigned getOpcode() const
Return the opcode number for this descriptor.
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition MCInstrDesc.h:88
uint8_t OperandType
Information about the type of the operand.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition MCInstrDesc.h:94
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void setVariableValue(const MCExpr *Value)
Definition MCSymbol.cpp:50
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
MIRFormater - Interface to format MIR operand based on target.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
void push_back(MachineInstr *MI)
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isImmutableObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an immutable object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
bool isCopy() const
const MachineBasicBlock * getParent() const
LLVM_ABI void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
bool isBundle() const
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromBundle()
Unlink 'this' from its basic block and delete it.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mop_range explicit_operands()
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just after the instruction itself.
LLVM_ABI void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo)
Clear all kill flags affecting Reg.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
A description of a memory reference used in the backend.
unsigned getAddrSpace() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
const GlobalValue * getGlobal() const
LLVM_ABI void ChangeToFrameIndex(int Idx, unsigned TargetFlags=0)
Replace this operand with a frame index.
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
LLVM_ABI void ChangeToGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
ChangeToGA - Replace this operand with a new global address operand.
void setIsKill(bool Val=true)
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
void setOffset(int64_t Offset)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isTargetIndex() const
isTargetIndex - Tests if this is a MO_TargetIndex operand.
void setTargetFlags(unsigned F)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps)
Move NumOps operands from Src to Dst, updating use-def lists as needed.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
LLVM_ABI void clearVirtRegs()
clearVirtRegs - Remove all virtual registers (after physreg assignment).
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
const MachineFunction & getMF() const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI bool isConstantPhysReg(MCRegister PhysReg) const
Returns true if PhysReg is unallocatable and constant throughout the function.
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void removeRegOperandFromUseList(MachineOperand *MO)
Remove MO from its use-def list.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI void addRegOperandToUseList(MachineOperand *MO)
Add MO to the linked list of operands for its register.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const final
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
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
bool isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
bool isLegalVSrcOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO would be a valid operand for the given operand definition OpInfo.
static bool isDOT(const MachineInstr &MI)
std::unique_ptr< PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
bool hasModifiers(unsigned Opcode) const
Return true if this instruction has any modifiers.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
static bool isSWMMAC(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
bool isWave32() const
bool isHighLatencyDef(int Opc) const override
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const
Legalize the OpIndex operand of this instruction by inserting a MOV.
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isVOPC(const MachineInstr &MI)
void removeModOperands(MachineInstr &MI) const
unsigned getRepeatRate(const MachineInstr &MI) const
Get the repeat rate for a VALU instruction from the scheduling model.
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool isLegalSingleSGPRReadInstOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for a single-SGPR-read instruction.
bool isXDL(const MachineInstr &MI) const
Register isStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
static bool isVIMAGE(const MachineInstr &MI)
void enforceOperandRCAlignment(MachineInstr &MI, AMDGPU::OpName OpName) const
static bool isSOP2(const MachineInstr &MI)
static bool isGWS(const MachineInstr &MI)
bool hasRAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI) const
bool isLegalAV64PseudoImm(uint64_t Imm) const
Check if this immediate value can be used for AV_MOV_B64_IMM_PSEUDO.
bool isNeverCoissue(MachineInstr &MI) const
static bool isBUF(const MachineInstr &MI)
void handleCopyToPhysHelper(SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst, MachineRegisterInfo &MRI, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
bool hasModifiersSet(const MachineInstr &MI, AMDGPU::OpName OpName) const
bool isLegalToSwap(const MachineInstr &MI, unsigned fromIdx, unsigned toIdx) const
static bool isFLATGlobal(const MachineInstr &MI)
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isGlobalMemoryObject(const MachineInstr *MI) const override
static bool isVSAMPLE(const MachineInstr &MI)
bool isBufferSMRD(const MachineInstr &MI) const
static bool isKillTerminator(unsigned Opcode)
bool isVOPDAntidependencyAllowed(const MachineInstr &MI) const
If OpX is multicycle, anti-dependencies are not allowed.
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
void insertScratchExecCopy(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, bool IsSCCLive, SlotIndexes *Indexes=nullptr) const
bool hasVALU32BitEncoding(unsigned Opcode) const
Return true if this 64-bit VALU instruction has a 32-bit encoding.
unsigned getMovOpcode(const TargetRegisterClass *DstRC) const
Register isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
unsigned buildExtractSubReg(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const
Legalize operands in MI by either commuting it or inserting a copy of src1.
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const final
static bool isTRANS(const MachineInstr &MI)
static bool isImage(const MachineInstr &MI)
static bool isSOPK(const MachineInstr &MI)
const TargetRegisterClass * getOpRegClass(const MachineInstr &MI, unsigned OpNo) const
Return the correct register class for OpNo.
MachineBasicBlock * insertSimulatedTrap(MachineRegisterInfo &MRI, MachineBasicBlock &MBB, MachineInstr &MI, const DebugLoc &DL) const
Build instructions that simulate the behavior of a s_trap 2 instructions for hardware (namely,...
static unsigned getNonSoftWaitcntOpcode(unsigned Opcode)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static bool isFoldableCopy(const MachineInstr &MI)
static bool isMUBUF(const MachineInstr &MI)
bool expandPostRAPseudo(MachineInstr &MI) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
void createWaterFallForSiCall(MachineInstr *MI, MachineDominatorTree *MDT, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={}) const
Wrapper function for generating waterfall for instruction MI This function take into consideration of...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSegmentSpecificFLAT(const MachineInstr &MI)
bool isReMaterializableImpl(const MachineInstr &MI) const override
static bool isVOP3(const MCInstrDesc &Desc)
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool physRegUsesConstantBus(const MachineOperand &Reg) const
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.
void moveToVALUImpl(SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
static bool isLDSDMA(const MachineInstr &MI)
static bool isVOP1(const MachineInstr &MI)
SIInstrInfo(const GCNSubtarget &ST)
std::optional< int64_t > getImmOrMaterializedImm(const MachineRegisterInfo &MRI, const MachineOperand &Op, MachineInstr **DefMI=nullptr) const
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool hasAnyModifiersSet(const MachineInstr &MI) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
void setHasSpilledVGPRs(bool Spill=true)
bool isWWMReg(Register Reg) const
bool checkFlag(Register Reg, uint8_t Flag) const
void setHasSpilledSGPRs(bool Spill=true)
unsigned getScratchReservedForDynamicVGPRs() const
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:66
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndexes pass.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:293
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
int64_t getImm() const
Register getReg() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Object returned by analyzeLoopForPipelining.
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:339
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:187
self_iterator getIterator()
Definition ilist_node.h:123
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
@ OPERAND_REG_IMM_V2FP64
Definition SIDefines.h:446
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:464
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:432
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:439
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:455
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:452
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:457
@ OPERAND_REG_IMM_V2INT64
Definition SIDefines.h:442
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:441
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:436
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:431
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:438
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:437
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:440
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:451
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:449
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:443
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:435
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:458
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:469
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:470
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:444
@ OPERAND_SDWA_VOPC_DST
Definition SIDefines.h:481
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:434
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:454
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:450
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:456
@ OPERAND_INLINE_C_AV64_PSEUDO
Definition SIDefines.h:475
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:445
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:471
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:453
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:433
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:461
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:669
@ TI_SCRATCH_RSRC_DWORD3
Definition AMDGPU.h:671
@ TI_SCRATCH_RSRC_DWORD0
Definition AMDGPU.h:668
@ TI_SCRATCH_RSRC_DWORD2
Definition AMDGPU.h:670
@ TI_CONSTDATA_START
Definition AMDGPU.h:667
bool isSingleSGPRReadInst(unsigned Opc)
Packed instructions that read a single SGPR for SGPR operands, except for 64-bit elements which read ...
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
const uint64_t RSRC_INDEX_STRIDE_SHIFT
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition CallingConv.h:41
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ OPERAND_GENERIC_4
Definition MCInstrDesc.h:71
@ OPERAND_GENERIC_2
Definition MCInstrDesc.h:69
@ OPERAND_GENERIC_1
Definition MCInstrDesc.h:68
@ OPERAND_GENERIC_3
Definition MCInstrDesc.h:70
@ OPERAND_IMMEDIATE
Definition MCInstrDesc.h:61
@ OPERAND_GENERIC_0
Definition MCInstrDesc.h:67
@ OPERAND_GENERIC_5
Definition MCInstrDesc.h:72
Not(const Pred &P) -> Not< Pred >
constexpr bool isD16Buf(const T &...O)
Definition SIDefines.h:343
constexpr bool isSDWA(const T &...O)
Definition SIDefines.h:252
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
Definition Threading.h:280
@ Offset
Definition DWP.cpp:577
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
constexpr uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
Definition MathExtras.h:208
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:541
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
Op::Description Desc
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg)
Return the SubReg component from REG_SEQUENCE.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
Definition SIInstrInfo.h:46
constexpr bool has_single_bit(T Value) noexcept
Definition bit.h:149
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
MachineInstr * getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, const MachineRegisterInfo &MRI)
Return the defining instruction for a given reg:subreg pair skipping copy like instructions and subre...
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI VirtRegInfo AnalyzeVirtRegInBundle(MachineInstr &MI, Register Reg, SmallVectorImpl< std::pair< MachineInstr *, unsigned > > *Ops=nullptr)
AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses a virtual register.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
Definition SIInstrInfo.h:54
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
Definition SIInstrInfo.h:42
constexpr unsigned BitWidth
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition SIInstrInfo.h:50
constexpr T reverseBits(T Val)
Reverse the bits in Val.
Definition MathExtras.h:119
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:567
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
constexpr RegState getUndefRegState(bool B)
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
Definition Uniformity.h:18
@ AlwaysUniform
The result value is always uniform.
Definition Uniformity.h:23
@ NeverUniform
The result value can never be assumed to be uniform.
Definition Uniformity.h:26
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
Definition SIInstrInfo.h:65
bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI)
Return false if EXEC is not changed between the def of VReg at DefMI and all its uses.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr bool all() const
Definition LaneBitmask.h:54
SparseBitVector AliveBlocks
AliveBlocks - Set of blocks in which this value is alive completely through.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:129
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Utility to store machine instructions worklist.
Definition SIInstrInfo.h:69
MachineInstr * top() const
Definition SIInstrInfo.h:74
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
Definition SIInstrInfo.h:92
void insert(MachineInstr *MI)
A pair composed of a register and a sub-register index.
VirtRegInfo - Information about a virtual register used by a set of operands.
bool Reads
Reads - One of the operands read the virtual register.
bool Writes
Writes - One of the operands writes the virtual register.