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
4916 if (ST.hasBF16InlineConstFromUpperFP32() && isVOP1(Opc)) {
4917 if ((OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_BF16 ||
4918 OpInfo.OperandType == AMDGPU::OPERAND_REG_INLINE_C_BF16) &&
4919 isInlineConstant(ImmVal, OpInfo.OperandType))
4920 return false;
4921 }
4922
4923 return RI.opCanUseInlineConstant(OpInfo.OperandType);
4924 }
4925
4926 return isLiteralOperandLegal(InstDesc, OpInfo);
4927}
4928
4929bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
4930 const MachineOperand &MO) const {
4931 if (MO.isImm())
4932 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
4933
4934 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
4935 "unexpected imm-like operand kind");
4936 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
4937 return isLiteralOperandLegal(InstDesc, OpInfo);
4938}
4939
4941 // 2 32-bit inline constants packed into one.
4942 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
4943 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
4944}
4945
4946bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
4947 // GFX90A does not have V_MUL_LEGACY_F32_e32.
4948 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
4949 return false;
4950
4951 int Op32 = AMDGPU::getVOPe32(Opcode);
4952 if (Op32 == -1)
4953 return false;
4954
4955 return pseudoToMCOpcode(Op32) != -1;
4956}
4957
4958bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
4959 // The src0_modifier operand is present on all instructions
4960 // that have modifiers.
4961
4962 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
4963}
4964
4966 AMDGPU::OpName OpName) const {
4967 const MachineOperand *Mods = getNamedOperand(MI, OpName);
4968 return Mods && Mods->getImm();
4969}
4970
4972 return any_of(ModifierOpNames,
4973 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
4974}
4975
4977 const MachineRegisterInfo &MRI) const {
4978 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4979 // Can't shrink instruction with three operands.
4980 if (Src2) {
4981 switch (MI.getOpcode()) {
4982 default: return false;
4983
4984 case AMDGPU::V_ADDC_U32_e64:
4985 case AMDGPU::V_SUBB_U32_e64:
4986 case AMDGPU::V_SUBBREV_U32_e64: {
4987 const MachineOperand *Src1
4988 = getNamedOperand(MI, AMDGPU::OpName::src1);
4989 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
4990 return false;
4991 // Additional verification is needed for sdst/src2.
4992 return true;
4993 }
4994 case AMDGPU::V_MAC_F16_e64:
4995 case AMDGPU::V_MAC_F32_e64:
4996 case AMDGPU::V_MAC_LEGACY_F32_e64:
4997 case AMDGPU::V_FMAC_F16_e64:
4998 case AMDGPU::V_FMAC_F16_t16_e64:
4999 case AMDGPU::V_FMAC_F16_fake16_e64:
5000 case AMDGPU::V_FMAC_F32_e64:
5001 case AMDGPU::V_FMAC_F64_e64:
5002 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5003 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
5004 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
5005 return false;
5006 break;
5007
5008 case AMDGPU::V_CNDMASK_B32_e64:
5009 break;
5010 }
5011 }
5012
5013 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
5014 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5015 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
5016 return false;
5017
5018 // Make sure src0 isn't using any modifiers.
5019 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
5020 return false;
5021
5022 // Can it be shrunk to a valid 32 bit opcode?
5023 if (!hasVALU32BitEncoding(MI.getOpcode()))
5024 return false;
5025
5026 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
5027 if (Src0 && Src0->isImm()) {
5028 unsigned Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5029 if (!isImmOperandLegal(
5030 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5031 *Src0))
5032 return false;
5033 }
5034
5035 // Check output modifiers
5036 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
5037 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
5038 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
5039 // TODO: Can we avoid checking bound_ctrl/fi here?
5040 // They are only used by permlane*_swap special case.
5041 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
5042 !hasModifiersSet(MI, AMDGPU::OpName::fi);
5043}
5044
5045// Set VCC operand with all flags from \p Orig, except for setting it as
5046// implicit.
5048 const MachineOperand &Orig) {
5049
5050 for (MachineOperand &Use : MI.implicit_operands()) {
5051 if (Use.isUse() &&
5052 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
5053 Use.setIsUndef(Orig.isUndef());
5054 Use.setIsKill(Orig.isKill());
5055 return;
5056 }
5057 }
5058}
5059
5061 unsigned Op32) const {
5062 MachineBasicBlock *MBB = MI.getParent();
5063
5064 const MCInstrDesc &Op32Desc = get(Op32);
5065 MachineInstrBuilder Inst32 =
5066 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
5067 .setMIFlags(MI.getFlags());
5068
5069 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
5070 // For VOPC instructions, this is replaced by an implicit def of vcc.
5071
5072 // We assume the defs of the shrunk opcode are in the same order, and the
5073 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
5074 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
5075 Inst32.add(MI.getOperand(I));
5076
5077 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5078
5079 int Idx = MI.getNumExplicitDefs();
5080 for (const MachineOperand &Use : MI.explicit_uses()) {
5081 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
5083 continue;
5084
5085 if (&Use == Src2) {
5086 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5087 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
5088 // replaced with an implicit read of vcc or vcc_lo. The implicit read
5089 // of vcc was already added during the initial BuildMI, but we
5090 // 1) may need to change vcc to vcc_lo to preserve the original register
5091 // 2) have to preserve the original flags.
5092 copyFlagsToImplicitVCC(*Inst32, *Src2);
5093 continue;
5094 }
5095 }
5096
5097 Inst32.add(Use);
5098 }
5099
5100 // FIXME: Losing implicit operands
5101 fixImplicitOperands(*Inst32);
5102 return Inst32;
5103}
5104
5106 // Null is free
5107 Register Reg = RegOp.getReg();
5108 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5109 return false;
5110
5111 // SGPRs use the constant bus
5112
5113 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
5114 // physical register operands should also count, except for exec.
5115 if (RegOp.isImplicit())
5116 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5117
5118 // SGPRs use the constant bus
5119 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5120 AMDGPU::SReg_64RegClass.contains(Reg);
5121}
5122
5124 const MachineRegisterInfo &MRI) const {
5125 Register Reg = RegOp.getReg();
5126 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5127 : physRegUsesConstantBus(RegOp);
5128}
5129
5131 const MachineOperand &MO,
5132 const MCOperandInfo &OpInfo) const {
5133 // Literal constants use the constant bus.
5134 if (!MO.isReg())
5135 return !isInlineConstant(MO, OpInfo);
5136
5137 Register Reg = MO.getReg();
5138 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5140}
5141
5143 for (const MachineOperand &MO : MI.implicit_operands()) {
5144 // We only care about reads.
5145 if (MO.isDef())
5146 continue;
5147
5148 switch (MO.getReg()) {
5149 case AMDGPU::VCC:
5150 case AMDGPU::VCC_LO:
5151 case AMDGPU::VCC_HI:
5152 case AMDGPU::M0:
5153 case AMDGPU::FLAT_SCR:
5154 return MO.getReg();
5155
5156 default:
5157 break;
5158 }
5159 }
5160
5161 return Register();
5162}
5163
5164static bool shouldReadExec(const MachineInstr &MI) {
5165 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5166 switch (MI.getOpcode()) {
5167 case AMDGPU::V_READLANE_B32:
5168 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5169 case AMDGPU::V_WRITELANE_B32:
5170 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5171 return false;
5172 }
5173
5174 return true;
5175 }
5176
5177 if (MI.isPreISelOpcode() ||
5178 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5181 return false;
5182
5183 return true;
5184}
5185
5186static bool isRegOrFI(const MachineOperand &MO) {
5187 return MO.isReg() || MO.isFI();
5188}
5189
5190static bool isSubRegOf(const SIRegisterInfo &TRI,
5191 const MachineOperand &SuperVec,
5192 const MachineOperand &SubReg) {
5193 if (SubReg.getReg().isPhysical())
5194 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5195
5196 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5197 SubReg.getReg() == SuperVec.getReg();
5198}
5199
5200// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5201bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5202 const MachineRegisterInfo &MRI,
5203 StringRef &ErrInfo) const {
5204 Register DstReg = MI.getOperand(0).getReg();
5205 Register SrcReg = MI.getOperand(1).getReg();
5206 // This is a check for copy from vector register to SGPR
5207 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5208 ErrInfo = "illegal copy from vector register to SGPR";
5209 return false;
5210 }
5211 return true;
5212}
5213
5215 StringRef &ErrInfo) const {
5216 uint32_t Opcode = MI.getOpcode();
5217 const MachineFunction *MF = MI.getMF();
5218 const MachineRegisterInfo &MRI = MF->getRegInfo();
5219
5220 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5221 // Find a better property to recognize the point where instruction selection
5222 // is just done.
5223 // We can only enforce this check after SIFixSGPRCopies pass so that the
5224 // illegal copies are legalized and thereafter we don't expect a pass
5225 // inserting similar copies.
5226 if (!MRI.isSSA() && MI.isCopy())
5227 return verifyCopy(MI, MRI, ErrInfo);
5228
5229 if (SIInstrInfo::isGenericOpcode(Opcode))
5230 return true;
5231
5232 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5233 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5234 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5235 int Src3Idx = -1;
5236 if (Src0Idx == -1) {
5237 // VOPD V_DUAL_* instructions use different operand names.
5238 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5239 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5240 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5241 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5242 }
5243
5244 // Make sure the number of operands is correct.
5245 const MCInstrDesc &Desc = get(Opcode);
5246 if (!Desc.isVariadic() &&
5247 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5248 ErrInfo = "Instruction has wrong number of operands.";
5249 return false;
5250 }
5251
5252 if (MI.isInlineAsm()) {
5253 // Verify register classes for inlineasm constraints.
5254 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5255 I != E; ++I) {
5256 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5257 if (!RC)
5258 continue;
5259
5260 const MachineOperand &Op = MI.getOperand(I);
5261 if (!Op.isReg())
5262 continue;
5263
5264 Register Reg = Op.getReg();
5265 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5266 ErrInfo = "inlineasm operand has incorrect register class.";
5267 return false;
5268 }
5269 }
5270
5271 return true;
5272 }
5273
5274 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5275 ErrInfo = "missing memory operand from image instruction.";
5276 return false;
5277 }
5278
5279 // Make sure the register classes are correct.
5280 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5281 const MachineOperand &MO = MI.getOperand(i);
5282 if (MO.isFPImm()) {
5283 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5284 "all fp values to integers.";
5285 return false;
5286 }
5287
5288 const MCOperandInfo &OpInfo = Desc.operands()[i];
5289 int16_t RegClass = getOpRegClassID(OpInfo);
5290
5291 switch (OpInfo.OperandType) {
5293 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5294 ErrInfo = "Illegal immediate value for operand.";
5295 return false;
5296 }
5297 break;
5309 break;
5311 break;
5312 break;
5326 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5327 ErrInfo = "Illegal immediate value for operand.";
5328 return false;
5329 }
5330 break;
5331 }
5336 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5337 !isInlineConstant(MI, i) &&
5339 OpInfo.OperandType ==
5341 ErrInfo = "illegal 64-bit immediate value for operand.";
5342 return false;
5343 }
5344 break;
5347 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5348 ErrInfo = "Expected inline constant for operand.";
5349 return false;
5350 }
5351 break;
5354 break;
5359 // Check if this operand is an immediate.
5360 // FrameIndex operands will be replaced by immediates, so they are
5361 // allowed.
5362 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5363 ErrInfo = "Expected immediate, but got non-immediate";
5364 return false;
5365 }
5366 break;
5370 break;
5371 default:
5372 if (OpInfo.isGenericType())
5373 continue;
5374 break;
5375 }
5376
5377 if (!MO.isReg())
5378 continue;
5379 Register Reg = MO.getReg();
5380 if (!Reg)
5381 continue;
5382
5383 // FIXME: Ideally we would have separate instruction definitions with the
5384 // aligned register constraint.
5385 // FIXME: We do not verify inline asm operands, but custom inline asm
5386 // verification is broken anyway
5387 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5388 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !isSpill(MI)) {
5389 const TargetRegisterClass *RC = RI.getRegClassForReg(MRI, Reg);
5390 if (RI.hasVectorRegisters(RC) && MO.getSubReg()) {
5391 if (const TargetRegisterClass *SubRC =
5392 RI.getSubRegisterClass(RC, MO.getSubReg())) {
5393 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.getSubReg());
5394 if (RC)
5395 RC = SubRC;
5396 }
5397 }
5398
5399 // Check that this is the aligned version of the class.
5400 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5401 ErrInfo = "Subtarget requires even aligned vector registers";
5402 return false;
5403 }
5404 }
5405
5406 if (RegClass != -1) {
5407 if (Reg.isVirtual())
5408 continue;
5409
5410 const TargetRegisterClass *RC = RI.getRegClass(RegClass);
5411 if (!RC->contains(Reg)) {
5412 ErrInfo = "Operand has incorrect register class.";
5413 return false;
5414 }
5415 }
5416 }
5417
5418 // Verify SDWA
5419 if (isSDWA(MI)) {
5420 if (!ST.hasSDWA()) {
5421 ErrInfo = "SDWA is not supported on this target";
5422 return false;
5423 }
5424
5425 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5426 AMDGPU::OpName::dst_sel}) {
5427 const MachineOperand *MO = getNamedOperand(MI, Op);
5428 if (!MO)
5429 continue;
5430 int64_t Imm = MO->getImm();
5431 if (Imm < 0 || Imm > AMDGPU::SDWA::SdwaSel::DWORD) {
5432 ErrInfo = "Invalid SDWA selection";
5433 return false;
5434 }
5435 }
5436
5437 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5438
5439 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5440 if (OpIdx == -1)
5441 continue;
5442 const MachineOperand &MO = MI.getOperand(OpIdx);
5443
5444 if (!ST.hasSDWAScalar()) {
5445 // Only VGPRS on VI
5446 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5447 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5448 return false;
5449 }
5450 } else {
5451 // No immediates on GFX9
5452 if (!MO.isReg()) {
5453 ErrInfo =
5454 "Only reg allowed as operands in SDWA instructions on GFX9+";
5455 return false;
5456 }
5457 }
5458 }
5459
5460 if (!ST.hasSDWAOmod()) {
5461 // No omod allowed on VI
5462 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5463 if (OMod != nullptr &&
5464 (!OMod->isImm() || OMod->getImm() != 0)) {
5465 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5466 return false;
5467 }
5468 }
5469
5470 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5471 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5472 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5473 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5474 const MachineOperand *Src0ModsMO =
5475 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5476 unsigned Mods = Src0ModsMO->getImm();
5477 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5478 Mods & SISrcMods::SEXT) {
5479 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5480 return false;
5481 }
5482 }
5483
5484 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5485 if (isVOPC(BasicOpcode)) {
5486 if (!ST.hasSDWASdst() && DstIdx != -1) {
5487 // Only vcc allowed as dst on VI for VOPC
5488 const MachineOperand &Dst = MI.getOperand(DstIdx);
5489 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5490 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5491 return false;
5492 }
5493 } else if (!ST.hasSDWAOutModsVOPC()) {
5494 // No clamp allowed on GFX9 for VOPC
5495 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5496 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5497 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5498 return false;
5499 }
5500
5501 // No omod allowed on GFX9 for VOPC
5502 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5503 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5504 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5505 return false;
5506 }
5507 }
5508 }
5509
5510 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5511 if (DstUnused && DstUnused->isImm() &&
5512 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5513 const MachineOperand &Dst = MI.getOperand(DstIdx);
5514 if (!Dst.isReg() || !Dst.isTied()) {
5515 ErrInfo = "Dst register should have tied register";
5516 return false;
5517 }
5518
5519 const MachineOperand &TiedMO =
5520 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5521 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5522 ErrInfo =
5523 "Dst register should be tied to implicit use of preserved register";
5524 return false;
5525 }
5526 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5527 ErrInfo = "Dst register should use same physical register as preserved";
5528 return false;
5529 }
5530 }
5531 }
5532
5533 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5534 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5535 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5536 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5537 return false;
5538 }
5539 if (Src1MO.isImm()) {
5540 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5541 return false;
5542 }
5543 }
5544
5545 // Verify MIMG / VIMAGE / VSAMPLE
5546 if (isImage(Opcode) && !MI.mayStore()) {
5547 // Ensure that the return type used is large enough for all the options
5548 // being used TFE/LWE require an extra result register.
5549 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5550 if (DMask) {
5551 uint64_t DMaskImm = DMask->getImm();
5552 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5553 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5554 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5555 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5556
5557 // Adjust for packed 16 bit values
5558 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5559 RegCount = divideCeil(RegCount, 2);
5560
5561 // Adjust if using LWE or TFE
5562 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5563 RegCount += 1;
5564
5565 const uint32_t DstIdx =
5566 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5567 const MachineOperand &Dst = MI.getOperand(DstIdx);
5568 if (Dst.isReg()) {
5569 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5570 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5571 if (RegCount > DstSize) {
5572 ErrInfo = "Image instruction returns too many registers for dst "
5573 "register class";
5574 return false;
5575 }
5576 }
5577 }
5578 }
5579
5580 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5581 if (isVALU(MI, /*AllowLDSDMA=*/true) &&
5582 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5583 unsigned ConstantBusCount = 0;
5584 bool UsesLiteral = false;
5585 const MachineOperand *LiteralVal = nullptr;
5586
5587 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5588 if (ImmIdx != -1) {
5589 ++ConstantBusCount;
5590 UsesLiteral = true;
5591 LiteralVal = &MI.getOperand(ImmIdx);
5592 }
5593
5594 SmallVector<Register, 2> SGPRsUsed;
5595 Register SGPRUsed;
5596
5597 // Only look at the true operands. Only a real operand can use the constant
5598 // bus, and we don't want to check pseudo-operands like the source modifier
5599 // flags.
5600 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5601 if (OpIdx == -1)
5602 continue;
5603 const MachineOperand &MO = MI.getOperand(OpIdx);
5604 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5605 if (MO.isReg()) {
5606 SGPRUsed = MO.getReg();
5607 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5608 ++ConstantBusCount;
5609 SGPRsUsed.push_back(SGPRUsed);
5610 }
5611 } else if (!MO.isFI()) { // Treat FI like a register.
5612 if (!UsesLiteral) {
5613 ++ConstantBusCount;
5614 UsesLiteral = true;
5615 LiteralVal = &MO;
5616 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5617 assert(isVOP2(MI) || isVOP3(MI));
5618 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5619 return false;
5620 }
5621 }
5622 }
5623 }
5624
5625 SGPRUsed = findImplicitSGPRRead(MI);
5626 if (SGPRUsed) {
5627 // Implicit uses may safely overlap true operands
5628 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5629 return !RI.regsOverlap(SGPRUsed, SGPR);
5630 })) {
5631 ++ConstantBusCount;
5632 SGPRsUsed.push_back(SGPRUsed);
5633 }
5634 }
5635
5636 // v_writelane_b32 is an exception from constant bus restriction:
5637 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5638 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5639 Opcode != AMDGPU::V_WRITELANE_B32) {
5640 ErrInfo = "VOP* instruction violates constant bus restriction";
5641 return false;
5642 }
5643
5644 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5645 ErrInfo = "VOP3 instruction uses literal";
5646 return false;
5647 }
5648 }
5649
5650 // Special case for writelane - this can break the multiple constant bus rule,
5651 // but still can't use more than one SGPR register
5652 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5653 unsigned SGPRCount = 0;
5654 Register SGPRUsed;
5655
5656 for (int OpIdx : {Src0Idx, Src1Idx}) {
5657 if (OpIdx == -1)
5658 break;
5659
5660 const MachineOperand &MO = MI.getOperand(OpIdx);
5661
5662 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5663 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5664 if (MO.getReg() != SGPRUsed)
5665 ++SGPRCount;
5666 SGPRUsed = MO.getReg();
5667 }
5668 }
5669 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5670 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5671 return false;
5672 }
5673 }
5674 }
5675
5676 // Verify misc. restrictions on specific instructions.
5677 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5678 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5679 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5680 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5681 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
5682 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5683 if (!compareMachineOp(Src0, Src1) &&
5684 !compareMachineOp(Src0, Src2)) {
5685 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
5686 return false;
5687 }
5688 }
5689 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
5690 SISrcMods::ABS) ||
5691 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
5692 SISrcMods::ABS) ||
5693 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
5694 SISrcMods::ABS)) {
5695 ErrInfo = "ABS not allowed in VOP3B instructions";
5696 return false;
5697 }
5698 }
5699
5700 if (isSOP2(MI) || isSOPC(MI)) {
5701 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5702 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5703
5704 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
5705 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
5706 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
5707 !Src0.isIdenticalTo(Src1)) {
5708 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
5709 return false;
5710 }
5711 }
5712
5713 if (isSOPK(MI)) {
5714 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
5715 if (Desc.isBranch()) {
5716 if (!Op->isMBB()) {
5717 ErrInfo = "invalid branch target for SOPK instruction";
5718 return false;
5719 }
5720 } else {
5721 uint64_t Imm = Op->getImm();
5722 if (sopkIsZext(Opcode)) {
5723 if (!isUInt<16>(Imm)) {
5724 ErrInfo = "invalid immediate for SOPK instruction";
5725 return false;
5726 }
5727 } else {
5728 if (!isInt<16>(Imm)) {
5729 ErrInfo = "invalid immediate for SOPK instruction";
5730 return false;
5731 }
5732 }
5733 }
5734 }
5735
5736 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5737 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5738 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5739 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5740 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5741 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5742
5743 const unsigned StaticNumOps =
5744 Desc.getNumOperands() + Desc.implicit_uses().size();
5745 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5746
5747 // Require additional implicit operands. This allows a fixup done by the
5748 // post RA scheduler where the main implicit operand is killed and
5749 // implicit-defs are added for sub-registers that remain live after this
5750 // instruction.
5751 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5752 ErrInfo = "missing implicit register operands";
5753 return false;
5754 }
5755
5756 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5757 if (IsDst) {
5758 if (!Dst->isUse()) {
5759 ErrInfo = "v_movreld_b32 vdst should be a use operand";
5760 return false;
5761 }
5762
5763 unsigned UseOpIdx;
5764 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5765 UseOpIdx != StaticNumOps + 1) {
5766 ErrInfo = "movrel implicit operands should be tied";
5767 return false;
5768 }
5769 }
5770
5771 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5772 const MachineOperand &ImpUse
5773 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5774 if (!ImpUse.isReg() || !ImpUse.isUse() ||
5775 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5776 ErrInfo = "src0 should be subreg of implicit vector use";
5777 return false;
5778 }
5779 }
5780
5781 // Make sure we aren't losing exec uses in the td files. This mostly requires
5782 // being careful when using let Uses to try to add other use registers.
5783 if (shouldReadExec(MI)) {
5784 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5785 ErrInfo = "VALU instruction does not implicitly read exec mask";
5786 return false;
5787 }
5788 }
5789
5790 if (isSMRD(MI)) {
5791 if (MI.mayStore() &&
5792 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
5793 // The register offset form of scalar stores may only use m0 as the
5794 // soffset register.
5795 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
5796 if (Soff && Soff->getReg() != AMDGPU::M0) {
5797 ErrInfo = "scalar stores must use m0 as offset register";
5798 return false;
5799 }
5800 }
5801 }
5802
5803 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
5804 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
5805 if (Offset->getImm() != 0) {
5806 ErrInfo = "subtarget does not support offsets in flat instructions";
5807 return false;
5808 }
5809 }
5810
5811 if (isDS(MI) && !ST.hasGDS()) {
5812 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
5813 if (GDSOp && GDSOp->getImm() != 0) {
5814 ErrInfo = "GDS is not supported on this subtarget";
5815 return false;
5816 }
5817 }
5818
5819 if (isImage(MI)) {
5820 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
5821 if (DimOp) {
5822 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5823 AMDGPU::OpName::vaddr0);
5824 AMDGPU::OpName RSrcOpName =
5825 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5826 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5827 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
5828 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
5829 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
5830 const AMDGPU::MIMGDimInfo *Dim =
5832
5833 if (!Dim) {
5834 ErrInfo = "dim is out of range";
5835 return false;
5836 }
5837
5838 bool IsA16 = false;
5839 if (ST.hasR128A16()) {
5840 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
5841 IsA16 = R128A16->getImm() != 0;
5842 } else if (ST.hasA16()) {
5843 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
5844 IsA16 = A16->getImm() != 0;
5845 }
5846
5847 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5848
5849 unsigned AddrWords =
5850 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
5851
5852 unsigned VAddrWords;
5853 if (IsNSA) {
5854 VAddrWords = RsrcIdx - VAddr0Idx;
5855 if (ST.hasPartialNSAEncoding() &&
5856 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
5857 unsigned LastVAddrIdx = RsrcIdx - 1;
5858 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
5859 }
5860 } else {
5861 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
5862 if (AddrWords > 12)
5863 AddrWords = 16;
5864 }
5865
5866 if (VAddrWords != AddrWords) {
5867 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
5868 << " but got " << VAddrWords << "\n");
5869 ErrInfo = "bad vaddr size";
5870 return false;
5871 }
5872 }
5873 }
5874
5875 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
5876 if (DppCt) {
5877 using namespace AMDGPU::DPP;
5878
5879 unsigned DC = DppCt->getImm();
5880 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5881 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5882 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5883 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5884 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5885 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5886 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5887 ErrInfo = "Invalid dpp_ctrl value";
5888 return false;
5889 }
5890 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5891 !ST.hasDPPWavefrontShifts()) {
5892 ErrInfo = "Invalid dpp_ctrl value: "
5893 "wavefront shifts are not supported on GFX10+";
5894 return false;
5895 }
5896 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5897 !ST.hasDPPBroadcasts()) {
5898 ErrInfo = "Invalid dpp_ctrl value: "
5899 "broadcasts are not supported on GFX10+";
5900 return false;
5901 }
5902 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
5903 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
5904 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
5905 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
5906 !ST.hasGFX90AInsts()) {
5907 ErrInfo = "Invalid dpp_ctrl value: "
5908 "row_newbroadcast/row_share is not supported before "
5909 "GFX90A/GFX10";
5910 return false;
5911 }
5912 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
5913 ErrInfo = "Invalid dpp_ctrl value: "
5914 "row_share and row_xmask are not supported before GFX10";
5915 return false;
5916 }
5917 }
5918
5919 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
5921 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
5922 ErrInfo = "Invalid dpp_ctrl value: "
5923 "DP ALU dpp only support row_newbcast";
5924 return false;
5925 }
5926 }
5927
5928 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
5929 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5930 AMDGPU::OpName DataName =
5931 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
5932 const MachineOperand *Data = getNamedOperand(MI, DataName);
5933 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
5934 if (Data && !Data->isReg())
5935 Data = nullptr;
5936
5937 if (!ST.hasGFX90AInsts()) {
5938 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
5939 (Data && RI.isAGPR(MRI, Data->getReg())) ||
5940 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
5941 ErrInfo = "Invalid register class: "
5942 "agpr loads and stores not supported on this GPU";
5943 return false;
5944 }
5945 }
5946 }
5947
5948 if (ST.needsAlignedVGPRs()) {
5949 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
5951 if (!Op)
5952 return true;
5953 Register Reg = Op->getReg();
5954 if (Reg.isPhysical())
5955 return !(RI.getHWRegIndex(Reg) & 1);
5956 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
5957 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
5958 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
5959 };
5960
5961 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
5962 Opcode == AMDGPU::DS_GWS_BARRIER) {
5963
5964 if (!isAlignedReg(AMDGPU::OpName::data0)) {
5965 ErrInfo = "Subtarget requires even aligned vector registers "
5966 "for DS_GWS instructions";
5967 return false;
5968 }
5969 }
5970
5971 if (isMIMG(MI)) {
5972 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
5973 ErrInfo = "Subtarget requires even aligned vector registers "
5974 "for vaddr operand of image instructions";
5975 return false;
5976 }
5977 }
5978 }
5979
5980 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
5981 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
5982 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
5983 ErrInfo = "Invalid register class: "
5984 "v_accvgpr_write with an SGPR is not supported on this GPU";
5985 return false;
5986 }
5987 }
5988
5989 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
5990 const MachineOperand &SrcOp = MI.getOperand(1);
5991 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
5992 ErrInfo = "pseudo expects only physical SGPRs";
5993 return false;
5994 }
5995 }
5996
5997 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
5998 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
5999 if (!ST.hasScaleOffset()) {
6000 ErrInfo = "Subtarget does not support offset scaling";
6001 return false;
6002 }
6003 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
6004 ErrInfo = "Instruction does not support offset scaling";
6005 return false;
6006 }
6007 }
6008 }
6009
6010 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6011 if (AMDGPU::isSingleSGPRReadInst(Opcode)) {
6012 for (unsigned I = 0; I < 3; ++I) {
6014 return false;
6015 }
6016 }
6017
6018 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
6019 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
6020 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
6021 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6022 &AMDGPU::SReg_64RegClass) ||
6023 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6024 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
6025 return false;
6026 }
6027 }
6028
6029 return true;
6030}
6031
6033 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
6034 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6035 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
6036 ? AMDGPU::COPY
6037 : AMDGPU::V_MOV_B32_e32;
6038 }
6039 return getVALUOp(MI.getOpcode());
6040}
6041
6042// It is more readable to list mapped opcodes on the same line.
6043// clang-format off
6044
6045unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
6046 switch (Opc) {
6047 default: return AMDGPU::INSTRUCTION_LIST_END;
6048 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
6049 case AMDGPU::COPY: return AMDGPU::COPY;
6050 case AMDGPU::PHI: return AMDGPU::PHI;
6051 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
6052 case AMDGPU::WQM: return AMDGPU::WQM;
6053 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
6054 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
6055 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
6056 case AMDGPU::S_ADD_I32:
6057 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6058 case AMDGPU::S_ADDC_U32:
6059 return AMDGPU::V_ADDC_U32_e32;
6060 case AMDGPU::S_SUB_I32:
6061 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6062 // FIXME: These are not consistently handled, and selected when the carry is
6063 // used.
6064 case AMDGPU::S_ADD_U32:
6065 return AMDGPU::V_ADD_CO_U32_e32;
6066 case AMDGPU::S_SUB_U32:
6067 return AMDGPU::V_SUB_CO_U32_e32;
6068 case AMDGPU::S_ADD_U64_PSEUDO:
6069 return AMDGPU::V_ADD_U64_PSEUDO;
6070 case AMDGPU::S_SUB_U64_PSEUDO:
6071 return AMDGPU::V_SUB_U64_PSEUDO;
6072 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
6073 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
6074 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
6075 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
6076 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
6077 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
6078 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
6079 case AMDGPU::S_XNOR_B32:
6080 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6081 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
6082 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
6083 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
6084 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
6085 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
6086 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
6087 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
6088 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
6089 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
6090 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
6091 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
6092 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
6093 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
6094 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
6095 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
6096 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
6097 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
6098 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
6099 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
6100 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
6101 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
6102 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
6103 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
6104 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
6105 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
6106 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
6107 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
6108 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
6109 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
6110 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
6111 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
6112 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
6113 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
6114 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
6115 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
6116 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
6117 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
6118 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
6119 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
6120 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
6121 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
6122 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
6123 case AMDGPU::S_CVT_F32_F16:
6124 case AMDGPU::S_CVT_HI_F32_F16:
6125 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6126 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6127 case AMDGPU::S_CVT_F16_F32:
6128 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6129 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6130 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
6131 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
6132 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
6133 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
6134 case AMDGPU::S_CEIL_F16:
6135 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6136 : AMDGPU::V_CEIL_F16_fake16_e64;
6137 case AMDGPU::S_FLOOR_F16:
6138 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6139 : AMDGPU::V_FLOOR_F16_fake16_e64;
6140 case AMDGPU::S_TRUNC_F16:
6141 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6142 : AMDGPU::V_TRUNC_F16_fake16_e64;
6143 case AMDGPU::S_RNDNE_F16:
6144 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6145 : AMDGPU::V_RNDNE_F16_fake16_e64;
6146 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6147 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6148 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6149 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6150 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6151 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6152 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6153 case AMDGPU::S_ADD_F16:
6154 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6155 : AMDGPU::V_ADD_F16_fake16_e64;
6156 case AMDGPU::S_SUB_F16:
6157 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6158 : AMDGPU::V_SUB_F16_fake16_e64;
6159 case AMDGPU::S_MIN_F16:
6160 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6161 : AMDGPU::V_MIN_F16_fake16_e64;
6162 case AMDGPU::S_MAX_F16:
6163 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6164 : AMDGPU::V_MAX_F16_fake16_e64;
6165 case AMDGPU::S_MINIMUM_F16:
6166 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6167 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6168 case AMDGPU::S_MAXIMUM_F16:
6169 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6170 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6171 case AMDGPU::S_MUL_F16:
6172 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6173 : AMDGPU::V_MUL_F16_fake16_e64;
6174 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6175 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6176 case AMDGPU::S_FMAC_F16:
6177 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6178 : AMDGPU::V_FMAC_F16_fake16_e64;
6179 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6180 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6181 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6182 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6183 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6184 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6185 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6186 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6187 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6188 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6189 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6190 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6191 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6192 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6193 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6194 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6195 case AMDGPU::S_CMP_LT_F16:
6196 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6197 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6198 case AMDGPU::S_CMP_EQ_F16:
6199 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6200 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6201 case AMDGPU::S_CMP_LE_F16:
6202 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6203 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6204 case AMDGPU::S_CMP_GT_F16:
6205 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6206 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6207 case AMDGPU::S_CMP_LG_F16:
6208 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6209 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6210 case AMDGPU::S_CMP_GE_F16:
6211 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6212 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6213 case AMDGPU::S_CMP_O_F16:
6214 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6215 : AMDGPU::V_CMP_O_F16_fake16_e64;
6216 case AMDGPU::S_CMP_U_F16:
6217 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6218 : AMDGPU::V_CMP_U_F16_fake16_e64;
6219 case AMDGPU::S_CMP_NGE_F16:
6220 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6221 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6222 case AMDGPU::S_CMP_NLG_F16:
6223 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6224 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6225 case AMDGPU::S_CMP_NGT_F16:
6226 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6227 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6228 case AMDGPU::S_CMP_NLE_F16:
6229 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6230 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6231 case AMDGPU::S_CMP_NEQ_F16:
6232 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6233 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6234 case AMDGPU::S_CMP_NLT_F16:
6235 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6236 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6237 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6238 case AMDGPU::V_S_EXP_F16_e64:
6239 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6240 : AMDGPU::V_EXP_F16_fake16_e64;
6241 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6242 case AMDGPU::V_S_LOG_F16_e64:
6243 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6244 : AMDGPU::V_LOG_F16_fake16_e64;
6245 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6246 case AMDGPU::V_S_RCP_F16_e64:
6247 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6248 : AMDGPU::V_RCP_F16_fake16_e64;
6249 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6250 case AMDGPU::V_S_RSQ_F16_e64:
6251 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6252 : AMDGPU::V_RSQ_F16_fake16_e64;
6253 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6254 case AMDGPU::V_S_SQRT_F16_e64:
6255 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6256 : AMDGPU::V_SQRT_F16_fake16_e64;
6257 }
6259 "Unexpected scalar opcode without corresponding vector one!");
6260}
6261
6262// clang-format on
6263
6267 const DebugLoc &DL, Register Reg,
6268 bool IsSCCLive,
6269 SlotIndexes *Indexes) const {
6270 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6271 const SIInstrInfo *TII = ST.getInstrInfo();
6273 if (IsSCCLive) {
6274 // Insert two move instructions, one to save the original value of EXEC and
6275 // the other to turn on all bits in EXEC. This is required as we can't use
6276 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6277 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6279 auto FlipExecMI =
6280 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6281 if (Indexes) {
6282 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6283 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6284 }
6285 } else {
6286 auto SaveExec =
6287 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6288 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6289 if (Indexes)
6290 Indexes->insertMachineInstrInMaps(*SaveExec);
6291 }
6292}
6293
6296 const DebugLoc &DL, Register Reg,
6297 SlotIndexes *Indexes) const {
6299 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6300 .addReg(Reg, RegState::Kill);
6301 if (Indexes)
6302 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6303}
6304
6308 "Not a whole wave func");
6309 MachineBasicBlock &MBB = *MF.begin();
6310 for (MachineInstr &MI : MBB)
6311 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6312 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6313 return &MI;
6314
6315 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6316}
6317
6319 unsigned OpNo) const {
6320 const MCInstrDesc &Desc = get(MI.getOpcode());
6321 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6322 Desc.operands()[OpNo].RegClass == -1) {
6323 Register Reg = MI.getOperand(OpNo).getReg();
6324
6325 if (Reg.isVirtual()) {
6326 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6327 return MRI.getRegClass(Reg);
6328 }
6329 return RI.getPhysRegBaseClass(Reg);
6330 }
6331
6332 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6333 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6334}
6335
6336// Convert VOP3 operand index to source number.
6337static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx) {
6338 constexpr AMDGPU::OpName OpNames[] = {
6339 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6340
6341 for (auto [I, OpName] : enumerate(OpNames)) {
6342 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6343 if (static_cast<unsigned>(SrcIdx) == OpIdx)
6344 return I;
6345 }
6346
6347 return UINT_MAX;
6348}
6349
6352 MachineBasicBlock *MBB = MI.getParent();
6353 MachineOperand &MO = MI.getOperand(OpIdx);
6354 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6355 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6356 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6357 unsigned Size = RI.getRegSizeInBits(*RC);
6358 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6359 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6360 : AMDGPU::V_MOV_B32_e32;
6361 if (MO.isReg())
6362 Opcode = AMDGPU::COPY;
6363 else if (RI.isSGPRClass(RC))
6364 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6365
6366 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6367 Register Reg = MRI.createVirtualRegister(VRC);
6368 DebugLoc DL = MBB->findDebugLoc(I);
6369
6370 if (Size == 128 && AMDGPU::isPackedSingleSGPR64BitInst(MI.getOpcode()) &&
6372 // Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
6373 // sources behave like OPSEL is set replicating low 64-bits into high. VGPR
6374 // sources in turn read actual 4 registers. To move operand from an SGPR to
6375 // a VGPR we need to replicate low half.
6376 // We also do not select immediates for these instructions so it always has
6377 // to be an SGPR register here.
6378 // Operands which are not legal as per isLegalSingleSGPRReadInstOperand()
6379 // sent here specifically to fix a non-splat SGPR and shall perform a full
6380 // copy.
6381
6382 const TargetRegisterClass *VRC64 = RI.getVGPRClassForBitWidth(64);
6383 Register Low64 = MRI.createVirtualRegister(VRC64);
6384 assert(MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()));
6385 BuildMI(*MBB, I, DL, get(TargetOpcode::COPY), Low64)
6386 .addReg(MO.getReg(), {}, AMDGPU::sub0_sub1);
6387 BuildMI(*MBB, I, DL, get(TargetOpcode::REG_SEQUENCE), Reg)
6388 .addReg(Low64)
6389 .addImm(AMDGPU::sub0_sub1)
6390 .addReg(Low64, RegState::Kill)
6391 .addImm(AMDGPU::sub2_sub3);
6392 } else {
6393 BuildMI(*MBB, I, DL, get(Opcode), Reg).add(MO);
6394 }
6395
6396 MO.ChangeToRegister(Reg, false);
6397}
6398
6401 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6402 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6403 if (!SuperReg.getReg().isVirtual())
6404 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6405
6406 MachineBasicBlock *MBB = MI->getParent();
6407 const DebugLoc &DL = MI->getDebugLoc();
6408 Register SubReg = MRI.createVirtualRegister(SubRC);
6409
6410 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6411 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6412 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6413 return SubReg;
6414}
6415
6418 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6419 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6420 if (Op.isImm()) {
6421 if (SubIdx == AMDGPU::sub0)
6422 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6423 if (SubIdx == AMDGPU::sub1)
6424 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6425
6426 llvm_unreachable("Unhandled register index for immediate");
6427 }
6428
6429 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6430 SubIdx, SubRC);
6431 return MachineOperand::CreateReg(SubReg, false);
6432}
6433
6434// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6435void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6436 assert(Inst.getNumExplicitOperands() == 3);
6437 MachineOperand Op1 = Inst.getOperand(1);
6438 Inst.removeOperand(1);
6439 Inst.addOperand(Op1);
6440}
6441
6443 const MCOperandInfo &OpInfo,
6444 const MachineOperand &MO) const {
6445 if (!MO.isReg())
6446 return false;
6447
6448 Register Reg = MO.getReg();
6449
6450 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6451 if (Reg.isPhysical())
6452 return DRC->contains(Reg);
6453
6454 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6455
6456 if (MO.getSubReg()) {
6457 const MachineFunction *MF = MO.getParent()->getMF();
6458 const TargetRegisterClass *SuperRC = RI.getLargestLegalSuperClass(RC, *MF);
6459 if (!SuperRC)
6460 return false;
6461 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6462 }
6463
6464 return RI.getCommonSubClass(DRC, RC) != nullptr;
6465}
6466
6468 const MachineOperand &MO) const {
6469 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6470 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6471 unsigned Opc = MI.getOpcode();
6472
6473 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6474 if (MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
6475 AMDGPU::isSingleSGPRReadInst(MI.getOpcode()) &&
6477 &MO))
6478 return false;
6479
6480 if (!isLegalRegOperand(MRI, OpInfo, MO))
6481 return false;
6482
6483 // check Accumulate GPR operand
6484 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6485 if (IsAGPR && !ST.hasMAIInsts())
6486 return false;
6487 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6488 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6489 return false;
6490 // Atomics should have both vdst and vdata either vgpr or agpr.
6491 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6492 const int DataIdx = AMDGPU::getNamedOperandIdx(
6493 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6494 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6495 MI.getOperand(DataIdx).isReg() &&
6496 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6497 return false;
6498 if ((int)OpIdx == DataIdx) {
6499 if (VDstIdx != -1 &&
6500 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6501 return false;
6502 // DS instructions with 2 src operands also must have tied RC.
6503 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6504 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6505 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6506 return false;
6507 }
6508
6509 // Check V_ACCVGPR_WRITE_B32_e64
6510 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6511 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6512 RI.isSGPRReg(MRI, MO.getReg()))
6513 return false;
6514
6515 if (ST.hasFlatScratchHiInB64InstHazard() &&
6516 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6517 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6518 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6519 64)
6520 return false;
6521 }
6522 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6523 return false;
6524 }
6525 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6526 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6527 return false;
6528
6529 return true;
6530}
6531
6533 const MCOperandInfo &OpInfo,
6534 const MachineOperand &MO) const {
6535 if (MO.isReg())
6536 return isLegalRegOperand(MRI, OpInfo, MO);
6537
6538 // Handle non-register types that are treated like immediates.
6539 assert(MO.isImm() || MO.isTargetIndex() || MO.isFI() || MO.isGlobal());
6540 return true;
6541}
6542
6544 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6545 const MachineOperand *MO) const {
6546 constexpr unsigned NumOps = 3;
6547 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6548 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6549 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6550 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6551
6552 assert(SrcN < NumOps);
6553
6554 if (!MO) {
6555 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6556 if (SrcIdx == -1)
6557 return true;
6558 MO = &MI.getOperand(SrcIdx);
6559 }
6560
6561 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6562 return true;
6563
6564 int ModsIdx =
6565 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6566 if (ModsIdx == -1)
6567 return false;
6568
6569 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6570 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6571 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6572
6573 return !OpSel && !OpSelHi;
6574}
6575
6576bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
6577 const MachineOperand *MO) const {
6578 const MachineFunction &MF = *MI.getMF();
6579 const MachineRegisterInfo &MRI = MF.getRegInfo();
6580 const MCInstrDesc &InstDesc = MI.getDesc();
6581 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6582 int64_t RegClass = getOpRegClassID(OpInfo);
6583 const TargetRegisterClass *DefinedRC =
6584 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6585 if (!MO)
6586 MO = &MI.getOperand(OpIdx);
6587
6588 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6589
6590 if (isVALU(MI, /*AllowLDSDMA=*/true) && !IsInlineConst &&
6591 usesConstantBus(MRI, *MO, OpInfo)) {
6592 const MachineOperand *UsedLiteral = nullptr;
6593
6594 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6595 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6596
6597 // TODO: Be more permissive with frame indexes.
6598 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6599 if (!LiteralLimit--)
6600 return false;
6601
6602 UsedLiteral = MO;
6603 }
6604
6606 if (MO->isReg())
6607 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6608
6609 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6610 if (i == OpIdx)
6611 continue;
6612 const MachineOperand &Op = MI.getOperand(i);
6613 if (Op.isReg()) {
6614 if (Op.isUse()) {
6615 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6616 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6617 if (--ConstantBusLimit <= 0)
6618 return false;
6619 }
6620 }
6621 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6622 !isInlineConstant(Op, InstDesc.operands()[i])) {
6623 // The same literal may be used multiple times.
6624 if (!UsedLiteral)
6625 UsedLiteral = &Op;
6626 else if (UsedLiteral->isIdenticalTo(Op))
6627 continue;
6628
6629 if (!LiteralLimit--)
6630 return false;
6631 if (--ConstantBusLimit <= 0)
6632 return false;
6633 }
6634 }
6635 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6636 // There can be at most one literal operand, but it can be repeated.
6637 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6638 if (i == OpIdx)
6639 continue;
6640 const MachineOperand &Op = MI.getOperand(i);
6641 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6642 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6643 !Op.isIdenticalTo(*MO))
6644 return false;
6645
6646 // Do not fold a non-inlineable and non-register operand into an
6647 // instruction that already has a frame index. The frame index handling
6648 // code could not handle well when a frame index co-exists with another
6649 // non-register operand, unless that operand is an inlineable immediate.
6650 if (Op.isFI())
6651 return false;
6652 }
6653 } else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6654 isF16PseudoScalarTrans(MI.getOpcode())) {
6655 return false;
6656 }
6657
6658 if (MO->isReg()) {
6659 if (!DefinedRC)
6660 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6661 return isLegalRegOperand(MI, OpIdx, *MO);
6662 }
6663
6664 if (MO->isImm()) {
6665 uint64_t Imm = MO->getImm();
6666 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6667 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6668 bool Is64BitOp = Is64BitFPOp ||
6669 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6670 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6671 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6672 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6673 if (Is64BitOp &&
6674 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6675 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6676 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6677 return false;
6678
6679 // FIXME: We can use sign extended 64-bit literals, but only for signed
6680 // operands. At the moment we do not know if an operand is signed.
6681 // Such operand will be encoded as its low 32 bits and then either
6682 // correctly sign extended or incorrectly zero extended by HW.
6683 // If 64-bit literals are supported and the literal will be encoded
6684 // as full 64 bit we still can use it.
6685 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6686 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
6687 return false;
6688 }
6689 }
6690
6691 // Handle non-register types that are treated like immediates.
6692 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
6693
6694 if (!DefinedRC) {
6695 // This operand expects an immediate.
6696 return true;
6697 }
6698
6699 return isImmOperandLegal(MI, OpIdx, *MO);
6700}
6701
6703 bool IsGFX950Only = ST.hasGFX950Insts();
6704 bool IsGFX940Only = ST.hasGFX940Insts();
6705
6706 if (!IsGFX950Only && !IsGFX940Only)
6707 return false;
6708
6709 if (!isVALU(MI, /*AllowLDSDMA=*/true))
6710 return false;
6711
6712 // V_COS, V_EXP, V_RCP, etc.
6713 if (isTRANS(MI))
6714 return true;
6715
6716 // DOT2, DOT2C, DOT4, etc.
6717 if (isDOT(MI))
6718 return true;
6719
6720 // MFMA, SMFMA
6721 if (isMFMA(MI))
6722 return true;
6723
6724 unsigned Opcode = MI.getOpcode();
6725 switch (Opcode) {
6726 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6727 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6728 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6729 case AMDGPU::V_MQSAD_U32_U8_e64:
6730 case AMDGPU::V_PK_ADD_F16:
6731 case AMDGPU::V_PK_ADD_F32:
6732 case AMDGPU::V_PK_ADD_I16:
6733 case AMDGPU::V_PK_ADD_U16:
6734 case AMDGPU::V_PK_ASHRREV_I16:
6735 case AMDGPU::V_PK_FMA_F16:
6736 case AMDGPU::V_PK_FMA_F32:
6737 case AMDGPU::V_PK_FMAC_F16_e32:
6738 case AMDGPU::V_PK_FMAC_F16_e64:
6739 case AMDGPU::V_PK_LSHLREV_B16:
6740 case AMDGPU::V_PK_LSHRREV_B16:
6741 case AMDGPU::V_PK_MAD_I16:
6742 case AMDGPU::V_PK_MAD_U16:
6743 case AMDGPU::V_PK_MAX_F16:
6744 case AMDGPU::V_PK_MAX_I16:
6745 case AMDGPU::V_PK_MAX_U16:
6746 case AMDGPU::V_PK_MIN_F16:
6747 case AMDGPU::V_PK_MIN_I16:
6748 case AMDGPU::V_PK_MIN_U16:
6749 case AMDGPU::V_PK_MOV_B32:
6750 case AMDGPU::V_PK_MUL_F16:
6751 case AMDGPU::V_PK_MUL_F32:
6752 case AMDGPU::V_PK_MUL_LO_U16:
6753 case AMDGPU::V_PK_SUB_I16:
6754 case AMDGPU::V_PK_SUB_U16:
6755 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6756 return true;
6757 default:
6758 return false;
6759 }
6760}
6761
6763 MachineInstr &MI) const {
6764 unsigned Opc = MI.getOpcode();
6765 const MCInstrDesc &InstrDesc = get(Opc);
6766
6767 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
6768 MachineOperand &Src0 = MI.getOperand(Src0Idx);
6769
6770 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
6771 MachineOperand &Src1 = MI.getOperand(Src1Idx);
6772
6773 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
6774 // we need to only have one constant bus use before GFX10.
6775 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
6776 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
6777 RI.isSGPRReg(MRI, Src0.getReg()))
6778 legalizeOpWithMove(MI, Src0Idx);
6779
6780 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
6781 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
6782 // src0/src1 with V_READFIRSTLANE.
6783 if (Opc == AMDGPU::V_WRITELANE_B32) {
6784 const DebugLoc &DL = MI.getDebugLoc();
6785 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
6786 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6787 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6788 .add(Src0);
6789 Src0.ChangeToRegister(Reg, false);
6790 }
6791 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
6792 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6793 const DebugLoc &DL = MI.getDebugLoc();
6794 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6795 .add(Src1);
6796 Src1.ChangeToRegister(Reg, false);
6797 }
6798 return;
6799 }
6800
6801 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
6802 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
6803 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
6804 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
6805 legalizeOpWithMove(MI, Src2Idx);
6806 }
6807
6808 // VOP2 src0 instructions support all operand types, so we don't need to check
6809 // their legality. If src1 is already legal, we don't need to do anything.
6810 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
6811 return;
6812
6813 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
6814 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
6815 // select is uniform.
6816 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
6817 RI.isVGPR(MRI, Src1.getReg())) {
6818 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6819 const DebugLoc &DL = MI.getDebugLoc();
6820 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6821 .add(Src1);
6822 Src1.ChangeToRegister(Reg, false);
6823 return;
6824 }
6825
6826 // We do not use commuteInstruction here because it is too aggressive and will
6827 // commute if it is possible. We only want to commute here if it improves
6828 // legality. This can be called a fairly large number of times so don't waste
6829 // compile time pointlessly swapping and checking legality again.
6830 if (HasImplicitSGPR || !MI.isCommutable()) {
6831 legalizeOpWithMove(MI, Src1Idx);
6832 return;
6833 }
6834
6835 // If src0 can be used as src1, commuting will make the operands legal.
6836 // Otherwise we have to give up and insert a move.
6837 //
6838 // TODO: Other immediate-like operand kinds could be commuted if there was a
6839 // MachineOperand::ChangeTo* for them.
6840 if ((!Src1.isImm() && !Src1.isReg()) ||
6841 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
6842 legalizeOpWithMove(MI, Src1Idx);
6843 return;
6844 }
6845
6846 int CommutedOpc = commuteOpcode(MI);
6847 if (CommutedOpc == -1) {
6848 legalizeOpWithMove(MI, Src1Idx);
6849 return;
6850 }
6851
6852 MI.setDesc(get(CommutedOpc));
6853
6854 Register Src0Reg = Src0.getReg();
6855 unsigned Src0SubReg = Src0.getSubReg();
6856 bool Src0Kill = Src0.isKill();
6857
6858 if (Src1.isImm())
6859 Src0.ChangeToImmediate(Src1.getImm());
6860 else if (Src1.isReg()) {
6861 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
6862 Src0.setSubReg(Src1.getSubReg());
6863 } else
6864 llvm_unreachable("Should only have register or immediate operands");
6865
6866 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
6867 Src1.setSubReg(Src0SubReg);
6869}
6870
6871// Legalize VOP3 operands. All operand types are supported for any operand
6872// but only one literal constant and only starting from GFX10.
6874 MachineInstr &MI) const {
6875 unsigned Opc = MI.getOpcode();
6876
6877 int VOP3Idx[3] = {
6878 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
6879 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
6880 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
6881 };
6882
6883 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6884 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6885 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6886 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6887 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6888 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6889 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6890 // src1 and src2 must be scalar
6891 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
6892 const DebugLoc &DL = MI.getDebugLoc();
6893 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
6894 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6895 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6896 .add(Src1);
6897 Src1.ChangeToRegister(Reg, false);
6898 }
6899 if (VOP3Idx[2] != -1) {
6900 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
6901 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
6902 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6903 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6904 .add(Src2);
6905 Src2.ChangeToRegister(Reg, false);
6906 }
6907 }
6908 }
6909
6910 // Find the one SGPR operand we are allowed to use.
6911 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
6912 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
6913 SmallDenseSet<unsigned> SGPRsUsed;
6914 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
6915 if (SGPRReg) {
6916 SGPRsUsed.insert(SGPRReg);
6917 --ConstantBusLimit;
6918 }
6919
6920 for (int Idx : VOP3Idx) {
6921 if (Idx == -1)
6922 break;
6923 MachineOperand &MO = MI.getOperand(Idx);
6924
6925 if (!MO.isReg()) {
6926 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
6927 continue;
6928
6929 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
6930 --LiteralLimit;
6931 --ConstantBusLimit;
6932 continue;
6933 }
6934
6935 --LiteralLimit;
6936 --ConstantBusLimit;
6937 legalizeOpWithMove(MI, Idx);
6938 continue;
6939 }
6940
6941 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
6942 continue; // VGPRs are legal
6943
6944 // We can use one SGPR in each VOP3 instruction prior to GFX10
6945 // and two starting from GFX10.
6946 if (SGPRsUsed.count(MO.getReg()))
6947 continue;
6948 if (ConstantBusLimit > 0) {
6949 SGPRsUsed.insert(MO.getReg());
6950 --ConstantBusLimit;
6951 continue;
6952 }
6953
6954 // If we make it this far, then the operand is not legal and we must
6955 // legalize it.
6956 legalizeOpWithMove(MI, Idx);
6957 }
6958
6959 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
6960 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64) &&
6961 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
6962 legalizeOpWithMove(MI, VOP3Idx[2]);
6963
6964 // Fix the register class of single-sgpr-read instructions on gfx12+. See
6965 // SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6967 for (unsigned I = 0; I < 3; ++I) {
6968 if (!isLegalSingleSGPRReadInstOperand(MRI, MI, /*SrcN=*/I))
6969 legalizeOpWithMove(MI, VOP3Idx[I]);
6970 }
6971 }
6972}
6973
6976 const TargetRegisterClass *DstRC /*=nullptr*/) const {
6977 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
6978 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
6979 if (DstRC)
6980 SRC = RI.getCommonSubClass(SRC, DstRC);
6981
6982 Register DstReg = MRI.createVirtualRegister(SRC);
6983 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
6984
6985 if (RI.hasAGPRs(VRC)) {
6986 VRC = RI.getEquivalentVGPRClass(VRC);
6987 Register NewSrcReg = MRI.createVirtualRegister(VRC);
6988 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6989 get(TargetOpcode::COPY), NewSrcReg)
6990 .addReg(SrcReg);
6991 SrcReg = NewSrcReg;
6992 }
6993
6994 if (SubRegs == 1) {
6995 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6996 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6997 .addReg(SrcReg);
6998 return DstReg;
6999 }
7000
7002 for (unsigned i = 0; i < SubRegs; ++i) {
7003 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7004 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7005 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7006 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7007 SRegs.push_back(SGPR);
7008 }
7009
7011 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7012 get(AMDGPU::REG_SEQUENCE), DstReg);
7013 for (unsigned i = 0; i < SubRegs; ++i) {
7014 MIB.addReg(SRegs[i]);
7015 MIB.addImm(RI.getSubRegFromChannel(i));
7016 }
7017 return DstReg;
7018}
7019
7021 MachineInstr &MI) const {
7022
7023 // If the pointer is store in VGPRs, then we need to move them to
7024 // SGPRs using v_readfirstlane. This is safe because we only select
7025 // loads with uniform pointers to SMRD instruction so we know the
7026 // pointer value is uniform.
7027 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
7028 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
7029 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
7030 SBase->setReg(SGPR);
7031 }
7032 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
7033 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
7034 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
7035 SOff->setReg(SGPR);
7036 }
7037}
7038
7040 unsigned Opc = Inst.getOpcode();
7041 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
7042 if (OldSAddrIdx < 0)
7043 return false;
7044
7045 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
7046
7047 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
7048 if (NewOpc < 0)
7050 if (NewOpc < 0)
7051 return false;
7052
7053 MachineRegisterInfo &MRI = Inst.getMF()->getRegInfo();
7054 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
7055 if (RI.isSGPRReg(MRI, SAddr.getReg()))
7056 return false;
7057
7058 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7059 if (NewVAddrIdx < 0)
7060 return false;
7061
7062 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
7063
7064 // Check vaddr, it shall be zero or absent.
7065 MachineInstr *VAddrDef = nullptr;
7066 if (OldVAddrIdx >= 0) {
7067 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
7068 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
7069 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
7070 !VAddrDef->getOperand(1).isImm() ||
7071 VAddrDef->getOperand(1).getImm() != 0)
7072 return false;
7073 }
7074
7075 const MCInstrDesc &NewDesc = get(NewOpc);
7076 Inst.setDesc(NewDesc);
7077
7078 // Callers expect iterator to be valid after this call, so modify the
7079 // instruction in place.
7080 if (OldVAddrIdx == NewVAddrIdx) {
7081 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
7082 // Clear use list from the old vaddr holding a zero register.
7083 MRI.removeRegOperandFromUseList(&NewVAddr);
7084 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7085 Inst.removeOperand(OldSAddrIdx);
7086 // Update the use list with the pointer we have just moved from vaddr to
7087 // saddr position. Otherwise new vaddr will be missing from the use list.
7088 MRI.removeRegOperandFromUseList(&NewVAddr);
7089 MRI.addRegOperandToUseList(&NewVAddr);
7090 } else {
7091 assert(OldSAddrIdx == NewVAddrIdx);
7092
7093 if (OldVAddrIdx >= 0) {
7094 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7095 AMDGPU::OpName::vdst_in);
7096
7097 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
7098 // it asserts. Untie the operands for now and retie them afterwards.
7099 if (NewVDstIn != -1) {
7100 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
7101 Inst.untieRegOperand(OldVDstIn);
7102 }
7103
7104 Inst.removeOperand(OldVAddrIdx);
7105
7106 if (NewVDstIn != -1) {
7107 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7108 Inst.tieOperands(NewVDst, NewVDstIn);
7109 }
7110 }
7111 }
7112
7113 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
7114 VAddrDef->eraseFromParent();
7115
7116 return true;
7117}
7118
7119// FIXME: Remove this when SelectionDAG is obsoleted.
7121 MachineInstr &MI) const {
7122 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
7123 return;
7124
7125 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
7126 // thinks they are uniform, so a readfirstlane should be valid.
7127 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
7128 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
7129 return;
7130
7132 return;
7133
7134 const TargetRegisterClass *DeclaredRC =
7135 getRegClass(MI.getDesc(), SAddr->getOperandNo());
7136
7137 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
7138 SAddr->setReg(ToSGPR);
7139}
7140
7143 const TargetRegisterClass *DstRC,
7146 const DebugLoc &DL) const {
7147 Register OpReg = Op.getReg();
7148 unsigned OpSubReg = Op.getSubReg();
7149
7150 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
7151 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7152
7153 // Check if operand is already the correct register class.
7154 if (DstRC == OpRC)
7155 return;
7156
7157 Register DstReg = MRI.createVirtualRegister(DstRC);
7158 auto Copy = BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg)
7159 .addReg(OpReg, {}, OpSubReg);
7160 Op.setReg(DstReg);
7161 Op.setSubReg(AMDGPU::NoSubRegister);
7162
7163 MachineInstr *Def = MRI.getVRegDef(OpReg);
7164 if (!Def)
7165 return;
7166
7167 // Try to eliminate the copy if it is copying an immediate value.
7168 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7169 foldImmediate(*Copy, *Def, OpReg, &MRI);
7170
7171 bool ImpDef = Def->isImplicitDef();
7172 while (!ImpDef && Def && Def->isCopy()) {
7173 if (Def->getOperand(1).getReg().isPhysical())
7174 break;
7175 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7176 ImpDef = Def && Def->isImplicitDef();
7177 }
7178 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7179 !ImpDef)
7180 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7181}
7182
7183// Emit the actual waterfall loop, executing the wrapped instruction for each
7184// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7185// iteration, in the worst case we execute 64 (once per lane).
7188 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7189 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7190 MachineFunction &MF = *LoopBB.getParent();
7192 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7194 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7195
7196 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7197 // available. Otherwise, use the previous pattern of v_cmp_eq,
7198 // s_and_saveexec, and s_xor.
7199 bool UseNewExecInstructions =
7200 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7201
7203 Register CondReg;
7204
7205 Register PhiExec;
7206 Register NewExec;
7207
7208 if (UseNewExecInstructions) {
7209 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7210 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7211 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7212 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7213 .addReg(LMC.ExecReg);
7214
7215 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7216 .addReg(InitExec)
7217 .addMBB(&PredBB)
7218 .addReg(NewExec)
7219 .addMBB(&BodyBB);
7220 }
7221
7222 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7223 // involves a trade-off between register pressure and latency:
7224 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7225 // register pressure because arguments and results of all
7226 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7227 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7228 // increase latency by placing v_readfirstlane instructions
7229 // immediately before v_cmpx instruction that directly depend on it.
7230 ///
7231 // Emitting interleaved v_cmpx and v_readfirstlane requires
7232 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7233 // v_cmpx needs to be treated as terminator until after register allocation
7234 // (spill placement) and instruction reordering.
7235 //
7236 // Current implementation defers v_cmpx and leaves other instruction
7237 // scheduling decisions to later passes, where register pressure is known or
7238 // easier to approximate.
7239 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7240 // v_cmpx instructions are inserted at the end of LoopBB.
7241 // After the first v_cmpx is emitted, I is updated to point to it
7242 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7243 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7244 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7245 unsigned NumSubRegs = RegSize / 32;
7246 Register VScalarOp = ScalarOp->getReg();
7247
7248 const TargetRegisterClass *RFLSrcRC =
7249 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7250
7251 if (NumSubRegs == 1) {
7252 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7253 if (const TargetRegisterClass *Common =
7254 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7255 Common != VScalarOpRC) {
7256 Register VRReg = MRI.createVirtualRegister(Common);
7257 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7258 VScalarOp = VRReg;
7259 }
7260 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7261
7262 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7263 .addReg(VScalarOp);
7264
7265 if (UseNewExecInstructions) {
7266 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7267 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7268 .addReg(CurReg)
7269 .addReg(VScalarOp);
7270 if (I == LoopBB.end())
7271 I = CmpxMI.getInstr()->getIterator();
7272 } else {
7273 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7274
7275 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7276 .addReg(CurReg)
7277 .addReg(VScalarOp);
7278
7279 // Combine the comparison results with AND.
7280 if (!CondReg) { // First.
7281 CondReg = NewCondReg;
7282 } else { // If not the first, we create an AND.
7283 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7284 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7285 .addReg(CondReg)
7286 .addReg(NewCondReg);
7287 CondReg = AndReg;
7288 }
7289 }
7290
7291 // Update ScalarOp operand to use the SGPR ScalarOp.
7292 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7293 ScalarOp->setReg(CurReg);
7294 else {
7295 // Insert into the same block of use
7296 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7297 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7298 .addReg(CurReg);
7299 ScalarOp->setReg(PhySGPRs[Idx]);
7300 }
7301 ScalarOp->setIsKill();
7302 } else {
7303 SmallVector<Register, 8> ReadlanePieces;
7304 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7305 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7306 "Unhandled register size");
7307
7308 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7309 Register CurRegLo =
7310 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7311 Register CurRegHi =
7312 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7313
7314 // Read the next variant <- also loop target.
7315 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7316 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7317
7318 // Read the next variant <- also loop target.
7319 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7320 .addReg(VScalarOp, VScalarOpUndef,
7321 TRI->getSubRegFromChannel(Idx + 1));
7322
7323 ReadlanePieces.push_back(CurRegLo);
7324 ReadlanePieces.push_back(CurRegHi);
7325
7326 // Comparison is to be done as 64-bit.
7327 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7328 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7329 .addReg(CurRegLo)
7330 .addImm(AMDGPU::sub0)
7331 .addReg(CurRegHi)
7332 .addImm(AMDGPU::sub1);
7333
7334 unsigned SubReg =
7335 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7336
7337 if (UseNewExecInstructions) {
7338 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7339 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7340 .addReg(CurReg)
7341 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7342 if (I == LoopBB.end())
7343 I = CmpxMI.getInstr()->getIterator();
7344 } else {
7345 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7346 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7347 .addReg(CurReg)
7348 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7349
7350 // Combine the comparison results with AND.
7351 if (!CondReg) { // First.
7352 CondReg = NewCondReg;
7353 } else { // If not the first, we create an AND.
7354 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7355 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7356 .addReg(CondReg)
7357 .addReg(NewCondReg);
7358 CondReg = AndReg;
7359 }
7360 }
7361 } // End for loop.
7362
7363 const auto *SScalarOpRC =
7364 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7365 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7366
7367 // Build scalar ScalarOp.
7368 auto Merge =
7369 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7370 unsigned Channel = 0;
7371 for (Register Piece : ReadlanePieces) {
7372 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7373 }
7374
7375 // Update ScalarOp operand to use the SGPR ScalarOp.
7376 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7377 ScalarOp->setReg(SScalarOp);
7378 else {
7379 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7380 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7381 .addReg(SScalarOp);
7382 ScalarOp->setReg(PhySGPRs[Idx]);
7383 }
7384 ScalarOp->setIsKill();
7385 }
7386 }
7387
7388 // Instructions AndSaveExecOpc and AndN2WrExecOpc that modify EXEC mask
7389 // should have isTerminator=1 but terminators that define
7390 // virtual registers are not supported.
7391 Register SaveExec;
7392 if (!UseNewExecInstructions) {
7393 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7394 MRI.setSimpleHint(SaveExec, CondReg);
7395
7396 // Update EXEC to matching lanes, saving original to SaveExec.
7397 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7398 .addReg(CondReg, RegState::Kill);
7399 }
7400
7401 // The original instruction is here; we insert the terminators after it.
7402 I = BodyBB.end();
7403
7404 if (UseNewExecInstructions) {
7405 MRI.setSimpleHint(NewExec, PhiExec);
7406 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2WrExecOpc), NewExec)
7407 .addReg(PhiExec);
7408 } else {
7409 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7410 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7411 .addReg(LMC.ExecReg)
7412 .addReg(SaveExec);
7413 }
7414
7415 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7416}
7417
7418// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7419// with SGPRs by iterating over all unique values across all lanes.
7420// Returns the loop basic block that now contains \p MI.
7421static MachineBasicBlock *
7425 MachineBasicBlock::iterator Begin = nullptr,
7426 MachineBasicBlock::iterator End = nullptr,
7427 ArrayRef<Register> PhySGPRs = {}) {
7428 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7429 "Physical SGPRs must be empty or match the number of scalar operands");
7430 MachineBasicBlock &MBB = *MI.getParent();
7431 MachineFunction &MF = *MBB.getParent();
7433 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7434 MachineRegisterInfo &MRI = MF.getRegInfo();
7435 if (!Begin.isValid())
7436 Begin = &MI;
7437 if (!End.isValid()) {
7438 End = &MI;
7439 ++End;
7440 }
7441 const DebugLoc &DL = MI.getDebugLoc();
7443 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7444
7445 // Save SCC. Waterfall Loop may overwrite SCC.
7446 Register SaveSCCReg;
7447
7448 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7449 // rather than unlimited scan everywhere
7450 bool SCCNotDead =
7451 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7452 std::numeric_limits<unsigned>::max()) !=
7454 if (SCCNotDead) {
7455 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7456 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7457 .addImm(1)
7458 .addImm(0);
7459 }
7460
7461 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7462
7463 // Save the EXEC mask
7464 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7465
7466 // Killed uses in the instruction we are waterfalling around will be
7467 // incorrect due to the added control-flow.
7469 ++AfterMI;
7470 for (auto I = Begin; I != AfterMI; I++) {
7471 for (auto &MO : I->all_uses())
7472 MRI.clearKillFlags(MO.getReg());
7473 }
7474
7475 // To insert the loop we need to split the block. Move everything after this
7476 // point to a new block, and insert a new empty block between the two.
7479 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7481 ++MBBI;
7482
7483 MF.insert(MBBI, LoopBB);
7484 MF.insert(MBBI, BodyBB);
7485 MF.insert(MBBI, RemainderBB);
7486
7487 LoopBB->addSuccessor(BodyBB);
7488 BodyBB->addSuccessor(LoopBB);
7489 BodyBB->addSuccessor(RemainderBB);
7490
7491 // Move Begin to MI to the BodyBB, and the remainder of the block to
7492 // RemainderBB.
7493 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7494 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7495 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7496
7497 MBB.addSuccessor(LoopBB);
7498
7499 // Update dominators. We know that MBB immediately dominates LoopBB, that
7500 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7501 // RemainderBB. RemainderBB immediately dominates all of the successors
7502 // transferred to it from MBB that MBB used to properly dominate.
7503 if (MDT) {
7504 MDT->addNewBlock(LoopBB, &MBB);
7505 MDT->addNewBlock(BodyBB, LoopBB);
7506 MDT->addNewBlock(RemainderBB, BodyBB);
7507 for (auto &Succ : RemainderBB->successors()) {
7508 if (MDT->properlyDominates(&MBB, Succ)) {
7509 MDT->changeImmediateDominator(Succ, RemainderBB);
7510 }
7511 }
7512 }
7513
7514 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7515 PhySGPRs);
7516
7517 MachineBasicBlock::iterator First = RemainderBB->begin();
7518 // Restore SCC
7519 if (SCCNotDead) {
7520 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7521 .addReg(SaveSCCReg, RegState::Kill)
7522 .addImm(0);
7523 }
7524
7525 // Restore the EXEC mask
7526 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7527 .addReg(SaveExec);
7528 return BodyBB;
7529}
7530
7531// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7532static std::tuple<unsigned, unsigned>
7534 MachineBasicBlock &MBB = *MI.getParent();
7535 MachineFunction &MF = *MBB.getParent();
7536 MachineRegisterInfo &MRI = MF.getRegInfo();
7537
7538 // Extract the ptr from the resource descriptor.
7539 unsigned RsrcPtr =
7540 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7541 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7542
7543 // Create an empty resource descriptor
7544 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7545 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7546 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7547 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7548 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7549
7550 // Zero64 = 0
7551 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7552 .addImm(0);
7553
7554 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7555 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7556 .addImm(Lo_32(RsrcDataFormat));
7557
7558 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7559 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7560 .addImm(Hi_32(RsrcDataFormat));
7561
7562 // NewSRsrc = {Zero64, SRsrcFormat}
7563 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7564 .addReg(Zero64)
7565 .addImm(AMDGPU::sub0_sub1)
7566 .addReg(SRsrcFormatLo)
7567 .addImm(AMDGPU::sub2)
7568 .addReg(SRsrcFormatHi)
7569 .addImm(AMDGPU::sub3);
7570
7571 return std::tuple(RsrcPtr, NewSRsrc);
7572}
7573
7576 MachineDominatorTree *MDT) const {
7577 MachineFunction &MF = *MI.getMF();
7578 MachineRegisterInfo &MRI = MF.getRegInfo();
7579 MachineBasicBlock *CreatedBB = nullptr;
7580
7581 // Legalize True16
7582 if (ST.useRealTrue16Insts())
7584
7585 // Legalize VOP2
7586 if (isVOP2(MI) || isVOPC(MI)) {
7588 return CreatedBB;
7589 }
7590
7591 // Legalize VOP3
7592 if (isVOP3(MI)) {
7594 return CreatedBB;
7595 }
7596
7597 // Legalize SMRD
7598 if (isSMRD(MI)) {
7600 return CreatedBB;
7601 }
7602
7603 // Legalize FLAT
7604 if (isFLAT(MI)) {
7606 return CreatedBB;
7607 }
7608
7609 // Legalize PHI
7610 // The register class of the operands must be the same type as the register
7611 // class of the output.
7612 if (MI.getOpcode() == AMDGPU::PHI) {
7613 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7614 assert(!RI.isSGPRClass(VRC));
7615
7616 // Update all the operands so they have the same type.
7617 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7618 MachineOperand &Op = MI.getOperand(I);
7619 if (!Op.isReg() || !Op.getReg().isVirtual())
7620 continue;
7621
7622 // MI is a PHI instruction.
7623 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7625
7626 // Avoid creating no-op copies with the same src and dst reg class. These
7627 // confuse some of the machine passes.
7628 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7629 }
7630 }
7631
7632 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7633 // VGPR dest type and SGPR sources, insert copies so all operands are
7634 // VGPRs. This seems to help operand folding / the register coalescer.
7635 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7636 MachineBasicBlock *MBB = MI.getParent();
7637 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7638 if (RI.hasVGPRs(DstRC)) {
7639 // Update all the operands so they are VGPR register classes. These may
7640 // not be the same register class because REG_SEQUENCE supports mixing
7641 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7642 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7643 MachineOperand &Op = MI.getOperand(I);
7644 if (!Op.isReg() || !Op.getReg().isVirtual())
7645 continue;
7646
7647 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7648 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7649 if (VRC == OpRC)
7650 continue;
7651
7652 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7653 Op.setIsKill();
7654 }
7655 }
7656
7657 return CreatedBB;
7658 }
7659
7660 // Legalize INSERT_SUBREG
7661 // src0 must have the same register class as dst
7662 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7663 Register Dst = MI.getOperand(0).getReg();
7664 Register Src0 = MI.getOperand(1).getReg();
7665 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7666 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7667 if (DstRC != Src0RC) {
7668 MachineBasicBlock *MBB = MI.getParent();
7669 MachineOperand &Op = MI.getOperand(1);
7670 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7671 }
7672 return CreatedBB;
7673 }
7674
7675 // Legalize SI_INIT_M0
7676 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7677 MachineOperand &Src = MI.getOperand(0);
7678 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7679 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7680 return CreatedBB;
7681 }
7682
7683 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
7684 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7685 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7686 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7687 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7688 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7689 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7690 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7691 MachineOperand &Src = MI.getOperand(1);
7692 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7693 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7694 return CreatedBB;
7695 }
7696
7697 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
7698 //
7699 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
7700 // scratch memory access. In both cases, the legalization never involves
7701 // conversion to the addr64 form.
7703 (isMUBUF(MI) || isMTBUF(MI)))) {
7704 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
7705 ? AMDGPU::OpName::rsrc
7706 : AMDGPU::OpName::srsrc;
7707 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
7708 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
7709 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
7710
7711 AMDGPU::OpName SampOpName =
7712 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7713 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
7714 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
7715 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
7716
7717 return CreatedBB;
7718 }
7719
7720 // Legalize SI_CALL
7721 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7722 MachineOperand *Dest = &MI.getOperand(0);
7723 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
7724 createWaterFallForSiCall(&MI, MDT, {Dest});
7725 }
7726 }
7727
7728 // Legalize s_sleep_var.
7729 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7730 const DebugLoc &DL = MI.getDebugLoc();
7731 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7732 int Src0Idx =
7733 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
7734 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7735 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7736 .add(Src0);
7737 Src0.ChangeToRegister(Reg, false);
7738 return nullptr;
7739 }
7740
7741 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
7742 // operands are scalar.
7743 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7744 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7745 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7746 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7747 for (MachineOperand &Src : MI.explicit_operands()) {
7748 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7749 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7750 }
7751 return CreatedBB;
7752 }
7753
7754 // Legalize MUBUF instructions.
7755 bool isSoffsetLegal = true;
7756 int SoffsetIdx =
7757 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
7758 if (SoffsetIdx != -1) {
7759 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
7760 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
7761 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
7762 isSoffsetLegal = false;
7763 }
7764 }
7765
7766 bool isRsrcLegal = true;
7767 int RsrcIdx =
7768 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
7769 if (RsrcIdx != -1) {
7770 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7771 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
7772 isRsrcLegal = false;
7773 }
7774
7775 // The operands are legal.
7776 if (isRsrcLegal && isSoffsetLegal)
7777 return CreatedBB;
7778
7779 if (!isRsrcLegal) {
7780 // Legalize a VGPR Rsrc
7781 //
7782 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
7783 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
7784 // a zero-value SRsrc.
7785 //
7786 // If the instruction is _OFFSET (both idxen and offen disabled), and we
7787 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
7788 // above.
7789 //
7790 // Otherwise we are on non-ADDR64 hardware, and/or we have
7791 // idxen/offen/bothen and we fall back to a waterfall loop.
7792
7793 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7794 MachineBasicBlock &MBB = *MI.getParent();
7795
7796 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
7797 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
7798 // This is already an ADDR64 instruction so we need to add the pointer
7799 // extracted from the resource descriptor to the current value of VAddr.
7800 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7801 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7802 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7803
7804 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7805 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
7806 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
7807
7808 unsigned RsrcPtr, NewSRsrc;
7809 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7810
7811 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
7812 const DebugLoc &DL = MI.getDebugLoc();
7813 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
7814 .addDef(CondReg0)
7815 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7816 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
7817 .addImm(0);
7818
7819 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
7820 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
7821 .addDef(CondReg1, RegState::Dead)
7822 .addReg(RsrcPtr, {}, AMDGPU::sub1)
7823 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
7824 .addReg(CondReg0, RegState::Kill)
7825 .addImm(0);
7826
7827 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7828 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
7829 .addReg(NewVAddrLo)
7830 .addImm(AMDGPU::sub0)
7831 .addReg(NewVAddrHi)
7832 .addImm(AMDGPU::sub1);
7833
7834 VAddr->setReg(NewVAddr);
7835 Rsrc->setReg(NewSRsrc);
7836 } else if (!VAddr && ST.hasAddr64()) {
7837 // This instructions is the _OFFSET variant, so we need to convert it to
7838 // ADDR64.
7839 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
7840 "FIXME: Need to emit flat atomics here");
7841
7842 unsigned RsrcPtr, NewSRsrc;
7843 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7844
7845 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7846 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
7847 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
7848 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7849 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
7850
7851 // Atomics with return have an additional tied operand and are
7852 // missing some of the special bits.
7853 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
7854 MachineInstr *Addr64;
7855
7856 if (!VDataIn) {
7857 // Regular buffer load / store.
7859 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7860 .add(*VData)
7861 .addReg(NewVAddr)
7862 .addReg(NewSRsrc)
7863 .add(*SOffset)
7864 .add(*Offset);
7865
7866 if (const MachineOperand *CPol =
7867 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
7868 MIB.addImm(CPol->getImm());
7869 }
7870
7871 if (const MachineOperand *TFE =
7872 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
7873 MIB.addImm(TFE->getImm());
7874 }
7875
7876 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
7877
7878 MIB.cloneMemRefs(MI);
7879 Addr64 = MIB;
7880 } else {
7881 // Atomics with return.
7882 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7883 .add(*VData)
7884 .add(*VDataIn)
7885 .addReg(NewVAddr)
7886 .addReg(NewSRsrc)
7887 .add(*SOffset)
7888 .add(*Offset)
7889 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
7890 .cloneMemRefs(MI);
7891 }
7892
7893 MI.removeFromParent();
7894
7895 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7896 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
7897 NewVAddr)
7898 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7899 .addImm(AMDGPU::sub0)
7900 .addReg(RsrcPtr, {}, AMDGPU::sub1)
7901 .addImm(AMDGPU::sub1);
7902 } else {
7903 // Legalize a VGPR Rsrc and soffset together.
7904 if (!isSoffsetLegal) {
7905 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7906 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
7907 return CreatedBB;
7908 }
7909 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
7910 return CreatedBB;
7911 }
7912 }
7913
7914 // Legalize a VGPR soffset.
7915 if (!isSoffsetLegal) {
7916 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7917 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
7918 return CreatedBB;
7919 }
7920 return CreatedBB;
7921}
7922
7924 if (InSet.insert(MI).second)
7925 InstrList.push_back(MI);
7926 // Add MBUF instructiosn to deferred list.
7927 int RsrcIdx =
7928 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
7929 if (RsrcIdx != -1) {
7930 DeferredList.insert(MI);
7931 }
7932}
7933
7935 return DeferredList.contains(MI);
7936}
7937
7938// Legalize size mismatches between 16bit and 32bit registers in v2s copy
7939// lowering (change sgpr to vgpr).
7940// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
7941// size. Need to legalize the size of the operands during the vgpr lowering
7942// chain. This can be removed after we have sgpr16 in place
7944 MachineRegisterInfo &MRI) const {
7945 if (!ST.useRealTrue16Insts())
7946 return;
7947
7948 unsigned Opcode = MI.getOpcode();
7949 MachineBasicBlock *MBB = MI.getParent();
7950 // Legalize operands and check for size mismatch
7951 if (OpIdx >= MI.getNumExplicitOperands() ||
7952 OpIdx >= get(Opcode).getNumOperands() ||
7953 get(Opcode).operands()[OpIdx].RegClass == -1)
7954 return;
7955
7956 MachineOperand &Op = MI.getOperand(OpIdx);
7957 if (!Op.isReg() || !Op.getReg().isVirtual() || Op.isDef())
7958 return;
7959
7960 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
7961 if (!RI.isVGPRClass(CurrRC))
7962 return;
7963
7964 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
7965 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
7966 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
7967 // Default to the lo16 only if the subregister is not specified.
7968 if (Op.getSubReg() == AMDGPU::NoSubRegister)
7969 Op.setSubReg(AMDGPU::lo16);
7970 return;
7971 }
7972
7973 const TargetRegisterClass *CurrSRC =
7974 RI.getSubRegisterClass(CurrRC, Op.getSubReg());
7975 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
7976 const DebugLoc &DL = MI.getDebugLoc();
7977 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7978 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
7979 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
7980 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
7981 .addReg(Op.getReg(), {}, Op.getSubReg())
7982 .addImm(AMDGPU::lo16)
7983 .addReg(Undef)
7984 .addImm(AMDGPU::hi16);
7985 Op.setReg(NewDstReg);
7986 Op.setSubReg(AMDGPU::NoSubRegister);
7987 }
7988}
7990 MachineRegisterInfo &MRI) const {
7991 for (unsigned OpIdx = 0; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
7992 legalizeOperandsVALUt16(MI, OpIdx, MRI);
7993}
7994
7998 ArrayRef<Register> PhySGPRs) const {
7999 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8000 "This only handle waterfall for SI_CALL_ISEL");
8001 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
8002 // following copies, we also need to move copies from and to physical
8003 // registers into the loop block.
8004 // Also move the copies to physical registers into the loop block
8005 MachineBasicBlock &MBB = *MI->getParent();
8007 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8008 --Start;
8010 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8011 ++End;
8012
8013 // Also include following copies of the return value
8014 ++End;
8015 while (End != MBB.end() && End->isCopy() &&
8016 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8017 ++End;
8018
8019 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
8020}
8021
8023 MachineDominatorTree *MDT) const {
8025 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
8026 while (!Worklist.empty()) {
8027 MachineInstr &Inst = *Worklist.top();
8028 Worklist.erase_top();
8029 // Skip MachineInstr in the deferred list.
8030 if (Worklist.isDeferred(&Inst))
8031 continue;
8032 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8033 }
8034
8035 // Deferred list of instructions will be processed once
8036 // all the MachineInstr in the worklist are done.
8037 for (MachineInstr *Inst : Worklist.getDeferredList()) {
8038 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8039 assert(Worklist.empty() &&
8040 "Deferred MachineInstr are not supposed to re-populate worklist");
8041 }
8042
8043 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
8044 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8045 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
8046 Entry.second.SGPRs);
8047 }
8048
8049 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8050 if (Entry.second)
8051 Entry.first->eraseFromParent();
8052}
8054 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
8055 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
8056 // hope for the best.
8057 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
8058 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
8059 if (SubRegIndices.size() <= 1) {
8060 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8061 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8062 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8063 .add(Inst.getOperand(1));
8064 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
8065 DstReg)
8066 .addReg(NewDst);
8067 } else {
8069 for (int16_t Indice : SubRegIndices) {
8070 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8071 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8072 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8073 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
8074
8075 DstRegs.push_back(NewDst);
8076 }
8078 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8079 get(AMDGPU::REG_SEQUENCE), DstReg);
8080 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
8081 MIB.addReg(DstRegs[i]);
8082 MIB.addImm(RI.getSubRegFromChannel(i));
8083 }
8084 }
8085}
8086
8088 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
8091 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8092 if (DstReg == AMDGPU::M0) {
8093 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8094 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8095 return;
8096 }
8097 Register SrcReg = Inst.getOperand(1).getReg();
8100 // Only search current block since phyreg's def & use cannot cross
8101 // blocks when MF.NoPhi = false.
8102 while (++I != E) {
8103 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
8104 // and record the operand for later waterfall loop generation.
8105 if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8106 MachineInstr *UseMI = &*I;
8107 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
8108 if (UseMI->getOperand(i).isReg() &&
8109 UseMI->getOperand(i).getReg() == DstReg) {
8110 MachineOperand *MO = &UseMI->getOperand(i);
8111 MO->setReg(SrcReg);
8112 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
8113 V2SCopyInfo.MOs.push_back(MO);
8114 V2SCopyInfo.SGPRs.push_back(DstReg);
8115 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8116 }
8117 }
8118 } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8119 I->getOperand(0).isReg() &&
8120 I->getOperand(0).getReg() == DstReg) {
8121 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8122 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8123 } else if (I->readsRegister(DstReg, &RI)) {
8124 // COPY cannot be erased if other type of inst uses it.
8125 V2SPhyCopiesToErase[&Inst] = false;
8126 }
8127 if (I->findRegisterDefOperand(DstReg, &RI))
8128 break;
8129 }
8130}
8131
8133 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
8135 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8136
8138 if (!MBB)
8139 return;
8140 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
8141 unsigned Opcode = Inst.getOpcode();
8142 unsigned NewOpcode = getVALUOp(Inst);
8143 const DebugLoc &DL = Inst.getDebugLoc();
8144
8145 // Handle some special cases
8146 switch (Opcode) {
8147 default:
8148 break;
8149 case AMDGPU::S_ADD_I32:
8150 case AMDGPU::S_SUB_I32: {
8151 // FIXME: The u32 versions currently selected use the carry.
8152 bool Changed;
8153 MachineBasicBlock *CreatedBBTmp = nullptr;
8154 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8155 if (Changed)
8156 return;
8157
8158 // Default handling
8159 break;
8160 }
8161
8162 case AMDGPU::S_MUL_U64:
8163 if (ST.hasVMulU64Inst()) {
8164 NewOpcode = AMDGPU::V_MUL_U64_e64;
8165 break;
8166 }
8167 // Split s_mul_u64 in 32-bit vector multiplications.
8168 splitScalarSMulU64(Worklist, Inst, MDT);
8169 Inst.eraseFromParent();
8170 return;
8171
8172 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8173 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8174 // This is a special case of s_mul_u64 where all the operands are either
8175 // zero extended or sign extended.
8176 splitScalarSMulPseudo(Worklist, Inst, MDT);
8177 Inst.eraseFromParent();
8178 return;
8179
8180 case AMDGPU::S_AND_B64:
8181 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8182 Inst.eraseFromParent();
8183 return;
8184
8185 case AMDGPU::S_OR_B64:
8186 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8187 Inst.eraseFromParent();
8188 return;
8189
8190 case AMDGPU::S_XOR_B64:
8191 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8192 Inst.eraseFromParent();
8193 return;
8194
8195 case AMDGPU::S_NAND_B64:
8196 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8197 Inst.eraseFromParent();
8198 return;
8199
8200 case AMDGPU::S_NOR_B64:
8201 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8202 Inst.eraseFromParent();
8203 return;
8204
8205 case AMDGPU::S_XNOR_B64:
8206 if (ST.hasDLInsts())
8207 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8208 else
8209 splitScalar64BitXnor(Worklist, Inst, MDT);
8210 Inst.eraseFromParent();
8211 return;
8212
8213 case AMDGPU::S_ANDN2_B64:
8214 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8215 Inst.eraseFromParent();
8216 return;
8217
8218 case AMDGPU::S_ORN2_B64:
8219 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8220 Inst.eraseFromParent();
8221 return;
8222
8223 case AMDGPU::S_BREV_B64:
8224 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8225 Inst.eraseFromParent();
8226 return;
8227
8228 case AMDGPU::S_NOT_B64:
8229 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8230 Inst.eraseFromParent();
8231 return;
8232
8233 case AMDGPU::S_BCNT1_I32_B64:
8234 splitScalar64BitBCNT(Worklist, Inst);
8235 Inst.eraseFromParent();
8236 return;
8237
8238 case AMDGPU::S_BFE_I64:
8239 splitScalar64BitBFE(Worklist, Inst);
8240 Inst.eraseFromParent();
8241 return;
8242
8243 case AMDGPU::S_FLBIT_I32_B64:
8244 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8245 Inst.eraseFromParent();
8246 return;
8247 case AMDGPU::S_FF1_I32_B64:
8248 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8249 Inst.eraseFromParent();
8250 return;
8251
8252 case AMDGPU::S_LSHL_B32:
8253 if (ST.hasOnlyRevVALUShifts()) {
8254 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8255 swapOperands(Inst);
8256 }
8257 break;
8258 case AMDGPU::S_ASHR_I32:
8259 if (ST.hasOnlyRevVALUShifts()) {
8260 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8261 swapOperands(Inst);
8262 }
8263 break;
8264 case AMDGPU::S_LSHR_B32:
8265 if (ST.hasOnlyRevVALUShifts()) {
8266 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8267 swapOperands(Inst);
8268 }
8269 break;
8270 case AMDGPU::S_LSHL_B64:
8271 if (ST.hasOnlyRevVALUShifts()) {
8272 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8273 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8274 : AMDGPU::V_LSHLREV_B64_e64;
8275 swapOperands(Inst);
8276 }
8277 break;
8278 case AMDGPU::S_ASHR_I64:
8279 if (ST.hasOnlyRevVALUShifts()) {
8280 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8281 swapOperands(Inst);
8282 }
8283 break;
8284 case AMDGPU::S_LSHR_B64:
8285 if (ST.hasOnlyRevVALUShifts()) {
8286 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8287 swapOperands(Inst);
8288 }
8289 break;
8290
8291 case AMDGPU::S_ABS_I32:
8292 lowerScalarAbs(Worklist, Inst);
8293 Inst.eraseFromParent();
8294 return;
8295
8296 case AMDGPU::S_ABSDIFF_I32:
8297 lowerScalarAbsDiff(Worklist, Inst);
8298 Inst.eraseFromParent();
8299 return;
8300
8301 case AMDGPU::S_CBRANCH_SCC0:
8302 case AMDGPU::S_CBRANCH_SCC1: {
8303 // Clear unused bits of vcc
8304 Register CondReg = Inst.getOperand(1).getReg();
8305 bool IsSCC = CondReg == AMDGPU::SCC;
8307 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8308 .addReg(LMC.ExecReg)
8309 .addReg(IsSCC ? LMC.VccReg : CondReg);
8310 Inst.removeOperand(1);
8311 } break;
8312
8313 case AMDGPU::S_BFE_U64:
8314 case AMDGPU::S_BFM_B64:
8315 llvm_unreachable("Moving this op to VALU not implemented");
8316
8317 case AMDGPU::S_PACK_LL_B32_B16:
8318 case AMDGPU::S_PACK_LH_B32_B16:
8319 case AMDGPU::S_PACK_HL_B32_B16:
8320 case AMDGPU::S_PACK_HH_B32_B16:
8321 movePackToVALU(Worklist, MRI, Inst);
8322 Inst.eraseFromParent();
8323 return;
8324
8325 case AMDGPU::S_XNOR_B32:
8326 lowerScalarXnor(Worklist, Inst);
8327 Inst.eraseFromParent();
8328 return;
8329
8330 case AMDGPU::S_NAND_B32:
8331 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8332 Inst.eraseFromParent();
8333 return;
8334
8335 case AMDGPU::S_NOR_B32:
8336 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8337 Inst.eraseFromParent();
8338 return;
8339
8340 case AMDGPU::S_ANDN2_B32:
8341 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8342 Inst.eraseFromParent();
8343 return;
8344
8345 case AMDGPU::S_ORN2_B32:
8346 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8347 Inst.eraseFromParent();
8348 return;
8349
8350 // TODO: remove as soon as everything is ready
8351 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8352 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8353 // can only be selected from the uniform SDNode.
8354 case AMDGPU::S_ADD_CO_PSEUDO:
8355 case AMDGPU::S_SUB_CO_PSEUDO: {
8356 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8357 ? AMDGPU::V_ADDC_U32_e64
8358 : AMDGPU::V_SUBB_U32_e64;
8359 const auto *CarryRC = RI.getWaveMaskRegClass();
8360
8361 Register CarryInReg = Inst.getOperand(4).getReg();
8362 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8363 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8364 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8365 .addReg(CarryInReg);
8366 }
8367
8368 Register CarryOutReg = Inst.getOperand(1).getReg();
8369
8370 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8371 MRI.getRegClass(Inst.getOperand(0).getReg())));
8372 MachineInstr *CarryOp =
8373 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8374 .addReg(CarryOutReg, RegState::Define)
8375 .add(Inst.getOperand(2))
8376 .add(Inst.getOperand(3))
8377 .addReg(CarryInReg)
8378 .addImm(0);
8379 legalizeOperands(*CarryOp);
8380 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8381 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8382 Inst.eraseFromParent();
8383 }
8384 return;
8385 case AMDGPU::S_UADDO_PSEUDO:
8386 case AMDGPU::S_USUBO_PSEUDO: {
8387 MachineOperand &Dest0 = Inst.getOperand(0);
8388 MachineOperand &Dest1 = Inst.getOperand(1);
8389 MachineOperand &Src0 = Inst.getOperand(2);
8390 MachineOperand &Src1 = Inst.getOperand(3);
8391
8392 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8393 ? AMDGPU::V_ADD_CO_U32_e64
8394 : AMDGPU::V_SUB_CO_U32_e64;
8395 const TargetRegisterClass *NewRC =
8396 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8397 Register DestReg = MRI.createVirtualRegister(NewRC);
8398 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8399 .addReg(Dest1.getReg(), RegState::Define)
8400 .add(Src0)
8401 .add(Src1)
8402 .addImm(0); // clamp bit
8403
8404 legalizeOperands(*NewInstr, MDT);
8405 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8406 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8407 Inst.eraseFromParent();
8408 }
8409 return;
8410 case AMDGPU::S_LSHL1_ADD_U32:
8411 case AMDGPU::S_LSHL2_ADD_U32:
8412 case AMDGPU::S_LSHL3_ADD_U32:
8413 case AMDGPU::S_LSHL4_ADD_U32: {
8414 MachineOperand &Dest = Inst.getOperand(0);
8415 MachineOperand &Src0 = Inst.getOperand(1);
8416 MachineOperand &Src1 = Inst.getOperand(2);
8417 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8418 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8419 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8420 : 4);
8421
8422 const TargetRegisterClass *NewRC =
8423 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8424 Register DestReg = MRI.createVirtualRegister(NewRC);
8425 MachineInstr *NewInstr =
8426 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8427 .add(Src0)
8428 .addImm(ShiftAmt)
8429 .add(Src1);
8430
8431 legalizeOperands(*NewInstr, MDT);
8432 MRI.replaceRegWith(Dest.getReg(), DestReg);
8433 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8434 Inst.eraseFromParent();
8435 }
8436 return;
8437 case AMDGPU::S_CSELECT_B32:
8438 case AMDGPU::S_CSELECT_B64:
8439 lowerSelect(Worklist, Inst, MDT);
8440 Inst.eraseFromParent();
8441 return;
8442 case AMDGPU::S_CMP_EQ_I32:
8443 case AMDGPU::S_CMP_LG_I32:
8444 case AMDGPU::S_CMP_GT_I32:
8445 case AMDGPU::S_CMP_GE_I32:
8446 case AMDGPU::S_CMP_LT_I32:
8447 case AMDGPU::S_CMP_LE_I32:
8448 case AMDGPU::S_CMP_EQ_U32:
8449 case AMDGPU::S_CMP_LG_U32:
8450 case AMDGPU::S_CMP_GT_U32:
8451 case AMDGPU::S_CMP_GE_U32:
8452 case AMDGPU::S_CMP_LT_U32:
8453 case AMDGPU::S_CMP_LE_U32:
8454 case AMDGPU::S_CMP_EQ_U64:
8455 case AMDGPU::S_CMP_LG_U64:
8456 case AMDGPU::S_CMP_LT_F32:
8457 case AMDGPU::S_CMP_EQ_F32:
8458 case AMDGPU::S_CMP_LE_F32:
8459 case AMDGPU::S_CMP_GT_F32:
8460 case AMDGPU::S_CMP_LG_F32:
8461 case AMDGPU::S_CMP_GE_F32:
8462 case AMDGPU::S_CMP_O_F32:
8463 case AMDGPU::S_CMP_U_F32:
8464 case AMDGPU::S_CMP_NGE_F32:
8465 case AMDGPU::S_CMP_NLG_F32:
8466 case AMDGPU::S_CMP_NGT_F32:
8467 case AMDGPU::S_CMP_NLE_F32:
8468 case AMDGPU::S_CMP_NEQ_F32:
8469 case AMDGPU::S_CMP_NLT_F32: {
8470 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8471 auto NewInstr =
8472 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8473 .setMIFlags(Inst.getFlags());
8474 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8475 0) {
8476 NewInstr
8477 .addImm(0) // src0_modifiers
8478 .add(Inst.getOperand(0)) // src0
8479 .addImm(0) // src1_modifiers
8480 .add(Inst.getOperand(1)) // src1
8481 .addImm(0); // clamp
8482 } else {
8483 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8484 }
8485 legalizeOperands(*NewInstr, MDT);
8486 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8487 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8488 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8489 Inst.eraseFromParent();
8490 return;
8491 }
8492 case AMDGPU::S_CMP_LT_F16:
8493 case AMDGPU::S_CMP_EQ_F16:
8494 case AMDGPU::S_CMP_LE_F16:
8495 case AMDGPU::S_CMP_GT_F16:
8496 case AMDGPU::S_CMP_LG_F16:
8497 case AMDGPU::S_CMP_GE_F16:
8498 case AMDGPU::S_CMP_O_F16:
8499 case AMDGPU::S_CMP_U_F16:
8500 case AMDGPU::S_CMP_NGE_F16:
8501 case AMDGPU::S_CMP_NLG_F16:
8502 case AMDGPU::S_CMP_NGT_F16:
8503 case AMDGPU::S_CMP_NLE_F16:
8504 case AMDGPU::S_CMP_NEQ_F16:
8505 case AMDGPU::S_CMP_NLT_F16: {
8506 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8507 auto NewInstr =
8508 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8509 .setMIFlags(Inst.getFlags());
8510 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8511 NewInstr
8512 .addImm(0) // src0_modifiers
8513 .add(Inst.getOperand(0)) // src0
8514 .addImm(0) // src1_modifiers
8515 .add(Inst.getOperand(1)) // src1
8516 .addImm(0); // clamp
8517 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8518 NewInstr.addImm(0); // op_sel0
8519 } else {
8520 NewInstr
8521 .add(Inst.getOperand(0))
8522 .add(Inst.getOperand(1));
8523 }
8524 legalizeOperands(*NewInstr, MDT);
8525 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8526 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8527 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8528 Inst.eraseFromParent();
8529 return;
8530 }
8531 case AMDGPU::S_CVT_HI_F32_F16: {
8532 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8533 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8534 if (ST.useRealTrue16Insts()) {
8535 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8536 .add(Inst.getOperand(1));
8537 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8538 .addImm(0) // src0_modifiers
8539 .addReg(TmpReg, {}, AMDGPU::hi16)
8540 .addImm(0) // clamp
8541 .addImm(0) // omod
8542 .addImm(0); // op_sel0
8543 } else {
8544 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8545 .addImm(16)
8546 .add(Inst.getOperand(1));
8547 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8548 .addImm(0) // src0_modifiers
8549 .addReg(TmpReg)
8550 .addImm(0) // clamp
8551 .addImm(0); // omod
8552 }
8553
8554 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8555 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8556 Inst.eraseFromParent();
8557 return;
8558 }
8559 case AMDGPU::S_MINIMUM_F32:
8560 case AMDGPU::S_MAXIMUM_F32: {
8561 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8562 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8563 .addImm(0) // src0_modifiers
8564 .add(Inst.getOperand(1))
8565 .addImm(0) // src1_modifiers
8566 .add(Inst.getOperand(2))
8567 .addImm(0) // clamp
8568 .addImm(0); // omod
8569 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8570
8571 legalizeOperands(*NewInstr, MDT);
8572 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8573 Inst.eraseFromParent();
8574 return;
8575 }
8576 case AMDGPU::S_MINIMUM_F16:
8577 case AMDGPU::S_MAXIMUM_F16: {
8578 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8579 ? &AMDGPU::VGPR_16RegClass
8580 : &AMDGPU::VGPR_32RegClass);
8581 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8582 .addImm(0) // src0_modifiers
8583 .add(Inst.getOperand(1))
8584 .addImm(0) // src1_modifiers
8585 .add(Inst.getOperand(2))
8586 .addImm(0) // clamp
8587 .addImm(0) // omod
8588 .addImm(0); // opsel0
8589 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8590 legalizeOperands(*NewInstr, MDT);
8591 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8592 Inst.eraseFromParent();
8593 return;
8594 }
8595 case AMDGPU::V_S_EXP_F16_e64:
8596 case AMDGPU::V_S_LOG_F16_e64:
8597 case AMDGPU::V_S_RCP_F16_e64:
8598 case AMDGPU::V_S_RSQ_F16_e64:
8599 case AMDGPU::V_S_SQRT_F16_e64: {
8600 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8601 ? &AMDGPU::VGPR_16RegClass
8602 : &AMDGPU::VGPR_32RegClass);
8603 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8604 .add(Inst.getOperand(1)) // src0_modifiers
8605 .add(Inst.getOperand(2))
8606 .add(Inst.getOperand(3)) // clamp
8607 .add(Inst.getOperand(4)) // omod
8608 .setMIFlags(Inst.getFlags());
8609 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8610 NewInstr.addImm(0); // opsel0
8611 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8612 legalizeOperands(*NewInstr, MDT);
8613 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8614 Inst.eraseFromParent();
8615 return;
8616 }
8617 }
8618
8619 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8620 // We cannot move this instruction to the VALU, so we should try to
8621 // legalize its operands instead.
8622 legalizeOperands(Inst, MDT);
8623 return;
8624 }
8625 // Handle converting generic instructions like COPY-to-SGPR into
8626 // COPY-to-VGPR.
8627 if (NewOpcode == Opcode) {
8628 Register DstReg = Inst.getOperand(0).getReg();
8629 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8630
8631 if (Inst.isCopy() && DstReg.isPhysical() &&
8632 Inst.getOperand(1).getReg().isVirtual()) {
8633 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8634 V2SPhyCopiesToErase);
8635 return;
8636 }
8637
8638 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8639 Register NewDstReg = Inst.getOperand(1).getReg();
8640 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8641 if (const TargetRegisterClass *CommonRC =
8642 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8643 // Instead of creating a copy where src and dst are the same register
8644 // class, we just replace all uses of dst with src. These kinds of
8645 // copies interfere with the heuristics MachineSink uses to decide
8646 // whether or not to split a critical edge. Since the pass assumes
8647 // that copies will end up as machine instructions and not be
8648 // eliminated.
8649 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8650 unsigned SrcSubReg = Inst.getOperand(1).getSubReg();
8651 for (MachineOperand &UseMO :
8652 make_early_inc_range(MRI.use_operands(DstReg))) {
8653 UseMO.setSubReg(
8654 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8655 UseMO.setReg(NewDstReg);
8656 }
8657 MRI.clearKillFlags(NewDstReg);
8658
8659 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8660 llvm_unreachable("failed to constrain register");
8661
8662 Inst.eraseFromParent();
8663
8664 for (MachineOperand &UseMO :
8665 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8666 MachineInstr &UseMI = *UseMO.getParent();
8667
8668 // Legalize t16 operands since replaceReg is called after
8669 // addUsersToVALU.
8671
8672 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
8673 if (const TargetRegisterClass *OpRC =
8674 getRegClass(UseMI.getDesc(), OpIdx))
8675 MRI.constrainRegClass(NewDstReg, OpRC);
8676 }
8677
8678 return;
8679 }
8680 }
8681
8682 // If this is a v2s copy between 16bit and 32bit reg,
8683 // replace vgpr copy to reg_sequence/extract_subreg
8684 // This can be remove after we have sgpr16 in place
8685 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
8686 Inst.getOperand(1).getReg().isVirtual() &&
8687 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
8688 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
8689 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8690 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8691 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8692 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8693 get(AMDGPU::IMPLICIT_DEF), Undef);
8694 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8695 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8696 .addReg(Inst.getOperand(1).getReg())
8697 .addImm(AMDGPU::lo16)
8698 .addReg(Undef)
8699 .addImm(AMDGPU::hi16);
8700 Inst.eraseFromParent();
8701 MRI.replaceRegWith(DstReg, NewDstReg);
8702 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8703 return;
8704 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8705 AMDGPU::lo16)) {
8706 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
8707 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8708 MRI.replaceRegWith(DstReg, NewDstReg);
8709 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8710 return;
8711 }
8712 }
8713
8714 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8715 MRI.replaceRegWith(DstReg, NewDstReg);
8716 legalizeOperands(Inst, MDT);
8717 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8718 return;
8719 }
8720
8721 // Use the new VALU Opcode.
8722 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
8723 .setMIFlags(Inst.getFlags());
8724 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
8725 // Intersperse VOP3 modifiers among the SALU operands.
8726 NewInstr->addOperand(Inst.getOperand(0));
8727 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8728 AMDGPU::OpName::src0_modifiers) >= 0)
8729 NewInstr.addImm(0);
8730 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
8731 const MachineOperand &Src = Inst.getOperand(1);
8732 NewInstr->addOperand(Src);
8733 }
8734
8735 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8736 // We are converting these to a BFE, so we need to add the missing
8737 // operands for the size and offset.
8738 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8739 NewInstr.addImm(0);
8740 NewInstr.addImm(Size);
8741 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8742 // The VALU version adds the second operand to the result, so insert an
8743 // extra 0 operand.
8744 NewInstr.addImm(0);
8745 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8746 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
8747 // If we need to move this to VGPRs, we need to unpack the second
8748 // operand back into the 2 separate ones for bit offset and width.
8749 assert(OffsetWidthOp.isImm() &&
8750 "Scalar BFE is only implemented for constant width and offset");
8751 uint32_t Imm = OffsetWidthOp.getImm();
8752
8753 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
8754 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
8755 NewInstr.addImm(Offset);
8756 NewInstr.addImm(BitWidth);
8757 } else {
8758 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8759 AMDGPU::OpName::src1_modifiers) >= 0)
8760 NewInstr.addImm(0);
8761 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8762 NewInstr->addOperand(Inst.getOperand(2));
8763 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8764 AMDGPU::OpName::src2_modifiers) >= 0)
8765 NewInstr.addImm(0);
8766 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8767 NewInstr->addOperand(Inst.getOperand(3));
8768 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8769 NewInstr.addImm(0);
8770 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8771 NewInstr.addImm(0);
8772 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8773 NewInstr.addImm(0);
8774 }
8775 } else {
8776 // Just copy the SALU operands.
8777 for (const MachineOperand &Op : Inst.explicit_operands())
8778 NewInstr->addOperand(Op);
8779 }
8780
8781 // Remove any references to SCC. Vector instructions can't read from it, and
8782 // We're just about to add the implicit use / defs of VCC, and we don't want
8783 // both.
8784 for (MachineOperand &Op : Inst.implicit_operands()) {
8785 if (Op.getReg() == AMDGPU::SCC) {
8786 // Only propagate through live-def of SCC.
8787 if (Op.isDef() && !Op.isDead())
8788 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
8789 if (Op.isUse())
8790 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8791 }
8792 }
8793 Inst.eraseFromParent();
8794 Register NewDstReg;
8795 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8796 Register DstReg = NewInstr->getOperand(0).getReg();
8797 assert(DstReg.isVirtual());
8798 // Update the destination register class.
8799 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
8800 assert(NewDstRC);
8801 NewDstReg = MRI.createVirtualRegister(NewDstRC);
8802 MRI.replaceRegWith(DstReg, NewDstReg);
8803 }
8804 fixImplicitOperands(*NewInstr);
8805
8806 // Legalize the operands
8807 legalizeOperands(*NewInstr, MDT);
8808 if (NewDstReg)
8809 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8810}
8811
8812// Add/sub require special handling to deal with carry outs.
8813std::pair<bool, MachineBasicBlock *>
8814SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
8815 MachineDominatorTree *MDT) const {
8816 if (ST.hasAddNoCarryInsts()) {
8817 // Assume there is no user of scc since we don't select this in that case.
8818 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
8819 // is used.
8820
8821 MachineBasicBlock &MBB = *Inst.getParent();
8822 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8823
8824 Register OldDstReg = Inst.getOperand(0).getReg();
8825 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8826
8827 unsigned Opc = Inst.getOpcode();
8828 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
8829
8830 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
8831 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8832
8833 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
8834 Inst.removeOperand(3);
8835
8836 Inst.setDesc(get(NewOpc));
8837 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
8838 Inst.addImplicitDefUseOperands(*MBB.getParent());
8839 MRI.replaceRegWith(OldDstReg, ResultReg);
8840 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
8841
8842 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8843 return std::pair(true, NewBB);
8844 }
8845
8846 return std::pair(false, nullptr);
8847}
8848
8849void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
8850 MachineDominatorTree *MDT) const {
8851
8852 MachineBasicBlock &MBB = *Inst.getParent();
8853 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8854 MachineBasicBlock::iterator MII = Inst;
8855 const DebugLoc &DL = Inst.getDebugLoc();
8856
8857 MachineOperand &Dest = Inst.getOperand(0);
8858 MachineOperand &Src0 = Inst.getOperand(1);
8859 MachineOperand &Src1 = Inst.getOperand(2);
8860 MachineOperand &Cond = Inst.getOperand(3);
8861
8862 Register CondReg = Cond.getReg();
8863 bool IsSCC = (CondReg == AMDGPU::SCC);
8864
8865 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
8866 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
8867 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
8868 // output directly into the V_CNDMASK.
8869 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
8870 (Src1.getImm() == 0)) {
8871 for (MachineOperand &UseMO :
8873 MachineInstr &UseMI = *UseMO.getParent();
8874 switch (UseMI.getOpcode()) {
8875 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8876 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8877 case AMDGPU::V_CNDMASK_B16_t16_e32:
8878 case AMDGPU::V_CNDMASK_B16_t16_e64:
8879 case AMDGPU::V_CNDMASK_B32_e32:
8880 case AMDGPU::V_CNDMASK_B32_e64:
8881 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8882 if (UseMO.isImplicit() ||
8883 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
8884 UseMO.setReg(CondReg);
8885 }
8886 }
8887 if (MRI.use_nodbg_empty(Dest.getReg()))
8888 return;
8889 }
8890
8891 Register NewCondReg = CondReg;
8892 if (IsSCC) {
8893 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
8894 NewCondReg = MRI.createVirtualRegister(TC);
8895
8896 // Now look for the closest SCC def if it is a copy
8897 // replacing the CondReg with the COPY source register
8898 bool CopyFound = false;
8899 for (MachineInstr &CandI :
8901 Inst.getParent()->rend())) {
8902 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
8903 -1) {
8904 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
8905 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
8906 .addReg(CandI.getOperand(1).getReg());
8907 CopyFound = true;
8908 }
8909 break;
8910 }
8911 }
8912 if (!CopyFound) {
8913 // SCC def is not a copy
8914 // Insert a trivial select instead of creating a copy, because a copy from
8915 // SCC would semantically mean just copying a single bit, but we may need
8916 // the result to be a vector condition mask that needs preserving.
8917 unsigned Opcode =
8918 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
8919 auto NewSelect =
8920 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
8921 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
8922 }
8923 }
8924
8925 Register NewDestReg = MRI.createVirtualRegister(
8926 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
8927 MachineInstr *NewInst;
8928 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
8929 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
8930 .addImm(0)
8931 .add(Src1) // False
8932 .addImm(0)
8933 .add(Src0) // True
8934 .addReg(NewCondReg);
8935 } else {
8936 NewInst =
8937 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
8938 .add(Src1) // False
8939 .add(Src0) // True
8940 .addReg(NewCondReg);
8941 }
8942 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
8943 legalizeOperands(*NewInst, MDT);
8944 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
8945}
8946
8947void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
8948 MachineInstr &Inst) const {
8949 MachineBasicBlock &MBB = *Inst.getParent();
8950 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8951 MachineBasicBlock::iterator MII = Inst;
8952 const DebugLoc &DL = Inst.getDebugLoc();
8953
8954 MachineOperand &Dest = Inst.getOperand(0);
8955 MachineOperand &Src = Inst.getOperand(1);
8956 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8957 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8958
8959 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8960 : AMDGPU::V_SUB_CO_U32_e32;
8961
8962 BuildMI(MBB, MII, DL, get(SubOp), TmpReg)
8963 .addImm(0)
8964 .addReg(Src.getReg());
8965
8966 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
8967 .addReg(Src.getReg())
8968 .addReg(TmpReg);
8969
8970 MRI.replaceRegWith(Dest.getReg(), ResultReg);
8971 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8972}
8973
8974void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
8975 MachineInstr &Inst) const {
8976 MachineBasicBlock &MBB = *Inst.getParent();
8977 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8978 MachineBasicBlock::iterator MII = Inst;
8979 const DebugLoc &DL = Inst.getDebugLoc();
8980
8981 MachineOperand &Dest = Inst.getOperand(0);
8982 MachineOperand &Src1 = Inst.getOperand(1);
8983 MachineOperand &Src2 = Inst.getOperand(2);
8984 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8985 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8986 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8987
8988 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8989 : AMDGPU::V_SUB_CO_U32_e32;
8990
8991 BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
8992 .addReg(Src1.getReg())
8993 .addReg(Src2.getReg());
8994
8995 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
8996
8997 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
8998 .addReg(SubResultReg)
8999 .addReg(TmpReg);
9000
9001 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9002 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9003}
9004
9005void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
9006 MachineInstr &Inst) const {
9007 MachineBasicBlock &MBB = *Inst.getParent();
9008 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9009 MachineBasicBlock::iterator MII = Inst;
9010 const DebugLoc &DL = Inst.getDebugLoc();
9011
9012 MachineOperand &Dest = Inst.getOperand(0);
9013 MachineOperand &Src0 = Inst.getOperand(1);
9014 MachineOperand &Src1 = Inst.getOperand(2);
9015
9016 if (ST.hasDLInsts()) {
9017 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9018 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
9019 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
9020
9021 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
9022 .add(Src0)
9023 .add(Src1);
9024
9025 MRI.replaceRegWith(Dest.getReg(), NewDest);
9026 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9027 } else {
9028 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
9029 // invert either source and then perform the XOR. If either source is a
9030 // scalar register, then we can leave the inversion on the scalar unit to
9031 // achieve a better distribution of scalar and vector instructions.
9032 bool Src0IsSGPR = Src0.isReg() &&
9033 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
9034 bool Src1IsSGPR = Src1.isReg() &&
9035 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
9036 MachineInstr *Xor;
9037 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9038 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9039
9040 // Build a pair of scalar instructions and add them to the work list.
9041 // The next iteration over the work list will lower these to the vector
9042 // unit as necessary.
9043 if (Src0IsSGPR) {
9044 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
9045 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9046 .addReg(Temp)
9047 .add(Src1);
9048 } else if (Src1IsSGPR) {
9049 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
9050 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9051 .add(Src0)
9052 .addReg(Temp);
9053 } else {
9054 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
9055 .add(Src0)
9056 .add(Src1);
9057 MachineInstr *Not =
9058 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
9059 Worklist.insert(Not);
9060 }
9061
9062 MRI.replaceRegWith(Dest.getReg(), NewDest);
9063
9064 Worklist.insert(Xor);
9065
9066 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9067 }
9068}
9069
9070void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
9071 MachineInstr &Inst,
9072 unsigned Opcode) const {
9073 MachineBasicBlock &MBB = *Inst.getParent();
9074 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9075 MachineBasicBlock::iterator MII = Inst;
9076 const DebugLoc &DL = Inst.getDebugLoc();
9077
9078 MachineOperand &Dest = Inst.getOperand(0);
9079 MachineOperand &Src0 = Inst.getOperand(1);
9080 MachineOperand &Src1 = Inst.getOperand(2);
9081
9082 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9083 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9084
9085 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
9086 .add(Src0)
9087 .add(Src1);
9088
9089 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
9090 .addReg(Interm);
9091
9092 Worklist.insert(&Op);
9093 Worklist.insert(&Not);
9094
9095 MRI.replaceRegWith(Dest.getReg(), NewDest);
9096 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9097}
9098
9099void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
9100 MachineInstr &Inst,
9101 unsigned Opcode) const {
9102 MachineBasicBlock &MBB = *Inst.getParent();
9103 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9104 MachineBasicBlock::iterator MII = Inst;
9105 const DebugLoc &DL = Inst.getDebugLoc();
9106
9107 MachineOperand &Dest = Inst.getOperand(0);
9108 MachineOperand &Src0 = Inst.getOperand(1);
9109 MachineOperand &Src1 = Inst.getOperand(2);
9110
9111 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9112 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9113
9114 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
9115 .add(Src1);
9116
9117 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
9118 .add(Src0)
9119 .addReg(Interm);
9120
9121 Worklist.insert(&Not);
9122 Worklist.insert(&Op);
9123
9124 MRI.replaceRegWith(Dest.getReg(), NewDest);
9125 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9126}
9127
9128void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
9129 MachineInstr &Inst, unsigned Opcode,
9130 bool Swap) const {
9131 MachineBasicBlock &MBB = *Inst.getParent();
9132 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9133
9134 MachineOperand &Dest = Inst.getOperand(0);
9135 MachineOperand &Src0 = Inst.getOperand(1);
9136 const DebugLoc &DL = Inst.getDebugLoc();
9137
9138 MachineBasicBlock::iterator MII = Inst;
9139
9140 const MCInstrDesc &InstDesc = get(Opcode);
9141 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9142 MRI.getRegClass(Src0.getReg()) :
9143 &AMDGPU::SGPR_32RegClass;
9144
9145 const TargetRegisterClass *Src0SubRC =
9146 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9147
9148 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9149 AMDGPU::sub0, Src0SubRC);
9150
9151 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9152 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9153 const TargetRegisterClass *NewDestSubRC =
9154 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9155
9156 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9157 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
9158
9159 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9160 AMDGPU::sub1, Src0SubRC);
9161
9162 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9163 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
9164
9165 if (Swap)
9166 std::swap(DestSub0, DestSub1);
9167
9168 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9169 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9170 .addReg(DestSub0)
9171 .addImm(AMDGPU::sub0)
9172 .addReg(DestSub1)
9173 .addImm(AMDGPU::sub1);
9174
9175 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9176
9177 Worklist.insert(&LoHalf);
9178 Worklist.insert(&HiHalf);
9179
9180 // We don't need to legalizeOperands here because for a single operand, src0
9181 // will support any kind of input.
9182
9183 // Move all users of this moved value.
9184 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9185}
9186
9187// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9188// split the s_mul_u64 in 32-bit vector multiplications.
9189void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9190 MachineInstr &Inst,
9191 MachineDominatorTree *MDT) const {
9192 MachineBasicBlock &MBB = *Inst.getParent();
9193 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9194
9195 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9196 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9197 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9198
9199 MachineOperand &Dest = Inst.getOperand(0);
9200 MachineOperand &Src0 = Inst.getOperand(1);
9201 MachineOperand &Src1 = Inst.getOperand(2);
9202 const DebugLoc &DL = Inst.getDebugLoc();
9203 MachineBasicBlock::iterator MII = Inst;
9204
9205 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9206 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9207 const TargetRegisterClass *Src0SubRC =
9208 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9209 if (RI.isSGPRClass(Src0SubRC))
9210 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9211 const TargetRegisterClass *Src1SubRC =
9212 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9213 if (RI.isSGPRClass(Src1SubRC))
9214 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9215
9216 // First, we extract the low 32-bit and high 32-bit values from each of the
9217 // operands.
9218 MachineOperand Op0L =
9219 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9220 MachineOperand Op1L =
9221 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9222 MachineOperand Op0H =
9223 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9224 MachineOperand Op1H =
9225 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9226
9227 // The multilication is done as follows:
9228 //
9229 // Op1H Op1L
9230 // * Op0H Op0L
9231 // --------------------
9232 // Op1H*Op0L Op1L*Op0L
9233 // + Op1H*Op0H Op1L*Op0H
9234 // -----------------------------------------
9235 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9236 //
9237 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9238 // value and that would overflow.
9239 // The low 32-bit value is Op1L*Op0L.
9240 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9241
9242 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9243 MachineInstr *Op1L_Op0H =
9244 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9245 .add(Op1L)
9246 .add(Op0H);
9247
9248 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9249 MachineInstr *Op1H_Op0L =
9250 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9251 .add(Op1H)
9252 .add(Op0L);
9253
9254 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9255 MachineInstr *Carry =
9256 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9257 .add(Op1L)
9258 .add(Op0L);
9259
9260 MachineInstr *LoHalf =
9261 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9262 .add(Op1L)
9263 .add(Op0L);
9264
9265 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9266 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9267 .addReg(Op1L_Op0H_Reg)
9268 .addReg(Op1H_Op0L_Reg);
9269
9270 MachineInstr *HiHalf =
9271 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9272 .addReg(AddReg)
9273 .addReg(CarryReg);
9274
9275 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9276 .addReg(DestSub0)
9277 .addImm(AMDGPU::sub0)
9278 .addReg(DestSub1)
9279 .addImm(AMDGPU::sub1);
9280
9281 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9282
9283 // Try to legalize the operands in case we need to swap the order to keep it
9284 // valid.
9285 legalizeOperands(*Op1L_Op0H, MDT);
9286 legalizeOperands(*Op1H_Op0L, MDT);
9287 legalizeOperands(*Carry, MDT);
9288 legalizeOperands(*LoHalf, MDT);
9289 legalizeOperands(*Add, MDT);
9290 legalizeOperands(*HiHalf, MDT);
9291
9292 // Move all users of this moved value.
9293 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9294}
9295
9296// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9297// multiplications.
9298void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9299 MachineInstr &Inst,
9300 MachineDominatorTree *MDT) const {
9301 MachineBasicBlock &MBB = *Inst.getParent();
9302 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9303
9304 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9305 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9306 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9307
9308 MachineOperand &Dest = Inst.getOperand(0);
9309 MachineOperand &Src0 = Inst.getOperand(1);
9310 MachineOperand &Src1 = Inst.getOperand(2);
9311 const DebugLoc &DL = Inst.getDebugLoc();
9312 MachineBasicBlock::iterator MII = Inst;
9313
9314 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9315 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9316 const TargetRegisterClass *Src0SubRC =
9317 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9318 if (RI.isSGPRClass(Src0SubRC))
9319 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9320 const TargetRegisterClass *Src1SubRC =
9321 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9322 if (RI.isSGPRClass(Src1SubRC))
9323 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9324
9325 // First, we extract the low 32-bit and high 32-bit values from each of the
9326 // operands.
9327 MachineOperand Op0L =
9328 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9329 MachineOperand Op1L =
9330 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9331
9332 unsigned Opc = Inst.getOpcode();
9333 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9334 ? AMDGPU::V_MUL_HI_U32_e64
9335 : AMDGPU::V_MUL_HI_I32_e64;
9336 MachineInstr *HiHalf =
9337 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9338
9339 MachineInstr *LoHalf =
9340 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9341 .add(Op1L)
9342 .add(Op0L);
9343
9344 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9345 .addReg(DestSub0)
9346 .addImm(AMDGPU::sub0)
9347 .addReg(DestSub1)
9348 .addImm(AMDGPU::sub1);
9349
9350 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9351
9352 // Try to legalize the operands in case we need to swap the order to keep it
9353 // valid.
9354 legalizeOperands(*HiHalf, MDT);
9355 legalizeOperands(*LoHalf, MDT);
9356
9357 // Move all users of this moved value.
9358 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9359}
9360
9361void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9362 MachineInstr &Inst, unsigned Opcode,
9363 MachineDominatorTree *MDT) const {
9364 MachineBasicBlock &MBB = *Inst.getParent();
9365 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9366
9367 MachineOperand &Dest = Inst.getOperand(0);
9368 MachineOperand &Src0 = Inst.getOperand(1);
9369 MachineOperand &Src1 = Inst.getOperand(2);
9370 const DebugLoc &DL = Inst.getDebugLoc();
9371
9372 MachineBasicBlock::iterator MII = Inst;
9373
9374 const MCInstrDesc &InstDesc = get(Opcode);
9375 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9376 MRI.getRegClass(Src0.getReg()) :
9377 &AMDGPU::SGPR_32RegClass;
9378
9379 const TargetRegisterClass *Src0SubRC =
9380 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9381 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9382 MRI.getRegClass(Src1.getReg()) :
9383 &AMDGPU::SGPR_32RegClass;
9384
9385 const TargetRegisterClass *Src1SubRC =
9386 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9387
9388 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9389 AMDGPU::sub0, Src0SubRC);
9390 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9391 AMDGPU::sub0, Src1SubRC);
9392 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9393 AMDGPU::sub1, Src0SubRC);
9394 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9395 AMDGPU::sub1, Src1SubRC);
9396
9397 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9398 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9399 const TargetRegisterClass *NewDestSubRC =
9400 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9401
9402 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9403 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9404 .add(SrcReg0Sub0)
9405 .add(SrcReg1Sub0);
9406
9407 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9408 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9409 .add(SrcReg0Sub1)
9410 .add(SrcReg1Sub1);
9411
9412 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9413 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9414 .addReg(DestSub0)
9415 .addImm(AMDGPU::sub0)
9416 .addReg(DestSub1)
9417 .addImm(AMDGPU::sub1);
9418
9419 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9420
9421 Worklist.insert(&LoHalf);
9422 Worklist.insert(&HiHalf);
9423
9424 // Move all users of this moved value.
9425 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9426}
9427
9428void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9429 MachineInstr &Inst,
9430 MachineDominatorTree *MDT) const {
9431 MachineBasicBlock &MBB = *Inst.getParent();
9432 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9433
9434 MachineOperand &Dest = Inst.getOperand(0);
9435 MachineOperand &Src0 = Inst.getOperand(1);
9436 MachineOperand &Src1 = Inst.getOperand(2);
9437 const DebugLoc &DL = Inst.getDebugLoc();
9438
9439 MachineBasicBlock::iterator MII = Inst;
9440
9441 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9442
9443 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9444
9445 MachineOperand* Op0;
9446 MachineOperand* Op1;
9447
9448 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9449 Op0 = &Src0;
9450 Op1 = &Src1;
9451 } else {
9452 Op0 = &Src1;
9453 Op1 = &Src0;
9454 }
9455
9456 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9457 .add(*Op0);
9458
9459 Register NewDest = MRI.createVirtualRegister(DestRC);
9460
9461 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9462 .addReg(Interm)
9463 .add(*Op1);
9464
9465 MRI.replaceRegWith(Dest.getReg(), NewDest);
9466
9467 Worklist.insert(&Xor);
9468}
9469
9470void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9471 MachineInstr &Inst) const {
9472 MachineBasicBlock &MBB = *Inst.getParent();
9473 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9474
9475 MachineBasicBlock::iterator MII = Inst;
9476 const DebugLoc &DL = Inst.getDebugLoc();
9477
9478 MachineOperand &Dest = Inst.getOperand(0);
9479 MachineOperand &Src = Inst.getOperand(1);
9480
9481 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9482 const TargetRegisterClass *SrcRC = Src.isReg() ?
9483 MRI.getRegClass(Src.getReg()) :
9484 &AMDGPU::SGPR_32RegClass;
9485
9486 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9487 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9488
9489 const TargetRegisterClass *SrcSubRC =
9490 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9491
9492 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9493 AMDGPU::sub0, SrcSubRC);
9494 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9495 AMDGPU::sub1, SrcSubRC);
9496
9497 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9498
9499 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9500
9501 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9502
9503 // We don't need to legalize operands here. src0 for either instruction can be
9504 // an SGPR, and the second input is unused or determined here.
9505 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9506}
9507
9508void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9509 MachineInstr &Inst) const {
9510 MachineBasicBlock &MBB = *Inst.getParent();
9511 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9512 MachineBasicBlock::iterator MII = Inst;
9513 const DebugLoc &DL = Inst.getDebugLoc();
9514
9515 MachineOperand &Dest = Inst.getOperand(0);
9516 uint32_t Imm = Inst.getOperand(2).getImm();
9517 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9518 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9519
9520 (void) Offset;
9521
9522 // Only sext_inreg cases handled.
9523 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9524 Offset == 0 && "Not implemented");
9525
9526 if (BitWidth < 32) {
9527 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9528 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9529 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9530
9531 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9532 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9533 .addImm(0)
9534 .addImm(BitWidth);
9535
9536 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9537 .addImm(31)
9538 .addReg(MidRegLo);
9539
9540 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9541 .addReg(MidRegLo)
9542 .addImm(AMDGPU::sub0)
9543 .addReg(MidRegHi)
9544 .addImm(AMDGPU::sub1);
9545
9546 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9547 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9548 return;
9549 }
9550
9551 MachineOperand &Src = Inst.getOperand(1);
9552 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9553 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9554
9555 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9556 .addImm(31)
9557 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9558
9559 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9560 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9561 .addImm(AMDGPU::sub0)
9562 .addReg(TmpReg)
9563 .addImm(AMDGPU::sub1);
9564
9565 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9566 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9567}
9568
9569void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9570 MachineInstr &Inst, unsigned Opcode,
9571 MachineDominatorTree *MDT) const {
9572 // (S_FLBIT_I32_B64 hi:lo) ->
9573 // -> (umin (V_FFBH_U32_e32 hi), (uaddsat (V_FFBH_U32_e32 lo), 32))
9574 // (S_FF1_I32_B64 hi:lo) ->
9575 // ->(umin (uaddsat (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9576
9577 MachineBasicBlock &MBB = *Inst.getParent();
9578 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9579 MachineBasicBlock::iterator MII = Inst;
9580 const DebugLoc &DL = Inst.getDebugLoc();
9581
9582 MachineOperand &Dest = Inst.getOperand(0);
9583 MachineOperand &Src = Inst.getOperand(1);
9584
9585 const MCInstrDesc &InstDesc = get(Opcode);
9586
9587 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9588 unsigned OpcodeAdd = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64
9589 : AMDGPU::V_ADD_CO_U32_e32;
9590
9591 const TargetRegisterClass *SrcRC =
9592 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9593 const TargetRegisterClass *SrcSubRC =
9594 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9595
9596 MachineOperand SrcRegSub0 =
9597 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9598 MachineOperand SrcRegSub1 =
9599 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9600
9601 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9602 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9603 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9604 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9605
9606 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9607
9608 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9609
9610 BuildMI(MBB, MII, DL, get(OpcodeAdd), MidReg3)
9611 .addReg(IsCtlz ? MidReg1 : MidReg2)
9612 .addImm(32)
9613 .addImm(1); // enable clamp
9614
9615 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9616 .addReg(MidReg3)
9617 .addReg(IsCtlz ? MidReg2 : MidReg1);
9618
9619 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9620
9621 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9622}
9623
9624void SIInstrInfo::addUsersToMoveToVALUWorklist(
9625 Register DstReg, MachineRegisterInfo &MRI,
9626 SIInstrWorklist &Worklist) const {
9627 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9628 MachineInstr &UseMI = *MO.getParent();
9629
9630 unsigned OpNo = 0;
9631
9632 switch (UseMI.getOpcode()) {
9633 case AMDGPU::COPY:
9634 case AMDGPU::WQM:
9635 case AMDGPU::SOFT_WQM:
9636 case AMDGPU::STRICT_WWM:
9637 case AMDGPU::STRICT_WQM:
9638 case AMDGPU::REG_SEQUENCE:
9639 case AMDGPU::PHI:
9640 case AMDGPU::INSERT_SUBREG:
9641 break;
9642 default:
9643 OpNo = MO.getOperandNo();
9644 break;
9645 }
9646
9647 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9648 MRI.constrainRegClass(DstReg, OpRC);
9649
9650 if (!RI.hasVectorRegisters(OpRC))
9651 Worklist.insert(&UseMI);
9652 else
9653 // Legalization could change user list.
9654 legalizeOperandsVALUt16(UseMI, OpNo, MRI);
9655 }
9656}
9657
9658void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
9660 MachineInstr &Inst) const {
9661 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9662 MachineBasicBlock *MBB = Inst.getParent();
9663 MachineOperand &Src0 = Inst.getOperand(1);
9664 MachineOperand &Src1 = Inst.getOperand(2);
9665 const DebugLoc &DL = Inst.getDebugLoc();
9666
9667 if (ST.useRealTrue16Insts()) {
9668 Register SrcReg0, SrcReg1;
9669 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
9670 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9671 BuildMI(*MBB, Inst, DL,
9672 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9673 .add(Src0);
9674 } else {
9675 SrcReg0 = Src0.getReg();
9676 }
9677
9678 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
9679 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9680 BuildMI(*MBB, Inst, DL,
9681 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9682 .add(Src1);
9683 } else {
9684 SrcReg1 = Src1.getReg();
9685 }
9686
9687 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
9688 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
9689
9690 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
9691 switch (Inst.getOpcode()) {
9692 case AMDGPU::S_PACK_LL_B32_B16:
9693 NewMI
9694 .addReg(SrcReg0, {},
9695 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9696 .addImm(AMDGPU::lo16)
9697 .addReg(SrcReg1, {},
9698 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9699 .addImm(AMDGPU::hi16);
9700 break;
9701 case AMDGPU::S_PACK_LH_B32_B16:
9702 NewMI
9703 .addReg(SrcReg0, {},
9704 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9705 .addImm(AMDGPU::lo16)
9706 .addReg(SrcReg1, {}, AMDGPU::hi16)
9707 .addImm(AMDGPU::hi16);
9708 break;
9709 case AMDGPU::S_PACK_HL_B32_B16:
9710 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9711 .addImm(AMDGPU::lo16)
9712 .addReg(SrcReg1, {},
9713 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9714 .addImm(AMDGPU::hi16);
9715 break;
9716 case AMDGPU::S_PACK_HH_B32_B16:
9717 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9718 .addImm(AMDGPU::lo16)
9719 .addReg(SrcReg1, {}, AMDGPU::hi16)
9720 .addImm(AMDGPU::hi16);
9721 break;
9722 default:
9723 llvm_unreachable("unhandled s_pack_* instruction");
9724 }
9725
9726 MachineOperand &Dest = Inst.getOperand(0);
9727 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9728 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9729 return;
9730 }
9731
9732 switch (Inst.getOpcode()) {
9733 case AMDGPU::S_PACK_LL_B32_B16: {
9734 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9735 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9736
9737 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
9738 // 0.
9739 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9740 .addImm(0xffff);
9741
9742 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
9743 .addReg(ImmReg, RegState::Kill)
9744 .add(Src0);
9745
9746 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9747 .add(Src1)
9748 .addImm(16)
9749 .addReg(TmpReg, RegState::Kill);
9750 break;
9751 }
9752 case AMDGPU::S_PACK_LH_B32_B16: {
9753 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9754 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9755 .addImm(0xffff);
9756 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
9757 .addReg(ImmReg, RegState::Kill)
9758 .add(Src0)
9759 .add(Src1);
9760 break;
9761 }
9762 case AMDGPU::S_PACK_HL_B32_B16: {
9763 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9764 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9765 .addImm(16)
9766 .add(Src0);
9767 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9768 .add(Src1)
9769 .addImm(16)
9770 .addReg(TmpReg, RegState::Kill);
9771 break;
9772 }
9773 case AMDGPU::S_PACK_HH_B32_B16: {
9774 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9775 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9776 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9777 .addImm(16)
9778 .add(Src0);
9779 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9780 .addImm(0xffff0000);
9781 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
9782 .add(Src1)
9783 .addReg(ImmReg, RegState::Kill)
9784 .addReg(TmpReg, RegState::Kill);
9785 break;
9786 }
9787 default:
9788 llvm_unreachable("unhandled s_pack_* instruction");
9789 }
9790
9791 MachineOperand &Dest = Inst.getOperand(0);
9792 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9793 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9794}
9795
9796void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
9797 MachineInstr &SCCDefInst,
9798 SIInstrWorklist &Worklist,
9799 Register NewCond) const {
9800
9801 // Ensure that def inst defines SCC, which is still live.
9802 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
9803 !Op.isDead() && Op.getParent() == &SCCDefInst);
9804 SmallVector<MachineInstr *, 4> CopyToDelete;
9805 // This assumes that all the users of SCC are in the same block
9806 // as the SCC def.
9807 for (MachineInstr &MI : // Skip the def inst itself.
9808 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
9809 SCCDefInst.getParent()->end())) {
9810 // Check if SCC is used first.
9811 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
9812 if (SCCIdx != -1) {
9813 if (MI.isCopy()) {
9814 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
9815 Register DestReg = MI.getOperand(0).getReg();
9816
9817 MRI.replaceRegWith(DestReg, NewCond);
9818 CopyToDelete.push_back(&MI);
9819 } else {
9820
9821 if (NewCond.isValid())
9822 MI.getOperand(SCCIdx).setReg(NewCond);
9823
9824 Worklist.insert(&MI);
9825 }
9826 }
9827 // Exit if we find another SCC def.
9828 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
9829 break;
9830 }
9831 for (auto &Copy : CopyToDelete)
9832 Copy->eraseFromParent();
9833}
9834
9835// Instructions that use SCC may be converted to VALU instructions. When that
9836// happens, the SCC register is changed to VCC_LO. The instruction that defines
9837// SCC must be changed to an instruction that defines VCC. This function makes
9838// sure that the instruction that defines SCC is added to the moveToVALU
9839// worklist.
9840void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
9841 SIInstrWorklist &Worklist) const {
9842 // Look for a preceding instruction that either defines VCC or SCC. If VCC
9843 // then there is nothing to do because the defining instruction has been
9844 // converted to a VALU already. If SCC then that instruction needs to be
9845 // converted to a VALU.
9846 for (MachineInstr &MI :
9847 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
9848 SCCUseInst->getParent()->rend())) {
9849 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
9850 break;
9851 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
9852 Worklist.insert(&MI);
9853 break;
9854 }
9855 }
9856}
9857
9858const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
9859 const MachineInstr &Inst) const {
9860 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
9861
9862 switch (Inst.getOpcode()) {
9863 // For target instructions, getOpRegClass just returns the virtual register
9864 // class associated with the operand, so we need to find an equivalent VGPR
9865 // register class in order to move the instruction to the VALU.
9866 case AMDGPU::COPY:
9867 case AMDGPU::PHI:
9868 case AMDGPU::REG_SEQUENCE:
9869 case AMDGPU::INSERT_SUBREG:
9870 case AMDGPU::WQM:
9871 case AMDGPU::SOFT_WQM:
9872 case AMDGPU::STRICT_WWM:
9873 case AMDGPU::STRICT_WQM: {
9874 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
9875 if (RI.isAGPRClass(SrcRC)) {
9876 if (RI.isAGPRClass(NewDstRC))
9877 return nullptr;
9878
9879 switch (Inst.getOpcode()) {
9880 case AMDGPU::PHI:
9881 case AMDGPU::REG_SEQUENCE:
9882 case AMDGPU::INSERT_SUBREG:
9883 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9884 break;
9885 default:
9886 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9887 }
9888
9889 if (!NewDstRC)
9890 return nullptr;
9891 } else {
9892 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9893 return nullptr;
9894
9895 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9896 if (!NewDstRC)
9897 return nullptr;
9898 }
9899
9900 return NewDstRC;
9901 }
9902 default:
9903 return NewDstRC;
9904 }
9905}
9906
9907// Find the one SGPR operand we are allowed to use.
9908Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
9909 int OpIndices[3]) const {
9910 const MCInstrDesc &Desc = MI.getDesc();
9911
9912 // Find the one SGPR operand we are allowed to use.
9913 //
9914 // First we need to consider the instruction's operand requirements before
9915 // legalizing. Some operands are required to be SGPRs, such as implicit uses
9916 // of VCC, but we are still bound by the constant bus requirement to only use
9917 // one.
9918 //
9919 // If the operand's class is an SGPR, we can never move it.
9920
9921 Register SGPRReg = findImplicitSGPRRead(MI);
9922 if (SGPRReg)
9923 return SGPRReg;
9924
9925 Register UsedSGPRs[3] = {Register()};
9926 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
9927
9928 for (unsigned i = 0; i < 3; ++i) {
9929 int Idx = OpIndices[i];
9930 if (Idx == -1)
9931 break;
9932
9933 const MachineOperand &MO = MI.getOperand(Idx);
9934 if (!MO.isReg())
9935 continue;
9936
9937 // Is this operand statically required to be an SGPR based on the operand
9938 // constraints?
9939 const TargetRegisterClass *OpRC =
9940 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
9941 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
9942 if (IsRequiredSGPR)
9943 return MO.getReg();
9944
9945 // If this could be a VGPR or an SGPR, Check the dynamic register class.
9946 Register Reg = MO.getReg();
9947 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
9948 if (RI.isSGPRClass(RegRC))
9949 UsedSGPRs[i] = Reg;
9950 }
9951
9952 // We don't have a required SGPR operand, so we have a bit more freedom in
9953 // selecting operands to move.
9954
9955 // Try to select the most used SGPR. If an SGPR is equal to one of the
9956 // others, we choose that.
9957 //
9958 // e.g.
9959 // V_FMA_F32 v0, s0, s0, s0 -> No moves
9960 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
9961
9962 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
9963 // prefer those.
9964
9965 if (UsedSGPRs[0]) {
9966 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
9967 SGPRReg = UsedSGPRs[0];
9968 }
9969
9970 if (!SGPRReg && UsedSGPRs[1]) {
9971 if (UsedSGPRs[1] == UsedSGPRs[2])
9972 SGPRReg = UsedSGPRs[1];
9973 }
9974
9975 return SGPRReg;
9976}
9977
9979 AMDGPU::OpName OperandName) const {
9980 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
9981 return nullptr;
9982
9983 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
9984 if (Idx == -1)
9985 return nullptr;
9986
9987 return &MI.getOperand(Idx);
9988}
9989
9991 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
9992 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
9995 return (Format << 44) |
9996 (1ULL << 56) | // RESOURCE_LEVEL = 1
9997 (3ULL << 60); // OOB_SELECT = 3
9998 }
9999
10000 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
10001 if (ST.isAmdHsaOS()) {
10002 // Set ATC = 1. GFX9 doesn't have this bit.
10003 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10004 RsrcDataFormat |= (1ULL << 56);
10005
10006 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
10007 // BTW, it disables TC L2 and therefore decreases performance.
10008 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
10009 RsrcDataFormat |= (2ULL << 59);
10010 }
10011
10012 return RsrcDataFormat;
10013}
10014
10018 0xffffffff; // Size;
10019
10020 // GFX9 doesn't have ELEMENT_SIZE.
10021 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
10022 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
10023 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
10024 }
10025
10026 // IndexStride = 64 / 32.
10027 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10028 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
10029
10030 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
10031 // Clear them unless we want a huge stride.
10032 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
10033 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
10034 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
10035
10036 return Rsrc23;
10037}
10038
10040 unsigned Opc = MI.getOpcode();
10041
10042 return isSMRD(Opc);
10043}
10044
10046 return get(Opc).mayLoad() &&
10047 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
10048}
10049
10051 TypeSize &MemBytes) const {
10052 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
10053 if (!Addr || !Addr->isFI())
10054 return Register();
10055
10056 assert(!MI.memoperands_empty() &&
10057 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
10058
10059 FrameIndex = Addr->getIndex();
10060
10061 int VDataIdx =
10062 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
10063 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
10064 return MI.getOperand(VDataIdx).getReg();
10065}
10066
10068 TypeSize &MemBytes) const {
10069 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
10070 assert(Addr && Addr->isFI());
10071 FrameIndex = Addr->getIndex();
10072
10073 int DataIdx =
10074 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
10075 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
10076 return MI.getOperand(DataIdx).getReg();
10077}
10078
10080 int &FrameIndex,
10081 TypeSize &MemBytes) const {
10082 if (!MI.mayLoad())
10083 return Register();
10084
10085 if (isMUBUF(MI) || isVGPRSpill(MI))
10086 return isStackAccess(MI, FrameIndex, MemBytes);
10087
10088 if (isSGPRSpill(MI))
10089 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10090
10091 return Register();
10092}
10093
10095 int &FrameIndex,
10096 TypeSize &MemBytes) const {
10097 if (!MI.mayStore())
10098 return Register();
10099
10100 if (isMUBUF(MI) || isVGPRSpill(MI))
10101 return isStackAccess(MI, FrameIndex, MemBytes);
10102
10103 if (isSGPRSpill(MI))
10104 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10105
10106 return Register();
10107}
10108
10110 unsigned Opc = MI.getOpcode();
10112 unsigned DescSize = Desc.getSize();
10113
10114 // If we have a definitive size, we can use it. Otherwise we need to inspect
10115 // the operands to know the size.
10116 if (isFixedSize(MI)) {
10117 unsigned Size = DescSize;
10118
10119 // If we hit the buggy offset, an extra nop will be inserted in MC so
10120 // estimate the worst case.
10121 if (MI.isBranch() && ST.hasOffset3fBug())
10122 Size += 4;
10123
10124 return Size;
10125 }
10126
10127 // Instructions may have a 32-bit literal encoded after them. Check
10128 // operands that could ever be literals.
10129 if (isVALU(MI, /*AllowLDSDMA=*/true) || isSALU(MI)) {
10130 if (isDPP(MI))
10131 return DescSize;
10132 bool HasLiteral = false;
10133 unsigned LiteralSize = 4;
10134 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
10135 const MachineOperand &Op = MI.getOperand(I);
10136 const MCOperandInfo &OpInfo = Desc.operands()[I];
10137 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
10138 HasLiteral = true;
10139 if (ST.has64BitLiterals()) {
10140 switch (OpInfo.OperandType) {
10141 default:
10142 break;
10145 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
10146 LiteralSize = 8;
10147 break;
10150 // A 32-bit literal is only valid when the value fits in BOTH signed
10151 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
10152 // emitter's getLit64Encoding logic. This is because of the lack of
10153 // abilility to tell signedness of the literal, therefore we need to
10154 // be conservative and assume values outside this range require a
10155 // 64-bit literal encoding (8 bytes).
10156 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
10157 !isUInt<32>(Op.getImm()))
10158 LiteralSize = 8;
10159 break;
10160 }
10161 }
10162 break;
10163 }
10164 }
10165 return HasLiteral ? DescSize + LiteralSize : DescSize;
10166 }
10167
10168 // Check whether we have extra NSA words.
10169 if (isMIMG(MI)) {
10170 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
10171 if (VAddr0Idx < 0)
10172 return 8;
10173
10174 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
10175 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10176 }
10177
10178 switch (Opc) {
10179 case TargetOpcode::BUNDLE:
10180 return getInstBundleSize(MI);
10181 case TargetOpcode::INLINEASM:
10182 case TargetOpcode::INLINEASM_BR: {
10183 const MachineFunction *MF = MI.getMF();
10184 const char *AsmStr = MI.getOperand(0).getSymbolName();
10185 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10186 }
10187 default:
10188 if (MI.isMetaInstruction())
10189 return 0;
10190
10191 // If D16 Pseudo inst, get correct MC code size
10192 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10193 if (D16Info) {
10194 // Assume d16_lo/hi inst are always in same size
10195 unsigned LoInstOpcode = D16Info->LoOp;
10196 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10197 DescSize = Desc.getSize();
10198 }
10199
10200 // If FMA Pseudo inst, get correct MC code size
10201 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10202 // All potential lowerings are the same size; arbitrarily pick one.
10203 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10204 DescSize = Desc.getSize();
10205 }
10206
10207 return DescSize;
10208 }
10209}
10210
10213 if (MI.isBranch() && ST.hasOffset3fBug())
10214 return InstSizeVerifyMode::NoVerify;
10215 return InstSizeVerifyMode::ExactSize;
10216}
10217
10219 if (!isFLAT(MI))
10220 return false;
10221
10222 if (MI.memoperands_empty())
10223 return true;
10224
10225 for (const MachineMemOperand *MMO : MI.memoperands()) {
10227 return true;
10228 }
10229 return false;
10230}
10231
10234 static const std::pair<int, const char *> TargetIndices[] = {
10235 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10236 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10237 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10238 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10239 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10240 return ArrayRef(TargetIndices);
10241}
10242
10243/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10244/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10247 const ScheduleDAG *DAG) const {
10248 return new GCNHazardRecognizer(DAG->MF);
10249}
10250
10251/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10252/// pass.
10259
10260// Called during:
10261// - pre-RA scheduling and post-RA scheduling
10264 const ScheduleDAGMI *DAG) const {
10265 // Borrowed from Arm Target
10266 // We would like to restrict this hazard recognizer to only
10267 // post-RA scheduling; we can tell that we're post-RA because we don't
10268 // track VRegLiveness.
10269 if (!DAG->hasVRegLiveness())
10270 return new GCNHazardRecognizer(DAG->MF);
10272}
10273
10274std::pair<unsigned, unsigned>
10276 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10277}
10278
10281 static const std::pair<unsigned, const char *> TargetFlags[] = {
10282 {MO_GOTPCREL, "amdgpu-gotprel"},
10283 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10284 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10285 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10286 {MO_REL32_LO, "amdgpu-rel32-lo"},
10287 {MO_REL32_HI, "amdgpu-rel32-hi"},
10288 {MO_REL64, "amdgpu-rel64"},
10289 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10290 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10291 {MO_ABS64, "amdgpu-abs64"},
10292 };
10293
10294 return ArrayRef(TargetFlags);
10295}
10296
10299 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10300 {
10301 {MONoClobber, "amdgpu-noclobber"},
10302 {MOLastUse, "amdgpu-last-use"},
10303 {MOCooperative, "amdgpu-cooperative"},
10304 {MOThreadPrivate, "amdgpu-thread-private"},
10305 };
10306
10307 return ArrayRef(TargetFlags);
10308}
10309
10311 const MachineFunction &MF) const {
10313 assert(SrcReg.isVirtual());
10314 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10315 return AMDGPU::WWM_COPY;
10316
10317 return AMDGPU::COPY;
10318}
10319
10321 uint32_t Opcode = MI.getOpcode();
10322 // Check if it is SGPR spill or wwm-register spill Opcode.
10323 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10324 return true;
10325
10326 const MachineFunction *MF = MI.getMF();
10327 const MachineRegisterInfo &MRI = MF->getRegInfo();
10329
10330 // See if this is Liverange split instruction inserted for SGPR or
10331 // wwm-register. The implicit def inserted for wwm-registers should also be
10332 // included as they can appear at the bb begin.
10333 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10334 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10335 return false;
10336
10337 Register Reg = MI.getOperand(0).getReg();
10338 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10339 return IsLRSplitInst;
10340
10341 return MFI->isWWMReg(Reg);
10342}
10343
10345 Register Reg) const {
10346 // We need to handle instructions which may be inserted during register
10347 // allocation to handle the prolog. The initial prolog instruction may have
10348 // been separated from the start of the block by spills and copies inserted
10349 // needed by the prolog. However, the insertions for scalar registers can
10350 // always be placed at the BB top as they are independent of the exec mask
10351 // value.
10352 bool IsNullOrVectorRegister = true;
10353 if (Reg) {
10354 const MachineFunction *MF = MI.getMF();
10355 const MachineRegisterInfo &MRI = MF->getRegInfo();
10356 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10357 }
10358
10359 return IsNullOrVectorRegister &&
10360 (canAddToBBProlog(MI) ||
10361 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10362 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10363}
10364
10368 const DebugLoc &DL,
10369 Register DestReg) const {
10370 if (ST.hasAddNoCarryInsts())
10371 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10372
10373 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10374 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10375 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10376
10377 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10378 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10379}
10380
10383 const DebugLoc &DL,
10384 Register DestReg,
10385 RegScavenger &RS) const {
10386 if (ST.hasAddNoCarryInsts())
10387 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10388
10389 // If available, prefer to use vcc.
10390 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10391 ? Register(RI.getVCC())
10392 : RS.scavengeRegisterBackwards(
10393 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10394 0, /* AllowSpill */ false);
10395
10396 // TODO: Users need to deal with this.
10397 if (!UnusedCarry.isValid())
10398 return MachineInstrBuilder();
10399
10400 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10401 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10402}
10403
10404bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10405 switch (Opcode) {
10406 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10407 case AMDGPU::SI_KILL_I1_TERMINATOR:
10408 return true;
10409 default:
10410 return false;
10411 }
10412}
10413
10415 switch (Opcode) {
10416 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10417 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10418 case AMDGPU::SI_KILL_I1_PSEUDO:
10419 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10420 default:
10421 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10422 }
10423}
10424
10425bool SIInstrInfo::isLegalMUBUFImmOffset(unsigned Imm) const {
10426 return Imm <= getMaxMUBUFImmOffset(ST);
10427}
10428
10430 // GFX12 field is non-negative 24-bit signed byte offset.
10431 const unsigned OffsetBits =
10432 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10433 return (1 << OffsetBits) - 1;
10434}
10435
10437 if (!ST.isWave32())
10438 return;
10439
10440 if (MI.isInlineAsm())
10441 return;
10442
10443 if (MI.getNumOperands() < MI.getNumExplicitOperands())
10444 return;
10445
10446 for (auto &Op : MI.implicit_operands()) {
10447 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10448 Op.setReg(AMDGPU::VCC_LO);
10449 }
10450}
10451
10453 if (!isSMRD(MI))
10454 return false;
10455
10456 // Check that it is using a buffer resource.
10457 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10458 if (Idx == -1) // e.g. s_memtime
10459 return false;
10460
10461 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10462 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10463}
10464
10465// Given Imm, split it into the values to put into the SOffset and ImmOffset
10466// fields in an MUBUF instruction. Return false if it is not possible (due to a
10467// hardware bug needing a workaround).
10468//
10469// The required alignment ensures that individual address components remain
10470// aligned if they are aligned to begin with. It also ensures that additional
10471// offsets within the given alignment can be added to the resulting ImmOffset.
10473 uint32_t &ImmOffset, Align Alignment) const {
10474 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10475 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10476 uint32_t Overflow = 0;
10477
10478 if (Imm > MaxImm) {
10479 if (Imm <= MaxImm + 64) {
10480 // Use an SOffset inline constant for 4..64
10481 Overflow = Imm - MaxImm;
10482 Imm = MaxImm;
10483 } else {
10484 // Try to keep the same value in SOffset for adjacent loads, so that
10485 // the corresponding register contents can be re-used.
10486 //
10487 // Load values with all low-bits (except for alignment bits) set into
10488 // SOffset, so that a larger range of values can be covered using
10489 // s_movk_i32.
10490 //
10491 // Atomic operations fail to work correctly when individual address
10492 // components are unaligned, even if their sum is aligned.
10493 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10494 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10495 Imm = Low;
10496 Overflow = High - Alignment.value();
10497 }
10498 }
10499
10500 if (Overflow > 0) {
10501 // There is a hardware bug in SI and CI which prevents address clamping in
10502 // MUBUF instructions from working correctly with SOffsets. The immediate
10503 // offset is unaffected.
10504 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10505 return false;
10506
10507 // It is not possible to set immediate in SOffset field on some targets.
10508 if (ST.hasRestrictedSOffset())
10509 return false;
10510 }
10511
10512 ImmOffset = Imm;
10513 SOffset = Overflow;
10514 return true;
10515}
10516
10517// Depending on the used address space and instructions, some immediate offsets
10518// are allowed and some are not.
10519// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10520// scratch instruction offsets can also be negative. On GFX12, offsets can be
10521// negative for all variants.
10522//
10523// There are several bugs related to these offsets:
10524// On gfx10.1, flat instructions that go into the global address space cannot
10525// use an offset.
10526//
10527// For scratch instructions, the address can be either an SGPR or a VGPR.
10528// The following offsets can be used, depending on the architecture (x means
10529// cannot be used):
10530// +----------------------------+------+------+
10531// | Address-Mode | SGPR | VGPR |
10532// +----------------------------+------+------+
10533// | gfx9 | | |
10534// | negative, 4-aligned offset | x | ok |
10535// | negative, unaligned offset | x | ok |
10536// +----------------------------+------+------+
10537// | gfx10 | | |
10538// | negative, 4-aligned offset | ok | ok |
10539// | negative, unaligned offset | ok | x |
10540// +----------------------------+------+------+
10541// | gfx10.3 | | |
10542// | negative, 4-aligned offset | ok | ok |
10543// | negative, unaligned offset | ok | ok |
10544// +----------------------------+------+------+
10545//
10546// This function ignores the addressing mode, so if an offset cannot be used in
10547// one addressing mode, it is considered illegal.
10548bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10549 AMDGPU::FlatAddrSpace FlatVariant) const {
10550 // TODO: Should 0 be special cased?
10551 if (!ST.hasFlatInstOffsets())
10552 return false;
10553
10555 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10556 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10557 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10558 return false;
10559
10560 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10561 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10562 (Offset % 4) != 0) {
10563 return false;
10564 }
10565
10566 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10567 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10568 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10569}
10570
10571// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10572std::pair<int64_t, int64_t>
10573SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10574 AMDGPU::FlatAddrSpace FlatVariant) const {
10575 int64_t RemainderOffset = COffsetVal;
10576 int64_t ImmField = 0;
10577
10578 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10579 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10580
10581 if (AllowNegative) {
10582 // Use signed division by a power of two to truncate towards 0.
10583 int64_t D = 1LL << NumBits;
10584 RemainderOffset = (COffsetVal / D) * D;
10585 ImmField = COffsetVal - RemainderOffset;
10586
10587 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10588 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10589 (ImmField % 4) != 0) {
10590 // Make ImmField a multiple of 4
10591 RemainderOffset += ImmField % 4;
10592 ImmField -= ImmField % 4;
10593 }
10594 } else if (COffsetVal >= 0) {
10595 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10596 RemainderOffset = COffsetVal - ImmField;
10597 }
10598
10599 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10600 assert(RemainderOffset + ImmField == COffsetVal);
10601 return {ImmField, RemainderOffset};
10602}
10603
10605 AMDGPU::FlatAddrSpace FlatVariant) const {
10606 if (ST.hasNegativeScratchOffsetBug() &&
10608 return false;
10609
10610 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10611}
10612
10613static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10614 switch (ST.getGeneration()) {
10615 default:
10616 break;
10619 return SIEncodingFamily::SI;
10622 return SIEncodingFamily::VI;
10626 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10629 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10633 }
10634 llvm_unreachable("Unknown subtarget generation!");
10635}
10636
10637bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10638 switch(MCOp) {
10639 // These opcodes use indirect register addressing so
10640 // they need special handling by codegen (currently missing).
10641 // Therefore it is too risky to allow these opcodes
10642 // to be selected by dpp combiner or sdwa peepholer.
10643 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10644 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10645 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10646 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10647 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10648 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10649 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10650 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10651 return true;
10652 default:
10653 return false;
10654 }
10655}
10656
10657#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10658 case OPCODE##_dpp: \
10659 case OPCODE##_e32: \
10660 case OPCODE##_e64: \
10661 case OPCODE##_e64_dpp: \
10662 case OPCODE##_sdwa:
10663
10664static bool isRenamedInGFX9(int Opcode) {
10665 switch (Opcode) {
10666 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
10667 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
10668 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
10669 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
10670 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
10671 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
10672 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
10673 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
10674 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
10675 //
10676 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10677 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10678 case AMDGPU::V_FMA_F16_gfx9_e64:
10679 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10680 case AMDGPU::V_INTERP_P2_F16:
10681 case AMDGPU::V_MAD_F16_e64:
10682 case AMDGPU::V_MAD_U16_e64:
10683 case AMDGPU::V_MAD_I16_e64:
10684 return true;
10685 default:
10686 return false;
10687 }
10688}
10689
10690int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
10691 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
10692 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10693
10694 unsigned Gen = subtargetEncodingFamily(ST);
10695
10696 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
10698
10699 // Adjust the encoding family to GFX80 for D16 buffer instructions when the
10700 // subtarget has UnpackedD16VMem feature.
10701 // TODO: remove this when we discard GFX80 encoding.
10702 if (ST.hasUnpackedD16VMem() && SIInstrFlags::isD16Buf(get(Opcode)))
10704
10705 if (SIInstrFlags::isSDWA(get(Opcode))) {
10706 switch (ST.getGeneration()) {
10707 default:
10709 break;
10712 break;
10715 break;
10716 }
10717 }
10718
10719 if (isMAI(Opcode)) {
10720 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
10721 if (MFMAOp != -1)
10722 Opcode = MFMAOp;
10723 }
10724
10725 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
10726
10727 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10729
10730 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10732
10733 // -1 means that Opcode is already a native instruction.
10734 if (MCOp == -1)
10735 return Opcode;
10736
10737 if (ST.hasGFX90AInsts()) {
10738 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10739 if (ST.hasGFX940Insts())
10741 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10743 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10745 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10746 MCOp = NMCOp;
10747 }
10748
10749 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
10750 // encoding in the given subtarget generation.
10751 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10752 return -1;
10753
10754 if (isAsmOnlyOpcode(MCOp))
10755 return -1;
10756
10757 return MCOp;
10758}
10759
10760static
10762 assert(RegOpnd.isReg());
10763 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
10764 getRegSubRegPair(RegOpnd);
10765}
10766
10769 assert(MI.isRegSequence());
10770 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
10771 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
10772 auto &RegOp = MI.getOperand(1 + 2 * I);
10773 return getRegOrUndef(RegOp);
10774 }
10776}
10777
10778// Try to find the definition of reg:subreg in subreg-manipulation pseudos
10779// Following a subreg of reg:subreg isn't supported
10782 if (!RSR.SubReg)
10783 return false;
10784 switch (MI.getOpcode()) {
10785 default: break;
10786 case AMDGPU::REG_SEQUENCE:
10787 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
10788 return true;
10789 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
10790 case AMDGPU::INSERT_SUBREG:
10791 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
10792 // inserted the subreg we're looking for
10793 RSR = getRegOrUndef(MI.getOperand(2));
10794 else { // the subreg in the rest of the reg
10795 auto R1 = getRegOrUndef(MI.getOperand(1));
10796 if (R1.SubReg) // subreg of subreg isn't supported
10797 return false;
10798 RSR.Reg = R1.Reg;
10799 }
10800 return true;
10801 }
10802 return false;
10803}
10804
10806 const MachineRegisterInfo &MRI) {
10807 assert(MRI.isSSA());
10808 if (!P.Reg.isVirtual())
10809 return nullptr;
10810
10811 auto RSR = P;
10812 auto *DefInst = MRI.getVRegDef(RSR.Reg);
10813 while (auto *MI = DefInst) {
10814 DefInst = nullptr;
10815 switch (MI->getOpcode()) {
10816 case AMDGPU::COPY:
10817 case AMDGPU::V_MOV_B32_e32: {
10818 auto &Op1 = MI->getOperand(1);
10819 if (Op1.isReg() && Op1.getReg().isVirtual()) {
10820 if (Op1.isUndef())
10821 return nullptr;
10822 RSR = getRegSubRegPair(Op1);
10823 DefInst = MRI.getVRegDef(RSR.Reg);
10824 }
10825 break;
10826 }
10827 default:
10828 if (followSubRegDef(*MI, RSR)) {
10829 if (!RSR.Reg)
10830 return nullptr;
10831 DefInst = MRI.getVRegDef(RSR.Reg);
10832 }
10833 }
10834 if (!DefInst)
10835 return MI;
10836 }
10837 return nullptr;
10838}
10839
10841 Register VReg,
10842 const MachineInstr &DefMI,
10843 const MachineInstr &UseMI) {
10844 assert(MRI.isSSA() && "Must be run on SSA");
10845
10846 auto *TRI = MRI.getTargetRegisterInfo();
10847 auto *DefBB = DefMI.getParent();
10848
10849 // Don't bother searching between blocks, although it is possible this block
10850 // doesn't modify exec.
10851 if (UseMI.getParent() != DefBB)
10852 return true;
10853
10854 const int MaxInstScan = 20;
10855 int NumInst = 0;
10856
10857 // Stop scan at the use.
10858 auto E = UseMI.getIterator();
10859 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
10860 if (I->isDebugInstr())
10861 continue;
10862
10863 if (++NumInst > MaxInstScan)
10864 return true;
10865
10866 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
10867 return true;
10868 }
10869
10870 return false;
10871}
10872
10874 Register VReg,
10875 const MachineInstr &DefMI) {
10876 assert(MRI.isSSA() && "Must be run on SSA");
10877
10878 auto *TRI = MRI.getTargetRegisterInfo();
10879 auto *DefBB = DefMI.getParent();
10880
10881 const int MaxUseScan = 10;
10882 int NumUse = 0;
10883
10884 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
10885 auto &UseInst = *Use.getParent();
10886 // Don't bother searching between blocks, although it is possible this block
10887 // doesn't modify exec.
10888 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10889 return true;
10890
10891 if (++NumUse > MaxUseScan)
10892 return true;
10893 }
10894
10895 if (NumUse == 0)
10896 return false;
10897
10898 const int MaxInstScan = 20;
10899 int NumInst = 0;
10900
10901 // Stop scan when we have seen all the uses.
10902 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
10903 assert(I != DefBB->end());
10904
10905 if (I->isDebugInstr())
10906 continue;
10907
10908 if (++NumInst > MaxInstScan)
10909 return true;
10910
10911 for (const MachineOperand &Op : I->operands()) {
10912 // We don't check reg masks here as they're used only on calls:
10913 // 1. EXEC is only considered const within one BB
10914 // 2. Call should be a terminator instruction if present in a BB
10915
10916 if (!Op.isReg())
10917 continue;
10918
10919 Register Reg = Op.getReg();
10920 if (Op.isUse()) {
10921 if (Reg == VReg && --NumUse == 0)
10922 return false;
10923 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
10924 return true;
10925 }
10926 }
10927}
10928
10931 const DebugLoc &DL, Register Src, Register Dst) const {
10932 auto Cur = MBB.begin();
10933 if (Cur != MBB.end())
10934 do {
10935 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
10936 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
10937 ++Cur;
10938 } while (Cur != MBB.end() && Cur != LastPHIIt);
10939
10940 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
10941 Dst);
10942}
10943
10946 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
10947 if (InsPt != MBB.end() &&
10948 (InsPt->getOpcode() == AMDGPU::SI_IF ||
10949 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
10950 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
10951 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
10952 InsPt++;
10953 return BuildMI(MBB, InsPt, DL,
10954 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
10955 .addReg(Src, {}, SrcSubReg)
10956 .addReg(AMDGPU::EXEC, RegState::Implicit);
10957 }
10958 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
10959 Dst);
10960}
10961
10962bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
10963
10965 const MachineInstr &SecondMI) const {
10966 for (const auto &Use : SecondMI.all_uses()) {
10967 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
10968 return true;
10969 }
10970 return false;
10971}
10972
10973/// If OpX is multicycle, anti-dependencies are not allowed.
10974/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
10975/// purpose.
10977 const MachineInstr &OpX) const {
10979}
10980
10983 ArrayRef<unsigned> Ops, int FrameIndex,
10984 MachineInstr *&CopyMI, LiveIntervals *LIS,
10985 VirtRegMap *VRM) const {
10986 // This is a bit of a hack (copied from AArch64). Consider this instruction:
10987 //
10988 // %0:sreg_32 = COPY $m0
10989 //
10990 // We explicitly chose SReg_32 for the virtual register so such a copy might
10991 // be eliminated by RegisterCoalescer. However, that may not be possible, and
10992 // %0 may even spill. We can't spill $m0 normally (it would require copying to
10993 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
10994 // TargetInstrInfo::foldMemoryOperand() is going to try.
10995 // A similar issue also exists with spilling and reloading $exec registers.
10996 //
10997 // To prevent that, constrain the %0 register class here.
10998 if (isFullCopyInstr(MI)) {
10999 Register DstReg = MI.getOperand(0).getReg();
11000 Register SrcReg = MI.getOperand(1).getReg();
11001 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
11002 (DstReg.isVirtual() != SrcReg.isVirtual())) {
11003 MachineRegisterInfo &MRI = MF.getRegInfo();
11004 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
11005 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
11006 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
11007 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11008 return nullptr;
11009 }
11010 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
11011 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11012 return nullptr;
11013 }
11014 }
11015 }
11016
11017 return nullptr;
11018}
11019
11021 const MachineInstr &MI,
11022 unsigned *PredCost) const {
11023 if (MI.isBundle()) {
11025 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
11026 unsigned Lat = 0, Count = 0;
11027 for (++I; I != E && I->isBundledWithPred(); ++I) {
11028 ++Count;
11029 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
11030 }
11031 return Lat + Count - 1;
11032 }
11033
11034 return SchedModel.computeInstrLatency(&MI);
11035}
11036
11037const MachineOperand &
11039 if (const MachineOperand *CallAddrOp =
11040 getNamedOperand(MI, AMDGPU::OpName::src0))
11041 return *CallAddrOp;
11043}
11044
11047 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11048 unsigned Opcode = MI.getOpcode();
11049
11050 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
11051 Register Dst = MI.getOperand(0).getReg();
11052 Register Src = isa<GIntrinsic>(MI) ? MI.getOperand(2).getReg()
11053 : MI.getOperand(1).getReg();
11054 LLT DstTy = MRI.getType(Dst);
11055 LLT SrcTy = MRI.getType(Src);
11056 unsigned DstAS = DstTy.getAddressSpace();
11057 unsigned SrcAS = SrcTy.getAddressSpace();
11058 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
11059 DstAS == AMDGPUAS::FLAT_ADDRESS &&
11060 ST.hasGloballyAddressableScratch()
11063 };
11064
11065 // If the target supports globally addressable scratch, the mapping from
11066 // scratch memory to the flat aperture changes therefore an address space cast
11067 // is no longer uniform.
11068 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11069 return HandleAddrSpaceCast(MI);
11070
11071 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
11072 auto IID = GI->getIntrinsicID();
11077
11078 switch (IID) {
11079 case Intrinsic::amdgcn_addrspacecast_nonnull:
11080 return HandleAddrSpaceCast(MI);
11081 case Intrinsic::amdgcn_if:
11082 case Intrinsic::amdgcn_else:
11083 // FIXME: Uniform if second result
11084 break;
11085 }
11086
11088 }
11089
11090 // Loads from the private and flat address spaces are divergent, because
11091 // threads can execute the load instruction with the same inputs and get
11092 // different results.
11093 //
11094 // All other loads are not divergent, because if threads issue loads with the
11095 // same arguments, they will always get the same result.
11096 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11097 Opcode == AMDGPU::G_SEXTLOAD) {
11098 if (MI.memoperands_empty())
11099 return ValueUniformity::NeverUniform; // conservative assumption
11100
11101 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11102 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11103 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11104 })) {
11105 // At least one MMO in a non-global address space.
11107 }
11109 }
11110
11111 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11112 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11113 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11114 AMDGPU::isGenericAtomic(Opcode)) {
11116 }
11117
11118 // Result is computed from uniform SP and uniform wave-wide max size.
11119 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11121
11122 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11124
11126}
11127
11129 if (!Formatter)
11130 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11131 return Formatter.get();
11132}
11133
11135
11136 if (isNeverUniform(MI))
11138
11139 unsigned opcode = MI.getOpcode();
11140 if (opcode == AMDGPU::V_READLANE_B32 ||
11141 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11142 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11144
11145 // If any of defs is divergent, report as NeverUniform. isUniformReg will
11146 // calculate in more detail for each def from its reg class, if available.
11147 if (MI.isInlineAsm()) {
11148 for (const MachineOperand &MO : MI.operands()) {
11149 if (!MO.isReg() || !MO.isDef())
11150 continue;
11151 const TargetRegisterClass *RC =
11152 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
11153 if (!RC || !RI.isSGPRClass(RC))
11155 }
11156 }
11157
11158 if (isCopyInstr(MI)) {
11159 const MachineOperand &srcOp = MI.getOperand(1);
11160 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
11161 const TargetRegisterClass *regClass =
11162 RI.getPhysRegBaseClass(srcOp.getReg());
11163 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
11165 }
11167 }
11168
11169 // GMIR handling
11170 if (MI.isPreISelOpcode())
11172
11173 // Atomics are divergent because they are executed sequentially: when an
11174 // atomic operation refers to the same address in each thread, then each
11175 // thread after the first sees the value written by the previous thread as
11176 // original value.
11177
11178 if (isAtomic(MI))
11180
11181 // Loads from the private and flat address spaces are divergent, because
11182 // threads can execute the load instruction with the same inputs and get
11183 // different results.
11184 if (isFLAT(MI) && MI.mayLoad()) {
11185 if (MI.memoperands_empty())
11186 return ValueUniformity::NeverUniform; // conservative assumption
11187
11188 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11189 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11190 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11191 })) {
11192 // At least one MMO in a non-global address space.
11194 }
11195
11197 }
11198
11199 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11200 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11201
11202 // FIXME: It's conceptually broken to report this for an instruction, and not
11203 // a specific def operand. For inline asm in particular, there could be mixed
11204 // uniform and divergent results.
11205 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11206 const MachineOperand &SrcOp = MI.getOperand(I);
11207 if (!SrcOp.isReg())
11208 continue;
11209
11210 Register Reg = SrcOp.getReg();
11211 if (!Reg || !SrcOp.readsReg())
11212 continue;
11213
11214 // If RegBank is null, this is unassigned or an unallocatable special
11215 // register, which are all scalars.
11216 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11217 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11219 }
11220
11221 // TODO: Uniformity check condtions above can be rearranged for more
11222 // redability
11223
11224 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11225 // currently turned into no-op COPYs by SelectionDAG ISel and are
11226 // therefore no longer recognizable.
11227
11229}
11230
11232 switch (MF.getFunction().getCallingConv()) {
11234 return 1;
11236 return 2;
11238 return 3;
11242 const Function &F = MF.getFunction();
11243 F.getContext().diagnose(DiagnosticInfoUnsupported(
11244 F, "ds_ordered_count unsupported for this calling conv"));
11245 [[fallthrough]];
11246 }
11249 case CallingConv::C:
11250 case CallingConv::Fast:
11251 default:
11252 // Assume other calling conventions are various compute callable functions
11253 return 0;
11254 }
11255}
11256
11258 Register &SrcReg2, int64_t &CmpMask,
11259 int64_t &CmpValue) const {
11260 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11261 return false;
11262
11263 switch (MI.getOpcode()) {
11264 default:
11265 break;
11266 case AMDGPU::S_CMP_EQ_U32:
11267 case AMDGPU::S_CMP_EQ_I32:
11268 case AMDGPU::S_CMP_LG_U32:
11269 case AMDGPU::S_CMP_LG_I32:
11270 case AMDGPU::S_CMP_LT_U32:
11271 case AMDGPU::S_CMP_LT_I32:
11272 case AMDGPU::S_CMP_GT_U32:
11273 case AMDGPU::S_CMP_GT_I32:
11274 case AMDGPU::S_CMP_LE_U32:
11275 case AMDGPU::S_CMP_LE_I32:
11276 case AMDGPU::S_CMP_GE_U32:
11277 case AMDGPU::S_CMP_GE_I32:
11278 case AMDGPU::S_CMP_EQ_U64:
11279 case AMDGPU::S_CMP_LG_U64:
11280 SrcReg = MI.getOperand(0).getReg();
11281 if (MI.getOperand(1).isReg()) {
11282 if (MI.getOperand(1).getSubReg())
11283 return false;
11284 SrcReg2 = MI.getOperand(1).getReg();
11285 CmpValue = 0;
11286 } else if (MI.getOperand(1).isImm()) {
11287 SrcReg2 = Register();
11288 CmpValue = MI.getOperand(1).getImm();
11289 } else {
11290 return false;
11291 }
11292 CmpMask = ~0;
11293 return true;
11294 case AMDGPU::S_CMPK_EQ_U32:
11295 case AMDGPU::S_CMPK_EQ_I32:
11296 case AMDGPU::S_CMPK_LG_U32:
11297 case AMDGPU::S_CMPK_LG_I32:
11298 case AMDGPU::S_CMPK_LT_U32:
11299 case AMDGPU::S_CMPK_LT_I32:
11300 case AMDGPU::S_CMPK_GT_U32:
11301 case AMDGPU::S_CMPK_GT_I32:
11302 case AMDGPU::S_CMPK_LE_U32:
11303 case AMDGPU::S_CMPK_LE_I32:
11304 case AMDGPU::S_CMPK_GE_U32:
11305 case AMDGPU::S_CMPK_GE_I32:
11306 SrcReg = MI.getOperand(0).getReg();
11307 SrcReg2 = Register();
11308 CmpValue = MI.getOperand(1).getImm();
11309 CmpMask = ~0;
11310 return true;
11311 }
11312
11313 return false;
11314}
11315
11317 for (MachineBasicBlock *S : MBB->successors()) {
11318 if (S->isLiveIn(AMDGPU::SCC))
11319 return false;
11320 }
11321 return true;
11322}
11323
11324// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11325// (incoming SCC) = !(SCC defined by SCCDef).
11326// Return true if all uses can be re-written, false otherwise.
11327bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11328 MachineBasicBlock *MBB = SCCDef->getParent();
11329 SmallVector<MachineInstr *> InvertInstr;
11330 bool SCCIsDead = false;
11331
11332 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11333 constexpr unsigned ScanLimit = 12;
11334 unsigned Count = 0;
11335 for (MachineInstr &MI :
11336 make_range(std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11337 if (++Count > ScanLimit)
11338 return false;
11339 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11340 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11341 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11342 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11343 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11344 InvertInstr.push_back(&MI);
11345 else
11346 return false;
11347 }
11348 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11349 SCCIsDead = true;
11350 break;
11351 }
11352 }
11353 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11354 SCCIsDead = true;
11355
11356 // SCC may have more uses. Can't invert all of them.
11357 if (!SCCIsDead)
11358 return false;
11359
11360 // Invert uses
11361 for (MachineInstr *MI : InvertInstr) {
11362 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11363 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11364 swapOperands(*MI);
11365 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11366 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11367 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11368 ? AMDGPU::S_CBRANCH_SCC1
11369 : AMDGPU::S_CBRANCH_SCC0));
11370 } else {
11371 llvm_unreachable("SCC used but no inversion handling");
11372 }
11373 }
11374 return true;
11375}
11376
11377// SCC is already valid after SCCValid.
11378// SCCRedefine will redefine SCC to the same value already available after
11379// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11380// update kill/dead flags if necessary.
11381bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11382 bool NeedInversion) const {
11383 MachineInstr *KillsSCC = nullptr;
11384 if (SCCValid->getParent() != SCCRedefine->getParent())
11385 return false;
11386 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11387 SCCRedefine->getIterator())) {
11388 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11389 return false;
11390 if (MI.killsRegister(AMDGPU::SCC, &RI))
11391 KillsSCC = &MI;
11392 }
11393 if (NeedInversion && !invertSCCUse(SCCRedefine))
11394 return false;
11395 if (MachineOperand *SccDef =
11396 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11397 SccDef->setIsDead(false);
11398 if (KillsSCC)
11399 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11400 SCCRedefine->eraseFromParent();
11401 return true;
11402}
11403
11404static bool foldableSelect(const MachineInstr &Def) {
11405 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11406 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11407 return false;
11408 bool Op1IsNonZeroImm =
11409 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11410 bool Op2IsZeroImm =
11411 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11412 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11413 return false;
11414 return true;
11415}
11416
11417static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11418 unsigned &NewDefOpc) {
11419 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11420 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11421 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11422 Def.getOpcode() != AMDGPU::S_ADD_U32)
11423 return false;
11424 const MachineOperand &AddSrc1 = Def.getOperand(1);
11425 const MachineOperand &AddSrc2 = Def.getOperand(2);
11426 int64_t addend;
11427
11428 if ((!AddSrc1.isImm() || AddSrc1.getImm() != 1) &&
11429 (!AddSrc2.isImm() || AddSrc2.getImm() != 1) &&
11430 (!getFoldableImm(&AddSrc1, addend) || addend != 1) &&
11431 (!getFoldableImm(&AddSrc2, addend) || addend != 1))
11432 return false;
11433
11434 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11435 const MachineOperand *SccDef =
11436 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11437 if (!SccDef->isDead())
11438 return false;
11439 NewDefOpc = AMDGPU::S_ADD_U32;
11440 }
11441 NeedInversion = !NeedInversion;
11442 return true;
11443}
11444
11446 Register SrcReg2, int64_t CmpMask,
11447 int64_t CmpValue,
11448 const MachineRegisterInfo *MRI) const {
11449 if (!SrcReg || SrcReg.isPhysical())
11450 return false;
11451
11452 if (SrcReg2 && !getFoldableImm(SrcReg2, *MRI, CmpValue))
11453 return false;
11454
11455 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11456 this](bool NeedInversion) -> bool {
11457 if (CmpValue != 0)
11458 return false;
11459
11460 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11461 if (!Def)
11462 return false;
11463
11464 // For S_OP that set SCC = DST!=0, do the transformation
11465 //
11466 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11467 //
11468 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11469 // do the transformation:
11470 //
11471 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11472 //
11473 // If foldableSelect, s_cmp_lg_* is redundant because the SCC input value
11474 // for S_CSELECT* already has the same value that will be calculated by
11475 // s_cmp_lg_*
11476 //
11477 // s_cmp_[lg|eq]_* (S_CSELECT* (non-zero imm), 0), 0 => (S_CSELECT*
11478 // (non-zero imm), 0)
11479
11480 unsigned NewDefOpc = Def->getOpcode();
11481 if (!setsSCCIfResultIsNonZero(*Def) &&
11482 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc) &&
11483 !foldableSelect(*Def))
11484 return false;
11485
11486 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11487 return false;
11488
11489 if (NewDefOpc != Def->getOpcode())
11490 Def->setDesc(get(NewDefOpc));
11491
11492 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11493 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11494 // 64-bit foldableSelect then delete s_or_b32 in the sequence:
11495 // sX = s_cselect_b64 (non-zero imm), 0
11496 // sLo = copy sX.sub0
11497 // sHi = copy sX.sub1
11498 // sY = s_or_b32 sLo, sHi
11499 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11500 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11501 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11502 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11503 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11504 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11505 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11506 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11507 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11508 Def2->getOperand(1).isReg() &&
11509 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11510 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11511 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11512 MachineInstr *Select = MRI->getVRegDef(Def1->getOperand(1).getReg());
11513 if (Select && foldableSelect(*Select))
11514 optimizeSCC(Select, Def, /*NeedInversion=*/false);
11515 }
11516 }
11517 }
11518 return true;
11519 };
11520
11521 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11522 this](int64_t ExpectedValue, unsigned SrcSize,
11523 bool IsReversible, bool IsSigned) -> bool {
11524 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11525 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11526 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11527 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11528 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11529 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11530 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11531 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11532 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11533 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11534 //
11535 // Signed ge/gt are not used for the sign bit.
11536 //
11537 // If result of the AND is unused except in the compare:
11538 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11539 //
11540 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11541 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11542 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11543 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11544 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11545 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11546
11547 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11548 if (!Def)
11549 return false;
11550
11551 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11552 Def->getOpcode() != AMDGPU::S_AND_B64)
11553 return false;
11554
11555 int64_t Mask;
11556 const auto isMask = [&Mask, SrcSize](const MachineOperand *MO) -> bool {
11557 if (MO->isImm())
11558 Mask = MO->getImm();
11559 else if (!getFoldableImm(MO, Mask))
11560 return false;
11561 Mask &= maxUIntN(SrcSize);
11562 return isPowerOf2_64(Mask);
11563 };
11564
11565 MachineOperand *SrcOp = &Def->getOperand(1);
11566 if (isMask(SrcOp))
11567 SrcOp = &Def->getOperand(2);
11568 else if (isMask(&Def->getOperand(2)))
11569 SrcOp = &Def->getOperand(1);
11570 else
11571 return false;
11572
11573 // A valid Mask is required to have a single bit set, hence a non-zero and
11574 // power-of-two value. This verifies that we will not do 64-bit shift below.
11575 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11576 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11577 if (IsSigned && BitNo == SrcSize - 1)
11578 return false;
11579
11580 ExpectedValue <<= BitNo;
11581
11582 bool IsReversedCC = false;
11583 if (CmpValue != ExpectedValue) {
11584 if (!IsReversible)
11585 return false;
11586 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11587 if (!IsReversedCC)
11588 return false;
11589 }
11590
11591 Register DefReg = Def->getOperand(0).getReg();
11592 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11593 return false;
11594
11595 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11596 return false;
11597
11598 if (!MRI->use_nodbg_empty(DefReg)) {
11599 assert(!IsReversedCC);
11600 return true;
11601 }
11602
11603 // Replace AND with unused result with a S_BITCMP.
11604 MachineBasicBlock *MBB = Def->getParent();
11605
11606 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11607 : AMDGPU::S_BITCMP1_B32
11608 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11609 : AMDGPU::S_BITCMP1_B64;
11610
11611 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11612 .add(*SrcOp)
11613 .addImm(BitNo);
11614 Def->eraseFromParent();
11615
11616 return true;
11617 };
11618
11619 switch (CmpInstr.getOpcode()) {
11620 default:
11621 break;
11622 case AMDGPU::S_CMP_EQ_U32:
11623 case AMDGPU::S_CMP_EQ_I32:
11624 case AMDGPU::S_CMPK_EQ_U32:
11625 case AMDGPU::S_CMPK_EQ_I32:
11626 return optimizeCmpAnd(1, 32, true, false) ||
11627 optimizeCmpSelect(/*NeedInversion=*/true);
11628 case AMDGPU::S_CMP_GE_U32:
11629 case AMDGPU::S_CMPK_GE_U32:
11630 return optimizeCmpAnd(1, 32, false, false);
11631 case AMDGPU::S_CMP_GE_I32:
11632 case AMDGPU::S_CMPK_GE_I32:
11633 return optimizeCmpAnd(1, 32, false, true);
11634 case AMDGPU::S_CMP_EQ_U64:
11635 return optimizeCmpAnd(1, 64, true, false);
11636 case AMDGPU::S_CMP_LG_U32:
11637 case AMDGPU::S_CMP_LG_I32:
11638 case AMDGPU::S_CMPK_LG_U32:
11639 case AMDGPU::S_CMPK_LG_I32:
11640 return optimizeCmpAnd(0, 32, true, false) ||
11641 optimizeCmpSelect(/*NeedInversion=*/false);
11642 case AMDGPU::S_CMP_GT_U32:
11643 case AMDGPU::S_CMPK_GT_U32:
11644 return optimizeCmpAnd(0, 32, false, false);
11645 case AMDGPU::S_CMP_GT_I32:
11646 case AMDGPU::S_CMPK_GT_I32:
11647 return optimizeCmpAnd(0, 32, false, true);
11648 case AMDGPU::S_CMP_LG_U64:
11649 return optimizeCmpAnd(0, 64, true, false) ||
11650 optimizeCmpSelect(/*NeedInversion=*/false);
11651 }
11652
11653 return false;
11654}
11655
11657 AMDGPU::OpName OpName) const {
11658 if (!ST.needsAlignedVGPRs())
11659 return;
11660
11661 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
11662 if (OpNo < 0)
11663 return;
11664 MachineOperand &Op = MI.getOperand(OpNo);
11665 if (getOpSize(MI, OpNo) > 4)
11666 return;
11667
11668 // Add implicit aligned super-reg to force alignment on the data operand.
11669 const DebugLoc &DL = MI.getDebugLoc();
11670 MachineBasicBlock *BB = MI.getParent();
11672 Register DataReg = Op.getReg();
11673 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11675 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11676 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
11677 Register NewVR =
11678 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
11679 : &AMDGPU::VReg_64_Align2RegClass);
11680 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
11681 .addReg(DataReg, {}, Op.getSubReg())
11682 .addImm(AMDGPU::sub0)
11683 .addReg(Undef)
11684 .addImm(AMDGPU::sub1);
11685 Op.setReg(NewVR);
11686 Op.setSubReg(AMDGPU::sub0);
11687 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
11688}
11689
11691 if (!SchedModel.hasInstrSchedModel())
11692 return 0;
11693
11694 // The repeat rate is the throughput-limiting resource occupancy: the largest
11695 // number of cycles any written processor resource is held.
11696 const MCSchedClassDesc *SCDesc = SchedModel.resolveSchedClass(&MI);
11697 unsigned RepeatRate = 0;
11699 PI = SchedModel.getWriteProcResBegin(SCDesc),
11700 PE = SchedModel.getWriteProcResEnd(SCDesc);
11701 PI != PE; ++PI) {
11702 RepeatRate = std::max(RepeatRate, (unsigned)PI->ReleaseAtCycle);
11703 }
11704
11705 return RepeatRate;
11706}
11707
11709 if (isIGLP(*MI))
11710 return false;
11711
11713}
11714
11716 if (!isWMMA(MI) && !isSWMMAC(MI))
11717 return false;
11718
11719 if (ST.hasGFX1250Insts())
11720 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
11721
11722 return true;
11723}
11724
11726 unsigned Opcode = MI.getOpcode();
11727
11728 if (AMDGPU::isGFX12Plus(ST))
11729 return isDOT(MI) || isXDLWMMA(MI);
11730
11731 if (!isMAI(MI) || isDGEMM(Opcode) ||
11732 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11733 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11734 return false;
11735
11736 if (!ST.hasGFX940Insts())
11737 return true;
11738
11739 return AMDGPU::getMAIIsGFX940XDL(Opcode);
11740}
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)
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 LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps)
Move NumOps operands from Src to Dst, updating use-def lists as needed.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
LLVM_ABI void clearVirtRegs()
clearVirtRegs - Remove all virtual registers (after physreg assignment).
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI bool isConstantPhysReg(MCRegister PhysReg) const
Returns true if PhysReg is unallocatable and constant throughout the function.
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void removeRegOperandFromUseList(MachineOperand *MO)
Remove MO from its use-def list.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI void addRegOperandToUseList(MachineOperand *MO)
Add MO to the linked list of operands for its register.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const final
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
bool isSpill(uint32_t Opcode) const
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool mayAccessFlatAddressSpace(const MachineInstr &MI) const
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
bool isLegalVSrcOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO would be a valid operand for the given operand definition OpInfo.
static bool isDOT(const MachineInstr &MI)
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
bool hasModifiers(unsigned Opcode) const
Return true if this instruction has any modifiers.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
static bool isSWMMAC(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
bool isWave32() const
bool isHighLatencyDef(int Opc) const override
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const
Legalize the OpIndex operand of this instruction by inserting a MOV.
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isVOPC(const MachineInstr &MI)
void removeModOperands(MachineInstr &MI) const
unsigned getRepeatRate(const MachineInstr &MI) const
Get the repeat rate for a VALU instruction from the scheduling model.
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool isLegalSingleSGPRReadInstOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for a single-SGPR-read instruction.
bool isXDL(const MachineInstr &MI) const
Register isStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
static bool isVIMAGE(const MachineInstr &MI)
void enforceOperandRCAlignment(MachineInstr &MI, AMDGPU::OpName OpName) const
static bool isSOP2(const MachineInstr &MI)
static bool isGWS(const MachineInstr &MI)
bool hasRAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI) const
bool isLegalAV64PseudoImm(uint64_t Imm) const
Check if this immediate value can be used for AV_MOV_B64_IMM_PSEUDO.
bool isNeverCoissue(MachineInstr &MI) const
static bool isBUF(const MachineInstr &MI)
void handleCopyToPhysHelper(SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst, MachineRegisterInfo &MRI, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
bool hasModifiersSet(const MachineInstr &MI, AMDGPU::OpName OpName) const
bool isLegalToSwap(const MachineInstr &MI, unsigned fromIdx, unsigned toIdx) const
static bool isFLATGlobal(const MachineInstr &MI)
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isGlobalMemoryObject(const MachineInstr *MI) const override
static bool isVSAMPLE(const MachineInstr &MI)
bool isBufferSMRD(const MachineInstr &MI) const
static bool isKillTerminator(unsigned Opcode)
bool isVOPDAntidependencyAllowed(const MachineInstr &MI) const
If OpX is multicycle, anti-dependencies are not allowed.
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
void insertScratchExecCopy(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, bool IsSCCLive, SlotIndexes *Indexes=nullptr) const
bool hasVALU32BitEncoding(unsigned Opcode) const
Return true if this 64-bit VALU instruction has a 32-bit encoding.
unsigned getMovOpcode(const TargetRegisterClass *DstRC) const
Register isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
unsigned buildExtractSubReg(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const
Legalize operands in MI by either commuting it or inserting a copy of src1.
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const final
static bool isTRANS(const MachineInstr &MI)
static bool isImage(const MachineInstr &MI)
static bool isSOPK(const MachineInstr &MI)
const TargetRegisterClass * getOpRegClass(const MachineInstr &MI, unsigned OpNo) const
Return the correct register class for OpNo.
MachineBasicBlock * insertSimulatedTrap(MachineRegisterInfo &MRI, MachineBasicBlock &MBB, MachineInstr &MI, const DebugLoc &DL) const
Build instructions that simulate the behavior of a s_trap 2 instructions for hardware (namely,...
static unsigned getNonSoftWaitcntOpcode(unsigned Opcode)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static bool isFoldableCopy(const MachineInstr &MI)
bool isIgnorableUse(const MachineOperand &MO) const override
static bool isMUBUF(const MachineInstr &MI)
bool expandPostRAPseudo(MachineInstr &MI) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
void createWaterFallForSiCall(MachineInstr *MI, MachineDominatorTree *MDT, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={}) const
Wrapper function for generating waterfall for instruction MI This function take into consideration of...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSegmentSpecificFLAT(const MachineInstr &MI)
bool isReMaterializableImpl(const MachineInstr &MI) const override
static bool isVOP3(const MCInstrDesc &Desc)
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool physRegUsesConstantBus(const MachineOperand &Reg) const
static bool isF16PseudoScalarTrans(unsigned Opcode)
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
bool mayAccessVMEMThroughFlat(const MachineInstr &MI) const
static bool isDPP(const MachineInstr &MI)
bool analyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
static bool isMFMA(const MachineInstr &MI)
bool isLowLatencyInstruction(const MachineInstr &MI) const
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is a instruction that moves/copies value from one register to ano...
void mutateAndCleanupImplicit(MachineInstr &MI, const MCInstrDesc &NewDesc) const
ValueUniformity getGenericValueUniformity(const MachineInstr &MI) const
static bool isMAI(const MCInstrDesc &Desc)
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const override
static bool usesLGKM_CNT(const MachineInstr &MI)
void legalizeOperandsVALUt16(MachineInstr &Inst, MachineRegisterInfo &MRI) const
Fix operands in Inst to fix 16bit SALU to VALU lowering.
bool isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo, const MachineOperand &MO) const
bool canShrink(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
const MachineOperand & getCalleeOperand(const MachineInstr &MI) const override
bool isAsmOnlyOpcode(int MCOp) const
Check if this instruction should only be used by assembler.
bool isAlwaysGDS(uint32_t Opcode) const
static bool isVGPRSpill(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
This is used by the post-RA scheduler (SchedulePostRAList.cpp).
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
unsigned getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr &MI, unsigned *PredCost=nullptr) const override
unsigned getVectorRegSpillSaveOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI, bool NeedsCFI) const
int64_t getNamedImmOperand(const MachineInstr &MI, AMDGPU::OpName OperandName) const
Get required immediate operand.
ArrayRef< std::pair< int, const char * > > getSerializableTargetIndices() const override
bool regUsesConstantBus(const MachineOperand &Reg, const MachineRegisterInfo &MRI) const
static bool isMIMG(const MachineInstr &MI)
MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isLegalRegOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO (a register operand) is a legal register for the given operand description or operand ind...
static unsigned getNumWaitStates(const MachineInstr &MI)
Return the number of wait states that result from executing this instruction.
unsigned getVALUOp(const MachineInstr &MI) const
static bool modifiesModeRegister(const MachineInstr &MI)
Return true if the instruction modifies the mode register.q.
Register readlaneVGPRToSGPR(Register SrcReg, MachineInstr &UseMI, MachineRegisterInfo &MRI, const TargetRegisterClass *DstRC=nullptr) const
Copy a value from a VGPR (SrcReg) to SGPR.
bool hasDivergentBranch(const MachineBasicBlock *MBB) const
Return whether the block terminate with divergent branch.
std::pair< int64_t, int64_t > splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Split COffsetVal into {immediate offset field, remainder offset} values.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void fixImplicitOperands(MachineInstr &MI) const
bool moveFlatAddrToVGPR(MachineInstr &Inst) const
Change SADDR form of a FLAT Inst to its VADDR form if saddr operand was moved to VGPR.
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
void createReadFirstLaneFromCopyToPhysReg(MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const
bool swapSourceModifiers(MachineInstr &MI, MachineOperand &Src0, AMDGPU::OpName Src0OpName, MachineOperand &Src1, AMDGPU::OpName Src1OpName) const
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const
This function is used to determine if an instruction can be safely executed under EXEC = 0 without ha...
bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg, int64_t &ImmVal) const override
static bool isAtomic(const MachineInstr &MI)
bool canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, int &CondCycles, int &TrueCycles, int &FalseCycles) const override
bool isLiteralOperandLegal(const MCInstrDesc &InstDesc, const MCOperandInfo &OpInfo) const
static bool isWWMRegSpillOpcode(uint32_t Opcode)
static bool sopkIsZext(unsigned Opcode)
static bool isSGPRSpill(const MachineInstr &MI)
static bool isWMMA(const MachineInstr &MI)
ArrayRef< std::pair< MachineMemOperand::Flags, const char * > > getSerializableMachineMemOperandTargetFlags() const override
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, LiveIntervals *LIS) const override
bool mayReadEXEC(const MachineRegisterInfo &MRI, const MachineInstr &MI) const
Returns true if the instruction could potentially depend on the value of exec.
void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
std::pair< MachineInstr *, MachineInstr * > expandMovDPP64(MachineInstr &MI) const
static bool isSOPC(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
bool isBarrier(unsigned Opcode) const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx0, unsigned OpIdx1) const override
bool mayAccessLDSThroughFlat(const MachineInstr &MI, bool TgSplit) const
int pseudoToMCOpcode(int Opcode) const
Return a target-specific opcode if Opcode is a pseudo instruction.
const MCInstrDesc & getMCOpcodeFromPseudo(unsigned Opcode) const
Return the descriptor of the target-specific machine instruction that corresponds to the specified ps...
static bool usesVM_CNT(const MachineInstr &MI)
MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const override
static bool isFixedSize(const MachineInstr &MI)
bool isSafeToSink(MachineInstr &MI, MachineBasicBlock *SuccToSinkTo, MachineCycleInfo *CI) const override
LLVM_READONLY int commuteOpcode(unsigned Opc) const
ValueUniformity getValueUniformity(const MachineInstr &MI) const final
uint64_t getScratchRsrcWords23() const
LLVM_READONLY MachineOperand * getNamedOperand(MachineInstr &MI, AMDGPU::OpName OperandName) const
Returns the operand named Op.
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx, const MachineOperand *MO=nullptr) const
Check if MO is a legal operand if it was the OpIdx Operand for MI.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool allowNegativeFlatOffset(AMDGPU::FlatAddrSpace FlatVariant) const
Returns true if negative offsets are allowed for the given FlatVariant.
std::optional< int64_t > getImmOrMaterializedImm(MachineOperand &Op) const
void moveToVALUImpl(SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
static bool isLDSDMA(const MachineInstr &MI)
static bool isVOP1(const MachineInstr &MI)
SIInstrInfo(const GCNSubtarget &ST)
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool hasAnyModifiersSet(const MachineInstr &MI) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
void setHasSpilledVGPRs(bool Spill=true)
bool isWWMReg(Register Reg) const
bool checkFlag(Register Reg, uint8_t Flag) const
void setHasSpilledSGPRs(bool Spill=true)
unsigned getScratchReservedForDynamicVGPRs() const
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:66
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndexes pass.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:293
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
int64_t getImm() const
Register getReg() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:187
self_iterator getIterator()
Definition ilist_node.h:123
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
@ OPERAND_REG_IMM_V2FP64
Definition SIDefines.h:447
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:465
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:433
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:440
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:456
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:453
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:458
@ OPERAND_REG_IMM_V2INT64
Definition SIDefines.h:443
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:442
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:437
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:432
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:439
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:438
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:441
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:452
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:450
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:444
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:436
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:459
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:470
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:471
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:445
@ OPERAND_SDWA_VOPC_DST
Definition SIDefines.h:482
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:435
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:455
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:451
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:457
@ OPERAND_INLINE_C_AV64_PSEUDO
Definition SIDefines.h:476
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:446
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:472
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:454
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:434
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:462
LLVM_READONLY int32_t getBasicFromSDWAOp(uint32_t Opcode)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
@ TI_SCRATCH_RSRC_DWORD1
Definition AMDGPU.h: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:344
constexpr bool isSDWA(const T &...O)
Definition SIDefines.h:253
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
Definition Threading.h:280
@ Offset
Definition DWP.cpp:578
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
constexpr uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
Definition MathExtras.h:208
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:547
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
Op::Description Desc
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg)
Return the SubReg component from REG_SEQUENCE.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
Definition SIInstrInfo.h:46
constexpr bool has_single_bit(T Value) noexcept
Definition bit.h:149
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
MachineInstr * getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, const MachineRegisterInfo &MRI)
Return the defining instruction for a given reg:subreg pair skipping copy like instructions and subre...
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI VirtRegInfo AnalyzeVirtRegInBundle(MachineInstr &MI, Register Reg, SmallVectorImpl< std::pair< MachineInstr *, unsigned > > *Ops=nullptr)
AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses a virtual register.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
Definition SIInstrInfo.h:54
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:395
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
Definition SIInstrInfo.h:42
constexpr unsigned BitWidth
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition SIInstrInfo.h:50
constexpr T reverseBits(T Val)
Reverse the bits in Val.
Definition MathExtras.h:119
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:573
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
constexpr RegState getUndefRegState(bool B)
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
Definition Uniformity.h:18
@ AlwaysUniform
The result value is always uniform.
Definition Uniformity.h:23
@ NeverUniform
The result value can never be assumed to be uniform.
Definition Uniformity.h:26
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
Definition SIInstrInfo.h:65
bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI)
Return false if EXEC is not changed between the def of VReg at DefMI and all its uses.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
constexpr bool all() const
Definition LaneBitmask.h:54
SparseBitVector AliveBlocks
AliveBlocks - Set of blocks in which this value is alive completely through.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:129
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Utility to store machine instructions worklist.
Definition SIInstrInfo.h:69
MachineInstr * top() const
Definition SIInstrInfo.h:74
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
Definition SIInstrInfo.h:92
void insert(MachineInstr *MI)
A pair composed of a register and a sub-register index.
VirtRegInfo - Information about a virtual register used by a set of operands.
bool Reads
Reads - One of the operands read the virtual register.
bool Writes
Writes - One of the operands writes the virtual register.