LLVM 24.0.0git
SIInstrInfo.cpp
Go to the documentation of this file.
1//===- SIInstrInfo.cpp - SI Instruction Information ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// SI Implementation of TargetInstrInfo.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SIInstrInfo.h"
15#include "AMDGPU.h"
16#include "AMDGPUInstrInfo.h"
17#include "AMDGPULaneMaskUtils.h"
18#include "GCNHazardRecognizer.h"
19#include "GCNSubtarget.h"
22#include "llvm/ADT/STLExtras.h"
34#include "llvm/IR/IntrinsicsAMDGPU.h"
35#include "llvm/MC/MCContext.h"
38#include <tuple>
39
40using namespace llvm;
41
42#define DEBUG_TYPE "si-instr-info"
43
44#define GET_INSTRINFO_CTOR_DTOR
45#include "AMDGPUGenInstrInfo.inc"
46
47namespace llvm::AMDGPU {
48#define GET_D16ImageDimIntrinsics_IMPL
49#define GET_ImageDimIntrinsicTable_IMPL
50#define GET_RsrcIntrinsics_IMPL
51#include "AMDGPUGenSearchableTables.inc"
52} // namespace llvm::AMDGPU
53
54// Must be at least 4 to be able to branch over minimum unconditional branch
55// code. This is only for making it possible to write reasonably small tests for
56// long branches.
58BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16),
59 cl::desc("Restrict range of branch instructions (DEBUG)"));
60
62 "amdgpu-fix-16-bit-physreg-copies",
63 cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"),
64 cl::init(true),
66
68 : AMDGPUGenInstrInfo(ST, RI, AMDGPU::ADJCALLSTACKUP,
69 AMDGPU::ADJCALLSTACKDOWN),
70 RI(ST), ST(ST) {
71 SchedModel.init(&ST);
72}
73
74//===----------------------------------------------------------------------===//
75// TargetInstrInfo callbacks
76//===----------------------------------------------------------------------===//
77
78static unsigned getNumOperandsNoGlue(SDNode *Node) {
79 unsigned N = Node->getNumOperands();
80 while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
81 --N;
82 return N;
83}
84
85/// Returns true if both nodes have the same value for the given
86/// operand \p Op, or if both nodes do not have this operand.
88 AMDGPU::OpName OpName) {
89 unsigned Opc0 = N0->getMachineOpcode();
90 unsigned Opc1 = N1->getMachineOpcode();
91
92 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName);
93 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName);
94
95 if (Op0Idx == -1 && Op1Idx == -1)
96 return true;
97
98
99 if ((Op0Idx == -1 && Op1Idx != -1) ||
100 (Op1Idx == -1 && Op0Idx != -1))
101 return false;
102
103 // getNamedOperandIdx returns the index for the MachineInstr's operands,
104 // which includes the result as the first operand. We are indexing into the
105 // MachineSDNode's operands, so we need to skip the result operand to get
106 // the real index.
107 --Op0Idx;
108 --Op1Idx;
109
110 return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx);
111}
112
113static bool canRemat(const MachineInstr &MI) {
114
118 return true;
119
120 if (SIInstrInfo::isSMRD(MI)) {
121 return !MI.memoperands_empty() &&
122 llvm::all_of(MI.memoperands(), [](const MachineMemOperand *MMO) {
123 return MMO->isLoad() && MMO->isInvariant();
124 });
125 }
126
127 return false;
128}
129
130// Split relocation flags for 64-bit global-address materialization into a
131// common base and the hi/lo relocation variants.
132static std::tuple<unsigned, unsigned, unsigned>
134 const MachineOperand &SrcOp) {
135 unsigned SrcFlags = SrcOp.getTargetFlags();
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 = SIInstrInfo::MO_ABS32_LO;
140 unsigned HiReloc = SIInstrInfo::MO_ABS32_HI;
141
142 if (SrcFlags & SIInstrInfo::MO_REL32) {
143 LoReloc = SIInstrInfo::MO_REL32_LO;
144 HiReloc = SIInstrInfo::MO_REL32_HI;
145 } else if (SrcFlags & SIInstrInfo::MO_GOTPCREL32_LO) {
148 } else if (SrcFlags & SIInstrInfo::MO_GOTPCREL64) {
149 // For 64-bit GOT-relative, use the 64-bit relocation.
152 }
153
154 unsigned BaseFlags =
159
160 return std::make_tuple(BaseFlags, LoReloc, HiReloc);
161}
162
164 const MachineInstr &MI) const {
165
166 if (canRemat(MI)) {
167 // Normally VALU use of exec would block the rematerialization, but that
168 // is OK in this case to have an implicit exec read as all VALU do.
169 // We really want all of the generic logic for this except for this.
170
171 // Another potential implicit use is mode register. The core logic of
172 // the RA will not attempt rematerialization if mode is set anywhere
173 // in the function, otherwise it is safe since mode is not changed.
174
175 // There is difference to generic method which does not allow
176 // rematerialization if there are virtual register uses. We allow this,
177 // therefore this method includes SOP instructions as well.
178 if (!MI.hasImplicitDef() &&
179 MI.getNumImplicitOperands() == MI.getDesc().implicit_uses().size() &&
180 !MI.mayRaiseFPException())
181 return true;
182 }
183
184 // Everything below copied from TargetInstrInfo::isReMaterializableImpl. The
185 // only difference is that we allow operations that perform read-modify-write
186 // on sub-registers.
187
188 // Remat clients assume operand 0 is the defined register.
189 if (!MI.getNumOperands() || !MI.getOperand(0).isReg())
190 return false;
191 Register DefReg = MI.getOperand(0).getReg();
192
193 const MachineFunction &MF = *MI.getMF();
194
195 // A load from a fixed stack slot can be rematerialized. This may be
196 // redundant with subsequent checks, but it's target-independent,
197 // simple, and a common case.
198 int FrameIdx = 0;
199 if (isLoadFromStackSlot(MI, FrameIdx) &&
201 return true;
202
203 // Avoid instructions obviously unsafe for remat.
204 if (MI.isNotDuplicable() || MI.mayStore() || MI.mayRaiseFPException() ||
205 MI.hasUnmodeledSideEffects())
206 return false;
207
208 // Don't remat inline asm. We have no idea how expensive it is
209 // even if it's side effect free.
210 if (MI.isInlineAsm())
211 return false;
212
213 // Avoid instructions which load from potentially varying memory.
214 if (MI.mayLoad() && !MI.isDereferenceableInvariantLoad())
215 return false;
216
217 const MachineRegisterInfo &MRI = MF.getRegInfo();
218
219 // If any of the registers accessed are non-constant, conservatively assume
220 // the instruction is not rematerializable.
221 for (const MachineOperand &MO : MI.operands()) {
222 if (!MO.isReg())
223 continue;
224 Register Reg = MO.getReg();
225 if (Reg == 0)
226 continue;
227
228 // Check for a well-behaved physical register.
229 if (Reg.isPhysical()) {
230 if (MO.isUse()) {
231 // If the physreg has no defs anywhere, it's just an ambient register
232 // and we can freely move its uses. Alternatively, if it's allocatable,
233 // it could get allocated to something with a def during allocation.
234 if (!MRI.isConstantPhysReg(Reg))
235 return false;
236 } else {
237 // A physreg def. We can't remat it.
238 return false;
239 }
240 continue;
241 }
242
243 // Only allow one virtual-register def. There may be multiple defs of the
244 // same virtual register, though.
245 if (MO.isDef() && Reg != DefReg)
246 return false;
247 }
248
249 return true;
250}
251
252// Returns true if the result of a VALU instruction depends on exec.
253bool SIInstrInfo::resultDependsOnExec(const MachineInstr &MI) const {
254 assert(isVALU(MI, /*AllowLDSDMA=*/true));
255
256 // If it is convergent it depends on EXEC.
257 if (MI.isConvergent())
258 return true;
259
260 // If it defines SGPR it depends on EXEC
261 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
262 for (const MachineOperand &Def : MI.defs()) {
263 if (!Def.isReg())
264 continue;
265
266 Register Reg = Def.getReg();
267 if (Reg && RI.isSGPRReg(MRI, Reg))
268 return true;
269 }
270
271 return false;
272}
273
275 // Any implicit use of exec by VALU is not a real register read.
276 return MO.getReg() == AMDGPU::EXEC && MO.isImplicit() &&
277 isVALU(*MO.getParent(), /*AllowLDSDMA=*/true) &&
278 !resultDependsOnExec(*MO.getParent());
279}
280
282 MachineBasicBlock *SuccToSinkTo,
283 MachineCycleInfo *CI) const {
284 // Allow sinking if MI edits lane mask (divergent i1 in sgpr).
285 if (MI.getOpcode() == AMDGPU::SI_IF_BREAK)
286 return true;
287
288 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
289 // Check if sinking of MI would create temporal divergent use.
290 for (auto Op : MI.uses()) {
291 if (Op.isReg() && Op.getReg().isVirtual() &&
292 RI.isSGPRClass(MRI.getRegClass(Op.getReg()))) {
293 MachineInstr *SgprDef = MRI.getVRegDef(Op.getReg());
294
295 // SgprDef defined inside cycle
296 CycleRef FromCycle = CI->getCycle(SgprDef->getParent());
297 if (!FromCycle)
298 continue;
299
300 CycleRef ToCycle = CI->getCycle(SuccToSinkTo);
301 // Check if there is a FromCycle that contains SgprDef's basic block but
302 // does not contain SuccToSinkTo and also has divergent exit condition.
303 while (FromCycle && !(ToCycle && CI->contains(FromCycle, ToCycle))) {
305 CI->getExitingBlocks(FromCycle, ExitingBlocks);
306
307 // FromCycle has divergent exit condition.
308 for (MachineBasicBlock *ExitingBlock : ExitingBlocks) {
309 if (hasDivergentBranch(ExitingBlock))
310 return false;
311 }
312
313 FromCycle = CI->getParentCycle(FromCycle);
314 }
315 }
316 }
317
318 return true;
319}
320
322 int64_t &Offset0,
323 int64_t &Offset1) const {
324 if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode())
325 return false;
326
327 unsigned Opc0 = Load0->getMachineOpcode();
328 unsigned Opc1 = Load1->getMachineOpcode();
329
330 // Make sure both are actually loads.
331 if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad())
332 return false;
333
334 // A mayLoad instruction without a def is not a load. Likely a prefetch.
335 if (!get(Opc0).getNumDefs() || !get(Opc1).getNumDefs())
336 return false;
337
338 if (isDS(Opc0) && isDS(Opc1)) {
339
340 // FIXME: Handle this case:
341 if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1))
342 return false;
343
344 // Check base reg.
345 if (Load0->getOperand(0) != Load1->getOperand(0))
346 return false;
347
348 // Skip read2 / write2 variants for simplicity.
349 // TODO: We should report true if the used offsets are adjacent (excluded
350 // st64 versions).
351 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
352 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
353 if (Offset0Idx == -1 || Offset1Idx == -1)
354 return false;
355
356 // XXX - be careful of dataless loads
357 // getNamedOperandIdx returns the index for MachineInstrs. Since they
358 // include the output in the operand list, but SDNodes don't, we need to
359 // subtract the index by one.
360 Offset0Idx -= get(Opc0).NumDefs;
361 Offset1Idx -= get(Opc1).NumDefs;
362 Offset0 = Load0->getConstantOperandVal(Offset0Idx);
363 Offset1 = Load1->getConstantOperandVal(Offset1Idx);
364 return true;
365 }
366
367 if (isSMRD(Opc0) && isSMRD(Opc1)) {
368 // Skip time and cache invalidation instructions.
369 if (!AMDGPU::hasNamedOperand(Opc0, AMDGPU::OpName::sbase) ||
370 !AMDGPU::hasNamedOperand(Opc1, AMDGPU::OpName::sbase))
371 return false;
372
373 unsigned NumOps = getNumOperandsNoGlue(Load0);
374 if (NumOps != getNumOperandsNoGlue(Load1))
375 return false;
376
377 // Check base reg.
378 if (Load0->getOperand(0) != Load1->getOperand(0))
379 return false;
380
381 // Match register offsets, if both register and immediate offsets present.
382 assert(NumOps == 4 || NumOps == 5);
383 if (NumOps == 5 && Load0->getOperand(1) != Load1->getOperand(1))
384 return false;
385
386 const ConstantSDNode *Load0Offset =
388 const ConstantSDNode *Load1Offset =
390
391 if (!Load0Offset || !Load1Offset)
392 return false;
393
394 Offset0 = Load0Offset->getZExtValue();
395 Offset1 = Load1Offset->getZExtValue();
396 return true;
397 }
398
399 // MUBUF and MTBUF can access the same addresses.
400 if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) {
401
402 // MUBUF and MTBUF have vaddr at different indices.
403 if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) ||
404 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) ||
405 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc))
406 return false;
407
408 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
409 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
410
411 if (OffIdx0 == -1 || OffIdx1 == -1)
412 return false;
413
414 // getNamedOperandIdx returns the index for MachineInstrs. Since they
415 // include the output in the operand list, but SDNodes don't, we need to
416 // subtract the index by one.
417 OffIdx0 -= get(Opc0).NumDefs;
418 OffIdx1 -= get(Opc1).NumDefs;
419
420 SDValue Off0 = Load0->getOperand(OffIdx0);
421 SDValue Off1 = Load1->getOperand(OffIdx1);
422
423 // The offset might be a FrameIndexSDNode.
424 if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1))
425 return false;
426
427 Offset0 = Off0->getAsZExtVal();
428 Offset1 = Off1->getAsZExtVal();
429 return true;
430 }
431
432 return false;
433}
434
435static bool isStride64(unsigned Opc) {
436 switch (Opc) {
437 case AMDGPU::DS_READ2ST64_B32:
438 case AMDGPU::DS_READ2ST64_B64:
439 case AMDGPU::DS_WRITE2ST64_B32:
440 case AMDGPU::DS_WRITE2ST64_B64:
441 return true;
442 default:
443 return false;
444 }
445}
446
449 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
450 const TargetRegisterInfo *TRI) const {
451 if (!LdSt.mayLoadOrStore())
452 return false;
453
454 unsigned Opc = LdSt.getOpcode();
455 OffsetIsScalable = false;
456 const MachineOperand *BaseOp, *OffsetOp;
457 int DataOpIdx;
458
459 if (isDS(LdSt)) {
460 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr);
461 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
462 if (OffsetOp) {
463 // Normal, single offset LDS instruction.
464 if (!BaseOp) {
465 // DS_CONSUME/DS_APPEND use M0 for the base address.
466 // TODO: find the implicit use operand for M0 and use that as BaseOp?
467 return false;
468 }
469 BaseOps.push_back(BaseOp);
470 Offset = OffsetOp->getImm();
471 // Get appropriate operand, and compute width accordingly.
472 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
473 if (DataOpIdx == -1)
474 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
475 if (Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
476 Width = LocationSize::precise(64);
477 else
478 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
479 } else {
480 // The 2 offset instructions use offset0 and offset1 instead. We can treat
481 // these as a load with a single offset if the 2 offsets are consecutive.
482 // We will use this for some partially aligned loads.
483 const MachineOperand *Offset0Op =
484 getNamedOperand(LdSt, AMDGPU::OpName::offset0);
485 const MachineOperand *Offset1Op =
486 getNamedOperand(LdSt, AMDGPU::OpName::offset1);
487
488 unsigned Offset0 = Offset0Op->getImm() & 0xff;
489 unsigned Offset1 = Offset1Op->getImm() & 0xff;
490 if (Offset0 + 1 != Offset1)
491 return false;
492
493 // Each of these offsets is in element sized units, so we need to convert
494 // to bytes of the individual reads.
495
496 unsigned EltSize;
497 if (LdSt.mayLoad())
498 EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16;
499 else {
500 assert(LdSt.mayStore());
501 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
502 EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8;
503 }
504
505 if (isStride64(Opc))
506 EltSize *= 64;
507
508 BaseOps.push_back(BaseOp);
509 Offset = EltSize * Offset0;
510 // Get appropriate operand(s), and compute width accordingly.
511 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
512 if (DataOpIdx == -1) {
513 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
514 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
515 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
516 Width = LocationSize::precise(
517 Width.getValue() + TypeSize::getFixed(getOpSize(LdSt, DataOpIdx)));
518 } else {
519 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
520 }
521 }
522 return true;
523 }
524
525 if (isMUBUF(LdSt) || isMTBUF(LdSt)) {
526 const MachineOperand *RSrc = getNamedOperand(LdSt, AMDGPU::OpName::srsrc);
527 if (!RSrc) // e.g. BUFFER_WBINVL1_VOL
528 return false;
529 BaseOps.push_back(RSrc);
530 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
531 if (BaseOp && !BaseOp->isFI())
532 BaseOps.push_back(BaseOp);
533 const MachineOperand *OffsetImm =
534 getNamedOperand(LdSt, AMDGPU::OpName::offset);
535 Offset = OffsetImm->getImm();
536 const MachineOperand *SOffset =
537 getNamedOperand(LdSt, AMDGPU::OpName::soffset);
538 if (SOffset) {
539 if (SOffset->isReg())
540 BaseOps.push_back(SOffset);
541 else
542 Offset += SOffset->getImm();
543 }
544 // Get appropriate operand, and compute width accordingly.
545 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
546 if (DataOpIdx == -1)
547 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
548 if (DataOpIdx == -1) // LDS DMA
549 return false;
550 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
551 return true;
552 }
553
554 if (isImage(LdSt)) {
555 auto RsrcOpName =
556 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
557 int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RsrcOpName);
558 BaseOps.push_back(&LdSt.getOperand(SRsrcIdx));
559 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
560 if (VAddr0Idx >= 0) {
561 // GFX10 possible NSA encoding.
562 for (int I = VAddr0Idx; I < SRsrcIdx; ++I)
563 BaseOps.push_back(&LdSt.getOperand(I));
564 } else {
565 BaseOps.push_back(getNamedOperand(LdSt, AMDGPU::OpName::vaddr));
566 }
567 Offset = 0;
568 // Get appropriate operand, and compute width accordingly.
569 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
570 if (DataOpIdx == -1)
571 return false; // no return sampler
572 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
573 return true;
574 }
575
576 if (isSMRD(LdSt)) {
577 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::sbase);
578 if (!BaseOp) // e.g. S_MEMTIME
579 return false;
580 BaseOps.push_back(BaseOp);
581 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
582 Offset = OffsetOp ? OffsetOp->getImm() : 0;
583 // Get appropriate operand, and compute width accordingly.
584 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
585 if (DataOpIdx == -1)
586 return false;
587 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
588 return true;
589 }
590
591 if (isFLAT(LdSt)) {
592 // Instructions have either vaddr or saddr or both or none.
593 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
594 if (BaseOp)
595 BaseOps.push_back(BaseOp);
596 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr);
597 if (BaseOp)
598 BaseOps.push_back(BaseOp);
599 Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm();
600 // Get appropriate operand, and compute width accordingly.
601 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
602 if (DataOpIdx == -1)
603 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
604 if (DataOpIdx == -1) // LDS DMA
605 return false;
606 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
607 return true;
608 }
609
610 return false;
611}
612
613static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
615 const MachineInstr &MI2,
617 // Only examine the first "base" operand of each instruction, on the
618 // assumption that it represents the real base address of the memory access.
619 // Other operands are typically offsets or indices from this base address.
620 if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
621 return true;
622
623 if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
624 return false;
625
626 auto *MO1 = *MI1.memoperands_begin();
627 auto *MO2 = *MI2.memoperands_begin();
628 if (MO1->getAddrSpace() != MO2->getAddrSpace())
629 return false;
630
631 const auto *Base1 = MO1->getValue();
632 const auto *Base2 = MO2->getValue();
633 if (!Base1 || !Base2)
634 return false;
635 Base1 = getUnderlyingObject(Base1);
636 Base2 = getUnderlyingObject(Base2);
637
638 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
639 return false;
640
641 return Base1 == Base2;
642}
643
645 int64_t Offset1, bool OffsetIsScalable1,
647 int64_t Offset2, bool OffsetIsScalable2,
648 unsigned ClusterSize,
649 unsigned NumBytes) const {
650 // If the mem ops (to be clustered) do not have the same base ptr, then they
651 // should not be clustered
652 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;
653 if (!BaseOps1.empty() && !BaseOps2.empty()) {
654 const MachineInstr &FirstLdSt = *BaseOps1.front()->getParent();
655 const MachineInstr &SecondLdSt = *BaseOps2.front()->getParent();
656 if (!memOpsHaveSameBasePtr(FirstLdSt, BaseOps1, SecondLdSt, BaseOps2))
657 return false;
658
659 const SIMachineFunctionInfo *MFI =
660 FirstLdSt.getMF()->getInfo<SIMachineFunctionInfo>();
661 MaxMemoryClusterDWords = MFI->getMaxMemoryClusterDWords();
662 } else if (!BaseOps1.empty() || !BaseOps2.empty()) {
663 // If only one base op is empty, they do not have the same base ptr
664 return false;
665 }
666
667 // In order to avoid register pressure, on an average, the number of DWORDS
668 // loaded together by all clustered mem ops should not exceed
669 // MaxMemoryClusterDWords. This is an empirical value based on certain
670 // observations and performance related experiments.
671 // The good thing about this heuristic is - it avoids clustering of too many
672 // sub-word loads, and also avoids clustering of wide loads. Below is the
673 // brief summary of how the heuristic behaves for various `LoadSize` when
674 // MaxMemoryClusterDWords is 8.
675 //
676 // (1) 1 <= LoadSize <= 4: cluster at max 8 mem ops
677 // (2) 5 <= LoadSize <= 8: cluster at max 4 mem ops
678 // (3) 9 <= LoadSize <= 12: cluster at max 2 mem ops
679 // (4) 13 <= LoadSize <= 16: cluster at max 2 mem ops
680 // (5) LoadSize >= 17: do not cluster
681 const unsigned LoadSize = NumBytes / ClusterSize;
682 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
683 return NumDWords <= MaxMemoryClusterDWords;
684}
685
686// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
687// the first 16 loads will be interleaved with the stores, and the next 16 will
688// be clustered as expected. It should really split into 2 16 store batches.
689//
690// Loads are clustered until this returns false, rather than trying to schedule
691// groups of stores. This also means we have to deal with saying different
692// address space loads should be clustered, and ones which might cause bank
693// conflicts.
694//
695// This might be deprecated so it might not be worth that much effort to fix.
697 int64_t Offset0, int64_t Offset1,
698 unsigned NumLoads) const {
699 assert(Offset1 > Offset0 &&
700 "Second offset should be larger than first offset!");
701 // If we have less than 16 loads in a row, and the offsets are within 64
702 // bytes, then schedule together.
703
704 // A cacheline is 64 bytes (for global memory).
705 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
706}
707
710 const DebugLoc &DL, MCRegister DestReg,
711 MCRegister SrcReg, bool KillSrc,
712 const char *Msg = "illegal VGPR to SGPR copy") {
713 MachineFunction *MF = MBB.getParent();
714
717
718 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg)
719 .addReg(SrcReg, getKillRegState(KillSrc));
720}
721
722/// Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908. It is not
723/// possible to have a direct copy in these cases on GFX908, so an intermediate
724/// VGPR copy is required.
727 const DebugLoc &DL, MCRegister DestReg,
728 MCRegister SrcReg, bool KillSrc,
729 RegScavenger &RS, bool RegsOverlap,
730 Register ImpUseSuperReg = Register()) {
731 assert((TII.getSubtarget().hasMAIInsts() &&
732 !TII.getSubtarget().hasGFX90AInsts()) &&
733 "Expected GFX908 subtarget.");
734
735 assert((AMDGPU::SReg_32RegClass.contains(SrcReg) ||
736 AMDGPU::AGPR_32RegClass.contains(SrcReg)) &&
737 "Source register of the copy should be either an SGPR or an AGPR.");
738
739 assert(AMDGPU::AGPR_32RegClass.contains(DestReg) &&
740 "Destination register of the copy should be an AGPR.");
741
742 const SIRegisterInfo &RI = TII.getRegisterInfo();
743
744 // First try to find defining accvgpr_write to avoid temporary registers.
745 // In the case of copies of overlapping AGPRs, we conservatively do not
746 // reuse previous accvgpr_writes. Otherwise, we may incorrectly pick up
747 // an accvgpr_write used for this same copy due to implicit-defs
748 if (!RegsOverlap) {
749 for (auto Def = MI, E = MBB.begin(); Def != E; ) {
750 --Def;
751
752 if (!Def->modifiesRegister(SrcReg, &RI))
753 continue;
754
755 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
756 Def->getOperand(0).getReg() != SrcReg)
757 break;
758
759 MachineOperand &DefOp = Def->getOperand(1);
760 assert(DefOp.isReg() || DefOp.isImm());
761
762 if (DefOp.isReg()) {
763 bool SafeToPropagate = true;
764 // Check that register source operand is not clobbered before MI.
765 // Immediate operands are always safe to propagate.
766 for (auto I = Def; I != MI && SafeToPropagate; ++I)
767 if (I->modifiesRegister(DefOp.getReg(), &RI))
768 SafeToPropagate = false;
769
770 if (!SafeToPropagate)
771 break;
772
773 for (auto I = Def; I != MI; ++I)
774 I->clearRegisterKills(DefOp.getReg(), &RI);
775 }
776
777 MachineInstrBuilder Builder =
778 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64),
779 DestReg)
780 .add(DefOp);
781
782 if (ImpUseSuperReg) {
783 Builder.addReg(ImpUseSuperReg,
785 }
786
787 return;
788 }
789 }
790
791 RS.enterBasicBlockEnd(MBB);
792 RS.backward(std::next(MI));
793
794 // Ideally we want to have three registers for a long reg_sequence copy
795 // to hide 2 waitstates between v_mov_b32 and accvgpr_write.
796 unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass,
797 *MBB.getParent());
798
799 // Registers in the sequence are allocated contiguously so we can just
800 // use register number to pick one of three round-robin temps.
801 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
802 Register Tmp =
803 MBB.getParent()->getInfo<SIMachineFunctionInfo>()->getVGPRForAGPRCopy();
804 assert(MBB.getParent()->getRegInfo().isReserved(Tmp) &&
805 "VGPR used for an intermediate copy should have been reserved.");
806
807 // Only loop through if there are any free registers left. We don't want to
808 // spill.
809 while (RegNo--) {
810 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI,
811 /* RestoreAfter */ false, 0,
812 /* AllowSpill */ false);
813 if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs)
814 break;
815 Tmp = Tmp2;
816 RS.setRegUsed(Tmp);
817 }
818
819 // Insert copy to temporary VGPR.
820 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
821 if (AMDGPU::AGPR_32RegClass.contains(SrcReg)) {
822 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
823 } else {
824 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
825 }
826
827 MachineInstrBuilder UseBuilder = BuildMI(MBB, MI, DL, TII.get(TmpCopyOp), Tmp)
828 .addReg(SrcReg, getKillRegState(KillSrc));
829 if (ImpUseSuperReg) {
830 UseBuilder.addReg(ImpUseSuperReg,
832 }
833
834 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
835 .addReg(Tmp, RegState::Kill);
836}
837
840 MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
841 const TargetRegisterClass *RC, bool Forward) {
842 const SIRegisterInfo &RI = TII.getRegisterInfo();
843 ArrayRef<int16_t> BaseIndices = RI.getRegSplitParts(RC, 4);
845 MachineInstr *FirstMI = nullptr, *LastMI = nullptr;
846
847 for (unsigned Idx = 0; Idx < BaseIndices.size(); ++Idx) {
848 int16_t SubIdx = BaseIndices[Idx];
849 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
850 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
851 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
852 unsigned Opcode = AMDGPU::S_MOV_B32;
853
854 // Is SGPR aligned? If so try to combine with next.
855 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
856 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
857 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.size())) {
858 // Can use SGPR64 copy
859 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
860 SubIdx = RI.getSubRegFromChannel(Channel, 2);
861 DestSubReg = RI.getSubReg(DestReg, SubIdx);
862 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
863 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
864 Opcode = AMDGPU::S_MOV_B64;
865 Idx++;
866 }
867
868 LastMI = BuildMI(MBB, I, DL, TII.get(Opcode), DestSubReg)
869 .addReg(SrcSubReg)
870 .addReg(SrcReg, RegState::Implicit);
871
872 if (!FirstMI)
873 FirstMI = LastMI;
874
875 if (!Forward)
876 I--;
877 }
878
879 assert(FirstMI && LastMI);
880 if (!Forward)
881 std::swap(FirstMI, LastMI);
882
883 if (KillSrc)
884 LastMI->addRegisterKilled(SrcReg, &RI);
885}
886
889 const DebugLoc &DL, Register DestReg,
890 Register SrcReg, bool KillSrc, bool RenamableDest,
891 bool RenamableSrc) const {
892 const TargetRegisterClass *RC = RI.getPhysRegBaseClass(DestReg);
893 unsigned Size = RI.getRegSizeInBits(*RC);
894 const TargetRegisterClass *SrcRC = RI.getPhysRegBaseClass(SrcReg);
895 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
896
897 // The rest of copyPhysReg assumes Src and Dst size are the same size.
898 // TODO-GFX11_16BIT If all true 16 bit instruction patterns are completed can
899 // we remove Fix16BitCopies and this code block?
900 if (Fix16BitCopies) {
901 if (((Size == 16) != (SrcSize == 16))) {
902 // Non-VGPR Src and Dst will later be expanded back to 32 bits.
903 assert(ST.useRealTrue16Insts());
904 Register &RegToFix = (Size == 32) ? DestReg : SrcReg;
905 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
906 RegToFix = SubReg;
907
908 if (DestReg == SrcReg) {
909 // Identity copy. Insert empty bundle since ExpandPostRA expects an
910 // instruction here.
911 BuildMI(MBB, MI, DL, get(AMDGPU::BUNDLE));
912 return;
913 }
914 RC = RI.getPhysRegBaseClass(DestReg);
915 Size = RI.getRegSizeInBits(*RC);
916 SrcRC = RI.getPhysRegBaseClass(SrcReg);
917 SrcSize = RI.getRegSizeInBits(*SrcRC);
918 }
919 }
920
921 if (RC == &AMDGPU::VGPR_32RegClass) {
922 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
923 AMDGPU::SReg_32RegClass.contains(SrcReg) ||
924 AMDGPU::AGPR_32RegClass.contains(SrcReg));
925 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
926 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
927 BuildMI(MBB, MI, DL, get(Opc), DestReg)
928 .addReg(SrcReg, getKillRegState(KillSrc));
929 return;
930 }
931
932 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
933 RC == &AMDGPU::SReg_32RegClass) {
934 if (SrcReg == AMDGPU::SCC) {
935 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg)
936 .addImm(1)
937 .addImm(0);
938 return;
939 }
940
941 if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) {
942 if (DestReg == AMDGPU::VCC_LO) {
943 // FIXME: Hack until VReg_1 removed.
944 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
945 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
946 .addImm(0)
947 .addReg(SrcReg, getKillRegState(KillSrc));
948 return;
949 }
950
951 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
952 return;
953 }
954
955 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
956 .addReg(SrcReg, getKillRegState(KillSrc));
957 return;
958 }
959
960 if (RC == &AMDGPU::SReg_64RegClass) {
961 if (SrcReg == AMDGPU::SCC) {
962 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B64), DestReg)
963 .addImm(1)
964 .addImm(0);
965 return;
966 }
967
968 if (!AMDGPU::SReg_64_EncodableRegClass.contains(SrcReg)) {
969 if (DestReg == AMDGPU::VCC) {
970 // FIXME: Hack until VReg_1 removed.
971 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
972 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
973 .addImm(0)
974 .addReg(SrcReg, getKillRegState(KillSrc));
975 return;
976 }
977
978 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
979 return;
980 }
981
982 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
983 .addReg(SrcReg, getKillRegState(KillSrc));
984 return;
985 }
986
987 if (DestReg == AMDGPU::SCC) {
988 // Copying 64-bit or 32-bit sources to SCC barely makes sense,
989 // but SelectionDAG emits such copies for i1 sources.
990 if (AMDGPU::SReg_64RegClass.contains(SrcReg)) {
991 // This copy can only be produced by patterns
992 // with explicit SCC, which are known to be enabled
993 // only for subtargets with S_CMP_LG_U64 present.
994 assert(ST.hasScalarCompareEq64());
995 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U64))
996 .addReg(SrcReg, getKillRegState(KillSrc))
997 .addImm(0);
998 } else {
999 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
1000 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32))
1001 .addReg(SrcReg, getKillRegState(KillSrc))
1002 .addImm(0);
1003 }
1004
1005 return;
1006 }
1007
1008 if (RC == &AMDGPU::AGPR_32RegClass) {
1009 if (AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
1010 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1011 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
1012 .addReg(SrcReg, getKillRegState(KillSrc));
1013 return;
1014 }
1015
1016 if (AMDGPU::AGPR_32RegClass.contains(SrcReg) && ST.hasGFX90AInsts()) {
1017 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_MOV_B32), DestReg)
1018 .addReg(SrcReg, getKillRegState(KillSrc));
1019 return;
1020 }
1021
1022 // FIXME: Pass should maintain scavenger to avoid scan through the block on
1023 // every AGPR spill.
1024 RegScavenger RS;
1025 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1026 indirectCopyToAGPR(*this, MBB, MI, DL, DestReg, SrcReg, KillSrc, RS, Overlap);
1027 return;
1028 }
1029
1030 if (Size == 16) {
1031 assert(AMDGPU::VGPR_16RegClass.contains(SrcReg) ||
1032 AMDGPU::SReg_LO16RegClass.contains(SrcReg) ||
1033 AMDGPU::AGPR_LO16RegClass.contains(SrcReg));
1034
1035 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1036 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1037 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1038 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1039 bool DstLow = !AMDGPU::isHi16Reg(DestReg, RI);
1040 bool SrcLow = !AMDGPU::isHi16Reg(SrcReg, RI);
1041 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1042 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1043
1044 if (IsSGPRDst) {
1045 if (!IsSGPRSrc) {
1046 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1047 return;
1048 }
1049
1050 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), NewDestReg)
1051 .addReg(NewSrcReg, getKillRegState(KillSrc));
1052 return;
1053 }
1054
1055 if (IsAGPRDst || IsAGPRSrc) {
1056 if (!DstLow || !SrcLow) {
1057 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1058 "Cannot use hi16 subreg with an AGPR!");
1059 }
1060
1061 copyPhysReg(MBB, MI, DL, NewDestReg, NewSrcReg, KillSrc);
1062 return;
1063 }
1064
1065 if (ST.useRealTrue16Insts()) {
1066 if (IsSGPRSrc) {
1067 assert(SrcLow);
1068 SrcReg = NewSrcReg;
1069 }
1070 // Use the smaller instruction encoding if possible.
1071 if (AMDGPU::VGPR_16_Lo128RegClass.contains(DestReg) &&
1072 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.contains(SrcReg))) {
1073 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e32), DestReg)
1074 .addReg(SrcReg);
1075 } else {
1076 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e64), DestReg)
1077 .addImm(0) // src0_modifiers
1078 .addReg(SrcReg)
1079 .addImm(0); // op_sel
1080 }
1081 return;
1082 }
1083
1084 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1085 if (!DstLow || !SrcLow) {
1086 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1087 "Cannot use hi16 subreg on VI!");
1088 }
1089
1090 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), NewDestReg)
1091 .addReg(NewSrcReg, getKillRegState(KillSrc));
1092 return;
1093 }
1094
1095 auto MIB = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_sdwa), NewDestReg)
1096 .addImm(0) // src0_modifiers
1097 .addReg(NewSrcReg)
1098 .addImm(0) // clamp
1105 // First implicit operand is $exec.
1106 MIB->tieOperands(0, MIB->getNumOperands() - 1);
1107 return;
1108 }
1109
1110 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1111 if (ST.hasVMovB64Inst()) {
1112 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_e32), DestReg)
1113 .addReg(SrcReg, getKillRegState(KillSrc));
1114 return;
1115 }
1116 if (ST.hasPkMovB32()) {
1117 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestReg)
1119 .addReg(SrcReg)
1121 .addReg(SrcReg)
1122 .addImm(0) // op_sel_lo
1123 .addImm(0) // op_sel_hi
1124 .addImm(0) // neg_lo
1125 .addImm(0) // neg_hi
1126 .addImm(0) // clamp
1127 .addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
1128 return;
1129 }
1130 }
1131
1132 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1133 if (RI.isSGPRClass(RC)) {
1134 if (!RI.isSGPRClass(SrcRC)) {
1135 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1136 return;
1137 }
1138 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1139 expandSGPRCopy(*this, MBB, MI, DL, DestReg, SrcReg, CanKillSuperReg, RC,
1140 Forward);
1141 return;
1142 }
1143
1144 unsigned EltSize = 4;
1145 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1146 if (RI.isAGPRClass(RC)) {
1147 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1148 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1149 else if (RI.hasVGPRs(SrcRC) ||
1150 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1151 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1152 else
1153 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1154 } else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1155 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1156 } else if ((Size % 64 == 0) && RI.hasVGPRs(RC) &&
1157 (RI.isProperlyAlignedRC(*RC) &&
1158 (SrcRC == RC || RI.isSGPRClass(SrcRC)))) {
1159 // TODO: In 96-bit case, could do a 64-bit mov and then a 32-bit mov.
1160 if (ST.hasVMovB64Inst()) {
1161 Opcode = AMDGPU::V_MOV_B64_e32;
1162 EltSize = 8;
1163 } else if (ST.hasPkMovB32()) {
1164 Opcode = AMDGPU::V_PK_MOV_B32;
1165 EltSize = 8;
1166 }
1167 }
1168
1169 // For the cases where we need an intermediate instruction/temporary register
1170 // (destination is an AGPR), we need a scavenger.
1171 //
1172 // FIXME: The pass should maintain this for us so we don't have to re-scan the
1173 // whole block for every handled copy.
1174 std::unique_ptr<RegScavenger> RS;
1175 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1176 RS = std::make_unique<RegScavenger>();
1177
1178 ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, EltSize);
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 (unsigned Idx = 0; Idx < SubIndices.size(); ++Idx) {
1186 unsigned SubIdx;
1187 if (Forward)
1188 SubIdx = SubIndices[Idx];
1189 else
1190 SubIdx = SubIndices[SubIndices.size() - Idx - 1];
1191 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1192 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1193 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
1194
1195 bool UseKill = CanKillSuperReg && Idx == SubIndices.size() - 1;
1196
1197 if (Opcode == AMDGPU::INSTRUCTION_LIST_END) {
1198 Register ImpUseSuper = SrcReg;
1199 indirectCopyToAGPR(*this, MBB, MI, DL, DestSubReg, SrcSubReg, UseKill,
1200 *RS, Overlap, ImpUseSuper);
1201 } else if (Opcode == AMDGPU::V_PK_MOV_B32) {
1202 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestSubReg)
1204 .addReg(SrcSubReg)
1206 .addReg(SrcSubReg)
1207 .addImm(0) // op_sel_lo
1208 .addImm(0) // op_sel_hi
1209 .addImm(0) // neg_lo
1210 .addImm(0) // neg_hi
1211 .addImm(0) // clamp
1212 .addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1213 } else {
1214 MachineInstrBuilder Builder =
1215 BuildMI(MBB, MI, DL, get(Opcode), DestSubReg).addReg(SrcSubReg);
1216
1217 Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1218 }
1219 }
1220}
1221
1222int SIInstrInfo::commuteOpcode(unsigned Opcode) const {
1223 int32_t NewOpc;
1224
1225 // Try to map original to commuted opcode
1226 NewOpc = AMDGPU::getCommuteRev(Opcode);
1227 if (NewOpc != -1)
1228 // Check if the commuted (REV) opcode exists on the target.
1229 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1230
1231 // Try to map commuted to original opcode
1232 NewOpc = AMDGPU::getCommuteOrig(Opcode);
1233 if (NewOpc != -1)
1234 // Check if the original (non-REV) opcode exists on the target.
1235 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1236
1237 return Opcode;
1238}
1239
1241 const Register Reg,
1242 int64_t &ImmVal) const {
1243 switch (MI.getOpcode()) {
1244 case AMDGPU::V_MOV_B32_e32:
1245 case AMDGPU::S_MOV_B32:
1246 case AMDGPU::S_MOVK_I32:
1247 case AMDGPU::S_MOV_B64:
1248 case AMDGPU::V_MOV_B64_e32:
1249 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1250 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1251 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1252 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1253 case AMDGPU::V_MOV_B64_PSEUDO:
1254 case AMDGPU::V_MOV_B16_t16_e32: {
1255 const MachineOperand &Src0 = MI.getOperand(1);
1256 if (Src0.isImm()) {
1257 ImmVal = Src0.getImm();
1258 return MI.getOperand(0).getReg() == Reg;
1259 }
1260
1261 return false;
1262 }
1263 case AMDGPU::V_MOV_B16_t16_e64: {
1264 const MachineOperand &Src0 = MI.getOperand(2);
1265 if (Src0.isImm() && !MI.getOperand(1).getImm()) {
1266 ImmVal = Src0.getImm();
1267 return MI.getOperand(0).getReg() == Reg;
1268 }
1269
1270 return false;
1271 }
1272 case AMDGPU::S_BREV_B32:
1273 case AMDGPU::V_BFREV_B32_e32:
1274 case AMDGPU::V_BFREV_B32_e64: {
1275 const MachineOperand &Src0 = MI.getOperand(1);
1276 if (Src0.isImm()) {
1277 ImmVal = static_cast<int64_t>(reverseBits<int32_t>(Src0.getImm()));
1278 return MI.getOperand(0).getReg() == Reg;
1279 }
1280
1281 return false;
1282 }
1283 case AMDGPU::S_NOT_B32:
1284 case AMDGPU::V_NOT_B32_e32:
1285 case AMDGPU::V_NOT_B32_e64: {
1286 const MachineOperand &Src0 = MI.getOperand(1);
1287 if (Src0.isImm()) {
1288 ImmVal = static_cast<int64_t>(~static_cast<int32_t>(Src0.getImm()));
1289 return MI.getOperand(0).getReg() == Reg;
1290 }
1291
1292 return false;
1293 }
1294 default:
1295 return false;
1296 }
1297}
1298
1299std::optional<int64_t>
1301 if (Op.isImm())
1302 return Op.getImm();
1303
1304 if (!Op.isReg() || !Op.getReg().isVirtual())
1305 return std::nullopt;
1306 MachineRegisterInfo &MRI = Op.getParent()->getMF()->getRegInfo();
1307 const MachineInstr *Def = MRI.getVRegDef(Op.getReg());
1308 if (Def && Def->isMoveImmediate()) {
1309 const MachineOperand &ImmSrc = Def->getOperand(1);
1310 if (ImmSrc.isImm())
1311 return extractSubregFromImm(ImmSrc.getImm(), Op.getSubReg());
1312 }
1313
1314 return std::nullopt;
1315}
1316
1318
1319 if (RI.isAGPRClass(DstRC))
1320 return AMDGPU::COPY;
1321 if (RI.getRegSizeInBits(*DstRC) == 16) {
1322 // Assume hi bits are unneeded. Only _e64 true16 instructions are legal
1323 // before RA.
1324 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1325 }
1326 if (RI.getRegSizeInBits(*DstRC) == 32)
1327 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1328 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1329 return AMDGPU::S_MOV_B64;
1330 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1331 return AMDGPU::V_MOV_B64_PSEUDO;
1332 return AMDGPU::COPY;
1333}
1334
1335const MCInstrDesc &
1337 bool IsIndirectSrc) const {
1338 if (IsIndirectSrc) {
1339 if (VecSize <= 32) // 4 bytes
1340 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1341 if (VecSize <= 64) // 8 bytes
1342 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1343 if (VecSize <= 96) // 12 bytes
1344 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1345 if (VecSize <= 128) // 16 bytes
1346 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1347 if (VecSize <= 160) // 20 bytes
1348 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1349 if (VecSize <= 192) // 24 bytes
1350 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1351 if (VecSize <= 224) // 28 bytes
1352 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1353 if (VecSize <= 256) // 32 bytes
1354 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1355 if (VecSize <= 288) // 36 bytes
1356 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1357 if (VecSize <= 320) // 40 bytes
1358 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1359 if (VecSize <= 352) // 44 bytes
1360 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1361 if (VecSize <= 384) // 48 bytes
1362 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1363 if (VecSize <= 512) // 64 bytes
1364 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1365 if (VecSize <= 1024) // 128 bytes
1366 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1367
1368 llvm_unreachable("unsupported size for IndirectRegReadGPRIDX pseudos");
1369 }
1370
1371 if (VecSize <= 32) // 4 bytes
1372 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1373 if (VecSize <= 64) // 8 bytes
1374 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1375 if (VecSize <= 96) // 12 bytes
1376 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1377 if (VecSize <= 128) // 16 bytes
1378 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1379 if (VecSize <= 160) // 20 bytes
1380 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1381 if (VecSize <= 192) // 24 bytes
1382 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1383 if (VecSize <= 224) // 28 bytes
1384 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1385 if (VecSize <= 256) // 32 bytes
1386 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1387 if (VecSize <= 288) // 36 bytes
1388 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1389 if (VecSize <= 320) // 40 bytes
1390 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1391 if (VecSize <= 352) // 44 bytes
1392 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1393 if (VecSize <= 384) // 48 bytes
1394 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1395 if (VecSize <= 512) // 64 bytes
1396 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1397 if (VecSize <= 1024) // 128 bytes
1398 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1399
1400 llvm_unreachable("unsupported size for IndirectRegWriteGPRIDX pseudos");
1401}
1402
1403static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize) {
1404 if (VecSize <= 32) // 4 bytes
1405 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1406 if (VecSize <= 64) // 8 bytes
1407 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1408 if (VecSize <= 96) // 12 bytes
1409 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1410 if (VecSize <= 128) // 16 bytes
1411 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1412 if (VecSize <= 160) // 20 bytes
1413 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1414 if (VecSize <= 192) // 24 bytes
1415 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1416 if (VecSize <= 224) // 28 bytes
1417 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1418 if (VecSize <= 256) // 32 bytes
1419 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1420 if (VecSize <= 288) // 36 bytes
1421 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1422 if (VecSize <= 320) // 40 bytes
1423 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1424 if (VecSize <= 352) // 44 bytes
1425 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1426 if (VecSize <= 384) // 48 bytes
1427 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1428 if (VecSize <= 512) // 64 bytes
1429 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1430 if (VecSize <= 1024) // 128 bytes
1431 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1432
1433 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1434}
1435
1436static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize) {
1437 if (VecSize <= 32) // 4 bytes
1438 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1439 if (VecSize <= 64) // 8 bytes
1440 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1441 if (VecSize <= 96) // 12 bytes
1442 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1443 if (VecSize <= 128) // 16 bytes
1444 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1445 if (VecSize <= 160) // 20 bytes
1446 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1447 if (VecSize <= 192) // 24 bytes
1448 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1449 if (VecSize <= 224) // 28 bytes
1450 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1451 if (VecSize <= 256) // 32 bytes
1452 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1453 if (VecSize <= 288) // 36 bytes
1454 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1455 if (VecSize <= 320) // 40 bytes
1456 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1457 if (VecSize <= 352) // 44 bytes
1458 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1459 if (VecSize <= 384) // 48 bytes
1460 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1461 if (VecSize <= 512) // 64 bytes
1462 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1463 if (VecSize <= 1024) // 128 bytes
1464 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1465
1466 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1467}
1468
1469static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize) {
1470 if (VecSize <= 64) // 8 bytes
1471 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1472 if (VecSize <= 128) // 16 bytes
1473 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1474 if (VecSize <= 256) // 32 bytes
1475 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1476 if (VecSize <= 512) // 64 bytes
1477 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1478 if (VecSize <= 1024) // 128 bytes
1479 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1480
1481 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1482}
1483
1484const MCInstrDesc &
1485SIInstrInfo::getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize,
1486 bool IsSGPR) const {
1487 if (IsSGPR) {
1488 switch (EltSize) {
1489 case 32:
1490 return get(getIndirectSGPRWriteMovRelPseudo32(VecSize));
1491 case 64:
1492 return get(getIndirectSGPRWriteMovRelPseudo64(VecSize));
1493 default:
1494 llvm_unreachable("invalid reg indexing elt size");
1495 }
1496 }
1497
1498 assert(EltSize == 32 && "invalid reg indexing elt size");
1500}
1501
1502static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1503 switch (Size) {
1504 case 4:
1505 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1506 case 8:
1507 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1508 case 12:
1509 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1510 case 16:
1511 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1512 : AMDGPU::SI_SPILL_S128_SAVE;
1513 case 20:
1514 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1515 : AMDGPU::SI_SPILL_S160_SAVE;
1516 case 24:
1517 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1518 : AMDGPU::SI_SPILL_S192_SAVE;
1519 case 28:
1520 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1521 : AMDGPU::SI_SPILL_S224_SAVE;
1522 case 32:
1523 return AMDGPU::SI_SPILL_S256_SAVE;
1524 case 36:
1525 return AMDGPU::SI_SPILL_S288_SAVE;
1526 case 40:
1527 return AMDGPU::SI_SPILL_S320_SAVE;
1528 case 44:
1529 return AMDGPU::SI_SPILL_S352_SAVE;
1530 case 48:
1531 return AMDGPU::SI_SPILL_S384_SAVE;
1532 case 64:
1533 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1534 : AMDGPU::SI_SPILL_S512_SAVE;
1535 case 128:
1536 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1537 : AMDGPU::SI_SPILL_S1024_SAVE;
1538 default:
1539 llvm_unreachable("unknown register size");
1540 }
1541}
1542
1543static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1544 switch (Size) {
1545 case 2:
1546 return AMDGPU::SI_SPILL_V16_SAVE;
1547 case 4:
1548 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1549 case 8:
1550 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1551 case 12:
1552 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1553 case 16:
1554 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1555 : AMDGPU::SI_SPILL_V128_SAVE;
1556 case 20:
1557 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1558 : AMDGPU::SI_SPILL_V160_SAVE;
1559 case 24:
1560 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1561 : AMDGPU::SI_SPILL_V192_SAVE;
1562 case 28:
1563 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1564 : AMDGPU::SI_SPILL_V224_SAVE;
1565 case 32:
1566 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1567 : AMDGPU::SI_SPILL_V256_SAVE;
1568 case 36:
1569 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1570 : AMDGPU::SI_SPILL_V288_SAVE;
1571 case 40:
1572 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1573 : AMDGPU::SI_SPILL_V320_SAVE;
1574 case 44:
1575 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1576 : AMDGPU::SI_SPILL_V352_SAVE;
1577 case 48:
1578 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1579 : AMDGPU::SI_SPILL_V384_SAVE;
1580 case 64:
1581 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1582 : AMDGPU::SI_SPILL_V512_SAVE;
1583 case 128:
1584 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1585 : AMDGPU::SI_SPILL_V1024_SAVE;
1586 default:
1587 llvm_unreachable("unknown register size");
1588 }
1589}
1590
1591static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1592 switch (Size) {
1593 case 4:
1594 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1595 : AMDGPU::SI_SPILL_AV32_SAVE;
1596 case 8:
1597 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1598 : AMDGPU::SI_SPILL_AV64_SAVE;
1599 case 12:
1600 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1601 : AMDGPU::SI_SPILL_AV96_SAVE;
1602 case 16:
1603 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1604 : AMDGPU::SI_SPILL_AV128_SAVE;
1605 case 20:
1606 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1607 : AMDGPU::SI_SPILL_AV160_SAVE;
1608 case 24:
1609 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1610 : AMDGPU::SI_SPILL_AV192_SAVE;
1611 case 28:
1612 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1613 : AMDGPU::SI_SPILL_AV224_SAVE;
1614 case 32:
1615 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1616 : AMDGPU::SI_SPILL_AV256_SAVE;
1617 case 36:
1618 return AMDGPU::SI_SPILL_AV288_SAVE;
1619 case 40:
1620 return AMDGPU::SI_SPILL_AV320_SAVE;
1621 case 44:
1622 return AMDGPU::SI_SPILL_AV352_SAVE;
1623 case 48:
1624 return AMDGPU::SI_SPILL_AV384_SAVE;
1625 case 64:
1626 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1627 : AMDGPU::SI_SPILL_AV512_SAVE;
1628 case 128:
1629 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1630 : AMDGPU::SI_SPILL_AV1024_SAVE;
1631 default:
1632 llvm_unreachable("unknown register size");
1633 }
1634}
1635
1636static unsigned getWWMRegSpillSaveOpcode(unsigned Size,
1637 bool IsVectorSuperClass) {
1638 // Currently, there is only 32-bit WWM register spills needed.
1639 if (Size != 4)
1640 llvm_unreachable("unknown wwm register spill size");
1641
1642 if (IsVectorSuperClass)
1643 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1644
1645 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1646}
1647
1649 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1650 const SIMachineFunctionInfo &MFI, bool NeedsCFI) const {
1651 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1652
1653 // Choose the right opcode if spilling a WWM register.
1655 return getWWMRegSpillSaveOpcode(Size, IsVectorSuperClass);
1656
1657 // TODO: Check if AGPRs are available
1658 if (ST.hasMAIInsts())
1659 return getAVSpillSaveOpcode(Size, NeedsCFI);
1660
1661 return getVGPRSpillSaveOpcode(Size, NeedsCFI);
1662}
1663
1664void SIInstrInfo::storeRegToStackSlotImpl(
1666 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1667 MachineInstr::MIFlag Flags, bool NeedsCFI) const {
1668 MachineFunction *MF = MBB.getParent();
1670 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1671 const DebugLoc &DL = MBB.findDebugLoc(MI);
1672
1673 MachinePointerInfo PtrInfo
1674 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1676 PtrInfo, MachineMemOperand::MOStore, FrameInfo.getObjectSize(FrameIndex),
1677 FrameInfo.getObjectAlign(FrameIndex));
1678 unsigned SpillSize = RI.getSpillSize(*RC);
1679
1680 MachineRegisterInfo &MRI = MF->getRegInfo();
1681 if (RI.isSGPRClass(RC)) {
1682 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1683 MFI->setHasSpilledSGPRs();
1684 assert(SrcReg != AMDGPU::M0 && "m0 should not be spilled");
1685 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1686 SrcReg != AMDGPU::EXEC && "exec should not be spilled");
1687
1688 // We are only allowed to create one new instruction when spilling
1689 // registers, so we need to use pseudo instruction for spilling SGPRs.
1690 const MCInstrDesc &OpDesc =
1691 get(getSGPRSpillSaveOpcode(SpillSize, NeedsCFI));
1692
1693 // The SGPR spill/restore instructions only work on number sgprs, so we need
1694 // to make sure we are using the correct register class.
1695 if (SrcReg.isVirtual() && SpillSize == 4) {
1696 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1697 }
1698
1699 BuildMI(MBB, MI, DL, OpDesc)
1700 .addReg(SrcReg, getKillRegState(isKill)) // data
1701 .addFrameIndex(FrameIndex) // addr
1702 .addMemOperand(MMO)
1704
1705 return;
1706 }
1707
1708 unsigned Opcode = getVectorRegSpillSaveOpcode(VReg ? VReg : SrcReg, RC,
1709 SpillSize, *MFI, NeedsCFI);
1710 MFI->setHasSpilledVGPRs();
1711
1712 BuildMI(MBB, MI, DL, get(Opcode))
1713 .addReg(SrcReg, getKillRegState(isKill)) // data
1714 .addFrameIndex(FrameIndex) // addr
1715 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1716 .addImm(0) // offset
1717 .addMemOperand(MMO);
1718}
1719
1722 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1723 MachineInstr::MIFlag Flags) const {
1724 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1725 false);
1726}
1727
1730 Register SrcReg, bool isKill,
1731 int FrameIndex,
1732 const TargetRegisterClass *RC) const {
1733 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, Register(),
1734 MachineInstr::NoFlags, true);
1735}
1736
1737static unsigned getSGPRSpillRestoreOpcode(unsigned Size) {
1738 switch (Size) {
1739 case 4:
1740 return AMDGPU::SI_SPILL_S32_RESTORE;
1741 case 8:
1742 return AMDGPU::SI_SPILL_S64_RESTORE;
1743 case 12:
1744 return AMDGPU::SI_SPILL_S96_RESTORE;
1745 case 16:
1746 return AMDGPU::SI_SPILL_S128_RESTORE;
1747 case 20:
1748 return AMDGPU::SI_SPILL_S160_RESTORE;
1749 case 24:
1750 return AMDGPU::SI_SPILL_S192_RESTORE;
1751 case 28:
1752 return AMDGPU::SI_SPILL_S224_RESTORE;
1753 case 32:
1754 return AMDGPU::SI_SPILL_S256_RESTORE;
1755 case 36:
1756 return AMDGPU::SI_SPILL_S288_RESTORE;
1757 case 40:
1758 return AMDGPU::SI_SPILL_S320_RESTORE;
1759 case 44:
1760 return AMDGPU::SI_SPILL_S352_RESTORE;
1761 case 48:
1762 return AMDGPU::SI_SPILL_S384_RESTORE;
1763 case 64:
1764 return AMDGPU::SI_SPILL_S512_RESTORE;
1765 case 128:
1766 return AMDGPU::SI_SPILL_S1024_RESTORE;
1767 default:
1768 llvm_unreachable("unknown register size");
1769 }
1770}
1771
1772static unsigned getVGPRSpillRestoreOpcode(unsigned Size) {
1773 switch (Size) {
1774 case 2:
1775 return AMDGPU::SI_SPILL_V16_RESTORE;
1776 case 4:
1777 return AMDGPU::SI_SPILL_V32_RESTORE;
1778 case 8:
1779 return AMDGPU::SI_SPILL_V64_RESTORE;
1780 case 12:
1781 return AMDGPU::SI_SPILL_V96_RESTORE;
1782 case 16:
1783 return AMDGPU::SI_SPILL_V128_RESTORE;
1784 case 20:
1785 return AMDGPU::SI_SPILL_V160_RESTORE;
1786 case 24:
1787 return AMDGPU::SI_SPILL_V192_RESTORE;
1788 case 28:
1789 return AMDGPU::SI_SPILL_V224_RESTORE;
1790 case 32:
1791 return AMDGPU::SI_SPILL_V256_RESTORE;
1792 case 36:
1793 return AMDGPU::SI_SPILL_V288_RESTORE;
1794 case 40:
1795 return AMDGPU::SI_SPILL_V320_RESTORE;
1796 case 44:
1797 return AMDGPU::SI_SPILL_V352_RESTORE;
1798 case 48:
1799 return AMDGPU::SI_SPILL_V384_RESTORE;
1800 case 64:
1801 return AMDGPU::SI_SPILL_V512_RESTORE;
1802 case 128:
1803 return AMDGPU::SI_SPILL_V1024_RESTORE;
1804 default:
1805 llvm_unreachable("unknown register size");
1806 }
1807}
1808
1809static unsigned getAVSpillRestoreOpcode(unsigned Size) {
1810 switch (Size) {
1811 case 4:
1812 return AMDGPU::SI_SPILL_AV32_RESTORE;
1813 case 8:
1814 return AMDGPU::SI_SPILL_AV64_RESTORE;
1815 case 12:
1816 return AMDGPU::SI_SPILL_AV96_RESTORE;
1817 case 16:
1818 return AMDGPU::SI_SPILL_AV128_RESTORE;
1819 case 20:
1820 return AMDGPU::SI_SPILL_AV160_RESTORE;
1821 case 24:
1822 return AMDGPU::SI_SPILL_AV192_RESTORE;
1823 case 28:
1824 return AMDGPU::SI_SPILL_AV224_RESTORE;
1825 case 32:
1826 return AMDGPU::SI_SPILL_AV256_RESTORE;
1827 case 36:
1828 return AMDGPU::SI_SPILL_AV288_RESTORE;
1829 case 40:
1830 return AMDGPU::SI_SPILL_AV320_RESTORE;
1831 case 44:
1832 return AMDGPU::SI_SPILL_AV352_RESTORE;
1833 case 48:
1834 return AMDGPU::SI_SPILL_AV384_RESTORE;
1835 case 64:
1836 return AMDGPU::SI_SPILL_AV512_RESTORE;
1837 case 128:
1838 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1839 default:
1840 llvm_unreachable("unknown register size");
1841 }
1842}
1843
1844static unsigned getWWMRegSpillRestoreOpcode(unsigned Size,
1845 bool IsVectorSuperClass) {
1846 // Currently, there is only 32-bit WWM register spills needed.
1847 if (Size != 4)
1848 llvm_unreachable("unknown wwm register spill size");
1849
1850 if (IsVectorSuperClass) // TODO: Always use this if there are AGPRs
1851 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1852
1853 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1854}
1855
1857 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1858 const SIMachineFunctionInfo &MFI) const {
1859 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1860
1861 // Choose the right opcode if restoring a WWM register.
1863 return getWWMRegSpillRestoreOpcode(Size, IsVectorSuperClass);
1864
1865 // TODO: Check if AGPRs are available
1866 if (ST.hasMAIInsts())
1868
1869 assert(!RI.isAGPRClass(RC));
1871}
1872
1875 Register DestReg, int FrameIndex,
1876 const TargetRegisterClass *RC,
1877 Register VReg, unsigned SubReg,
1878 MachineInstr::MIFlag Flags) const {
1879 MachineFunction *MF = MBB.getParent();
1881 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1882 const DebugLoc &DL = MBB.findDebugLoc(MI);
1883 unsigned SpillSize = RI.getSpillSize(*RC);
1884
1885 MachinePointerInfo PtrInfo
1886 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1887
1889 PtrInfo, MachineMemOperand::MOLoad, FrameInfo.getObjectSize(FrameIndex),
1890 FrameInfo.getObjectAlign(FrameIndex));
1891
1892 if (RI.isSGPRClass(RC)) {
1893 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1894 MFI->setHasSpilledSGPRs();
1895 assert(DestReg != AMDGPU::M0 && "m0 should not be reloaded into");
1896 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1897 DestReg != AMDGPU::EXEC && "exec should not be spilled");
1898
1899 // FIXME: Maybe this should not include a memoperand because it will be
1900 // lowered to non-memory instructions.
1901 const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize));
1902 if (DestReg.isVirtual() && SpillSize == 4) {
1903 MachineRegisterInfo &MRI = MF->getRegInfo();
1904 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1905 }
1906
1907 BuildMI(MBB, MI, DL, OpDesc, DestReg)
1908 .addFrameIndex(FrameIndex) // addr
1909 .addMemOperand(MMO)
1911
1912 return;
1913 }
1914
1915 unsigned Opcode = getVectorRegSpillRestoreOpcode(VReg ? VReg : DestReg, RC,
1916 SpillSize, *MFI);
1917 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
1918 .addFrameIndex(FrameIndex) // vaddr
1919 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1920 .addImm(0) // offset
1921 .addMemOperand(MMO);
1922}
1923
1928
1931 unsigned Quantity) const {
1932 DebugLoc DL = MBB.findDebugLoc(MI);
1933 unsigned MaxSNopCount = 1u << ST.getSNopBits();
1934 while (Quantity > 0) {
1935 unsigned Arg = std::min(Quantity, MaxSNopCount);
1936 Quantity -= Arg;
1937 BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
1938 }
1939}
1940
1944 const DebugLoc &DL) const {
1945 MachineFunction *MF = MBB.getParent();
1946 constexpr unsigned DoorbellIDMask = 0x3ff;
1947 constexpr unsigned ECQueueWaveAbort = 0x400;
1948
1949 MachineBasicBlock *TrapBB = &MBB;
1950 MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock();
1951
1952 if (!MBB.succ_empty() || std::next(MI.getIterator()) != MBB.end()) {
1953 MBB.splitAt(MI, /*UpdateLiveIns=*/false);
1954 TrapBB = MF->CreateMachineBasicBlock();
1955 BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB);
1956 MF->push_back(TrapBB);
1957 MBB.addSuccessor(TrapBB);
1958 }
1959 // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this
1960 // will be a nop.
1961 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP))
1962 .addImm(static_cast<unsigned>(GCNSubtarget::TrapID::LLVMAMDHSATrap));
1963 Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1964 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32),
1965 DoorbellReg)
1967 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
1968 .addUse(AMDGPU::M0);
1969 Register DoorbellRegMasked =
1970 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1971 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked)
1972 .addUse(DoorbellReg)
1973 .addImm(DoorbellIDMask);
1974 Register SetWaveAbortBit =
1975 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1976 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit)
1977 .addUse(DoorbellRegMasked)
1978 .addImm(ECQueueWaveAbort);
1979 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1980 .addUse(SetWaveAbortBit);
1981 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG))
1983 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1984 .addUse(AMDGPU::TTMP2);
1985 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB);
1986 TrapBB->addSuccessor(HaltLoopBB);
1987
1988 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5);
1989 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH))
1990 .addMBB(HaltLoopBB);
1991 MF->push_back(HaltLoopBB);
1992 HaltLoopBB->addSuccessor(HaltLoopBB);
1993
1994 return MBB.getNextNode();
1995}
1996
1998 switch (MI.getOpcode()) {
1999 default:
2000 if (MI.isMetaInstruction())
2001 return 0;
2002 return 1; // FIXME: Do wait states equal cycles?
2003
2004 case AMDGPU::S_NOP:
2005 return MI.getOperand(0).getImm() + 1;
2006 // SI_RETURN_TO_EPILOG is a fallthrough to code outside of the function. The
2007 // hazard, even if one exist, won't really be visible. Should we handle it?
2008 }
2009}
2010
2012 MachineBasicBlock &MBB = *MI.getParent();
2013 DebugLoc DL = MBB.findDebugLoc(MI);
2015
2016 switch (MI.getOpcode()) {
2017 default: return TargetInstrInfo::expandPostRAPseudo(MI);
2018 case AMDGPU::S_MOV_B64_term:
2019 // This is only a terminator to get the correct spill code placement during
2020 // register allocation.
2021 MI.setDesc(get(AMDGPU::S_MOV_B64));
2022 break;
2023
2024 case AMDGPU::S_MOV_B32_term:
2025 // This is only a terminator to get the correct spill code placement during
2026 // register allocation.
2027 MI.setDesc(get(AMDGPU::S_MOV_B32));
2028 break;
2029
2030 case AMDGPU::S_XOR_B64_term:
2031 // This is only a terminator to get the correct spill code placement during
2032 // register allocation.
2033 MI.setDesc(get(AMDGPU::S_XOR_B64));
2034 break;
2035
2036 case AMDGPU::S_XOR_B32_term:
2037 // This is only a terminator to get the correct spill code placement during
2038 // register allocation.
2039 MI.setDesc(get(AMDGPU::S_XOR_B32));
2040 break;
2041 case AMDGPU::S_OR_B64_term:
2042 // This is only a terminator to get the correct spill code placement during
2043 // register allocation.
2044 MI.setDesc(get(AMDGPU::S_OR_B64));
2045 break;
2046 case AMDGPU::S_OR_B32_term:
2047 // This is only a terminator to get the correct spill code placement during
2048 // register allocation.
2049 MI.setDesc(get(AMDGPU::S_OR_B32));
2050 break;
2051
2052 case AMDGPU::S_ANDN2_B64_term:
2053 // This is only a terminator to get the correct spill code placement during
2054 // register allocation.
2055 MI.setDesc(get(AMDGPU::S_ANDN2_B64));
2056 break;
2057
2058 case AMDGPU::S_ANDN2_B32_term:
2059 // This is only a terminator to get the correct spill code placement during
2060 // register allocation.
2061 MI.setDesc(get(AMDGPU::S_ANDN2_B32));
2062 break;
2063
2064 case AMDGPU::S_AND_B64_term:
2065 // This is only a terminator to get the correct spill code placement during
2066 // register allocation.
2067 MI.setDesc(get(AMDGPU::S_AND_B64));
2068 break;
2069
2070 case AMDGPU::S_AND_B32_term:
2071 // This is only a terminator to get the correct spill code placement during
2072 // register allocation.
2073 MI.setDesc(get(AMDGPU::S_AND_B32));
2074 break;
2075
2076 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2077 // This is only a terminator to get the correct spill code placement during
2078 // register allocation.
2079 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B64));
2080 break;
2081
2082 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2083 // This is only a terminator to get the correct spill code placement during
2084 // register allocation.
2085 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B32));
2086 break;
2087
2088 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2089 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2090 break;
2091 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2092 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2093 break;
2094
2095 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2096 MI.setDesc(get(AMDGPU::V_WRITELANE_B32));
2097 break;
2098
2099 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2100 MI.setDesc(get(AMDGPU::V_READLANE_B32));
2101 break;
2102 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2103 Register Dst = MI.getOperand(0).getReg();
2104 bool IsAGPR = SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst));
2105 MI.setDesc(
2106 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2107 break;
2108 }
2109 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2110 Register Dst = MI.getOperand(0).getReg();
2111 if (SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst))) {
2112 int64_t Imm = MI.getOperand(1).getImm();
2113
2114 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2115 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2116 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstLo)
2117 .addImm(SignExtend64<32>(Imm));
2118 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstHi)
2119 .addImm(SignExtend64<32>(Imm >> 32));
2120 MI.eraseFromParent();
2121 break;
2122 }
2123
2124 [[fallthrough]];
2125 }
2126 case AMDGPU::V_MOV_B64_PSEUDO: {
2127 Register Dst = MI.getOperand(0).getReg();
2128 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2129 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2130
2131 const MCInstrDesc &Mov64Desc = get(AMDGPU::V_MOV_B64_e32);
2132 const TargetRegisterClass *Mov64RC = getRegClass(Mov64Desc, /*OpNum=*/0);
2133
2134 const MachineOperand &SrcOp = MI.getOperand(1);
2135 // FIXME: Will this work for 64-bit floating point immediates?
2136 assert(!SrcOp.isFPImm());
2137 if (ST.hasVMovB64Inst() && Mov64RC->contains(Dst)) {
2138 MI.setDesc(Mov64Desc);
2139 if (SrcOp.isReg() || isInlineConstant(MI, 1) ||
2140 (SrcOp.isImm() &&
2141 (isUInt<32>(SrcOp.getImm()) || ST.has64BitLiterals())) ||
2142 (SrcOp.isGlobal() && ST.has64BitLiterals()))
2143 break;
2144 }
2145 if (SrcOp.isGlobal()) {
2146 // The address is unknown until link time, so the PK_MOV inline-constant
2147 // shortcut cannot apply.
2148 const GlobalValue *GV = SrcOp.getGlobal();
2149 int64_t Offset = SrcOp.getOffset();
2150 unsigned BaseFlags, LoReloc, HiReloc;
2151 std::tie(BaseFlags, LoReloc, HiReloc) =
2153
2154 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2155 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2156 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2157 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2158 } else if (SrcOp.isImm()) {
2159 APInt Imm(64, SrcOp.getImm());
2160 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2161 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2162 const MCInstrDesc &PkMovDesc = get(AMDGPU::V_PK_MOV_B32);
2163 const TargetRegisterClass *PkMovRC = getRegClass(PkMovDesc, /*OpNum=*/0);
2164
2165 if (ST.hasPkMovB32() && Lo == Hi && isInlineConstant(Lo) &&
2166 PkMovRC->contains(Dst)) {
2167 BuildMI(MBB, MI, DL, PkMovDesc, Dst)
2169 .addImm(Lo.getSExtValue())
2171 .addImm(Lo.getSExtValue())
2172 .addImm(0) // op_sel_lo
2173 .addImm(0) // op_sel_hi
2174 .addImm(0) // neg_lo
2175 .addImm(0) // neg_hi
2176 .addImm(0); // clamp
2177 } else {
2178 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2179 .addImm(Lo.getSExtValue());
2180 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2181 .addImm(Hi.getSExtValue());
2182 }
2183 } else {
2184 assert(SrcOp.isReg());
2185 if (ST.hasPkMovB32() &&
2186 !RI.isAGPR(MBB.getParent()->getRegInfo(), SrcOp.getReg())) {
2187 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), Dst)
2188 .addImm(SISrcMods::OP_SEL_1) // src0_mod
2189 .addReg(SrcOp.getReg())
2191 .addReg(SrcOp.getReg())
2192 .addImm(0) // op_sel_lo
2193 .addImm(0) // op_sel_hi
2194 .addImm(0) // neg_lo
2195 .addImm(0) // neg_hi
2196 .addImm(0); // clamp
2197 } else {
2198 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2199 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0));
2200 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2201 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1));
2202 }
2203 }
2204 MI.eraseFromParent();
2205 break;
2206 }
2207 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2209 break;
2210 }
2211 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2212 const MachineOperand &SrcOp = MI.getOperand(1);
2213 assert(!SrcOp.isFPImm());
2214
2215 if (ST.has64BitLiterals()) {
2216 MI.setDesc(get(AMDGPU::S_MOV_B64));
2217 break;
2218 }
2219
2220 if (SrcOp.isGlobal()) {
2221 Register Dst = MI.getOperand(0).getReg();
2222 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2223 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2224 const GlobalValue *GV = SrcOp.getGlobal();
2225 int64_t Offset = SrcOp.getOffset();
2226 unsigned BaseFlags, LoReloc, HiReloc;
2227 std::tie(BaseFlags, LoReloc, HiReloc) =
2229
2230 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2231 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2232 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2233 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2234 MI.eraseFromParent();
2235 break;
2236 }
2237
2238 // SrcOp is immediate
2239 APInt Imm(64, SrcOp.getImm());
2240 if (Imm.isIntN(32) || isInlineConstant(Imm)) {
2241 MI.setDesc(get(AMDGPU::S_MOV_B64));
2242 break;
2243 }
2244
2245 Register Dst = MI.getOperand(0).getReg();
2246 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2247 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2248
2249 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2250 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2251 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2252 .addImm(Lo.getSExtValue());
2253 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2254 .addImm(Hi.getSExtValue());
2255 MI.eraseFromParent();
2256 break;
2257 }
2258 case AMDGPU::V_SET_INACTIVE_B32: {
2259 // Lower V_SET_INACTIVE_B32 to V_CNDMASK_B32.
2260 Register DstReg = MI.getOperand(0).getReg();
2261 BuildMI(MBB, MI, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2262 .add(MI.getOperand(3))
2263 .add(MI.getOperand(4))
2264 .add(MI.getOperand(1))
2265 .add(MI.getOperand(2))
2266 .add(MI.getOperand(5));
2267 MI.eraseFromParent();
2268 break;
2269 }
2270 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2271 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2272 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2273 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2274 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2275 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2276 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2277 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2278 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2279 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2280 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2281 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2282 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2283 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2284 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2285 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2286 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2287 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2288 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2289 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2290 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2291 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2292 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2293 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2294 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2295 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2296 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2297 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2298 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2299 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2300 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2301 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2302 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2303 const TargetRegisterClass *EltRC = getOpRegClass(MI, 2);
2304
2305 unsigned Opc;
2306 if (RI.hasVGPRs(EltRC)) {
2307 Opc = AMDGPU::V_MOVRELD_B32_e32;
2308 } else {
2309 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2310 : AMDGPU::S_MOVRELD_B32;
2311 }
2312
2313 const MCInstrDesc &OpDesc = get(Opc);
2314 Register VecReg = MI.getOperand(0).getReg();
2315 bool IsUndef = MI.getOperand(1).isUndef();
2316 unsigned SubReg = MI.getOperand(3).getImm();
2317 assert(VecReg == MI.getOperand(1).getReg());
2318
2320 BuildMI(MBB, MI, DL, OpDesc)
2321 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2322 .add(MI.getOperand(2))
2324 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2325
2326 const int ImpDefIdx =
2327 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2328 const int ImpUseIdx = ImpDefIdx + 1;
2329 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2330 MI.eraseFromParent();
2331 break;
2332 }
2333 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2334 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2335 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2336 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2337 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2338 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2339 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2340 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2341 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2342 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2343 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2344 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2345 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2346 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2347 assert(ST.useVGPRIndexMode());
2348 Register VecReg = MI.getOperand(0).getReg();
2349 bool IsUndef = MI.getOperand(1).isUndef();
2350 MachineOperand &Idx = MI.getOperand(3);
2351 Register SubReg = MI.getOperand(4).getImm();
2352
2353 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2354 .add(Idx)
2356 SetOn->getOperand(3).setIsUndef();
2357
2358 const MCInstrDesc &OpDesc = get(AMDGPU::V_MOV_B32_indirect_write);
2360 BuildMI(MBB, MI, DL, OpDesc)
2361 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2362 .add(MI.getOperand(2))
2364 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2365
2366 const int ImpDefIdx =
2367 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2368 const int ImpUseIdx = ImpDefIdx + 1;
2369 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2370
2371 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2372
2373 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2374
2375 MI.eraseFromParent();
2376 break;
2377 }
2378 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2379 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2380 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2381 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2382 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2383 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2384 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2385 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2386 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2387 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2388 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2389 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2390 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2391 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2392 assert(ST.useVGPRIndexMode());
2393 Register Dst = MI.getOperand(0).getReg();
2394 Register VecReg = MI.getOperand(1).getReg();
2395 bool IsUndef = MI.getOperand(1).isUndef();
2396 Register SubReg = MI.getOperand(3).getImm();
2397
2398 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2399 .add(MI.getOperand(2))
2401 SetOn->getOperand(3).setIsUndef();
2402
2403 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_indirect_read))
2404 .addDef(Dst)
2405 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2406 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2407
2408 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2409
2410 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2411
2412 MI.eraseFromParent();
2413 break;
2414 }
2415 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2416 MachineFunction &MF = *MBB.getParent();
2417 Register Reg = MI.getOperand(0).getReg();
2418 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2419 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2420 MachineOperand OpLo = MI.getOperand(1);
2421 MachineOperand OpHi = MI.getOperand(2);
2422
2423 // Create a bundle so these instructions won't be re-ordered by the
2424 // post-RA scheduler.
2425 MIBundleBuilder Bundler(MBB, MI);
2426 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2427
2428 // What we want here is an offset from the value returned by s_getpc (which
2429 // is the address of the s_add_u32 instruction) to the global variable, but
2430 // since the encoding of $symbol starts 4 bytes after the start of the
2431 // s_add_u32 instruction, we end up with an offset that is 4 bytes too
2432 // small. This requires us to add 4 to the global variable offset in order
2433 // to compute the correct address. Similarly for the s_addc_u32 instruction,
2434 // the encoding of $symbol starts 12 bytes after the start of the s_add_u32
2435 // instruction.
2436
2437 int64_t Adjust = 0;
2438 if (ST.hasGetPCZeroExtension()) {
2439 // Fix up hardware that does not sign-extend the 48-bit PC value by
2440 // inserting: s_sext_i32_i16 reghi, reghi
2441 Bundler.append(
2442 BuildMI(MF, DL, get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2443 Adjust += 4;
2444 }
2445
2446 if (OpLo.isGlobal())
2447 OpLo.setOffset(OpLo.getOffset() + Adjust + 4);
2448 Bundler.append(
2449 BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2450
2451 if (OpHi.isGlobal())
2452 OpHi.setOffset(OpHi.getOffset() + Adjust + 12);
2453 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi)
2454 .addReg(RegHi)
2455 .add(OpHi));
2456
2457 finalizeBundle(MBB, Bundler.begin());
2458
2459 MI.eraseFromParent();
2460 break;
2461 }
2462 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2463 MachineFunction &MF = *MBB.getParent();
2464 Register Reg = MI.getOperand(0).getReg();
2465 MachineOperand Op = MI.getOperand(1);
2466
2467 // Create a bundle so these instructions won't be re-ordered by the
2468 // post-RA scheduler.
2469 MIBundleBuilder Bundler(MBB, MI);
2470 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2471 if (Op.isGlobal())
2472 Op.setOffset(Op.getOffset() + 4);
2473 Bundler.append(
2474 BuildMI(MF, DL, get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(Op));
2475
2476 finalizeBundle(MBB, Bundler.begin());
2477
2478 MI.eraseFromParent();
2479 break;
2480 }
2481 case AMDGPU::ENTER_STRICT_WWM: {
2482 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2483 // Whole Wave Mode is entered.
2484 MI.setDesc(get(LMC.OrSaveExecOpc));
2485 break;
2486 }
2487 case AMDGPU::ENTER_STRICT_WQM: {
2488 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2489 // STRICT_WQM is entered.
2490 BuildMI(MBB, MI, DL, get(LMC.MovOpc), MI.getOperand(0).getReg())
2491 .addReg(LMC.ExecReg);
2492 BuildMI(MBB, MI, DL, get(LMC.WQMOpc), LMC.ExecReg).addReg(LMC.ExecReg);
2493
2494 MI.eraseFromParent();
2495 break;
2496 }
2497 case AMDGPU::EXIT_STRICT_WWM:
2498 case AMDGPU::EXIT_STRICT_WQM: {
2499 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2500 // WWM/STICT_WQM is exited.
2501 MI.setDesc(get(LMC.MovOpc));
2502 break;
2503 }
2504 case AMDGPU::SI_RETURN: {
2505 const MachineFunction *MF = MBB.getParent();
2506 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2507 const SIRegisterInfo *TRI = ST.getRegisterInfo();
2508 // Hiding the return address use with SI_RETURN may lead to extra kills in
2509 // the function and missing live-ins. We are fine in practice because callee
2510 // saved register handling ensures the register value is restored before
2511 // RET, but we need the undef flag here to appease the MachineVerifier
2512 // liveness checks.
2514 BuildMI(MBB, MI, DL, get(AMDGPU::S_SETPC_B64_return))
2515 .addReg(TRI->getReturnAddressReg(*MF), RegState::Undef);
2516
2517 MIB.copyImplicitOps(MI);
2518 MI.eraseFromParent();
2519 break;
2520 }
2521
2522 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2523 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2524 MI.setDesc(get(AMDGPU::S_MUL_U64));
2525 break;
2526
2527 case AMDGPU::S_GETPC_B64_pseudo:
2528 MI.setDesc(get(AMDGPU::S_GETPC_B64));
2529 if (ST.hasGetPCZeroExtension()) {
2530 Register Dst = MI.getOperand(0).getReg();
2531 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2532 // Fix up hardware that does not sign-extend the 48-bit PC value by
2533 // inserting: s_sext_i32_i16 dsthi, dsthi
2534 BuildMI(MBB, std::next(MI.getIterator()), DL, get(AMDGPU::S_SEXT_I32_I16),
2535 DstHi)
2536 .addReg(DstHi);
2537 }
2538 break;
2539
2540 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2541 assert(ST.hasBF16PackedInsts());
2542 MI.setDesc(get(AMDGPU::V_PK_MAX_NUM_BF16));
2543 MI.addOperand(MachineOperand::CreateImm(0)); // op_sel
2544 MI.addOperand(MachineOperand::CreateImm(0)); // neg_lo
2545 MI.addOperand(MachineOperand::CreateImm(0)); // neg_hi
2546 auto Op0 = getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
2547 Op0->setImm(Op0->getImm() | SISrcMods::OP_SEL_1);
2548 auto Op1 = getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
2549 Op1->setImm(Op1->getImm() | SISrcMods::OP_SEL_1);
2550 break;
2551 }
2552
2553 case AMDGPU::GET_STACK_BASE:
2554 // The stack starts at offset 0 unless we need to reserve some space at the
2555 // bottom.
2556 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*MBB.getParent())) {
2557 // When CWSR is used in dynamic VGPR mode, the trap handler needs to save
2558 // some of the VGPRs. The size of the required scratch space has already
2559 // been computed by prolog epilog insertion.
2560 const SIMachineFunctionInfo *MFI =
2561 MBB.getParent()->getInfo<SIMachineFunctionInfo>();
2562 unsigned VGPRSize = MFI->getScratchReservedForDynamicVGPRs();
2563 Register DestReg = MI.getOperand(0).getReg();
2564 BuildMI(MBB, MI, DL, get(AMDGPU::S_GETREG_B32), DestReg)
2567 // The MicroEngine ID is 0 for the graphics queue, and 1 or 2 for compute
2568 // (3 is unused, so we ignore it). Unfortunately, S_GETREG doesn't set
2569 // SCC, so we need to check for 0 manually.
2570 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)).addImm(0).addReg(DestReg);
2571 // Change the implicif-def of SCC to an explicit use (but first remove
2572 // the dead flag if present).
2573 MI.getOperand(MI.getNumExplicitOperands()).setIsDead(false);
2574 MI.getOperand(MI.getNumExplicitOperands()).setIsUse();
2575 MI.setDesc(get(AMDGPU::S_CMOVK_I32));
2576 MI.addOperand(MachineOperand::CreateImm(VGPRSize));
2577 } else {
2578 MI.setDesc(get(AMDGPU::S_MOV_B32));
2579 MI.addOperand(MachineOperand::CreateImm(0));
2580 MI.removeOperand(
2581 MI.getNumExplicitOperands()); // Drop implicit def of SCC.
2582 }
2583 break;
2584 }
2585
2586 return true;
2587}
2588
2591 unsigned SubIdx, const MachineInstr &Orig,
2592 LaneBitmask UsedLanes) const {
2593
2594 // Try shrinking the instruction to remat only the part needed for current
2595 // context.
2596 // TODO: Handle more cases.
2597 unsigned Opcode = Orig.getOpcode();
2598 switch (Opcode) {
2599 case AMDGPU::S_MOV_B64:
2600 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2601 if (SubIdx != 0)
2602 break;
2603
2604 if (!Orig.getOperand(1).isImm())
2605 break;
2606
2607 // Shrink S_MOV_B64 to S_MOV_B32 when UsedLanes indicates only a single
2608 // 32-bit lane of the 64-bit value is live at the rematerialization point.
2609 if (UsedLanes.all())
2610 break;
2611
2612 // Determine which half of the 64-bit immediate corresponds to the use.
2613 unsigned OrigSubReg = Orig.getOperand(0).getSubReg();
2614 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2615 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2616
2617 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2618 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2619
2620 if (NeedLo && NeedHi)
2621 break;
2622
2623 int64_t Imm64 = Orig.getOperand(1).getImm();
2624 int32_t Imm32 = NeedLo ? Lo_32(Imm64) : Hi_32(Imm64);
2625
2626 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2627
2628 // Emit S_MOV_B32 defining just the needed 32-bit subreg of DestReg.
2629 BuildMI(MBB, I, Orig.getDebugLoc(), get(AMDGPU::S_MOV_B32))
2630 .addReg(DestReg, RegState::Define | RegState::Undef, UseSubReg)
2631 .addImm(Imm32);
2632 return;
2633 }
2634
2635 case AMDGPU::S_LOAD_DWORDX16_IMM:
2636 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2637 if (SubIdx != 0)
2638 break;
2639
2640 if (I == MBB.end())
2641 break;
2642
2643 if (I->isBundled())
2644 break;
2645
2646 // Look for a single use of the register that is also a subreg.
2647 Register RegToFind = Orig.getOperand(0).getReg();
2648 MachineOperand *UseMO = nullptr;
2649 for (auto &CandMO : I->operands()) {
2650 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2651 continue;
2652 if (UseMO) {
2653 UseMO = nullptr;
2654 break;
2655 }
2656 UseMO = &CandMO;
2657 }
2658 if (!UseMO || UseMO->getSubReg() == AMDGPU::NoSubRegister)
2659 break;
2660
2661 unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
2662 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());
2663
2664 MachineFunction *MF = MBB.getParent();
2665 MachineRegisterInfo &MRI = MF->getRegInfo();
2666 assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");
2667
2668 unsigned NewOpcode = -1;
2669 if (SubregSize == 256)
2670 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2671 else if (SubregSize == 128)
2672 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2673 else
2674 break;
2675
2676 const MCInstrDesc &TID = get(NewOpcode);
2677 const TargetRegisterClass *NewRC =
2678 RI.getAllocatableClass(getRegClass(TID, 0));
2679 MRI.setRegClass(DestReg, NewRC);
2680
2681 UseMO->setReg(DestReg);
2682 UseMO->setSubReg(AMDGPU::NoSubRegister);
2683
2684 // Use a smaller load with the desired size, possibly with updated offset.
2685 MachineInstr *MI = MF->CloneMachineInstr(&Orig);
2686 MI->setDesc(TID);
2687 MI->getOperand(0).setReg(DestReg);
2688 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2689 if (Offset) {
2690 MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
2691 int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
2692 OffsetMO->setImm(FinalOffset);
2693 }
2695 for (const MachineMemOperand *MemOp : Orig.memoperands())
2696 NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
2697 SubregSize / 8));
2698 MI->setMemRefs(*MF, NewMMOs);
2699
2700 MBB.insert(I, MI);
2701 return;
2702 }
2703
2704 default:
2705 break;
2706 }
2707
2708 TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
2709}
2710
2711std::pair<MachineInstr*, MachineInstr*>
2713 assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2714
2715 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2717 ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
2718 MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
2719 return std::pair(&MI, nullptr);
2720 }
2721
2722 MachineBasicBlock &MBB = *MI.getParent();
2723 DebugLoc DL = MBB.findDebugLoc(MI);
2724 MachineFunction *MF = MBB.getParent();
2725 MachineRegisterInfo &MRI = MF->getRegInfo();
2726 Register Dst = MI.getOperand(0).getReg();
2727 unsigned Part = 0;
2728 MachineInstr *Split[2];
2729
2730 for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2731 auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
2732 if (Dst.isPhysical()) {
2733 MovDPP.addDef(RI.getSubReg(Dst, Sub));
2734 } else {
2735 assert(MRI.isSSA());
2736 auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2737 MovDPP.addDef(Tmp);
2738 }
2739
2740 for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
2741 const MachineOperand &SrcOp = MI.getOperand(I);
2742 assert(!SrcOp.isFPImm());
2743 if (SrcOp.isImm()) {
2744 APInt Imm(64, SrcOp.getImm());
2745 Imm.ashrInPlace(Part * 32);
2746 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2747 } else {
2748 assert(SrcOp.isReg());
2749 Register Src = SrcOp.getReg();
2750 if (Src.isPhysical())
2751 MovDPP.addReg(RI.getSubReg(Src, Sub));
2752 else
2753 MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
2754 }
2755 }
2756
2757 for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
2758 MovDPP.addImm(MO.getImm());
2759
2760 Split[Part] = MovDPP;
2761 ++Part;
2762 }
2763
2764 if (Dst.isVirtual())
2765 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
2766 .addReg(Split[0]->getOperand(0).getReg())
2767 .addImm(AMDGPU::sub0)
2768 .addReg(Split[1]->getOperand(0).getReg())
2769 .addImm(AMDGPU::sub1);
2770
2771 MI.eraseFromParent();
2772 return std::pair(Split[0], Split[1]);
2773}
2774
2775std::optional<DestSourcePair>
2777 if (MI.getOpcode() == AMDGPU::WWM_COPY)
2778 return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
2779
2780 return std::nullopt;
2781}
2782
2784 AMDGPU::OpName Src0OpName,
2785 MachineOperand &Src1,
2786 AMDGPU::OpName Src1OpName) const {
2787 MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
2788 if (!Src0Mods)
2789 return false;
2790
2791 MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
2792 assert(Src1Mods &&
2793 "All commutable instructions have both src0 and src1 modifiers");
2794
2795 int Src0ModsVal = Src0Mods->getImm();
2796 int Src1ModsVal = Src1Mods->getImm();
2797
2798 Src1Mods->setImm(Src0ModsVal);
2799 Src0Mods->setImm(Src1ModsVal);
2800 return true;
2801}
2802
2804 MachineOperand &RegOp,
2805 MachineOperand &NonRegOp) {
2806 Register Reg = RegOp.getReg();
2807 unsigned SubReg = RegOp.getSubReg();
2808 bool IsKill = RegOp.isKill();
2809 bool IsDead = RegOp.isDead();
2810 bool IsUndef = RegOp.isUndef();
2811 bool IsDebug = RegOp.isDebug();
2812
2813 if (NonRegOp.isImm())
2814 RegOp.ChangeToImmediate(NonRegOp.getImm());
2815 else if (NonRegOp.isFI())
2816 RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
2817 else if (NonRegOp.isGlobal()) {
2818 RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
2819 NonRegOp.getTargetFlags());
2820 } else
2821 return nullptr;
2822
2823 // Make sure we don't reinterpret a subreg index in the target flags.
2824 RegOp.setTargetFlags(NonRegOp.getTargetFlags());
2825
2826 NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
2827 NonRegOp.setSubReg(SubReg);
2828
2829 return &MI;
2830}
2831
2833 MachineOperand &NonRegOp1,
2834 MachineOperand &NonRegOp2) {
2835 unsigned TargetFlags = NonRegOp1.getTargetFlags();
2836 int64_t NonRegVal = NonRegOp1.getImm();
2837
2838 NonRegOp1.setImm(NonRegOp2.getImm());
2839 NonRegOp2.setImm(NonRegVal);
2840 NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
2841 NonRegOp2.setTargetFlags(TargetFlags);
2842 return &MI;
2843}
2844
2845bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
2846 unsigned OpIdx1) const {
2847 const MCInstrDesc &InstDesc = MI.getDesc();
2848 const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
2849 const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];
2850
2851 unsigned Opc = MI.getOpcode();
2852 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2853
2854 const MachineOperand &MO0 = MI.getOperand(OpIdx0);
2855 const MachineOperand &MO1 = MI.getOperand(OpIdx1);
2856
2857 // Swap doesn't breach constant bus or literal limits
2858 // It may move literal to position other than src0, this is not allowed
2859 // pre-gfx10 However, most test cases need literals in Src0 for VOP
2860 // FIXME: After gfx9, literal can be in place other than Src0
2861 if (isVALU(MI, /*AllowLDSDMA=*/true)) {
2862 if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
2863 !isInlineConstant(MO0, OpInfo1))
2864 return false;
2865 if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
2866 !isInlineConstant(MO1, OpInfo0))
2867 return false;
2868 }
2869
2870 if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
2871 if (OpInfo1.RegClass == -1)
2872 return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
2873 return isLegalRegOperand(MI, OpIdx1, MO0) &&
2874 (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
2875 }
2876 if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
2877 if (OpInfo0.RegClass == -1)
2878 return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
2879 return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
2880 isLegalRegOperand(MI, OpIdx0, MO1);
2881 }
2882
2883 // No need to check 64-bit literals since swapping does not bring new
2884 // 64-bit literals into current instruction to fold to 32-bit
2885
2886 return isImmOperandLegal(MI, OpIdx1, MO0);
2887}
2888
2890 unsigned Src0Idx,
2891 unsigned Src1Idx) const {
2892 assert(!NewMI && "this should never be used");
2893
2894 unsigned Opc = MI.getOpcode();
2895 int CommutedOpcode = commuteOpcode(Opc);
2896 if (CommutedOpcode == -1)
2897 return nullptr;
2898
2899 if (Src0Idx > Src1Idx)
2900 std::swap(Src0Idx, Src1Idx);
2901
2902 assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
2903 static_cast<int>(Src0Idx) &&
2904 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
2905 static_cast<int>(Src1Idx) &&
2906 "inconsistency with findCommutedOpIndices");
2907
2908 if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
2909 return nullptr;
2910
2911 MachineInstr *CommutedMI = nullptr;
2912 MachineOperand &Src0 = MI.getOperand(Src0Idx);
2913 MachineOperand &Src1 = MI.getOperand(Src1Idx);
2914 if (Src0.isReg() && Src1.isReg()) {
2915 // Be sure to copy the source modifiers to the right place.
2916 CommutedMI =
2917 TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
2918 } else if (Src0.isReg() && !Src1.isReg()) {
2919 CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
2920 } else if (!Src0.isReg() && Src1.isReg()) {
2921 CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
2922 } else if (Src0.isImm() && Src1.isImm()) {
2923 CommutedMI = swapImmOperands(MI, Src0, Src1);
2924 } else {
2925 // FIXME: Found two non registers to commute. This does happen.
2926 return nullptr;
2927 }
2928
2929 if (CommutedMI) {
2930 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
2931 Src1, AMDGPU::OpName::src1_modifiers);
2932
2933 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
2934 AMDGPU::OpName::src1_sel);
2935
2936 CommutedMI->setDesc(get(CommutedOpcode));
2937 }
2938
2939 return CommutedMI;
2940}
2941
2942// This needs to be implemented because the source modifiers may be inserted
2943// between the true commutable operands, and the base
2944// TargetInstrInfo::commuteInstruction uses it.
2946 unsigned &SrcOpIdx0,
2947 unsigned &SrcOpIdx1) const {
2948 return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
2949}
2950
2952 unsigned &SrcOpIdx0,
2953 unsigned &SrcOpIdx1) const {
2954 if (!Desc.isCommutable())
2955 return false;
2956
2957 unsigned Opc = Desc.getOpcode();
2958 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2959 if (Src0Idx == -1)
2960 return false;
2961
2962 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
2963 if (Src1Idx == -1)
2964 return false;
2965
2966 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
2967}
2968
2970 int64_t BrOffset) const {
2971 // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
2972 // because its dest block is unanalyzable.
2973 assert(isSOPP(BranchOp) || isSOPK(BranchOp));
2974
2975 // Convert to dwords.
2976 BrOffset /= 4;
2977
2978 // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
2979 // from the next instruction.
2980 BrOffset -= 1;
2981
2982 return isIntN(BranchOffsetBits, BrOffset);
2983}
2984
2987 return MI.getOperand(0).getMBB();
2988}
2989
2991 for (const MachineInstr &MI : MBB->terminators()) {
2992 if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
2993 MI.getOpcode() == AMDGPU::SI_LOOP)
2994 return true;
2995 }
2996 return false;
2997}
2998
3000 MachineBasicBlock &DestBB,
3001 MachineBasicBlock &RestoreBB,
3002 const DebugLoc &DL, int64_t BrOffset,
3003 RegScavenger *RS) const {
3004 assert(MBB.empty() &&
3005 "new block should be inserted for expanding unconditional branch");
3006 assert(MBB.pred_size() == 1);
3007 assert(RestoreBB.empty() &&
3008 "restore block should be inserted for restoring clobbered registers");
3009
3010 MachineFunction *MF = MBB.getParent();
3011 MachineRegisterInfo &MRI = MF->getRegInfo();
3013 auto I = MBB.end();
3014 auto &MCCtx = MF->getContext();
3015
3016 if (ST.useAddPC64Inst()) {
3017 MCSymbol *Offset =
3018 MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
3019 auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
3021 MCSymbol *PostAddPCLabel =
3022 MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
3023 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3024 auto *OffsetExpr = MCBinaryExpr::createSub(
3025 MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
3026 MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
3027 Offset->setVariableValue(OffsetExpr);
3028 return;
3029 }
3030
3031 assert(RS && "RegScavenger required for long branching");
3032
3033 // FIXME: Virtual register workaround for RegScavenger not working with empty
3034 // blocks.
3035 Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3036
3037 // Note: as this is used after hazard recognizer we need to apply some hazard
3038 // workarounds directly.
3039 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3040 ST.hasVALUReadSGPRHazard();
3041 auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
3042 if (FlushSGPRWrites)
3043 BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
3045 };
3046
3047 // We need to compute the offset relative to the instruction immediately after
3048 // s_getpc_b64. Insert pc arithmetic code before last terminator.
3049 MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
3050 ApplyHazardWorkarounds();
3051
3052 MCSymbol *PostGetPCLabel =
3053 MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
3054 GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);
3055
3056 MCSymbol *OffsetLo =
3057 MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
3058 MCSymbol *OffsetHi =
3059 MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
3060 BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
3061 .addReg(PCReg, RegState::Define, AMDGPU::sub0)
3062 .addReg(PCReg, {}, AMDGPU::sub0)
3063 .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
3064 BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
3065 .addReg(PCReg, RegState::Define, AMDGPU::sub1)
3066 .addReg(PCReg, {}, AMDGPU::sub1)
3067 .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
3068 ApplyHazardWorkarounds();
3069
3070 // Insert the indirect branch after the other terminator.
3071 BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
3072 .addReg(PCReg);
3073
3074 // If a spill is needed for the pc register pair, we need to insert a spill
3075 // restore block right before the destination block, and insert a short branch
3076 // into the old destination block's fallthrough predecessor.
3077 // e.g.:
3078 //
3079 // s_cbranch_scc0 skip_long_branch:
3080 //
3081 // long_branch_bb:
3082 // spill s[8:9]
3083 // s_getpc_b64 s[8:9]
3084 // s_add_u32 s8, s8, restore_bb
3085 // s_addc_u32 s9, s9, 0
3086 // s_setpc_b64 s[8:9]
3087 //
3088 // skip_long_branch:
3089 // foo;
3090 //
3091 // .....
3092 //
3093 // dest_bb_fallthrough_predecessor:
3094 // bar;
3095 // s_branch dest_bb
3096 //
3097 // restore_bb:
3098 // restore s[8:9]
3099 // fallthrough dest_bb
3100 ///
3101 // dest_bb:
3102 // buzz;
3103
3104 Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
3105 Register Scav;
3106
3107 // If we've previously reserved a register for long branches
3108 // avoid running the scavenger and just use those registers
3109 if (LongBranchReservedReg) {
3110 RS->enterBasicBlock(MBB);
3111 Scav = LongBranchReservedReg;
3112 } else {
3113 RS->enterBasicBlockEnd(MBB);
3114 Scav = RS->scavengeRegisterBackwards(
3115 AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
3116 /* RestoreAfter */ false, 0, /* AllowSpill */ false);
3117 }
3118 if (Scav) {
3119 RS->setRegUsed(Scav);
3120 MRI.replaceRegWith(PCReg, Scav);
3121 MRI.clearVirtRegs();
3122 } else {
3123 // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
3124 // SGPR spill.
3125 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
3126 const SIRegisterInfo *TRI = ST.getRegisterInfo();
3127 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3128 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3129 MRI.clearVirtRegs();
3130 }
3131
3132 MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
3133 // Now, the distance could be defined.
3135 MCSymbolRefExpr::create(DestLabel, MCCtx),
3136 MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
3137 // Add offset assignments.
3138 auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
3139 OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
3140 auto *ShAmt = MCConstantExpr::create(32, MCCtx);
3141 OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
3142}
3143
3144unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
3145 switch (Cond) {
3146 case SIInstrInfo::SCC_TRUE:
3147 return AMDGPU::S_CBRANCH_SCC1;
3148 case SIInstrInfo::SCC_FALSE:
3149 return AMDGPU::S_CBRANCH_SCC0;
3150 case SIInstrInfo::VCCNZ:
3151 return AMDGPU::S_CBRANCH_VCCNZ;
3152 case SIInstrInfo::VCCZ:
3153 return AMDGPU::S_CBRANCH_VCCZ;
3154 case SIInstrInfo::EXECNZ:
3155 return AMDGPU::S_CBRANCH_EXECNZ;
3156 case SIInstrInfo::EXECZ:
3157 return AMDGPU::S_CBRANCH_EXECZ;
3158 default:
3159 llvm_unreachable("invalid branch predicate");
3160 }
3161}
3162
3163SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
3164 switch (Opcode) {
3165 case AMDGPU::S_CBRANCH_SCC0:
3166 return SCC_FALSE;
3167 case AMDGPU::S_CBRANCH_SCC1:
3168 return SCC_TRUE;
3169 case AMDGPU::S_CBRANCH_VCCNZ:
3170 return VCCNZ;
3171 case AMDGPU::S_CBRANCH_VCCZ:
3172 return VCCZ;
3173 case AMDGPU::S_CBRANCH_EXECNZ:
3174 return EXECNZ;
3175 case AMDGPU::S_CBRANCH_EXECZ:
3176 return EXECZ;
3177 default:
3178 return INVALID_BR;
3179 }
3180}
3181
3185 MachineBasicBlock *&FBB,
3187 bool AllowModify) const {
3188 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3189 // Unconditional Branch
3190 TBB = I->getOperand(0).getMBB();
3191 return false;
3192 }
3193
3194 BranchPredicate Pred = getBranchPredicate(I->getOpcode());
3195 if (Pred == INVALID_BR)
3196 return true;
3197
3198 MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
3199 Cond.push_back(MachineOperand::CreateImm(Pred));
3200 Cond.push_back(I->getOperand(1)); // Save the branch register.
3201
3202 ++I;
3203
3204 if (I == MBB.end()) {
3205 // Conditional branch followed by fall-through.
3206 TBB = CondBB;
3207 return false;
3208 }
3209
3210 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3211 TBB = CondBB;
3212 FBB = I->getOperand(0).getMBB();
3213 return false;
3214 }
3215
3216 return true;
3217}
3218
3220 MachineBasicBlock *&FBB,
3222 bool AllowModify) const {
3223 MachineBasicBlock::iterator I = MBB.getFirstTerminator();
3224 auto E = MBB.end();
3225 if (I == E)
3226 return false;
3227
3228 // Skip over the instructions that are artificially terminators for special
3229 // exec management.
3230 while (I != E && !I->isBranch() && !I->isReturn()) {
3231 switch (I->getOpcode()) {
3232 case AMDGPU::S_MOV_B64_term:
3233 case AMDGPU::S_XOR_B64_term:
3234 case AMDGPU::S_OR_B64_term:
3235 case AMDGPU::S_ANDN2_B64_term:
3236 case AMDGPU::S_AND_B64_term:
3237 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3238 case AMDGPU::S_MOV_B32_term:
3239 case AMDGPU::S_XOR_B32_term:
3240 case AMDGPU::S_OR_B32_term:
3241 case AMDGPU::S_ANDN2_B32_term:
3242 case AMDGPU::S_AND_B32_term:
3243 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3244 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3245 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3246 break;
3247 case AMDGPU::SI_IF:
3248 case AMDGPU::SI_ELSE:
3249 case AMDGPU::SI_KILL_I1_TERMINATOR:
3250 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3251 // FIXME: It's messy that these need to be considered here at all.
3252 return true;
3253 default:
3254 llvm_unreachable("unexpected non-branch terminator inst");
3255 }
3256
3257 ++I;
3258 }
3259
3260 if (I == E)
3261 return false;
3262
3263 return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
3264}
3265
3267 int *BytesRemoved) const {
3268 unsigned Count = 0;
3269 unsigned RemovedSize = 0;
3270 for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
3271 // Skip over artificial terminators when removing instructions.
3272 if (MI.isBranch() || MI.isReturn()) {
3273 RemovedSize += getInstSizeInBytes(MI);
3274 MI.eraseFromParent();
3275 ++Count;
3276 }
3277 }
3278
3279 if (BytesRemoved)
3280 *BytesRemoved = RemovedSize;
3281
3282 return Count;
3283}
3284
3285// Copy the flags onto the implicit condition register operand.
3287 const MachineOperand &OrigCond) {
3288 CondReg.setIsUndef(OrigCond.isUndef());
3289 CondReg.setIsKill(OrigCond.isKill());
3290}
3291
3294 MachineBasicBlock *FBB,
3296 const DebugLoc &DL,
3297 int *BytesAdded) const {
3298 if (!FBB && Cond.empty()) {
3299 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3300 .addMBB(TBB);
3301 if (BytesAdded)
3302 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3303 return 1;
3304 }
3305
3306 assert(TBB && Cond[0].isImm());
3307
3308 unsigned Opcode
3309 = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));
3310
3311 if (!FBB) {
3312 MachineInstr *CondBr =
3313 BuildMI(&MBB, DL, get(Opcode))
3314 .addMBB(TBB);
3315
3316 // Copy the flags onto the implicit condition register operand.
3317 preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
3318 fixImplicitOperands(*CondBr);
3319
3320 if (BytesAdded)
3321 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3322 return 1;
3323 }
3324
3325 assert(TBB && FBB);
3326
3327 MachineInstr *CondBr =
3328 BuildMI(&MBB, DL, get(Opcode))
3329 .addMBB(TBB);
3330 fixImplicitOperands(*CondBr);
3331 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3332 .addMBB(FBB);
3333
3334 MachineOperand &CondReg = CondBr->getOperand(1);
3335 CondReg.setIsUndef(Cond[1].isUndef());
3336 CondReg.setIsKill(Cond[1].isKill());
3337
3338 if (BytesAdded)
3339 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3340
3341 return 2;
3342}
3343
3346 if (Cond.size() != 2) {
3347 return true;
3348 }
3349
3350 if (Cond[0].isImm()) {
3351 Cond[0].setImm(-Cond[0].getImm());
3352 return false;
3353 }
3354
3355 return true;
3356}
3357
3360 Register DstReg, Register TrueReg,
3361 Register FalseReg, int &CondCycles,
3362 int &TrueCycles, int &FalseCycles) const {
3363 switch (Cond[0].getImm()) {
3364 case VCCNZ:
3365 case VCCZ: {
3366 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3367 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3368 if (MRI.getRegClass(FalseReg) != RC)
3369 return false;
3370
3371 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3372 CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
3373
3374 // Limit to equal cost for branch vs. N v_cndmask_b32s.
3375 return RI.hasVGPRs(RC) && NumInsts <= 6;
3376 }
3377 case SCC_TRUE:
3378 case SCC_FALSE: {
3379 // FIXME: We could insert for VGPRs if we could replace the original compare
3380 // with a vector one.
3381 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3382 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3383 if (MRI.getRegClass(FalseReg) != RC)
3384 return false;
3385
3386 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3387
3388 // Multiples of 8 can do s_cselect_b64
3389 if (NumInsts % 2 == 0)
3390 NumInsts /= 2;
3391
3392 CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
3393 return RI.isSGPRClass(RC);
3394 }
3395 default:
3396 return false;
3397 }
3398}
3399
3403 Register TrueReg, Register FalseReg) const {
3404 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3405 if (Pred == VCCZ || Pred == SCC_FALSE) {
3406 Pred = static_cast<BranchPredicate>(-Pred);
3407 std::swap(TrueReg, FalseReg);
3408 }
3409
3410 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3411 const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
3412 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3413
3414 if (DstSize == 32) {
3416 if (Pred == SCC_TRUE) {
3417 Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
3418 .addReg(TrueReg)
3419 .addReg(FalseReg);
3420 } else {
3421 // Instruction's operands are backwards from what is expected.
3422 Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
3423 .addReg(FalseReg)
3424 .addReg(TrueReg);
3425 }
3426
3427 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3428 return;
3429 }
3430
3431 if (DstSize == 64 && Pred == SCC_TRUE) {
3433 BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
3434 .addReg(TrueReg)
3435 .addReg(FalseReg);
3436
3437 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3438 return;
3439 }
3440
3441 static const int16_t Sub0_15[] = {
3442 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3443 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3444 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3445 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3446 };
3447
3448 static const int16_t Sub0_15_64[] = {
3449 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3450 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3451 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3452 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3453 };
3454
3455 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3456 const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
3457 const int16_t *SubIndices = Sub0_15;
3458 int NElts = DstSize / 32;
3459
3460 // 64-bit select is only available for SALU.
3461 // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
3462 if (Pred == SCC_TRUE) {
3463 if (NElts % 2) {
3464 SelOp = AMDGPU::S_CSELECT_B32;
3465 EltRC = &AMDGPU::SGPR_32RegClass;
3466 } else {
3467 SelOp = AMDGPU::S_CSELECT_B64;
3468 EltRC = &AMDGPU::SGPR_64RegClass;
3469 SubIndices = Sub0_15_64;
3470 NElts /= 2;
3471 }
3472 }
3473
3475 MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);
3476
3477 I = MIB->getIterator();
3478
3480 for (int Idx = 0; Idx != NElts; ++Idx) {
3481 Register DstElt = MRI.createVirtualRegister(EltRC);
3482 Regs.push_back(DstElt);
3483
3484 unsigned SubIdx = SubIndices[Idx];
3485
3487 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3488 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3489 .addReg(FalseReg, {}, SubIdx)
3490 .addReg(TrueReg, {}, SubIdx);
3491 } else {
3492 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3493 .addReg(TrueReg, {}, SubIdx)
3494 .addReg(FalseReg, {}, SubIdx);
3495 }
3496
3497 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3499
3500 MIB.addReg(DstElt)
3501 .addImm(SubIdx);
3502 }
3503}
3504
3506
3507 if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
3508 return true;
3509
3510 switch (MI.getOpcode()) {
3511 case AMDGPU::S_ENDPGM:
3512 case AMDGPU::S_ENDPGM_SAVED:
3513 case AMDGPU::S_TRAP:
3514 case AMDGPU::S_GETREG_B32:
3515 case AMDGPU::S_SETREG_B32:
3516 case AMDGPU::S_SETREG_B32_mode:
3517 case AMDGPU::S_SETREG_IMM32_B32:
3518 case AMDGPU::S_SETREG_IMM32_B32_mode:
3519 case AMDGPU::S_SENDMSG:
3520 case AMDGPU::S_SENDMSGHALT:
3521 case AMDGPU::S_SENDMSG_RTN_B32:
3522 case AMDGPU::S_SENDMSG_RTN_B64:
3523 case AMDGPU::S_BARRIER_WAIT:
3524 case AMDGPU::S_BARRIER_SIGNAL_M0:
3525 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3526 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3527 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3528 return true;
3529 default:
3530 return false;
3531 }
3532}
3533
3535 switch (MI.getOpcode()) {
3536 case AMDGPU::V_MOV_B16_t16_e32:
3537 case AMDGPU::V_MOV_B16_t16_e64:
3538 case AMDGPU::V_MOV_B32_e32:
3539 case AMDGPU::V_MOV_B32_e64:
3540 case AMDGPU::V_MOV_B64_PSEUDO:
3541 case AMDGPU::V_MOV_B64_e32:
3542 case AMDGPU::V_MOV_B64_e64:
3543 case AMDGPU::S_MOV_B32:
3544 case AMDGPU::S_MOV_B64:
3545 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3546 case AMDGPU::COPY:
3547 case AMDGPU::WWM_COPY:
3548 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3549 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3550 case AMDGPU::V_ACCVGPR_MOV_B32:
3551 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3552 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3553 return true;
3554 default:
3555 return false;
3556 }
3557}
3558
3560 switch (MI.getOpcode()) {
3561 case AMDGPU::V_MOV_B16_t16_e32:
3562 case AMDGPU::V_MOV_B16_t16_e64:
3563 return 2;
3564 case AMDGPU::V_MOV_B32_e32:
3565 case AMDGPU::V_MOV_B32_e64:
3566 case AMDGPU::V_MOV_B64_PSEUDO:
3567 case AMDGPU::V_MOV_B64_e32:
3568 case AMDGPU::V_MOV_B64_e64:
3569 case AMDGPU::S_MOV_B32:
3570 case AMDGPU::S_MOV_B64:
3571 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3572 case AMDGPU::COPY:
3573 case AMDGPU::WWM_COPY:
3574 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3575 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3576 case AMDGPU::V_ACCVGPR_MOV_B32:
3577 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3578 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3579 return 1;
3580 default:
3581 llvm_unreachable("MI is not a foldable copy");
3582 }
3583}
3584
3585static constexpr AMDGPU::OpName ModifierOpNames[] = {
3586 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3587 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3588 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3589
3591 unsigned Opc = MI.getOpcode();
3592 for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
3593 int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
3594 if (Idx >= 0)
3595 MI.removeOperand(Idx);
3596 }
3597}
3598
3600 const MCInstrDesc &NewDesc) const {
3601 MI.setDesc(NewDesc);
3602
3603 // Remove any leftover implicit operands from mutating the instruction. e.g.
3604 // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
3605 // anymore.
3606 const MCInstrDesc &Desc = MI.getDesc();
3607 unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
3608 Desc.implicit_defs().size();
3609
3610 for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
3611 MI.removeOperand(I);
3612}
3613
3614std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
3615 unsigned SubRegIndex) {
3616 switch (SubRegIndex) {
3617 case AMDGPU::NoSubRegister:
3618 return Imm;
3619 case AMDGPU::sub0:
3620 return SignExtend64<32>(Imm);
3621 case AMDGPU::sub1:
3622 return SignExtend64<32>(Imm >> 32);
3623 case AMDGPU::lo16:
3624 return SignExtend64<16>(Imm);
3625 case AMDGPU::hi16:
3626 return SignExtend64<16>(Imm >> 16);
3627 case AMDGPU::sub1_lo16:
3628 return SignExtend64<16>(Imm >> 32);
3629 case AMDGPU::sub1_hi16:
3630 return SignExtend64<16>(Imm >> 48);
3631 default:
3632 return std::nullopt;
3633 }
3634
3635 llvm_unreachable("covered subregister switch");
3636}
3637
3638static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
3639 switch (Opc) {
3640 case AMDGPU::V_MAC_F16_e32:
3641 case AMDGPU::V_MAC_F16_e64:
3642 case AMDGPU::V_MAD_F16_e64:
3643 return AMDGPU::V_MADAK_F16;
3644 case AMDGPU::V_MAC_F32_e32:
3645 case AMDGPU::V_MAC_F32_e64:
3646 case AMDGPU::V_MAD_F32_e64:
3647 return AMDGPU::V_MADAK_F32;
3648 case AMDGPU::V_FMAC_F32_e32:
3649 case AMDGPU::V_FMAC_F32_e64:
3650 case AMDGPU::V_FMA_F32_e64:
3651 return AMDGPU::V_FMAAK_F32;
3652 case AMDGPU::V_FMAC_F16_e32:
3653 case AMDGPU::V_FMAC_F16_e64:
3654 case AMDGPU::V_FMAC_F16_t16_e64:
3655 case AMDGPU::V_FMAC_F16_fake16_e64:
3656 case AMDGPU::V_FMAC_F16_t16_e32:
3657 case AMDGPU::V_FMAC_F16_fake16_e32:
3658 case AMDGPU::V_FMA_F16_e64:
3659 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3660 ? AMDGPU::V_FMAAK_F16_t16
3661 : AMDGPU::V_FMAAK_F16_fake16
3662 : AMDGPU::V_FMAAK_F16;
3663 case AMDGPU::V_FMAC_F64_e32:
3664 case AMDGPU::V_FMAC_F64_e64:
3665 case AMDGPU::V_FMA_F64_e64:
3666 return AMDGPU::V_FMAAK_F64;
3667 default:
3668 llvm_unreachable("invalid instruction");
3669 }
3670}
3671
3672static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
3673 switch (Opc) {
3674 case AMDGPU::V_MAC_F16_e32:
3675 case AMDGPU::V_MAC_F16_e64:
3676 case AMDGPU::V_MAD_F16_e64:
3677 return AMDGPU::V_MADMK_F16;
3678 case AMDGPU::V_MAC_F32_e32:
3679 case AMDGPU::V_MAC_F32_e64:
3680 case AMDGPU::V_MAD_F32_e64:
3681 return AMDGPU::V_MADMK_F32;
3682 case AMDGPU::V_FMAC_F32_e32:
3683 case AMDGPU::V_FMAC_F32_e64:
3684 case AMDGPU::V_FMA_F32_e64:
3685 return AMDGPU::V_FMAMK_F32;
3686 case AMDGPU::V_FMAC_F16_e32:
3687 case AMDGPU::V_FMAC_F16_e64:
3688 case AMDGPU::V_FMAC_F16_t16_e64:
3689 case AMDGPU::V_FMAC_F16_fake16_e64:
3690 case AMDGPU::V_FMAC_F16_t16_e32:
3691 case AMDGPU::V_FMAC_F16_fake16_e32:
3692 case AMDGPU::V_FMA_F16_e64:
3693 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3694 ? AMDGPU::V_FMAMK_F16_t16
3695 : AMDGPU::V_FMAMK_F16_fake16
3696 : AMDGPU::V_FMAMK_F16;
3697 case AMDGPU::V_FMAC_F64_e32:
3698 case AMDGPU::V_FMAC_F64_e64:
3699 case AMDGPU::V_FMA_F64_e64:
3700 return AMDGPU::V_FMAMK_F64;
3701 default:
3702 llvm_unreachable("invalid instruction");
3703 }
3704}
3705
3707 Register Reg, MachineRegisterInfo *MRI) const {
3708 int64_t Imm;
3709 if (!getConstValDefinedInReg(DefMI, Reg, Imm))
3710 return false;
3711
3712 const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);
3713
3714 assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");
3715
3716 unsigned Opc = UseMI.getOpcode();
3717 if (Opc == AMDGPU::COPY) {
3718 assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");
3719
3720 Register DstReg = UseMI.getOperand(0).getReg();
3721 Register UseSubReg = UseMI.getOperand(1).getSubReg();
3722
3723 const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);
3724
3725 if (HasMultipleUses) {
3726 // TODO: This should fold in more cases with multiple use, but we need to
3727 // more carefully consider what those uses are.
3728 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));
3729
3730 // Avoid breaking up a 64-bit inline immediate into a subregister extract.
3731 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3732 return false;
3733
3734 // Most of the time folding a 32-bit inline constant is free (though this
3735 // might not be true if we can't later fold it into a real user).
3736 //
3737 // FIXME: This isInlineConstant check is imprecise if
3738 // getConstValDefinedInReg handled the tricky non-mov cases.
3739 if (ImmDefSize == 32 &&
3741 return false;
3742 }
3743
3744 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3745 RI.getSubRegIdxSize(UseSubReg) == 16;
3746
3747 if (Is16Bit) {
3748 if (RI.hasVGPRs(DstRC))
3749 return false; // Do not clobber vgpr_hi16
3750
3751 if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
3752 return false;
3753 }
3754
3755 MachineFunction *MF = UseMI.getMF();
3756
3757 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3758 MCRegister MovDstPhysReg =
3759 DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();
3760
3761 std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);
3762
3763 // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
3764 for (unsigned MovOp :
3765 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3766 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3767 const MCInstrDesc &MovDesc = get(MovOp);
3768
3769 const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
3770 if (Is16Bit) {
3771 // We just need to find a correctly sized register class, so the
3772 // subregister index compatibility doesn't matter since we're statically
3773 // extracting the immediate value.
3774 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3775 if (!MovDstRC)
3776 continue;
3777
3778 if (MovDstPhysReg) {
3779 // FIXME: We probably should not do this. If there is a live value in
3780 // the high half of the register, it will be corrupted.
3781 MovDstPhysReg =
3782 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3783 if (!MovDstPhysReg)
3784 continue;
3785 }
3786 }
3787
3788 // Result class isn't the right size, try the next instruction.
3789 if (MovDstPhysReg) {
3790 if (!MovDstRC->contains(MovDstPhysReg))
3791 return false;
3792 } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
3793 // TODO: This will be overly conservative in the case of 16-bit virtual
3794 // SGPRs. We could hack up the virtual register uses to use a compatible
3795 // 32-bit class.
3796 continue;
3797 }
3798
3799 const MCOperandInfo &OpInfo = MovDesc.operands()[1];
3800
3801 // Ensure the interpreted immediate value is a valid operand in the new
3802 // mov.
3803 //
3804 // FIXME: isImmOperandLegal should have form that doesn't require existing
3805 // MachineInstr or MachineOperand
3806 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3807 !isInlineConstant(*SubRegImm, OpInfo.OperandType))
3808 break;
3809
3810 NewOpc = MovOp;
3811 break;
3812 }
3813
3814 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
3815 return false;
3816
3817 if (Is16Bit) {
3818 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
3819 if (MovDstPhysReg)
3820 UseMI.getOperand(0).setReg(MovDstPhysReg);
3821 assert(UseMI.getOperand(1).getReg().isVirtual());
3822 }
3823
3824 const MCInstrDesc &NewMCID = get(NewOpc);
3825 UseMI.setDesc(NewMCID);
3826 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
3827 UseMI.addImplicitDefUseOperands(*MF);
3828 return true;
3829 }
3830
3831 if (HasMultipleUses)
3832 return false;
3833
3834 if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
3835 Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
3836 Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
3837 Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
3838 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3839 Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
3840 Opc == AMDGPU::V_FMAC_F64_e64) {
3841 // Don't fold if we are using source or output modifiers. The new VOP2
3842 // instructions don't have them.
3844 return false;
3845
3846 // If this is a free constant, there's no reason to do this.
3847 // TODO: We could fold this here instead of letting SIFoldOperands do it
3848 // later.
3849 int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
3850
3851 // Any src operand can be used for the legality check.
3852 if (isInlineConstant(UseMI, Src0Idx, Imm))
3853 return false;
3854
3855 MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);
3856
3857 MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
3858 MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);
3859
3860 auto CopyRegOperandToNarrowerRC =
3861 [MRI, this](MachineInstr &MI, unsigned OpNo,
3862 const TargetRegisterClass *NewRC) -> void {
3863 if (!MI.getOperand(OpNo).isReg())
3864 return;
3865 Register Reg = MI.getOperand(OpNo).getReg();
3866 const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
3867 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
3868 return;
3869 Register Tmp = MRI->createVirtualRegister(NewRC);
3870 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
3871 get(AMDGPU::COPY), Tmp)
3872 .addReg(Reg);
3873 MI.getOperand(OpNo).setReg(Tmp);
3874 MI.getOperand(OpNo).setIsKill();
3875 };
3876
3877 // Multiplied part is the constant: Use v_madmk_{f16, f32}.
3878 if ((Src0->isReg() && Src0->getReg() == Reg) ||
3879 (Src1->isReg() && Src1->getReg() == Reg)) {
3880 MachineOperand *RegSrc =
3881 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
3882 if (!RegSrc->isReg())
3883 return false;
3884 if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
3885 ST.getConstantBusLimit(Opc) < 2)
3886 return false;
3887
3888 if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
3889 return false;
3890
3891 // If src2 is also a literal constant then we have to choose which one to
3892 // fold. In general it is better to choose madak so that the other literal
3893 // can be materialized in an sgpr instead of a vgpr:
3894 // s_mov_b32 s0, literal
3895 // v_madak_f32 v0, s0, v0, literal
3896 // Instead of:
3897 // v_mov_b32 v1, literal
3898 // v_madmk_f32 v0, v0, literal, v1
3899 MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
3900 if (Def && Def->isMoveImmediate() &&
3901 !isInlineConstant(Def->getOperand(1)))
3902 return false;
3903
3904 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
3905 if (pseudoToMCOpcode(NewOpc) == -1)
3906 return false;
3907
3908 const std::optional<int64_t> SubRegImm = extractSubregFromImm(
3909 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
3910
3911 // FIXME: This would be a lot easier if we could return a new instruction
3912 // instead of having to modify in place.
3913
3914 Register SrcReg = RegSrc->getReg();
3915 unsigned SrcSubReg = RegSrc->getSubReg();
3916 Src0->setReg(SrcReg);
3917 Src0->setSubReg(SrcSubReg);
3918 Src0->setIsKill(RegSrc->isKill());
3919
3920 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
3921 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3922 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3923 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
3924 UseMI.untieRegOperand(
3925 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
3926
3927 Src1->ChangeToImmediate(*SubRegImm);
3928
3930 UseMI.setDesc(get(NewOpc));
3931
3932 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
3933 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
3934 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
3935 Register Tmp = MRI->createVirtualRegister(NewRC);
3936 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
3937 UseMI.getDebugLoc(), get(AMDGPU::COPY),
3938 UseMI.getOperand(0).getReg())
3939 .addReg(Tmp, RegState::Kill);
3940 UseMI.getOperand(0).setReg(Tmp);
3941 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
3942 CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
3943 }
3944
3945 bool DeleteDef = MRI->use_nodbg_empty(Reg);
3946 if (DeleteDef)
3947 DefMI.eraseFromParent();
3948
3949 return true;
3950 }
3951
3952 // Added part is the constant: Use v_madak_{f16, f32}.
3953 if (Src2->isReg() && Src2->getReg() == Reg) {
3954 if (ST.getConstantBusLimit(Opc) < 2) {
3955 // Not allowed to use constant bus for another operand.
3956 // We can however allow an inline immediate as src0.
3957 bool Src0Inlined = false;
3958 if (Src0->isReg()) {
3959 // Try to inline constant if possible.
3960 // If the Def moves immediate and the use is single
3961 // We are saving VGPR here.
3962 MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
3963 if (Def && Def->isMoveImmediate() &&
3964 isInlineConstant(Def->getOperand(1)) &&
3965 MRI->hasOneNonDBGUse(Src0->getReg())) {
3966 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
3967 Src0Inlined = true;
3968 } else if (ST.getConstantBusLimit(Opc) <= 1 &&
3969 RI.isSGPRReg(*MRI, Src0->getReg())) {
3970 return false;
3971 }
3972 // VGPR is okay as Src0 - fallthrough
3973 }
3974
3975 if (Src1->isReg() && !Src0Inlined) {
3976 // We have one slot for inlinable constant so far - try to fill it
3977 MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
3978 if (Def && Def->isMoveImmediate() &&
3979 isInlineConstant(Def->getOperand(1)) &&
3980 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
3981 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
3982 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
3983 return false;
3984 // VGPR is okay as Src1 - fallthrough
3985 }
3986 }
3987
3988 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
3989 if (pseudoToMCOpcode(NewOpc) == -1)
3990 return false;
3991
3992 // FIXME: This would be a lot easier if we could return a new instruction
3993 // instead of having to modify in place.
3994
3995 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
3996 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3997 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3998 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
3999 UseMI.untieRegOperand(
4000 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4001
4002 const std::optional<int64_t> SubRegImm =
4003 extractSubregFromImm(Imm, Src2->getSubReg());
4004
4005 // ChangingToImmediate adds Src2 back to the instruction.
4006 Src2->ChangeToImmediate(*SubRegImm);
4007
4008 // These come before src2.
4010 UseMI.setDesc(get(NewOpc));
4011
4012 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4013 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4014 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4015 Register Tmp = MRI->createVirtualRegister(NewRC);
4016 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4017 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4018 UseMI.getOperand(0).getReg())
4019 .addReg(Tmp, RegState::Kill);
4020 UseMI.getOperand(0).setReg(Tmp);
4021 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4022 CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
4023 }
4024
4025 // It might happen that UseMI was commuted
4026 // and we now have SGPR as SRC1. If so 2 inlined
4027 // constant and SGPR are illegal.
4029
4030 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4031 if (DeleteDef)
4032 DefMI.eraseFromParent();
4033
4034 return true;
4035 }
4036 }
4037
4038 return false;
4039}
4040
4041static bool
4044 if (BaseOps1.size() != BaseOps2.size())
4045 return false;
4046 for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
4047 if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
4048 return false;
4049 }
4050 return true;
4051}
4052
4053static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
4054 LocationSize WidthB, int OffsetB) {
4055 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4056 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4057 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4058 return LowWidth.hasValue() &&
4059 LowOffset + (int)LowWidth.getValue() <= HighOffset;
4060}
4061
4062bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
4063 const MachineInstr &MIb) const {
4064 SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
4065 int64_t Offset0, Offset1;
4066 LocationSize Dummy0 = LocationSize::precise(0);
4067 LocationSize Dummy1 = LocationSize::precise(0);
4068 bool Offset0IsScalable, Offset1IsScalable;
4069 if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
4070 Dummy0, &RI) ||
4071 !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
4072 Dummy1, &RI))
4073 return false;
4074
4075 if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
4076 return false;
4077
4078 if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
4079 // FIXME: Handle ds_read2 / ds_write2.
4080 return false;
4081 }
4082 LocationSize Width0 = MIa.memoperands().front()->getSize();
4083 LocationSize Width1 = MIb.memoperands().front()->getSize();
4084 return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
4085}
4086
4088 const MachineInstr &MIb) const {
4089 assert(MIa.mayLoadOrStore() &&
4090 "MIa must load from or modify a memory location");
4091 assert(MIb.mayLoadOrStore() &&
4092 "MIb must load from or modify a memory location");
4093
4095 return false;
4096
4097 // XXX - Can we relax this between address spaces?
4098 if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
4099 return false;
4100
4101 if (isLDSDMA(MIa) || isLDSDMA(MIb))
4102 return false;
4103
4104 if (MIa.isBundle() || MIb.isBundle())
4105 return false;
4106
4107 // TODO: Should we check the address space from the MachineMemOperand? That
4108 // would allow us to distinguish objects we know don't alias based on the
4109 // underlying address space, even if it was lowered to a different one,
4110 // e.g. private accesses lowered to use MUBUF instructions on a scratch
4111 // buffer.
4112 if (isDS(MIa)) {
4113 if (isDS(MIb))
4114 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4115
4116 return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
4117 }
4118
4119 if (isMUBUF(MIa) || isMTBUF(MIa)) {
4120 if (isMUBUF(MIb) || isMTBUF(MIb))
4121 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4122
4123 if (isFLAT(MIb))
4124 return isFLATScratch(MIb);
4125
4126 return !isSMRD(MIb);
4127 }
4128
4129 if (isSMRD(MIa)) {
4130 if (isSMRD(MIb))
4131 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4132
4133 if (isFLAT(MIb))
4134 return isFLATScratch(MIb);
4135
4136 return !isMUBUF(MIb) && !isMTBUF(MIb);
4137 }
4138
4139 if (isFLAT(MIa)) {
4140 if (isFLAT(MIb)) {
4141 if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
4142 (isFLATGlobal(MIa) && isFLATScratch(MIb)))
4143 return true;
4144
4145 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4146 }
4147
4148 return false;
4149 }
4150
4151 return false;
4152}
4153
4155 int64_t &Imm, MachineInstr **DefMI = nullptr) {
4156 if (Reg.isPhysical())
4157 return false;
4158 auto *Def = MRI.getUniqueVRegDef(Reg);
4159 if (Def && SIInstrInfo::isFoldableCopy(*Def) && Def->getOperand(1).isImm()) {
4160 Imm = Def->getOperand(1).getImm();
4161 if (DefMI)
4162 *DefMI = Def;
4163 return true;
4164 }
4165 return false;
4166}
4167
4168static bool getFoldableImm(const MachineOperand *MO, int64_t &Imm,
4169 MachineInstr **DefMI = nullptr) {
4170 if (!MO->isReg())
4171 return false;
4172 const MachineFunction *MF = MO->getParent()->getMF();
4173 const MachineRegisterInfo &MRI = MF->getRegInfo();
4174 return getFoldableImm(MO->getReg(), MRI, Imm, DefMI);
4175}
4176
4178 MachineInstr &NewMI) {
4179 if (LV) {
4180 unsigned NumOps = MI.getNumOperands();
4181 for (unsigned I = 1; I < NumOps; ++I) {
4182 MachineOperand &Op = MI.getOperand(I);
4183 if (Op.isReg() && Op.isKill())
4184 LV->replaceKillInstruction(Op.getReg(), MI, NewMI);
4185 }
4186 }
4187}
4188
4189static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
4190 switch (Opc) {
4191 case AMDGPU::V_MAC_F16_e32:
4192 case AMDGPU::V_MAC_F16_e64:
4193 return AMDGPU::V_MAD_F16_e64;
4194 case AMDGPU::V_MAC_F32_e32:
4195 case AMDGPU::V_MAC_F32_e64:
4196 return AMDGPU::V_MAD_F32_e64;
4197 case AMDGPU::V_MAC_LEGACY_F32_e32:
4198 case AMDGPU::V_MAC_LEGACY_F32_e64:
4199 return AMDGPU::V_MAD_LEGACY_F32_e64;
4200 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4201 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4202 return AMDGPU::V_FMA_LEGACY_F32_e64;
4203 case AMDGPU::V_FMAC_F16_e32:
4204 case AMDGPU::V_FMAC_F16_e64:
4205 case AMDGPU::V_FMAC_F16_t16_e64:
4206 case AMDGPU::V_FMAC_F16_fake16_e64:
4207 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4208 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4209 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4210 : AMDGPU::V_FMA_F16_gfx9_e64;
4211 case AMDGPU::V_FMAC_F32_e32:
4212 case AMDGPU::V_FMAC_F32_e64:
4213 return AMDGPU::V_FMA_F32_e64;
4214 case AMDGPU::V_FMAC_F64_e32:
4215 case AMDGPU::V_FMAC_F64_e64:
4216 return AMDGPU::V_FMA_F64_e64;
4217 default:
4218 llvm_unreachable("invalid instruction");
4219 }
4220}
4221
4222/// Helper struct for the implementation of 3-address conversion to communicate
4223/// updates made to instruction operands.
4225 /// Other instruction whose def is no longer used by the converted
4226 /// instruction.
4228};
4229
4231 LiveVariables *LV,
4232 LiveIntervals *LIS) const {
4233 MachineBasicBlock &MBB = *MI.getParent();
4234 MachineInstr *CandidateMI = &MI;
4235
4236 if (MI.isBundle()) {
4237 // This is a temporary placeholder for bundle handling that enables us to
4238 // exercise the relevant code paths in the two-address instruction pass.
4239 if (MI.getBundleSize() != 1)
4240 return nullptr;
4241 CandidateMI = MI.getNextNode();
4242 }
4243
4245 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4246 if (!NewMI)
4247 return nullptr;
4248
4249 if (MI.isBundle()) {
4250 CandidateMI->eraseFromBundle();
4251
4252 for (MachineOperand &MO : MI.all_defs()) {
4253 if (MO.isTied())
4254 MI.untieRegOperand(MO.getOperandNo());
4255 }
4256 } else {
4257 updateLiveVariables(LV, MI, *NewMI);
4258 if (LIS) {
4259 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
4260 // SlotIndex of defs needs to be updated when converting to early-clobber
4261 MachineOperand &Def = NewMI->getOperand(0);
4262 if (Def.isEarlyClobber() && Def.isReg() &&
4263 LIS->hasInterval(Def.getReg())) {
4264 SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
4265 SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
4266 auto &LI = LIS->getInterval(Def.getReg());
4267 auto UpdateDefIndex = [&](LiveRange &LR) {
4268 auto *S = LR.find(OldIndex);
4269 if (S != LR.end() && S->start == OldIndex) {
4270 assert(S->valno && S->valno->def == OldIndex);
4271 S->start = NewIndex;
4272 S->valno->def = NewIndex;
4273 }
4274 };
4275 UpdateDefIndex(LI);
4276 for (auto &SR : LI.subranges())
4277 UpdateDefIndex(SR);
4278 }
4279 }
4280 }
4281
4282 if (U.RemoveMIUse) {
4283 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4284 // The only user is the instruction which will be killed.
4285 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4286
4287 if (MRI.hasOneNonDBGUse(DefReg)) {
4288 // We cannot just remove the DefMI here, calling pass will crash.
4289 U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
4290 U.RemoveMIUse->getOperand(0).setIsDead(true);
4291 for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
4292 U.RemoveMIUse->removeOperand(I);
4293 if (LV)
4294 LV->getVarInfo(DefReg).AliveBlocks.clear();
4295 }
4296
4297 if (MI.isBundle()) {
4298 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4299 if (!VRI.Reads && !VRI.Writes) {
4300 for (MachineOperand &MO : MI.all_uses()) {
4301 if (MO.isReg() && MO.getReg() == DefReg) {
4302 assert(MO.getSubReg() == 0 &&
4303 "tied sub-registers in bundles currently not supported");
4304 MI.removeOperand(MO.getOperandNo());
4305 break;
4306 }
4307 }
4308
4309 if (LIS)
4310 LIS->shrinkToUses(&LIS->getInterval(DefReg));
4311 }
4312 } else if (LIS) {
4313 LiveInterval &DefLI = LIS->getInterval(DefReg);
4314
4315 // We cannot delete the original instruction here, so hack out the use
4316 // in the original instruction with a dummy register so we can use
4317 // shrinkToUses to deal with any multi-use edge cases. Other targets do
4318 // not have the complexity of deleting a use to consider here.
4319 Register DummyReg = MRI.cloneVirtualRegister(DefReg);
4320 for (MachineOperand &MIOp : MI.uses()) {
4321 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4322 MIOp.setIsUndef(true);
4323 MIOp.setReg(DummyReg);
4324 }
4325 }
4326
4327 if (MI.isBundle()) {
4328 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4329 if (!VRI.Reads && !VRI.Writes) {
4330 for (MachineOperand &MIOp : MI.uses()) {
4331 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4332 MIOp.setIsUndef(true);
4333 MIOp.setReg(DummyReg);
4334 }
4335 }
4336 }
4337
4338 MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
4339 false, /*isUndef=*/true));
4340 }
4341
4342 LIS->shrinkToUses(&DefLI);
4343 }
4344 }
4345
4346 return MI.isBundle() ? &MI : NewMI;
4347}
4348
4350SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
4351 ThreeAddressUpdates &U) const {
4352 MachineBasicBlock &MBB = *MI.getParent();
4353 unsigned Opc = MI.getOpcode();
4354
4355 // Handle MFMA.
4356 int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
4357 if (NewMFMAOpc != -1) {
4359 BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
4360 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4361 MIB.add(MI.getOperand(I));
4362 return MIB;
4363 }
4364
4365 if (SIInstrInfo::isWMMA(MI)) {
4366 unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
4367 MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4368 .setMIFlags(MI.getFlags());
4369 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4370 MIB->addOperand(MI.getOperand(I));
4371 return MIB;
4372 }
4373
4374 assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4375 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4376 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4377 "present pre-RA");
4378
4379 // Handle MAC/FMAC.
4380 bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
4381 bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4382 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4383 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4384 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4385 bool Src0Literal = false;
4386
4387 switch (Opc) {
4388 default:
4389 return nullptr;
4390 case AMDGPU::V_MAC_F16_e64:
4391 case AMDGPU::V_FMAC_F16_e64:
4392 case AMDGPU::V_FMAC_F16_t16_e64:
4393 case AMDGPU::V_FMAC_F16_fake16_e64:
4394 case AMDGPU::V_MAC_F32_e64:
4395 case AMDGPU::V_MAC_LEGACY_F32_e64:
4396 case AMDGPU::V_FMAC_F32_e64:
4397 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4398 case AMDGPU::V_FMAC_F64_e64:
4399 break;
4400 case AMDGPU::V_MAC_F16_e32:
4401 case AMDGPU::V_FMAC_F16_e32:
4402 case AMDGPU::V_MAC_F32_e32:
4403 case AMDGPU::V_MAC_LEGACY_F32_e32:
4404 case AMDGPU::V_FMAC_F32_e32:
4405 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4406 case AMDGPU::V_FMAC_F64_e32: {
4407 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
4408 AMDGPU::OpName::src0);
4409 const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
4410 if (!Src0->isReg() && !Src0->isImm())
4411 return nullptr;
4412
4413 if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
4414 Src0Literal = true;
4415
4416 break;
4417 }
4418 }
4419
4420 MachineInstrBuilder MIB;
4421 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
4422 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
4423 const MachineOperand *Src0Mods =
4424 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
4425 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4426 const MachineOperand *Src1Mods =
4427 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
4428 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4429 const MachineOperand *Src2Mods =
4430 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
4431 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
4432 const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
4433 const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);
4434
4435 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4436 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4437 // If we have an SGPR input, we will violate the constant bus restriction.
4438 (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
4439 !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
4440 MachineInstr *DefMI = nullptr;
4441
4442 int64_t Imm;
4443 if (!Src0Literal && getFoldableImm(Src2, Imm, &DefMI)) {
4444 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4445 if (pseudoToMCOpcode(NewOpc) != -1) {
4446 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4447 .add(*Dst)
4448 .add(*Src0)
4449 .add(*Src1)
4450 .addImm(Imm)
4451 .setMIFlags(MI.getFlags());
4452 U.RemoveMIUse = DefMI;
4453 return MIB;
4454 }
4455 }
4456 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4457 if (!Src0Literal && getFoldableImm(Src1, Imm, &DefMI)) {
4458 if (pseudoToMCOpcode(NewOpc) != -1) {
4459 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4460 .add(*Dst)
4461 .add(*Src0)
4462 .addImm(Imm)
4463 .add(*Src2)
4464 .setMIFlags(MI.getFlags());
4465 U.RemoveMIUse = DefMI;
4466 return MIB;
4467 }
4468 }
4469 if (Src0Literal || getFoldableImm(Src0, Imm, &DefMI)) {
4470 if (Src0Literal) {
4471 Imm = Src0->getImm();
4472 DefMI = nullptr;
4473 }
4474 if (pseudoToMCOpcode(NewOpc) != -1 &&
4476 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4477 Src1)) {
4478 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4479 .add(*Dst)
4480 .add(*Src1)
4481 .addImm(Imm)
4482 .add(*Src2)
4483 .setMIFlags(MI.getFlags());
4484 U.RemoveMIUse = DefMI;
4485 return MIB;
4486 }
4487 }
4488 }
4489
4490 // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
4491 // if VOP3 does not allow a literal operand.
4492 if (Src0Literal && !ST.hasVOP3Literal())
4493 return nullptr;
4494
4495 unsigned NewOpc = getNewFMAInst(ST, Opc);
4496
4497 if (pseudoToMCOpcode(NewOpc) == -1)
4498 return nullptr;
4499
4500 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4501 .add(*Dst)
4502 .addImm(Src0Mods ? Src0Mods->getImm() : 0)
4503 .add(*Src0)
4504 .addImm(Src1Mods ? Src1Mods->getImm() : 0)
4505 .add(*Src1)
4506 .addImm(Src2Mods ? Src2Mods->getImm() : 0)
4507 .add(*Src2)
4508 .addImm(Clamp ? Clamp->getImm() : 0)
4509 .addImm(Omod ? Omod->getImm() : 0)
4510 .setMIFlags(MI.getFlags());
4511 if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
4512 MIB.addImm(OpSel ? OpSel->getImm() : 0);
4513 return MIB;
4514}
4515
4516// It's not generally safe to move VALU instructions across these since it will
4517// start using the register as a base index rather than directly.
4518// XXX - Why isn't hasSideEffects sufficient for these?
4520 switch (MI.getOpcode()) {
4521 case AMDGPU::S_SET_GPR_IDX_ON:
4522 case AMDGPU::S_SET_GPR_IDX_MODE:
4523 case AMDGPU::S_SET_GPR_IDX_OFF:
4524 return true;
4525 default:
4526 return false;
4527 }
4528}
4529
4531 const MachineBasicBlock *MBB,
4532 const MachineFunction &MF) const {
4533 // Skipping the check for SP writes in the base implementation. The reason it
4534 // was added was apparently due to compile time concerns.
4535 //
4536 // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
4537 // but is probably avoidable.
4538
4539 // Copied from base implementation.
4540 // Terminators and labels can't be scheduled around.
4541 if (MI.isTerminator() || MI.isPosition())
4542 return true;
4543
4544 // INLINEASM_BR can jump to another block
4545 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4546 return true;
4547
4548 if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
4549 return true;
4550
4551 // Target-independent instructions do not have an implicit-use of EXEC, even
4552 // when they operate on VGPRs. Treating EXEC modifications as scheduling
4553 // boundaries prevents incorrect movements of such instructions.
4554 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4555 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4556 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4557 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4558 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4560}
4561
4563 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4564 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4565 Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
4566}
4567
4569 // Instructions that access scratch use FLAT encoding or BUF encodings.
4570 if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
4571 return false;
4572
4573 // SCRATCH instructions always access scratch.
4574 if (isFLATScratch(MI))
4575 return true;
4576
4577 // If FLAT_SCRATCH registers are not initialized, we can never access scratch
4578 // via the aperture.
4579 if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
4580 return false;
4581
4582 // If there are no memory operands then conservatively assume the flat
4583 // operation may access scratch.
4584 if (MI.memoperands_empty())
4585 return true;
4586
4587 // See if any memory operand specifies an address space that involves scratch.
4588 return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
4589 unsigned AS = Memop->getAddrSpace();
4590 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4591 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4592 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4593 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4594 }
4595 return AS == AMDGPUAS::PRIVATE_ADDRESS;
4596 });
4597}
4598
4600 assert(isFLAT(MI));
4601
4602 // All flat instructions use the VMEM counter except prefetch.
4603 if (!usesVM_CNT(MI))
4604 return false;
4605
4606 // If there are no memory operands then conservatively assume the flat
4607 // operation may access VMEM.
4608 if (MI.memoperands_empty())
4609 return true;
4610
4611 // See if any memory operand specifies an address space that involves VMEM.
4612 // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
4613 // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
4614 // (GDS) address space is not supported by flat operations. Therefore, simply
4615 // return true unless only the LDS address space is found.
4616 for (const MachineMemOperand *Memop : MI.memoperands()) {
4617 unsigned AS = Memop->getAddrSpace();
4619 if (AS != AMDGPUAS::LOCAL_ADDRESS)
4620 return true;
4621 }
4622
4623 return false;
4624}
4625
4627 bool TgSplit) const {
4628 assert(isFLAT(MI));
4629
4630 // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
4631 if (!usesLGKM_CNT(MI))
4632 return false;
4633
4634 // If in tgsplit mode then there can be no use of LDS.
4635 if (TgSplit)
4636 return false;
4637
4638 // If there are no memory operands then conservatively assume the flat
4639 // operation may access LDS.
4640 if (MI.memoperands_empty())
4641 return true;
4642
4643 // See if any memory operand specifies an address space that involves LDS.
4644 for (const MachineMemOperand *Memop : MI.memoperands()) {
4645 unsigned AS = Memop->getAddrSpace();
4647 return true;
4648 }
4649
4650 return false;
4651}
4652
4654 // Skip the full operand and register alias search modifiesRegister
4655 // does. There's only a handful of instructions that touch this, it's only an
4656 // implicit def, and doesn't alias any other registers.
4657 return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
4658}
4659
4661 unsigned Opcode = MI.getOpcode();
4662
4663 if (MI.mayStore() && isSMRD(MI))
4664 return true; // scalar store or atomic
4665
4666 // This will terminate the function when other lanes may need to continue.
4667 if (MI.isReturn())
4668 return true;
4669
4670 // These instructions cause shader I/O that may cause hardware lockups
4671 // when executed with an empty EXEC mask.
4672 //
4673 // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
4674 // EXEC = 0, but checking for that case here seems not worth it
4675 // given the typical code patterns.
4676 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4677 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4678 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4679 Opcode == AMDGPU::S_SETHALT)
4680 return true;
4681
4682 if (MI.isCall() || MI.isInlineAsm())
4683 return true; // conservative assumption
4684
4685 // Assume that barrier interactions are only intended with active lanes.
4686 if (isBarrier(Opcode))
4687 return true;
4688
4689 // A mode change is a scalar operation that influences vector instructions.
4691 return true;
4692
4693 // These are like SALU instructions in terms of effects, so it's questionable
4694 // whether we should return true for those.
4695 //
4696 // However, executing them with EXEC = 0 causes them to operate on undefined
4697 // data, which we avoid by returning true here.
4698 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4699 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4700 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4701 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4702 return true;
4703
4704 return false;
4705}
4706
4708 const MachineInstr &MI) const {
4709 if (MI.isMetaInstruction())
4710 return false;
4711
4712 // This won't read exec if this is an SGPR->SGPR copy.
4713 if (MI.isCopyLike()) {
4714 if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
4715 return true;
4716
4717 // Make sure this isn't copying exec as a normal operand
4718 return MI.readsRegister(AMDGPU::EXEC, &RI);
4719 }
4720
4721 // Make a conservative assumption about the callee.
4722 if (MI.isCall())
4723 return true;
4724
4725 // Be conservative with any unhandled generic opcodes.
4726 if (!isTargetSpecificOpcode(MI.getOpcode()))
4727 return true;
4728
4729 return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
4730}
4731
4732bool SIInstrInfo::isInlineConstant(const APInt &Imm) const {
4733 switch (Imm.getBitWidth()) {
4734 case 1: // This likely will be a condition code mask.
4735 return true;
4736
4737 case 32:
4738 return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
4739 ST.hasInv2PiInlineImm());
4740 case 64:
4741 return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
4742 ST.hasInv2PiInlineImm());
4743 case 16:
4744 return ST.has16BitInsts() &&
4745 AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
4746 ST.hasInv2PiInlineImm());
4747 default:
4748 llvm_unreachable("invalid bitwidth");
4749 }
4750}
4751
4753 APInt IntImm = Imm.bitcastToAPInt();
4754 int64_t IntImmVal = IntImm.getSExtValue();
4755 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4756 switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
4757 default:
4758 llvm_unreachable("invalid fltSemantics");
4761 return isInlineConstant(IntImm);
4763 return ST.has16BitInsts() &&
4764 AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
4766 return ST.has16BitInsts() &&
4767 AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
4768 }
4769}
4770
4771bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
4772 // MachineOperand provides no way to tell the true operand size, since it only
4773 // records a 64-bit value. We need to know the size to determine if a 32-bit
4774 // floating point immediate bit pattern is legal for an integer immediate. It
4775 // would be for any 32-bit integer operand, but would not be for a 64-bit one.
4776 switch (OperandType) {
4786 int32_t Trunc = static_cast<int32_t>(Imm);
4787 return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
4788 }
4796 return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
4799 // We would expect inline immediates to not be concerned with an integer/fp
4800 // distinction. However, in the case of 16-bit integer operations, the
4801 // "floating point" values appear to not work. It seems read the low 16-bits
4802 // of 32-bit immediates, which happens to always work for the integer
4803 // values.
4804 //
4805 // See llvm bugzilla 46302.
4806 //
4807 // TODO: Theoretically we could use op-sel to use the high bits of the
4808 // 32-bit FP values.
4817 return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
4822 return false;
4825 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
4826 // A few special case instructions have 16-bit operands on subtargets
4827 // where 16-bit instructions are not legal.
4828 // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
4829 // constants in these cases
4830 int16_t Trunc = static_cast<int16_t>(Imm);
4831 return ST.has16BitInsts() &&
4832 AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
4833 }
4834
4835 return false;
4836 }
4839 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
4840 int16_t Trunc = static_cast<int16_t>(Imm);
4841 return ST.has16BitInsts() &&
4842 AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
4843 }
4844 return false;
4845 }
4849 return false;
4851 return isLegalAV64PseudoImm(Imm);
4854 // Always embedded in the instruction for free.
4855 return true;
4865 // Just ignore anything else.
4866 return false;
4867 default:
4868 llvm_unreachable("invalid operand type");
4869 }
4870}
4871
4872static bool compareMachineOp(const MachineOperand &Op0,
4873 const MachineOperand &Op1) {
4874 if (Op0.getType() != Op1.getType())
4875 return false;
4876
4877 switch (Op0.getType()) {
4879 return Op0.getReg() == Op1.getReg();
4881 return Op0.getImm() == Op1.getImm();
4882 default:
4883 llvm_unreachable("Didn't expect to be comparing these operand types");
4884 }
4885}
4886
4888 const MCOperandInfo &OpInfo) const {
4889 if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
4890 return true;
4891
4892 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
4893 return false;
4894
4895 if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
4896 return true;
4897
4898 return ST.hasVOP3Literal();
4899}
4900
4901bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
4902 int64_t ImmVal) const {
4903 const unsigned Opc = InstDesc.getOpcode();
4904 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
4905 if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
4906 OpNo == static_cast<unsigned>(Src1Idx))
4907 return false;
4908
4909 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
4910 if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
4911 if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
4912 OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
4913 AMDGPU::OpName::src2))
4914 return false;
4915 return RI.opCanUseInlineConstant(OpInfo.OperandType);
4916 }
4917
4918 return isLiteralOperandLegal(InstDesc, OpInfo);
4919}
4920
4921bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
4922 const MachineOperand &MO) const {
4923 if (MO.isImm())
4924 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
4925
4926 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
4927 "unexpected imm-like operand kind");
4928 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
4929 return isLiteralOperandLegal(InstDesc, OpInfo);
4930}
4931
4933 // 2 32-bit inline constants packed into one.
4934 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
4935 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
4936}
4937
4938bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
4939 // GFX90A does not have V_MUL_LEGACY_F32_e32.
4940 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
4941 return false;
4942
4943 int Op32 = AMDGPU::getVOPe32(Opcode);
4944 if (Op32 == -1)
4945 return false;
4946
4947 return pseudoToMCOpcode(Op32) != -1;
4948}
4949
4950bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
4951 // The src0_modifier operand is present on all instructions
4952 // that have modifiers.
4953
4954 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
4955}
4956
4958 AMDGPU::OpName OpName) const {
4959 const MachineOperand *Mods = getNamedOperand(MI, OpName);
4960 return Mods && Mods->getImm();
4961}
4962
4964 return any_of(ModifierOpNames,
4965 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
4966}
4967
4969 const MachineRegisterInfo &MRI) const {
4970 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4971 // Can't shrink instruction with three operands.
4972 if (Src2) {
4973 switch (MI.getOpcode()) {
4974 default: return false;
4975
4976 case AMDGPU::V_ADDC_U32_e64:
4977 case AMDGPU::V_SUBB_U32_e64:
4978 case AMDGPU::V_SUBBREV_U32_e64: {
4979 const MachineOperand *Src1
4980 = getNamedOperand(MI, AMDGPU::OpName::src1);
4981 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
4982 return false;
4983 // Additional verification is needed for sdst/src2.
4984 return true;
4985 }
4986 case AMDGPU::V_MAC_F16_e64:
4987 case AMDGPU::V_MAC_F32_e64:
4988 case AMDGPU::V_MAC_LEGACY_F32_e64:
4989 case AMDGPU::V_FMAC_F16_e64:
4990 case AMDGPU::V_FMAC_F16_t16_e64:
4991 case AMDGPU::V_FMAC_F16_fake16_e64:
4992 case AMDGPU::V_FMAC_F32_e64:
4993 case AMDGPU::V_FMAC_F64_e64:
4994 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4995 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
4996 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
4997 return false;
4998 break;
4999
5000 case AMDGPU::V_CNDMASK_B32_e64:
5001 break;
5002 }
5003 }
5004
5005 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
5006 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5007 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
5008 return false;
5009
5010 // We don't need to check src0, all input types are legal, so just make sure
5011 // src0 isn't using any modifiers.
5012 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
5013 return false;
5014
5015 // Can it be shrunk to a valid 32 bit opcode?
5016 if (!hasVALU32BitEncoding(MI.getOpcode()))
5017 return false;
5018
5019 // Check output modifiers
5020 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
5021 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
5022 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
5023 // TODO: Can we avoid checking bound_ctrl/fi here?
5024 // They are only used by permlane*_swap special case.
5025 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
5026 !hasModifiersSet(MI, AMDGPU::OpName::fi);
5027}
5028
5029// Set VCC operand with all flags from \p Orig, except for setting it as
5030// implicit.
5032 const MachineOperand &Orig) {
5033
5034 for (MachineOperand &Use : MI.implicit_operands()) {
5035 if (Use.isUse() &&
5036 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
5037 Use.setIsUndef(Orig.isUndef());
5038 Use.setIsKill(Orig.isKill());
5039 return;
5040 }
5041 }
5042}
5043
5045 unsigned Op32) const {
5046 MachineBasicBlock *MBB = MI.getParent();
5047
5048 const MCInstrDesc &Op32Desc = get(Op32);
5049 MachineInstrBuilder Inst32 =
5050 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
5051 .setMIFlags(MI.getFlags());
5052
5053 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
5054 // For VOPC instructions, this is replaced by an implicit def of vcc.
5055
5056 // We assume the defs of the shrunk opcode are in the same order, and the
5057 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
5058 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
5059 Inst32.add(MI.getOperand(I));
5060
5061 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5062
5063 int Idx = MI.getNumExplicitDefs();
5064 for (const MachineOperand &Use : MI.explicit_uses()) {
5065 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
5067 continue;
5068
5069 if (&Use == Src2) {
5070 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5071 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
5072 // replaced with an implicit read of vcc or vcc_lo. The implicit read
5073 // of vcc was already added during the initial BuildMI, but we
5074 // 1) may need to change vcc to vcc_lo to preserve the original register
5075 // 2) have to preserve the original flags.
5076 copyFlagsToImplicitVCC(*Inst32, *Src2);
5077 continue;
5078 }
5079 }
5080
5081 Inst32.add(Use);
5082 }
5083
5084 // FIXME: Losing implicit operands
5085 fixImplicitOperands(*Inst32);
5086 return Inst32;
5087}
5088
5090 // Null is free
5091 Register Reg = RegOp.getReg();
5092 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5093 return false;
5094
5095 // SGPRs use the constant bus
5096
5097 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
5098 // physical register operands should also count, except for exec.
5099 if (RegOp.isImplicit())
5100 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5101
5102 // SGPRs use the constant bus
5103 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5104 AMDGPU::SReg_64RegClass.contains(Reg);
5105}
5106
5108 const MachineRegisterInfo &MRI) const {
5109 Register Reg = RegOp.getReg();
5110 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5111 : physRegUsesConstantBus(RegOp);
5112}
5113
5115 const MachineOperand &MO,
5116 const MCOperandInfo &OpInfo) const {
5117 // Literal constants use the constant bus.
5118 if (!MO.isReg())
5119 return !isInlineConstant(MO, OpInfo);
5120
5121 Register Reg = MO.getReg();
5122 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5124}
5125
5127 for (const MachineOperand &MO : MI.implicit_operands()) {
5128 // We only care about reads.
5129 if (MO.isDef())
5130 continue;
5131
5132 switch (MO.getReg()) {
5133 case AMDGPU::VCC:
5134 case AMDGPU::VCC_LO:
5135 case AMDGPU::VCC_HI:
5136 case AMDGPU::M0:
5137 case AMDGPU::FLAT_SCR:
5138 return MO.getReg();
5139
5140 default:
5141 break;
5142 }
5143 }
5144
5145 return Register();
5146}
5147
5148static bool shouldReadExec(const MachineInstr &MI) {
5149 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5150 switch (MI.getOpcode()) {
5151 case AMDGPU::V_READLANE_B32:
5152 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5153 case AMDGPU::V_WRITELANE_B32:
5154 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5155 return false;
5156 }
5157
5158 return true;
5159 }
5160
5161 if (MI.isPreISelOpcode() ||
5162 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5165 return false;
5166
5167 return true;
5168}
5169
5170static bool isRegOrFI(const MachineOperand &MO) {
5171 return MO.isReg() || MO.isFI();
5172}
5173
5174static bool isSubRegOf(const SIRegisterInfo &TRI,
5175 const MachineOperand &SuperVec,
5176 const MachineOperand &SubReg) {
5177 if (SubReg.getReg().isPhysical())
5178 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5179
5180 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5181 SubReg.getReg() == SuperVec.getReg();
5182}
5183
5184// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5185bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5186 const MachineRegisterInfo &MRI,
5187 StringRef &ErrInfo) const {
5188 Register DstReg = MI.getOperand(0).getReg();
5189 Register SrcReg = MI.getOperand(1).getReg();
5190 // This is a check for copy from vector register to SGPR
5191 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5192 ErrInfo = "illegal copy from vector register to SGPR";
5193 return false;
5194 }
5195 return true;
5196}
5197
5199 StringRef &ErrInfo) const {
5200 uint32_t Opcode = MI.getOpcode();
5201 const MachineFunction *MF = MI.getMF();
5202 const MachineRegisterInfo &MRI = MF->getRegInfo();
5203
5204 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5205 // Find a better property to recognize the point where instruction selection
5206 // is just done.
5207 // We can only enforce this check after SIFixSGPRCopies pass so that the
5208 // illegal copies are legalized and thereafter we don't expect a pass
5209 // inserting similar copies.
5210 if (!MRI.isSSA() && MI.isCopy())
5211 return verifyCopy(MI, MRI, ErrInfo);
5212
5213 if (SIInstrInfo::isGenericOpcode(Opcode))
5214 return true;
5215
5216 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5217 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5218 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5219 int Src3Idx = -1;
5220 if (Src0Idx == -1) {
5221 // VOPD V_DUAL_* instructions use different operand names.
5222 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5223 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5224 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5225 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5226 }
5227
5228 // Make sure the number of operands is correct.
5229 const MCInstrDesc &Desc = get(Opcode);
5230 if (!Desc.isVariadic() &&
5231 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5232 ErrInfo = "Instruction has wrong number of operands.";
5233 return false;
5234 }
5235
5236 if (MI.isInlineAsm()) {
5237 // Verify register classes for inlineasm constraints.
5238 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5239 I != E; ++I) {
5240 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5241 if (!RC)
5242 continue;
5243
5244 const MachineOperand &Op = MI.getOperand(I);
5245 if (!Op.isReg())
5246 continue;
5247
5248 Register Reg = Op.getReg();
5249 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5250 ErrInfo = "inlineasm operand has incorrect register class.";
5251 return false;
5252 }
5253 }
5254
5255 return true;
5256 }
5257
5258 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5259 ErrInfo = "missing memory operand from image instruction.";
5260 return false;
5261 }
5262
5263 // Make sure the register classes are correct.
5264 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5265 const MachineOperand &MO = MI.getOperand(i);
5266 if (MO.isFPImm()) {
5267 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5268 "all fp values to integers.";
5269 return false;
5270 }
5271
5272 const MCOperandInfo &OpInfo = Desc.operands()[i];
5273 int16_t RegClass = getOpRegClassID(OpInfo);
5274
5275 switch (OpInfo.OperandType) {
5277 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5278 ErrInfo = "Illegal immediate value for operand.";
5279 return false;
5280 }
5281 break;
5293 break;
5295 break;
5296 break;
5310 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5311 ErrInfo = "Illegal immediate value for operand.";
5312 return false;
5313 }
5314 break;
5315 }
5320 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5321 !isInlineConstant(MI, i) &&
5323 OpInfo.OperandType ==
5325 ErrInfo = "illegal 64-bit immediate value for operand.";
5326 return false;
5327 }
5328 break;
5331 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5332 ErrInfo = "Expected inline constant for operand.";
5333 return false;
5334 }
5335 break;
5338 break;
5343 // Check if this operand is an immediate.
5344 // FrameIndex operands will be replaced by immediates, so they are
5345 // allowed.
5346 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5347 ErrInfo = "Expected immediate, but got non-immediate";
5348 return false;
5349 }
5350 break;
5354 break;
5355 default:
5356 if (OpInfo.isGenericType())
5357 continue;
5358 break;
5359 }
5360
5361 if (!MO.isReg())
5362 continue;
5363 Register Reg = MO.getReg();
5364 if (!Reg)
5365 continue;
5366
5367 // FIXME: Ideally we would have separate instruction definitions with the
5368 // aligned register constraint.
5369 // FIXME: We do not verify inline asm operands, but custom inline asm
5370 // verification is broken anyway
5371 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5372 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !isSpill(MI)) {
5373 const TargetRegisterClass *RC = RI.getRegClassForReg(MRI, Reg);
5374 if (RI.hasVectorRegisters(RC) && MO.getSubReg()) {
5375 if (const TargetRegisterClass *SubRC =
5376 RI.getSubRegisterClass(RC, MO.getSubReg())) {
5377 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.getSubReg());
5378 if (RC)
5379 RC = SubRC;
5380 }
5381 }
5382
5383 // Check that this is the aligned version of the class.
5384 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5385 ErrInfo = "Subtarget requires even aligned vector registers";
5386 return false;
5387 }
5388 }
5389
5390 if (RegClass != -1) {
5391 if (Reg.isVirtual())
5392 continue;
5393
5394 const TargetRegisterClass *RC = RI.getRegClass(RegClass);
5395 if (!RC->contains(Reg)) {
5396 ErrInfo = "Operand has incorrect register class.";
5397 return false;
5398 }
5399 }
5400 }
5401
5402 // Verify SDWA
5403 if (isSDWA(MI)) {
5404 if (!ST.hasSDWA()) {
5405 ErrInfo = "SDWA is not supported on this target";
5406 return false;
5407 }
5408
5409 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5410 AMDGPU::OpName::dst_sel}) {
5411 const MachineOperand *MO = getNamedOperand(MI, Op);
5412 if (!MO)
5413 continue;
5414 int64_t Imm = MO->getImm();
5415 if (Imm < 0 || Imm > AMDGPU::SDWA::SdwaSel::DWORD) {
5416 ErrInfo = "Invalid SDWA selection";
5417 return false;
5418 }
5419 }
5420
5421 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5422
5423 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5424 if (OpIdx == -1)
5425 continue;
5426 const MachineOperand &MO = MI.getOperand(OpIdx);
5427
5428 if (!ST.hasSDWAScalar()) {
5429 // Only VGPRS on VI
5430 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5431 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5432 return false;
5433 }
5434 } else {
5435 // No immediates on GFX9
5436 if (!MO.isReg()) {
5437 ErrInfo =
5438 "Only reg allowed as operands in SDWA instructions on GFX9+";
5439 return false;
5440 }
5441 }
5442 }
5443
5444 if (!ST.hasSDWAOmod()) {
5445 // No omod allowed on VI
5446 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5447 if (OMod != nullptr &&
5448 (!OMod->isImm() || OMod->getImm() != 0)) {
5449 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5450 return false;
5451 }
5452 }
5453
5454 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5455 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5456 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5457 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5458 const MachineOperand *Src0ModsMO =
5459 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5460 unsigned Mods = Src0ModsMO->getImm();
5461 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5462 Mods & SISrcMods::SEXT) {
5463 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5464 return false;
5465 }
5466 }
5467
5468 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5469 if (isVOPC(BasicOpcode)) {
5470 if (!ST.hasSDWASdst() && DstIdx != -1) {
5471 // Only vcc allowed as dst on VI for VOPC
5472 const MachineOperand &Dst = MI.getOperand(DstIdx);
5473 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5474 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5475 return false;
5476 }
5477 } else if (!ST.hasSDWAOutModsVOPC()) {
5478 // No clamp allowed on GFX9 for VOPC
5479 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5480 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5481 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5482 return false;
5483 }
5484
5485 // No omod allowed on GFX9 for VOPC
5486 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5487 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5488 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5489 return false;
5490 }
5491 }
5492 }
5493
5494 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5495 if (DstUnused && DstUnused->isImm() &&
5496 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5497 const MachineOperand &Dst = MI.getOperand(DstIdx);
5498 if (!Dst.isReg() || !Dst.isTied()) {
5499 ErrInfo = "Dst register should have tied register";
5500 return false;
5501 }
5502
5503 const MachineOperand &TiedMO =
5504 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5505 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5506 ErrInfo =
5507 "Dst register should be tied to implicit use of preserved register";
5508 return false;
5509 }
5510 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5511 ErrInfo = "Dst register should use same physical register as preserved";
5512 return false;
5513 }
5514 }
5515 }
5516
5517 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5518 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5519 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5520 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5521 return false;
5522 }
5523 if (Src1MO.isImm()) {
5524 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5525 return false;
5526 }
5527 }
5528
5529 // Verify MIMG / VIMAGE / VSAMPLE
5530 if (isImage(Opcode) && !MI.mayStore()) {
5531 // Ensure that the return type used is large enough for all the options
5532 // being used TFE/LWE require an extra result register.
5533 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5534 if (DMask) {
5535 uint64_t DMaskImm = DMask->getImm();
5536 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5537 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5538 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5539 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5540
5541 // Adjust for packed 16 bit values
5542 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5543 RegCount = divideCeil(RegCount, 2);
5544
5545 // Adjust if using LWE or TFE
5546 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5547 RegCount += 1;
5548
5549 const uint32_t DstIdx =
5550 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5551 const MachineOperand &Dst = MI.getOperand(DstIdx);
5552 if (Dst.isReg()) {
5553 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5554 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5555 if (RegCount > DstSize) {
5556 ErrInfo = "Image instruction returns too many registers for dst "
5557 "register class";
5558 return false;
5559 }
5560 }
5561 }
5562 }
5563
5564 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5565 if (isVALU(MI, /*AllowLDSDMA=*/true) &&
5566 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5567 unsigned ConstantBusCount = 0;
5568 bool UsesLiteral = false;
5569 const MachineOperand *LiteralVal = nullptr;
5570
5571 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5572 if (ImmIdx != -1) {
5573 ++ConstantBusCount;
5574 UsesLiteral = true;
5575 LiteralVal = &MI.getOperand(ImmIdx);
5576 }
5577
5578 SmallVector<Register, 2> SGPRsUsed;
5579 Register SGPRUsed;
5580
5581 // Only look at the true operands. Only a real operand can use the constant
5582 // bus, and we don't want to check pseudo-operands like the source modifier
5583 // flags.
5584 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5585 if (OpIdx == -1)
5586 continue;
5587 const MachineOperand &MO = MI.getOperand(OpIdx);
5588 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5589 if (MO.isReg()) {
5590 SGPRUsed = MO.getReg();
5591 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5592 ++ConstantBusCount;
5593 SGPRsUsed.push_back(SGPRUsed);
5594 }
5595 } else if (!MO.isFI()) { // Treat FI like a register.
5596 if (!UsesLiteral) {
5597 ++ConstantBusCount;
5598 UsesLiteral = true;
5599 LiteralVal = &MO;
5600 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5601 assert(isVOP2(MI) || isVOP3(MI));
5602 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5603 return false;
5604 }
5605 }
5606 }
5607 }
5608
5609 SGPRUsed = findImplicitSGPRRead(MI);
5610 if (SGPRUsed) {
5611 // Implicit uses may safely overlap true operands
5612 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5613 return !RI.regsOverlap(SGPRUsed, SGPR);
5614 })) {
5615 ++ConstantBusCount;
5616 SGPRsUsed.push_back(SGPRUsed);
5617 }
5618 }
5619
5620 // v_writelane_b32 is an exception from constant bus restriction:
5621 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5622 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5623 Opcode != AMDGPU::V_WRITELANE_B32) {
5624 ErrInfo = "VOP* instruction violates constant bus restriction";
5625 return false;
5626 }
5627
5628 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5629 ErrInfo = "VOP3 instruction uses literal";
5630 return false;
5631 }
5632 }
5633
5634 // Special case for writelane - this can break the multiple constant bus rule,
5635 // but still can't use more than one SGPR register
5636 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5637 unsigned SGPRCount = 0;
5638 Register SGPRUsed;
5639
5640 for (int OpIdx : {Src0Idx, Src1Idx}) {
5641 if (OpIdx == -1)
5642 break;
5643
5644 const MachineOperand &MO = MI.getOperand(OpIdx);
5645
5646 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5647 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5648 if (MO.getReg() != SGPRUsed)
5649 ++SGPRCount;
5650 SGPRUsed = MO.getReg();
5651 }
5652 }
5653 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5654 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5655 return false;
5656 }
5657 }
5658 }
5659
5660 // Verify misc. restrictions on specific instructions.
5661 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5662 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5663 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5664 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5665 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
5666 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5667 if (!compareMachineOp(Src0, Src1) &&
5668 !compareMachineOp(Src0, Src2)) {
5669 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
5670 return false;
5671 }
5672 }
5673 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
5674 SISrcMods::ABS) ||
5675 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
5676 SISrcMods::ABS) ||
5677 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
5678 SISrcMods::ABS)) {
5679 ErrInfo = "ABS not allowed in VOP3B instructions";
5680 return false;
5681 }
5682 }
5683
5684 if (isSOP2(MI) || isSOPC(MI)) {
5685 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5686 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5687
5688 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
5689 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
5690 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
5691 !Src0.isIdenticalTo(Src1)) {
5692 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
5693 return false;
5694 }
5695 }
5696
5697 if (isSOPK(MI)) {
5698 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
5699 if (Desc.isBranch()) {
5700 if (!Op->isMBB()) {
5701 ErrInfo = "invalid branch target for SOPK instruction";
5702 return false;
5703 }
5704 } else {
5705 uint64_t Imm = Op->getImm();
5706 if (sopkIsZext(Opcode)) {
5707 if (!isUInt<16>(Imm)) {
5708 ErrInfo = "invalid immediate for SOPK instruction";
5709 return false;
5710 }
5711 } else {
5712 if (!isInt<16>(Imm)) {
5713 ErrInfo = "invalid immediate for SOPK instruction";
5714 return false;
5715 }
5716 }
5717 }
5718 }
5719
5720 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5721 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5722 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5723 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5724 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5725 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5726
5727 const unsigned StaticNumOps =
5728 Desc.getNumOperands() + Desc.implicit_uses().size();
5729 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5730
5731 // Require additional implicit operands. This allows a fixup done by the
5732 // post RA scheduler where the main implicit operand is killed and
5733 // implicit-defs are added for sub-registers that remain live after this
5734 // instruction.
5735 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5736 ErrInfo = "missing implicit register operands";
5737 return false;
5738 }
5739
5740 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5741 if (IsDst) {
5742 if (!Dst->isUse()) {
5743 ErrInfo = "v_movreld_b32 vdst should be a use operand";
5744 return false;
5745 }
5746
5747 unsigned UseOpIdx;
5748 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5749 UseOpIdx != StaticNumOps + 1) {
5750 ErrInfo = "movrel implicit operands should be tied";
5751 return false;
5752 }
5753 }
5754
5755 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5756 const MachineOperand &ImpUse
5757 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5758 if (!ImpUse.isReg() || !ImpUse.isUse() ||
5759 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5760 ErrInfo = "src0 should be subreg of implicit vector use";
5761 return false;
5762 }
5763 }
5764
5765 // Make sure we aren't losing exec uses in the td files. This mostly requires
5766 // being careful when using let Uses to try to add other use registers.
5767 if (shouldReadExec(MI)) {
5768 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5769 ErrInfo = "VALU instruction does not implicitly read exec mask";
5770 return false;
5771 }
5772 }
5773
5774 if (isSMRD(MI)) {
5775 if (MI.mayStore() &&
5776 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
5777 // The register offset form of scalar stores may only use m0 as the
5778 // soffset register.
5779 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
5780 if (Soff && Soff->getReg() != AMDGPU::M0) {
5781 ErrInfo = "scalar stores must use m0 as offset register";
5782 return false;
5783 }
5784 }
5785 }
5786
5787 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
5788 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
5789 if (Offset->getImm() != 0) {
5790 ErrInfo = "subtarget does not support offsets in flat instructions";
5791 return false;
5792 }
5793 }
5794
5795 if (isDS(MI) && !ST.hasGDS()) {
5796 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
5797 if (GDSOp && GDSOp->getImm() != 0) {
5798 ErrInfo = "GDS is not supported on this subtarget";
5799 return false;
5800 }
5801 }
5802
5803 if (isImage(MI)) {
5804 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
5805 if (DimOp) {
5806 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5807 AMDGPU::OpName::vaddr0);
5808 AMDGPU::OpName RSrcOpName =
5809 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5810 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5811 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
5812 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
5813 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
5814 const AMDGPU::MIMGDimInfo *Dim =
5816
5817 if (!Dim) {
5818 ErrInfo = "dim is out of range";
5819 return false;
5820 }
5821
5822 bool IsA16 = false;
5823 if (ST.hasR128A16()) {
5824 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
5825 IsA16 = R128A16->getImm() != 0;
5826 } else if (ST.hasA16()) {
5827 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
5828 IsA16 = A16->getImm() != 0;
5829 }
5830
5831 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5832
5833 unsigned AddrWords =
5834 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
5835
5836 unsigned VAddrWords;
5837 if (IsNSA) {
5838 VAddrWords = RsrcIdx - VAddr0Idx;
5839 if (ST.hasPartialNSAEncoding() &&
5840 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
5841 unsigned LastVAddrIdx = RsrcIdx - 1;
5842 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
5843 }
5844 } else {
5845 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
5846 if (AddrWords > 12)
5847 AddrWords = 16;
5848 }
5849
5850 if (VAddrWords != AddrWords) {
5851 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
5852 << " but got " << VAddrWords << "\n");
5853 ErrInfo = "bad vaddr size";
5854 return false;
5855 }
5856 }
5857 }
5858
5859 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
5860 if (DppCt) {
5861 using namespace AMDGPU::DPP;
5862
5863 unsigned DC = DppCt->getImm();
5864 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5865 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5866 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5867 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5868 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5869 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5870 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5871 ErrInfo = "Invalid dpp_ctrl value";
5872 return false;
5873 }
5874 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5875 !ST.hasDPPWavefrontShifts()) {
5876 ErrInfo = "Invalid dpp_ctrl value: "
5877 "wavefront shifts are not supported on GFX10+";
5878 return false;
5879 }
5880 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5881 !ST.hasDPPBroadcasts()) {
5882 ErrInfo = "Invalid dpp_ctrl value: "
5883 "broadcasts are not supported on GFX10+";
5884 return false;
5885 }
5886 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
5887 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
5888 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
5889 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
5890 !ST.hasGFX90AInsts()) {
5891 ErrInfo = "Invalid dpp_ctrl value: "
5892 "row_newbroadcast/row_share is not supported before "
5893 "GFX90A/GFX10";
5894 return false;
5895 }
5896 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
5897 ErrInfo = "Invalid dpp_ctrl value: "
5898 "row_share and row_xmask are not supported before GFX10";
5899 return false;
5900 }
5901 }
5902
5903 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
5905 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
5906 ErrInfo = "Invalid dpp_ctrl value: "
5907 "DP ALU dpp only support row_newbcast";
5908 return false;
5909 }
5910 }
5911
5912 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
5913 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5914 AMDGPU::OpName DataName =
5915 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
5916 const MachineOperand *Data = getNamedOperand(MI, DataName);
5917 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
5918 if (Data && !Data->isReg())
5919 Data = nullptr;
5920
5921 if (!ST.hasGFX90AInsts()) {
5922 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
5923 (Data && RI.isAGPR(MRI, Data->getReg())) ||
5924 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
5925 ErrInfo = "Invalid register class: "
5926 "agpr loads and stores not supported on this GPU";
5927 return false;
5928 }
5929 }
5930 }
5931
5932 if (ST.needsAlignedVGPRs()) {
5933 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
5935 if (!Op)
5936 return true;
5937 Register Reg = Op->getReg();
5938 if (Reg.isPhysical())
5939 return !(RI.getHWRegIndex(Reg) & 1);
5940 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
5941 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
5942 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
5943 };
5944
5945 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
5946 Opcode == AMDGPU::DS_GWS_BARRIER) {
5947
5948 if (!isAlignedReg(AMDGPU::OpName::data0)) {
5949 ErrInfo = "Subtarget requires even aligned vector registers "
5950 "for DS_GWS instructions";
5951 return false;
5952 }
5953 }
5954
5955 if (isMIMG(MI)) {
5956 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
5957 ErrInfo = "Subtarget requires even aligned vector registers "
5958 "for vaddr operand of image instructions";
5959 return false;
5960 }
5961 }
5962 }
5963
5964 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
5965 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
5966 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
5967 ErrInfo = "Invalid register class: "
5968 "v_accvgpr_write with an SGPR is not supported on this GPU";
5969 return false;
5970 }
5971 }
5972
5973 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
5974 const MachineOperand &SrcOp = MI.getOperand(1);
5975 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
5976 ErrInfo = "pseudo expects only physical SGPRs";
5977 return false;
5978 }
5979 }
5980
5981 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
5982 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
5983 if (!ST.hasScaleOffset()) {
5984 ErrInfo = "Subtarget does not support offset scaling";
5985 return false;
5986 }
5987 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
5988 ErrInfo = "Instruction does not support offset scaling";
5989 return false;
5990 }
5991 }
5992 }
5993
5994 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
5995 if (AMDGPU::isSingleSGPRReadInst(Opcode)) {
5996 for (unsigned I = 0; I < 3; ++I) {
5998 return false;
5999 }
6000 }
6001
6002 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
6003 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
6004 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
6005 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6006 &AMDGPU::SReg_64RegClass) ||
6007 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6008 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
6009 return false;
6010 }
6011 }
6012
6013 return true;
6014}
6015
6017 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
6018 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6019 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
6020 ? AMDGPU::COPY
6021 : AMDGPU::V_MOV_B32_e32;
6022 }
6023 return getVALUOp(MI.getOpcode());
6024}
6025
6026// It is more readable to list mapped opcodes on the same line.
6027// clang-format off
6028
6029unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
6030 switch (Opc) {
6031 default: return AMDGPU::INSTRUCTION_LIST_END;
6032 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
6033 case AMDGPU::COPY: return AMDGPU::COPY;
6034 case AMDGPU::PHI: return AMDGPU::PHI;
6035 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
6036 case AMDGPU::WQM: return AMDGPU::WQM;
6037 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
6038 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
6039 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
6040 case AMDGPU::S_ADD_I32:
6041 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6042 case AMDGPU::S_ADDC_U32:
6043 return AMDGPU::V_ADDC_U32_e32;
6044 case AMDGPU::S_SUB_I32:
6045 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6046 // FIXME: These are not consistently handled, and selected when the carry is
6047 // used.
6048 case AMDGPU::S_ADD_U32:
6049 return AMDGPU::V_ADD_CO_U32_e32;
6050 case AMDGPU::S_SUB_U32:
6051 return AMDGPU::V_SUB_CO_U32_e32;
6052 case AMDGPU::S_ADD_U64_PSEUDO:
6053 return AMDGPU::V_ADD_U64_PSEUDO;
6054 case AMDGPU::S_SUB_U64_PSEUDO:
6055 return AMDGPU::V_SUB_U64_PSEUDO;
6056 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
6057 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
6058 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
6059 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
6060 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
6061 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
6062 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
6063 case AMDGPU::S_XNOR_B32:
6064 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6065 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
6066 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
6067 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
6068 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
6069 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
6070 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
6071 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
6072 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
6073 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
6074 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
6075 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
6076 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
6077 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
6078 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
6079 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
6080 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
6081 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
6082 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
6083 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
6084 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
6085 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
6086 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
6087 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
6088 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
6089 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
6090 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
6091 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
6092 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
6093 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
6094 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
6095 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
6096 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
6097 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
6098 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
6099 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
6100 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
6101 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
6102 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
6103 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
6104 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
6105 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
6106 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
6107 case AMDGPU::S_CVT_F32_F16:
6108 case AMDGPU::S_CVT_HI_F32_F16:
6109 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6110 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6111 case AMDGPU::S_CVT_F16_F32:
6112 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6113 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6114 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
6115 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
6116 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
6117 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
6118 case AMDGPU::S_CEIL_F16:
6119 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6120 : AMDGPU::V_CEIL_F16_fake16_e64;
6121 case AMDGPU::S_FLOOR_F16:
6122 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6123 : AMDGPU::V_FLOOR_F16_fake16_e64;
6124 case AMDGPU::S_TRUNC_F16:
6125 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6126 : AMDGPU::V_TRUNC_F16_fake16_e64;
6127 case AMDGPU::S_RNDNE_F16:
6128 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6129 : AMDGPU::V_RNDNE_F16_fake16_e64;
6130 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6131 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6132 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6133 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6134 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6135 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6136 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6137 case AMDGPU::S_ADD_F16:
6138 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6139 : AMDGPU::V_ADD_F16_fake16_e64;
6140 case AMDGPU::S_SUB_F16:
6141 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6142 : AMDGPU::V_SUB_F16_fake16_e64;
6143 case AMDGPU::S_MIN_F16:
6144 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6145 : AMDGPU::V_MIN_F16_fake16_e64;
6146 case AMDGPU::S_MAX_F16:
6147 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6148 : AMDGPU::V_MAX_F16_fake16_e64;
6149 case AMDGPU::S_MINIMUM_F16:
6150 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6151 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6152 case AMDGPU::S_MAXIMUM_F16:
6153 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6154 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6155 case AMDGPU::S_MUL_F16:
6156 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6157 : AMDGPU::V_MUL_F16_fake16_e64;
6158 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6159 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6160 case AMDGPU::S_FMAC_F16:
6161 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6162 : AMDGPU::V_FMAC_F16_fake16_e64;
6163 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6164 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6165 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6166 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6167 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6168 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6169 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6170 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6171 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6172 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6173 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6174 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6175 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6176 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6177 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6178 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6179 case AMDGPU::S_CMP_LT_F16:
6180 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6181 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6182 case AMDGPU::S_CMP_EQ_F16:
6183 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6184 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6185 case AMDGPU::S_CMP_LE_F16:
6186 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6187 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6188 case AMDGPU::S_CMP_GT_F16:
6189 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6190 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6191 case AMDGPU::S_CMP_LG_F16:
6192 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6193 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6194 case AMDGPU::S_CMP_GE_F16:
6195 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6196 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6197 case AMDGPU::S_CMP_O_F16:
6198 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6199 : AMDGPU::V_CMP_O_F16_fake16_e64;
6200 case AMDGPU::S_CMP_U_F16:
6201 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6202 : AMDGPU::V_CMP_U_F16_fake16_e64;
6203 case AMDGPU::S_CMP_NGE_F16:
6204 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6205 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6206 case AMDGPU::S_CMP_NLG_F16:
6207 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6208 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6209 case AMDGPU::S_CMP_NGT_F16:
6210 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6211 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6212 case AMDGPU::S_CMP_NLE_F16:
6213 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6214 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6215 case AMDGPU::S_CMP_NEQ_F16:
6216 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6217 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6218 case AMDGPU::S_CMP_NLT_F16:
6219 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6220 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6221 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6222 case AMDGPU::V_S_EXP_F16_e64:
6223 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6224 : AMDGPU::V_EXP_F16_fake16_e64;
6225 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6226 case AMDGPU::V_S_LOG_F16_e64:
6227 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6228 : AMDGPU::V_LOG_F16_fake16_e64;
6229 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6230 case AMDGPU::V_S_RCP_F16_e64:
6231 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6232 : AMDGPU::V_RCP_F16_fake16_e64;
6233 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6234 case AMDGPU::V_S_RSQ_F16_e64:
6235 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6236 : AMDGPU::V_RSQ_F16_fake16_e64;
6237 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6238 case AMDGPU::V_S_SQRT_F16_e64:
6239 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6240 : AMDGPU::V_SQRT_F16_fake16_e64;
6241 }
6243 "Unexpected scalar opcode without corresponding vector one!");
6244}
6245
6246// clang-format on
6247
6251 const DebugLoc &DL, Register Reg,
6252 bool IsSCCLive,
6253 SlotIndexes *Indexes) const {
6254 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6255 const SIInstrInfo *TII = ST.getInstrInfo();
6257 if (IsSCCLive) {
6258 // Insert two move instructions, one to save the original value of EXEC and
6259 // the other to turn on all bits in EXEC. This is required as we can't use
6260 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6261 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6263 auto FlipExecMI =
6264 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6265 if (Indexes) {
6266 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6267 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6268 }
6269 } else {
6270 auto SaveExec =
6271 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6272 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6273 if (Indexes)
6274 Indexes->insertMachineInstrInMaps(*SaveExec);
6275 }
6276}
6277
6280 const DebugLoc &DL, Register Reg,
6281 SlotIndexes *Indexes) const {
6283 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6284 .addReg(Reg, RegState::Kill);
6285 if (Indexes)
6286 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6287}
6288
6292 "Not a whole wave func");
6293 MachineBasicBlock &MBB = *MF.begin();
6294 for (MachineInstr &MI : MBB)
6295 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6296 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6297 return &MI;
6298
6299 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6300}
6301
6303 unsigned OpNo) const {
6304 const MCInstrDesc &Desc = get(MI.getOpcode());
6305 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6306 Desc.operands()[OpNo].RegClass == -1) {
6307 Register Reg = MI.getOperand(OpNo).getReg();
6308
6309 if (Reg.isVirtual()) {
6310 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6311 return MRI.getRegClass(Reg);
6312 }
6313 return RI.getPhysRegBaseClass(Reg);
6314 }
6315
6316 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6317 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6318}
6319
6320// Convert VOP3 operand index to source number.
6321static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx) {
6322 constexpr AMDGPU::OpName OpNames[] = {
6323 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6324
6325 for (auto [I, OpName] : enumerate(OpNames)) {
6326 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6327 if (static_cast<unsigned>(SrcIdx) == OpIdx)
6328 return I;
6329 }
6330
6331 return UINT_MAX;
6332}
6333
6336 MachineBasicBlock *MBB = MI.getParent();
6337 MachineOperand &MO = MI.getOperand(OpIdx);
6338 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6339 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6340 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6341 unsigned Size = RI.getRegSizeInBits(*RC);
6342 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6343 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6344 : AMDGPU::V_MOV_B32_e32;
6345 if (MO.isReg())
6346 Opcode = AMDGPU::COPY;
6347 else if (RI.isSGPRClass(RC))
6348 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6349
6350 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6351 Register Reg = MRI.createVirtualRegister(VRC);
6352 DebugLoc DL = MBB->findDebugLoc(I);
6353
6354 if (Size == 128 && AMDGPU::isPackedSingleSGPR64BitInst(MI.getOpcode()) &&
6356 // Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
6357 // sources behave like OPSEL is set replicating low 64-bits into high. VGPR
6358 // sources in turn read actual 4 registers. To move operand from an SGPR to
6359 // a VGPR we need to replicate low half.
6360 // We also do not select immediates for these instructions so it always has
6361 // to be an SGPR register here.
6362 // Operands which are not legal as per isLegalSingleSGPRReadInstOperand()
6363 // sent here specifically to fix a non-splat SGPR and shall perform a full
6364 // copy.
6365
6366 const TargetRegisterClass *VRC64 = RI.getVGPRClassForBitWidth(64);
6367 Register Low64 = MRI.createVirtualRegister(VRC64);
6368 assert(MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()));
6369 BuildMI(*MBB, I, DL, get(TargetOpcode::COPY), Low64)
6370 .addReg(MO.getReg(), {}, AMDGPU::sub0_sub1);
6371 BuildMI(*MBB, I, DL, get(TargetOpcode::REG_SEQUENCE), Reg)
6372 .addReg(Low64)
6373 .addImm(AMDGPU::sub0_sub1)
6374 .addReg(Low64, RegState::Kill)
6375 .addImm(AMDGPU::sub2_sub3);
6376 } else {
6377 BuildMI(*MBB, I, DL, get(Opcode), Reg).add(MO);
6378 }
6379
6380 MO.ChangeToRegister(Reg, false);
6381}
6382
6385 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6386 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6387 if (!SuperReg.getReg().isVirtual())
6388 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6389
6390 MachineBasicBlock *MBB = MI->getParent();
6391 const DebugLoc &DL = MI->getDebugLoc();
6392 Register SubReg = MRI.createVirtualRegister(SubRC);
6393
6394 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6395 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6396 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6397 return SubReg;
6398}
6399
6402 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6403 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6404 if (Op.isImm()) {
6405 if (SubIdx == AMDGPU::sub0)
6406 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6407 if (SubIdx == AMDGPU::sub1)
6408 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6409
6410 llvm_unreachable("Unhandled register index for immediate");
6411 }
6412
6413 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6414 SubIdx, SubRC);
6415 return MachineOperand::CreateReg(SubReg, false);
6416}
6417
6418// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6419void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6420 assert(Inst.getNumExplicitOperands() == 3);
6421 MachineOperand Op1 = Inst.getOperand(1);
6422 Inst.removeOperand(1);
6423 Inst.addOperand(Op1);
6424}
6425
6427 const MCOperandInfo &OpInfo,
6428 const MachineOperand &MO) const {
6429 if (!MO.isReg())
6430 return false;
6431
6432 Register Reg = MO.getReg();
6433
6434 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6435 if (Reg.isPhysical())
6436 return DRC->contains(Reg);
6437
6438 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6439
6440 if (MO.getSubReg()) {
6441 const MachineFunction *MF = MO.getParent()->getMF();
6442 const TargetRegisterClass *SuperRC = RI.getLargestLegalSuperClass(RC, *MF);
6443 if (!SuperRC)
6444 return false;
6445 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6446 }
6447
6448 return RI.getCommonSubClass(DRC, RC) != nullptr;
6449}
6450
6452 const MachineOperand &MO) const {
6453 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6454 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6455 unsigned Opc = MI.getOpcode();
6456
6457 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6458 if (MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
6459 AMDGPU::isSingleSGPRReadInst(MI.getOpcode()) &&
6461 &MO))
6462 return false;
6463
6464 if (!isLegalRegOperand(MRI, OpInfo, MO))
6465 return false;
6466
6467 // check Accumulate GPR operand
6468 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6469 if (IsAGPR && !ST.hasMAIInsts())
6470 return false;
6471 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6472 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6473 return false;
6474 // Atomics should have both vdst and vdata either vgpr or agpr.
6475 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6476 const int DataIdx = AMDGPU::getNamedOperandIdx(
6477 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6478 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6479 MI.getOperand(DataIdx).isReg() &&
6480 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6481 return false;
6482 if ((int)OpIdx == DataIdx) {
6483 if (VDstIdx != -1 &&
6484 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6485 return false;
6486 // DS instructions with 2 src operands also must have tied RC.
6487 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6488 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6489 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6490 return false;
6491 }
6492
6493 // Check V_ACCVGPR_WRITE_B32_e64
6494 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6495 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6496 RI.isSGPRReg(MRI, MO.getReg()))
6497 return false;
6498
6499 if (ST.hasFlatScratchHiInB64InstHazard() &&
6500 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6501 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6502 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6503 64)
6504 return false;
6505 }
6506 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6507 return false;
6508 }
6509 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6510 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6511 return false;
6512
6513 return true;
6514}
6515
6517 const MCOperandInfo &OpInfo,
6518 const MachineOperand &MO) const {
6519 if (MO.isReg())
6520 return isLegalRegOperand(MRI, OpInfo, MO);
6521
6522 // Handle non-register types that are treated like immediates.
6523 assert(MO.isImm() || MO.isTargetIndex() || MO.isFI() || MO.isGlobal());
6524 return true;
6525}
6526
6528 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6529 const MachineOperand *MO) const {
6530 constexpr unsigned NumOps = 3;
6531 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6532 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6533 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6534 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6535
6536 assert(SrcN < NumOps);
6537
6538 if (!MO) {
6539 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6540 if (SrcIdx == -1)
6541 return true;
6542 MO = &MI.getOperand(SrcIdx);
6543 }
6544
6545 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6546 return true;
6547
6548 int ModsIdx =
6549 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6550 if (ModsIdx == -1)
6551 return false;
6552
6553 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6554 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6555 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6556
6557 return !OpSel && !OpSelHi;
6558}
6559
6561 const MachineOperand *MO) const {
6562 const MachineFunction &MF = *MI.getMF();
6563 const MachineRegisterInfo &MRI = MF.getRegInfo();
6564 const MCInstrDesc &InstDesc = MI.getDesc();
6565 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6566 int64_t RegClass = getOpRegClassID(OpInfo);
6567 const TargetRegisterClass *DefinedRC =
6568 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6569 if (!MO)
6570 MO = &MI.getOperand(OpIdx);
6571
6572 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6573
6574 if (isVALU(MI, /*AllowLDSDMA=*/true) && !IsInlineConst &&
6575 usesConstantBus(MRI, *MO, OpInfo)) {
6576 const MachineOperand *UsedLiteral = nullptr;
6577
6578 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6579 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6580
6581 // TODO: Be more permissive with frame indexes.
6582 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6583 if (!LiteralLimit--)
6584 return false;
6585
6586 UsedLiteral = MO;
6587 }
6588
6590 if (MO->isReg())
6591 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6592
6593 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6594 if (i == OpIdx)
6595 continue;
6596 const MachineOperand &Op = MI.getOperand(i);
6597 if (Op.isReg()) {
6598 if (Op.isUse()) {
6599 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6600 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6601 if (--ConstantBusLimit <= 0)
6602 return false;
6603 }
6604 }
6605 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6606 !isInlineConstant(Op, InstDesc.operands()[i])) {
6607 // The same literal may be used multiple times.
6608 if (!UsedLiteral)
6609 UsedLiteral = &Op;
6610 else if (UsedLiteral->isIdenticalTo(Op))
6611 continue;
6612
6613 if (!LiteralLimit--)
6614 return false;
6615 if (--ConstantBusLimit <= 0)
6616 return false;
6617 }
6618 }
6619 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6620 // There can be at most one literal operand, but it can be repeated.
6621 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6622 if (i == OpIdx)
6623 continue;
6624 const MachineOperand &Op = MI.getOperand(i);
6625 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6626 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6627 !Op.isIdenticalTo(*MO))
6628 return false;
6629
6630 // Do not fold a non-inlineable and non-register operand into an
6631 // instruction that already has a frame index. The frame index handling
6632 // code could not handle well when a frame index co-exists with another
6633 // non-register operand, unless that operand is an inlineable immediate.
6634 if (Op.isFI())
6635 return false;
6636 }
6637 } else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6638 isF16PseudoScalarTrans(MI.getOpcode())) {
6639 return false;
6640 }
6641
6642 if (MO->isReg()) {
6643 if (!DefinedRC)
6644 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6645 return isLegalRegOperand(MI, OpIdx, *MO);
6646 }
6647
6648 if (MO->isImm()) {
6649 uint64_t Imm = MO->getImm();
6650 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6651 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6652 bool Is64BitOp = Is64BitFPOp ||
6653 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6654 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6655 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6656 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6657 if (Is64BitOp &&
6658 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6659 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6660 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6661 return false;
6662
6663 // FIXME: We can use sign extended 64-bit literals, but only for signed
6664 // operands. At the moment we do not know if an operand is signed.
6665 // Such operand will be encoded as its low 32 bits and then either
6666 // correctly sign extended or incorrectly zero extended by HW.
6667 // If 64-bit literals are supported and the literal will be encoded
6668 // as full 64 bit we still can use it.
6669 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6670 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
6671 return false;
6672 }
6673 }
6674
6675 // Handle non-register types that are treated like immediates.
6676 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
6677
6678 if (!DefinedRC) {
6679 // This operand expects an immediate.
6680 return true;
6681 }
6682
6683 return isImmOperandLegal(MI, OpIdx, *MO);
6684}
6685
6687 bool IsGFX950Only = ST.hasGFX950Insts();
6688 bool IsGFX940Only = ST.hasGFX940Insts();
6689
6690 if (!IsGFX950Only && !IsGFX940Only)
6691 return false;
6692
6693 if (!isVALU(MI, /*AllowLDSDMA=*/true))
6694 return false;
6695
6696 // V_COS, V_EXP, V_RCP, etc.
6697 if (isTRANS(MI))
6698 return true;
6699
6700 // DOT2, DOT2C, DOT4, etc.
6701 if (isDOT(MI))
6702 return true;
6703
6704 // MFMA, SMFMA
6705 if (isMFMA(MI))
6706 return true;
6707
6708 unsigned Opcode = MI.getOpcode();
6709 switch (Opcode) {
6710 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6711 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6712 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6713 case AMDGPU::V_MQSAD_U32_U8_e64:
6714 case AMDGPU::V_PK_ADD_F16:
6715 case AMDGPU::V_PK_ADD_F32:
6716 case AMDGPU::V_PK_ADD_I16:
6717 case AMDGPU::V_PK_ADD_U16:
6718 case AMDGPU::V_PK_ASHRREV_I16:
6719 case AMDGPU::V_PK_FMA_F16:
6720 case AMDGPU::V_PK_FMA_F32:
6721 case AMDGPU::V_PK_FMAC_F16_e32:
6722 case AMDGPU::V_PK_FMAC_F16_e64:
6723 case AMDGPU::V_PK_LSHLREV_B16:
6724 case AMDGPU::V_PK_LSHRREV_B16:
6725 case AMDGPU::V_PK_MAD_I16:
6726 case AMDGPU::V_PK_MAD_U16:
6727 case AMDGPU::V_PK_MAX_F16:
6728 case AMDGPU::V_PK_MAX_I16:
6729 case AMDGPU::V_PK_MAX_U16:
6730 case AMDGPU::V_PK_MIN_F16:
6731 case AMDGPU::V_PK_MIN_I16:
6732 case AMDGPU::V_PK_MIN_U16:
6733 case AMDGPU::V_PK_MOV_B32:
6734 case AMDGPU::V_PK_MUL_F16:
6735 case AMDGPU::V_PK_MUL_F32:
6736 case AMDGPU::V_PK_MUL_LO_U16:
6737 case AMDGPU::V_PK_SUB_I16:
6738 case AMDGPU::V_PK_SUB_U16:
6739 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6740 return true;
6741 default:
6742 return false;
6743 }
6744}
6745
6747 MachineInstr &MI) const {
6748 unsigned Opc = MI.getOpcode();
6749 const MCInstrDesc &InstrDesc = get(Opc);
6750
6751 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
6752 MachineOperand &Src0 = MI.getOperand(Src0Idx);
6753
6754 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
6755 MachineOperand &Src1 = MI.getOperand(Src1Idx);
6756
6757 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
6758 // we need to only have one constant bus use before GFX10.
6759 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
6760 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
6761 RI.isSGPRReg(MRI, Src0.getReg()))
6762 legalizeOpWithMove(MI, Src0Idx);
6763
6764 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
6765 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
6766 // src0/src1 with V_READFIRSTLANE.
6767 if (Opc == AMDGPU::V_WRITELANE_B32) {
6768 const DebugLoc &DL = MI.getDebugLoc();
6769 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
6770 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6771 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6772 .add(Src0);
6773 Src0.ChangeToRegister(Reg, false);
6774 }
6775 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
6776 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6777 const DebugLoc &DL = MI.getDebugLoc();
6778 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6779 .add(Src1);
6780 Src1.ChangeToRegister(Reg, false);
6781 }
6782 return;
6783 }
6784
6785 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
6786 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
6787 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
6788 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
6789 legalizeOpWithMove(MI, Src2Idx);
6790 }
6791
6792 // VOP2 src0 instructions support all operand types, so we don't need to check
6793 // their legality. If src1 is already legal, we don't need to do anything.
6794 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
6795 return;
6796
6797 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
6798 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
6799 // select is uniform.
6800 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
6801 RI.isVGPR(MRI, Src1.getReg())) {
6802 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6803 const DebugLoc &DL = MI.getDebugLoc();
6804 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6805 .add(Src1);
6806 Src1.ChangeToRegister(Reg, false);
6807 return;
6808 }
6809
6810 // We do not use commuteInstruction here because it is too aggressive and will
6811 // commute if it is possible. We only want to commute here if it improves
6812 // legality. This can be called a fairly large number of times so don't waste
6813 // compile time pointlessly swapping and checking legality again.
6814 if (HasImplicitSGPR || !MI.isCommutable()) {
6815 legalizeOpWithMove(MI, Src1Idx);
6816 return;
6817 }
6818
6819 // If src0 can be used as src1, commuting will make the operands legal.
6820 // Otherwise we have to give up and insert a move.
6821 //
6822 // TODO: Other immediate-like operand kinds could be commuted if there was a
6823 // MachineOperand::ChangeTo* for them.
6824 if ((!Src1.isImm() && !Src1.isReg()) ||
6825 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
6826 legalizeOpWithMove(MI, Src1Idx);
6827 return;
6828 }
6829
6830 int CommutedOpc = commuteOpcode(MI);
6831 if (CommutedOpc == -1) {
6832 legalizeOpWithMove(MI, Src1Idx);
6833 return;
6834 }
6835
6836 MI.setDesc(get(CommutedOpc));
6837
6838 Register Src0Reg = Src0.getReg();
6839 unsigned Src0SubReg = Src0.getSubReg();
6840 bool Src0Kill = Src0.isKill();
6841
6842 if (Src1.isImm())
6843 Src0.ChangeToImmediate(Src1.getImm());
6844 else if (Src1.isReg()) {
6845 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
6846 Src0.setSubReg(Src1.getSubReg());
6847 } else
6848 llvm_unreachable("Should only have register or immediate operands");
6849
6850 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
6851 Src1.setSubReg(Src0SubReg);
6853}
6854
6855// Legalize VOP3 operands. All operand types are supported for any operand
6856// but only one literal constant and only starting from GFX10.
6858 MachineInstr &MI) const {
6859 unsigned Opc = MI.getOpcode();
6860
6861 int VOP3Idx[3] = {
6862 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
6863 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
6864 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
6865 };
6866
6867 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6868 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6869 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6870 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6871 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6872 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6873 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6874 // src1 and src2 must be scalar
6875 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
6876 const DebugLoc &DL = MI.getDebugLoc();
6877 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
6878 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6879 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6880 .add(Src1);
6881 Src1.ChangeToRegister(Reg, false);
6882 }
6883 if (VOP3Idx[2] != -1) {
6884 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
6885 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
6886 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6887 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6888 .add(Src2);
6889 Src2.ChangeToRegister(Reg, false);
6890 }
6891 }
6892 }
6893
6894 // Find the one SGPR operand we are allowed to use.
6895 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
6896 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
6897 SmallDenseSet<unsigned> SGPRsUsed;
6898 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
6899 if (SGPRReg) {
6900 SGPRsUsed.insert(SGPRReg);
6901 --ConstantBusLimit;
6902 }
6903
6904 for (int Idx : VOP3Idx) {
6905 if (Idx == -1)
6906 break;
6907 MachineOperand &MO = MI.getOperand(Idx);
6908
6909 if (!MO.isReg()) {
6910 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
6911 continue;
6912
6913 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
6914 --LiteralLimit;
6915 --ConstantBusLimit;
6916 continue;
6917 }
6918
6919 --LiteralLimit;
6920 --ConstantBusLimit;
6921 legalizeOpWithMove(MI, Idx);
6922 continue;
6923 }
6924
6925 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
6926 continue; // VGPRs are legal
6927
6928 // We can use one SGPR in each VOP3 instruction prior to GFX10
6929 // and two starting from GFX10.
6930 if (SGPRsUsed.count(MO.getReg()))
6931 continue;
6932 if (ConstantBusLimit > 0) {
6933 SGPRsUsed.insert(MO.getReg());
6934 --ConstantBusLimit;
6935 continue;
6936 }
6937
6938 // If we make it this far, then the operand is not legal and we must
6939 // legalize it.
6940 legalizeOpWithMove(MI, Idx);
6941 }
6942
6943 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
6944 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64) &&
6945 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
6946 legalizeOpWithMove(MI, VOP3Idx[2]);
6947
6948 // Fix the register class of single-sgpr-read instructions on gfx12+. See
6949 // SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6951 for (unsigned I = 0; I < 3; ++I) {
6952 if (!isLegalSingleSGPRReadInstOperand(MRI, MI, /*SrcN=*/I))
6953 legalizeOpWithMove(MI, VOP3Idx[I]);
6954 }
6955 }
6956}
6957
6960 const TargetRegisterClass *DstRC /*=nullptr*/) const {
6961 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
6962 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
6963 if (DstRC)
6964 SRC = RI.getCommonSubClass(SRC, DstRC);
6965
6966 Register DstReg = MRI.createVirtualRegister(SRC);
6967 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
6968
6969 if (RI.hasAGPRs(VRC)) {
6970 VRC = RI.getEquivalentVGPRClass(VRC);
6971 Register NewSrcReg = MRI.createVirtualRegister(VRC);
6972 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6973 get(TargetOpcode::COPY), NewSrcReg)
6974 .addReg(SrcReg);
6975 SrcReg = NewSrcReg;
6976 }
6977
6978 if (SubRegs == 1) {
6979 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6980 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6981 .addReg(SrcReg);
6982 return DstReg;
6983 }
6984
6986 for (unsigned i = 0; i < SubRegs; ++i) {
6987 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
6988 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6989 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
6990 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
6991 SRegs.push_back(SGPR);
6992 }
6993
6995 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6996 get(AMDGPU::REG_SEQUENCE), DstReg);
6997 for (unsigned i = 0; i < SubRegs; ++i) {
6998 MIB.addReg(SRegs[i]);
6999 MIB.addImm(RI.getSubRegFromChannel(i));
7000 }
7001 return DstReg;
7002}
7003
7005 MachineInstr &MI) const {
7006
7007 // If the pointer is store in VGPRs, then we need to move them to
7008 // SGPRs using v_readfirstlane. This is safe because we only select
7009 // loads with uniform pointers to SMRD instruction so we know the
7010 // pointer value is uniform.
7011 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
7012 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
7013 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
7014 SBase->setReg(SGPR);
7015 }
7016 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
7017 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
7018 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
7019 SOff->setReg(SGPR);
7020 }
7021}
7022
7024 unsigned Opc = Inst.getOpcode();
7025 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
7026 if (OldSAddrIdx < 0)
7027 return false;
7028
7029 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
7030
7031 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
7032 if (NewOpc < 0)
7034 if (NewOpc < 0)
7035 return false;
7036
7037 MachineRegisterInfo &MRI = Inst.getMF()->getRegInfo();
7038 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
7039 if (RI.isSGPRReg(MRI, SAddr.getReg()))
7040 return false;
7041
7042 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7043 if (NewVAddrIdx < 0)
7044 return false;
7045
7046 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
7047
7048 // Check vaddr, it shall be zero or absent.
7049 MachineInstr *VAddrDef = nullptr;
7050 if (OldVAddrIdx >= 0) {
7051 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
7052 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
7053 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
7054 !VAddrDef->getOperand(1).isImm() ||
7055 VAddrDef->getOperand(1).getImm() != 0)
7056 return false;
7057 }
7058
7059 const MCInstrDesc &NewDesc = get(NewOpc);
7060 Inst.setDesc(NewDesc);
7061
7062 // Callers expect iterator to be valid after this call, so modify the
7063 // instruction in place.
7064 if (OldVAddrIdx == NewVAddrIdx) {
7065 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
7066 // Clear use list from the old vaddr holding a zero register.
7067 MRI.removeRegOperandFromUseList(&NewVAddr);
7068 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7069 Inst.removeOperand(OldSAddrIdx);
7070 // Update the use list with the pointer we have just moved from vaddr to
7071 // saddr position. Otherwise new vaddr will be missing from the use list.
7072 MRI.removeRegOperandFromUseList(&NewVAddr);
7073 MRI.addRegOperandToUseList(&NewVAddr);
7074 } else {
7075 assert(OldSAddrIdx == NewVAddrIdx);
7076
7077 if (OldVAddrIdx >= 0) {
7078 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7079 AMDGPU::OpName::vdst_in);
7080
7081 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
7082 // it asserts. Untie the operands for now and retie them afterwards.
7083 if (NewVDstIn != -1) {
7084 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
7085 Inst.untieRegOperand(OldVDstIn);
7086 }
7087
7088 Inst.removeOperand(OldVAddrIdx);
7089
7090 if (NewVDstIn != -1) {
7091 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7092 Inst.tieOperands(NewVDst, NewVDstIn);
7093 }
7094 }
7095 }
7096
7097 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
7098 VAddrDef->eraseFromParent();
7099
7100 return true;
7101}
7102
7103// FIXME: Remove this when SelectionDAG is obsoleted.
7105 MachineInstr &MI) const {
7106 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
7107 return;
7108
7109 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
7110 // thinks they are uniform, so a readfirstlane should be valid.
7111 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
7112 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
7113 return;
7114
7116 return;
7117
7118 const TargetRegisterClass *DeclaredRC =
7119 getRegClass(MI.getDesc(), SAddr->getOperandNo());
7120
7121 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
7122 SAddr->setReg(ToSGPR);
7123}
7124
7127 const TargetRegisterClass *DstRC,
7130 const DebugLoc &DL) const {
7131 Register OpReg = Op.getReg();
7132 unsigned OpSubReg = Op.getSubReg();
7133
7134 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
7135 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7136
7137 // Check if operand is already the correct register class.
7138 if (DstRC == OpRC)
7139 return;
7140
7141 Register DstReg = MRI.createVirtualRegister(DstRC);
7142 auto Copy = BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg)
7143 .addReg(OpReg, {}, OpSubReg);
7144 Op.setReg(DstReg);
7145 Op.setSubReg(AMDGPU::NoSubRegister);
7146
7147 MachineInstr *Def = MRI.getVRegDef(OpReg);
7148 if (!Def)
7149 return;
7150
7151 // Try to eliminate the copy if it is copying an immediate value.
7152 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7153 foldImmediate(*Copy, *Def, OpReg, &MRI);
7154
7155 bool ImpDef = Def->isImplicitDef();
7156 while (!ImpDef && Def && Def->isCopy()) {
7157 if (Def->getOperand(1).getReg().isPhysical())
7158 break;
7159 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7160 ImpDef = Def && Def->isImplicitDef();
7161 }
7162 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7163 !ImpDef)
7164 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7165}
7166
7167// Emit the actual waterfall loop, executing the wrapped instruction for each
7168// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7169// iteration, in the worst case we execute 64 (once per lane).
7172 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7173 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7174 MachineFunction &MF = *LoopBB.getParent();
7176 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7178 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7179
7180 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7181 // available. Otherwise, use the previous pattern of v_cmp_eq,
7182 // s_and_saveexec, and s_xor.
7183 bool UseNewExecInstructions =
7184 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7185
7187 Register CondReg;
7188
7189 Register PhiExec;
7190 Register NewExec;
7191
7192 if (UseNewExecInstructions) {
7193 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7194 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7195 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7196 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7197 .addReg(LMC.ExecReg);
7198
7199 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7200 .addReg(InitExec)
7201 .addMBB(&PredBB)
7202 .addReg(NewExec)
7203 .addMBB(&BodyBB);
7204 }
7205
7206 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7207 // involves a trade-off between register pressure and latency:
7208 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7209 // register pressure because arguments and results of all
7210 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7211 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7212 // increase latency by placing v_readfirstlane instructions
7213 // immediately before v_cmpx instruction that directly depend on it.
7214 ///
7215 // Emitting interleaved v_cmpx and v_readfirstlane requires
7216 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7217 // v_cmpx needs to be treated as terminator until after register allocation
7218 // (spill placement) and instruction reordering.
7219 //
7220 // Current implementation defers v_cmpx and leaves other instruction
7221 // scheduling decisions to later passes, where register pressure is known or
7222 // easier to approximate.
7223 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7224 // v_cmpx instructions are inserted at the end of LoopBB.
7225 // After the first v_cmpx is emitted, I is updated to point to it
7226 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7227 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7228 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7229 unsigned NumSubRegs = RegSize / 32;
7230 Register VScalarOp = ScalarOp->getReg();
7231
7232 const TargetRegisterClass *RFLSrcRC =
7233 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7234
7235 if (NumSubRegs == 1) {
7236 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7237 if (const TargetRegisterClass *Common =
7238 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7239 Common != VScalarOpRC) {
7240 Register VRReg = MRI.createVirtualRegister(Common);
7241 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7242 VScalarOp = VRReg;
7243 }
7244 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7245
7246 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7247 .addReg(VScalarOp);
7248
7249 if (UseNewExecInstructions) {
7250 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7251 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7252 .addReg(CurReg)
7253 .addReg(VScalarOp);
7254 if (I == LoopBB.end())
7255 I = CmpxMI.getInstr()->getIterator();
7256 } else {
7257 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7258
7259 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7260 .addReg(CurReg)
7261 .addReg(VScalarOp);
7262
7263 // Combine the comparison results with AND.
7264 if (!CondReg) { // First.
7265 CondReg = NewCondReg;
7266 } else { // If not the first, we create an AND.
7267 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7268 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7269 .addReg(CondReg)
7270 .addReg(NewCondReg);
7271 CondReg = AndReg;
7272 }
7273 }
7274
7275 // Update ScalarOp operand to use the SGPR ScalarOp.
7276 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7277 ScalarOp->setReg(CurReg);
7278 else {
7279 // Insert into the same block of use
7280 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7281 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7282 .addReg(CurReg);
7283 ScalarOp->setReg(PhySGPRs[Idx]);
7284 }
7285 ScalarOp->setIsKill();
7286 } else {
7287 SmallVector<Register, 8> ReadlanePieces;
7288 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7289 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7290 "Unhandled register size");
7291
7292 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7293 Register CurRegLo =
7294 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7295 Register CurRegHi =
7296 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7297
7298 // Read the next variant <- also loop target.
7299 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7300 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7301
7302 // Read the next variant <- also loop target.
7303 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7304 .addReg(VScalarOp, VScalarOpUndef,
7305 TRI->getSubRegFromChannel(Idx + 1));
7306
7307 ReadlanePieces.push_back(CurRegLo);
7308 ReadlanePieces.push_back(CurRegHi);
7309
7310 // Comparison is to be done as 64-bit.
7311 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7312 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7313 .addReg(CurRegLo)
7314 .addImm(AMDGPU::sub0)
7315 .addReg(CurRegHi)
7316 .addImm(AMDGPU::sub1);
7317
7318 unsigned SubReg =
7319 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7320
7321 if (UseNewExecInstructions) {
7322 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7323 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7324 .addReg(CurReg)
7325 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7326 if (I == LoopBB.end())
7327 I = CmpxMI.getInstr()->getIterator();
7328 } else {
7329 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7330 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7331 .addReg(CurReg)
7332 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7333
7334 // Combine the comparison results with AND.
7335 if (!CondReg) { // First.
7336 CondReg = NewCondReg;
7337 } else { // If not the first, we create an AND.
7338 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7339 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7340 .addReg(CondReg)
7341 .addReg(NewCondReg);
7342 CondReg = AndReg;
7343 }
7344 }
7345 } // End for loop.
7346
7347 const auto *SScalarOpRC =
7348 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7349 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7350
7351 // Build scalar ScalarOp.
7352 auto Merge =
7353 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7354 unsigned Channel = 0;
7355 for (Register Piece : ReadlanePieces) {
7356 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7357 }
7358
7359 // Update ScalarOp operand to use the SGPR ScalarOp.
7360 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7361 ScalarOp->setReg(SScalarOp);
7362 else {
7363 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7364 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7365 .addReg(SScalarOp);
7366 ScalarOp->setReg(PhySGPRs[Idx]);
7367 }
7368 ScalarOp->setIsKill();
7369 }
7370 }
7371
7372 // Instructions AndSaveExecOpc and AndN2WrExecOpc that modify EXEC mask
7373 // should have isTerminator=1 but terminators that define
7374 // virtual registers are not supported.
7375 Register SaveExec;
7376 if (!UseNewExecInstructions) {
7377 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7378 MRI.setSimpleHint(SaveExec, CondReg);
7379
7380 // Update EXEC to matching lanes, saving original to SaveExec.
7381 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7382 .addReg(CondReg, RegState::Kill);
7383 }
7384
7385 // The original instruction is here; we insert the terminators after it.
7386 I = BodyBB.end();
7387
7388 if (UseNewExecInstructions) {
7389 MRI.setSimpleHint(NewExec, PhiExec);
7390 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2WrExecOpc), NewExec)
7391 .addReg(PhiExec);
7392 } else {
7393 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7394 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7395 .addReg(LMC.ExecReg)
7396 .addReg(SaveExec);
7397 }
7398
7399 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7400}
7401
7402// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7403// with SGPRs by iterating over all unique values across all lanes.
7404// Returns the loop basic block that now contains \p MI.
7405static MachineBasicBlock *
7409 MachineBasicBlock::iterator Begin = nullptr,
7410 MachineBasicBlock::iterator End = nullptr,
7411 ArrayRef<Register> PhySGPRs = {}) {
7412 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7413 "Physical SGPRs must be empty or match the number of scalar operands");
7414 MachineBasicBlock &MBB = *MI.getParent();
7415 MachineFunction &MF = *MBB.getParent();
7417 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7418 MachineRegisterInfo &MRI = MF.getRegInfo();
7419 if (!Begin.isValid())
7420 Begin = &MI;
7421 if (!End.isValid()) {
7422 End = &MI;
7423 ++End;
7424 }
7425 const DebugLoc &DL = MI.getDebugLoc();
7427 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7428
7429 // Save SCC. Waterfall Loop may overwrite SCC.
7430 Register SaveSCCReg;
7431
7432 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7433 // rather than unlimited scan everywhere
7434 bool SCCNotDead =
7435 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7436 std::numeric_limits<unsigned>::max()) !=
7438 if (SCCNotDead) {
7439 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7440 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7441 .addImm(1)
7442 .addImm(0);
7443 }
7444
7445 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7446
7447 // Save the EXEC mask
7448 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7449
7450 // Killed uses in the instruction we are waterfalling around will be
7451 // incorrect due to the added control-flow.
7453 ++AfterMI;
7454 for (auto I = Begin; I != AfterMI; I++) {
7455 for (auto &MO : I->all_uses())
7456 MRI.clearKillFlags(MO.getReg());
7457 }
7458
7459 // To insert the loop we need to split the block. Move everything after this
7460 // point to a new block, and insert a new empty block between the two.
7463 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7465 ++MBBI;
7466
7467 MF.insert(MBBI, LoopBB);
7468 MF.insert(MBBI, BodyBB);
7469 MF.insert(MBBI, RemainderBB);
7470
7471 LoopBB->addSuccessor(BodyBB);
7472 BodyBB->addSuccessor(LoopBB);
7473 BodyBB->addSuccessor(RemainderBB);
7474
7475 // Move Begin to MI to the BodyBB, and the remainder of the block to
7476 // RemainderBB.
7477 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7478 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7479 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7480
7481 MBB.addSuccessor(LoopBB);
7482
7483 // Update dominators. We know that MBB immediately dominates LoopBB, that
7484 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7485 // RemainderBB. RemainderBB immediately dominates all of the successors
7486 // transferred to it from MBB that MBB used to properly dominate.
7487 if (MDT) {
7488 MDT->addNewBlock(LoopBB, &MBB);
7489 MDT->addNewBlock(BodyBB, LoopBB);
7490 MDT->addNewBlock(RemainderBB, BodyBB);
7491 for (auto &Succ : RemainderBB->successors()) {
7492 if (MDT->properlyDominates(&MBB, Succ)) {
7493 MDT->changeImmediateDominator(Succ, RemainderBB);
7494 }
7495 }
7496 }
7497
7498 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7499 PhySGPRs);
7500
7501 MachineBasicBlock::iterator First = RemainderBB->begin();
7502 // Restore SCC
7503 if (SCCNotDead) {
7504 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7505 .addReg(SaveSCCReg, RegState::Kill)
7506 .addImm(0);
7507 }
7508
7509 // Restore the EXEC mask
7510 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7511 .addReg(SaveExec);
7512 return BodyBB;
7513}
7514
7515// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7516static std::tuple<unsigned, unsigned>
7518 MachineBasicBlock &MBB = *MI.getParent();
7519 MachineFunction &MF = *MBB.getParent();
7520 MachineRegisterInfo &MRI = MF.getRegInfo();
7521
7522 // Extract the ptr from the resource descriptor.
7523 unsigned RsrcPtr =
7524 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7525 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7526
7527 // Create an empty resource descriptor
7528 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7529 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7530 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7531 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7532 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7533
7534 // Zero64 = 0
7535 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7536 .addImm(0);
7537
7538 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7539 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7540 .addImm(Lo_32(RsrcDataFormat));
7541
7542 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7543 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7544 .addImm(Hi_32(RsrcDataFormat));
7545
7546 // NewSRsrc = {Zero64, SRsrcFormat}
7547 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7548 .addReg(Zero64)
7549 .addImm(AMDGPU::sub0_sub1)
7550 .addReg(SRsrcFormatLo)
7551 .addImm(AMDGPU::sub2)
7552 .addReg(SRsrcFormatHi)
7553 .addImm(AMDGPU::sub3);
7554
7555 return std::tuple(RsrcPtr, NewSRsrc);
7556}
7557
7560 MachineDominatorTree *MDT) const {
7561 MachineFunction &MF = *MI.getMF();
7562 MachineRegisterInfo &MRI = MF.getRegInfo();
7563 MachineBasicBlock *CreatedBB = nullptr;
7564
7565 // Legalize True16
7566 if (ST.useRealTrue16Insts())
7568
7569 // Legalize VOP2
7570 if (isVOP2(MI) || isVOPC(MI)) {
7572 return CreatedBB;
7573 }
7574
7575 // Legalize VOP3
7576 if (isVOP3(MI)) {
7578 return CreatedBB;
7579 }
7580
7581 // Legalize SMRD
7582 if (isSMRD(MI)) {
7584 return CreatedBB;
7585 }
7586
7587 // Legalize FLAT
7588 if (isFLAT(MI)) {
7590 return CreatedBB;
7591 }
7592
7593 // Legalize PHI
7594 // The register class of the operands must be the same type as the register
7595 // class of the output.
7596 if (MI.getOpcode() == AMDGPU::PHI) {
7597 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7598 assert(!RI.isSGPRClass(VRC));
7599
7600 // Update all the operands so they have the same type.
7601 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7602 MachineOperand &Op = MI.getOperand(I);
7603 if (!Op.isReg() || !Op.getReg().isVirtual())
7604 continue;
7605
7606 // MI is a PHI instruction.
7607 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7609
7610 // Avoid creating no-op copies with the same src and dst reg class. These
7611 // confuse some of the machine passes.
7612 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7613 }
7614 }
7615
7616 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7617 // VGPR dest type and SGPR sources, insert copies so all operands are
7618 // VGPRs. This seems to help operand folding / the register coalescer.
7619 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7620 MachineBasicBlock *MBB = MI.getParent();
7621 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7622 if (RI.hasVGPRs(DstRC)) {
7623 // Update all the operands so they are VGPR register classes. These may
7624 // not be the same register class because REG_SEQUENCE supports mixing
7625 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7626 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7627 MachineOperand &Op = MI.getOperand(I);
7628 if (!Op.isReg() || !Op.getReg().isVirtual())
7629 continue;
7630
7631 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7632 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7633 if (VRC == OpRC)
7634 continue;
7635
7636 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7637 Op.setIsKill();
7638 }
7639 }
7640
7641 return CreatedBB;
7642 }
7643
7644 // Legalize INSERT_SUBREG
7645 // src0 must have the same register class as dst
7646 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7647 Register Dst = MI.getOperand(0).getReg();
7648 Register Src0 = MI.getOperand(1).getReg();
7649 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7650 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7651 if (DstRC != Src0RC) {
7652 MachineBasicBlock *MBB = MI.getParent();
7653 MachineOperand &Op = MI.getOperand(1);
7654 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7655 }
7656 return CreatedBB;
7657 }
7658
7659 // Legalize SI_INIT_M0
7660 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7661 MachineOperand &Src = MI.getOperand(0);
7662 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7663 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7664 return CreatedBB;
7665 }
7666
7667 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
7668 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7669 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7670 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7671 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7672 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7673 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7674 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7675 MachineOperand &Src = MI.getOperand(1);
7676 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7677 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7678 return CreatedBB;
7679 }
7680
7681 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
7682 //
7683 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
7684 // scratch memory access. In both cases, the legalization never involves
7685 // conversion to the addr64 form.
7687 (isMUBUF(MI) || isMTBUF(MI)))) {
7688 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
7689 ? AMDGPU::OpName::rsrc
7690 : AMDGPU::OpName::srsrc;
7691 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
7692 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
7693 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
7694
7695 AMDGPU::OpName SampOpName =
7696 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7697 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
7698 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
7699 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
7700
7701 return CreatedBB;
7702 }
7703
7704 // Legalize SI_CALL
7705 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7706 MachineOperand *Dest = &MI.getOperand(0);
7707 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
7708 createWaterFallForSiCall(&MI, MDT, {Dest});
7709 }
7710 }
7711
7712 // Legalize s_sleep_var.
7713 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7714 const DebugLoc &DL = MI.getDebugLoc();
7715 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7716 int Src0Idx =
7717 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
7718 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7719 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7720 .add(Src0);
7721 Src0.ChangeToRegister(Reg, false);
7722 return nullptr;
7723 }
7724
7725 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
7726 // operands are scalar.
7727 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7728 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7729 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7730 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7731 for (MachineOperand &Src : MI.explicit_operands()) {
7732 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7733 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7734 }
7735 return CreatedBB;
7736 }
7737
7738 // Legalize MUBUF instructions.
7739 bool isSoffsetLegal = true;
7740 int SoffsetIdx =
7741 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
7742 if (SoffsetIdx != -1) {
7743 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
7744 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
7745 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
7746 isSoffsetLegal = false;
7747 }
7748 }
7749
7750 bool isRsrcLegal = true;
7751 int RsrcIdx =
7752 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
7753 if (RsrcIdx != -1) {
7754 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7755 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
7756 isRsrcLegal = false;
7757 }
7758
7759 // The operands are legal.
7760 if (isRsrcLegal && isSoffsetLegal)
7761 return CreatedBB;
7762
7763 if (!isRsrcLegal) {
7764 // Legalize a VGPR Rsrc
7765 //
7766 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
7767 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
7768 // a zero-value SRsrc.
7769 //
7770 // If the instruction is _OFFSET (both idxen and offen disabled), and we
7771 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
7772 // above.
7773 //
7774 // Otherwise we are on non-ADDR64 hardware, and/or we have
7775 // idxen/offen/bothen and we fall back to a waterfall loop.
7776
7777 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7778 MachineBasicBlock &MBB = *MI.getParent();
7779
7780 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
7781 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
7782 // This is already an ADDR64 instruction so we need to add the pointer
7783 // extracted from the resource descriptor to the current value of VAddr.
7784 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7785 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7786 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7787
7788 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7789 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
7790 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
7791
7792 unsigned RsrcPtr, NewSRsrc;
7793 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7794
7795 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
7796 const DebugLoc &DL = MI.getDebugLoc();
7797 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
7798 .addDef(CondReg0)
7799 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7800 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
7801 .addImm(0);
7802
7803 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
7804 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
7805 .addDef(CondReg1, RegState::Dead)
7806 .addReg(RsrcPtr, {}, AMDGPU::sub1)
7807 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
7808 .addReg(CondReg0, RegState::Kill)
7809 .addImm(0);
7810
7811 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7812 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
7813 .addReg(NewVAddrLo)
7814 .addImm(AMDGPU::sub0)
7815 .addReg(NewVAddrHi)
7816 .addImm(AMDGPU::sub1);
7817
7818 VAddr->setReg(NewVAddr);
7819 Rsrc->setReg(NewSRsrc);
7820 } else if (!VAddr && ST.hasAddr64()) {
7821 // This instructions is the _OFFSET variant, so we need to convert it to
7822 // ADDR64.
7823 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
7824 "FIXME: Need to emit flat atomics here");
7825
7826 unsigned RsrcPtr, NewSRsrc;
7827 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7828
7829 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7830 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
7831 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
7832 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7833 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
7834
7835 // Atomics with return have an additional tied operand and are
7836 // missing some of the special bits.
7837 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
7838 MachineInstr *Addr64;
7839
7840 if (!VDataIn) {
7841 // Regular buffer load / store.
7843 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7844 .add(*VData)
7845 .addReg(NewVAddr)
7846 .addReg(NewSRsrc)
7847 .add(*SOffset)
7848 .add(*Offset);
7849
7850 if (const MachineOperand *CPol =
7851 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
7852 MIB.addImm(CPol->getImm());
7853 }
7854
7855 if (const MachineOperand *TFE =
7856 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
7857 MIB.addImm(TFE->getImm());
7858 }
7859
7860 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
7861
7862 MIB.cloneMemRefs(MI);
7863 Addr64 = MIB;
7864 } else {
7865 // Atomics with return.
7866 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7867 .add(*VData)
7868 .add(*VDataIn)
7869 .addReg(NewVAddr)
7870 .addReg(NewSRsrc)
7871 .add(*SOffset)
7872 .add(*Offset)
7873 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
7874 .cloneMemRefs(MI);
7875 }
7876
7877 MI.removeFromParent();
7878
7879 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7880 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
7881 NewVAddr)
7882 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7883 .addImm(AMDGPU::sub0)
7884 .addReg(RsrcPtr, {}, AMDGPU::sub1)
7885 .addImm(AMDGPU::sub1);
7886 } else {
7887 // Legalize a VGPR Rsrc and soffset together.
7888 if (!isSoffsetLegal) {
7889 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7890 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
7891 return CreatedBB;
7892 }
7893 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
7894 return CreatedBB;
7895 }
7896 }
7897
7898 // Legalize a VGPR soffset.
7899 if (!isSoffsetLegal) {
7900 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7901 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
7902 return CreatedBB;
7903 }
7904 return CreatedBB;
7905}
7906
7908 if (InSet.insert(MI).second)
7909 InstrList.push_back(MI);
7910 // Add MBUF instructiosn to deferred list.
7911 int RsrcIdx =
7912 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
7913 if (RsrcIdx != -1) {
7914 DeferredList.insert(MI);
7915 }
7916}
7917
7919 return DeferredList.contains(MI);
7920}
7921
7922// Legalize size mismatches between 16bit and 32bit registers in v2s copy
7923// lowering (change sgpr to vgpr).
7924// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
7925// size. Need to legalize the size of the operands during the vgpr lowering
7926// chain. This can be removed after we have sgpr16 in place
7928 MachineRegisterInfo &MRI) const {
7929 if (!ST.useRealTrue16Insts())
7930 return;
7931
7932 unsigned Opcode = MI.getOpcode();
7933 MachineBasicBlock *MBB = MI.getParent();
7934 // Legalize operands and check for size mismatch
7935 if (OpIdx >= MI.getNumExplicitOperands() ||
7936 OpIdx >= get(Opcode).getNumOperands() ||
7937 get(Opcode).operands()[OpIdx].RegClass == -1)
7938 return;
7939
7940 MachineOperand &Op = MI.getOperand(OpIdx);
7941 if (!Op.isReg() || !Op.getReg().isVirtual() || Op.isDef())
7942 return;
7943
7944 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
7945 if (!RI.isVGPRClass(CurrRC))
7946 return;
7947
7948 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
7949 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
7950 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
7951 // Default to the lo16 only if the subregister is not specified.
7952 if (Op.getSubReg() == AMDGPU::NoSubRegister)
7953 Op.setSubReg(AMDGPU::lo16);
7954 return;
7955 }
7956
7957 const TargetRegisterClass *CurrSRC =
7958 RI.getSubRegisterClass(CurrRC, Op.getSubReg());
7959 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
7960 const DebugLoc &DL = MI.getDebugLoc();
7961 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7962 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
7963 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
7964 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
7965 .addReg(Op.getReg(), {}, Op.getSubReg())
7966 .addImm(AMDGPU::lo16)
7967 .addReg(Undef)
7968 .addImm(AMDGPU::hi16);
7969 Op.setReg(NewDstReg);
7970 Op.setSubReg(AMDGPU::NoSubRegister);
7971 }
7972}
7974 MachineRegisterInfo &MRI) const {
7975 for (unsigned OpIdx = 0; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
7977}
7978
7982 ArrayRef<Register> PhySGPRs) const {
7983 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
7984 "This only handle waterfall for SI_CALL_ISEL");
7985 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
7986 // following copies, we also need to move copies from and to physical
7987 // registers into the loop block.
7988 // Also move the copies to physical registers into the loop block
7989 MachineBasicBlock &MBB = *MI->getParent();
7991 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
7992 --Start;
7994 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
7995 ++End;
7996
7997 // Also include following copies of the return value
7998 ++End;
7999 while (End != MBB.end() && End->isCopy() &&
8000 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8001 ++End;
8002
8003 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
8004}
8005
8007 MachineDominatorTree *MDT) const {
8009 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
8010 while (!Worklist.empty()) {
8011 MachineInstr &Inst = *Worklist.top();
8012 Worklist.erase_top();
8013 // Skip MachineInstr in the deferred list.
8014 if (Worklist.isDeferred(&Inst))
8015 continue;
8016 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8017 }
8018
8019 // Deferred list of instructions will be processed once
8020 // all the MachineInstr in the worklist are done.
8021 for (MachineInstr *Inst : Worklist.getDeferredList()) {
8022 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8023 assert(Worklist.empty() &&
8024 "Deferred MachineInstr are not supposed to re-populate worklist");
8025 }
8026
8027 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
8028 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8029 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
8030 Entry.second.SGPRs);
8031 }
8032
8033 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8034 if (Entry.second)
8035 Entry.first->eraseFromParent();
8036}
8038 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
8039 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
8040 // hope for the best.
8041 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
8042 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
8043 if (SubRegIndices.size() <= 1) {
8044 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8045 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8046 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8047 .add(Inst.getOperand(1));
8048 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
8049 DstReg)
8050 .addReg(NewDst);
8051 } else {
8053 for (int16_t Indice : SubRegIndices) {
8054 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8055 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8056 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8057 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
8058
8059 DstRegs.push_back(NewDst);
8060 }
8062 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8063 get(AMDGPU::REG_SEQUENCE), DstReg);
8064 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
8065 MIB.addReg(DstRegs[i]);
8066 MIB.addImm(RI.getSubRegFromChannel(i));
8067 }
8068 }
8069}
8070
8072 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
8075 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8076 if (DstReg == AMDGPU::M0) {
8077 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8078 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8079 return;
8080 }
8081 Register SrcReg = Inst.getOperand(1).getReg();
8084 // Only search current block since phyreg's def & use cannot cross
8085 // blocks when MF.NoPhi = false.
8086 while (++I != E) {
8087 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
8088 // and record the operand for later waterfall loop generation.
8089 if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8090 MachineInstr *UseMI = &*I;
8091 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
8092 if (UseMI->getOperand(i).isReg() &&
8093 UseMI->getOperand(i).getReg() == DstReg) {
8094 MachineOperand *MO = &UseMI->getOperand(i);
8095 MO->setReg(SrcReg);
8096 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
8097 V2SCopyInfo.MOs.push_back(MO);
8098 V2SCopyInfo.SGPRs.push_back(DstReg);
8099 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8100 }
8101 }
8102 } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8103 I->getOperand(0).isReg() &&
8104 I->getOperand(0).getReg() == DstReg) {
8105 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8106 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8107 } else if (I->readsRegister(DstReg, &RI)) {
8108 // COPY cannot be erased if other type of inst uses it.
8109 V2SPhyCopiesToErase[&Inst] = false;
8110 }
8111 if (I->findRegisterDefOperand(DstReg, &RI))
8112 break;
8113 }
8114}
8115
8117 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
8119 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8120
8122 if (!MBB)
8123 return;
8124 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
8125 unsigned Opcode = Inst.getOpcode();
8126 unsigned NewOpcode = getVALUOp(Inst);
8127 const DebugLoc &DL = Inst.getDebugLoc();
8128
8129 // Handle some special cases
8130 switch (Opcode) {
8131 default:
8132 break;
8133 case AMDGPU::S_ADD_I32:
8134 case AMDGPU::S_SUB_I32: {
8135 // FIXME: The u32 versions currently selected use the carry.
8136 bool Changed;
8137 MachineBasicBlock *CreatedBBTmp = nullptr;
8138 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8139 if (Changed)
8140 return;
8141
8142 // Default handling
8143 break;
8144 }
8145
8146 case AMDGPU::S_MUL_U64:
8147 if (ST.hasVMulU64Inst()) {
8148 NewOpcode = AMDGPU::V_MUL_U64_e64;
8149 break;
8150 }
8151 // Split s_mul_u64 in 32-bit vector multiplications.
8152 splitScalarSMulU64(Worklist, Inst, MDT);
8153 Inst.eraseFromParent();
8154 return;
8155
8156 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8157 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8158 // This is a special case of s_mul_u64 where all the operands are either
8159 // zero extended or sign extended.
8160 splitScalarSMulPseudo(Worklist, Inst, MDT);
8161 Inst.eraseFromParent();
8162 return;
8163
8164 case AMDGPU::S_AND_B64:
8165 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8166 Inst.eraseFromParent();
8167 return;
8168
8169 case AMDGPU::S_OR_B64:
8170 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8171 Inst.eraseFromParent();
8172 return;
8173
8174 case AMDGPU::S_XOR_B64:
8175 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8176 Inst.eraseFromParent();
8177 return;
8178
8179 case AMDGPU::S_NAND_B64:
8180 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8181 Inst.eraseFromParent();
8182 return;
8183
8184 case AMDGPU::S_NOR_B64:
8185 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8186 Inst.eraseFromParent();
8187 return;
8188
8189 case AMDGPU::S_XNOR_B64:
8190 if (ST.hasDLInsts())
8191 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8192 else
8193 splitScalar64BitXnor(Worklist, Inst, MDT);
8194 Inst.eraseFromParent();
8195 return;
8196
8197 case AMDGPU::S_ANDN2_B64:
8198 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8199 Inst.eraseFromParent();
8200 return;
8201
8202 case AMDGPU::S_ORN2_B64:
8203 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8204 Inst.eraseFromParent();
8205 return;
8206
8207 case AMDGPU::S_BREV_B64:
8208 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8209 Inst.eraseFromParent();
8210 return;
8211
8212 case AMDGPU::S_NOT_B64:
8213 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8214 Inst.eraseFromParent();
8215 return;
8216
8217 case AMDGPU::S_BCNT1_I32_B64:
8218 splitScalar64BitBCNT(Worklist, Inst);
8219 Inst.eraseFromParent();
8220 return;
8221
8222 case AMDGPU::S_BFE_I64:
8223 splitScalar64BitBFE(Worklist, Inst);
8224 Inst.eraseFromParent();
8225 return;
8226
8227 case AMDGPU::S_FLBIT_I32_B64:
8228 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8229 Inst.eraseFromParent();
8230 return;
8231 case AMDGPU::S_FF1_I32_B64:
8232 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8233 Inst.eraseFromParent();
8234 return;
8235
8236 case AMDGPU::S_LSHL_B32:
8237 if (ST.hasOnlyRevVALUShifts()) {
8238 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8239 swapOperands(Inst);
8240 }
8241 break;
8242 case AMDGPU::S_ASHR_I32:
8243 if (ST.hasOnlyRevVALUShifts()) {
8244 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8245 swapOperands(Inst);
8246 }
8247 break;
8248 case AMDGPU::S_LSHR_B32:
8249 if (ST.hasOnlyRevVALUShifts()) {
8250 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8251 swapOperands(Inst);
8252 }
8253 break;
8254 case AMDGPU::S_LSHL_B64:
8255 if (ST.hasOnlyRevVALUShifts()) {
8256 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8257 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8258 : AMDGPU::V_LSHLREV_B64_e64;
8259 swapOperands(Inst);
8260 }
8261 break;
8262 case AMDGPU::S_ASHR_I64:
8263 if (ST.hasOnlyRevVALUShifts()) {
8264 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8265 swapOperands(Inst);
8266 }
8267 break;
8268 case AMDGPU::S_LSHR_B64:
8269 if (ST.hasOnlyRevVALUShifts()) {
8270 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8271 swapOperands(Inst);
8272 }
8273 break;
8274
8275 case AMDGPU::S_ABS_I32:
8276 lowerScalarAbs(Worklist, Inst);
8277 Inst.eraseFromParent();
8278 return;
8279
8280 case AMDGPU::S_ABSDIFF_I32:
8281 lowerScalarAbsDiff(Worklist, Inst);
8282 Inst.eraseFromParent();
8283 return;
8284
8285 case AMDGPU::S_CBRANCH_SCC0:
8286 case AMDGPU::S_CBRANCH_SCC1: {
8287 // Clear unused bits of vcc
8288 Register CondReg = Inst.getOperand(1).getReg();
8289 bool IsSCC = CondReg == AMDGPU::SCC;
8291 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8292 .addReg(LMC.ExecReg)
8293 .addReg(IsSCC ? LMC.VccReg : CondReg);
8294 Inst.removeOperand(1);
8295 } break;
8296
8297 case AMDGPU::S_BFE_U64:
8298 case AMDGPU::S_BFM_B64:
8299 llvm_unreachable("Moving this op to VALU not implemented");
8300
8301 case AMDGPU::S_PACK_LL_B32_B16:
8302 case AMDGPU::S_PACK_LH_B32_B16:
8303 case AMDGPU::S_PACK_HL_B32_B16:
8304 case AMDGPU::S_PACK_HH_B32_B16:
8305 movePackToVALU(Worklist, MRI, Inst);
8306 Inst.eraseFromParent();
8307 return;
8308
8309 case AMDGPU::S_XNOR_B32:
8310 lowerScalarXnor(Worklist, Inst);
8311 Inst.eraseFromParent();
8312 return;
8313
8314 case AMDGPU::S_NAND_B32:
8315 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8316 Inst.eraseFromParent();
8317 return;
8318
8319 case AMDGPU::S_NOR_B32:
8320 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8321 Inst.eraseFromParent();
8322 return;
8323
8324 case AMDGPU::S_ANDN2_B32:
8325 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8326 Inst.eraseFromParent();
8327 return;
8328
8329 case AMDGPU::S_ORN2_B32:
8330 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8331 Inst.eraseFromParent();
8332 return;
8333
8334 // TODO: remove as soon as everything is ready
8335 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8336 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8337 // can only be selected from the uniform SDNode.
8338 case AMDGPU::S_ADD_CO_PSEUDO:
8339 case AMDGPU::S_SUB_CO_PSEUDO: {
8340 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8341 ? AMDGPU::V_ADDC_U32_e64
8342 : AMDGPU::V_SUBB_U32_e64;
8343 const auto *CarryRC = RI.getWaveMaskRegClass();
8344
8345 Register CarryInReg = Inst.getOperand(4).getReg();
8346 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8347 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8348 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8349 .addReg(CarryInReg);
8350 }
8351
8352 Register CarryOutReg = Inst.getOperand(1).getReg();
8353
8354 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8355 MRI.getRegClass(Inst.getOperand(0).getReg())));
8356 MachineInstr *CarryOp =
8357 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8358 .addReg(CarryOutReg, RegState::Define)
8359 .add(Inst.getOperand(2))
8360 .add(Inst.getOperand(3))
8361 .addReg(CarryInReg)
8362 .addImm(0);
8363 legalizeOperands(*CarryOp);
8364 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8365 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8366 Inst.eraseFromParent();
8367 }
8368 return;
8369 case AMDGPU::S_UADDO_PSEUDO:
8370 case AMDGPU::S_USUBO_PSEUDO: {
8371 MachineOperand &Dest0 = Inst.getOperand(0);
8372 MachineOperand &Dest1 = Inst.getOperand(1);
8373 MachineOperand &Src0 = Inst.getOperand(2);
8374 MachineOperand &Src1 = Inst.getOperand(3);
8375
8376 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8377 ? AMDGPU::V_ADD_CO_U32_e64
8378 : AMDGPU::V_SUB_CO_U32_e64;
8379 const TargetRegisterClass *NewRC =
8380 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8381 Register DestReg = MRI.createVirtualRegister(NewRC);
8382 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8383 .addReg(Dest1.getReg(), RegState::Define)
8384 .add(Src0)
8385 .add(Src1)
8386 .addImm(0); // clamp bit
8387
8388 legalizeOperands(*NewInstr, MDT);
8389 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8390 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8391 Inst.eraseFromParent();
8392 }
8393 return;
8394 case AMDGPU::S_LSHL1_ADD_U32:
8395 case AMDGPU::S_LSHL2_ADD_U32:
8396 case AMDGPU::S_LSHL3_ADD_U32:
8397 case AMDGPU::S_LSHL4_ADD_U32: {
8398 MachineOperand &Dest = Inst.getOperand(0);
8399 MachineOperand &Src0 = Inst.getOperand(1);
8400 MachineOperand &Src1 = Inst.getOperand(2);
8401 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8402 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8403 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8404 : 4);
8405
8406 const TargetRegisterClass *NewRC =
8407 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8408 Register DestReg = MRI.createVirtualRegister(NewRC);
8409 MachineInstr *NewInstr =
8410 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8411 .add(Src0)
8412 .addImm(ShiftAmt)
8413 .add(Src1);
8414
8415 legalizeOperands(*NewInstr, MDT);
8416 MRI.replaceRegWith(Dest.getReg(), DestReg);
8417 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8418 Inst.eraseFromParent();
8419 }
8420 return;
8421 case AMDGPU::S_CSELECT_B32:
8422 case AMDGPU::S_CSELECT_B64:
8423 lowerSelect(Worklist, Inst, MDT);
8424 Inst.eraseFromParent();
8425 return;
8426 case AMDGPU::S_CMP_EQ_I32:
8427 case AMDGPU::S_CMP_LG_I32:
8428 case AMDGPU::S_CMP_GT_I32:
8429 case AMDGPU::S_CMP_GE_I32:
8430 case AMDGPU::S_CMP_LT_I32:
8431 case AMDGPU::S_CMP_LE_I32:
8432 case AMDGPU::S_CMP_EQ_U32:
8433 case AMDGPU::S_CMP_LG_U32:
8434 case AMDGPU::S_CMP_GT_U32:
8435 case AMDGPU::S_CMP_GE_U32:
8436 case AMDGPU::S_CMP_LT_U32:
8437 case AMDGPU::S_CMP_LE_U32:
8438 case AMDGPU::S_CMP_EQ_U64:
8439 case AMDGPU::S_CMP_LG_U64:
8440 case AMDGPU::S_CMP_LT_F32:
8441 case AMDGPU::S_CMP_EQ_F32:
8442 case AMDGPU::S_CMP_LE_F32:
8443 case AMDGPU::S_CMP_GT_F32:
8444 case AMDGPU::S_CMP_LG_F32:
8445 case AMDGPU::S_CMP_GE_F32:
8446 case AMDGPU::S_CMP_O_F32:
8447 case AMDGPU::S_CMP_U_F32:
8448 case AMDGPU::S_CMP_NGE_F32:
8449 case AMDGPU::S_CMP_NLG_F32:
8450 case AMDGPU::S_CMP_NGT_F32:
8451 case AMDGPU::S_CMP_NLE_F32:
8452 case AMDGPU::S_CMP_NEQ_F32:
8453 case AMDGPU::S_CMP_NLT_F32: {
8454 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8455 auto NewInstr =
8456 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8457 .setMIFlags(Inst.getFlags());
8458 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8459 0) {
8460 NewInstr
8461 .addImm(0) // src0_modifiers
8462 .add(Inst.getOperand(0)) // src0
8463 .addImm(0) // src1_modifiers
8464 .add(Inst.getOperand(1)) // src1
8465 .addImm(0); // clamp
8466 } else {
8467 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8468 }
8469 legalizeOperands(*NewInstr, MDT);
8470 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8471 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8472 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8473 Inst.eraseFromParent();
8474 return;
8475 }
8476 case AMDGPU::S_CMP_LT_F16:
8477 case AMDGPU::S_CMP_EQ_F16:
8478 case AMDGPU::S_CMP_LE_F16:
8479 case AMDGPU::S_CMP_GT_F16:
8480 case AMDGPU::S_CMP_LG_F16:
8481 case AMDGPU::S_CMP_GE_F16:
8482 case AMDGPU::S_CMP_O_F16:
8483 case AMDGPU::S_CMP_U_F16:
8484 case AMDGPU::S_CMP_NGE_F16:
8485 case AMDGPU::S_CMP_NLG_F16:
8486 case AMDGPU::S_CMP_NGT_F16:
8487 case AMDGPU::S_CMP_NLE_F16:
8488 case AMDGPU::S_CMP_NEQ_F16:
8489 case AMDGPU::S_CMP_NLT_F16: {
8490 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8491 auto NewInstr =
8492 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8493 .setMIFlags(Inst.getFlags());
8494 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8495 NewInstr
8496 .addImm(0) // src0_modifiers
8497 .add(Inst.getOperand(0)) // src0
8498 .addImm(0) // src1_modifiers
8499 .add(Inst.getOperand(1)) // src1
8500 .addImm(0); // clamp
8501 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8502 NewInstr.addImm(0); // op_sel0
8503 } else {
8504 NewInstr
8505 .add(Inst.getOperand(0))
8506 .add(Inst.getOperand(1));
8507 }
8508 legalizeOperands(*NewInstr, MDT);
8509 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8510 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8511 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8512 Inst.eraseFromParent();
8513 return;
8514 }
8515 case AMDGPU::S_CVT_HI_F32_F16: {
8516 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8517 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8518 if (ST.useRealTrue16Insts()) {
8519 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8520 .add(Inst.getOperand(1));
8521 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8522 .addImm(0) // src0_modifiers
8523 .addReg(TmpReg, {}, AMDGPU::hi16)
8524 .addImm(0) // clamp
8525 .addImm(0) // omod
8526 .addImm(0); // op_sel0
8527 } else {
8528 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8529 .addImm(16)
8530 .add(Inst.getOperand(1));
8531 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8532 .addImm(0) // src0_modifiers
8533 .addReg(TmpReg)
8534 .addImm(0) // clamp
8535 .addImm(0); // omod
8536 }
8537
8538 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8539 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8540 Inst.eraseFromParent();
8541 return;
8542 }
8543 case AMDGPU::S_MINIMUM_F32:
8544 case AMDGPU::S_MAXIMUM_F32: {
8545 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8546 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8547 .addImm(0) // src0_modifiers
8548 .add(Inst.getOperand(1))
8549 .addImm(0) // src1_modifiers
8550 .add(Inst.getOperand(2))
8551 .addImm(0) // clamp
8552 .addImm(0); // omod
8553 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8554
8555 legalizeOperands(*NewInstr, MDT);
8556 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8557 Inst.eraseFromParent();
8558 return;
8559 }
8560 case AMDGPU::S_MINIMUM_F16:
8561 case AMDGPU::S_MAXIMUM_F16: {
8562 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8563 ? &AMDGPU::VGPR_16RegClass
8564 : &AMDGPU::VGPR_32RegClass);
8565 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8566 .addImm(0) // src0_modifiers
8567 .add(Inst.getOperand(1))
8568 .addImm(0) // src1_modifiers
8569 .add(Inst.getOperand(2))
8570 .addImm(0) // clamp
8571 .addImm(0) // omod
8572 .addImm(0); // opsel0
8573 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8574 legalizeOperands(*NewInstr, MDT);
8575 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8576 Inst.eraseFromParent();
8577 return;
8578 }
8579 case AMDGPU::V_S_EXP_F16_e64:
8580 case AMDGPU::V_S_LOG_F16_e64:
8581 case AMDGPU::V_S_RCP_F16_e64:
8582 case AMDGPU::V_S_RSQ_F16_e64:
8583 case AMDGPU::V_S_SQRT_F16_e64: {
8584 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8585 ? &AMDGPU::VGPR_16RegClass
8586 : &AMDGPU::VGPR_32RegClass);
8587 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8588 .add(Inst.getOperand(1)) // src0_modifiers
8589 .add(Inst.getOperand(2))
8590 .add(Inst.getOperand(3)) // clamp
8591 .add(Inst.getOperand(4)) // omod
8592 .setMIFlags(Inst.getFlags());
8593 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8594 NewInstr.addImm(0); // opsel0
8595 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8596 legalizeOperands(*NewInstr, MDT);
8597 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8598 Inst.eraseFromParent();
8599 return;
8600 }
8601 }
8602
8603 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8604 // We cannot move this instruction to the VALU, so we should try to
8605 // legalize its operands instead.
8606 legalizeOperands(Inst, MDT);
8607 return;
8608 }
8609 // Handle converting generic instructions like COPY-to-SGPR into
8610 // COPY-to-VGPR.
8611 if (NewOpcode == Opcode) {
8612 Register DstReg = Inst.getOperand(0).getReg();
8613 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8614
8615 if (Inst.isCopy() && DstReg.isPhysical() &&
8616 Inst.getOperand(1).getReg().isVirtual()) {
8617 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8618 V2SPhyCopiesToErase);
8619 return;
8620 }
8621
8622 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8623 Register NewDstReg = Inst.getOperand(1).getReg();
8624 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8625 if (const TargetRegisterClass *CommonRC =
8626 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8627 // Instead of creating a copy where src and dst are the same register
8628 // class, we just replace all uses of dst with src. These kinds of
8629 // copies interfere with the heuristics MachineSink uses to decide
8630 // whether or not to split a critical edge. Since the pass assumes
8631 // that copies will end up as machine instructions and not be
8632 // eliminated.
8633 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8634 unsigned SrcSubReg = Inst.getOperand(1).getSubReg();
8635 for (MachineOperand &UseMO :
8636 make_early_inc_range(MRI.use_operands(DstReg))) {
8637 UseMO.setSubReg(
8638 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8639 UseMO.setReg(NewDstReg);
8640 }
8641 MRI.clearKillFlags(NewDstReg);
8642
8643 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8644 llvm_unreachable("failed to constrain register");
8645
8646 Inst.eraseFromParent();
8647
8648 for (MachineOperand &UseMO :
8649 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8650 MachineInstr &UseMI = *UseMO.getParent();
8651
8652 // Legalize t16 operands since replaceReg is called after
8653 // addUsersToVALU.
8655
8656 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
8657 if (const TargetRegisterClass *OpRC =
8658 getRegClass(UseMI.getDesc(), OpIdx))
8659 MRI.constrainRegClass(NewDstReg, OpRC);
8660 }
8661
8662 return;
8663 }
8664 }
8665
8666 // If this is a v2s copy between 16bit and 32bit reg,
8667 // replace vgpr copy to reg_sequence/extract_subreg
8668 // This can be remove after we have sgpr16 in place
8669 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
8670 Inst.getOperand(1).getReg().isVirtual() &&
8671 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
8672 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
8673 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8674 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8675 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8676 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8677 get(AMDGPU::IMPLICIT_DEF), Undef);
8678 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8679 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8680 .addReg(Inst.getOperand(1).getReg())
8681 .addImm(AMDGPU::lo16)
8682 .addReg(Undef)
8683 .addImm(AMDGPU::hi16);
8684 Inst.eraseFromParent();
8685 MRI.replaceRegWith(DstReg, NewDstReg);
8686 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8687 return;
8688 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8689 AMDGPU::lo16)) {
8690 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
8691 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8692 MRI.replaceRegWith(DstReg, NewDstReg);
8693 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8694 return;
8695 }
8696 }
8697
8698 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8699 MRI.replaceRegWith(DstReg, NewDstReg);
8700 legalizeOperands(Inst, MDT);
8701 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8702 return;
8703 }
8704
8705 // Use the new VALU Opcode.
8706 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
8707 .setMIFlags(Inst.getFlags());
8708 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
8709 // Intersperse VOP3 modifiers among the SALU operands.
8710 NewInstr->addOperand(Inst.getOperand(0));
8711 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8712 AMDGPU::OpName::src0_modifiers) >= 0)
8713 NewInstr.addImm(0);
8714 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
8715 const MachineOperand &Src = Inst.getOperand(1);
8716 NewInstr->addOperand(Src);
8717 }
8718
8719 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8720 // We are converting these to a BFE, so we need to add the missing
8721 // operands for the size and offset.
8722 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8723 NewInstr.addImm(0);
8724 NewInstr.addImm(Size);
8725 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8726 // The VALU version adds the second operand to the result, so insert an
8727 // extra 0 operand.
8728 NewInstr.addImm(0);
8729 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8730 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
8731 // If we need to move this to VGPRs, we need to unpack the second
8732 // operand back into the 2 separate ones for bit offset and width.
8733 assert(OffsetWidthOp.isImm() &&
8734 "Scalar BFE is only implemented for constant width and offset");
8735 uint32_t Imm = OffsetWidthOp.getImm();
8736
8737 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
8738 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
8739 NewInstr.addImm(Offset);
8740 NewInstr.addImm(BitWidth);
8741 } else {
8742 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8743 AMDGPU::OpName::src1_modifiers) >= 0)
8744 NewInstr.addImm(0);
8745 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8746 NewInstr->addOperand(Inst.getOperand(2));
8747 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8748 AMDGPU::OpName::src2_modifiers) >= 0)
8749 NewInstr.addImm(0);
8750 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8751 NewInstr->addOperand(Inst.getOperand(3));
8752 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8753 NewInstr.addImm(0);
8754 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8755 NewInstr.addImm(0);
8756 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8757 NewInstr.addImm(0);
8758 }
8759 } else {
8760 // Just copy the SALU operands.
8761 for (const MachineOperand &Op : Inst.explicit_operands())
8762 NewInstr->addOperand(Op);
8763 }
8764
8765 // Remove any references to SCC. Vector instructions can't read from it, and
8766 // We're just about to add the implicit use / defs of VCC, and we don't want
8767 // both.
8768 for (MachineOperand &Op : Inst.implicit_operands()) {
8769 if (Op.getReg() == AMDGPU::SCC) {
8770 // Only propagate through live-def of SCC.
8771 if (Op.isDef() && !Op.isDead())
8772 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
8773 if (Op.isUse())
8774 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8775 }
8776 }
8777 Inst.eraseFromParent();
8778 Register NewDstReg;
8779 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8780 Register DstReg = NewInstr->getOperand(0).getReg();
8781 assert(DstReg.isVirtual());
8782 // Update the destination register class.
8783 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
8784 assert(NewDstRC);
8785 NewDstReg = MRI.createVirtualRegister(NewDstRC);
8786 MRI.replaceRegWith(DstReg, NewDstReg);
8787 }
8788 fixImplicitOperands(*NewInstr);
8789
8790 // Legalize the operands
8791 legalizeOperands(*NewInstr, MDT);
8792 if (NewDstReg)
8793 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8794}
8795
8796// Add/sub require special handling to deal with carry outs.
8797std::pair<bool, MachineBasicBlock *>
8798SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
8799 MachineDominatorTree *MDT) const {
8800 if (ST.hasAddNoCarryInsts()) {
8801 // Assume there is no user of scc since we don't select this in that case.
8802 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
8803 // is used.
8804
8805 MachineBasicBlock &MBB = *Inst.getParent();
8806 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8807
8808 Register OldDstReg = Inst.getOperand(0).getReg();
8809 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8810
8811 unsigned Opc = Inst.getOpcode();
8812 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
8813
8814 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
8815 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8816
8817 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
8818 Inst.removeOperand(3);
8819
8820 Inst.setDesc(get(NewOpc));
8821 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
8822 Inst.addImplicitDefUseOperands(*MBB.getParent());
8823 MRI.replaceRegWith(OldDstReg, ResultReg);
8824 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
8825
8826 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8827 return std::pair(true, NewBB);
8828 }
8829
8830 return std::pair(false, nullptr);
8831}
8832
8833void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
8834 MachineDominatorTree *MDT) const {
8835
8836 MachineBasicBlock &MBB = *Inst.getParent();
8837 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8838 MachineBasicBlock::iterator MII = Inst;
8839 const DebugLoc &DL = Inst.getDebugLoc();
8840
8841 MachineOperand &Dest = Inst.getOperand(0);
8842 MachineOperand &Src0 = Inst.getOperand(1);
8843 MachineOperand &Src1 = Inst.getOperand(2);
8844 MachineOperand &Cond = Inst.getOperand(3);
8845
8846 Register CondReg = Cond.getReg();
8847 bool IsSCC = (CondReg == AMDGPU::SCC);
8848
8849 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
8850 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
8851 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
8852 // output directly into the V_CNDMASK.
8853 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
8854 (Src1.getImm() == 0)) {
8855 for (MachineOperand &UseMO :
8857 MachineInstr &UseMI = *UseMO.getParent();
8858 switch (UseMI.getOpcode()) {
8859 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8860 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8861 case AMDGPU::V_CNDMASK_B16_t16_e32:
8862 case AMDGPU::V_CNDMASK_B16_t16_e64:
8863 case AMDGPU::V_CNDMASK_B32_e32:
8864 case AMDGPU::V_CNDMASK_B32_e64:
8865 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8866 if (UseMO.isImplicit() ||
8867 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
8868 UseMO.setReg(CondReg);
8869 }
8870 }
8871 if (MRI.use_nodbg_empty(Dest.getReg()))
8872 return;
8873 }
8874
8875 Register NewCondReg = CondReg;
8876 if (IsSCC) {
8877 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
8878 NewCondReg = MRI.createVirtualRegister(TC);
8879
8880 // Now look for the closest SCC def if it is a copy
8881 // replacing the CondReg with the COPY source register
8882 bool CopyFound = false;
8883 for (MachineInstr &CandI :
8885 Inst.getParent()->rend())) {
8886 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
8887 -1) {
8888 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
8889 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
8890 .addReg(CandI.getOperand(1).getReg());
8891 CopyFound = true;
8892 }
8893 break;
8894 }
8895 }
8896 if (!CopyFound) {
8897 // SCC def is not a copy
8898 // Insert a trivial select instead of creating a copy, because a copy from
8899 // SCC would semantically mean just copying a single bit, but we may need
8900 // the result to be a vector condition mask that needs preserving.
8901 unsigned Opcode =
8902 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
8903 auto NewSelect =
8904 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
8905 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
8906 }
8907 }
8908
8909 Register NewDestReg = MRI.createVirtualRegister(
8910 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
8911 MachineInstr *NewInst;
8912 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
8913 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
8914 .addImm(0)
8915 .add(Src1) // False
8916 .addImm(0)
8917 .add(Src0) // True
8918 .addReg(NewCondReg);
8919 } else {
8920 NewInst =
8921 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
8922 .add(Src1) // False
8923 .add(Src0) // True
8924 .addReg(NewCondReg);
8925 }
8926 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
8927 legalizeOperands(*NewInst, MDT);
8928 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
8929}
8930
8931void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
8932 MachineInstr &Inst) const {
8933 MachineBasicBlock &MBB = *Inst.getParent();
8934 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8935 MachineBasicBlock::iterator MII = Inst;
8936 const DebugLoc &DL = Inst.getDebugLoc();
8937
8938 MachineOperand &Dest = Inst.getOperand(0);
8939 MachineOperand &Src = Inst.getOperand(1);
8940 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8941 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8942
8943 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8944 : AMDGPU::V_SUB_CO_U32_e32;
8945
8946 BuildMI(MBB, MII, DL, get(SubOp), TmpReg)
8947 .addImm(0)
8948 .addReg(Src.getReg());
8949
8950 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
8951 .addReg(Src.getReg())
8952 .addReg(TmpReg);
8953
8954 MRI.replaceRegWith(Dest.getReg(), ResultReg);
8955 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8956}
8957
8958void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
8959 MachineInstr &Inst) const {
8960 MachineBasicBlock &MBB = *Inst.getParent();
8961 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8962 MachineBasicBlock::iterator MII = Inst;
8963 const DebugLoc &DL = Inst.getDebugLoc();
8964
8965 MachineOperand &Dest = Inst.getOperand(0);
8966 MachineOperand &Src1 = Inst.getOperand(1);
8967 MachineOperand &Src2 = Inst.getOperand(2);
8968 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8969 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8970 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8971
8972 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8973 : AMDGPU::V_SUB_CO_U32_e32;
8974
8975 BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
8976 .addReg(Src1.getReg())
8977 .addReg(Src2.getReg());
8978
8979 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
8980
8981 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
8982 .addReg(SubResultReg)
8983 .addReg(TmpReg);
8984
8985 MRI.replaceRegWith(Dest.getReg(), ResultReg);
8986 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8987}
8988
8989void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
8990 MachineInstr &Inst) const {
8991 MachineBasicBlock &MBB = *Inst.getParent();
8992 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8993 MachineBasicBlock::iterator MII = Inst;
8994 const DebugLoc &DL = Inst.getDebugLoc();
8995
8996 MachineOperand &Dest = Inst.getOperand(0);
8997 MachineOperand &Src0 = Inst.getOperand(1);
8998 MachineOperand &Src1 = Inst.getOperand(2);
8999
9000 if (ST.hasDLInsts()) {
9001 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9002 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
9003 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
9004
9005 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
9006 .add(Src0)
9007 .add(Src1);
9008
9009 MRI.replaceRegWith(Dest.getReg(), NewDest);
9010 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9011 } else {
9012 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
9013 // invert either source and then perform the XOR. If either source is a
9014 // scalar register, then we can leave the inversion on the scalar unit to
9015 // achieve a better distribution of scalar and vector instructions.
9016 bool Src0IsSGPR = Src0.isReg() &&
9017 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
9018 bool Src1IsSGPR = Src1.isReg() &&
9019 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
9020 MachineInstr *Xor;
9021 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9022 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9023
9024 // Build a pair of scalar instructions and add them to the work list.
9025 // The next iteration over the work list will lower these to the vector
9026 // unit as necessary.
9027 if (Src0IsSGPR) {
9028 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
9029 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9030 .addReg(Temp)
9031 .add(Src1);
9032 } else if (Src1IsSGPR) {
9033 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
9034 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9035 .add(Src0)
9036 .addReg(Temp);
9037 } else {
9038 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
9039 .add(Src0)
9040 .add(Src1);
9041 MachineInstr *Not =
9042 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
9043 Worklist.insert(Not);
9044 }
9045
9046 MRI.replaceRegWith(Dest.getReg(), NewDest);
9047
9048 Worklist.insert(Xor);
9049
9050 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9051 }
9052}
9053
9054void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
9055 MachineInstr &Inst,
9056 unsigned Opcode) const {
9057 MachineBasicBlock &MBB = *Inst.getParent();
9058 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9059 MachineBasicBlock::iterator MII = Inst;
9060 const DebugLoc &DL = Inst.getDebugLoc();
9061
9062 MachineOperand &Dest = Inst.getOperand(0);
9063 MachineOperand &Src0 = Inst.getOperand(1);
9064 MachineOperand &Src1 = Inst.getOperand(2);
9065
9066 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9067 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9068
9069 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
9070 .add(Src0)
9071 .add(Src1);
9072
9073 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
9074 .addReg(Interm);
9075
9076 Worklist.insert(&Op);
9077 Worklist.insert(&Not);
9078
9079 MRI.replaceRegWith(Dest.getReg(), NewDest);
9080 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9081}
9082
9083void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
9084 MachineInstr &Inst,
9085 unsigned Opcode) const {
9086 MachineBasicBlock &MBB = *Inst.getParent();
9087 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9088 MachineBasicBlock::iterator MII = Inst;
9089 const DebugLoc &DL = Inst.getDebugLoc();
9090
9091 MachineOperand &Dest = Inst.getOperand(0);
9092 MachineOperand &Src0 = Inst.getOperand(1);
9093 MachineOperand &Src1 = Inst.getOperand(2);
9094
9095 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9096 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9097
9098 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
9099 .add(Src1);
9100
9101 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
9102 .add(Src0)
9103 .addReg(Interm);
9104
9105 Worklist.insert(&Not);
9106 Worklist.insert(&Op);
9107
9108 MRI.replaceRegWith(Dest.getReg(), NewDest);
9109 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9110}
9111
9112void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
9113 MachineInstr &Inst, unsigned Opcode,
9114 bool Swap) const {
9115 MachineBasicBlock &MBB = *Inst.getParent();
9116 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9117
9118 MachineOperand &Dest = Inst.getOperand(0);
9119 MachineOperand &Src0 = Inst.getOperand(1);
9120 const DebugLoc &DL = Inst.getDebugLoc();
9121
9122 MachineBasicBlock::iterator MII = Inst;
9123
9124 const MCInstrDesc &InstDesc = get(Opcode);
9125 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9126 MRI.getRegClass(Src0.getReg()) :
9127 &AMDGPU::SGPR_32RegClass;
9128
9129 const TargetRegisterClass *Src0SubRC =
9130 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9131
9132 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9133 AMDGPU::sub0, Src0SubRC);
9134
9135 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9136 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9137 const TargetRegisterClass *NewDestSubRC =
9138 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9139
9140 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9141 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
9142
9143 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9144 AMDGPU::sub1, Src0SubRC);
9145
9146 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9147 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
9148
9149 if (Swap)
9150 std::swap(DestSub0, DestSub1);
9151
9152 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9153 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9154 .addReg(DestSub0)
9155 .addImm(AMDGPU::sub0)
9156 .addReg(DestSub1)
9157 .addImm(AMDGPU::sub1);
9158
9159 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9160
9161 Worklist.insert(&LoHalf);
9162 Worklist.insert(&HiHalf);
9163
9164 // We don't need to legalizeOperands here because for a single operand, src0
9165 // will support any kind of input.
9166
9167 // Move all users of this moved value.
9168 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9169}
9170
9171// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9172// split the s_mul_u64 in 32-bit vector multiplications.
9173void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9174 MachineInstr &Inst,
9175 MachineDominatorTree *MDT) const {
9176 MachineBasicBlock &MBB = *Inst.getParent();
9177 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9178
9179 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9180 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9181 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9182
9183 MachineOperand &Dest = Inst.getOperand(0);
9184 MachineOperand &Src0 = Inst.getOperand(1);
9185 MachineOperand &Src1 = Inst.getOperand(2);
9186 const DebugLoc &DL = Inst.getDebugLoc();
9187 MachineBasicBlock::iterator MII = Inst;
9188
9189 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9190 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9191 const TargetRegisterClass *Src0SubRC =
9192 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9193 if (RI.isSGPRClass(Src0SubRC))
9194 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9195 const TargetRegisterClass *Src1SubRC =
9196 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9197 if (RI.isSGPRClass(Src1SubRC))
9198 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9199
9200 // First, we extract the low 32-bit and high 32-bit values from each of the
9201 // operands.
9202 MachineOperand Op0L =
9203 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9204 MachineOperand Op1L =
9205 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9206 MachineOperand Op0H =
9207 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9208 MachineOperand Op1H =
9209 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9210
9211 // The multilication is done as follows:
9212 //
9213 // Op1H Op1L
9214 // * Op0H Op0L
9215 // --------------------
9216 // Op1H*Op0L Op1L*Op0L
9217 // + Op1H*Op0H Op1L*Op0H
9218 // -----------------------------------------
9219 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9220 //
9221 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9222 // value and that would overflow.
9223 // The low 32-bit value is Op1L*Op0L.
9224 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9225
9226 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9227 MachineInstr *Op1L_Op0H =
9228 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9229 .add(Op1L)
9230 .add(Op0H);
9231
9232 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9233 MachineInstr *Op1H_Op0L =
9234 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9235 .add(Op1H)
9236 .add(Op0L);
9237
9238 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9239 MachineInstr *Carry =
9240 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9241 .add(Op1L)
9242 .add(Op0L);
9243
9244 MachineInstr *LoHalf =
9245 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9246 .add(Op1L)
9247 .add(Op0L);
9248
9249 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9250 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9251 .addReg(Op1L_Op0H_Reg)
9252 .addReg(Op1H_Op0L_Reg);
9253
9254 MachineInstr *HiHalf =
9255 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9256 .addReg(AddReg)
9257 .addReg(CarryReg);
9258
9259 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9260 .addReg(DestSub0)
9261 .addImm(AMDGPU::sub0)
9262 .addReg(DestSub1)
9263 .addImm(AMDGPU::sub1);
9264
9265 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9266
9267 // Try to legalize the operands in case we need to swap the order to keep it
9268 // valid.
9269 legalizeOperands(*Op1L_Op0H, MDT);
9270 legalizeOperands(*Op1H_Op0L, MDT);
9271 legalizeOperands(*Carry, MDT);
9272 legalizeOperands(*LoHalf, MDT);
9273 legalizeOperands(*Add, MDT);
9274 legalizeOperands(*HiHalf, MDT);
9275
9276 // Move all users of this moved value.
9277 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9278}
9279
9280// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9281// multiplications.
9282void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9283 MachineInstr &Inst,
9284 MachineDominatorTree *MDT) const {
9285 MachineBasicBlock &MBB = *Inst.getParent();
9286 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9287
9288 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9289 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9290 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9291
9292 MachineOperand &Dest = Inst.getOperand(0);
9293 MachineOperand &Src0 = Inst.getOperand(1);
9294 MachineOperand &Src1 = Inst.getOperand(2);
9295 const DebugLoc &DL = Inst.getDebugLoc();
9296 MachineBasicBlock::iterator MII = Inst;
9297
9298 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9299 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9300 const TargetRegisterClass *Src0SubRC =
9301 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9302 if (RI.isSGPRClass(Src0SubRC))
9303 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9304 const TargetRegisterClass *Src1SubRC =
9305 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9306 if (RI.isSGPRClass(Src1SubRC))
9307 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9308
9309 // First, we extract the low 32-bit and high 32-bit values from each of the
9310 // operands.
9311 MachineOperand Op0L =
9312 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9313 MachineOperand Op1L =
9314 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9315
9316 unsigned Opc = Inst.getOpcode();
9317 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9318 ? AMDGPU::V_MUL_HI_U32_e64
9319 : AMDGPU::V_MUL_HI_I32_e64;
9320 MachineInstr *HiHalf =
9321 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9322
9323 MachineInstr *LoHalf =
9324 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9325 .add(Op1L)
9326 .add(Op0L);
9327
9328 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9329 .addReg(DestSub0)
9330 .addImm(AMDGPU::sub0)
9331 .addReg(DestSub1)
9332 .addImm(AMDGPU::sub1);
9333
9334 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9335
9336 // Try to legalize the operands in case we need to swap the order to keep it
9337 // valid.
9338 legalizeOperands(*HiHalf, MDT);
9339 legalizeOperands(*LoHalf, MDT);
9340
9341 // Move all users of this moved value.
9342 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9343}
9344
9345void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9346 MachineInstr &Inst, unsigned Opcode,
9347 MachineDominatorTree *MDT) const {
9348 MachineBasicBlock &MBB = *Inst.getParent();
9349 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9350
9351 MachineOperand &Dest = Inst.getOperand(0);
9352 MachineOperand &Src0 = Inst.getOperand(1);
9353 MachineOperand &Src1 = Inst.getOperand(2);
9354 const DebugLoc &DL = Inst.getDebugLoc();
9355
9356 MachineBasicBlock::iterator MII = Inst;
9357
9358 const MCInstrDesc &InstDesc = get(Opcode);
9359 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9360 MRI.getRegClass(Src0.getReg()) :
9361 &AMDGPU::SGPR_32RegClass;
9362
9363 const TargetRegisterClass *Src0SubRC =
9364 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9365 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9366 MRI.getRegClass(Src1.getReg()) :
9367 &AMDGPU::SGPR_32RegClass;
9368
9369 const TargetRegisterClass *Src1SubRC =
9370 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9371
9372 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9373 AMDGPU::sub0, Src0SubRC);
9374 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9375 AMDGPU::sub0, Src1SubRC);
9376 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9377 AMDGPU::sub1, Src0SubRC);
9378 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9379 AMDGPU::sub1, Src1SubRC);
9380
9381 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9382 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9383 const TargetRegisterClass *NewDestSubRC =
9384 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9385
9386 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9387 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9388 .add(SrcReg0Sub0)
9389 .add(SrcReg1Sub0);
9390
9391 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9392 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9393 .add(SrcReg0Sub1)
9394 .add(SrcReg1Sub1);
9395
9396 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9397 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9398 .addReg(DestSub0)
9399 .addImm(AMDGPU::sub0)
9400 .addReg(DestSub1)
9401 .addImm(AMDGPU::sub1);
9402
9403 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9404
9405 Worklist.insert(&LoHalf);
9406 Worklist.insert(&HiHalf);
9407
9408 // Move all users of this moved value.
9409 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9410}
9411
9412void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9413 MachineInstr &Inst,
9414 MachineDominatorTree *MDT) const {
9415 MachineBasicBlock &MBB = *Inst.getParent();
9416 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9417
9418 MachineOperand &Dest = Inst.getOperand(0);
9419 MachineOperand &Src0 = Inst.getOperand(1);
9420 MachineOperand &Src1 = Inst.getOperand(2);
9421 const DebugLoc &DL = Inst.getDebugLoc();
9422
9423 MachineBasicBlock::iterator MII = Inst;
9424
9425 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9426
9427 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9428
9429 MachineOperand* Op0;
9430 MachineOperand* Op1;
9431
9432 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9433 Op0 = &Src0;
9434 Op1 = &Src1;
9435 } else {
9436 Op0 = &Src1;
9437 Op1 = &Src0;
9438 }
9439
9440 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9441 .add(*Op0);
9442
9443 Register NewDest = MRI.createVirtualRegister(DestRC);
9444
9445 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9446 .addReg(Interm)
9447 .add(*Op1);
9448
9449 MRI.replaceRegWith(Dest.getReg(), NewDest);
9450
9451 Worklist.insert(&Xor);
9452}
9453
9454void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9455 MachineInstr &Inst) const {
9456 MachineBasicBlock &MBB = *Inst.getParent();
9457 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9458
9459 MachineBasicBlock::iterator MII = Inst;
9460 const DebugLoc &DL = Inst.getDebugLoc();
9461
9462 MachineOperand &Dest = Inst.getOperand(0);
9463 MachineOperand &Src = Inst.getOperand(1);
9464
9465 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9466 const TargetRegisterClass *SrcRC = Src.isReg() ?
9467 MRI.getRegClass(Src.getReg()) :
9468 &AMDGPU::SGPR_32RegClass;
9469
9470 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9471 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9472
9473 const TargetRegisterClass *SrcSubRC =
9474 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9475
9476 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9477 AMDGPU::sub0, SrcSubRC);
9478 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9479 AMDGPU::sub1, SrcSubRC);
9480
9481 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9482
9483 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9484
9485 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9486
9487 // We don't need to legalize operands here. src0 for either instruction can be
9488 // an SGPR, and the second input is unused or determined here.
9489 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9490}
9491
9492void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9493 MachineInstr &Inst) const {
9494 MachineBasicBlock &MBB = *Inst.getParent();
9495 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9496 MachineBasicBlock::iterator MII = Inst;
9497 const DebugLoc &DL = Inst.getDebugLoc();
9498
9499 MachineOperand &Dest = Inst.getOperand(0);
9500 uint32_t Imm = Inst.getOperand(2).getImm();
9501 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9502 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9503
9504 (void) Offset;
9505
9506 // Only sext_inreg cases handled.
9507 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9508 Offset == 0 && "Not implemented");
9509
9510 if (BitWidth < 32) {
9511 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9512 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9513 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9514
9515 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9516 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9517 .addImm(0)
9518 .addImm(BitWidth);
9519
9520 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9521 .addImm(31)
9522 .addReg(MidRegLo);
9523
9524 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9525 .addReg(MidRegLo)
9526 .addImm(AMDGPU::sub0)
9527 .addReg(MidRegHi)
9528 .addImm(AMDGPU::sub1);
9529
9530 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9531 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9532 return;
9533 }
9534
9535 MachineOperand &Src = Inst.getOperand(1);
9536 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9537 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9538
9539 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9540 .addImm(31)
9541 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9542
9543 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9544 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9545 .addImm(AMDGPU::sub0)
9546 .addReg(TmpReg)
9547 .addImm(AMDGPU::sub1);
9548
9549 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9550 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9551}
9552
9553void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9554 MachineInstr &Inst, unsigned Opcode,
9555 MachineDominatorTree *MDT) const {
9556 // (S_FLBIT_I32_B64 hi:lo) ->
9557 // -> (umin (V_FFBH_U32_e32 hi), (uaddsat (V_FFBH_U32_e32 lo), 32))
9558 // (S_FF1_I32_B64 hi:lo) ->
9559 // ->(umin (uaddsat (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9560
9561 MachineBasicBlock &MBB = *Inst.getParent();
9562 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9563 MachineBasicBlock::iterator MII = Inst;
9564 const DebugLoc &DL = Inst.getDebugLoc();
9565
9566 MachineOperand &Dest = Inst.getOperand(0);
9567 MachineOperand &Src = Inst.getOperand(1);
9568
9569 const MCInstrDesc &InstDesc = get(Opcode);
9570
9571 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9572 unsigned OpcodeAdd = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64
9573 : AMDGPU::V_ADD_CO_U32_e32;
9574
9575 const TargetRegisterClass *SrcRC =
9576 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9577 const TargetRegisterClass *SrcSubRC =
9578 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9579
9580 MachineOperand SrcRegSub0 =
9581 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9582 MachineOperand SrcRegSub1 =
9583 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9584
9585 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9586 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9587 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9588 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9589
9590 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9591
9592 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9593
9594 BuildMI(MBB, MII, DL, get(OpcodeAdd), MidReg3)
9595 .addReg(IsCtlz ? MidReg1 : MidReg2)
9596 .addImm(32)
9597 .addImm(1); // enable clamp
9598
9599 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9600 .addReg(MidReg3)
9601 .addReg(IsCtlz ? MidReg2 : MidReg1);
9602
9603 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9604
9605 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9606}
9607
9608void SIInstrInfo::addUsersToMoveToVALUWorklist(
9609 Register DstReg, MachineRegisterInfo &MRI,
9610 SIInstrWorklist &Worklist) const {
9611 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9612 MachineInstr &UseMI = *MO.getParent();
9613
9614 unsigned OpNo = 0;
9615
9616 switch (UseMI.getOpcode()) {
9617 case AMDGPU::COPY:
9618 case AMDGPU::WQM:
9619 case AMDGPU::SOFT_WQM:
9620 case AMDGPU::STRICT_WWM:
9621 case AMDGPU::STRICT_WQM:
9622 case AMDGPU::REG_SEQUENCE:
9623 case AMDGPU::PHI:
9624 case AMDGPU::INSERT_SUBREG:
9625 break;
9626 default:
9627 OpNo = MO.getOperandNo();
9628 break;
9629 }
9630
9631 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9632 MRI.constrainRegClass(DstReg, OpRC);
9633
9634 if (!RI.hasVectorRegisters(OpRC))
9635 Worklist.insert(&UseMI);
9636 else
9637 // Legalization could change user list.
9638 legalizeOperandsVALUt16(UseMI, OpNo, MRI);
9639 }
9640}
9641
9642void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
9644 MachineInstr &Inst) const {
9645 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9646 MachineBasicBlock *MBB = Inst.getParent();
9647 MachineOperand &Src0 = Inst.getOperand(1);
9648 MachineOperand &Src1 = Inst.getOperand(2);
9649 const DebugLoc &DL = Inst.getDebugLoc();
9650
9651 if (ST.useRealTrue16Insts()) {
9652 Register SrcReg0, SrcReg1;
9653 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
9654 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9655 BuildMI(*MBB, Inst, DL,
9656 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9657 .add(Src0);
9658 } else {
9659 SrcReg0 = Src0.getReg();
9660 }
9661
9662 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
9663 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9664 BuildMI(*MBB, Inst, DL,
9665 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9666 .add(Src1);
9667 } else {
9668 SrcReg1 = Src1.getReg();
9669 }
9670
9671 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
9672 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
9673
9674 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
9675 switch (Inst.getOpcode()) {
9676 case AMDGPU::S_PACK_LL_B32_B16:
9677 NewMI
9678 .addReg(SrcReg0, {},
9679 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9680 .addImm(AMDGPU::lo16)
9681 .addReg(SrcReg1, {},
9682 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9683 .addImm(AMDGPU::hi16);
9684 break;
9685 case AMDGPU::S_PACK_LH_B32_B16:
9686 NewMI
9687 .addReg(SrcReg0, {},
9688 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9689 .addImm(AMDGPU::lo16)
9690 .addReg(SrcReg1, {}, AMDGPU::hi16)
9691 .addImm(AMDGPU::hi16);
9692 break;
9693 case AMDGPU::S_PACK_HL_B32_B16:
9694 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9695 .addImm(AMDGPU::lo16)
9696 .addReg(SrcReg1, {},
9697 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9698 .addImm(AMDGPU::hi16);
9699 break;
9700 case AMDGPU::S_PACK_HH_B32_B16:
9701 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9702 .addImm(AMDGPU::lo16)
9703 .addReg(SrcReg1, {}, AMDGPU::hi16)
9704 .addImm(AMDGPU::hi16);
9705 break;
9706 default:
9707 llvm_unreachable("unhandled s_pack_* instruction");
9708 }
9709
9710 MachineOperand &Dest = Inst.getOperand(0);
9711 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9712 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9713 return;
9714 }
9715
9716 switch (Inst.getOpcode()) {
9717 case AMDGPU::S_PACK_LL_B32_B16: {
9718 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9719 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9720
9721 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
9722 // 0.
9723 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9724 .addImm(0xffff);
9725
9726 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
9727 .addReg(ImmReg, RegState::Kill)
9728 .add(Src0);
9729
9730 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9731 .add(Src1)
9732 .addImm(16)
9733 .addReg(TmpReg, RegState::Kill);
9734 break;
9735 }
9736 case AMDGPU::S_PACK_LH_B32_B16: {
9737 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9738 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9739 .addImm(0xffff);
9740 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
9741 .addReg(ImmReg, RegState::Kill)
9742 .add(Src0)
9743 .add(Src1);
9744 break;
9745 }
9746 case AMDGPU::S_PACK_HL_B32_B16: {
9747 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9748 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9749 .addImm(16)
9750 .add(Src0);
9751 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9752 .add(Src1)
9753 .addImm(16)
9754 .addReg(TmpReg, RegState::Kill);
9755 break;
9756 }
9757 case AMDGPU::S_PACK_HH_B32_B16: {
9758 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9759 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9760 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9761 .addImm(16)
9762 .add(Src0);
9763 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9764 .addImm(0xffff0000);
9765 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
9766 .add(Src1)
9767 .addReg(ImmReg, RegState::Kill)
9768 .addReg(TmpReg, RegState::Kill);
9769 break;
9770 }
9771 default:
9772 llvm_unreachable("unhandled s_pack_* instruction");
9773 }
9774
9775 MachineOperand &Dest = Inst.getOperand(0);
9776 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9777 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9778}
9779
9780void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
9781 MachineInstr &SCCDefInst,
9782 SIInstrWorklist &Worklist,
9783 Register NewCond) const {
9784
9785 // Ensure that def inst defines SCC, which is still live.
9786 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
9787 !Op.isDead() && Op.getParent() == &SCCDefInst);
9788 SmallVector<MachineInstr *, 4> CopyToDelete;
9789 // This assumes that all the users of SCC are in the same block
9790 // as the SCC def.
9791 for (MachineInstr &MI : // Skip the def inst itself.
9792 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
9793 SCCDefInst.getParent()->end())) {
9794 // Check if SCC is used first.
9795 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
9796 if (SCCIdx != -1) {
9797 if (MI.isCopy()) {
9798 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
9799 Register DestReg = MI.getOperand(0).getReg();
9800
9801 MRI.replaceRegWith(DestReg, NewCond);
9802 CopyToDelete.push_back(&MI);
9803 } else {
9804
9805 if (NewCond.isValid())
9806 MI.getOperand(SCCIdx).setReg(NewCond);
9807
9808 Worklist.insert(&MI);
9809 }
9810 }
9811 // Exit if we find another SCC def.
9812 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
9813 break;
9814 }
9815 for (auto &Copy : CopyToDelete)
9816 Copy->eraseFromParent();
9817}
9818
9819// Instructions that use SCC may be converted to VALU instructions. When that
9820// happens, the SCC register is changed to VCC_LO. The instruction that defines
9821// SCC must be changed to an instruction that defines VCC. This function makes
9822// sure that the instruction that defines SCC is added to the moveToVALU
9823// worklist.
9824void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
9825 SIInstrWorklist &Worklist) const {
9826 // Look for a preceding instruction that either defines VCC or SCC. If VCC
9827 // then there is nothing to do because the defining instruction has been
9828 // converted to a VALU already. If SCC then that instruction needs to be
9829 // converted to a VALU.
9830 for (MachineInstr &MI :
9831 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
9832 SCCUseInst->getParent()->rend())) {
9833 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
9834 break;
9835 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
9836 Worklist.insert(&MI);
9837 break;
9838 }
9839 }
9840}
9841
9842const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
9843 const MachineInstr &Inst) const {
9844 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
9845
9846 switch (Inst.getOpcode()) {
9847 // For target instructions, getOpRegClass just returns the virtual register
9848 // class associated with the operand, so we need to find an equivalent VGPR
9849 // register class in order to move the instruction to the VALU.
9850 case AMDGPU::COPY:
9851 case AMDGPU::PHI:
9852 case AMDGPU::REG_SEQUENCE:
9853 case AMDGPU::INSERT_SUBREG:
9854 case AMDGPU::WQM:
9855 case AMDGPU::SOFT_WQM:
9856 case AMDGPU::STRICT_WWM:
9857 case AMDGPU::STRICT_WQM: {
9858 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
9859 if (RI.isAGPRClass(SrcRC)) {
9860 if (RI.isAGPRClass(NewDstRC))
9861 return nullptr;
9862
9863 switch (Inst.getOpcode()) {
9864 case AMDGPU::PHI:
9865 case AMDGPU::REG_SEQUENCE:
9866 case AMDGPU::INSERT_SUBREG:
9867 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9868 break;
9869 default:
9870 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9871 }
9872
9873 if (!NewDstRC)
9874 return nullptr;
9875 } else {
9876 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9877 return nullptr;
9878
9879 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9880 if (!NewDstRC)
9881 return nullptr;
9882 }
9883
9884 return NewDstRC;
9885 }
9886 default:
9887 return NewDstRC;
9888 }
9889}
9890
9891// Find the one SGPR operand we are allowed to use.
9892Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
9893 int OpIndices[3]) const {
9894 const MCInstrDesc &Desc = MI.getDesc();
9895
9896 // Find the one SGPR operand we are allowed to use.
9897 //
9898 // First we need to consider the instruction's operand requirements before
9899 // legalizing. Some operands are required to be SGPRs, such as implicit uses
9900 // of VCC, but we are still bound by the constant bus requirement to only use
9901 // one.
9902 //
9903 // If the operand's class is an SGPR, we can never move it.
9904
9905 Register SGPRReg = findImplicitSGPRRead(MI);
9906 if (SGPRReg)
9907 return SGPRReg;
9908
9909 Register UsedSGPRs[3] = {Register()};
9910 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
9911
9912 for (unsigned i = 0; i < 3; ++i) {
9913 int Idx = OpIndices[i];
9914 if (Idx == -1)
9915 break;
9916
9917 const MachineOperand &MO = MI.getOperand(Idx);
9918 if (!MO.isReg())
9919 continue;
9920
9921 // Is this operand statically required to be an SGPR based on the operand
9922 // constraints?
9923 const TargetRegisterClass *OpRC =
9924 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
9925 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
9926 if (IsRequiredSGPR)
9927 return MO.getReg();
9928
9929 // If this could be a VGPR or an SGPR, Check the dynamic register class.
9930 Register Reg = MO.getReg();
9931 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
9932 if (RI.isSGPRClass(RegRC))
9933 UsedSGPRs[i] = Reg;
9934 }
9935
9936 // We don't have a required SGPR operand, so we have a bit more freedom in
9937 // selecting operands to move.
9938
9939 // Try to select the most used SGPR. If an SGPR is equal to one of the
9940 // others, we choose that.
9941 //
9942 // e.g.
9943 // V_FMA_F32 v0, s0, s0, s0 -> No moves
9944 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
9945
9946 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
9947 // prefer those.
9948
9949 if (UsedSGPRs[0]) {
9950 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
9951 SGPRReg = UsedSGPRs[0];
9952 }
9953
9954 if (!SGPRReg && UsedSGPRs[1]) {
9955 if (UsedSGPRs[1] == UsedSGPRs[2])
9956 SGPRReg = UsedSGPRs[1];
9957 }
9958
9959 return SGPRReg;
9960}
9961
9963 AMDGPU::OpName OperandName) const {
9964 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
9965 return nullptr;
9966
9967 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
9968 if (Idx == -1)
9969 return nullptr;
9970
9971 return &MI.getOperand(Idx);
9972}
9973
9975 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
9976 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
9979 return (Format << 44) |
9980 (1ULL << 56) | // RESOURCE_LEVEL = 1
9981 (3ULL << 60); // OOB_SELECT = 3
9982 }
9983
9984 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
9985 if (ST.isAmdHsaOS()) {
9986 // Set ATC = 1. GFX9 doesn't have this bit.
9987 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
9988 RsrcDataFormat |= (1ULL << 56);
9989
9990 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
9991 // BTW, it disables TC L2 and therefore decreases performance.
9992 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
9993 RsrcDataFormat |= (2ULL << 59);
9994 }
9995
9996 return RsrcDataFormat;
9997}
9998
10002 0xffffffff; // Size;
10003
10004 // GFX9 doesn't have ELEMENT_SIZE.
10005 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
10006 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
10007 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
10008 }
10009
10010 // IndexStride = 64 / 32.
10011 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10012 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
10013
10014 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
10015 // Clear them unless we want a huge stride.
10016 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
10017 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
10018 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
10019
10020 return Rsrc23;
10021}
10022
10024 unsigned Opc = MI.getOpcode();
10025
10026 return isSMRD(Opc);
10027}
10028
10030 return get(Opc).mayLoad() &&
10031 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
10032}
10033
10035 TypeSize &MemBytes) const {
10036 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
10037 if (!Addr || !Addr->isFI())
10038 return Register();
10039
10040 assert(!MI.memoperands_empty() &&
10041 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
10042
10043 FrameIndex = Addr->getIndex();
10044
10045 int VDataIdx =
10046 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
10047 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
10048 return MI.getOperand(VDataIdx).getReg();
10049}
10050
10052 TypeSize &MemBytes) const {
10053 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
10054 assert(Addr && Addr->isFI());
10055 FrameIndex = Addr->getIndex();
10056
10057 int DataIdx =
10058 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
10059 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
10060 return MI.getOperand(DataIdx).getReg();
10061}
10062
10064 int &FrameIndex,
10065 TypeSize &MemBytes) const {
10066 if (!MI.mayLoad())
10067 return Register();
10068
10069 if (isMUBUF(MI) || isVGPRSpill(MI))
10070 return isStackAccess(MI, FrameIndex, MemBytes);
10071
10072 if (isSGPRSpill(MI))
10073 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10074
10075 return Register();
10076}
10077
10079 int &FrameIndex,
10080 TypeSize &MemBytes) const {
10081 if (!MI.mayStore())
10082 return Register();
10083
10084 if (isMUBUF(MI) || isVGPRSpill(MI))
10085 return isStackAccess(MI, FrameIndex, MemBytes);
10086
10087 if (isSGPRSpill(MI))
10088 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10089
10090 return Register();
10091}
10092
10094 unsigned Opc = MI.getOpcode();
10096 unsigned DescSize = Desc.getSize();
10097
10098 // If we have a definitive size, we can use it. Otherwise we need to inspect
10099 // the operands to know the size.
10100 if (isFixedSize(MI)) {
10101 unsigned Size = DescSize;
10102
10103 // If we hit the buggy offset, an extra nop will be inserted in MC so
10104 // estimate the worst case.
10105 if (MI.isBranch() && ST.hasOffset3fBug())
10106 Size += 4;
10107
10108 return Size;
10109 }
10110
10111 // Instructions may have a 32-bit literal encoded after them. Check
10112 // operands that could ever be literals.
10113 if (isVALU(MI, /*AllowLDSDMA=*/true) || isSALU(MI)) {
10114 if (isDPP(MI))
10115 return DescSize;
10116 bool HasLiteral = false;
10117 unsigned LiteralSize = 4;
10118 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
10119 const MachineOperand &Op = MI.getOperand(I);
10120 const MCOperandInfo &OpInfo = Desc.operands()[I];
10121 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
10122 HasLiteral = true;
10123 if (ST.has64BitLiterals()) {
10124 switch (OpInfo.OperandType) {
10125 default:
10126 break;
10129 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
10130 LiteralSize = 8;
10131 break;
10134 // A 32-bit literal is only valid when the value fits in BOTH signed
10135 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
10136 // emitter's getLit64Encoding logic. This is because of the lack of
10137 // abilility to tell signedness of the literal, therefore we need to
10138 // be conservative and assume values outside this range require a
10139 // 64-bit literal encoding (8 bytes).
10140 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
10141 !isUInt<32>(Op.getImm()))
10142 LiteralSize = 8;
10143 break;
10144 }
10145 }
10146 break;
10147 }
10148 }
10149 return HasLiteral ? DescSize + LiteralSize : DescSize;
10150 }
10151
10152 // Check whether we have extra NSA words.
10153 if (isMIMG(MI)) {
10154 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
10155 if (VAddr0Idx < 0)
10156 return 8;
10157
10158 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
10159 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10160 }
10161
10162 switch (Opc) {
10163 case TargetOpcode::BUNDLE:
10164 return getInstBundleSize(MI);
10165 case TargetOpcode::INLINEASM:
10166 case TargetOpcode::INLINEASM_BR: {
10167 const MachineFunction *MF = MI.getMF();
10168 const char *AsmStr = MI.getOperand(0).getSymbolName();
10169 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10170 }
10171 default:
10172 if (MI.isMetaInstruction())
10173 return 0;
10174
10175 // If D16 Pseudo inst, get correct MC code size
10176 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10177 if (D16Info) {
10178 // Assume d16_lo/hi inst are always in same size
10179 unsigned LoInstOpcode = D16Info->LoOp;
10180 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10181 DescSize = Desc.getSize();
10182 }
10183
10184 // If FMA Pseudo inst, get correct MC code size
10185 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10186 // All potential lowerings are the same size; arbitrarily pick one.
10187 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10188 DescSize = Desc.getSize();
10189 }
10190
10191 return DescSize;
10192 }
10193}
10194
10197 if (MI.isBranch() && ST.hasOffset3fBug())
10198 return InstSizeVerifyMode::NoVerify;
10199 return InstSizeVerifyMode::ExactSize;
10200}
10201
10203 if (!isFLAT(MI))
10204 return false;
10205
10206 if (MI.memoperands_empty())
10207 return true;
10208
10209 for (const MachineMemOperand *MMO : MI.memoperands()) {
10211 return true;
10212 }
10213 return false;
10214}
10215
10218 static const std::pair<int, const char *> TargetIndices[] = {
10219 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10220 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10221 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10222 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10223 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10224 return ArrayRef(TargetIndices);
10225}
10226
10227/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10228/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10231 const ScheduleDAG *DAG) const {
10232 return new GCNHazardRecognizer(DAG->MF);
10233}
10234
10235/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10236/// pass.
10243
10244// Called during:
10245// - pre-RA scheduling and post-RA scheduling
10248 const ScheduleDAGMI *DAG) const {
10249 // Borrowed from Arm Target
10250 // We would like to restrict this hazard recognizer to only
10251 // post-RA scheduling; we can tell that we're post-RA because we don't
10252 // track VRegLiveness.
10253 if (!DAG->hasVRegLiveness())
10254 return new GCNHazardRecognizer(DAG->MF);
10256}
10257
10258std::pair<unsigned, unsigned>
10260 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10261}
10262
10265 static const std::pair<unsigned, const char *> TargetFlags[] = {
10266 {MO_GOTPCREL, "amdgpu-gotprel"},
10267 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10268 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10269 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10270 {MO_REL32_LO, "amdgpu-rel32-lo"},
10271 {MO_REL32_HI, "amdgpu-rel32-hi"},
10272 {MO_REL64, "amdgpu-rel64"},
10273 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10274 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10275 {MO_ABS64, "amdgpu-abs64"},
10276 };
10277
10278 return ArrayRef(TargetFlags);
10279}
10280
10283 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10284 {
10285 {MONoClobber, "amdgpu-noclobber"},
10286 {MOLastUse, "amdgpu-last-use"},
10287 {MOCooperative, "amdgpu-cooperative"},
10288 {MOThreadPrivate, "amdgpu-thread-private"},
10289 };
10290
10291 return ArrayRef(TargetFlags);
10292}
10293
10295 const MachineFunction &MF) const {
10297 assert(SrcReg.isVirtual());
10298 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10299 return AMDGPU::WWM_COPY;
10300
10301 return AMDGPU::COPY;
10302}
10303
10305 uint32_t Opcode = MI.getOpcode();
10306 // Check if it is SGPR spill or wwm-register spill Opcode.
10307 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10308 return true;
10309
10310 const MachineFunction *MF = MI.getMF();
10311 const MachineRegisterInfo &MRI = MF->getRegInfo();
10313
10314 // See if this is Liverange split instruction inserted for SGPR or
10315 // wwm-register. The implicit def inserted for wwm-registers should also be
10316 // included as they can appear at the bb begin.
10317 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10318 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10319 return false;
10320
10321 Register Reg = MI.getOperand(0).getReg();
10322 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10323 return IsLRSplitInst;
10324
10325 return MFI->isWWMReg(Reg);
10326}
10327
10329 Register Reg) const {
10330 // We need to handle instructions which may be inserted during register
10331 // allocation to handle the prolog. The initial prolog instruction may have
10332 // been separated from the start of the block by spills and copies inserted
10333 // needed by the prolog. However, the insertions for scalar registers can
10334 // always be placed at the BB top as they are independent of the exec mask
10335 // value.
10336 bool IsNullOrVectorRegister = true;
10337 if (Reg) {
10338 const MachineFunction *MF = MI.getMF();
10339 const MachineRegisterInfo &MRI = MF->getRegInfo();
10340 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10341 }
10342
10343 return IsNullOrVectorRegister &&
10344 (canAddToBBProlog(MI) ||
10345 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10346 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10347}
10348
10352 const DebugLoc &DL,
10353 Register DestReg) const {
10354 if (ST.hasAddNoCarryInsts())
10355 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10356
10357 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10358 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10359 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10360
10361 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10362 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10363}
10364
10367 const DebugLoc &DL,
10368 Register DestReg,
10369 RegScavenger &RS) const {
10370 if (ST.hasAddNoCarryInsts())
10371 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10372
10373 // If available, prefer to use vcc.
10374 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10375 ? Register(RI.getVCC())
10376 : RS.scavengeRegisterBackwards(
10377 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10378 0, /* AllowSpill */ false);
10379
10380 // TODO: Users need to deal with this.
10381 if (!UnusedCarry.isValid())
10382 return MachineInstrBuilder();
10383
10384 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10385 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10386}
10387
10388bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10389 switch (Opcode) {
10390 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10391 case AMDGPU::SI_KILL_I1_TERMINATOR:
10392 return true;
10393 default:
10394 return false;
10395 }
10396}
10397
10399 switch (Opcode) {
10400 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10401 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10402 case AMDGPU::SI_KILL_I1_PSEUDO:
10403 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10404 default:
10405 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10406 }
10407}
10408
10409bool SIInstrInfo::isLegalMUBUFImmOffset(unsigned Imm) const {
10410 return Imm <= getMaxMUBUFImmOffset(ST);
10411}
10412
10414 // GFX12 field is non-negative 24-bit signed byte offset.
10415 const unsigned OffsetBits =
10416 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10417 return (1 << OffsetBits) - 1;
10418}
10419
10421 if (!ST.isWave32())
10422 return;
10423
10424 if (MI.isInlineAsm())
10425 return;
10426
10427 if (MI.getNumOperands() < MI.getNumExplicitOperands())
10428 return;
10429
10430 for (auto &Op : MI.implicit_operands()) {
10431 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10432 Op.setReg(AMDGPU::VCC_LO);
10433 }
10434}
10435
10437 if (!isSMRD(MI))
10438 return false;
10439
10440 // Check that it is using a buffer resource.
10441 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10442 if (Idx == -1) // e.g. s_memtime
10443 return false;
10444
10445 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10446 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10447}
10448
10449// Given Imm, split it into the values to put into the SOffset and ImmOffset
10450// fields in an MUBUF instruction. Return false if it is not possible (due to a
10451// hardware bug needing a workaround).
10452//
10453// The required alignment ensures that individual address components remain
10454// aligned if they are aligned to begin with. It also ensures that additional
10455// offsets within the given alignment can be added to the resulting ImmOffset.
10457 uint32_t &ImmOffset, Align Alignment) const {
10458 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10459 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10460 uint32_t Overflow = 0;
10461
10462 if (Imm > MaxImm) {
10463 if (Imm <= MaxImm + 64) {
10464 // Use an SOffset inline constant for 4..64
10465 Overflow = Imm - MaxImm;
10466 Imm = MaxImm;
10467 } else {
10468 // Try to keep the same value in SOffset for adjacent loads, so that
10469 // the corresponding register contents can be re-used.
10470 //
10471 // Load values with all low-bits (except for alignment bits) set into
10472 // SOffset, so that a larger range of values can be covered using
10473 // s_movk_i32.
10474 //
10475 // Atomic operations fail to work correctly when individual address
10476 // components are unaligned, even if their sum is aligned.
10477 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10478 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10479 Imm = Low;
10480 Overflow = High - Alignment.value();
10481 }
10482 }
10483
10484 if (Overflow > 0) {
10485 // There is a hardware bug in SI and CI which prevents address clamping in
10486 // MUBUF instructions from working correctly with SOffsets. The immediate
10487 // offset is unaffected.
10488 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10489 return false;
10490
10491 // It is not possible to set immediate in SOffset field on some targets.
10492 if (ST.hasRestrictedSOffset())
10493 return false;
10494 }
10495
10496 ImmOffset = Imm;
10497 SOffset = Overflow;
10498 return true;
10499}
10500
10501// Depending on the used address space and instructions, some immediate offsets
10502// are allowed and some are not.
10503// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10504// scratch instruction offsets can also be negative. On GFX12, offsets can be
10505// negative for all variants.
10506//
10507// There are several bugs related to these offsets:
10508// On gfx10.1, flat instructions that go into the global address space cannot
10509// use an offset.
10510//
10511// For scratch instructions, the address can be either an SGPR or a VGPR.
10512// The following offsets can be used, depending on the architecture (x means
10513// cannot be used):
10514// +----------------------------+------+------+
10515// | Address-Mode | SGPR | VGPR |
10516// +----------------------------+------+------+
10517// | gfx9 | | |
10518// | negative, 4-aligned offset | x | ok |
10519// | negative, unaligned offset | x | ok |
10520// +----------------------------+------+------+
10521// | gfx10 | | |
10522// | negative, 4-aligned offset | ok | ok |
10523// | negative, unaligned offset | ok | x |
10524// +----------------------------+------+------+
10525// | gfx10.3 | | |
10526// | negative, 4-aligned offset | ok | ok |
10527// | negative, unaligned offset | ok | ok |
10528// +----------------------------+------+------+
10529//
10530// This function ignores the addressing mode, so if an offset cannot be used in
10531// one addressing mode, it is considered illegal.
10532bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10533 AMDGPU::FlatAddrSpace FlatVariant) const {
10534 // TODO: Should 0 be special cased?
10535 if (!ST.hasFlatInstOffsets())
10536 return false;
10537
10539 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10540 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10541 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10542 return false;
10543
10544 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10545 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10546 (Offset % 4) != 0) {
10547 return false;
10548 }
10549
10550 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10551 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10552 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10553}
10554
10555// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10556std::pair<int64_t, int64_t>
10557SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10558 AMDGPU::FlatAddrSpace FlatVariant) const {
10559 int64_t RemainderOffset = COffsetVal;
10560 int64_t ImmField = 0;
10561
10562 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10563 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10564
10565 if (AllowNegative) {
10566 // Use signed division by a power of two to truncate towards 0.
10567 int64_t D = 1LL << NumBits;
10568 RemainderOffset = (COffsetVal / D) * D;
10569 ImmField = COffsetVal - RemainderOffset;
10570
10571 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10572 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10573 (ImmField % 4) != 0) {
10574 // Make ImmField a multiple of 4
10575 RemainderOffset += ImmField % 4;
10576 ImmField -= ImmField % 4;
10577 }
10578 } else if (COffsetVal >= 0) {
10579 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10580 RemainderOffset = COffsetVal - ImmField;
10581 }
10582
10583 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10584 assert(RemainderOffset + ImmField == COffsetVal);
10585 return {ImmField, RemainderOffset};
10586}
10587
10589 AMDGPU::FlatAddrSpace FlatVariant) const {
10590 if (ST.hasNegativeScratchOffsetBug() &&
10592 return false;
10593
10594 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10595}
10596
10597static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10598 switch (ST.getGeneration()) {
10599 default:
10600 break;
10603 return SIEncodingFamily::SI;
10606 return SIEncodingFamily::VI;
10610 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10613 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10617 }
10618 llvm_unreachable("Unknown subtarget generation!");
10619}
10620
10621bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10622 switch(MCOp) {
10623 // These opcodes use indirect register addressing so
10624 // they need special handling by codegen (currently missing).
10625 // Therefore it is too risky to allow these opcodes
10626 // to be selected by dpp combiner or sdwa peepholer.
10627 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10628 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10629 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10630 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10631 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10632 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10633 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10634 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10635 return true;
10636 default:
10637 return false;
10638 }
10639}
10640
10641#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10642 case OPCODE##_dpp: \
10643 case OPCODE##_e32: \
10644 case OPCODE##_e64: \
10645 case OPCODE##_e64_dpp: \
10646 case OPCODE##_sdwa:
10647
10648static bool isRenamedInGFX9(int Opcode) {
10649 switch (Opcode) {
10650 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
10651 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
10652 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
10653 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
10654 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
10655 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
10656 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
10657 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
10658 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
10659 //
10660 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10661 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10662 case AMDGPU::V_FMA_F16_gfx9_e64:
10663 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10664 case AMDGPU::V_INTERP_P2_F16:
10665 case AMDGPU::V_MAD_F16_e64:
10666 case AMDGPU::V_MAD_U16_e64:
10667 case AMDGPU::V_MAD_I16_e64:
10668 return true;
10669 default:
10670 return false;
10671 }
10672}
10673
10674int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
10675 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
10676 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10677
10678 unsigned Gen = subtargetEncodingFamily(ST);
10679
10680 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
10682
10683 // Adjust the encoding family to GFX80 for D16 buffer instructions when the
10684 // subtarget has UnpackedD16VMem feature.
10685 // TODO: remove this when we discard GFX80 encoding.
10686 if (ST.hasUnpackedD16VMem() && SIInstrFlags::isD16Buf(get(Opcode)))
10688
10689 if (SIInstrFlags::isSDWA(get(Opcode))) {
10690 switch (ST.getGeneration()) {
10691 default:
10693 break;
10696 break;
10699 break;
10700 }
10701 }
10702
10703 if (isMAI(Opcode)) {
10704 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
10705 if (MFMAOp != -1)
10706 Opcode = MFMAOp;
10707 }
10708
10709 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
10710
10711 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10713
10714 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10716
10717 // -1 means that Opcode is already a native instruction.
10718 if (MCOp == -1)
10719 return Opcode;
10720
10721 if (ST.hasGFX90AInsts()) {
10722 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10723 if (ST.hasGFX940Insts())
10725 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10727 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10729 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10730 MCOp = NMCOp;
10731 }
10732
10733 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
10734 // encoding in the given subtarget generation.
10735 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10736 return -1;
10737
10738 if (isAsmOnlyOpcode(MCOp))
10739 return -1;
10740
10741 return MCOp;
10742}
10743
10744static
10746 assert(RegOpnd.isReg());
10747 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
10748 getRegSubRegPair(RegOpnd);
10749}
10750
10753 assert(MI.isRegSequence());
10754 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
10755 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
10756 auto &RegOp = MI.getOperand(1 + 2 * I);
10757 return getRegOrUndef(RegOp);
10758 }
10760}
10761
10762// Try to find the definition of reg:subreg in subreg-manipulation pseudos
10763// Following a subreg of reg:subreg isn't supported
10766 if (!RSR.SubReg)
10767 return false;
10768 switch (MI.getOpcode()) {
10769 default: break;
10770 case AMDGPU::REG_SEQUENCE:
10771 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
10772 return true;
10773 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
10774 case AMDGPU::INSERT_SUBREG:
10775 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
10776 // inserted the subreg we're looking for
10777 RSR = getRegOrUndef(MI.getOperand(2));
10778 else { // the subreg in the rest of the reg
10779 auto R1 = getRegOrUndef(MI.getOperand(1));
10780 if (R1.SubReg) // subreg of subreg isn't supported
10781 return false;
10782 RSR.Reg = R1.Reg;
10783 }
10784 return true;
10785 }
10786 return false;
10787}
10788
10790 const MachineRegisterInfo &MRI) {
10791 assert(MRI.isSSA());
10792 if (!P.Reg.isVirtual())
10793 return nullptr;
10794
10795 auto RSR = P;
10796 auto *DefInst = MRI.getVRegDef(RSR.Reg);
10797 while (auto *MI = DefInst) {
10798 DefInst = nullptr;
10799 switch (MI->getOpcode()) {
10800 case AMDGPU::COPY:
10801 case AMDGPU::V_MOV_B32_e32: {
10802 auto &Op1 = MI->getOperand(1);
10803 if (Op1.isReg() && Op1.getReg().isVirtual()) {
10804 if (Op1.isUndef())
10805 return nullptr;
10806 RSR = getRegSubRegPair(Op1);
10807 DefInst = MRI.getVRegDef(RSR.Reg);
10808 }
10809 break;
10810 }
10811 default:
10812 if (followSubRegDef(*MI, RSR)) {
10813 if (!RSR.Reg)
10814 return nullptr;
10815 DefInst = MRI.getVRegDef(RSR.Reg);
10816 }
10817 }
10818 if (!DefInst)
10819 return MI;
10820 }
10821 return nullptr;
10822}
10823
10825 Register VReg,
10826 const MachineInstr &DefMI,
10827 const MachineInstr &UseMI) {
10828 assert(MRI.isSSA() && "Must be run on SSA");
10829
10830 auto *TRI = MRI.getTargetRegisterInfo();
10831 auto *DefBB = DefMI.getParent();
10832
10833 // Don't bother searching between blocks, although it is possible this block
10834 // doesn't modify exec.
10835 if (UseMI.getParent() != DefBB)
10836 return true;
10837
10838 const int MaxInstScan = 20;
10839 int NumInst = 0;
10840
10841 // Stop scan at the use.
10842 auto E = UseMI.getIterator();
10843 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
10844 if (I->isDebugInstr())
10845 continue;
10846
10847 if (++NumInst > MaxInstScan)
10848 return true;
10849
10850 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
10851 return true;
10852 }
10853
10854 return false;
10855}
10856
10858 Register VReg,
10859 const MachineInstr &DefMI) {
10860 assert(MRI.isSSA() && "Must be run on SSA");
10861
10862 auto *TRI = MRI.getTargetRegisterInfo();
10863 auto *DefBB = DefMI.getParent();
10864
10865 const int MaxUseScan = 10;
10866 int NumUse = 0;
10867
10868 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
10869 auto &UseInst = *Use.getParent();
10870 // Don't bother searching between blocks, although it is possible this block
10871 // doesn't modify exec.
10872 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10873 return true;
10874
10875 if (++NumUse > MaxUseScan)
10876 return true;
10877 }
10878
10879 if (NumUse == 0)
10880 return false;
10881
10882 const int MaxInstScan = 20;
10883 int NumInst = 0;
10884
10885 // Stop scan when we have seen all the uses.
10886 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
10887 assert(I != DefBB->end());
10888
10889 if (I->isDebugInstr())
10890 continue;
10891
10892 if (++NumInst > MaxInstScan)
10893 return true;
10894
10895 for (const MachineOperand &Op : I->operands()) {
10896 // We don't check reg masks here as they're used only on calls:
10897 // 1. EXEC is only considered const within one BB
10898 // 2. Call should be a terminator instruction if present in a BB
10899
10900 if (!Op.isReg())
10901 continue;
10902
10903 Register Reg = Op.getReg();
10904 if (Op.isUse()) {
10905 if (Reg == VReg && --NumUse == 0)
10906 return false;
10907 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
10908 return true;
10909 }
10910 }
10911}
10912
10915 const DebugLoc &DL, Register Src, Register Dst) const {
10916 auto Cur = MBB.begin();
10917 if (Cur != MBB.end())
10918 do {
10919 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
10920 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
10921 ++Cur;
10922 } while (Cur != MBB.end() && Cur != LastPHIIt);
10923
10924 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
10925 Dst);
10926}
10927
10930 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
10931 if (InsPt != MBB.end() &&
10932 (InsPt->getOpcode() == AMDGPU::SI_IF ||
10933 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
10934 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
10935 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
10936 InsPt++;
10937 return BuildMI(MBB, InsPt, DL,
10938 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
10939 .addReg(Src, {}, SrcSubReg)
10940 .addReg(AMDGPU::EXEC, RegState::Implicit);
10941 }
10942 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
10943 Dst);
10944}
10945
10946bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
10947
10949 const MachineInstr &SecondMI) const {
10950 for (const auto &Use : SecondMI.all_uses()) {
10951 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
10952 return true;
10953 }
10954 return false;
10955}
10956
10957/// If OpX is multicycle, anti-dependencies are not allowed.
10958/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
10959/// purpose.
10961 const MachineInstr &OpX) const {
10963}
10964
10967 ArrayRef<unsigned> Ops, int FrameIndex,
10968 MachineInstr *&CopyMI, LiveIntervals *LIS,
10969 VirtRegMap *VRM) const {
10970 // This is a bit of a hack (copied from AArch64). Consider this instruction:
10971 //
10972 // %0:sreg_32 = COPY $m0
10973 //
10974 // We explicitly chose SReg_32 for the virtual register so such a copy might
10975 // be eliminated by RegisterCoalescer. However, that may not be possible, and
10976 // %0 may even spill. We can't spill $m0 normally (it would require copying to
10977 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
10978 // TargetInstrInfo::foldMemoryOperand() is going to try.
10979 // A similar issue also exists with spilling and reloading $exec registers.
10980 //
10981 // To prevent that, constrain the %0 register class here.
10982 if (isFullCopyInstr(MI)) {
10983 Register DstReg = MI.getOperand(0).getReg();
10984 Register SrcReg = MI.getOperand(1).getReg();
10985 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
10986 (DstReg.isVirtual() != SrcReg.isVirtual())) {
10987 MachineRegisterInfo &MRI = MF.getRegInfo();
10988 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
10989 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
10990 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
10991 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
10992 return nullptr;
10993 }
10994 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
10995 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
10996 return nullptr;
10997 }
10998 }
10999 }
11000
11001 return nullptr;
11002}
11003
11005 const MachineInstr &MI,
11006 unsigned *PredCost) const {
11007 if (MI.isBundle()) {
11009 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
11010 unsigned Lat = 0, Count = 0;
11011 for (++I; I != E && I->isBundledWithPred(); ++I) {
11012 ++Count;
11013 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
11014 }
11015 return Lat + Count - 1;
11016 }
11017
11018 return SchedModel.computeInstrLatency(&MI);
11019}
11020
11021const MachineOperand &
11023 if (const MachineOperand *CallAddrOp =
11024 getNamedOperand(MI, AMDGPU::OpName::src0))
11025 return *CallAddrOp;
11027}
11028
11031 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11032 unsigned Opcode = MI.getOpcode();
11033
11034 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
11035 Register Dst = MI.getOperand(0).getReg();
11036 Register Src = isa<GIntrinsic>(MI) ? MI.getOperand(2).getReg()
11037 : MI.getOperand(1).getReg();
11038 LLT DstTy = MRI.getType(Dst);
11039 LLT SrcTy = MRI.getType(Src);
11040 unsigned DstAS = DstTy.getAddressSpace();
11041 unsigned SrcAS = SrcTy.getAddressSpace();
11042 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
11043 DstAS == AMDGPUAS::FLAT_ADDRESS &&
11044 ST.hasGloballyAddressableScratch()
11047 };
11048
11049 // If the target supports globally addressable scratch, the mapping from
11050 // scratch memory to the flat aperture changes therefore an address space cast
11051 // is no longer uniform.
11052 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11053 return HandleAddrSpaceCast(MI);
11054
11055 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
11056 auto IID = GI->getIntrinsicID();
11061
11062 switch (IID) {
11063 case Intrinsic::amdgcn_addrspacecast_nonnull:
11064 return HandleAddrSpaceCast(MI);
11065 case Intrinsic::amdgcn_if:
11066 case Intrinsic::amdgcn_else:
11067 // FIXME: Uniform if second result
11068 break;
11069 }
11070
11072 }
11073
11074 // Loads from the private and flat address spaces are divergent, because
11075 // threads can execute the load instruction with the same inputs and get
11076 // different results.
11077 //
11078 // All other loads are not divergent, because if threads issue loads with the
11079 // same arguments, they will always get the same result.
11080 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11081 Opcode == AMDGPU::G_SEXTLOAD) {
11082 if (MI.memoperands_empty())
11083 return ValueUniformity::NeverUniform; // conservative assumption
11084
11085 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11086 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11087 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11088 })) {
11089 // At least one MMO in a non-global address space.
11091 }
11093 }
11094
11095 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11096 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11097 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11098 AMDGPU::isGenericAtomic(Opcode)) {
11100 }
11101
11102 // Result is computed from uniform SP and uniform wave-wide max size.
11103 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11105
11106 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11108
11110}
11111
11113 if (!Formatter)
11114 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11115 return Formatter.get();
11116}
11117
11119
11120 if (isNeverUniform(MI))
11122
11123 unsigned opcode = MI.getOpcode();
11124 if (opcode == AMDGPU::V_READLANE_B32 ||
11125 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11126 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11128
11129 // If any of defs is divergent, report as NeverUniform. isUniformReg will
11130 // calculate in more detail for each def from its reg class, if available.
11131 if (MI.isInlineAsm()) {
11132 for (const MachineOperand &MO : MI.operands()) {
11133 if (!MO.isReg() || !MO.isDef())
11134 continue;
11135 const TargetRegisterClass *RC =
11136 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
11137 if (!RC || !RI.isSGPRClass(RC))
11139 }
11140 }
11141
11142 if (isCopyInstr(MI)) {
11143 const MachineOperand &srcOp = MI.getOperand(1);
11144 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
11145 const TargetRegisterClass *regClass =
11146 RI.getPhysRegBaseClass(srcOp.getReg());
11147 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
11149 }
11151 }
11152
11153 // GMIR handling
11154 if (MI.isPreISelOpcode())
11156
11157 // Atomics are divergent because they are executed sequentially: when an
11158 // atomic operation refers to the same address in each thread, then each
11159 // thread after the first sees the value written by the previous thread as
11160 // original value.
11161
11162 if (isAtomic(MI))
11164
11165 // Loads from the private and flat address spaces are divergent, because
11166 // threads can execute the load instruction with the same inputs and get
11167 // different results.
11168 if (isFLAT(MI) && MI.mayLoad()) {
11169 if (MI.memoperands_empty())
11170 return ValueUniformity::NeverUniform; // conservative assumption
11171
11172 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11173 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11174 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11175 })) {
11176 // At least one MMO in a non-global address space.
11178 }
11179
11181 }
11182
11183 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11184 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11185
11186 // FIXME: It's conceptually broken to report this for an instruction, and not
11187 // a specific def operand. For inline asm in particular, there could be mixed
11188 // uniform and divergent results.
11189 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11190 const MachineOperand &SrcOp = MI.getOperand(I);
11191 if (!SrcOp.isReg())
11192 continue;
11193
11194 Register Reg = SrcOp.getReg();
11195 if (!Reg || !SrcOp.readsReg())
11196 continue;
11197
11198 // If RegBank is null, this is unassigned or an unallocatable special
11199 // register, which are all scalars.
11200 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11201 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11203 }
11204
11205 // TODO: Uniformity check condtions above can be rearranged for more
11206 // redability
11207
11208 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11209 // currently turned into no-op COPYs by SelectionDAG ISel and are
11210 // therefore no longer recognizable.
11211
11213}
11214
11216 switch (MF.getFunction().getCallingConv()) {
11218 return 1;
11220 return 2;
11222 return 3;
11226 const Function &F = MF.getFunction();
11227 F.getContext().diagnose(DiagnosticInfoUnsupported(
11228 F, "ds_ordered_count unsupported for this calling conv"));
11229 [[fallthrough]];
11230 }
11233 case CallingConv::C:
11234 case CallingConv::Fast:
11235 default:
11236 // Assume other calling conventions are various compute callable functions
11237 return 0;
11238 }
11239}
11240
11242 Register &SrcReg2, int64_t &CmpMask,
11243 int64_t &CmpValue) const {
11244 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11245 return false;
11246
11247 switch (MI.getOpcode()) {
11248 default:
11249 break;
11250 case AMDGPU::S_CMP_EQ_U32:
11251 case AMDGPU::S_CMP_EQ_I32:
11252 case AMDGPU::S_CMP_LG_U32:
11253 case AMDGPU::S_CMP_LG_I32:
11254 case AMDGPU::S_CMP_LT_U32:
11255 case AMDGPU::S_CMP_LT_I32:
11256 case AMDGPU::S_CMP_GT_U32:
11257 case AMDGPU::S_CMP_GT_I32:
11258 case AMDGPU::S_CMP_LE_U32:
11259 case AMDGPU::S_CMP_LE_I32:
11260 case AMDGPU::S_CMP_GE_U32:
11261 case AMDGPU::S_CMP_GE_I32:
11262 case AMDGPU::S_CMP_EQ_U64:
11263 case AMDGPU::S_CMP_LG_U64:
11264 SrcReg = MI.getOperand(0).getReg();
11265 if (MI.getOperand(1).isReg()) {
11266 if (MI.getOperand(1).getSubReg())
11267 return false;
11268 SrcReg2 = MI.getOperand(1).getReg();
11269 CmpValue = 0;
11270 } else if (MI.getOperand(1).isImm()) {
11271 SrcReg2 = Register();
11272 CmpValue = MI.getOperand(1).getImm();
11273 } else {
11274 return false;
11275 }
11276 CmpMask = ~0;
11277 return true;
11278 case AMDGPU::S_CMPK_EQ_U32:
11279 case AMDGPU::S_CMPK_EQ_I32:
11280 case AMDGPU::S_CMPK_LG_U32:
11281 case AMDGPU::S_CMPK_LG_I32:
11282 case AMDGPU::S_CMPK_LT_U32:
11283 case AMDGPU::S_CMPK_LT_I32:
11284 case AMDGPU::S_CMPK_GT_U32:
11285 case AMDGPU::S_CMPK_GT_I32:
11286 case AMDGPU::S_CMPK_LE_U32:
11287 case AMDGPU::S_CMPK_LE_I32:
11288 case AMDGPU::S_CMPK_GE_U32:
11289 case AMDGPU::S_CMPK_GE_I32:
11290 SrcReg = MI.getOperand(0).getReg();
11291 SrcReg2 = Register();
11292 CmpValue = MI.getOperand(1).getImm();
11293 CmpMask = ~0;
11294 return true;
11295 }
11296
11297 return false;
11298}
11299
11301 for (MachineBasicBlock *S : MBB->successors()) {
11302 if (S->isLiveIn(AMDGPU::SCC))
11303 return false;
11304 }
11305 return true;
11306}
11307
11308// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11309// (incoming SCC) = !(SCC defined by SCCDef).
11310// Return true if all uses can be re-written, false otherwise.
11311bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11312 MachineBasicBlock *MBB = SCCDef->getParent();
11313 SmallVector<MachineInstr *> InvertInstr;
11314 bool SCCIsDead = false;
11315
11316 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11317 constexpr unsigned ScanLimit = 12;
11318 unsigned Count = 0;
11319 for (MachineInstr &MI :
11320 make_range(std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11321 if (++Count > ScanLimit)
11322 return false;
11323 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11324 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11325 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11326 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11327 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11328 InvertInstr.push_back(&MI);
11329 else
11330 return false;
11331 }
11332 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11333 SCCIsDead = true;
11334 break;
11335 }
11336 }
11337 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11338 SCCIsDead = true;
11339
11340 // SCC may have more uses. Can't invert all of them.
11341 if (!SCCIsDead)
11342 return false;
11343
11344 // Invert uses
11345 for (MachineInstr *MI : InvertInstr) {
11346 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11347 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11348 swapOperands(*MI);
11349 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11350 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11351 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11352 ? AMDGPU::S_CBRANCH_SCC1
11353 : AMDGPU::S_CBRANCH_SCC0));
11354 } else {
11355 llvm_unreachable("SCC used but no inversion handling");
11356 }
11357 }
11358 return true;
11359}
11360
11361// SCC is already valid after SCCValid.
11362// SCCRedefine will redefine SCC to the same value already available after
11363// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11364// update kill/dead flags if necessary.
11365bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11366 bool NeedInversion) const {
11367 MachineInstr *KillsSCC = nullptr;
11368 if (SCCValid->getParent() != SCCRedefine->getParent())
11369 return false;
11370 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11371 SCCRedefine->getIterator())) {
11372 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11373 return false;
11374 if (MI.killsRegister(AMDGPU::SCC, &RI))
11375 KillsSCC = &MI;
11376 }
11377 if (NeedInversion && !invertSCCUse(SCCRedefine))
11378 return false;
11379 if (MachineOperand *SccDef =
11380 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11381 SccDef->setIsDead(false);
11382 if (KillsSCC)
11383 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11384 SCCRedefine->eraseFromParent();
11385 return true;
11386}
11387
11388static bool foldableSelect(const MachineInstr &Def) {
11389 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11390 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11391 return false;
11392 bool Op1IsNonZeroImm =
11393 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11394 bool Op2IsZeroImm =
11395 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11396 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11397 return false;
11398 return true;
11399}
11400
11401static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11402 unsigned &NewDefOpc) {
11403 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11404 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11405 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11406 Def.getOpcode() != AMDGPU::S_ADD_U32)
11407 return false;
11408 const MachineOperand &AddSrc1 = Def.getOperand(1);
11409 const MachineOperand &AddSrc2 = Def.getOperand(2);
11410 int64_t addend;
11411
11412 if ((!AddSrc1.isImm() || AddSrc1.getImm() != 1) &&
11413 (!AddSrc2.isImm() || AddSrc2.getImm() != 1) &&
11414 (!getFoldableImm(&AddSrc1, addend) || addend != 1) &&
11415 (!getFoldableImm(&AddSrc2, addend) || addend != 1))
11416 return false;
11417
11418 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11419 const MachineOperand *SccDef =
11420 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11421 if (!SccDef->isDead())
11422 return false;
11423 NewDefOpc = AMDGPU::S_ADD_U32;
11424 }
11425 NeedInversion = !NeedInversion;
11426 return true;
11427}
11428
11430 Register SrcReg2, int64_t CmpMask,
11431 int64_t CmpValue,
11432 const MachineRegisterInfo *MRI) const {
11433 if (!SrcReg || SrcReg.isPhysical())
11434 return false;
11435
11436 if (SrcReg2 && !getFoldableImm(SrcReg2, *MRI, CmpValue))
11437 return false;
11438
11439 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11440 this](bool NeedInversion) -> bool {
11441 if (CmpValue != 0)
11442 return false;
11443
11444 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11445 if (!Def)
11446 return false;
11447
11448 // For S_OP that set SCC = DST!=0, do the transformation
11449 //
11450 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11451 //
11452 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11453 // do the transformation:
11454 //
11455 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11456 //
11457 // If foldableSelect, s_cmp_lg_* is redundant because the SCC input value
11458 // for S_CSELECT* already has the same value that will be calculated by
11459 // s_cmp_lg_*
11460 //
11461 // s_cmp_[lg|eq]_* (S_CSELECT* (non-zero imm), 0), 0 => (S_CSELECT*
11462 // (non-zero imm), 0)
11463
11464 unsigned NewDefOpc = Def->getOpcode();
11465 if (!setsSCCIfResultIsNonZero(*Def) &&
11466 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc) &&
11467 !foldableSelect(*Def))
11468 return false;
11469
11470 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11471 return false;
11472
11473 if (NewDefOpc != Def->getOpcode())
11474 Def->setDesc(get(NewDefOpc));
11475
11476 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11477 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11478 // 64-bit foldableSelect then delete s_or_b32 in the sequence:
11479 // sX = s_cselect_b64 (non-zero imm), 0
11480 // sLo = copy sX.sub0
11481 // sHi = copy sX.sub1
11482 // sY = s_or_b32 sLo, sHi
11483 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11484 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11485 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11486 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11487 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11488 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11489 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11490 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11491 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11492 Def2->getOperand(1).isReg() &&
11493 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11494 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11495 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11496 MachineInstr *Select = MRI->getVRegDef(Def1->getOperand(1).getReg());
11497 if (Select && foldableSelect(*Select))
11498 optimizeSCC(Select, Def, /*NeedInversion=*/false);
11499 }
11500 }
11501 }
11502 return true;
11503 };
11504
11505 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11506 this](int64_t ExpectedValue, unsigned SrcSize,
11507 bool IsReversible, bool IsSigned) -> bool {
11508 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11509 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11510 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11511 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11512 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11513 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11514 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11515 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11516 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11517 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11518 //
11519 // Signed ge/gt are not used for the sign bit.
11520 //
11521 // If result of the AND is unused except in the compare:
11522 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11523 //
11524 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11525 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11526 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11527 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11528 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11529 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11530
11531 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11532 if (!Def)
11533 return false;
11534
11535 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11536 Def->getOpcode() != AMDGPU::S_AND_B64)
11537 return false;
11538
11539 int64_t Mask;
11540 const auto isMask = [&Mask, SrcSize](const MachineOperand *MO) -> bool {
11541 if (MO->isImm())
11542 Mask = MO->getImm();
11543 else if (!getFoldableImm(MO, Mask))
11544 return false;
11545 Mask &= maxUIntN(SrcSize);
11546 return isPowerOf2_64(Mask);
11547 };
11548
11549 MachineOperand *SrcOp = &Def->getOperand(1);
11550 if (isMask(SrcOp))
11551 SrcOp = &Def->getOperand(2);
11552 else if (isMask(&Def->getOperand(2)))
11553 SrcOp = &Def->getOperand(1);
11554 else
11555 return false;
11556
11557 // A valid Mask is required to have a single bit set, hence a non-zero and
11558 // power-of-two value. This verifies that we will not do 64-bit shift below.
11559 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11560 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11561 if (IsSigned && BitNo == SrcSize - 1)
11562 return false;
11563
11564 ExpectedValue <<= BitNo;
11565
11566 bool IsReversedCC = false;
11567 if (CmpValue != ExpectedValue) {
11568 if (!IsReversible)
11569 return false;
11570 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11571 if (!IsReversedCC)
11572 return false;
11573 }
11574
11575 Register DefReg = Def->getOperand(0).getReg();
11576 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11577 return false;
11578
11579 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11580 return false;
11581
11582 if (!MRI->use_nodbg_empty(DefReg)) {
11583 assert(!IsReversedCC);
11584 return true;
11585 }
11586
11587 // Replace AND with unused result with a S_BITCMP.
11588 MachineBasicBlock *MBB = Def->getParent();
11589
11590 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11591 : AMDGPU::S_BITCMP1_B32
11592 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11593 : AMDGPU::S_BITCMP1_B64;
11594
11595 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11596 .add(*SrcOp)
11597 .addImm(BitNo);
11598 Def->eraseFromParent();
11599
11600 return true;
11601 };
11602
11603 switch (CmpInstr.getOpcode()) {
11604 default:
11605 break;
11606 case AMDGPU::S_CMP_EQ_U32:
11607 case AMDGPU::S_CMP_EQ_I32:
11608 case AMDGPU::S_CMPK_EQ_U32:
11609 case AMDGPU::S_CMPK_EQ_I32:
11610 return optimizeCmpAnd(1, 32, true, false) ||
11611 optimizeCmpSelect(/*NeedInversion=*/true);
11612 case AMDGPU::S_CMP_GE_U32:
11613 case AMDGPU::S_CMPK_GE_U32:
11614 return optimizeCmpAnd(1, 32, false, false);
11615 case AMDGPU::S_CMP_GE_I32:
11616 case AMDGPU::S_CMPK_GE_I32:
11617 return optimizeCmpAnd(1, 32, false, true);
11618 case AMDGPU::S_CMP_EQ_U64:
11619 return optimizeCmpAnd(1, 64, true, false);
11620 case AMDGPU::S_CMP_LG_U32:
11621 case AMDGPU::S_CMP_LG_I32:
11622 case AMDGPU::S_CMPK_LG_U32:
11623 case AMDGPU::S_CMPK_LG_I32:
11624 return optimizeCmpAnd(0, 32, true, false) ||
11625 optimizeCmpSelect(/*NeedInversion=*/false);
11626 case AMDGPU::S_CMP_GT_U32:
11627 case AMDGPU::S_CMPK_GT_U32:
11628 return optimizeCmpAnd(0, 32, false, false);
11629 case AMDGPU::S_CMP_GT_I32:
11630 case AMDGPU::S_CMPK_GT_I32:
11631 return optimizeCmpAnd(0, 32, false, true);
11632 case AMDGPU::S_CMP_LG_U64:
11633 return optimizeCmpAnd(0, 64, true, false) ||
11634 optimizeCmpSelect(/*NeedInversion=*/false);
11635 }
11636
11637 return false;
11638}
11639
11641 AMDGPU::OpName OpName) const {
11642 if (!ST.needsAlignedVGPRs())
11643 return;
11644
11645 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
11646 if (OpNo < 0)
11647 return;
11648 MachineOperand &Op = MI.getOperand(OpNo);
11649 if (getOpSize(MI, OpNo) > 4)
11650 return;
11651
11652 // Add implicit aligned super-reg to force alignment on the data operand.
11653 const DebugLoc &DL = MI.getDebugLoc();
11654 MachineBasicBlock *BB = MI.getParent();
11656 Register DataReg = Op.getReg();
11657 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11659 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11660 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
11661 Register NewVR =
11662 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
11663 : &AMDGPU::VReg_64_Align2RegClass);
11664 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
11665 .addReg(DataReg, {}, Op.getSubReg())
11666 .addImm(AMDGPU::sub0)
11667 .addReg(Undef)
11668 .addImm(AMDGPU::sub1);
11669 Op.setReg(NewVR);
11670 Op.setSubReg(AMDGPU::sub0);
11671 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
11672}
11673
11675 if (!SchedModel.hasInstrSchedModel())
11676 return 0;
11677
11678 // The repeat rate is the throughput-limiting resource occupancy: the largest
11679 // number of cycles any written processor resource is held.
11680 const MCSchedClassDesc *SCDesc = SchedModel.resolveSchedClass(&MI);
11681 unsigned RepeatRate = 0;
11683 PI = SchedModel.getWriteProcResBegin(SCDesc),
11684 PE = SchedModel.getWriteProcResEnd(SCDesc);
11685 PI != PE; ++PI) {
11686 RepeatRate = std::max(RepeatRate, (unsigned)PI->ReleaseAtCycle);
11687 }
11688
11689 return RepeatRate;
11690}
11691
11693 if (isIGLP(*MI))
11694 return false;
11695
11697}
11698
11700 if (!isWMMA(MI) && !isSWMMAC(MI))
11701 return false;
11702
11703 if (ST.hasGFX1250Insts())
11704 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
11705
11706 return true;
11707}
11708
11710 unsigned Opcode = MI.getOpcode();
11711
11712 if (AMDGPU::isGFX12Plus(ST))
11713 return isDOT(MI) || isXDLWMMA(MI);
11714
11715 if (!isMAI(MI) || isDGEMM(Opcode) ||
11716 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11717 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11718 return false;
11719
11720 if (!ST.hasGFX940Insts())
11721 return true;
11722
11723 return AMDGPU::getMAIIsGFX940XDL(Opcode);
11724}
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!")
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)
MachineInstr unsigned OpIdx
uint64_t High
uint64_t IntrinsicInst * II
#define P(N)
R600 Clause Merge
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static cl::opt< bool > Fix16BitCopies("amdgpu-fix-16-bit-physreg-copies", cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"), cl::init(true), cl::ReallyHidden)
static void expandSGPRCopy(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RC, bool Forward)
static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc)
static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize)
static bool compareMachineOp(const MachineOperand &Op0, const MachineOperand &Op1)
static bool isStride64(unsigned Opc)
static MachineBasicBlock * generateWaterFallLoop(const SIInstrInfo &TII, MachineInstr &MI, ArrayRef< MachineOperand * > ScalarOps, MachineDominatorTree *MDT, MachineBasicBlock::iterator Begin=nullptr, MachineBasicBlock::iterator End=nullptr, ArrayRef< Register > PhySGPRs={})
#define GENERATE_RENAMED_GFX9_CASES(OPCODE)
static std::tuple< unsigned, unsigned > extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc)
static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx)
static bool followSubRegDef(MachineInstr &MI, TargetInstrInfo::RegSubRegPair &RSR)
static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize)
static MachineInstr * swapImmOperands(MachineInstr &MI, MachineOperand &NonRegOp1, MachineOperand &NonRegOp2)
static void copyFlagsToImplicitVCC(MachineInstr &MI, const MachineOperand &Orig)
static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, LocationSize WidthB, int OffsetB)
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, RegScavenger &RS, bool RegsOverlap, Register ImpUseSuperReg=Register())
Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908.
static unsigned getWWMRegSpillSaveOpcode(unsigned Size, bool IsVectorSuperClass)
static bool memOpsHaveSameBaseOperands(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getWWMRegSpillRestoreOpcode(unsigned Size, bool IsVectorSuperClass)
static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion, unsigned &NewDefOpc)
static bool isSCCDeadOnExit(MachineBasicBlock *MBB)
static bool getFoldableImm(Register Reg, const MachineRegisterInfo &MRI, int64_t &Imm, MachineInstr **DefMI=nullptr)
static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize)
static unsigned subtargetEncodingFamily(const GCNSubtarget &ST)
static void preserveCondRegFlags(MachineOperand &CondReg, const MachineOperand &OrigCond)
static Register findImplicitSGPRRead(const MachineInstr &MI)
static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc)
static cl::opt< unsigned > BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16), cl::desc("Restrict range of branch instructions (DEBUG)"))
static void updateLiveVariables(LiveVariables *LV, MachineInstr &MI, MachineInstr &NewMI)
static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getSGPRSpillRestoreOpcode(unsigned Size)
static bool isRegOrFI(const MachineOperand &MO)
static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static constexpr AMDGPU::OpName ModifierOpNames[]
static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const char *Msg="illegal VGPR to SGPR copy")
static MachineInstr * swapRegAndNonRegOperand(MachineInstr &MI, MachineOperand &RegOp, MachineOperand &NonRegOp)
static bool shouldReadExec(const MachineInstr &MI)
static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc)
static bool isRenamedInGFX9(int Opcode)
static TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd)
static std::tuple< unsigned, unsigned, unsigned > splitGlobalAddressRelocFlags(const GCNSubtarget &ST, const MachineOperand &SrcOp)
static bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
static bool foldableSelect(const MachineInstr &Def)
static bool nodesHaveSameOperandValue(SDNode *N0, SDNode *N1, AMDGPU::OpName OpName)
Returns true if both nodes have the same value for the given operand Op, or if both nodes do not have...
static unsigned getNumOperandsNoGlue(SDNode *Node)
static bool canRemat(const MachineInstr &MI)
static unsigned getAVSpillRestoreOpcode(unsigned Size)
static void emitLoadScalarOpsFromVGPRLoop(const SIInstrInfo &TII, MachineRegisterInfo &MRI, MachineBasicBlock &PredBB, MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={})
static unsigned getVGPRSpillRestoreOpcode(unsigned Size)
Interface definition for SIInstrInfo.
bool IsDead
const char * Msg
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
#define LLVM_DEBUG(...)
Definition Debug.h:119
static const LaneMaskConstants & get(const GCNSubtarget &ST)
static LLVM_ABI Semantics SemanticsToEnum(const llvm::fltSemantics &Sem)
Definition APFloat.cpp:183
Class for arbitrary precision integers.
Definition APInt.h:78
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1587
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A debug info location.
Definition DebugLoc.h:126
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:299
Diagnostic information for unsupported feature in backend.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:272
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:353
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
CycleRef getParentCycle(CycleRef C) const
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
Itinerary data supplied by a subtarget to be used by a target.
constexpr unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LiveInterval - This class represents the liveness of a register, or stack slot.
bool hasInterval(Register Reg) const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
LLVM_ABI bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
This class represents the liveness of a register, stack slot, etc.
LLVM_ABI void replaceKillInstruction(Register Reg, MachineInstr &OldMI, MachineInstr &NewMI)
replaceKillInstruction - Update register kill info by replacing a kill instruction with a new one.
LLVM_ABI VarInfo & getVarInfo(Register Reg)
getVarInfo - Return the VarInfo structure for the specified VIRTUAL register.
bool hasValue() const
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:347
static const MCBinaryExpr * createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:417
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
unsigned getOpcode() const
Return the opcode number for this descriptor.
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition MCInstrDesc.h:86
uint8_t OperandType
Information about the type of the operand.
Definition MCInstrDesc.h:98
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition MCInstrDesc.h:92
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void setVariableValue(const MCExpr *Value)
Definition MCSymbol.cpp:50
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
MIRFormater - Interface to format MIR operand based on target.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
void push_back(MachineInstr *MI)
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isImmutableObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an immutable object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
bool isCopy() const
const MachineBasicBlock * getParent() const
LLVM_ABI void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
bool isBundle() const
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromBundle()
Unlink 'this' from its basic block and delete it.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mop_range explicit_operands()
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just after the instruction itself.
LLVM_ABI void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo)
Clear all kill flags affecting Reg.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
A description of a memory reference used in the backend.
unsigned getAddrSpace() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
const GlobalValue * getGlobal() const
LLVM_ABI void ChangeToFrameIndex(int Idx, unsigned TargetFlags=0)
Replace this operand with a frame index.
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
LLVM_ABI void ChangeToGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
ChangeToGA - Replace this operand with a new global address operand.
void setIsKill(bool Val=true)
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
void setOffset(int64_t Offset)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isTargetIndex() const
isTargetIndex - Tests if this is a MO_TargetIndex operand.
void setTargetFlags(unsigned F)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI 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.
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 MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const final
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
bool isSpill(uint32_t Opcode) const
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool mayAccessFlatAddressSpace(const MachineInstr &MI) const
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
bool isLegalVSrcOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO would be a valid operand for the given operand definition OpInfo.
static bool isDOT(const MachineInstr &MI)
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
bool hasModifiers(unsigned Opcode) const
Return true if this instruction has any modifiers.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
static bool isSWMMAC(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
bool isWave32() const
bool isHighLatencyDef(int Opc) const override
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const
Legalize the OpIndex operand of this instruction by inserting a MOV.
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isVOPC(const MachineInstr &MI)
void removeModOperands(MachineInstr &MI) const
unsigned getRepeatRate(const MachineInstr &MI) const
Get the repeat rate for a VALU instruction from the scheduling model.
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool isLegalSingleSGPRReadInstOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for a single-SGPR-read instruction.
bool isXDL(const MachineInstr &MI) const
Register isStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
static bool isVIMAGE(const MachineInstr &MI)
void enforceOperandRCAlignment(MachineInstr &MI, AMDGPU::OpName OpName) const
static bool isSOP2(const MachineInstr &MI)
static bool isGWS(const MachineInstr &MI)
bool hasRAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI) const
bool isLegalAV64PseudoImm(uint64_t Imm) const
Check if this immediate value can be used for AV_MOV_B64_IMM_PSEUDO.
bool isNeverCoissue(MachineInstr &MI) const
static bool isBUF(const MachineInstr &MI)
void handleCopyToPhysHelper(SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst, MachineRegisterInfo &MRI, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
bool hasModifiersSet(const MachineInstr &MI, AMDGPU::OpName OpName) const
bool isLegalToSwap(const MachineInstr &MI, unsigned fromIdx, unsigned toIdx) const
static bool isFLATGlobal(const MachineInstr &MI)
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isGlobalMemoryObject(const MachineInstr *MI) const override
static bool isVSAMPLE(const MachineInstr &MI)
bool isBufferSMRD(const MachineInstr &MI) const
static bool isKillTerminator(unsigned Opcode)
bool isVOPDAntidependencyAllowed(const MachineInstr &MI) const
If OpX is multicycle, anti-dependencies are not allowed.
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
void insertScratchExecCopy(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, bool IsSCCLive, SlotIndexes *Indexes=nullptr) const
bool hasVALU32BitEncoding(unsigned Opcode) const
Return true if this 64-bit VALU instruction has a 32-bit encoding.
unsigned getMovOpcode(const TargetRegisterClass *DstRC) const
Register isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
unsigned buildExtractSubReg(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const
Legalize operands in MI by either commuting it or inserting a copy of src1.
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const final
static bool isTRANS(const MachineInstr &MI)
static bool isImage(const MachineInstr &MI)
static bool isSOPK(const MachineInstr &MI)
const TargetRegisterClass * getOpRegClass(const MachineInstr &MI, unsigned OpNo) const
Return the correct register class for OpNo.
MachineBasicBlock * insertSimulatedTrap(MachineRegisterInfo &MRI, MachineBasicBlock &MBB, MachineInstr &MI, const DebugLoc &DL) const
Build instructions that simulate the behavior of a s_trap 2 instructions for hardware (namely,...
static unsigned getNonSoftWaitcntOpcode(unsigned Opcode)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static bool isFoldableCopy(const MachineInstr &MI)
bool isIgnorableUse(const MachineOperand &MO) const override
static bool isMUBUF(const MachineInstr &MI)
bool expandPostRAPseudo(MachineInstr &MI) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
void createWaterFallForSiCall(MachineInstr *MI, MachineDominatorTree *MDT, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={}) const
Wrapper function for generating waterfall for instruction MI This function take into consideration of...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSegmentSpecificFLAT(const MachineInstr &MI)
bool isReMaterializableImpl(const MachineInstr &MI) const override
static bool isVOP3(const MCInstrDesc &Desc)
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool physRegUsesConstantBus(const MachineOperand &Reg) const
static bool isF16PseudoScalarTrans(unsigned Opcode)
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
bool mayAccessVMEMThroughFlat(const MachineInstr &MI) const
static bool isDPP(const MachineInstr &MI)
bool analyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
static bool isMFMA(const MachineInstr &MI)
bool isLowLatencyInstruction(const MachineInstr &MI) const
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is a instruction that moves/copies value from one register to ano...
void mutateAndCleanupImplicit(MachineInstr &MI, const MCInstrDesc &NewDesc) const
ValueUniformity getGenericValueUniformity(const MachineInstr &MI) const
static bool isMAI(const MCInstrDesc &Desc)
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const override
static bool usesLGKM_CNT(const MachineInstr &MI)
void legalizeOperandsVALUt16(MachineInstr &Inst, MachineRegisterInfo &MRI) const
Fix operands in Inst to fix 16bit SALU to VALU lowering.
bool isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo, const MachineOperand &MO) const
bool canShrink(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
const MachineOperand & getCalleeOperand(const MachineInstr &MI) const override
bool isAsmOnlyOpcode(int MCOp) const
Check if this instruction should only be used by assembler.
bool isAlwaysGDS(uint32_t Opcode) const
static bool isVGPRSpill(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
This is used by the post-RA scheduler (SchedulePostRAList.cpp).
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
unsigned getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr &MI, unsigned *PredCost=nullptr) const override
unsigned getVectorRegSpillSaveOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI, bool NeedsCFI) const
int64_t getNamedImmOperand(const MachineInstr &MI, AMDGPU::OpName OperandName) const
Get required immediate operand.
ArrayRef< std::pair< int, const char * > > getSerializableTargetIndices() const override
bool regUsesConstantBus(const MachineOperand &Reg, const MachineRegisterInfo &MRI) const
static bool isMIMG(const MachineInstr &MI)
MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isLegalRegOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO (a register operand) is a legal register for the given operand description or operand ind...
static unsigned getNumWaitStates(const MachineInstr &MI)
Return the number of wait states that result from executing this instruction.
unsigned getVALUOp(const MachineInstr &MI) const
static bool modifiesModeRegister(const MachineInstr &MI)
Return true if the instruction modifies the mode register.q.
Register readlaneVGPRToSGPR(Register SrcReg, MachineInstr &UseMI, MachineRegisterInfo &MRI, const TargetRegisterClass *DstRC=nullptr) const
Copy a value from a VGPR (SrcReg) to SGPR.
bool hasDivergentBranch(const MachineBasicBlock *MBB) const
Return whether the block terminate with divergent branch.
std::pair< int64_t, int64_t > splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Split COffsetVal into {immediate offset field, remainder offset} values.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void fixImplicitOperands(MachineInstr &MI) const
bool moveFlatAddrToVGPR(MachineInstr &Inst) const
Change SADDR form of a FLAT Inst to its VADDR form if saddr operand was moved to VGPR.
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
void createReadFirstLaneFromCopyToPhysReg(MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const
bool swapSourceModifiers(MachineInstr &MI, MachineOperand &Src0, AMDGPU::OpName Src0OpName, MachineOperand &Src1, AMDGPU::OpName Src1OpName) const
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const
This function is used to determine if an instruction can be safely executed under EXEC = 0 without ha...
bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg, int64_t &ImmVal) const override
static bool isAtomic(const MachineInstr &MI)
bool canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, int &CondCycles, int &TrueCycles, int &FalseCycles) const override
bool isLiteralOperandLegal(const MCInstrDesc &InstDesc, const MCOperandInfo &OpInfo) const
static bool isWWMRegSpillOpcode(uint32_t Opcode)
static bool sopkIsZext(unsigned Opcode)
static bool isSGPRSpill(const MachineInstr &MI)
static bool isWMMA(const MachineInstr &MI)
ArrayRef< std::pair< MachineMemOperand::Flags, const char * > > getSerializableMachineMemOperandTargetFlags() const override
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, LiveIntervals *LIS) const override
bool mayReadEXEC(const MachineRegisterInfo &MRI, const MachineInstr &MI) const
Returns true if the instruction could potentially depend on the value of exec.
void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
std::pair< MachineInstr *, MachineInstr * > expandMovDPP64(MachineInstr &MI) const
static bool isSOPC(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
bool isBarrier(unsigned Opcode) const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx0, unsigned OpIdx1) const override
bool mayAccessLDSThroughFlat(const MachineInstr &MI, bool TgSplit) const
int pseudoToMCOpcode(int Opcode) const
Return a target-specific opcode if Opcode is a pseudo instruction.
const MCInstrDesc & getMCOpcodeFromPseudo(unsigned Opcode) const
Return the descriptor of the target-specific machine instruction that corresponds to the specified ps...
static bool usesVM_CNT(const MachineInstr &MI)
MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const override
static bool isFixedSize(const MachineInstr &MI)
bool isSafeToSink(MachineInstr &MI, MachineBasicBlock *SuccToSinkTo, MachineCycleInfo *CI) const override
LLVM_READONLY int commuteOpcode(unsigned Opc) const
ValueUniformity getValueUniformity(const MachineInstr &MI) const final
uint64_t getScratchRsrcWords23() const
LLVM_READONLY MachineOperand * getNamedOperand(MachineInstr &MI, AMDGPU::OpName OperandName) const
Returns the operand named Op.
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx, const MachineOperand *MO=nullptr) const
Check if MO is a legal operand if it was the OpIdx Operand for MI.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool allowNegativeFlatOffset(AMDGPU::FlatAddrSpace FlatVariant) const
Returns true if negative offsets are allowed for the given FlatVariant.
std::optional< int64_t > getImmOrMaterializedImm(MachineOperand &Op) const
void moveToVALUImpl(SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
static bool isLDSDMA(const MachineInstr &MI)
static bool isVOP1(const MachineInstr &MI)
SIInstrInfo(const GCNSubtarget &ST)
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool hasAnyModifiersSet(const MachineInstr &MI) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
void setHasSpilledVGPRs(bool Spill=true)
bool isWWMReg(Register Reg) const
bool checkFlag(Register Reg, uint8_t Flag) const
void setHasSpilledSGPRs(bool Spill=true)
unsigned getScratchReservedForDynamicVGPRs() const
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:66
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndexes pass.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:293
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
int64_t getImm() const
Register getReg() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:187
self_iterator getIterator()
Definition ilist_node.h:123
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
@ OPERAND_REG_IMM_V2FP64
Definition SIDefines.h:439
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:457
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:425
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:432
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:448
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:445
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:450
@ OPERAND_REG_IMM_V2INT64
Definition SIDefines.h:435
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:434
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:429
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:424
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:431
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:430
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:433
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:444
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:442
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:436
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:428
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:451
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:462
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:463
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:437
@ OPERAND_SDWA_VOPC_DST
Definition SIDefines.h:474
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:427
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:447
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:443
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:449
@ OPERAND_INLINE_C_AV64_PSEUDO
Definition SIDefines.h:468
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:438
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:464
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:446
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:426
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:454
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:612
@ TI_SCRATCH_RSRC_DWORD3
Definition AMDGPU.h:614
@ TI_SCRATCH_RSRC_DWORD0
Definition AMDGPU.h:611
@ TI_SCRATCH_RSRC_DWORD2
Definition AMDGPU.h:613
@ TI_CONSTDATA_START
Definition AMDGPU.h:610
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:336
constexpr bool isSDWA(const T &...O)
Definition SIDefines.h:246
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
Definition Threading.h:280
@ Offset
Definition DWP.cpp:578
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
constexpr uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
Definition MathExtras.h:208
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:547
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
Op::Description Desc
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg)
Return the SubReg component from REG_SEQUENCE.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
Definition SIInstrInfo.h:46
constexpr bool has_single_bit(T Value) noexcept
Definition bit.h:149
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
MachineInstr * getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, const MachineRegisterInfo &MRI)
Return the defining instruction for a given reg:subreg pair skipping copy like instructions and subre...
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI VirtRegInfo AnalyzeVirtRegInBundle(MachineInstr &MI, Register Reg, SmallVectorImpl< std::pair< MachineInstr *, unsigned > > *Ops=nullptr)
AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses a virtual register.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
Definition SIInstrInfo.h:54
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:395
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
Definition SIInstrInfo.h:42
constexpr unsigned BitWidth
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition SIInstrInfo.h:50
constexpr T reverseBits(T Val)
Reverse the bits in Val.
Definition MathExtras.h:119
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:573
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
constexpr RegState getUndefRegState(bool B)
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
Definition Uniformity.h:18
@ AlwaysUniform
The result value is always uniform.
Definition Uniformity.h:23
@ NeverUniform
The result value can never be assumed to be uniform.
Definition Uniformity.h:26
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
Definition SIInstrInfo.h:65
bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI)
Return false if EXEC is not changed between the def of VReg at DefMI and all its uses.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
constexpr bool all() const
Definition LaneBitmask.h:54
SparseBitVector AliveBlocks
AliveBlocks - Set of blocks in which this value is alive completely through.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:129
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Utility to store machine instructions worklist.
Definition SIInstrInfo.h:69
MachineInstr * top() const
Definition SIInstrInfo.h:74
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
Definition SIInstrInfo.h:92
void insert(MachineInstr *MI)
A pair composed of a register and a sub-register index.
VirtRegInfo - Information about a virtual register used by a set of operands.
bool Reads
Reads - One of the operands read the virtual register.
bool Writes
Writes - One of the operands writes the virtual register.