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"
33#include "llvm/IR/IntrinsicsAMDGPU.h"
34#include "llvm/MC/MCContext.h"
37#include <tuple>
38
39using namespace llvm;
40
41#define DEBUG_TYPE "si-instr-info"
42
43#define GET_INSTRINFO_CTOR_DTOR
44#include "AMDGPUGenInstrInfo.inc"
45
46namespace llvm::AMDGPU {
47#define GET_ImageDimIntrinsicTable_IMPL
48#define GET_RsrcIntrinsics_IMPL
49#define GET_GFX1250BlockingCyclesTable_DECL
50#define GET_GFX1250BlockingCyclesTable_IMPL
51
56
57#include "AMDGPUGenSearchableTables.inc"
58} // namespace llvm::AMDGPU
59
61 : AMDGPUGenInstrInfo(ST, RI, AMDGPU::ADJCALLSTACKUP,
62 AMDGPU::ADJCALLSTACKDOWN),
63 RI(ST), ST(ST) {
64 SchedModel.init(&ST);
65}
66
67//===----------------------------------------------------------------------===//
68// TargetInstrInfo callbacks
69//===----------------------------------------------------------------------===//
70
71static unsigned getNumOperandsNoGlue(SDNode *Node) {
72 unsigned N = Node->getNumOperands();
73 while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
74 --N;
75 return N;
76}
77
78/// Returns true if both nodes have the same value for the given
79/// operand \p Op, or if both nodes do not have this operand.
81 AMDGPU::OpName OpName) {
82 unsigned Opc0 = N0->getMachineOpcode();
83 unsigned Opc1 = N1->getMachineOpcode();
84
85 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName);
86 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName);
87
88 if (Op0Idx == -1 && Op1Idx == -1)
89 return true;
90
91
92 if ((Op0Idx == -1 && Op1Idx != -1) ||
93 (Op1Idx == -1 && Op0Idx != -1))
94 return false;
95
96 // getNamedOperandIdx returns the index for the MachineInstr's operands,
97 // which includes the result as the first operand. We are indexing into the
98 // MachineSDNode's operands, so we need to skip the result operand to get
99 // the real index.
100 --Op0Idx;
101 --Op1Idx;
102
103 return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx);
104}
105
106static bool canRemat(const MachineInstr &MI) {
107
111 return true;
112
113 if (SIInstrInfo::isSMRD(MI)) {
114 return !MI.memoperands_empty() &&
115 llvm::all_of(MI.memoperands(), [](const MachineMemOperand *MMO) {
116 return MMO->isLoad() && MMO->isInvariant();
117 });
118 }
119
120 return false;
121}
122
123// Split relocation flags for 64-bit global-address materialization into the
124// flags for the lo and hi halves.
125static std::pair<unsigned, unsigned>
127 const unsigned Flags = SrcOp.getTargetFlags();
128
129 // Infer the relocation type from the existing flags on the global operand.
130 // The relocation type should have been determined earlier in the pipeline.
131 switch (Flags & SIInstrInfo::MO_MASK) {
134 // For 64-bit GOT-relative, use the 64-bit relocation.
135 const unsigned GotFlags =
136 (Flags & ~SIInstrInfo::MO_MASK) | SIInstrInfo::MO_GOTPCREL64;
137 return {GotFlags, GotFlags};
138 }
139 default:
140 break;
141 }
142
143 std::optional<unsigned> LoFlags =
145 std::optional<unsigned> HiFlags =
147 if (!LoFlags || !HiFlags)
148 llvm_unreachable("unknown relocation type for global address");
149 return {*LoFlags, *HiFlags};
150}
151
153 const MachineInstr &MI) const {
154
155 if (canRemat(MI)) {
156 // Normally VALU use of exec would block the rematerialization, but that
157 // is OK in this case to have an implicit exec read as all VALU do.
158 // We really want all of the generic logic for this except for this.
159
160 // Another potential implicit use is mode register. The core logic of
161 // the RA will not attempt rematerialization if mode is set anywhere
162 // in the function, otherwise it is safe since mode is not changed.
163
164 // There is difference to generic method which does not allow
165 // rematerialization if there are virtual register uses. We allow this,
166 // therefore this method includes SOP instructions as well.
167 if (!MI.hasImplicitDef() &&
168 MI.getNumImplicitOperands() == MI.getDesc().implicit_uses().size() &&
169 !MI.mayRaiseFPException())
170 return true;
171 }
172
173 // Everything below copied from TargetInstrInfo::isReMaterializableImpl. The
174 // only difference is that we allow operations that perform read-modify-write
175 // on sub-registers.
176
177 // Remat clients assume operand 0 is the defined register.
178 if (!MI.getNumOperands() || !MI.getOperand(0).isReg())
179 return false;
180 Register DefReg = MI.getOperand(0).getReg();
181
182 const MachineFunction &MF = *MI.getMF();
183
184 // A load from a fixed stack slot can be rematerialized. This may be
185 // redundant with subsequent checks, but it's target-independent,
186 // simple, and a common case.
187 int FrameIdx = 0;
188 if (isLoadFromStackSlot(MI, FrameIdx) &&
190 return true;
191
192 // Avoid instructions obviously unsafe for remat.
193 if (MI.isNotDuplicable() || MI.mayStore() || MI.mayRaiseFPException() ||
194 MI.hasUnmodeledSideEffects())
195 return false;
196
197 // Don't remat inline asm. We have no idea how expensive it is
198 // even if it's side effect free.
199 if (MI.isInlineAsm())
200 return false;
201
202 // Avoid instructions which load from potentially varying memory.
203 if (MI.mayLoad() && !MI.isDereferenceableInvariantLoad())
204 return false;
205
206 const MachineRegisterInfo &MRI = MF.getRegInfo();
207
208 // If any of the registers accessed are non-constant, conservatively assume
209 // the instruction is not rematerializable.
210 for (const MachineOperand &MO : MI.operands()) {
211 if (!MO.isReg())
212 continue;
213 Register Reg = MO.getReg();
214 if (Reg == 0)
215 continue;
216
217 // Check for a well-behaved physical register.
218 if (Reg.isPhysical()) {
219 if (MO.isUse()) {
220 // If the physreg has no defs anywhere, it's just an ambient register
221 // and we can freely move its uses. Alternatively, if it's allocatable,
222 // it could get allocated to something with a def during allocation.
223 if (!MRI.isConstantPhysReg(Reg))
224 return false;
225 } else {
226 // A physreg def. We can't remat it.
227 return false;
228 }
229 continue;
230 }
231
232 // Only allow one virtual-register def. There may be multiple defs of the
233 // same virtual register, though.
234 if (MO.isDef() && Reg != DefReg)
235 return false;
236 }
237
238 return true;
239}
240
242 switch (Opcode) {
243 // v_subrev_u16 (gfx9)
244 case AMDGPU::V_SUBREV_U16_e32:
245 case AMDGPU::V_SUBREV_U16_e64:
246 // v_subrev_u32 (gfx9) / v_subrev_nc_u32 (gfx10+)
247 case AMDGPU::V_SUBREV_U32_e32:
248 case AMDGPU::V_SUBREV_U32_e64:
249 // v_subrev_co_u32
250 case AMDGPU::V_SUBREV_CO_U32_e32:
251 case AMDGPU::V_SUBREV_CO_U32_e64:
252 // v_subbrev_u32 (gfx9) / v_subrev_co_ci_u32 (gfx10+)
253 case AMDGPU::V_SUBBREV_U32_e32:
254 case AMDGPU::V_SUBBREV_U32_e64:
255 return true;
256 // REV shift opcodes worked this way before GFX11, verified on hardware
257 case AMDGPU::V_ASHRREV_I16_e32:
258 case AMDGPU::V_ASHRREV_I16_e64:
259 case AMDGPU::V_ASHRREV_I32_e32:
260 case AMDGPU::V_ASHRREV_I32_e64:
261 case AMDGPU::V_ASHRREV_I64_e64:
262 case AMDGPU::V_LSHLREV_B16_e32:
263 case AMDGPU::V_LSHLREV_B16_e64:
264 case AMDGPU::V_LSHLREV_B32_e32:
265 case AMDGPU::V_LSHLREV_B32_e64:
266 case AMDGPU::V_LSHLREV_B64_e64:
267 case AMDGPU::V_LSHRREV_B16_e32:
268 case AMDGPU::V_LSHRREV_B16_e64:
269 case AMDGPU::V_LSHRREV_B32_e32:
270 case AMDGPU::V_LSHRREV_B32_e64:
271 case AMDGPU::V_LSHRREV_B64_e64:
272 return !ST.hasGFX11Insts();
273 default:
274 return false;
275 }
276}
277
278// Returns true if the result of a VALU instruction depends on exec.
279bool SIInstrInfo::resultDependsOnExec(const MachineInstr &MI) const {
280 assert(isVALU(MI, /*AllowLDSDMA=*/true));
281
282 // If it is convergent it depends on EXEC.
283 if (MI.isConvergent())
284 return true;
285
286 // If it defines an SGPR it depends on EXEC, unless it's dead.
287 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
288 for (const MachineOperand &Def : MI.defs()) {
289 if (Def.isDead())
290 continue;
291
292 Register Reg = Def.getReg();
293 if (Reg && RI.isSGPRReg(MRI, Reg))
294 return true;
295 }
296
297 return false;
298}
299
300bool SIInstrInfo::isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const {
301 const MachineOperand &MO = MI.getOperand(OpIdx);
302 // Any implicit use of exec by VALU is not a real register read.
303 return MO.getReg() == AMDGPU::EXEC && MO.isImplicit() &&
304 isVALU(MI, /*AllowLDSDMA=*/true) && !resultDependsOnExec(MI);
305}
306
308 MachineBasicBlock *SuccToSinkTo,
309 MachineCycleInfo *CI) const {
310 // Allow sinking if MI edits lane mask (divergent i1 in sgpr).
311 if (MI.getOpcode() == AMDGPU::SI_IF_BREAK)
312 return true;
313
314 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
315 // Check if sinking of MI would create temporal divergent use.
316 for (auto Op : MI.uses()) {
317 if (Op.isReg() && Op.getReg().isVirtual() &&
318 RI.isSGPRClass(MRI.getRegClass(Op.getReg()))) {
319 MachineInstr *SgprDef = MRI.getVRegDef(Op.getReg());
320 if (!SgprDef)
321 continue;
322
323 // SgprDef defined inside cycle
324 CycleRef FromCycle = CI->getCycle(SgprDef->getParent());
325 if (!FromCycle)
326 continue;
327
328 CycleRef ToCycle = CI->getCycle(SuccToSinkTo);
329 // Check if there is a FromCycle that contains SgprDef's basic block but
330 // does not contain SuccToSinkTo and also has divergent exit condition.
331 while (FromCycle && !(ToCycle && CI->contains(FromCycle, ToCycle))) {
333 CI->getExitingBlocks(FromCycle, ExitingBlocks);
334
335 // FromCycle has divergent exit condition.
336 for (MachineBasicBlock *ExitingBlock : ExitingBlocks) {
337 if (hasDivergentBranch(ExitingBlock))
338 return false;
339 }
340
341 FromCycle = CI->getParentCycle(FromCycle);
342 }
343 }
344 }
345
346 return true;
347}
348
350 int64_t &Offset0,
351 int64_t &Offset1) const {
352 if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode())
353 return false;
354
355 unsigned Opc0 = Load0->getMachineOpcode();
356 unsigned Opc1 = Load1->getMachineOpcode();
357
358 // Make sure both are actually loads.
359 if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad())
360 return false;
361
362 // A mayLoad instruction without a def is not a load. Likely a prefetch.
363 if (!get(Opc0).getNumDefs() || !get(Opc1).getNumDefs())
364 return false;
365
366 if (isDS(Opc0) && isDS(Opc1)) {
367
368 // FIXME: Handle this case:
369 if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1))
370 return false;
371
372 // Check base reg.
373 if (Load0->getOperand(0) != Load1->getOperand(0))
374 return false;
375
376 // Skip read2 / write2 variants for simplicity.
377 // TODO: We should report true if the used offsets are adjacent (excluded
378 // st64 versions).
379 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
380 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
381 if (Offset0Idx == -1 || Offset1Idx == -1)
382 return false;
383
384 // XXX - be careful of dataless loads
385 // getNamedOperandIdx returns the index for MachineInstrs. Since they
386 // include the output in the operand list, but SDNodes don't, we need to
387 // subtract the index by one.
388 Offset0Idx -= get(Opc0).NumDefs;
389 Offset1Idx -= get(Opc1).NumDefs;
390 Offset0 = Load0->getConstantOperandVal(Offset0Idx);
391 Offset1 = Load1->getConstantOperandVal(Offset1Idx);
392 return true;
393 }
394
395 if (isSMRD(Opc0) && isSMRD(Opc1)) {
396 // Skip time and cache invalidation instructions.
397 if (!AMDGPU::hasNamedOperand(Opc0, AMDGPU::OpName::sbase) ||
398 !AMDGPU::hasNamedOperand(Opc1, AMDGPU::OpName::sbase))
399 return false;
400
401 unsigned NumOps = getNumOperandsNoGlue(Load0);
402 if (NumOps != getNumOperandsNoGlue(Load1))
403 return false;
404
405 // Check base reg.
406 if (Load0->getOperand(0) != Load1->getOperand(0))
407 return false;
408
409 // Match register offsets, if both register and immediate offsets present.
410 assert(NumOps == 4 || NumOps == 5);
411 if (NumOps == 5 && Load0->getOperand(1) != Load1->getOperand(1))
412 return false;
413
414 const ConstantSDNode *Load0Offset =
416 const ConstantSDNode *Load1Offset =
418
419 if (!Load0Offset || !Load1Offset)
420 return false;
421
422 Offset0 = Load0Offset->getZExtValue();
423 Offset1 = Load1Offset->getZExtValue();
424 return true;
425 }
426
427 // MUBUF and MTBUF can access the same addresses.
428 if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) {
429
430 // MUBUF and MTBUF have vaddr at different indices.
431 if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) ||
432 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) ||
433 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc))
434 return false;
435
436 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
437 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
438
439 if (OffIdx0 == -1 || OffIdx1 == -1)
440 return false;
441
442 // getNamedOperandIdx returns the index for MachineInstrs. Since they
443 // include the output in the operand list, but SDNodes don't, we need to
444 // subtract the index by one.
445 OffIdx0 -= get(Opc0).NumDefs;
446 OffIdx1 -= get(Opc1).NumDefs;
447
448 SDValue Off0 = Load0->getOperand(OffIdx0);
449 SDValue Off1 = Load1->getOperand(OffIdx1);
450
451 // The offset might be a FrameIndexSDNode.
452 if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1))
453 return false;
454
455 Offset0 = Off0->getAsZExtVal();
456 Offset1 = Off1->getAsZExtVal();
457 return true;
458 }
459
460 return false;
461}
462
463static bool isStride64(unsigned Opc) {
464 switch (Opc) {
465 case AMDGPU::DS_READ2ST64_B32:
466 case AMDGPU::DS_READ2ST64_B64:
467 case AMDGPU::DS_WRITE2ST64_B32:
468 case AMDGPU::DS_WRITE2ST64_B64:
469 return true;
470 default:
471 return false;
472 }
473}
474
477 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const {
478 if (!LdSt.mayLoadOrStore())
479 return false;
480
481 unsigned Opc = LdSt.getOpcode();
482 OffsetIsScalable = false;
483 const MachineOperand *BaseOp, *OffsetOp;
484 int DataOpIdx;
485
486 if (isDS(LdSt)) {
487 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr);
488 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
489 if (OffsetOp) {
490 // Normal, single offset LDS instruction.
491 if (!BaseOp) {
492 // DS_CONSUME/DS_APPEND use M0 for the base address.
493 // TODO: find the implicit use operand for M0 and use that as BaseOp?
494 return false;
495 }
496 BaseOps.push_back(BaseOp);
497 Offset = OffsetOp->getImm();
498 // Get appropriate operand, and compute width accordingly.
499 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
500 if (DataOpIdx == -1)
501 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
502 if (Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
503 Width = LocationSize::precise(64);
504 else
505 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
506 } else {
507 // The 2 offset instructions use offset0 and offset1 instead. We can treat
508 // these as a load with a single offset if the 2 offsets are consecutive.
509 // We will use this for some partially aligned loads.
510 const MachineOperand *Offset0Op =
511 getNamedOperand(LdSt, AMDGPU::OpName::offset0);
512 const MachineOperand *Offset1Op =
513 getNamedOperand(LdSt, AMDGPU::OpName::offset1);
514
515 unsigned Offset0 = Offset0Op->getImm() & 0xff;
516 unsigned Offset1 = Offset1Op->getImm() & 0xff;
517 if (Offset0 + 1 != Offset1)
518 return false;
519
520 // Each of these offsets is in element sized units, so we need to convert
521 // to bytes of the individual reads.
522
523 unsigned EltSize;
524 if (LdSt.mayLoad())
525 EltSize = RI.getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16;
526 else {
527 assert(LdSt.mayStore());
528 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
529 EltSize = RI.getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8;
530 }
531
532 if (isStride64(Opc))
533 EltSize *= 64;
534
535 BaseOps.push_back(BaseOp);
536 Offset = EltSize * Offset0;
537 // Get appropriate operand(s), and compute width accordingly.
538 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
539 if (DataOpIdx == -1) {
540 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
541 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
542 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
543 Width = LocationSize::precise(
544 Width.getValue() + TypeSize::getFixed(getOpSize(LdSt, DataOpIdx)));
545 } else {
546 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
547 }
548 }
549 return true;
550 }
551
552 if (isMUBUF(LdSt) || isMTBUF(LdSt)) {
553 const MachineOperand *RSrc = getNamedOperand(LdSt, AMDGPU::OpName::srsrc);
554 if (!RSrc) // e.g. BUFFER_WBINVL1_VOL
555 return false;
556 BaseOps.push_back(RSrc);
557 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
558 if (BaseOp && !BaseOp->isFI())
559 BaseOps.push_back(BaseOp);
560 const MachineOperand *OffsetImm =
561 getNamedOperand(LdSt, AMDGPU::OpName::offset);
562 Offset = OffsetImm->getImm();
563 const MachineOperand *SOffset =
564 getNamedOperand(LdSt, AMDGPU::OpName::soffset);
565 if (SOffset) {
566 if (SOffset->isReg())
567 BaseOps.push_back(SOffset);
568 else
569 Offset += SOffset->getImm();
570 }
571 // Get appropriate operand, and compute width accordingly.
572 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
573 if (DataOpIdx == -1)
574 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
575 if (DataOpIdx == -1) // LDS DMA
576 return false;
577 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
578 return true;
579 }
580
581 if (isImage(LdSt)) {
582 auto RsrcOpName =
583 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
584 int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RsrcOpName);
585 BaseOps.push_back(&LdSt.getOperand(SRsrcIdx));
586 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
587 if (VAddr0Idx >= 0) {
588 // GFX10 possible NSA encoding.
589 for (int I = VAddr0Idx; I < SRsrcIdx; ++I)
590 BaseOps.push_back(&LdSt.getOperand(I));
591 } else {
592 BaseOps.push_back(getNamedOperand(LdSt, AMDGPU::OpName::vaddr));
593 }
594 Offset = 0;
595 // Get appropriate operand, and compute width accordingly.
596 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
597 if (DataOpIdx == -1)
598 return false; // no return sampler
599 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
600 return true;
601 }
602
603 if (isSMRD(LdSt)) {
604 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::sbase);
605 if (!BaseOp) // e.g. S_MEMTIME
606 return false;
607 BaseOps.push_back(BaseOp);
608 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
609 Offset = OffsetOp ? OffsetOp->getImm() : 0;
610 // Get appropriate operand, and compute width accordingly.
611 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
612 if (DataOpIdx == -1)
613 return false;
614 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
615 return true;
616 }
617
618 if (isFLAT(LdSt)) {
619 // Instructions have either vaddr or saddr or both or none.
620 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
621 if (BaseOp)
622 BaseOps.push_back(BaseOp);
623 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr);
624 if (BaseOp)
625 BaseOps.push_back(BaseOp);
626 Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm();
627 // Get appropriate operand, and compute width accordingly.
628 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
629 if (DataOpIdx == -1)
630 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
631 if (DataOpIdx == -1) // LDS DMA
632 return false;
633 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
634 return true;
635 }
636
637 return false;
638}
639
640static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
642 const MachineInstr &MI2,
644 // Only examine the first "base" operand of each instruction, on the
645 // assumption that it represents the real base address of the memory access.
646 // Other operands are typically offsets or indices from this base address.
647 if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
648 return true;
649
650 if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
651 return false;
652
653 auto *MO1 = *MI1.memoperands_begin();
654 auto *MO2 = *MI2.memoperands_begin();
655 if (MO1->getAddrSpace() != MO2->getAddrSpace())
656 return false;
657
658 const auto *Base1 = MO1->getValue();
659 const auto *Base2 = MO2->getValue();
660 if (!Base1 || !Base2)
661 return false;
662 Base1 = getUnderlyingObject(Base1);
663 Base2 = getUnderlyingObject(Base2);
664
665 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
666 return false;
667
668 return Base1 == Base2;
669}
670
673 ArrayRef<const MachineOperand *> BaseOps2) const {
674 // Accesses without base operands (e.g. scratch addressed only by an
675 // immediate offset) share the same implicit base.
676 if (BaseOps1.empty() || BaseOps2.empty())
677 return BaseOps1.empty() && BaseOps2.empty();
678 return memOpsHaveSameBasePtr(*BaseOps1.front()->getParent(), BaseOps1,
679 *BaseOps2.front()->getParent(), BaseOps2);
680}
681
683 int64_t Offset1, bool OffsetIsScalable1,
685 int64_t Offset2, bool OffsetIsScalable2,
686 unsigned ClusterSize,
687 unsigned NumBytes) const {
688 // If the mem ops (to be clustered) do not have the same base ptr, then they
689 // should not be clustered
690 if (!memOpsHaveSameBase(BaseOps1, BaseOps2))
691 return false;
692
693 // Both lists are empty or neither is, so BaseOps1 alone decides whether
694 // there is an instruction to read the budget from.
695 assert(BaseOps1.empty() == BaseOps2.empty());
696 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;
697 if (!BaseOps1.empty()) {
698 const MachineFunction *MF = BaseOps1.front()->getParent()->getMF();
699 MaxMemoryClusterDWords =
700 MF->getInfo<SIMachineFunctionInfo>()->getMaxMemoryClusterDWords();
701 }
702
703 // In order to avoid register pressure, on an average, the number of DWORDS
704 // loaded together by all clustered mem ops should not exceed
705 // MaxMemoryClusterDWords. This is an empirical value based on certain
706 // observations and performance related experiments.
707 // The good thing about this heuristic is - it avoids clustering of too many
708 // sub-word loads, and also avoids clustering of wide loads. Below is the
709 // brief summary of how the heuristic behaves for various `LoadSize` when
710 // MaxMemoryClusterDWords is 8.
711 //
712 // (1) 1 <= LoadSize <= 4: cluster at max 8 mem ops
713 // (2) 5 <= LoadSize <= 8: cluster at max 4 mem ops
714 // (3) 9 <= LoadSize <= 12: cluster at max 2 mem ops
715 // (4) 13 <= LoadSize <= 16: cluster at max 2 mem ops
716 // (5) LoadSize >= 17: do not cluster
717 const unsigned LoadSize = NumBytes / ClusterSize;
718 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
719 return NumDWords <= MaxMemoryClusterDWords;
720}
721
722// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
723// the first 16 loads will be interleaved with the stores, and the next 16 will
724// be clustered as expected. It should really split into 2 16 store batches.
725//
726// Loads are clustered until this returns false, rather than trying to schedule
727// groups of stores. This also means we have to deal with saying different
728// address space loads should be clustered, and ones which might cause bank
729// conflicts.
730//
731// This might be deprecated so it might not be worth that much effort to fix.
733 int64_t Offset0, int64_t Offset1,
734 unsigned NumLoads) const {
735 assert(Offset1 > Offset0 &&
736 "Second offset should be larger than first offset!");
737 // If we have less than 16 loads in a row, and the offsets are within 64
738 // bytes, then schedule together.
739
740 // A cacheline is 64 bytes (for global memory).
741 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
742}
743
746 const DebugLoc &DL, MCRegister DestReg,
747 MCRegister SrcReg, bool KillSrc,
748 const char *Msg = "illegal VGPR to SGPR copy") {
749 MachineFunction *MF = MBB.getParent();
750
753
754 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg)
755 .addReg(SrcReg, getKillRegState(KillSrc));
756}
757
758/// Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908. It is not
759/// possible to have a direct copy in these cases on GFX908, so an intermediate
760/// VGPR copy is required.
763 const DebugLoc &DL, MCRegister DestReg,
764 MCRegister SrcReg, bool KillSrc,
765 RegScavenger &RS, bool RegsOverlap,
766 Register ImpUseSuperReg = Register()) {
767 assert((TII.getSubtarget().hasMAIInsts() &&
768 !TII.getSubtarget().hasGFX90AInsts()) &&
769 "Expected GFX908 subtarget.");
770
771 assert((AMDGPU::SReg_32RegClass.contains(SrcReg) ||
772 AMDGPU::AGPR_32RegClass.contains(SrcReg)) &&
773 "Source register of the copy should be either an SGPR or an AGPR.");
774
775 assert(AMDGPU::AGPR_32RegClass.contains(DestReg) &&
776 "Destination register of the copy should be an AGPR.");
777
778 const SIRegisterInfo &RI = TII.getRegisterInfo();
779
780 // First try to find defining accvgpr_write to avoid temporary registers.
781 // In the case of copies of overlapping AGPRs, we conservatively do not
782 // reuse previous accvgpr_writes. Otherwise, we may incorrectly pick up
783 // an accvgpr_write used for this same copy due to implicit-defs
784 if (!RegsOverlap) {
785 for (auto Def = MI, E = MBB.begin(); Def != E; ) {
786 --Def;
787
788 if (!Def->modifiesRegister(SrcReg, &RI))
789 continue;
790
791 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
792 Def->getOperand(0).getReg() != SrcReg)
793 break;
794
795 MachineOperand &DefOp = Def->getOperand(1);
796 assert(DefOp.isReg() || DefOp.isImm());
797
798 if (DefOp.isReg()) {
799 bool SafeToPropagate = true;
800 // Check that register source operand is not clobbered before MI.
801 // Immediate operands are always safe to propagate.
802 for (auto I = Def; I != MI && SafeToPropagate; ++I)
803 if (I->modifiesRegister(DefOp.getReg(), &RI))
804 SafeToPropagate = false;
805
806 if (!SafeToPropagate)
807 break;
808
809 for (auto I = Def; I != MI; ++I)
810 I->clearRegisterKills(DefOp.getReg(), &RI);
811 }
812
813 MachineInstrBuilder Builder =
814 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64),
815 DestReg)
816 .add(DefOp);
817
818 if (ImpUseSuperReg) {
819 Builder.addReg(ImpUseSuperReg,
821 }
822
823 return;
824 }
825 }
826
827 RS.enterBasicBlockEnd(MBB);
828 RS.backward(std::next(MI));
829
830 // Ideally we want to have three registers for a long reg_sequence copy
831 // to hide 2 waitstates between v_mov_b32 and accvgpr_write.
832 unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass,
833 *MBB.getParent());
834
835 // Registers in the sequence are allocated contiguously so we can just
836 // use register number to pick one of three round-robin temps.
837 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
838 Register Tmp =
839 MBB.getParent()->getInfo<SIMachineFunctionInfo>()->getVGPRForAGPRCopy();
840 assert(MBB.getParent()->getRegInfo().isReserved(Tmp) &&
841 "VGPR used for an intermediate copy should have been reserved.");
842
843 // Only loop through if there are any free registers left. We don't want to
844 // spill.
845 while (RegNo--) {
846 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI,
847 /* RestoreAfter */ false, 0,
848 /* AllowSpill */ false);
849 if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs)
850 break;
851 Tmp = Tmp2;
852 RS.setRegUsed(Tmp);
853 }
854
855 // Insert copy to temporary VGPR.
856 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
857 if (AMDGPU::AGPR_32RegClass.contains(SrcReg)) {
858 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
859 } else {
860 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
861 }
862
863 MachineInstrBuilder UseBuilder = BuildMI(MBB, MI, DL, TII.get(TmpCopyOp), Tmp)
864 .addReg(SrcReg, getKillRegState(KillSrc));
865 if (ImpUseSuperReg) {
866 UseBuilder.addReg(ImpUseSuperReg,
868 }
869
870 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
871 .addReg(Tmp, RegState::Kill);
872}
873
876 MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
877 const TargetRegisterClass *RC, bool Forward) {
878 const SIRegisterInfo &RI = TII.getRegisterInfo();
879 ArrayRef<int16_t> BaseIndices = RI.getRegSplitParts(RC, 4);
881 MachineInstr *FirstMI = nullptr, *LastMI = nullptr;
882
883 for (unsigned Idx = 0; Idx < BaseIndices.size(); ++Idx) {
884 int16_t SubIdx = BaseIndices[Idx];
885 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
886 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
887 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
888 unsigned Opcode = AMDGPU::S_MOV_B32;
889
890 // Is SGPR aligned? If so try to combine with next.
891 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
892 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
893 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.size())) {
894 // Can use SGPR64 copy
895 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
896 SubIdx = RI.getSubRegFromChannel(Channel, 2);
897 DestSubReg = RI.getSubReg(DestReg, SubIdx);
898 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
899 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
900 Opcode = AMDGPU::S_MOV_B64;
901 Idx++;
902 }
903
904 LastMI = BuildMI(MBB, I, DL, TII.get(Opcode), DestSubReg)
905 .addReg(SrcSubReg)
906 .addReg(SrcReg, RegState::Implicit);
907
908 if (!FirstMI)
909 FirstMI = LastMI;
910
911 if (!Forward)
912 I--;
913 }
914
915 assert(FirstMI && LastMI);
916 if (!Forward)
917 std::swap(FirstMI, LastMI);
918
919 if (KillSrc)
920 LastMI->addRegisterKilled(SrcReg, &RI);
921}
922
925 const DebugLoc &DL, Register DestReg,
926 Register SrcReg, bool KillSrc, bool RenamableDest,
927 bool RenamableSrc) const {
928 const TargetRegisterClass *RC = RI.getPhysRegBaseClass(DestReg);
929 unsigned Size = RI.getRegSizeInBits(*RC);
930 const TargetRegisterClass *SrcRC = RI.getPhysRegBaseClass(SrcReg);
931 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
932
933 // The rest of copyPhysReg assumes Src and Dst size are the same size.
934 // TODO-GFX11_16BIT If all true 16 bit instruction patterns are completed can
935 // we remove fix_16_bit_physreg_copies and this code block?
936 if (ST.getCLOpts().fix_16_bit_physreg_copies) {
937 if (((Size == 16) != (SrcSize == 16))) {
938 // Non-VGPR Src and Dst will later be expanded back to 32 bits.
939 assert(ST.useRealTrue16Insts());
940 Register &RegToFix = (Size == 32) ? DestReg : SrcReg;
941 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
942 RegToFix = SubReg;
943
944 if (DestReg == SrcReg) {
945 // Identity copy. Insert empty bundle since ExpandPostRA expects an
946 // instruction here.
947 BuildMI(MBB, MI, DL, get(AMDGPU::BUNDLE));
948 return;
949 }
950 RC = RI.getPhysRegBaseClass(DestReg);
951 Size = RI.getRegSizeInBits(*RC);
952 SrcRC = RI.getPhysRegBaseClass(SrcReg);
953 SrcSize = RI.getRegSizeInBits(*SrcRC);
954 }
955 }
956
957 if (RC == &AMDGPU::VGPR_32RegClass) {
958 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
959 AMDGPU::SReg_32RegClass.contains(SrcReg) ||
960 AMDGPU::AGPR_32RegClass.contains(SrcReg));
961 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
962 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
963 BuildMI(MBB, MI, DL, get(Opc), DestReg)
964 .addReg(SrcReg, getKillRegState(KillSrc));
965 return;
966 }
967
968 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
969 RC == &AMDGPU::SReg_32RegClass) {
970 if (SrcReg == AMDGPU::SCC) {
971 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg)
972 .addImm(1)
973 .addImm(0);
974 return;
975 }
976
977 if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) {
978 if (DestReg == AMDGPU::VCC_LO) {
979 // FIXME: Hack until VReg_1 removed.
980 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
981 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
982 .addImm(0)
983 .addReg(SrcReg, getKillRegState(KillSrc));
984 return;
985 }
986
987 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
988 return;
989 }
990
991 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
992 .addReg(SrcReg, getKillRegState(KillSrc));
993 return;
994 }
995
996 if (RC == &AMDGPU::SReg_64RegClass) {
997 if (SrcReg == AMDGPU::SCC) {
998 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B64), DestReg)
999 .addImm(1)
1000 .addImm(0);
1001 return;
1002 }
1003
1004 if (!AMDGPU::SReg_64_EncodableRegClass.contains(SrcReg)) {
1005 if (DestReg == AMDGPU::VCC) {
1006 // FIXME: Hack until VReg_1 removed.
1007 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
1008 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
1009 .addImm(0)
1010 .addReg(SrcReg, getKillRegState(KillSrc));
1011 return;
1012 }
1013
1014 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1015 return;
1016 }
1017
1018 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
1019 .addReg(SrcReg, getKillRegState(KillSrc));
1020 return;
1021 }
1022
1023 if (DestReg == AMDGPU::SCC) {
1024 // Copying 64-bit or 32-bit sources to SCC barely makes sense,
1025 // but SelectionDAG emits such copies for i1 sources.
1026 if (AMDGPU::SReg_64RegClass.contains(SrcReg)) {
1027 // This copy can only be produced by patterns
1028 // with explicit SCC, which are known to be enabled
1029 // only for subtargets with S_CMP_LG_U64 present.
1030 assert(ST.hasScalarCompareEq64());
1031 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U64))
1032 .addReg(SrcReg, getKillRegState(KillSrc))
1033 .addImm(0);
1034 } else {
1035 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
1036 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32))
1037 .addReg(SrcReg, getKillRegState(KillSrc))
1038 .addImm(0);
1039 }
1040
1041 return;
1042 }
1043
1044 if (RC == &AMDGPU::AGPR_32RegClass) {
1045 if (AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
1046 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1047 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
1048 .addReg(SrcReg, getKillRegState(KillSrc));
1049 return;
1050 }
1051
1052 if (AMDGPU::AGPR_32RegClass.contains(SrcReg) && ST.hasGFX90AInsts()) {
1053 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_MOV_B32), DestReg)
1054 .addReg(SrcReg, getKillRegState(KillSrc));
1055 return;
1056 }
1057
1058 // FIXME: Pass should maintain scavenger to avoid scan through the block on
1059 // every AGPR spill.
1060 RegScavenger RS;
1061 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1062 indirectCopyToAGPR(*this, MBB, MI, DL, DestReg, SrcReg, KillSrc, RS, Overlap);
1063 return;
1064 }
1065
1066 if (Size == 16) {
1067 assert(AMDGPU::VGPR_16RegClass.contains(SrcReg) ||
1068 AMDGPU::SReg_LO16RegClass.contains(SrcReg) ||
1069 AMDGPU::AGPR_LO16RegClass.contains(SrcReg));
1070
1071 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1072 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1073 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1074 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1075 bool DstLow = !AMDGPU::isHi16Reg(DestReg, RI);
1076 bool SrcLow = !AMDGPU::isHi16Reg(SrcReg, RI);
1077 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1078 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1079
1080 if (IsSGPRDst) {
1081 if (!IsSGPRSrc) {
1082 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1083 return;
1084 }
1085
1086 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), NewDestReg)
1087 .addReg(NewSrcReg, getKillRegState(KillSrc));
1088 return;
1089 }
1090
1091 if (IsAGPRDst || IsAGPRSrc) {
1092 if (!DstLow || !SrcLow) {
1093 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1094 "Cannot use hi16 subreg with an AGPR!");
1095 }
1096
1097 copyPhysReg(MBB, MI, DL, NewDestReg, NewSrcReg, KillSrc);
1098 return;
1099 }
1100
1101 if (ST.useRealTrue16Insts()) {
1102 if (IsSGPRSrc) {
1103 assert(SrcLow);
1104 SrcReg = NewSrcReg;
1105 }
1106 // Use the smaller instruction encoding if possible.
1107 if (AMDGPU::VGPR_16_Lo128RegClass.contains(DestReg) &&
1108 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.contains(SrcReg))) {
1109 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e32), DestReg)
1110 .addReg(SrcReg);
1111 } else {
1112 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e64), DestReg)
1113 .addImm(0) // src0_modifiers
1114 .addReg(SrcReg)
1115 .addImm(0); // op_sel
1116 }
1117 return;
1118 }
1119
1120 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1121 if (!DstLow || !SrcLow) {
1122 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1123 "Cannot use hi16 subreg on VI!");
1124 }
1125
1126 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), NewDestReg)
1127 .addReg(NewSrcReg, getKillRegState(KillSrc));
1128 return;
1129 }
1130
1131 auto MIB = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_sdwa), NewDestReg)
1132 .addImm(0) // src0_modifiers
1133 .addReg(NewSrcReg)
1134 .addImm(0) // clamp
1141 // First implicit operand is $exec.
1142 MIB->tieOperands(0, MIB->getNumOperands() - 1);
1143 return;
1144 }
1145
1146 // Returns true if Dst and Src are in Opc's HwMode-resolved destination and
1147 // source operand classes.
1148 auto CanCopyWith = [&](unsigned Opc, MCRegister Dst, MCRegister Src,
1149 unsigned SrcOp = 1) {
1150 const MCInstrDesc &Desc = get(Opc);
1151 const TargetRegisterClass *DstOpRC = getRegClass(Desc, 0);
1152 const TargetRegisterClass *SrcOpRC = getRegClass(Desc, SrcOp);
1153 return DstOpRC && SrcOpRC && DstOpRC->contains(Dst) &&
1154 SrcOpRC->contains(Src);
1155 };
1156
1157 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1158 if (ST.hasVMovB64Inst() &&
1159 CanCopyWith(AMDGPU::V_MOV_B64_e32, DestReg, SrcReg)) {
1160 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_e32), DestReg)
1161 .addReg(SrcReg, getKillRegState(KillSrc));
1162 return;
1163 }
1164 if (ST.hasPkMovB32() &&
1165 CanCopyWith(AMDGPU::V_PK_MOV_B32, DestReg, SrcReg, /*SrcOp=*/2)) {
1166 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestReg)
1168 .addReg(SrcReg)
1170 .addReg(SrcReg)
1171 .addImm(0) // op_sel_lo
1172 .addImm(0) // op_sel_hi
1173 .addImm(0) // neg_lo
1174 .addImm(0) // neg_hi
1175 .addImm(0) // clamp
1176 .addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
1177 return;
1178 }
1179 }
1180
1181 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1182 if (RI.isSGPRClass(RC)) {
1183 if (!RI.isSGPRClass(SrcRC)) {
1184 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1185 return;
1186 }
1187 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1188 expandSGPRCopy(*this, MBB, MI, DL, DestReg, SrcReg, CanKillSuperReg, RC,
1189 Forward);
1190 return;
1191 }
1192
1193 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1194 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1195 if (RI.isAGPRClass(RC)) {
1196 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1197 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1198 else if (RI.hasVGPRs(SrcRC) ||
1199 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1200 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1201 else
1202 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1203 } else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1204 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1205 } else if (RI.isVGPRClass(RC)) {
1206 if (ST.hasVMovB64Inst())
1207 WideOpcode = AMDGPU::V_MOV_B64_e32;
1208 else if (ST.hasPkMovB32())
1209 WideOpcode = AMDGPU::V_PK_MOV_B32;
1210 }
1211
1212 const TargetRegisterClass *WideDstRC{}, *WideSrcRC{};
1213 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1214 const MCInstrDesc &Desc = get(WideOpcode);
1215 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1216 WideDstRC = getRegClass(Desc, 0);
1217 WideSrcRC = getRegClass(Desc, SrcOp);
1218 }
1219
1220 // If there is an overlap, we can't kill the super-register on the last
1221 // instruction, since it will also kill the components made live by this def.
1222 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1223 const bool CanKillSuperReg = KillSrc && !Overlap;
1224
1225 // For the cases where we need an intermediate instruction/temporary register
1226 // (destination is an AGPR), we need a scavenger.
1227 //
1228 // FIXME: The pass should maintain this for us so we don't have to re-scan the
1229 // whole block for every handled copy.
1230 std::unique_ptr<RegScavenger> RS;
1231 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1232 RS = std::make_unique<RegScavenger>();
1233
1234 ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, 4);
1235
1236 for (unsigned Idx{}; Idx < SubIndices.size();) {
1237 unsigned NumRegs = 1;
1238 unsigned ThisOpcode = Opcode;
1239 unsigned SubIdx =
1240 Forward ? SubIndices[Idx] : SubIndices[SubIndices.size() - Idx - 1];
1241
1242 if (WideDstRC && WideSrcRC && Idx + 1 < SubIndices.size()) {
1243 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1244 if (!Forward)
1245 --Channel;
1246
1247 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1248 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1249 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1250
1251 if (WideDst && WideSrc && WideDstRC->contains(WideDst) &&
1252 WideSrcRC->contains(WideSrc)) {
1253 SubIdx = WideSubIdx;
1254 NumRegs = 2;
1255 ThisOpcode = WideOpcode;
1256 }
1257 }
1258
1259 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1260 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1261 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
1262
1263 Idx += NumRegs;
1264 bool UseKill = CanKillSuperReg && Idx == SubIndices.size();
1265
1266 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1267 Register ImpUseSuper = SrcReg;
1268 indirectCopyToAGPR(*this, MBB, MI, DL, DestSubReg, SrcSubReg, UseKill,
1269 *RS, Overlap, ImpUseSuper);
1270 } else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1271 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestSubReg)
1273 .addReg(SrcSubReg)
1275 .addReg(SrcSubReg)
1276 .addImm(0) // op_sel_lo
1277 .addImm(0) // op_sel_hi
1278 .addImm(0) // neg_lo
1279 .addImm(0) // neg_hi
1280 .addImm(0) // clamp
1281 .addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1282 } else {
1283 MachineInstrBuilder Builder =
1284 BuildMI(MBB, MI, DL, get(ThisOpcode), DestSubReg).addReg(SrcSubReg);
1285
1286 Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1287 }
1288 }
1289}
1290
1291int SIInstrInfo::commuteOpcode(unsigned Opcode) const {
1292 int32_t NewOpc;
1293
1294 // Try to map original to commuted opcode
1295 NewOpc = AMDGPU::getCommuteRev(Opcode);
1296 if (NewOpc != -1)
1297 // Check if the commuted (REV) opcode exists on the target.
1298 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1299
1300 // Try to map commuted to original opcode
1301 NewOpc = AMDGPU::getCommuteOrig(Opcode);
1302 if (NewOpc != -1)
1303 // Check if the original (non-REV) opcode exists on the target.
1304 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1305
1306 return Opcode;
1307}
1308
1310 const Register Reg,
1311 int64_t &ImmVal) const {
1312 switch (MI.getOpcode()) {
1313 case AMDGPU::V_MOV_B32_e32:
1314 case AMDGPU::S_MOV_B32:
1315 case AMDGPU::S_MOVK_I32:
1316 case AMDGPU::S_MOV_B64:
1317 case AMDGPU::V_MOV_B64_e32:
1318 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1319 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1320 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1321 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1322 case AMDGPU::V_MOV_B64_PSEUDO:
1323 case AMDGPU::V_MOV_B16_t16_e32: {
1324 const MachineOperand &Src0 = MI.getOperand(1);
1325 if (Src0.isImm()) {
1326 ImmVal = Src0.getImm();
1327 return MI.getOperand(0).getReg() == Reg;
1328 }
1329
1330 return false;
1331 }
1332 case AMDGPU::V_MOV_B16_t16_e64: {
1333 const MachineOperand &Src0 = MI.getOperand(2);
1334 if (Src0.isImm() && !MI.getOperand(1).getImm()) {
1335 ImmVal = Src0.getImm();
1336 return MI.getOperand(0).getReg() == Reg;
1337 }
1338
1339 return false;
1340 }
1341 case AMDGPU::S_BREV_B32:
1342 case AMDGPU::V_BFREV_B32_e32:
1343 case AMDGPU::V_BFREV_B32_e64: {
1344 const MachineOperand &Src0 = MI.getOperand(1);
1345 if (Src0.isImm()) {
1346 ImmVal = static_cast<int64_t>(reverseBits<int32_t>(Src0.getImm()));
1347 return MI.getOperand(0).getReg() == Reg;
1348 }
1349
1350 return false;
1351 }
1352 case AMDGPU::S_NOT_B32:
1353 case AMDGPU::V_NOT_B32_e32:
1354 case AMDGPU::V_NOT_B32_e64: {
1355 const MachineOperand &Src0 = MI.getOperand(1);
1356 if (Src0.isImm()) {
1357 ImmVal = static_cast<int64_t>(~static_cast<int32_t>(Src0.getImm()));
1358 return MI.getOperand(0).getReg() == Reg;
1359 }
1360
1361 return false;
1362 }
1363 default:
1364 return false;
1365 }
1366}
1367
1368std::optional<int64_t>
1370 const MachineOperand &Op,
1371 MachineInstr **DefMI) const {
1372 if (DefMI)
1373 *DefMI = nullptr;
1374
1375 if (Op.isImm())
1376 return Op.getImm();
1377
1378 if (!Op.isReg() || !Op.getReg().isVirtual())
1379 return std::nullopt;
1380 MachineInstr *Def = MRI.getUniqueVRegDef(Op.getReg());
1381 if (Def && Def->isMoveImmediate()) {
1382 const MachineOperand &ImmSrc = Def->getOperand(1);
1383 if (ImmSrc.isImm()) {
1384 if (DefMI)
1385 *DefMI = Def;
1386 return extractSubregFromImm(ImmSrc.getImm(), Op.getSubReg());
1387 }
1388 }
1389
1390 return std::nullopt;
1391}
1392
1393std::optional<int64_t>
1399
1401
1402 if (RI.isAGPRClass(DstRC))
1403 return AMDGPU::COPY;
1404 if (RI.getRegSizeInBits(*DstRC) == 16) {
1405 // Assume hi bits are unneeded. Only _e64 true16 instructions are legal
1406 // before RA.
1407 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1408 }
1409 if (RI.getRegSizeInBits(*DstRC) == 32)
1410 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1411 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1412 return AMDGPU::S_MOV_B64;
1413 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1414 return AMDGPU::V_MOV_B64_PSEUDO;
1415 return AMDGPU::COPY;
1416}
1417
1418const MCInstrDesc &
1420 bool IsIndirectSrc) const {
1421 if (IsIndirectSrc) {
1422 if (VecSize <= 32) // 4 bytes
1423 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1424 if (VecSize <= 64) // 8 bytes
1425 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1426 if (VecSize <= 96) // 12 bytes
1427 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1428 if (VecSize <= 128) // 16 bytes
1429 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1430 if (VecSize <= 160) // 20 bytes
1431 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1432 if (VecSize <= 192) // 24 bytes
1433 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1434 if (VecSize <= 224) // 28 bytes
1435 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1436 if (VecSize <= 256) // 32 bytes
1437 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1438 if (VecSize <= 288) // 36 bytes
1439 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1440 if (VecSize <= 320) // 40 bytes
1441 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1442 if (VecSize <= 352) // 44 bytes
1443 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1444 if (VecSize <= 384) // 48 bytes
1445 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1446 if (VecSize <= 512) // 64 bytes
1447 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1448 if (VecSize <= 1024) // 128 bytes
1449 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1450
1451 llvm_unreachable("unsupported size for IndirectRegReadGPRIDX pseudos");
1452 }
1453
1454 if (VecSize <= 32) // 4 bytes
1455 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1456 if (VecSize <= 64) // 8 bytes
1457 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1458 if (VecSize <= 96) // 12 bytes
1459 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1460 if (VecSize <= 128) // 16 bytes
1461 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1462 if (VecSize <= 160) // 20 bytes
1463 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1464 if (VecSize <= 192) // 24 bytes
1465 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1466 if (VecSize <= 224) // 28 bytes
1467 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1468 if (VecSize <= 256) // 32 bytes
1469 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1470 if (VecSize <= 288) // 36 bytes
1471 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1472 if (VecSize <= 320) // 40 bytes
1473 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1474 if (VecSize <= 352) // 44 bytes
1475 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1476 if (VecSize <= 384) // 48 bytes
1477 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1478 if (VecSize <= 512) // 64 bytes
1479 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1480 if (VecSize <= 1024) // 128 bytes
1481 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1482
1483 llvm_unreachable("unsupported size for IndirectRegWriteGPRIDX pseudos");
1484}
1485
1486static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize) {
1487 if (VecSize <= 32) // 4 bytes
1488 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1489 if (VecSize <= 64) // 8 bytes
1490 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1491 if (VecSize <= 96) // 12 bytes
1492 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1493 if (VecSize <= 128) // 16 bytes
1494 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1495 if (VecSize <= 160) // 20 bytes
1496 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1497 if (VecSize <= 192) // 24 bytes
1498 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1499 if (VecSize <= 224) // 28 bytes
1500 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1501 if (VecSize <= 256) // 32 bytes
1502 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1503 if (VecSize <= 288) // 36 bytes
1504 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1505 if (VecSize <= 320) // 40 bytes
1506 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1507 if (VecSize <= 352) // 44 bytes
1508 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1509 if (VecSize <= 384) // 48 bytes
1510 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1511 if (VecSize <= 512) // 64 bytes
1512 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1513 if (VecSize <= 1024) // 128 bytes
1514 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1515
1516 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1517}
1518
1519static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize) {
1520 if (VecSize <= 32) // 4 bytes
1521 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1522 if (VecSize <= 64) // 8 bytes
1523 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1524 if (VecSize <= 96) // 12 bytes
1525 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1526 if (VecSize <= 128) // 16 bytes
1527 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1528 if (VecSize <= 160) // 20 bytes
1529 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1530 if (VecSize <= 192) // 24 bytes
1531 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1532 if (VecSize <= 224) // 28 bytes
1533 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1534 if (VecSize <= 256) // 32 bytes
1535 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1536 if (VecSize <= 288) // 36 bytes
1537 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1538 if (VecSize <= 320) // 40 bytes
1539 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1540 if (VecSize <= 352) // 44 bytes
1541 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1542 if (VecSize <= 384) // 48 bytes
1543 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1544 if (VecSize <= 512) // 64 bytes
1545 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1546 if (VecSize <= 1024) // 128 bytes
1547 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1548
1549 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1550}
1551
1552static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize) {
1553 if (VecSize <= 64) // 8 bytes
1554 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1555 if (VecSize <= 128) // 16 bytes
1556 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1557 if (VecSize <= 256) // 32 bytes
1558 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1559 if (VecSize <= 512) // 64 bytes
1560 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1561 if (VecSize <= 1024) // 128 bytes
1562 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1563
1564 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1565}
1566
1567const MCInstrDesc &
1568SIInstrInfo::getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize,
1569 bool IsSGPR) const {
1570 if (IsSGPR) {
1571 switch (EltSize) {
1572 case 32:
1573 return get(getIndirectSGPRWriteMovRelPseudo32(VecSize));
1574 case 64:
1575 return get(getIndirectSGPRWriteMovRelPseudo64(VecSize));
1576 default:
1577 llvm_unreachable("invalid reg indexing elt size");
1578 }
1579 }
1580
1581 assert(EltSize == 32 && "invalid reg indexing elt size");
1583}
1584
1585static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1586 switch (Size) {
1587 case 4:
1588 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1589 case 8:
1590 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1591 case 12:
1592 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1593 case 16:
1594 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1595 : AMDGPU::SI_SPILL_S128_SAVE;
1596 case 20:
1597 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1598 : AMDGPU::SI_SPILL_S160_SAVE;
1599 case 24:
1600 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1601 : AMDGPU::SI_SPILL_S192_SAVE;
1602 case 28:
1603 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1604 : AMDGPU::SI_SPILL_S224_SAVE;
1605 case 32:
1606 return AMDGPU::SI_SPILL_S256_SAVE;
1607 case 36:
1608 return AMDGPU::SI_SPILL_S288_SAVE;
1609 case 40:
1610 return AMDGPU::SI_SPILL_S320_SAVE;
1611 case 44:
1612 return AMDGPU::SI_SPILL_S352_SAVE;
1613 case 48:
1614 return AMDGPU::SI_SPILL_S384_SAVE;
1615 case 64:
1616 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1617 : AMDGPU::SI_SPILL_S512_SAVE;
1618 case 128:
1619 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1620 : AMDGPU::SI_SPILL_S1024_SAVE;
1621 default:
1622 llvm_unreachable("unknown register size");
1623 }
1624}
1625
1626static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1627 switch (Size) {
1628 case 2:
1629 return AMDGPU::SI_SPILL_V16_SAVE;
1630 case 4:
1631 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1632 case 8:
1633 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1634 case 12:
1635 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1636 case 16:
1637 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1638 : AMDGPU::SI_SPILL_V128_SAVE;
1639 case 20:
1640 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1641 : AMDGPU::SI_SPILL_V160_SAVE;
1642 case 24:
1643 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1644 : AMDGPU::SI_SPILL_V192_SAVE;
1645 case 28:
1646 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1647 : AMDGPU::SI_SPILL_V224_SAVE;
1648 case 32:
1649 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1650 : AMDGPU::SI_SPILL_V256_SAVE;
1651 case 36:
1652 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1653 : AMDGPU::SI_SPILL_V288_SAVE;
1654 case 40:
1655 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1656 : AMDGPU::SI_SPILL_V320_SAVE;
1657 case 44:
1658 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1659 : AMDGPU::SI_SPILL_V352_SAVE;
1660 case 48:
1661 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1662 : AMDGPU::SI_SPILL_V384_SAVE;
1663 case 64:
1664 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1665 : AMDGPU::SI_SPILL_V512_SAVE;
1666 case 128:
1667 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1668 : AMDGPU::SI_SPILL_V1024_SAVE;
1669 default:
1670 llvm_unreachable("unknown register size");
1671 }
1672}
1673
1674static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1675 switch (Size) {
1676 case 4:
1677 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1678 : AMDGPU::SI_SPILL_AV32_SAVE;
1679 case 8:
1680 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1681 : AMDGPU::SI_SPILL_AV64_SAVE;
1682 case 12:
1683 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1684 : AMDGPU::SI_SPILL_AV96_SAVE;
1685 case 16:
1686 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1687 : AMDGPU::SI_SPILL_AV128_SAVE;
1688 case 20:
1689 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1690 : AMDGPU::SI_SPILL_AV160_SAVE;
1691 case 24:
1692 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1693 : AMDGPU::SI_SPILL_AV192_SAVE;
1694 case 28:
1695 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1696 : AMDGPU::SI_SPILL_AV224_SAVE;
1697 case 32:
1698 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1699 : AMDGPU::SI_SPILL_AV256_SAVE;
1700 case 36:
1701 return AMDGPU::SI_SPILL_AV288_SAVE;
1702 case 40:
1703 return AMDGPU::SI_SPILL_AV320_SAVE;
1704 case 44:
1705 return AMDGPU::SI_SPILL_AV352_SAVE;
1706 case 48:
1707 return AMDGPU::SI_SPILL_AV384_SAVE;
1708 case 64:
1709 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1710 : AMDGPU::SI_SPILL_AV512_SAVE;
1711 case 128:
1712 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1713 : AMDGPU::SI_SPILL_AV1024_SAVE;
1714 default:
1715 llvm_unreachable("unknown register size");
1716 }
1717}
1718
1719static unsigned getWWMRegSpillSaveOpcode(unsigned Size,
1720 bool IsVectorSuperClass) {
1721 // Currently, there is only 32-bit WWM register spills needed.
1722 if (Size != 4)
1723 llvm_unreachable("unknown wwm register spill size");
1724
1725 if (IsVectorSuperClass)
1726 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1727
1728 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1729}
1730
1732 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1733 const SIMachineFunctionInfo &MFI, bool NeedsCFI) const {
1734 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1735
1736 // Choose the right opcode if spilling a WWM register.
1738 return getWWMRegSpillSaveOpcode(Size, IsVectorSuperClass);
1739
1740 // TODO: Check if AGPRs are available
1741 if (ST.hasMAIInsts())
1742 return getAVSpillSaveOpcode(Size, NeedsCFI);
1743
1744 return getVGPRSpillSaveOpcode(Size, NeedsCFI);
1745}
1746
1747void SIInstrInfo::storeRegToStackSlotImpl(
1749 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1750 MachineInstr::MIFlag Flags, bool NeedsCFI) const {
1751 MachineFunction *MF = MBB.getParent();
1753 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1754 const DebugLoc &DL = MBB.findDebugLoc(MI);
1755
1756 MachinePointerInfo PtrInfo
1757 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1759 PtrInfo, MachineMemOperand::MOStore, FrameInfo.getObjectSize(FrameIndex),
1760 FrameInfo.getObjectAlign(FrameIndex));
1761 unsigned SpillSize = RI.getSpillSize(*RC);
1762
1764 if (RI.isSGPRClass(RC)) {
1765 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1766 MFI->setHasSpilledSGPRs();
1767 assert(SrcReg != AMDGPU::M0 && "m0 should not be spilled");
1768 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1769 SrcReg != AMDGPU::EXEC && "exec should not be spilled");
1770
1771 // We are only allowed to create one new instruction when spilling
1772 // registers, so we need to use pseudo instruction for spilling SGPRs.
1773 const MCInstrDesc &OpDesc =
1774 get(getSGPRSpillSaveOpcode(SpillSize, NeedsCFI));
1775
1776 // The SGPR spill/restore instructions only work on number sgprs, so we need
1777 // to make sure we are using the correct register class.
1778 if (SrcReg.isVirtual() && SpillSize == 4) {
1779 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1780 }
1781
1782 BuildMI(MBB, MI, DL, OpDesc)
1783 .addReg(SrcReg, getKillRegState(isKill)) // data
1784 .addFrameIndex(FrameIndex) // addr
1785 .addMemOperand(MMO)
1787
1788 return;
1789 }
1790
1791 unsigned Opcode = getVectorRegSpillSaveOpcode(VReg ? VReg : SrcReg, RC,
1792 SpillSize, *MFI, NeedsCFI);
1793 MFI->setHasSpilledVGPRs();
1794
1795 BuildMI(MBB, MI, DL, get(Opcode))
1796 .addReg(SrcReg, getKillRegState(isKill)) // data
1797 .addFrameIndex(FrameIndex) // addr
1798 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1799 .addImm(0) // offset
1800 .addMemOperand(MMO);
1801}
1802
1805 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1806 MachineInstr::MIFlag Flags) const {
1807 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1808 false);
1809}
1810
1813 Register SrcReg, bool isKill,
1814 int FrameIndex,
1815 const TargetRegisterClass *RC) const {
1816 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, Register(),
1817 MachineInstr::NoFlags, true);
1818}
1819
1820static unsigned getSGPRSpillRestoreOpcode(unsigned Size) {
1821 switch (Size) {
1822 case 4:
1823 return AMDGPU::SI_SPILL_S32_RESTORE;
1824 case 8:
1825 return AMDGPU::SI_SPILL_S64_RESTORE;
1826 case 12:
1827 return AMDGPU::SI_SPILL_S96_RESTORE;
1828 case 16:
1829 return AMDGPU::SI_SPILL_S128_RESTORE;
1830 case 20:
1831 return AMDGPU::SI_SPILL_S160_RESTORE;
1832 case 24:
1833 return AMDGPU::SI_SPILL_S192_RESTORE;
1834 case 28:
1835 return AMDGPU::SI_SPILL_S224_RESTORE;
1836 case 32:
1837 return AMDGPU::SI_SPILL_S256_RESTORE;
1838 case 36:
1839 return AMDGPU::SI_SPILL_S288_RESTORE;
1840 case 40:
1841 return AMDGPU::SI_SPILL_S320_RESTORE;
1842 case 44:
1843 return AMDGPU::SI_SPILL_S352_RESTORE;
1844 case 48:
1845 return AMDGPU::SI_SPILL_S384_RESTORE;
1846 case 64:
1847 return AMDGPU::SI_SPILL_S512_RESTORE;
1848 case 128:
1849 return AMDGPU::SI_SPILL_S1024_RESTORE;
1850 default:
1851 llvm_unreachable("unknown register size");
1852 }
1853}
1854
1855static unsigned getVGPRSpillRestoreOpcode(unsigned Size) {
1856 switch (Size) {
1857 case 2:
1858 return AMDGPU::SI_SPILL_V16_RESTORE;
1859 case 4:
1860 return AMDGPU::SI_SPILL_V32_RESTORE;
1861 case 8:
1862 return AMDGPU::SI_SPILL_V64_RESTORE;
1863 case 12:
1864 return AMDGPU::SI_SPILL_V96_RESTORE;
1865 case 16:
1866 return AMDGPU::SI_SPILL_V128_RESTORE;
1867 case 20:
1868 return AMDGPU::SI_SPILL_V160_RESTORE;
1869 case 24:
1870 return AMDGPU::SI_SPILL_V192_RESTORE;
1871 case 28:
1872 return AMDGPU::SI_SPILL_V224_RESTORE;
1873 case 32:
1874 return AMDGPU::SI_SPILL_V256_RESTORE;
1875 case 36:
1876 return AMDGPU::SI_SPILL_V288_RESTORE;
1877 case 40:
1878 return AMDGPU::SI_SPILL_V320_RESTORE;
1879 case 44:
1880 return AMDGPU::SI_SPILL_V352_RESTORE;
1881 case 48:
1882 return AMDGPU::SI_SPILL_V384_RESTORE;
1883 case 64:
1884 return AMDGPU::SI_SPILL_V512_RESTORE;
1885 case 128:
1886 return AMDGPU::SI_SPILL_V1024_RESTORE;
1887 default:
1888 llvm_unreachable("unknown register size");
1889 }
1890}
1891
1892static unsigned getAVSpillRestoreOpcode(unsigned Size) {
1893 switch (Size) {
1894 case 4:
1895 return AMDGPU::SI_SPILL_AV32_RESTORE;
1896 case 8:
1897 return AMDGPU::SI_SPILL_AV64_RESTORE;
1898 case 12:
1899 return AMDGPU::SI_SPILL_AV96_RESTORE;
1900 case 16:
1901 return AMDGPU::SI_SPILL_AV128_RESTORE;
1902 case 20:
1903 return AMDGPU::SI_SPILL_AV160_RESTORE;
1904 case 24:
1905 return AMDGPU::SI_SPILL_AV192_RESTORE;
1906 case 28:
1907 return AMDGPU::SI_SPILL_AV224_RESTORE;
1908 case 32:
1909 return AMDGPU::SI_SPILL_AV256_RESTORE;
1910 case 36:
1911 return AMDGPU::SI_SPILL_AV288_RESTORE;
1912 case 40:
1913 return AMDGPU::SI_SPILL_AV320_RESTORE;
1914 case 44:
1915 return AMDGPU::SI_SPILL_AV352_RESTORE;
1916 case 48:
1917 return AMDGPU::SI_SPILL_AV384_RESTORE;
1918 case 64:
1919 return AMDGPU::SI_SPILL_AV512_RESTORE;
1920 case 128:
1921 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1922 default:
1923 llvm_unreachable("unknown register size");
1924 }
1925}
1926
1927static unsigned getWWMRegSpillRestoreOpcode(unsigned Size,
1928 bool IsVectorSuperClass) {
1929 // Currently, there is only 32-bit WWM register spills needed.
1930 if (Size != 4)
1931 llvm_unreachable("unknown wwm register spill size");
1932
1933 if (IsVectorSuperClass) // TODO: Always use this if there are AGPRs
1934 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1935
1936 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1937}
1938
1940 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1941 const SIMachineFunctionInfo &MFI) const {
1942 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1943
1944 // Choose the right opcode if restoring a WWM register.
1946 return getWWMRegSpillRestoreOpcode(Size, IsVectorSuperClass);
1947
1948 // TODO: Check if AGPRs are available
1949 if (ST.hasMAIInsts())
1951
1952 assert(!RI.isAGPRClass(RC));
1954}
1955
1958 Register DestReg, int FrameIndex,
1959 const TargetRegisterClass *RC,
1960 Register VReg, unsigned SubReg,
1961 MachineInstr::MIFlag Flags) const {
1962 MachineFunction *MF = MBB.getParent();
1964 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1965 const DebugLoc &DL = MBB.findDebugLoc(MI);
1966 unsigned SpillSize = RI.getSpillSize(*RC);
1967
1968 MachinePointerInfo PtrInfo
1969 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1970
1972 PtrInfo, MachineMemOperand::MOLoad, FrameInfo.getObjectSize(FrameIndex),
1973 FrameInfo.getObjectAlign(FrameIndex));
1974
1975 if (RI.isSGPRClass(RC)) {
1976 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1977 MFI->setHasSpilledSGPRs();
1978 assert(DestReg != AMDGPU::M0 && "m0 should not be reloaded into");
1979 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1980 DestReg != AMDGPU::EXEC && "exec should not be spilled");
1981
1982 // FIXME: Maybe this should not include a memoperand because it will be
1983 // lowered to non-memory instructions.
1984 const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize));
1985 if (DestReg.isVirtual() && SpillSize == 4) {
1987 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1988 }
1989
1990 BuildMI(MBB, MI, DL, OpDesc, DestReg)
1991 .addFrameIndex(FrameIndex) // addr
1992 .addMemOperand(MMO)
1994
1995 return;
1996 }
1997
1998 unsigned Opcode = getVectorRegSpillRestoreOpcode(VReg ? VReg : DestReg, RC,
1999 SpillSize, *MFI);
2000 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
2001 .addFrameIndex(FrameIndex) // vaddr
2002 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
2003 .addImm(0) // offset
2004 .addMemOperand(MMO);
2005}
2006
2011
2014 unsigned Quantity) const {
2015 DebugLoc DL = MBB.findDebugLoc(MI);
2016 unsigned MaxSNopCount = 1u << ST.getSNopBits();
2017 while (Quantity > 0) {
2018 unsigned Arg = std::min(Quantity, MaxSNopCount);
2019 Quantity -= Arg;
2020 BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
2021 }
2022}
2023
2027 const DebugLoc &DL) const {
2028 MachineFunction *MF = MBB.getParent();
2029 constexpr unsigned DoorbellIDMask = 0x3ff;
2030 constexpr unsigned ECQueueWaveAbort = 0x400;
2031
2032 MachineBasicBlock *TrapBB = &MBB;
2033 MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock();
2034
2035 if (!MBB.succ_empty() ||
2037 /*SkipPseudoOp=*/false) != MBB.end()) {
2038 MBB.splitAt(MI, /*UpdateLiveIns=*/false);
2039 TrapBB = MF->CreateMachineBasicBlock();
2040 BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB);
2041 MF->push_back(TrapBB);
2042 MBB.addSuccessor(TrapBB);
2043 }
2044 // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this
2045 // will be a nop.
2046 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP))
2047 .addImm(static_cast<unsigned>(GCNSubtarget::TrapID::LLVMAMDHSATrap));
2048 Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2049 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32),
2050 DoorbellReg)
2052 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2053 .addUse(AMDGPU::M0);
2054 Register DoorbellRegMasked =
2055 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2056 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2057 .addUse(DoorbellReg)
2058 .addImm(DoorbellIDMask)
2059 .setOperandDead(3); // implicit-def $scc
2060 Register SetWaveAbortBit =
2061 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2062 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2063 .addUse(DoorbellRegMasked)
2064 .addImm(ECQueueWaveAbort)
2065 .setOperandDead(3); // implicit-def $scc
2066 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2067 .addUse(SetWaveAbortBit);
2068 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG))
2070 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2071 .addUse(AMDGPU::TTMP2);
2072 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB);
2073 TrapBB->addSuccessor(HaltLoopBB);
2074
2075 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5);
2076 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH))
2077 .addMBB(HaltLoopBB);
2078 MF->push_back(HaltLoopBB);
2079 HaltLoopBB->addSuccessor(HaltLoopBB);
2080
2081 return MBB.getNextNode();
2082}
2083
2085 switch (MI.getOpcode()) {
2086 default:
2087 if (MI.isMetaInstruction())
2088 return 0;
2089 return 1; // FIXME: Do wait states equal cycles?
2090
2091 case AMDGPU::S_NOP:
2092 return MI.getOperand(0).getImm() + 1;
2093 // SI_RETURN_TO_EPILOG is a fallthrough to code outside of the function. The
2094 // hazard, even if one exist, won't really be visible. Should we handle it?
2095 }
2096}
2097
2099 MachineBasicBlock &MBB = *MI.getParent();
2100 DebugLoc DL = MBB.findDebugLoc(MI);
2102
2103 switch (MI.getOpcode()) {
2104 default: return TargetInstrInfo::expandPostRAPseudo(MI);
2105 case AMDGPU::S_MOV_B64_term:
2106 // This is only a terminator to get the correct spill code placement during
2107 // register allocation.
2108 MI.setDesc(get(AMDGPU::S_MOV_B64));
2109 break;
2110
2111 case AMDGPU::S_MOV_B32_term:
2112 // This is only a terminator to get the correct spill code placement during
2113 // register allocation.
2114 MI.setDesc(get(AMDGPU::S_MOV_B32));
2115 break;
2116
2117 case AMDGPU::S_XOR_B64_term:
2118 // This is only a terminator to get the correct spill code placement during
2119 // register allocation.
2120 MI.setDesc(get(AMDGPU::S_XOR_B64));
2121 break;
2122
2123 case AMDGPU::S_XOR_B32_term:
2124 // This is only a terminator to get the correct spill code placement during
2125 // register allocation.
2126 MI.setDesc(get(AMDGPU::S_XOR_B32));
2127 break;
2128 case AMDGPU::S_OR_B64_term:
2129 // This is only a terminator to get the correct spill code placement during
2130 // register allocation.
2131 MI.setDesc(get(AMDGPU::S_OR_B64));
2132 break;
2133 case AMDGPU::S_OR_B32_term:
2134 // This is only a terminator to get the correct spill code placement during
2135 // register allocation.
2136 MI.setDesc(get(AMDGPU::S_OR_B32));
2137 break;
2138
2139 case AMDGPU::S_ANDN2_B64_term:
2140 // This is only a terminator to get the correct spill code placement during
2141 // register allocation.
2142 MI.setDesc(get(AMDGPU::S_ANDN2_B64));
2143 break;
2144
2145 case AMDGPU::S_ANDN2_B32_term:
2146 // This is only a terminator to get the correct spill code placement during
2147 // register allocation.
2148 MI.setDesc(get(AMDGPU::S_ANDN2_B32));
2149 break;
2150
2151 case AMDGPU::S_AND_B64_term:
2152 // This is only a terminator to get the correct spill code placement during
2153 // register allocation.
2154 MI.setDesc(get(AMDGPU::S_AND_B64));
2155 break;
2156
2157 case AMDGPU::S_AND_B32_term:
2158 // This is only a terminator to get the correct spill code placement during
2159 // register allocation.
2160 MI.setDesc(get(AMDGPU::S_AND_B32));
2161 break;
2162
2163 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2164 // This is only a terminator to get the correct spill code placement during
2165 // register allocation.
2166 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B64));
2167 break;
2168
2169 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2170 // This is only a terminator to get the correct spill code placement during
2171 // register allocation.
2172 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B32));
2173 break;
2174
2175 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2176 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2177 break;
2178 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2179 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2180 break;
2181
2182 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2183 MI.setDesc(get(AMDGPU::V_WRITELANE_B32));
2184 break;
2185
2186 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2187 MI.setDesc(get(AMDGPU::V_READLANE_B32));
2188 break;
2189 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2190 Register Dst = MI.getOperand(0).getReg();
2191 bool IsAGPR = SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst));
2192 MI.setDesc(
2193 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2194 break;
2195 }
2196 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2197 Register Dst = MI.getOperand(0).getReg();
2198 if (SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst))) {
2199 int64_t Imm = MI.getOperand(1).getImm();
2200
2201 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2202 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2203 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstLo)
2205 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstHi)
2206 .addImm(SignExtend64<32>(Imm >> 32));
2207 MI.eraseFromParent();
2208 break;
2209 }
2210
2211 [[fallthrough]];
2212 }
2213 case AMDGPU::V_MOV_B64_PSEUDO: {
2214 Register Dst = MI.getOperand(0).getReg();
2215 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2216 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2217
2218 const MCInstrDesc &Mov64Desc = get(AMDGPU::V_MOV_B64_e32);
2219 const TargetRegisterClass *Mov64RC = getRegClass(Mov64Desc, /*OpNum=*/0);
2220
2221 const MachineOperand &SrcOp = MI.getOperand(1);
2222 // FIXME: Will this work for 64-bit floating point immediates?
2223 assert(!SrcOp.isFPImm());
2224 if (ST.hasVMovB64Inst() && Mov64RC->contains(Dst)) {
2225 MI.setDesc(Mov64Desc);
2226 if (SrcOp.isReg() || isInlineConstant(MI, 1) ||
2227 (SrcOp.isImm() &&
2228 (isUInt<32>(SrcOp.getImm()) || ST.has64BitLiterals())) ||
2229 (SrcOp.isGlobal() && ST.has64BitLiterals()))
2230 break;
2231 }
2232 if (SrcOp.isGlobal()) {
2233 // The address is unknown until link time, so the PK_MOV inline-constant
2234 // shortcut cannot apply.
2235 const GlobalValue *GV = SrcOp.getGlobal();
2236 int64_t Offset = SrcOp.getOffset();
2237 auto [LoFlags, HiFlags] = splitGlobalAddressRelocFlags(SrcOp);
2238
2239 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2240 .addGlobalAddress(GV, Offset, LoFlags);
2241 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2242 .addGlobalAddress(GV, Offset, HiFlags);
2243 } else if (SrcOp.isImm()) {
2244 APInt Imm(64, SrcOp.getImm());
2245 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2246 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2247 const MCInstrDesc &PkMovDesc = get(AMDGPU::V_PK_MOV_B32);
2248 const TargetRegisterClass *PkMovRC = getRegClass(PkMovDesc, /*OpNum=*/0);
2249
2250 if (ST.hasPkMovB32() && Lo == Hi && isInlineConstant(Lo) &&
2251 PkMovRC->contains(Dst)) {
2252 BuildMI(MBB, MI, DL, PkMovDesc, Dst)
2254 .addImm(Lo.getSExtValue())
2256 .addImm(Lo.getSExtValue())
2257 .addImm(0) // op_sel_lo
2258 .addImm(0) // op_sel_hi
2259 .addImm(0) // neg_lo
2260 .addImm(0) // neg_hi
2261 .addImm(0); // clamp
2262 } else {
2263 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2264 .addImm(Lo.getSExtValue());
2265 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2266 .addImm(Hi.getSExtValue());
2267 }
2268 } else {
2269 assert(SrcOp.isReg());
2270 if (ST.hasPkMovB32() &&
2271 !RI.isAGPR(MBB.getParent()->getRegInfo(), SrcOp.getReg())) {
2272 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), Dst)
2273 .addImm(SISrcMods::OP_SEL_1) // src0_mod
2274 .addReg(SrcOp.getReg())
2276 .addReg(SrcOp.getReg())
2277 .addImm(0) // op_sel_lo
2278 .addImm(0) // op_sel_hi
2279 .addImm(0) // neg_lo
2280 .addImm(0) // neg_hi
2281 .addImm(0); // clamp
2282 } else {
2283 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2284 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0));
2285 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2286 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1));
2287 }
2288 }
2289 MI.eraseFromParent();
2290 break;
2291 }
2292 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2294 break;
2295 }
2296 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2297 const MachineOperand &SrcOp = MI.getOperand(1);
2298 assert(!SrcOp.isFPImm());
2299
2300 if (ST.has64BitLiterals()) {
2301 MI.setDesc(get(AMDGPU::S_MOV_B64));
2302 break;
2303 }
2304
2305 if (SrcOp.isGlobal()) {
2306 Register Dst = MI.getOperand(0).getReg();
2307 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2308 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2309 const GlobalValue *GV = SrcOp.getGlobal();
2310 int64_t Offset = SrcOp.getOffset();
2311 auto [LoFlags, HiFlags] = splitGlobalAddressRelocFlags(SrcOp);
2312
2313 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2314 .addGlobalAddress(GV, Offset, LoFlags);
2315 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2316 .addGlobalAddress(GV, Offset, HiFlags);
2317 MI.eraseFromParent();
2318 break;
2319 }
2320
2321 // SrcOp is immediate
2322 APInt Imm(64, SrcOp.getImm());
2323 if (Imm.isIntN(32) || isInlineConstant(Imm)) {
2324 MI.setDesc(get(AMDGPU::S_MOV_B64));
2325 break;
2326 }
2327
2328 Register Dst = MI.getOperand(0).getReg();
2329 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2330 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2331
2332 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2333 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2334 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2335 .addImm(Lo.getSExtValue());
2336 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2337 .addImm(Hi.getSExtValue());
2338 MI.eraseFromParent();
2339 break;
2340 }
2341 case AMDGPU::V_SET_INACTIVE_B32: {
2342 // Lower V_SET_INACTIVE_B32 to V_CNDMASK_B32.
2343 Register DstReg = MI.getOperand(0).getReg();
2344 BuildMI(MBB, MI, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2345 .add(MI.getOperand(3))
2346 .add(MI.getOperand(4))
2347 .add(MI.getOperand(1))
2348 .add(MI.getOperand(2))
2349 .add(MI.getOperand(5));
2350 MI.eraseFromParent();
2351 break;
2352 }
2353 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2354 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2355 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2356 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2357 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2358 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2359 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2360 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2361 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2362 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2363 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2364 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2365 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2366 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2367 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2368 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2369 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2370 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2371 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2372 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2373 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2374 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2375 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2376 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2377 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2378 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2379 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2380 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2381 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2382 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2383 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2384 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2385 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2386 const TargetRegisterClass *EltRC = getOpRegClass(MI, 2);
2387
2388 unsigned Opc;
2389 if (RI.hasVGPRs(EltRC)) {
2390 Opc = AMDGPU::V_MOVRELD_B32_e32;
2391 } else {
2392 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2393 : AMDGPU::S_MOVRELD_B32;
2394 }
2395
2396 const MCInstrDesc &OpDesc = get(Opc);
2397 Register VecReg = MI.getOperand(0).getReg();
2398 bool IsUndef = MI.getOperand(1).isUndef();
2399 unsigned SubReg = MI.getOperand(3).getImm();
2400 assert(VecReg == MI.getOperand(1).getReg());
2401
2403 BuildMI(MBB, MI, DL, OpDesc)
2404 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2405 .add(MI.getOperand(2))
2407 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2408
2409 const int ImpDefIdx =
2410 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2411 const int ImpUseIdx = ImpDefIdx + 1;
2412 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2413 MI.eraseFromParent();
2414 break;
2415 }
2416 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2417 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2418 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2419 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2420 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2421 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2422 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2423 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2424 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2425 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2426 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2427 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2428 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2429 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2430 assert(ST.useVGPRIndexMode());
2431 Register VecReg = MI.getOperand(0).getReg();
2432 bool IsUndef = MI.getOperand(1).isUndef();
2433 MachineOperand &Idx = MI.getOperand(3);
2434 Register SubReg = MI.getOperand(4).getImm();
2435
2436 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2437 .add(Idx)
2439 SetOn->getOperand(3).setIsUndef();
2440
2441 const MCInstrDesc &OpDesc = get(AMDGPU::V_MOV_B32_indirect_write);
2443 BuildMI(MBB, MI, DL, OpDesc)
2444 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2445 .add(MI.getOperand(2))
2447 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2448
2449 const int ImpDefIdx =
2450 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2451 const int ImpUseIdx = ImpDefIdx + 1;
2452 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2453
2454 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2455
2456 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2457
2458 MI.eraseFromParent();
2459 break;
2460 }
2461 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2462 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2463 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2464 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2465 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2466 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2467 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2468 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2469 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2470 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2471 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2472 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2473 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2474 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2475 assert(ST.useVGPRIndexMode());
2476 Register Dst = MI.getOperand(0).getReg();
2477 Register VecReg = MI.getOperand(1).getReg();
2478 bool IsUndef = MI.getOperand(1).isUndef();
2479 Register SubReg = MI.getOperand(3).getImm();
2480
2481 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2482 .add(MI.getOperand(2))
2484 SetOn->getOperand(3).setIsUndef();
2485
2486 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_indirect_read))
2487 .addDef(Dst)
2488 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2489 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2490
2491 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2492
2493 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2494
2495 MI.eraseFromParent();
2496 break;
2497 }
2498 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2499 MachineFunction &MF = *MBB.getParent();
2500 Register Reg = MI.getOperand(0).getReg();
2501 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2502 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2503 MachineOperand OpLo = MI.getOperand(1);
2504 MachineOperand OpHi = MI.getOperand(2);
2505
2506 // Create a bundle so these instructions won't be re-ordered by the
2507 // post-RA scheduler.
2508 MIBundleBuilder Bundler(MBB, MI);
2509 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2510
2511 // What we want here is an offset from the value returned by s_getpc (which
2512 // is the address of the s_add_u32 instruction) to the global variable, but
2513 // since the encoding of $symbol starts 4 bytes after the start of the
2514 // s_add_u32 instruction, we end up with an offset that is 4 bytes too
2515 // small. This requires us to add 4 to the global variable offset in order
2516 // to compute the correct address. Similarly for the s_addc_u32 instruction,
2517 // the encoding of $symbol starts 12 bytes after the start of the s_add_u32
2518 // instruction.
2519
2520 int64_t Adjust = 0;
2521 if (ST.hasGetPCZeroExtension()) {
2522 // Fix up hardware that does not sign-extend the 48-bit PC value by
2523 // inserting: s_sext_i32_i16 reghi, reghi
2524 Bundler.append(
2525 BuildMI(MF, DL, get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2526 Adjust += 4;
2527 }
2528
2529 if (OpLo.isGlobal())
2530 OpLo.setOffset(OpLo.getOffset() + Adjust + 4);
2531 Bundler.append(
2532 BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2533
2534 if (OpHi.isGlobal())
2535 OpHi.setOffset(OpHi.getOffset() + Adjust + 12);
2536 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi)
2537 .addReg(RegHi)
2538 .add(OpHi));
2539
2540 finalizeBundle(MBB, Bundler.begin());
2541
2542 MI.eraseFromParent();
2543 break;
2544 }
2545 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2546 MachineFunction &MF = *MBB.getParent();
2547 Register Reg = MI.getOperand(0).getReg();
2548 MachineOperand Op = MI.getOperand(1);
2549
2550 // Create a bundle so these instructions won't be re-ordered by the
2551 // post-RA scheduler.
2552 MIBundleBuilder Bundler(MBB, MI);
2553 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2554 if (Op.isGlobal())
2555 Op.setOffset(Op.getOffset() + 4);
2556 Bundler.append(
2557 BuildMI(MF, DL, get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(Op));
2558
2559 finalizeBundle(MBB, Bundler.begin());
2560
2561 MI.eraseFromParent();
2562 break;
2563 }
2564 case AMDGPU::ENTER_STRICT_WWM: {
2565 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2566 // Whole Wave Mode is entered.
2567 MI.setDesc(get(LMC.OrSaveExecOpc));
2568 break;
2569 }
2570 case AMDGPU::ENTER_STRICT_WQM: {
2571 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2572 // STRICT_WQM is entered.
2573 BuildMI(MBB, MI, DL, get(LMC.MovOpc), MI.getOperand(0).getReg())
2574 .addReg(LMC.ExecReg);
2575 BuildMI(MBB, MI, DL, get(LMC.WQMOpc), LMC.ExecReg).addReg(LMC.ExecReg);
2576
2577 MI.eraseFromParent();
2578 break;
2579 }
2580 case AMDGPU::EXIT_STRICT_WWM:
2581 case AMDGPU::EXIT_STRICT_WQM: {
2582 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2583 // WWM/STICT_WQM is exited.
2584 MI.setDesc(get(LMC.MovOpc));
2585 break;
2586 }
2587 case AMDGPU::SI_RETURN: {
2588 const MachineFunction *MF = MBB.getParent();
2589 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2590 const SIRegisterInfo *TRI = ST.getRegisterInfo();
2591 // Hiding the return address use with SI_RETURN may lead to extra kills in
2592 // the function and missing live-ins. We are fine in practice because callee
2593 // saved register handling ensures the register value is restored before
2594 // RET, but we need the undef flag here to appease the MachineVerifier
2595 // liveness checks.
2597 BuildMI(MBB, MI, DL, get(AMDGPU::S_SETPC_B64_return))
2598 .addReg(TRI->getReturnAddressReg(*MF), RegState::Undef);
2599
2600 MIB.copyImplicitOps(MI);
2601 MI.eraseFromParent();
2602 break;
2603 }
2604
2605 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2606 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2607 MI.setDesc(get(AMDGPU::S_MUL_U64));
2608 break;
2609
2610 case AMDGPU::S_GETPC_B64_pseudo:
2611 MI.setDesc(get(AMDGPU::S_GETPC_B64));
2612 if (ST.hasGetPCZeroExtension()) {
2613 Register Dst = MI.getOperand(0).getReg();
2614 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2615 // Fix up hardware that does not sign-extend the 48-bit PC value by
2616 // inserting: s_sext_i32_i16 dsthi, dsthi
2617 BuildMI(MBB, std::next(MI.getIterator()), DL, get(AMDGPU::S_SEXT_I32_I16),
2618 DstHi)
2619 .addReg(DstHi);
2620 }
2621 break;
2622
2623 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2624 assert(ST.hasBF16PackedInsts());
2625 MI.setDesc(get(AMDGPU::V_PK_MAX_NUM_BF16));
2626 MI.addOperand(MachineOperand::CreateImm(0)); // op_sel
2627 MI.addOperand(MachineOperand::CreateImm(0)); // neg_lo
2628 MI.addOperand(MachineOperand::CreateImm(0)); // neg_hi
2629 auto Op0 = getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
2630 Op0->setImm(Op0->getImm() | SISrcMods::OP_SEL_1);
2631 auto Op1 = getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
2632 Op1->setImm(Op1->getImm() | SISrcMods::OP_SEL_1);
2633 break;
2634 }
2635
2636 case AMDGPU::GET_STACK_BASE:
2637 // The stack starts at offset 0 unless we need to reserve some space at the
2638 // bottom.
2639 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*MBB.getParent())) {
2640 // When CWSR is used in dynamic VGPR mode, the trap handler needs to save
2641 // some of the VGPRs. The size of the required scratch space has already
2642 // been computed by prolog epilog insertion.
2643 const SIMachineFunctionInfo *MFI =
2644 MBB.getParent()->getInfo<SIMachineFunctionInfo>();
2645 unsigned VGPRSize = MFI->getScratchReservedForDynamicVGPRs();
2646 Register DestReg = MI.getOperand(0).getReg();
2647 BuildMI(MBB, MI, DL, get(AMDGPU::S_GETREG_B32), DestReg)
2650 // The MicroEngine ID is 0 for the graphics queue, and 1 or 2 for compute
2651 // (3 is unused, so we ignore it). Unfortunately, S_GETREG doesn't set
2652 // SCC, so we need to check for 0 manually.
2653 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)).addImm(0).addReg(DestReg);
2654 // Change the implicif-def of SCC to an explicit use (but first remove
2655 // the dead flag if present).
2656 MI.getOperand(MI.getNumExplicitOperands()).setIsDead(false);
2657 MI.getOperand(MI.getNumExplicitOperands()).setIsUse();
2658 MI.setDesc(get(AMDGPU::S_CMOVK_I32));
2659 MI.addOperand(MachineOperand::CreateImm(VGPRSize));
2660 } else {
2661 MI.setDesc(get(AMDGPU::S_MOV_B32));
2662 MI.addOperand(MachineOperand::CreateImm(0));
2663 MI.removeOperand(
2664 MI.getNumExplicitOperands()); // Drop implicit def of SCC.
2665 }
2666 break;
2667 }
2668
2669 return true;
2670}
2671
2674 unsigned SubIdx, const MachineInstr &Orig,
2675 LaneBitmask UsedLanes) const {
2676
2677 // Try shrinking the instruction to remat only the part needed for current
2678 // context.
2679 // TODO: Handle more cases.
2680 unsigned Opcode = Orig.getOpcode();
2681 switch (Opcode) {
2682 case AMDGPU::S_MOV_B64:
2683 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2684 if (SubIdx != 0)
2685 break;
2686
2687 if (!Orig.getOperand(1).isImm())
2688 break;
2689
2690 // Shrink S_MOV_B64 to S_MOV_B32 when UsedLanes indicates only a single
2691 // 32-bit lane of the 64-bit value is live at the rematerialization point.
2692 if (UsedLanes.all())
2693 break;
2694
2695 // Determine which half of the 64-bit immediate corresponds to the use.
2696 unsigned OrigSubReg = Orig.getOperand(0).getSubReg();
2697 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2698 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2699
2700 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2701 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2702
2703 if (NeedLo && NeedHi)
2704 break;
2705
2706 int64_t Imm64 = Orig.getOperand(1).getImm();
2707 int32_t Imm32 = NeedLo ? Lo_32(Imm64) : Hi_32(Imm64);
2708
2709 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2710
2711 // Emit S_MOV_B32 defining just the needed 32-bit subreg of DestReg.
2712 BuildMI(MBB, I, Orig.getDebugLoc(), get(AMDGPU::S_MOV_B32))
2713 .addReg(DestReg, RegState::Define | RegState::Undef, UseSubReg)
2714 .addImm(Imm32);
2715 return;
2716 }
2717
2718 case AMDGPU::S_LOAD_DWORDX16_IMM:
2719 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2720 if (SubIdx != 0 || UsedLanes.all())
2721 break;
2722
2723 if (I == MBB.end())
2724 break;
2725
2726 if (I->isBundled())
2727 break;
2728
2729 MachineFunction *MF = MBB.getParent();
2731 assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");
2732
2733 // Look for a single use of the register at the insertion point that is also
2734 // a subreg.
2735 Register RegToFind = Orig.getOperand(0).getReg();
2736 MachineOperand *UseMO = MRI.getOneNonDBGUse(RegToFind);
2737 if (!UseMO ||
2738 UseMO != I->findRegisterUseOperand(RegToFind, /*TRI=*/nullptr) ||
2739 UseMO->getSubReg() == AMDGPU::NoSubRegister)
2740 break;
2741
2742 unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
2743 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());
2744
2745 unsigned NewOpcode = -1;
2746 if (SubregSize == 256)
2747 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2748 else if (SubregSize == 128)
2749 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2750 else
2751 break;
2752
2753 const MCInstrDesc &TID = get(NewOpcode);
2754 const TargetRegisterClass *NewRC =
2755 RI.getAllocatableClass(getRegClass(TID, 0));
2756 MRI.setRegClass(DestReg, NewRC);
2757
2758 UseMO->setReg(DestReg);
2759 UseMO->setSubReg(AMDGPU::NoSubRegister);
2760
2761 // Use a smaller load with the desired size, possibly with updated offset.
2762 MachineInstr *MI = MF->CloneMachineInstr(&Orig);
2763 MI->setDesc(TID);
2764 MI->getOperand(0).setReg(DestReg);
2765 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2766 if (Offset) {
2767 MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
2768 int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
2769 OffsetMO->setImm(FinalOffset);
2770 }
2772 for (const MachineMemOperand *MemOp : Orig.memoperands())
2773 NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
2774 SubregSize / 8));
2775 MI->setMemRefs(*MF, NewMMOs);
2776
2777 MBB.insert(I, MI);
2778 return;
2779 }
2780
2781 default:
2782 break;
2783 }
2784
2785 TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
2786}
2787
2788std::pair<MachineInstr*, MachineInstr*>
2790 assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2791
2792 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2794 ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
2795 MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
2796 return std::pair(&MI, nullptr);
2797 }
2798
2799 MachineBasicBlock &MBB = *MI.getParent();
2800 DebugLoc DL = MBB.findDebugLoc(MI);
2801 MachineFunction *MF = MBB.getParent();
2803 Register Dst = MI.getOperand(0).getReg();
2804 unsigned Part = 0;
2805 MachineInstr *Split[2];
2806
2807 for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2808 auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
2809 if (Dst.isPhysical()) {
2810 MovDPP.addDef(RI.getSubReg(Dst, Sub));
2811 } else {
2812 assert(MRI.isSSA());
2813 auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2814 MovDPP.addDef(Tmp);
2815 }
2816
2817 for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
2818 const MachineOperand &SrcOp = MI.getOperand(I);
2819 assert(!SrcOp.isFPImm());
2820 if (SrcOp.isImm()) {
2821 APInt Imm(64, SrcOp.getImm());
2822 Imm.ashrInPlace(Part * 32);
2823 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2824 } else {
2825 assert(SrcOp.isReg());
2826 Register Src = SrcOp.getReg();
2827 if (Src.isPhysical())
2828 MovDPP.addReg(RI.getSubReg(Src, Sub));
2829 else
2830 MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
2831 }
2832 }
2833
2834 for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
2835 MovDPP.addImm(MO.getImm());
2836
2837 Split[Part] = MovDPP;
2838 ++Part;
2839 }
2840
2841 if (Dst.isVirtual())
2842 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
2843 .addReg(Split[0]->getOperand(0).getReg())
2844 .addImm(AMDGPU::sub0)
2845 .addReg(Split[1]->getOperand(0).getReg())
2846 .addImm(AMDGPU::sub1);
2847
2848 MI.eraseFromParent();
2849 return std::pair(Split[0], Split[1]);
2850}
2851
2852std::optional<DestSourcePair>
2854 if (MI.getOpcode() == AMDGPU::WWM_COPY)
2855 return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
2856
2857 return std::nullopt;
2858}
2859
2861 AMDGPU::OpName Src0OpName,
2862 MachineOperand &Src1,
2863 AMDGPU::OpName Src1OpName) const {
2864 MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
2865 if (!Src0Mods)
2866 return false;
2867
2868 MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
2869 assert(Src1Mods &&
2870 "All commutable instructions have both src0 and src1 modifiers");
2871
2872 int Src0ModsVal = Src0Mods->getImm();
2873 int Src1ModsVal = Src1Mods->getImm();
2874
2875 Src1Mods->setImm(Src0ModsVal);
2876 Src0Mods->setImm(Src1ModsVal);
2877 return true;
2878}
2879
2881 MachineOperand &RegOp,
2882 MachineOperand &NonRegOp) {
2883 Register Reg = RegOp.getReg();
2884 unsigned SubReg = RegOp.getSubReg();
2885 bool IsKill = RegOp.isKill();
2886 bool IsDead = RegOp.isDead();
2887 bool IsUndef = RegOp.isUndef();
2888 bool IsDebug = RegOp.isDebug();
2889
2890 if (NonRegOp.isImm())
2891 RegOp.ChangeToImmediate(NonRegOp.getImm());
2892 else if (NonRegOp.isFI())
2893 RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
2894 else if (NonRegOp.isGlobal()) {
2895 RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
2896 NonRegOp.getTargetFlags());
2897 } else
2898 return nullptr;
2899
2900 // Make sure we don't reinterpret a subreg index in the target flags.
2901 RegOp.setTargetFlags(NonRegOp.getTargetFlags());
2902
2903 NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
2904 NonRegOp.setSubReg(SubReg);
2905
2906 return &MI;
2907}
2908
2910 MachineOperand &NonRegOp1,
2911 MachineOperand &NonRegOp2) {
2912 unsigned TargetFlags = NonRegOp1.getTargetFlags();
2913 int64_t NonRegVal = NonRegOp1.getImm();
2914
2915 NonRegOp1.setImm(NonRegOp2.getImm());
2916 NonRegOp2.setImm(NonRegVal);
2917 NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
2918 NonRegOp2.setTargetFlags(TargetFlags);
2919 return &MI;
2920}
2921
2922// GFX950 v_pk_{add,mul}_f32 must not have opsel[1:0] == 2'b10, i.e. OP_SEL_0 on
2923// src1 but not on src0, and v_pk_fma_f32 must not have OP_SEL_0 on src1 or
2924// src2.
2926 bool CheckSwappedSrc = false) {
2927 unsigned Opc = MI.getOpcode();
2928 if (!TII.getSubtarget().hasPkF32InvalidOpSel() ||
2929 (Opc != AMDGPU::V_PK_ADD_F32 && Opc != AMDGPU::V_PK_MUL_F32 &&
2930 Opc != AMDGPU::V_PK_FMA_F32))
2931 return true;
2932
2933 auto Mods = [&](AMDGPU::OpName Name) {
2934 const MachineOperand *Op = TII.getNamedOperand(MI, Name);
2935 return Op ? static_cast<unsigned>(Op->getImm()) : 0u;
2936 };
2937 unsigned Src0Mods = Mods(AMDGPU::OpName::src0_modifiers);
2938 unsigned Src1Mods = Mods(AMDGPU::OpName::src1_modifiers);
2939 unsigned Src2Mods = Mods(AMDGPU::OpName::src2_modifiers);
2940
2941 if (CheckSwappedSrc)
2942 std::swap(Src0Mods, Src1Mods);
2943
2944 if (Opc == AMDGPU::V_PK_FMA_F32)
2945 return !((Src1Mods | Src2Mods) & SISrcMods::OP_SEL_0);
2946 return (Src0Mods & SISrcMods::OP_SEL_0) || !(Src1Mods & SISrcMods::OP_SEL_0);
2947}
2948
2949bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
2950 unsigned OpIdx1) const {
2951 const MCInstrDesc &InstDesc = MI.getDesc();
2952 const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
2953 const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];
2954
2955 unsigned Opc = MI.getOpcode();
2956 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2957 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
2958
2959 // Swapping src0 and src1 swaps their modifiers; refuse a swap that would
2960 // leave an invalid GFX950 packed FP32 op_sel.
2961 bool IsSrc01Swap = ((int)OpIdx0 == Src0Idx && (int)OpIdx1 == Src1Idx) ||
2962 ((int)OpIdx0 == Src1Idx && (int)OpIdx1 == Src0Idx);
2963 if (IsSrc01Swap && !isLegalPkF32OpSel(*this, MI, true))
2964 return false;
2965
2966 const MachineOperand &MO0 = MI.getOperand(OpIdx0);
2967 const MachineOperand &MO1 = MI.getOperand(OpIdx1);
2968
2969 // Swap doesn't breach constant bus or literal limits, but it may move a
2970 // constant out of src0. Allow that for immediates where the destination
2971 // operand can hold them, e.g. VOP3 sources on targets with VOP3 literal
2972 // support. Other non-register operands stay in src0.
2973 if (isVALU(MI, /*AllowLDSDMA=*/false)) {
2974 if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
2975 (!MO0.isImm() || !isImmOperandLegal(MI, OpIdx1, MO0)))
2976 return false;
2977 if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
2978 (!MO1.isImm() || !isImmOperandLegal(MI, OpIdx0, MO1)))
2979 return false;
2980 }
2981
2982 if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
2983 if (OpInfo1.RegClass == -1)
2984 return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
2985 return isLegalRegOperand(MI, OpIdx1, MO0) &&
2986 (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
2987 }
2988 if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
2989 if (OpInfo0.RegClass == -1)
2990 return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
2991 return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
2992 isLegalRegOperand(MI, OpIdx0, MO1);
2993 }
2994
2995 // No need to check 64-bit literals since swapping does not bring new
2996 // 64-bit literals into current instruction to fold to 32-bit
2997
2998 return isImmOperandLegal(MI, OpIdx1, MO0);
2999}
3000
3002 if (!isDPP(MI))
3003 return false;
3004 const MachineOperand *DppCtrl = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
3005 return !DppCtrl || DppCtrl->getImm() != AMDGPU::DPP::QUAD_PERM_ID;
3006}
3007
3009 unsigned Src0Idx,
3010 unsigned Src1Idx) const {
3011 assert(!NewMI && "this should never be used");
3012
3014 return nullptr;
3015
3016 unsigned Opc = MI.getOpcode();
3017 int CommutedOpcode = commuteOpcode(Opc);
3018 if (CommutedOpcode == -1)
3019 return nullptr;
3020
3021 if (Src0Idx > Src1Idx)
3022 std::swap(Src0Idx, Src1Idx);
3023
3024 assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
3025 static_cast<int>(Src0Idx) &&
3026 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
3027 static_cast<int>(Src1Idx) &&
3028 "inconsistency with findCommutedOpIndices");
3029
3030 if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
3031 return nullptr;
3032
3033 MachineInstr *CommutedMI = nullptr;
3034 MachineOperand &Src0 = MI.getOperand(Src0Idx);
3035 MachineOperand &Src1 = MI.getOperand(Src1Idx);
3036 if (Src0.isReg() && Src1.isReg()) {
3037 // Be sure to copy the source modifiers to the right place.
3038 CommutedMI =
3039 TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
3040 } else if (Src0.isReg() && !Src1.isReg()) {
3041 CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
3042 } else if (!Src0.isReg() && Src1.isReg()) {
3043 CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
3044 } else if (Src0.isImm() && Src1.isImm()) {
3045 CommutedMI = swapImmOperands(MI, Src0, Src1);
3046 } else {
3047 // FIXME: Found two non registers to commute. This does happen.
3048 return nullptr;
3049 }
3050
3051 if (CommutedMI) {
3052 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
3053 Src1, AMDGPU::OpName::src1_modifiers);
3054
3055 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
3056 AMDGPU::OpName::src1_sel);
3057
3058 CommutedMI->setDesc(get(CommutedOpcode));
3059 }
3060
3061 return CommutedMI;
3062}
3063
3064// This needs to be implemented because the source modifiers may be inserted
3065// between the true commutable operands, and the base
3066// TargetInstrInfo::commuteInstruction uses it.
3068 unsigned &SrcOpIdx0,
3069 unsigned &SrcOpIdx1) const {
3071 return false;
3072
3073 return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
3074}
3075
3077 unsigned &SrcOpIdx0,
3078 unsigned &SrcOpIdx1) const {
3079 if (!Desc.isCommutable())
3080 return false;
3081
3082 unsigned Opc = Desc.getOpcode();
3083 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
3084 if (Src0Idx == -1)
3085 return false;
3086
3087 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
3088 if (Src1Idx == -1)
3089 return false;
3090
3091 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3092}
3093
3095 int64_t BrOffset) const {
3096 // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
3097 // because its dest block is unanalyzable.
3098 assert(isSOPP(BranchOp) || isSOPK(BranchOp));
3099
3100 // Convert to dwords.
3101 BrOffset /= 4;
3102
3103 // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
3104 // from the next instruction.
3105 BrOffset -= 1;
3106
3107 return isIntN(ST.getCLOpts().s_branch_bits, BrOffset);
3108}
3109
3112 return MI.getOperand(0).getMBB();
3113}
3114
3116 for (const MachineInstr &MI : MBB->terminators()) {
3117 if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
3118 MI.getOpcode() == AMDGPU::SI_LOOP ||
3119 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3120 return true;
3121 }
3122 return false;
3123}
3124
3126 MachineBasicBlock &DestBB,
3127 MachineBasicBlock &RestoreBB,
3128 const DebugLoc &DL, int64_t BrOffset,
3129 RegScavenger *RS) const {
3130 assert(MBB.empty() &&
3131 "new block should be inserted for expanding unconditional branch");
3132 assert(MBB.pred_size() == 1);
3133 assert(RestoreBB.empty() &&
3134 "restore block should be inserted for restoring clobbered registers");
3135
3136 MachineFunction *MF = MBB.getParent();
3139 auto I = MBB.end();
3140 auto &MCCtx = MF->getContext();
3141
3142 if (ST.useAddPCI64Inst()) {
3143 MCSymbol *Offset =
3144 MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
3145 auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
3147 MCSymbol *PostAddPCLabel =
3148 MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
3149 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3150 auto *OffsetExpr = MCBinaryExpr::createSub(
3151 MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
3152 MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
3153 Offset->setVariableValue(OffsetExpr);
3154 return;
3155 }
3156
3157 assert(RS && "RegScavenger required for long branching");
3158
3159 // FIXME: Virtual register workaround for RegScavenger not working with empty
3160 // blocks.
3161 Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3162
3163 // Note: as this is used after hazard recognizer we need to apply some hazard
3164 // workarounds directly.
3165 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3166 ST.hasVALUReadSGPRHazard();
3167 auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
3168 if (FlushSGPRWrites)
3169 BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
3171 };
3172
3173 // We need to compute the offset relative to the instruction immediately after
3174 // s_getpc_b64. Insert pc arithmetic code before last terminator.
3175 MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
3176 ApplyHazardWorkarounds();
3177
3178 MCSymbol *PostGetPCLabel =
3179 MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
3180 GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);
3181
3182 MCSymbol *OffsetLo =
3183 MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
3184 MCSymbol *OffsetHi =
3185 MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
3186 BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
3187 .addReg(PCReg, RegState::Define, AMDGPU::sub0)
3188 .addReg(PCReg, {}, AMDGPU::sub0)
3189 .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
3190 BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
3191 .addReg(PCReg, RegState::Define, AMDGPU::sub1)
3192 .addReg(PCReg, {}, AMDGPU::sub1)
3193 .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
3194 ApplyHazardWorkarounds();
3195
3196 // Insert the indirect branch after the other terminator.
3197 BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
3198 .addReg(PCReg);
3199
3200 // If a spill is needed for the pc register pair, we need to insert a spill
3201 // restore block right before the destination block, and insert a short branch
3202 // into the old destination block's fallthrough predecessor.
3203 // e.g.:
3204 //
3205 // s_cbranch_scc0 skip_long_branch:
3206 //
3207 // long_branch_bb:
3208 // spill s[8:9]
3209 // s_getpc_b64 s[8:9]
3210 // s_add_u32 s8, s8, restore_bb
3211 // s_addc_u32 s9, s9, 0
3212 // s_setpc_b64 s[8:9]
3213 //
3214 // skip_long_branch:
3215 // foo;
3216 //
3217 // .....
3218 //
3219 // dest_bb_fallthrough_predecessor:
3220 // bar;
3221 // s_branch dest_bb
3222 //
3223 // restore_bb:
3224 // restore s[8:9]
3225 // fallthrough dest_bb
3226 ///
3227 // dest_bb:
3228 // buzz;
3229
3230 Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
3231 Register Scav;
3232
3233 // If we've previously reserved a register for long branches
3234 // avoid running the scavenger and just use those registers
3235 if (LongBranchReservedReg) {
3236 RS->enterBasicBlock(MBB);
3237 Scav = LongBranchReservedReg;
3238 } else {
3239 RS->enterBasicBlockEnd(MBB);
3240 Scav = RS->scavengeRegisterBackwards(
3241 AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
3242 /* RestoreAfter */ false, 0, /* AllowSpill */ false);
3243 }
3244 if (Scav) {
3245 RS->setRegUsed(Scav);
3246 MRI.replaceRegWith(PCReg, Scav);
3247 MRI.clearVirtRegs();
3248 } else {
3249 // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
3250 // SGPR spill.
3251 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
3252 const SIRegisterInfo *TRI = ST.getRegisterInfo();
3253 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3254 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3255 MRI.clearVirtRegs();
3256 }
3257
3258 MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
3259 // Now, the distance could be defined.
3261 MCSymbolRefExpr::create(DestLabel, MCCtx),
3262 MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
3263 // Add offset assignments.
3264 auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
3265 OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
3266 auto *ShAmt = MCConstantExpr::create(32, MCCtx);
3267 OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
3268}
3269
3270unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
3271 switch (Cond) {
3272 case SIInstrInfo::SCC_TRUE:
3273 return AMDGPU::S_CBRANCH_SCC1;
3274 case SIInstrInfo::SCC_FALSE:
3275 return AMDGPU::S_CBRANCH_SCC0;
3276 case SIInstrInfo::VCCNZ:
3277 return AMDGPU::S_CBRANCH_VCCNZ;
3278 case SIInstrInfo::VCCZ:
3279 return AMDGPU::S_CBRANCH_VCCZ;
3280 case SIInstrInfo::EXECNZ:
3281 return AMDGPU::S_CBRANCH_EXECNZ;
3282 case SIInstrInfo::EXECZ:
3283 return AMDGPU::S_CBRANCH_EXECZ;
3284 default:
3285 llvm_unreachable("invalid branch predicate");
3286 }
3287}
3288
3289SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
3290 switch (Opcode) {
3291 case AMDGPU::S_CBRANCH_SCC0:
3292 return SCC_FALSE;
3293 case AMDGPU::S_CBRANCH_SCC1:
3294 return SCC_TRUE;
3295 case AMDGPU::S_CBRANCH_VCCNZ:
3296 return VCCNZ;
3297 case AMDGPU::S_CBRANCH_VCCZ:
3298 return VCCZ;
3299 case AMDGPU::S_CBRANCH_EXECNZ:
3300 return EXECNZ;
3301 case AMDGPU::S_CBRANCH_EXECZ:
3302 return EXECZ;
3303 default:
3304 return INVALID_BR;
3305 }
3306}
3307
3311 MachineBasicBlock *&FBB,
3313 bool AllowModify) const {
3314 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3315 // Unconditional Branch
3316 TBB = I->getOperand(0).getMBB();
3317 return false;
3318 }
3319
3320 BranchPredicate Pred = getBranchPredicate(I->getOpcode());
3321 if (Pred == INVALID_BR)
3322 return true;
3323
3324 MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
3325 Cond.push_back(MachineOperand::CreateImm(Pred));
3326 Cond.push_back(I->getOperand(1)); // Save the branch register.
3327
3328 ++I;
3329
3330 if (I == MBB.end()) {
3331 // Conditional branch followed by fall-through.
3332 TBB = CondBB;
3333 return false;
3334 }
3335
3336 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3337 TBB = CondBB;
3338 FBB = I->getOperand(0).getMBB();
3339 return false;
3340 }
3341
3342 return true;
3343}
3344
3346 MachineBasicBlock *&FBB,
3348 bool AllowModify) const {
3349 MachineBasicBlock::iterator I = MBB.getFirstTerminator();
3350 auto E = MBB.end();
3351 if (I == E)
3352 return false;
3353
3354 // Skip over the instructions that are artificially terminators for special
3355 // exec management.
3356 while (I != E && !I->isBranch() && !I->isReturn()) {
3357 switch (I->getOpcode()) {
3358 case AMDGPU::S_MOV_B64_term:
3359 case AMDGPU::S_XOR_B64_term:
3360 case AMDGPU::S_OR_B64_term:
3361 case AMDGPU::S_ANDN2_B64_term:
3362 case AMDGPU::S_AND_B64_term:
3363 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3364 case AMDGPU::S_MOV_B32_term:
3365 case AMDGPU::S_XOR_B32_term:
3366 case AMDGPU::S_OR_B32_term:
3367 case AMDGPU::S_ANDN2_B32_term:
3368 case AMDGPU::S_AND_B32_term:
3369 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3370 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3371 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3372 break;
3373 case AMDGPU::SI_IF:
3374 case AMDGPU::SI_ELSE:
3375 case AMDGPU::SI_KILL_I1_TERMINATOR:
3376 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3377 // FIXME: It's messy that these need to be considered here at all.
3378 return true;
3379 default:
3380 llvm_unreachable("unexpected non-branch terminator inst");
3381 }
3382
3383 ++I;
3384 }
3385
3386 if (I == E)
3387 return false;
3388
3389 return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
3390}
3391
3393 int *BytesRemoved) const {
3394 unsigned Count = 0;
3395 unsigned RemovedSize = 0;
3396 for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
3397 // Skip over artificial terminators when removing instructions.
3398 if (MI.isBranch() || MI.isReturn()) {
3399 RemovedSize += getInstSizeInBytes(MI);
3400 MI.eraseFromParent();
3401 ++Count;
3402 }
3403 }
3404
3405 if (BytesRemoved)
3406 *BytesRemoved = RemovedSize;
3407
3408 return Count;
3409}
3410
3411// Copy the flags onto the implicit condition register operand.
3413 const MachineOperand &OrigCond) {
3414 CondReg.setIsUndef(OrigCond.isUndef());
3415 CondReg.setIsKill(OrigCond.isKill());
3416}
3417
3420 MachineBasicBlock *FBB,
3422 const DebugLoc &DL,
3423 int *BytesAdded) const {
3424 if (!FBB && Cond.empty()) {
3425 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3426 .addMBB(TBB);
3427 if (BytesAdded)
3428 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3429 return 1;
3430 }
3431
3432 assert(TBB && Cond[0].isImm());
3433
3434 unsigned Opcode
3435 = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));
3436
3437 if (!FBB) {
3438 MachineInstr *CondBr =
3439 BuildMI(&MBB, DL, get(Opcode))
3440 .addMBB(TBB);
3441
3442 // Copy the flags onto the implicit condition register operand.
3443 preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
3444 fixImplicitOperands(*CondBr);
3445
3446 if (BytesAdded)
3447 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3448 return 1;
3449 }
3450
3451 assert(TBB && FBB);
3452
3453 MachineInstr *CondBr =
3454 BuildMI(&MBB, DL, get(Opcode))
3455 .addMBB(TBB);
3456 fixImplicitOperands(*CondBr);
3457 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3458 .addMBB(FBB);
3459
3460 MachineOperand &CondReg = CondBr->getOperand(1);
3461 CondReg.setIsUndef(Cond[1].isUndef());
3462 CondReg.setIsKill(Cond[1].isKill());
3463
3464 if (BytesAdded)
3465 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3466
3467 return 2;
3468}
3469
3472 if (Cond.size() != 2) {
3473 return true;
3474 }
3475
3476 if (Cond[0].isImm()) {
3477 Cond[0].setImm(-Cond[0].getImm());
3478 return false;
3479 }
3480
3481 return true;
3482}
3483
3484namespace {
3485class AMDGPUPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
3486private:
3487 /// The compare instruction for loop control
3488 const MachineInstr *CmpInst = nullptr;
3489 /// The normalized condition used by createTripCountGreaterCondition()
3491
3492public:
3493 AMDGPUPipelinerLoopInfo(MachineInstr *CmpInst,
3495 : CmpInst(CmpInst), Cond(Cond.begin(), Cond.end()) {}
3496
3497 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
3498 return CmpInst && MI == CmpInst;
3499 }
3500
3501 std::optional<bool> createTripCountGreaterCondition(
3502 int TC, MachineBasicBlock &MBB,
3503 SmallVectorImpl<MachineOperand> &CondParam) override {
3504 CondParam = this->Cond;
3505 return {};
3506 }
3507
3508 void adjustTripCount(int TripCountAdjust) override {}
3509
3510 void setPreheader(MachineBasicBlock *NewPreheader) override {}
3511};
3512} // namespace
3513
3514std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3516 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
3518 // Unanalyzable terminator.
3519 if (analyzeBranch(*LoopBB, TBB, FBB, Cond, /*AllowModify=*/false))
3520 return nullptr;
3521
3522 // Infinite loops are not supported.
3523 if (TBB == LoopBB && FBB == LoopBB)
3524 return nullptr;
3525
3526 // Must be conditional branch.
3527 if (FBB == nullptr)
3528 return nullptr;
3529
3530 assert((TBB == LoopBB || FBB == LoopBB) &&
3531 "The Loop must be a single-basic-block loop");
3532
3533 // Divergent (VCC/EXEC) back-edge is not supported.
3534 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3535 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3536 return nullptr;
3537
3538 // Calls and inline assembly are not supported.
3539 for (const MachineInstr &MI : *LoopBB)
3540 if (MI.isCall() || MI.isInlineAsm())
3541 return nullptr;
3542
3543 // Normalization for createTripCountGreaterCondition(): make Cond mean
3544 // "exit the loop" so the expander emits correct prolog guard branches.
3545 if (TBB == LoopBB)
3547
3548 auto Instructions = make_range(
3550 LoopBB->rend());
3551 auto CmpI = llvm::find_if(Instructions, [&](const MachineInstr &MI) {
3552 return MI.modifiesRegister(Cond[1].getReg(), &RI);
3553 });
3554
3555 if (CmpI == Instructions.end() || CmpI->isPHI())
3556 return nullptr;
3557 MachineInstr *CmpInst = &*CmpI;
3558
3559 return std::make_unique<AMDGPUPipelinerLoopInfo>(CmpInst, Cond);
3560}
3561
3564 Register DstReg, Register TrueReg,
3565 Register FalseReg,
3566 SelectExpansion &Exp) const {
3567 switch (Cond[0].getImm()) {
3568 case VCCNZ:
3569 case VCCZ: {
3570 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3571 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3572 if (MRI.getRegClass(FalseReg) != RC)
3573 return false;
3574
3575 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3576 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts; // ???
3577
3578 // Limit to equal cost for branch vs. N v_cndmask_b32s.
3579 return RI.hasVGPRs(RC) && NumInsts <= 6;
3580 }
3581 case SCC_TRUE:
3582 case SCC_FALSE: {
3583 // FIXME: We could insert for VGPRs if we could replace the original compare
3584 // with a vector one.
3585 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3586 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3587 if (MRI.getRegClass(FalseReg) != RC)
3588 return false;
3589
3590 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3591
3592 // Multiples of 8 can do s_cselect_b64
3593 if (NumInsts % 2 == 0)
3594 NumInsts /= 2;
3595
3596 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts; // ???
3597 return RI.isSGPRClass(RC);
3598 }
3599 default:
3600 return false;
3601 }
3602}
3603
3607 Register TrueReg, Register FalseReg) const {
3608 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3609 if (Pred == VCCZ || Pred == SCC_FALSE) {
3610 Pred = static_cast<BranchPredicate>(-Pred);
3611 std::swap(TrueReg, FalseReg);
3612 }
3613
3614 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3615 const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
3616 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3617
3618 if (DstSize == 32) {
3620 if (Pred == SCC_TRUE) {
3621 Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
3622 .addReg(TrueReg)
3623 .addReg(FalseReg);
3624 } else {
3625 // Instruction's operands are backwards from what is expected.
3626 Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
3627 .addReg(FalseReg)
3628 .addReg(TrueReg);
3629 }
3630
3631 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3632 return;
3633 }
3634
3635 if (DstSize == 64 && Pred == SCC_TRUE) {
3637 BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
3638 .addReg(TrueReg)
3639 .addReg(FalseReg);
3640
3641 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3642 return;
3643 }
3644
3645 static const int16_t Sub0_15[] = {
3646 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3647 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3648 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3649 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3650 };
3651
3652 static const int16_t Sub0_15_64[] = {
3653 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3654 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3655 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3656 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3657 };
3658
3659 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3660 const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
3661 const int16_t *SubIndices = Sub0_15;
3662 int NElts = DstSize / 32;
3663
3664 // 64-bit select is only available for SALU.
3665 // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
3666 if (Pred == SCC_TRUE) {
3667 if (NElts % 2) {
3668 SelOp = AMDGPU::S_CSELECT_B32;
3669 EltRC = &AMDGPU::SGPR_32RegClass;
3670 } else {
3671 SelOp = AMDGPU::S_CSELECT_B64;
3672 EltRC = &AMDGPU::SGPR_64RegClass;
3673 SubIndices = Sub0_15_64;
3674 NElts /= 2;
3675 }
3676 }
3677
3679 MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);
3680
3681 I = MIB->getIterator();
3682
3684 for (int Idx = 0; Idx != NElts; ++Idx) {
3685 Register DstElt = MRI.createVirtualRegister(EltRC);
3686 Regs.push_back(DstElt);
3687
3688 unsigned SubIdx = SubIndices[Idx];
3689
3691 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3692 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3693 .addReg(FalseReg, {}, SubIdx)
3694 .addReg(TrueReg, {}, SubIdx);
3695 } else {
3696 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3697 .addReg(TrueReg, {}, SubIdx)
3698 .addReg(FalseReg, {}, SubIdx);
3699 }
3700
3701 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3703
3704 MIB.addReg(DstElt)
3705 .addImm(SubIdx);
3706 }
3707}
3708
3710
3711 if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
3712 return true;
3713
3714 switch (MI.getOpcode()) {
3715 case AMDGPU::S_ENDPGM:
3716 case AMDGPU::S_ENDPGM_SAVED:
3717 case AMDGPU::S_TRAP:
3718 case AMDGPU::S_GETREG_B32:
3719 case AMDGPU::S_SETREG_B32:
3720 case AMDGPU::S_SETREG_B32_mode:
3721 case AMDGPU::S_SETREG_IMM32_B32:
3722 case AMDGPU::S_SETREG_IMM32_B32_mode:
3723 case AMDGPU::S_SENDMSG:
3724 case AMDGPU::S_SENDMSGHALT:
3725 case AMDGPU::S_SENDMSG_RTN_B32:
3726 case AMDGPU::S_SENDMSG_RTN_B64:
3727 case AMDGPU::S_BARRIER_WAIT:
3728 case AMDGPU::S_BARRIER_SIGNAL_M0:
3729 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3730 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3731 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3732 return true;
3733 default:
3734 return false;
3735 }
3736}
3737
3739 switch (MI.getOpcode()) {
3740 case AMDGPU::V_MOV_B16_t16_e32:
3741 case AMDGPU::V_MOV_B16_t16_e64:
3742 case AMDGPU::V_MOV_B32_e32:
3743 case AMDGPU::V_MOV_B32_e64:
3744 case AMDGPU::V_MOV_B64_PSEUDO:
3745 case AMDGPU::V_MOV_B64_e32:
3746 case AMDGPU::V_MOV_B64_e64:
3747 case AMDGPU::S_MOV_B32:
3748 case AMDGPU::S_MOV_B64:
3749 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3750 case AMDGPU::COPY:
3751 case AMDGPU::WWM_COPY:
3752 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3753 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3754 case AMDGPU::V_ACCVGPR_MOV_B32:
3755 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3756 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3757 return true;
3758 default:
3759 return false;
3760 }
3761}
3762
3764 switch (MI.getOpcode()) {
3765 case AMDGPU::V_MOV_B16_t16_e32:
3766 case AMDGPU::V_MOV_B16_t16_e64:
3767 return 2;
3768 case AMDGPU::V_MOV_B32_e32:
3769 case AMDGPU::V_MOV_B32_e64:
3770 case AMDGPU::V_MOV_B64_PSEUDO:
3771 case AMDGPU::V_MOV_B64_e32:
3772 case AMDGPU::V_MOV_B64_e64:
3773 case AMDGPU::S_MOV_B32:
3774 case AMDGPU::S_MOV_B64:
3775 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3776 case AMDGPU::COPY:
3777 case AMDGPU::WWM_COPY:
3778 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3779 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3780 case AMDGPU::V_ACCVGPR_MOV_B32:
3781 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3782 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3783 return 1;
3784 default:
3785 llvm_unreachable("MI is not a foldable copy");
3786 }
3787}
3788
3789static constexpr AMDGPU::OpName ModifierOpNames[] = {
3790 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3791 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3792 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3793
3795 unsigned Opc = MI.getOpcode();
3796 for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
3797 int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
3798 if (Idx >= 0)
3799 MI.removeOperand(Idx);
3800 }
3801}
3802
3804 const MCInstrDesc &NewDesc) const {
3805 MI.setDesc(NewDesc);
3806
3807 // Remove any leftover implicit operands from mutating the instruction. e.g.
3808 // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
3809 // anymore.
3810 const MCInstrDesc &Desc = MI.getDesc();
3811 unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
3812 Desc.implicit_defs().size();
3813
3814 for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
3815 MI.removeOperand(I);
3816}
3817
3818std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
3819 unsigned SubRegIndex) {
3820 switch (SubRegIndex) {
3821 case AMDGPU::NoSubRegister:
3822 return Imm;
3823 case AMDGPU::sub0:
3824 return SignExtend64<32>(Imm);
3825 case AMDGPU::sub1:
3826 return SignExtend64<32>(Imm >> 32);
3827 case AMDGPU::lo16:
3828 return SignExtend64<16>(Imm);
3829 case AMDGPU::hi16:
3830 return SignExtend64<16>(Imm >> 16);
3831 case AMDGPU::sub1_lo16:
3832 return SignExtend64<16>(Imm >> 32);
3833 case AMDGPU::sub1_hi16:
3834 return SignExtend64<16>(Imm >> 48);
3835 default:
3836 return std::nullopt;
3837 }
3838
3839 llvm_unreachable("covered subregister switch");
3840}
3841
3842std::optional<unsigned>
3844 unsigned SubRegIndex) {
3845 if (SubRegIndex == AMDGPU::NoSubRegister)
3846 return TargetFlags;
3847
3848 unsigned LoReloc, HiReloc;
3849 switch (TargetFlags & MO_MASK) {
3850 case MO_REL32_LO:
3851 case MO_REL32_HI:
3852 case MO_REL64:
3853 LoReloc = MO_REL32_LO;
3854 HiReloc = MO_REL32_HI;
3855 break;
3856 case MO_GOTPCREL32_LO:
3857 case MO_GOTPCREL32_HI:
3858 LoReloc = MO_GOTPCREL32_LO;
3859 HiReloc = MO_GOTPCREL32_HI;
3860 break;
3861 case MO_ABS32_LO:
3862 case MO_ABS32_HI:
3863 case MO_ABS64:
3864 LoReloc = MO_ABS32_LO;
3865 HiReloc = MO_ABS32_HI;
3866 break;
3867 default:
3868 return std::nullopt;
3869 }
3870
3871 const unsigned BaseFlags = TargetFlags & ~MO_MASK;
3872 switch (SubRegIndex) {
3873 case AMDGPU::sub0:
3874 return BaseFlags | LoReloc;
3875 case AMDGPU::sub1:
3876 return BaseFlags | HiReloc;
3877 default:
3878 return std::nullopt;
3879 }
3880}
3881
3882static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
3883 switch (Opc) {
3884 case AMDGPU::V_MAC_F16_e32:
3885 case AMDGPU::V_MAC_F16_e64:
3886 case AMDGPU::V_MAD_F16_e64:
3887 return AMDGPU::V_MADAK_F16;
3888 case AMDGPU::V_MAC_F32_e32:
3889 case AMDGPU::V_MAC_F32_e64:
3890 case AMDGPU::V_MAD_F32_e64:
3891 return AMDGPU::V_MADAK_F32;
3892 case AMDGPU::V_FMAC_F32_e32:
3893 case AMDGPU::V_FMAC_F32_e64:
3894 case AMDGPU::V_FMA_F32_e64:
3895 return AMDGPU::V_FMAAK_F32;
3896 case AMDGPU::V_FMAC_F16_e32:
3897 case AMDGPU::V_FMAC_F16_e64:
3898 case AMDGPU::V_FMAC_F16_t16_e64:
3899 case AMDGPU::V_FMAC_F16_fake16_e64:
3900 case AMDGPU::V_FMAC_F16_t16_e32:
3901 case AMDGPU::V_FMAC_F16_fake16_e32:
3902 case AMDGPU::V_FMA_F16_e64:
3903 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3904 ? AMDGPU::V_FMAAK_F16_t16
3905 : AMDGPU::V_FMAAK_F16_fake16
3906 : AMDGPU::V_FMAAK_F16;
3907 case AMDGPU::V_FMAC_F64_e32:
3908 case AMDGPU::V_FMAC_F64_e64:
3909 case AMDGPU::V_FMA_F64_e64:
3910 return AMDGPU::V_FMAAK_F64;
3911 default:
3912 llvm_unreachable("invalid instruction");
3913 }
3914}
3915
3916static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
3917 switch (Opc) {
3918 case AMDGPU::V_MAC_F16_e32:
3919 case AMDGPU::V_MAC_F16_e64:
3920 case AMDGPU::V_MAD_F16_e64:
3921 return AMDGPU::V_MADMK_F16;
3922 case AMDGPU::V_MAC_F32_e32:
3923 case AMDGPU::V_MAC_F32_e64:
3924 case AMDGPU::V_MAD_F32_e64:
3925 return AMDGPU::V_MADMK_F32;
3926 case AMDGPU::V_FMAC_F32_e32:
3927 case AMDGPU::V_FMAC_F32_e64:
3928 case AMDGPU::V_FMA_F32_e64:
3929 return AMDGPU::V_FMAMK_F32;
3930 case AMDGPU::V_FMAC_F16_e32:
3931 case AMDGPU::V_FMAC_F16_e64:
3932 case AMDGPU::V_FMAC_F16_t16_e64:
3933 case AMDGPU::V_FMAC_F16_fake16_e64:
3934 case AMDGPU::V_FMAC_F16_t16_e32:
3935 case AMDGPU::V_FMAC_F16_fake16_e32:
3936 case AMDGPU::V_FMA_F16_e64:
3937 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3938 ? AMDGPU::V_FMAMK_F16_t16
3939 : AMDGPU::V_FMAMK_F16_fake16
3940 : AMDGPU::V_FMAMK_F16;
3941 case AMDGPU::V_FMAC_F64_e32:
3942 case AMDGPU::V_FMAC_F64_e64:
3943 case AMDGPU::V_FMA_F64_e64:
3944 return AMDGPU::V_FMAMK_F64;
3945 default:
3946 llvm_unreachable("invalid instruction");
3947 }
3948}
3949
3951 Register Reg, MachineRegisterInfo *MRI) const {
3952 int64_t Imm;
3953 if (!getConstValDefinedInReg(DefMI, Reg, Imm))
3954 return false;
3955
3956 const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);
3957
3958 assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");
3959
3960 unsigned Opc = UseMI.getOpcode();
3961 if (Opc == AMDGPU::COPY) {
3962 assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");
3963
3964 Register DstReg = UseMI.getOperand(0).getReg();
3965 Register UseSubReg = UseMI.getOperand(1).getSubReg();
3966
3967 const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);
3968
3969 if (HasMultipleUses) {
3970 // TODO: This should fold in more cases with multiple use, but we need to
3971 // more carefully consider what those uses are.
3972 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));
3973
3974 // Avoid breaking up a 64-bit inline immediate into a subregister extract.
3975 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3976 return false;
3977
3978 // Most of the time folding a 32-bit inline constant is free (though this
3979 // might not be true if we can't later fold it into a real user).
3980 //
3981 // FIXME: This isInlineConstant check is imprecise if
3982 // getConstValDefinedInReg handled the tricky non-mov cases.
3983 if (ImmDefSize == 32 &&
3985 return false;
3986 }
3987
3988 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3989 RI.getSubRegIdxSize(UseSubReg) == 16;
3990
3991 if (Is16Bit) {
3992 if (RI.hasVGPRs(DstRC))
3993 return false; // Do not clobber vgpr_hi16
3994
3995 if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
3996 return false;
3997 }
3998
3999 MachineFunction *MF = UseMI.getMF();
4000
4001 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
4002 MCRegister MovDstPhysReg =
4003 DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();
4004
4005 std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);
4006
4007 // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
4008 for (unsigned MovOp :
4009 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
4010 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
4011 const MCInstrDesc &MovDesc = get(MovOp);
4012
4013 const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
4014 if (Is16Bit) {
4015 // We just need to find a correctly sized register class, so the
4016 // subregister index compatibility doesn't matter since we're statically
4017 // extracting the immediate value.
4018 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
4019 if (!MovDstRC)
4020 continue;
4021
4022 if (MovDstPhysReg) {
4023 // FIXME: We probably should not do this. If there is a live value in
4024 // the high half of the register, it will be corrupted.
4025 MovDstPhysReg =
4026 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
4027 if (!MovDstPhysReg)
4028 continue;
4029 }
4030 }
4031
4032 // Result class isn't the right size, try the next instruction.
4033 if (MovDstPhysReg) {
4034 if (!MovDstRC->contains(MovDstPhysReg))
4035 return false;
4036 } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
4037 // TODO: This will be overly conservative in the case of 16-bit virtual
4038 // SGPRs. We could hack up the virtual register uses to use a compatible
4039 // 32-bit class.
4040 continue;
4041 }
4042
4043 const MCOperandInfo &OpInfo = MovDesc.operands()[1];
4044
4045 // Ensure the interpreted immediate value is a valid operand in the new
4046 // mov.
4047 //
4048 // FIXME: isImmOperandLegal should have form that doesn't require existing
4049 // MachineInstr or MachineOperand
4050 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4051 !isInlineConstant(*SubRegImm, OpInfo.OperandType))
4052 break;
4053
4054 NewOpc = MovOp;
4055 break;
4056 }
4057
4058 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4059 return false;
4060
4061 if (Is16Bit) {
4062 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4063 if (MovDstPhysReg)
4064 UseMI.getOperand(0).setReg(MovDstPhysReg);
4065 assert(UseMI.getOperand(1).getReg().isVirtual());
4066 }
4067
4068 const MCInstrDesc &NewMCID = get(NewOpc);
4069 UseMI.setDesc(NewMCID);
4070 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4071 UseMI.addImplicitDefUseOperands(*MF);
4072 return true;
4073 }
4074
4075 if (HasMultipleUses)
4076 return false;
4077
4078 if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
4079 Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4080 Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
4081 Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
4082 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4083 Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
4084 Opc == AMDGPU::V_FMAC_F64_e64) {
4085 // Don't fold if we are using source or output modifiers. The new VOP2
4086 // instructions don't have them.
4088 return false;
4089
4090 // If this is a free constant, there's no reason to do this.
4091 // TODO: We could fold this here instead of letting SIFoldOperands do it
4092 // later.
4093 int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4094
4095 // Any src operand can be used for the legality check.
4096 if (isInlineConstant(UseMI, Src0Idx, Imm))
4097 return false;
4098
4099 MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);
4100
4101 MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
4102 MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);
4103
4104 auto CopyRegOperandToNarrowerRC =
4105 [MRI, this](MachineInstr &MI, unsigned OpNo,
4106 const TargetRegisterClass *NewRC) -> void {
4107 if (!MI.getOperand(OpNo).isReg())
4108 return;
4109 Register Reg = MI.getOperand(OpNo).getReg();
4110 const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
4111 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4112 return;
4113 Register Tmp = MRI->createVirtualRegister(NewRC);
4114 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
4115 get(AMDGPU::COPY), Tmp)
4116 .addReg(Reg);
4117 MI.getOperand(OpNo).setReg(Tmp);
4118 };
4119
4120 // Multiplied part is the constant: Use v_madmk_{f16, f32}.
4121 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4122 (Src1->isReg() && Src1->getReg() == Reg)) {
4123 MachineOperand *RegSrc =
4124 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4125 if (!RegSrc->isReg())
4126 return false;
4127 if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
4128 ST.getConstantBusLimit(Opc) < 2)
4129 return false;
4130
4131 if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
4132 return false;
4133
4134 // If src2 is also a literal constant then we have to choose which one to
4135 // fold. In general it is better to choose madak so that the other literal
4136 // can be materialized in an sgpr instead of a vgpr:
4137 // s_mov_b32 s0, literal
4138 // v_madak_f32 v0, s0, v0, literal
4139 // Instead of:
4140 // v_mov_b32 v1, literal
4141 // v_madmk_f32 v0, v0, literal, v1
4142 MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
4143 if (Def && Def->isMoveImmediate() &&
4144 !isInlineConstant(Def->getOperand(1)))
4145 return false;
4146
4147 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4148 if (pseudoToMCOpcode(NewOpc) == -1)
4149 return false;
4150
4151 const std::optional<int64_t> SubRegImm = extractSubregFromImm(
4152 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4153
4154 // FIXME: This would be a lot easier if we could return a new instruction
4155 // instead of having to modify in place.
4156
4157 Register SrcReg = RegSrc->getReg();
4158 unsigned SrcSubReg = RegSrc->getSubReg();
4159 Src0->setReg(SrcReg);
4160 Src0->setSubReg(SrcSubReg);
4161 Src0->setIsKill(RegSrc->isKill());
4162
4163 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4164 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4165 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4166 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4167 UseMI.untieRegOperand(
4168 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4169
4170 Src1->ChangeToImmediate(*SubRegImm);
4171
4173 UseMI.setDesc(get(NewOpc));
4174
4175 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4176 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4177 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4178 Register Tmp = MRI->createVirtualRegister(NewRC);
4179 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4180 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4181 UseMI.getOperand(0).getReg())
4182 .addReg(Tmp);
4183 UseMI.getOperand(0).setReg(Tmp);
4184 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4185 CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
4186 }
4187
4188 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4189 if (DeleteDef)
4190 DefMI.eraseFromParent();
4191
4192 return true;
4193 }
4194
4195 // Added part is the constant: Use v_madak_{f16, f32}.
4196 if (Src2->isReg() && Src2->getReg() == Reg) {
4197 if (ST.getConstantBusLimit(Opc) < 2) {
4198 // Not allowed to use constant bus for another operand.
4199 // We can however allow an inline immediate as src0.
4200 bool Src0Inlined = false;
4201 if (Src0->isReg()) {
4202 // Try to inline constant if possible.
4203 // If the Def moves immediate and the use is single
4204 // We are saving VGPR here.
4205 MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
4206 if (Def && Def->isMoveImmediate() &&
4207 isInlineConstant(Def->getOperand(1)) &&
4208 MRI->hasOneNonDBGUse(Src0->getReg())) {
4209 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4210 Src0Inlined = true;
4211 } else if (ST.getConstantBusLimit(Opc) <= 1 &&
4212 RI.isSGPRReg(*MRI, Src0->getReg())) {
4213 return false;
4214 }
4215 // VGPR is okay as Src0 - fallthrough
4216 }
4217
4218 if (Src1->isReg() && !Src0Inlined) {
4219 // We have one slot for inlinable constant so far - try to fill it
4220 MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
4221 if (Def && Def->isMoveImmediate() &&
4222 isInlineConstant(Def->getOperand(1)) &&
4223 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
4224 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4225 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
4226 return false;
4227 // VGPR is okay as Src1 - fallthrough
4228 }
4229 }
4230
4231 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4232 if (pseudoToMCOpcode(NewOpc) == -1)
4233 return false;
4234
4235 // FIXME: This would be a lot easier if we could return a new instruction
4236 // instead of having to modify in place.
4237
4238 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
4239 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4240 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4241 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
4242 UseMI.untieRegOperand(
4243 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
4244
4245 const std::optional<int64_t> SubRegImm =
4246 extractSubregFromImm(Imm, Src2->getSubReg());
4247
4248 // ChangingToImmediate adds Src2 back to the instruction.
4249 Src2->ChangeToImmediate(*SubRegImm);
4250
4251 // These come before src2.
4253 UseMI.setDesc(get(NewOpc));
4254
4255 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4256 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4257 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
4258 Register Tmp = MRI->createVirtualRegister(NewRC);
4259 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
4260 UseMI.getDebugLoc(), get(AMDGPU::COPY),
4261 UseMI.getOperand(0).getReg())
4262 .addReg(Tmp);
4263 UseMI.getOperand(0).setReg(Tmp);
4264 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
4265 CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
4266 }
4267
4268 // It might happen that UseMI was commuted
4269 // and we now have SGPR as SRC1. If so 2 inlined
4270 // constant and SGPR are illegal.
4272
4273 int NewSrc0Idx =
4274 AMDGPU::getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
4275 if (!isOperandLegal(UseMI, NewSrc0Idx))
4276 legalizeOpWithMove(UseMI, NewSrc0Idx);
4277
4278 bool DeleteDef = MRI->use_nodbg_empty(Reg);
4279 if (DeleteDef)
4280 DefMI.eraseFromParent();
4281
4282 return true;
4283 }
4284 }
4285
4286 return false;
4287}
4288
4289static bool
4292 if (BaseOps1.size() != BaseOps2.size())
4293 return false;
4294 for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
4295 if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
4296 return false;
4297 }
4298 return true;
4299}
4300
4301static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
4302 LocationSize WidthB, int OffsetB) {
4303 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4304 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4305 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4306 return LowWidth.hasValue() &&
4307 LowOffset + (int)LowWidth.getValue() <= HighOffset;
4308}
4309
4310bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
4311 const MachineInstr &MIb) const {
4312 SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
4313 int64_t Offset0, Offset1;
4314 LocationSize Dummy0 = LocationSize::precise(0);
4315 LocationSize Dummy1 = LocationSize::precise(0);
4316 bool Offset0IsScalable, Offset1IsScalable;
4317 if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
4318 Dummy0) ||
4319 !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
4320 Dummy1))
4321 return false;
4322
4323 if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
4324 return false;
4325
4326 if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
4327 // FIXME: Handle ds_read2 / ds_write2.
4328 return false;
4329 }
4330 LocationSize Width0 = MIa.memoperands().front()->getSize();
4331 LocationSize Width1 = MIb.memoperands().front()->getSize();
4332 return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
4333}
4334
4336 const MachineInstr &MIb) const {
4337 assert(MIa.mayLoadOrStore() &&
4338 "MIa must load from or modify a memory location");
4339 assert(MIb.mayLoadOrStore() &&
4340 "MIb must load from or modify a memory location");
4341
4343 return false;
4344
4345 // XXX - Can we relax this between address spaces?
4346 if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
4347 return false;
4348
4349 if (isLDSDMA(MIa) || isLDSDMA(MIb))
4350 return false;
4351
4352 if (MIa.isBundle() || MIb.isBundle())
4353 return false;
4354
4355 // TODO: Should we check the address space from the MachineMemOperand? That
4356 // would allow us to distinguish objects we know don't alias based on the
4357 // underlying address space, even if it was lowered to a different one,
4358 // e.g. private accesses lowered to use MUBUF instructions on a scratch
4359 // buffer.
4360 if (isDS(MIa)) {
4361 if (isDS(MIb))
4362 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4363
4364 return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
4365 }
4366
4367 if (isMUBUF(MIa) || isMTBUF(MIa)) {
4368 if (isMUBUF(MIb) || isMTBUF(MIb))
4369 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4370
4371 if (isFLAT(MIb))
4372 return isFLATScratch(MIb);
4373
4374 return !isSMRD(MIb);
4375 }
4376
4377 if (isSMRD(MIa)) {
4378 if (isSMRD(MIb))
4379 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4380
4381 if (isFLAT(MIb))
4382 return isFLATScratch(MIb);
4383
4384 return !isMUBUF(MIb) && !isMTBUF(MIb);
4385 }
4386
4387 if (isFLAT(MIa)) {
4388 if (isFLAT(MIb)) {
4389 if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
4390 (isFLATGlobal(MIa) && isFLATScratch(MIb)))
4391 return true;
4392
4393 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4394 }
4395
4396 return false;
4397 }
4398
4399 return false;
4400}
4401
4402static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
4403 switch (Opc) {
4404 case AMDGPU::V_MAC_F16_e32:
4405 case AMDGPU::V_MAC_F16_e64:
4406 return AMDGPU::V_MAD_F16_e64;
4407 case AMDGPU::V_MAC_F32_e32:
4408 case AMDGPU::V_MAC_F32_e64:
4409 return AMDGPU::V_MAD_F32_e64;
4410 case AMDGPU::V_MAC_LEGACY_F32_e32:
4411 case AMDGPU::V_MAC_LEGACY_F32_e64:
4412 return AMDGPU::V_MAD_LEGACY_F32_e64;
4413 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4414 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4415 return AMDGPU::V_FMA_LEGACY_F32_e64;
4416 case AMDGPU::V_FMAC_F16_e32:
4417 case AMDGPU::V_FMAC_F16_e64:
4418 case AMDGPU::V_FMAC_F16_t16_e64:
4419 case AMDGPU::V_FMAC_F16_fake16_e64:
4420 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4421 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4422 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4423 : AMDGPU::V_FMA_F16_gfx9_e64;
4424 case AMDGPU::V_FMAC_F32_e32:
4425 case AMDGPU::V_FMAC_F32_e64:
4426 return AMDGPU::V_FMA_F32_e64;
4427 case AMDGPU::V_FMAC_F64_e32:
4428 case AMDGPU::V_FMAC_F64_e64:
4429 return AMDGPU::V_FMA_F64_e64;
4430 default:
4431 llvm_unreachable("invalid instruction");
4432 }
4433}
4434
4435/// Helper struct for the implementation of 3-address conversion to communicate
4436/// updates made to instruction operands.
4438 /// Other instruction whose def is no longer used by the converted
4439 /// instruction.
4441};
4442
4444 LiveIntervals *LIS) const {
4445 MachineBasicBlock &MBB = *MI.getParent();
4446 MachineInstr *CandidateMI = &MI;
4447
4448 if (MI.isBundle()) {
4449 // This is a temporary placeholder for bundle handling that enables us to
4450 // exercise the relevant code paths in the two-address instruction pass.
4451 if (MI.getBundleSize() != 1)
4452 return nullptr;
4453 CandidateMI = MI.getNextNode();
4454 }
4455
4457 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4458 if (!NewMI)
4459 return nullptr;
4460
4461 if (MI.isBundle()) {
4462 CandidateMI->eraseFromBundle();
4463
4464 for (MachineOperand &MO : MI.all_defs()) {
4465 if (MO.isTied())
4466 MI.untieRegOperand(MO.getOperandNo());
4467 }
4468 } else {
4469 if (LIS) {
4470 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
4471 // SlotIndex of defs needs to be updated when converting to early-clobber
4472 MachineOperand &Def = NewMI->getOperand(0);
4473 if (Def.isEarlyClobber() && Def.isReg() &&
4474 LIS->hasInterval(Def.getReg())) {
4475 SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
4476 SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
4477 auto &LI = LIS->getInterval(Def.getReg());
4478 auto UpdateDefIndex = [&](LiveRange &LR) {
4479 auto *S = LR.find(OldIndex);
4480 if (S != LR.end() && S->start == OldIndex) {
4481 assert(S->valno && S->valno->def == OldIndex);
4482 S->start = NewIndex;
4483 S->valno->def = NewIndex;
4484 }
4485 };
4486 UpdateDefIndex(LI);
4487 for (auto &SR : LI.subranges())
4488 UpdateDefIndex(SR);
4489 }
4490
4491 // A use tied to an early-clobber def is read at the early-clobber slot.
4492 // The three-address instruction has no tied operands, so the use is now
4493 // read at the register slot.
4494 const MachineOperand &OldDef = MI.getOperand(0);
4495 if (OldDef.isEarlyClobber()) {
4496 assert(OldDef.isTied() &&
4497 "expected a tied def in the two-address form");
4499 MI.getOperand(MI.findTiedOperandIdx(OldDef.getOperandNo()))
4500 .getReg();
4501 SlotIndex Idx = LIS->getInstructionIndex(*NewMI);
4502 SlotIndex OldEnd = Idx.getRegSlot(true);
4503 SlotIndex NewEnd = Idx.getRegSlot();
4504 auto UpdateUseIndex = [&](LiveRange &LR) {
4505 LiveRange::Segment *S = LR.getSegmentContaining(Idx);
4506 if (S && S->end == OldEnd)
4507 S->end = NewEnd;
4508 };
4509 LiveInterval &LI = LIS->getInterval(UseReg);
4510 UpdateUseIndex(LI);
4511 for (LiveInterval::SubRange &SR : LI.subranges())
4512 UpdateUseIndex(SR);
4513 }
4514 }
4515 }
4516
4517 if (U.RemoveMIUse) {
4518 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4519 // The only user is the instruction which will be killed.
4520 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4521
4522 if (MRI.hasOneNonDBGUse(DefReg)) {
4523 // We cannot just remove the DefMI here, calling pass will crash.
4524 U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
4525 U.RemoveMIUse->getOperand(0).setIsDead(true);
4526 for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
4527 U.RemoveMIUse->removeOperand(I);
4528 }
4529
4530 if (MI.isBundle()) {
4531 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4532 if (!VRI.Reads && !VRI.Writes) {
4533 for (MachineOperand &MO : MI.all_uses()) {
4534 if (MO.isReg() && MO.getReg() == DefReg) {
4535 assert(MO.getSubReg() == 0 &&
4536 "tied sub-registers in bundles currently not supported");
4537 MI.removeOperand(MO.getOperandNo());
4538 break;
4539 }
4540 }
4541
4542 if (LIS)
4543 LIS->shrinkToUses(&LIS->getInterval(DefReg));
4544 }
4545 } else if (LIS) {
4546 LiveInterval &DefLI = LIS->getInterval(DefReg);
4547
4548 // We cannot delete the original instruction here, so hack out the use
4549 // in the original instruction with a dummy register so we can use
4550 // shrinkToUses to deal with any multi-use edge cases. Other targets do
4551 // not have the complexity of deleting a use to consider here.
4552 Register DummyReg = MRI.cloneVirtualRegister(DefReg);
4553 for (MachineOperand &MIOp : MI.uses()) {
4554 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4555 MIOp.setIsUndef(true);
4556 MIOp.setReg(DummyReg);
4557 }
4558 }
4559
4560 if (MI.isBundle()) {
4561 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4562 if (!VRI.Reads && !VRI.Writes) {
4563 for (MachineOperand &MIOp : MI.uses()) {
4564 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4565 MIOp.setIsUndef(true);
4566 MIOp.setReg(DummyReg);
4567 }
4568 }
4569 }
4570
4571 MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
4572 false, /*isUndef=*/true));
4573 }
4574
4575 LIS->shrinkToUses(&DefLI);
4576 }
4577 }
4578
4579 return MI.isBundle() ? &MI : NewMI;
4580}
4581
4583SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
4584 ThreeAddressUpdates &U) const {
4585 MachineBasicBlock &MBB = *MI.getParent();
4586 unsigned Opc = MI.getOpcode();
4587
4588 // Handle MFMA.
4589 int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
4590 if (NewMFMAOpc != -1) {
4592 BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
4593 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4594 MIB.add(MI.getOperand(I));
4595 return MIB;
4596 }
4597
4598 if (SIInstrInfo::isWMMA(MI)) {
4599 unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
4600 MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4601 .setMIFlags(MI.getFlags());
4602 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4603 MIB->addOperand(MI.getOperand(I));
4604 return MIB;
4605 }
4606
4607 assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4608 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4609 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4610 "present pre-RA");
4611
4612 // Handle MAC/FMAC.
4613 bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
4614 bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4615 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4616 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4617 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4618 bool Src0Literal = false;
4619
4620 switch (Opc) {
4621 default:
4622 return nullptr;
4623 case AMDGPU::V_MAC_F16_e64:
4624 case AMDGPU::V_FMAC_F16_e64:
4625 case AMDGPU::V_FMAC_F16_t16_e64:
4626 case AMDGPU::V_FMAC_F16_fake16_e64:
4627 case AMDGPU::V_MAC_F32_e64:
4628 case AMDGPU::V_MAC_LEGACY_F32_e64:
4629 case AMDGPU::V_FMAC_F32_e64:
4630 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4631 case AMDGPU::V_FMAC_F64_e64:
4632 break;
4633 case AMDGPU::V_MAC_F16_e32:
4634 case AMDGPU::V_FMAC_F16_e32:
4635 case AMDGPU::V_MAC_F32_e32:
4636 case AMDGPU::V_MAC_LEGACY_F32_e32:
4637 case AMDGPU::V_FMAC_F32_e32:
4638 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4639 case AMDGPU::V_FMAC_F64_e32: {
4640 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
4641 AMDGPU::OpName::src0);
4642 const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
4643 if (!Src0->isReg() && !Src0->isImm())
4644 return nullptr;
4645
4646 if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
4647 Src0Literal = true;
4648
4649 break;
4650 }
4651 }
4652
4653 MachineInstrBuilder MIB;
4654 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
4655 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
4656 const MachineOperand *Src0Mods =
4657 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
4658 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4659 const MachineOperand *Src1Mods =
4660 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
4661 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4662 const MachineOperand *Src2Mods =
4663 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
4664 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
4665 const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
4666 const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);
4667
4668 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4669 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4670 // If we have an SGPR input, we will violate the constant bus restriction.
4671 (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
4672 !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
4673 MachineInstr *DefMI = nullptr;
4674 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4675 std::optional<int64_t> ImmOpt;
4676 int64_t Imm;
4677
4678 if (!Src0Literal &&
4679 (ImmOpt = getImmOrMaterializedImm(MRI, *Src2, &DefMI))) {
4680 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4681 if (pseudoToMCOpcode(NewOpc) != -1) {
4682 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4683 .add(*Dst)
4684 .add(*Src0)
4685 .add(*Src1)
4686 .addImm(*ImmOpt)
4687 .setMIFlags(MI.getFlags());
4688 U.RemoveMIUse = DefMI;
4689 return MIB;
4690 }
4691 }
4692 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4693 if (!Src0Literal &&
4694 (ImmOpt = getImmOrMaterializedImm(MRI, *Src1, &DefMI))) {
4695 if (pseudoToMCOpcode(NewOpc) != -1) {
4696 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4697 .add(*Dst)
4698 .add(*Src0)
4699 .addImm(*ImmOpt)
4700 .add(*Src2)
4701 .setMIFlags(MI.getFlags());
4702 U.RemoveMIUse = DefMI;
4703 return MIB;
4704 }
4705 }
4706 if ((ImmOpt = getImmOrMaterializedImm(MRI, *Src0, &DefMI))) {
4707 Imm = *ImmOpt;
4708 if (pseudoToMCOpcode(NewOpc) != -1 &&
4710 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4711 Src1)) {
4712 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4713 .add(*Dst)
4714 .add(*Src1)
4715 .addImm(Imm)
4716 .add(*Src2)
4717 .setMIFlags(MI.getFlags());
4718 U.RemoveMIUse = DefMI;
4719 return MIB;
4720 }
4721 }
4722 }
4723
4724 // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
4725 // if VOP3 does not allow a literal operand.
4726 if (Src0Literal && !ST.hasVOP3Literal())
4727 return nullptr;
4728
4729 unsigned NewOpc = getNewFMAInst(ST, Opc);
4730
4731 if (pseudoToMCOpcode(NewOpc) == -1)
4732 return nullptr;
4733
4734 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4735 .add(*Dst)
4736 .addImm(Src0Mods ? Src0Mods->getImm() : 0)
4737 .add(*Src0)
4738 .addImm(Src1Mods ? Src1Mods->getImm() : 0)
4739 .add(*Src1)
4740 .addImm(Src2Mods ? Src2Mods->getImm() : 0)
4741 .add(*Src2)
4742 .addImm(Clamp ? Clamp->getImm() : 0)
4743 .addImm(Omod ? Omod->getImm() : 0)
4744 .setMIFlags(MI.getFlags());
4745 if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
4746 MIB.addImm(OpSel ? OpSel->getImm() : 0);
4747 return MIB;
4748}
4749
4750// It's not generally safe to move VALU instructions across these since it will
4751// start using the register as a base index rather than directly.
4752// XXX - Why isn't hasSideEffects sufficient for these?
4754 switch (MI.getOpcode()) {
4755 case AMDGPU::S_SET_GPR_IDX_ON:
4756 case AMDGPU::S_SET_GPR_IDX_MODE:
4757 case AMDGPU::S_SET_GPR_IDX_OFF:
4758 return true;
4759 default:
4760 return false;
4761 }
4762}
4763
4765 const MachineBasicBlock *MBB,
4766 const MachineFunction &MF) const {
4767 // Skipping the check for SP writes in the base implementation. The reason it
4768 // was added was apparently due to compile time concerns.
4769 //
4770 // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
4771 // but is probably avoidable.
4772
4773 // Copied from base implementation.
4774 // Terminators and labels can't be scheduled around.
4775 if (MI.isTerminator() || MI.isPosition())
4776 return true;
4777
4778 // INLINEASM_BR can jump to another block
4779 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4780 return true;
4781
4782 if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
4783 return true;
4784
4785 // Target-independent instructions do not have an implicit-use of EXEC, even
4786 // when they operate on VGPRs. Treating EXEC modifications as scheduling
4787 // boundaries prevents incorrect movements of such instructions.
4788 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4789 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4790 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4791 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4792 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4794}
4795
4797 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4798 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4799 Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
4800}
4801
4803 // Instructions that access scratch use FLAT encoding or BUF encodings.
4804 if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
4805 return false;
4806
4807 // SCRATCH instructions always access scratch.
4808 if (isFLATScratch(MI))
4809 return true;
4810
4811 // If FLAT_SCRATCH registers are not initialized, we can never access scratch
4812 // via the aperture.
4813 if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
4814 return false;
4815
4816 // If there are no memory operands then conservatively assume the flat
4817 // operation may access scratch.
4818 if (MI.memoperands_empty())
4819 return true;
4820
4821 // See if any memory operand specifies an address space that involves scratch.
4822 return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
4823 unsigned AS = Memop->getAddrSpace();
4824 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4825 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4826 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4827 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4828 }
4829 return AS == AMDGPUAS::PRIVATE_ADDRESS;
4830 });
4831}
4832
4834 assert(isFLAT(MI));
4835
4836 // All flat instructions use the VMEM counter except prefetch.
4837 if (!usesVM_CNT(MI))
4838 return false;
4839
4840 // If there are no memory operands then conservatively assume the flat
4841 // operation may access VMEM.
4842 if (MI.memoperands_empty())
4843 return true;
4844
4845 // See if any memory operand specifies an address space that involves VMEM.
4846 // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
4847 // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
4848 // (GDS) address space is not supported by flat operations. Therefore, simply
4849 // return true unless only the LDS address space is found.
4850 for (const MachineMemOperand *Memop : MI.memoperands()) {
4851 unsigned AS = Memop->getAddrSpace();
4853 if (AS != AMDGPUAS::LOCAL_ADDRESS)
4854 return true;
4855 }
4856
4857 return false;
4858}
4859
4861 bool TgSplit) const {
4862 assert(isFLAT(MI));
4863
4864 // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
4865 if (!usesLGKM_CNT(MI))
4866 return false;
4867
4868 // If in tgsplit mode then there can be no use of LDS.
4869 if (TgSplit)
4870 return false;
4871
4872 // If there are no memory operands then conservatively assume the flat
4873 // operation may access LDS.
4874 if (MI.memoperands_empty())
4875 return true;
4876
4877 // See if any memory operand specifies an address space that involves LDS.
4878 for (const MachineMemOperand *Memop : MI.memoperands()) {
4879 unsigned AS = Memop->getAddrSpace();
4881 return true;
4882 }
4883
4884 return false;
4885}
4886
4888 if (!isAsync(MI))
4890 if (usesTENSOR_CNT(MI))
4892 if (!usesASYNC_CNT(MI))
4894
4895 // TODO: Declare the stage of each async instruction in TableGen alongside
4896 // its definition, instead of listing opcodes here.
4897 switch (MI.getOpcode()) {
4898 // Keep in sync with FLATInstructions.td.
4899 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B8:
4900 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B8_SADDR:
4901 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B32:
4902 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B32_SADDR:
4903 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B64:
4904 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B64_SADDR:
4905 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B128:
4906 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B128_SADDR:
4908 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B8:
4909 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B8_SADDR:
4910 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B32:
4911 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B32_SADDR:
4912 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B64:
4913 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B64_SADDR:
4914 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B128:
4915 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B128_SADDR:
4917 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B8:
4918 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B8_SADDR:
4919 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B32:
4920 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B32_SADDR:
4921 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B64:
4922 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B64_SADDR:
4923 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B128:
4924 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B128_SADDR:
4926 default:
4927 llvm_unreachable("Async opcode has no associated async stage");
4928 }
4929}
4930
4932 // Skip the full operand and register alias search modifiesRegister
4933 // does. There's only a handful of instructions that touch this, it's only an
4934 // implicit def, and doesn't alias any other registers.
4935 return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
4936}
4937
4939 unsigned Opcode = MI.getOpcode();
4940
4941 if (MI.mayStore() && isSMRD(MI))
4942 return true; // scalar store or atomic
4943
4944 // This will terminate the function when other lanes may need to continue.
4945 if (MI.isReturn())
4946 return true;
4947
4948 // These instructions cause shader I/O that may cause hardware lockups
4949 // when executed with an empty EXEC mask.
4950 //
4951 // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
4952 // EXEC = 0, but checking for that case here seems not worth it
4953 // given the typical code patterns.
4954 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4955 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4956 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4957 Opcode == AMDGPU::S_SETHALT)
4958 return true;
4959
4960 if (MI.isCall() || MI.isInlineAsm())
4961 return true; // conservative assumption
4962
4963 // V_PERM_PK16 must issue with EXEC != 0 so its follower (or an inserted
4964 // V_NOP) actually runs on the VALU pipe. Returning true here keeps the
4965 // s_cbranch_execz that skips this region when EXEC is empty.
4966 if (ST.hasVPermPk16Hazard() && isVPermPk16(Opcode))
4967 return true;
4968
4969 // Assume that barrier interactions are only intended with active lanes.
4970 if (isBarrier(Opcode))
4971 return true;
4972
4973 // A mode change is a scalar operation that influences vector instructions.
4975 return true;
4976
4977 // These are like SALU instructions in terms of effects, so it's questionable
4978 // whether we should return true for those.
4979 //
4980 // However, executing them with EXEC = 0 causes them to operate on undefined
4981 // data, which we avoid by returning true here.
4982 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4983 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4984 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4985 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4986 return true;
4987
4988 return false;
4989}
4990
4992 const MachineInstr &MI) const {
4993 if (MI.isMetaInstruction())
4994 return false;
4995
4996 // This won't read exec if this is an SGPR->SGPR copy.
4997 if (MI.isCopyLike()) {
4998 if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
4999 return true;
5000
5001 // Make sure this isn't copying exec as a normal operand
5002 return MI.readsRegister(AMDGPU::EXEC, &RI);
5003 }
5004
5005 // Make a conservative assumption about the callee.
5006 if (MI.isCall())
5007 return true;
5008
5009 // Be conservative with any unhandled generic opcodes.
5010 if (!isTargetSpecificOpcode(MI.getOpcode()))
5011 return true;
5012
5013 return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
5014}
5015
5017 switch (Imm.getBitWidth()) {
5018 case 1: // This likely will be a condition code mask.
5019 return true;
5020
5021 case 32:
5022 return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
5023 ST.hasInv2PiInlineImm());
5024 case 64:
5025 return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
5026 ST.hasInv2PiInlineImm());
5027 case 16:
5028 return ST.has16BitInsts() &&
5029 AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
5030 ST.hasInv2PiInlineImm());
5031 default:
5032 llvm_unreachable("invalid bitwidth");
5033 }
5034}
5035
5037 APInt IntImm = Imm.bitcastToAPInt();
5038 int64_t IntImmVal = IntImm.getSExtValue();
5039 bool HasInv2Pi = ST.hasInv2PiInlineImm();
5040 switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
5041 default:
5042 llvm_unreachable("invalid fltSemantics");
5045 return isInlineConstant(IntImm);
5047 return ST.has16BitInsts() &&
5048 AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
5050 return ST.has16BitInsts() &&
5051 AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
5052 }
5053}
5054
5055bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
5056 // MachineOperand provides no way to tell the true operand size, since it only
5057 // records a 64-bit value. We need to know the size to determine if a 32-bit
5058 // floating point immediate bit pattern is legal for an integer immediate. It
5059 // would be for any 32-bit integer operand, but would not be for a 64-bit one.
5060 switch (OperandType) {
5070 int32_t Trunc = static_cast<int32_t>(Imm);
5071 return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
5072 }
5080 return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
5083 // We would expect inline immediates to not be concerned with an integer/fp
5084 // distinction. However, in the case of 16-bit integer operations, the
5085 // "floating point" values appear to not work. It seems read the low 16-bits
5086 // of 32-bit immediates, which happens to always work for the integer
5087 // values.
5088 //
5089 // See llvm bugzilla 46302.
5090 //
5091 // TODO: Theoretically we could use op-sel to use the high bits of the
5092 // 32-bit FP values.
5101 return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
5106 return false;
5109 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
5110 // A few special case instructions have 16-bit operands on subtargets
5111 // where 16-bit instructions are not legal.
5112 // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
5113 // constants in these cases
5114 int16_t Trunc = static_cast<int16_t>(Imm);
5115 return ST.has16BitInsts() &&
5116 AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
5117 }
5118
5119 return false;
5120 }
5123 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
5124 int16_t Trunc = static_cast<int16_t>(Imm);
5125 return ST.has16BitInsts() &&
5126 AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
5127 }
5128 return false;
5129 }
5134 return false;
5136 return isLegalAV64PseudoImm(Imm);
5139 // Always embedded in the instruction for free.
5140 return true;
5150 // Just ignore anything else.
5151 return false;
5152 default:
5153 llvm_unreachable("invalid operand type");
5154 }
5155}
5156
5157static bool compareMachineOp(const MachineOperand &Op0,
5158 const MachineOperand &Op1) {
5159 if (Op0.getType() != Op1.getType())
5160 return false;
5161
5162 switch (Op0.getType()) {
5164 return Op0.getReg() == Op1.getReg();
5166 return Op0.getImm() == Op1.getImm();
5167 default:
5168 llvm_unreachable("Didn't expect to be comparing these operand types");
5169 }
5170}
5171
5173 const MCOperandInfo &OpInfo) const {
5174 if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
5175 return true;
5176
5177 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5178 return false;
5179
5180 if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
5181 return true;
5182
5183 return ST.hasVOP3Literal();
5184}
5185
5186bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5187 int64_t ImmVal) const {
5188 const unsigned Opc = InstDesc.getOpcode();
5189 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
5190 if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
5191 OpNo == static_cast<unsigned>(Src1Idx))
5192 return false;
5193
5194 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5195 if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
5196 if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5197 OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
5198 AMDGPU::OpName::src2))
5199 return false;
5200
5201 if (ST.hasBF16InlineConstFromUpperFP32() && isVOP1(Opc)) {
5202 if ((OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_BF16 ||
5203 OpInfo.OperandType == AMDGPU::OPERAND_REG_INLINE_C_BF16) &&
5204 isInlineConstant(ImmVal, OpInfo.OperandType))
5205 return false;
5206 }
5207
5208 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5209 }
5210
5211 return isLiteralOperandLegal(InstDesc, OpInfo);
5212}
5213
5214bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
5215 const MachineOperand &MO) const {
5216 if (MO.isImm())
5217 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
5218
5219 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
5220 "unexpected imm-like operand kind");
5221 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
5222 return isLiteralOperandLegal(InstDesc, OpInfo);
5223}
5224
5226 // 2 32-bit inline constants packed into one.
5227 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
5228 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
5229}
5230
5231bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
5232 // GFX90A does not have V_MUL_LEGACY_F32_e32.
5233 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5234 return false;
5235
5236 int Op32 = AMDGPU::getVOPe32(Opcode);
5237 if (Op32 == -1)
5238 return false;
5239
5240 return pseudoToMCOpcode(Op32) != -1;
5241}
5242
5243/// Return true if \p MI is a VALU comparison, i.e. an instruction that writes
5244/// a lane mask with one bit per lane, and zeroes the bits of lanes that were
5245/// inactive when it executed.
5246///
5247/// TODO: Also handle the sdst result of V_ADD_CO_U32 and V_SUB_CO_U32 and
5248/// V_DIV_SCALE_F32.
5249static bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI) {
5250 if (TII.isVOPC(MI))
5251 return true;
5252 int Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5253 return Op32 != -1 && TII.isVOPC(Op32);
5254}
5255
5257 const MachineRegisterInfo &MRI,
5258 unsigned Depth) const {
5259 assert(MRI.isSSA() && "isMaskedByExec requires SSA form");
5261 const MachineBasicBlock *MBB = Use.getParent();
5262
5263 // EXEC itself is trivially masked by EXEC.
5264 if (Reg == LMC.ExecReg)
5265 return true;
5266
5267 // Maximum depth of the def-use walk.
5268 constexpr unsigned MaxDepth = 6;
5269 if (Depth >= MaxDepth || !Reg.isVirtual())
5270 return false;
5271
5272 // Only look at definitions that can execute under the same EXEC mask as the
5273 // use.
5274 const MachineInstr *Def = MRI.getVRegDef(Reg);
5275 if (!Def || Def->getParent() != MBB)
5276 return false;
5277
5278 if (isVCmp(*this, *Def))
5279 return true;
5280
5281 // Recurse into an operand, which must be a whole register to say anything
5282 // about the whole lane mask.
5283 auto Recurse = [&](unsigned OpIdx) {
5284 const MachineOperand &MO = Def->getOperand(OpIdx);
5285 return MO.isReg() && !MO.getSubReg() &&
5286 isMaskedByExec(MO.getReg(), Use, MRI, Depth + 1);
5287 };
5288
5289 unsigned Opc = Def->getOpcode();
5290 if (Opc == AMDGPU::COPY && Recurse(1))
5291 return true;
5292 if (Opc == LMC.AndOpc && (Recurse(1) || Recurse(2)))
5293 return true;
5294 if (Opc == LMC.AndN2Opc && Recurse(1))
5295 return true;
5296 if ((Opc == LMC.OrOpc || Opc == LMC.XorOpc) && Recurse(1) && Recurse(2))
5297 return true;
5298 // TODO: Sometimes we encounter "reg = S_CSELECT -1, 0". If Reg has no other
5299 // uses this could be optimized to "reg = S_CSELECT $exec, 0".
5300
5301 return false;
5302}
5303
5304bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
5305 // The src0_modifier operand is present on all instructions
5306 // that have modifiers.
5307
5308 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
5309}
5310
5312 AMDGPU::OpName OpName) const {
5313 const MachineOperand *Mods = getNamedOperand(MI, OpName);
5314 return Mods && Mods->getImm();
5315}
5316
5318 return any_of(ModifierOpNames,
5319 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
5320}
5321
5323 const MachineRegisterInfo &MRI) const {
5324 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5325 // Can't shrink instruction with three operands.
5326 if (Src2) {
5327 switch (MI.getOpcode()) {
5328 default: return false;
5329
5330 case AMDGPU::V_ADDC_U32_e64:
5331 case AMDGPU::V_SUBB_U32_e64:
5332 case AMDGPU::V_SUBBREV_U32_e64: {
5333 const MachineOperand *Src1
5334 = getNamedOperand(MI, AMDGPU::OpName::src1);
5335 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
5336 return false;
5337 // Additional verification is needed for sdst/src2.
5338 return true;
5339 }
5340 case AMDGPU::V_MAC_F16_e64:
5341 case AMDGPU::V_MAC_F32_e64:
5342 case AMDGPU::V_MAC_LEGACY_F32_e64:
5343 case AMDGPU::V_FMAC_F16_e64:
5344 case AMDGPU::V_FMAC_F16_t16_e64:
5345 case AMDGPU::V_FMAC_F16_fake16_e64:
5346 case AMDGPU::V_FMAC_F32_e64:
5347 case AMDGPU::V_FMAC_F64_e64:
5348 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5349 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
5350 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
5351 return false;
5352 break;
5353
5354 case AMDGPU::V_CNDMASK_B32_e64:
5355 break;
5356 }
5357 }
5358
5359 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
5360 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
5361 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
5362 return false;
5363
5364 // Make sure src0 isn't using any modifiers.
5365 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
5366 return false;
5367
5368 // Can it be shrunk to a valid 32 bit opcode?
5369 if (!hasVALU32BitEncoding(MI.getOpcode()))
5370 return false;
5371
5372 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
5373 if (Src0 && Src0->isImm()) {
5374 unsigned Op32 = AMDGPU::getVOPe32(MI.getOpcode());
5375 if (!isImmOperandLegal(
5376 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5377 *Src0))
5378 return false;
5379 }
5380
5381 // Check output modifiers
5382 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
5383 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
5384 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
5385 // TODO: Can we avoid checking bound_ctrl/fi here?
5386 // They are only used by permlane*_swap special case.
5387 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
5388 !hasModifiersSet(MI, AMDGPU::OpName::fi);
5389}
5390
5391// Set VCC operand with all flags from \p Orig, except for setting it as
5392// implicit.
5394 const MachineOperand &Orig) {
5395
5396 for (MachineOperand &Use : MI.implicit_operands()) {
5397 if (Use.isUse() &&
5398 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
5399 Use.setIsUndef(Orig.isUndef());
5400 Use.setIsKill(Orig.isKill());
5401 return;
5402 }
5403 }
5404}
5405
5407 unsigned Op32) const {
5408 MachineBasicBlock *MBB = MI.getParent();
5409
5410 const MCInstrDesc &Op32Desc = get(Op32);
5411 MachineInstrBuilder Inst32 =
5412 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
5413 .setMIFlags(MI.getFlags());
5414
5415 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
5416 // For VOPC instructions, this is replaced by an implicit def of vcc.
5417
5418 // We assume the defs of the shrunk opcode are in the same order, and the
5419 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
5420 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
5421 Inst32.add(MI.getOperand(I));
5422
5423 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
5424
5425 int Idx = MI.getNumExplicitDefs();
5426 for (const MachineOperand &Use : MI.explicit_uses()) {
5427 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
5429 continue;
5430
5431 if (&Use == Src2) {
5432 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5433 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
5434 // replaced with an implicit read of vcc or vcc_lo. The implicit read
5435 // of vcc was already added during the initial BuildMI, but we
5436 // 1) may need to change vcc to vcc_lo to preserve the original register
5437 // 2) have to preserve the original flags.
5438 copyFlagsToImplicitVCC(*Inst32, *Src2);
5439 continue;
5440 }
5441 }
5442
5443 Inst32.add(Use);
5444 }
5445
5446 // FIXME: Losing implicit operands
5447 fixImplicitOperands(*Inst32);
5448
5449 // The explicit carry/result def is dropped in favor of an implicit VCC def;
5450 // preserve the dead flag.
5451 const MachineOperand *OldSDst = getNamedOperand(MI, AMDGPU::OpName::sdst);
5452 if (OldSDst && OldSDst->isDead()) {
5453 if (MachineOperand *NewVCC =
5454 Inst32->findRegisterDefOperand(RI.getVCC(), &RI))
5455 NewVCC->setIsDead();
5456 }
5457
5458 return Inst32;
5459}
5460
5462 // Null is free
5463 Register Reg = RegOp.getReg();
5464 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5465 return false;
5466
5467 // SGPRs use the constant bus
5468
5469 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
5470 // physical register operands should also count, except for exec.
5471 if (RegOp.isImplicit())
5472 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5473
5474 // SGPRs use the constant bus
5475 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5476 AMDGPU::SReg_64RegClass.contains(Reg);
5477}
5478
5480 const MachineRegisterInfo &MRI) const {
5481 Register Reg = RegOp.getReg();
5482 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5483 : physRegUsesConstantBus(RegOp);
5484}
5485
5487 const MachineOperand &MO,
5488 const MCOperandInfo &OpInfo) const {
5489 // Literal constants use the constant bus.
5490 if (!MO.isReg())
5491 return !isInlineConstant(MO, OpInfo);
5492
5493 Register Reg = MO.getReg();
5494 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5496}
5497
5499 for (const MachineOperand &MO : MI.implicit_operands()) {
5500 // We only care about reads.
5501 if (MO.isDef())
5502 continue;
5503
5504 switch (MO.getReg()) {
5505 case AMDGPU::VCC:
5506 case AMDGPU::VCC_LO:
5507 case AMDGPU::VCC_HI:
5508 case AMDGPU::M0:
5509 case AMDGPU::FLAT_SCR:
5510 return MO.getReg();
5511
5512 default:
5513 break;
5514 }
5515 }
5516
5517 return Register();
5518}
5519
5520static bool shouldReadExec(const MachineInstr &MI) {
5521 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5522 switch (MI.getOpcode()) {
5523 case AMDGPU::V_READLANE_B32:
5524 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5525 case AMDGPU::V_WRITELANE_B32:
5526 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5527 return false;
5528 }
5529
5530 return true;
5531 }
5532
5533 if (MI.isPreISelOpcode() ||
5534 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5537 return false;
5538
5539 return true;
5540}
5541
5542static bool isRegOrFI(const MachineOperand &MO) {
5543 return MO.isReg() || MO.isFI();
5544}
5545
5546static bool isSubRegOf(const SIRegisterInfo &TRI,
5547 const MachineOperand &SuperVec,
5548 const MachineOperand &SubReg) {
5549 if (SubReg.getReg().isPhysical())
5550 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5551
5552 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5553 SubReg.getReg() == SuperVec.getReg();
5554}
5555
5556// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5557bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5558 const MachineRegisterInfo &MRI,
5559 StringRef &ErrInfo) const {
5560 Register DstReg = MI.getOperand(0).getReg();
5561 Register SrcReg = MI.getOperand(1).getReg();
5562 // This is a check for copy from vector register to SGPR
5563 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5564 ErrInfo = "illegal copy from vector register to SGPR";
5565 return false;
5566 }
5567 return true;
5568}
5569
5571 StringRef &ErrInfo) const {
5572 uint32_t Opcode = MI.getOpcode();
5573 const MachineFunction *MF = MI.getMF();
5574 const MachineRegisterInfo &MRI = MF->getRegInfo();
5575
5576 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5577 // Find a better property to recognize the point where instruction selection
5578 // is just done.
5579 // We can only enforce this check after SIFixSGPRCopies pass so that the
5580 // illegal copies are legalized and thereafter we don't expect a pass
5581 // inserting similar copies.
5582 if (!MRI.isSSA() && MI.isCopy())
5583 return verifyCopy(MI, MRI, ErrInfo);
5584
5585 if (SIInstrInfo::isGenericOpcode(Opcode))
5586 return true;
5587
5588 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5589 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5590 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5591 int Src3Idx = -1;
5592 if (Src0Idx == -1) {
5593 // VOPD V_DUAL_* instructions use different operand names.
5594 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5595 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5596 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5597 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5598 }
5599
5600 // Make sure the number of operands is correct.
5601 const MCInstrDesc &Desc = get(Opcode);
5602 if (!Desc.isVariadic() &&
5603 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5604 ErrInfo = "Instruction has wrong number of operands.";
5605 return false;
5606 }
5607
5608 if (MI.isInlineAsm()) {
5609 // Verify register classes for inlineasm constraints.
5610 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5611 I != E; ++I) {
5612 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5613 if (!RC)
5614 continue;
5615
5616 const MachineOperand &Op = MI.getOperand(I);
5617 if (!Op.isReg())
5618 continue;
5619
5620 Register Reg = Op.getReg();
5621 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5622 ErrInfo = "inlineasm operand has incorrect register class.";
5623 return false;
5624 }
5625 }
5626
5627 return true;
5628 }
5629
5630 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5631 ErrInfo = "missing memory operand from image instruction.";
5632 return false;
5633 }
5634
5635 // Make sure the register classes are correct.
5636 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5637 const MachineOperand &MO = MI.getOperand(i);
5638 if (MO.isFPImm()) {
5639 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5640 "all fp values to integers.";
5641 return false;
5642 }
5643
5644 const MCOperandInfo &OpInfo = Desc.operands()[i];
5645
5646 switch (OpInfo.OperandType) {
5648 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5649 ErrInfo = "Illegal immediate value for operand.";
5650 return false;
5651 }
5652 break;
5666 break;
5680 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5681 ErrInfo = "Illegal immediate value for operand.";
5682 return false;
5683 }
5684 break;
5685 }
5690 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5691 !isInlineConstant(MI, i) &&
5693 OpInfo.OperandType ==
5695 ErrInfo = "illegal 64-bit immediate value for operand.";
5696 return false;
5697 }
5698 break;
5701 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5702 ErrInfo = "Expected inline constant for operand.";
5703 return false;
5704 }
5705 break;
5708 break;
5713 // Check if this operand is an immediate.
5714 // FrameIndex operands will be replaced by immediates, so they are
5715 // allowed.
5716 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5717 ErrInfo = "Expected immediate, but got non-immediate";
5718 return false;
5719 }
5720 break;
5724 break;
5725 default:
5726 if (OpInfo.isGenericType())
5727 continue;
5728 break;
5729 }
5730 }
5731
5732 // Verify SDWA
5733 if (isSDWA(MI)) {
5734 if (!ST.hasSDWA()) {
5735 ErrInfo = "SDWA is not supported on this target";
5736 return false;
5737 }
5738
5739 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5740 AMDGPU::OpName::dst_sel}) {
5741 const MachineOperand *MO = getNamedOperand(MI, Op);
5742 if (!MO)
5743 continue;
5744 int64_t Imm = MO->getImm();
5746 ErrInfo = "Invalid SDWA selection";
5747 return false;
5748 }
5749 }
5750
5751 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5752
5753 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5754 if (OpIdx == -1)
5755 continue;
5756 const MachineOperand &MO = MI.getOperand(OpIdx);
5757
5758 if (!ST.hasSDWAScalar()) {
5759 // Only VGPRS on VI
5760 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5761 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5762 return false;
5763 }
5764 } else {
5765 // No immediates on GFX9
5766 if (!MO.isReg()) {
5767 ErrInfo =
5768 "Only reg allowed as operands in SDWA instructions on GFX9+";
5769 return false;
5770 }
5771 }
5772 }
5773
5774 if (!ST.hasSDWAOmod()) {
5775 // No omod allowed on VI
5776 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5777 if (OMod != nullptr &&
5778 (!OMod->isImm() || OMod->getImm() != 0)) {
5779 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5780 return false;
5781 }
5782 }
5783
5784 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5785 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5786 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5787 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5788 const MachineOperand *Src0ModsMO =
5789 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5790 unsigned Mods = Src0ModsMO->getImm();
5791 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5792 Mods & SISrcMods::SEXT) {
5793 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5794 return false;
5795 }
5796 }
5797
5798 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5799 if (isVOPC(BasicOpcode)) {
5800 if (!ST.hasSDWASdst() && DstIdx != -1) {
5801 // Only vcc allowed as dst on VI for VOPC
5802 const MachineOperand &Dst = MI.getOperand(DstIdx);
5803 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5804 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5805 return false;
5806 }
5807 } else if (!ST.hasSDWAOutModsVOPC()) {
5808 // No clamp allowed on GFX9 for VOPC
5809 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5810 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5811 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5812 return false;
5813 }
5814
5815 // No omod allowed on GFX9 for VOPC
5816 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5817 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5818 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5819 return false;
5820 }
5821 }
5822 }
5823
5824 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5825 if (DstUnused && DstUnused->isImm() &&
5826 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5827 const MachineOperand &Dst = MI.getOperand(DstIdx);
5828 if (!Dst.isReg() || !Dst.isTied()) {
5829 ErrInfo = "Dst register should have tied register";
5830 return false;
5831 }
5832
5833 const MachineOperand &TiedMO =
5834 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5835 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5836 ErrInfo =
5837 "Dst register should be tied to implicit use of preserved register";
5838 return false;
5839 }
5840 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5841 ErrInfo = "Dst register should use same physical register as preserved";
5842 return false;
5843 }
5844 }
5845 }
5846
5847 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5848 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5849 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5850 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5851 return false;
5852 }
5853 if (Src1MO.isImm()) {
5854 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5855 return false;
5856 }
5857 }
5858
5859 // Verify MIMG / VIMAGE / VSAMPLE
5860 if (isImage(Opcode) && !MI.mayStore()) {
5861 // Ensure that the return type used is large enough for all the options
5862 // being used TFE/LWE require an extra result register.
5863 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5864 if (DMask) {
5865 uint64_t DMaskImm = DMask->getImm();
5866 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5867 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5868 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5869 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5870
5871 // Adjust for packed 16 bit values
5872 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5873 RegCount = divideCeil(RegCount, 2);
5874
5875 // Adjust if using LWE or TFE
5876 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5877 RegCount += 1;
5878
5879 const uint32_t DstIdx =
5880 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5881 const MachineOperand &Dst = MI.getOperand(DstIdx);
5882 if (Dst.isReg()) {
5883 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5884 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5885 if (RegCount > DstSize) {
5886 ErrInfo = "Image instruction returns too many registers for dst "
5887 "register class";
5888 return false;
5889 }
5890 }
5891 }
5892 }
5893
5894 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5895 if (isVALU(MI, /*AllowLDSDMA=*/false) &&
5896 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5897 unsigned ConstantBusCount = 0;
5898 bool UsesLiteral = false;
5899 const MachineOperand *LiteralVal = nullptr;
5900
5901 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5902 if (ImmIdx != -1) {
5903 ++ConstantBusCount;
5904 UsesLiteral = true;
5905 LiteralVal = &MI.getOperand(ImmIdx);
5906 }
5907
5908 SmallVector<Register, 2> SGPRsUsed;
5909 Register SGPRUsed;
5910
5911 // Only look at the true operands. Only a real operand can use the constant
5912 // bus, and we don't want to check pseudo-operands like the source modifier
5913 // flags.
5914 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5915 if (OpIdx == -1)
5916 continue;
5917 const MachineOperand &MO = MI.getOperand(OpIdx);
5918 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5919 if (MO.isReg()) {
5920 SGPRUsed = MO.getReg();
5921 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5922 ++ConstantBusCount;
5923 SGPRsUsed.push_back(SGPRUsed);
5924 }
5925 } else if (!MO.isFI()) { // Treat FI like a register.
5926 if (!UsesLiteral) {
5927 ++ConstantBusCount;
5928 UsesLiteral = true;
5929 LiteralVal = &MO;
5930 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5931 assert(isVOP2(MI) || isVOP3(MI));
5932 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5933 return false;
5934 }
5935 }
5936 }
5937 }
5938
5939 SGPRUsed = findImplicitSGPRRead(MI);
5940 if (SGPRUsed) {
5941 // Implicit uses may safely overlap true operands
5942 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5943 return !RI.regsOverlap(SGPRUsed, SGPR);
5944 })) {
5945 ++ConstantBusCount;
5946 SGPRsUsed.push_back(SGPRUsed);
5947 }
5948 }
5949
5950 // v_writelane_b32 is an exception from constant bus restriction:
5951 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5952 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5953 Opcode != AMDGPU::V_WRITELANE_B32) {
5954 ErrInfo = "VOP* instruction violates constant bus restriction";
5955 return false;
5956 }
5957
5958 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5959 ErrInfo = "VOP3 instruction uses literal";
5960 return false;
5961 }
5962 }
5963
5964 // Special case for writelane - this can break the multiple constant bus rule,
5965 // but still can't use more than one SGPR register
5966 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5967 unsigned SGPRCount = 0;
5968 Register SGPRUsed;
5969
5970 for (int OpIdx : {Src0Idx, Src1Idx}) {
5971 if (OpIdx == -1)
5972 break;
5973
5974 const MachineOperand &MO = MI.getOperand(OpIdx);
5975
5976 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5977 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5978 if (MO.getReg() != SGPRUsed)
5979 ++SGPRCount;
5980 SGPRUsed = MO.getReg();
5981 }
5982 }
5983 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5984 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5985 return false;
5986 }
5987 }
5988 }
5989
5990 if (Opcode == AMDGPU::ASYNCMARK || Opcode == AMDGPU::WAIT_ASYNCMARK) {
5991 int64_t Mask = MI.getOperand(MI.getNumExplicitOperands() - 1).getImm();
5992 if (!AMDGPU::isValidAsyncStageMask(Mask)) {
5993 ErrInfo = "invalid asyncmark stage mask";
5994 return false;
5995 }
5996 }
5997
5998 // Verify misc. restrictions on specific instructions.
5999 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
6000 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
6001 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
6002 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
6003 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
6004 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
6005 if (!compareMachineOp(Src0, Src1) &&
6006 !compareMachineOp(Src0, Src2)) {
6007 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
6008 return false;
6009 }
6010 }
6011 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
6012 SISrcMods::ABS) ||
6013 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
6014 SISrcMods::ABS) ||
6015 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
6016 SISrcMods::ABS)) {
6017 ErrInfo = "ABS not allowed in VOP3B instructions";
6018 return false;
6019 }
6020 }
6021
6022 if (isSOP2(MI) || isSOPC(MI)) {
6023 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
6024 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
6025
6026 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
6027 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
6028 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
6029 !Src0.isIdenticalTo(Src1)) {
6030 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
6031 return false;
6032 }
6033 }
6034
6035 if (isSOPK(MI)) {
6036 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
6037 if (Desc.isBranch()) {
6038 if (!Op->isMBB()) {
6039 ErrInfo = "invalid branch target for SOPK instruction";
6040 return false;
6041 }
6042 } else {
6043 uint64_t Imm = Op->getImm();
6044 if (sopkIsZext(Opcode)) {
6045 if (!isUInt<16>(Imm)) {
6046 ErrInfo = "invalid immediate for SOPK instruction";
6047 return false;
6048 }
6049 } else {
6050 if (!isInt<16>(Imm)) {
6051 ErrInfo = "invalid immediate for SOPK instruction";
6052 return false;
6053 }
6054 }
6055 }
6056 }
6057
6058 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
6059 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
6060 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
6061 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
6062 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
6063 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
6064
6065 const unsigned StaticNumOps =
6066 Desc.getNumOperands() + Desc.implicit_uses().size();
6067 const unsigned NumImplicitOps = IsDst ? 2 : 1;
6068
6069 // Require additional implicit operands. This allows a fixup done by the
6070 // post RA scheduler where the main implicit operand is killed and
6071 // implicit-defs are added for sub-registers that remain live after this
6072 // instruction.
6073 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
6074 ErrInfo = "missing implicit register operands";
6075 return false;
6076 }
6077
6078 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
6079 if (IsDst) {
6080 if (!Dst->isUse()) {
6081 ErrInfo = "v_movreld_b32 vdst should be a use operand";
6082 return false;
6083 }
6084
6085 unsigned UseOpIdx;
6086 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
6087 UseOpIdx != StaticNumOps + 1) {
6088 ErrInfo = "movrel implicit operands should be tied";
6089 return false;
6090 }
6091 }
6092
6093 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
6094 const MachineOperand &ImpUse
6095 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
6096 if (!ImpUse.isReg() || !ImpUse.isUse() ||
6097 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
6098 ErrInfo = "src0 should be subreg of implicit vector use";
6099 return false;
6100 }
6101 }
6102
6103 // Make sure we aren't losing exec uses in the td files. This mostly requires
6104 // being careful when using let Uses to try to add other use registers.
6105 if (shouldReadExec(MI)) {
6106 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
6107 ErrInfo = "VALU instruction does not implicitly read exec mask";
6108 return false;
6109 }
6110 }
6111
6112 if (isSMRD(MI)) {
6113 if (MI.mayStore() &&
6114 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
6115 // The register offset form of scalar stores may only use m0 as the
6116 // soffset register.
6117 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
6118 if (Soff && Soff->getReg() != AMDGPU::M0) {
6119 ErrInfo = "scalar stores must use m0 as offset register";
6120 return false;
6121 }
6122 }
6123 }
6124
6125 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
6126 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
6127 if (Offset->getImm() != 0) {
6128 ErrInfo = "subtarget does not support offsets in flat instructions";
6129 return false;
6130 }
6131 }
6132
6133 if (isDS(MI) && !ST.hasGDS()) {
6134 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
6135 if (GDSOp && GDSOp->getImm() != 0) {
6136 ErrInfo = "GDS is not supported on this subtarget";
6137 return false;
6138 }
6139 }
6140
6141 if (isImage(MI)) {
6142 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
6143 if (DimOp) {
6144 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
6145 AMDGPU::OpName::vaddr0);
6146 AMDGPU::OpName RSrcOpName =
6147 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
6148 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
6149 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
6150 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
6151 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
6152 const AMDGPU::MIMGDimInfo *Dim =
6154
6155 if (!Dim) {
6156 ErrInfo = "dim is out of range";
6157 return false;
6158 }
6159
6160 bool IsA16 = false;
6161 if (ST.hasR128A16()) {
6162 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
6163 IsA16 = R128A16->getImm() != 0;
6164 } else if (ST.hasA16()) {
6165 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
6166 IsA16 = A16->getImm() != 0;
6167 }
6168
6169 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
6170
6171 unsigned AddrWords =
6172 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
6173
6174 unsigned VAddrWords;
6175 if (IsNSA) {
6176 VAddrWords = RsrcIdx - VAddr0Idx;
6177 if (ST.hasPartialNSAEncoding() &&
6178 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
6179 unsigned LastVAddrIdx = RsrcIdx - 1;
6180 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
6181 }
6182 } else {
6183 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
6184 if (AddrWords > 12)
6185 AddrWords = 16;
6186 }
6187
6188 if (VAddrWords != AddrWords) {
6189 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
6190 << " but got " << VAddrWords << "\n");
6191 ErrInfo = "bad vaddr size";
6192 return false;
6193 }
6194 }
6195 }
6196
6197 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
6198 if (DppCt) {
6199 using namespace AMDGPU::DPP;
6200
6201 unsigned DC = DppCt->getImm();
6202 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6203 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6204 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6205 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6206 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6207 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6208 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6209 ErrInfo = "Invalid dpp_ctrl value";
6210 return false;
6211 }
6212 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6213 !ST.hasDPPWavefrontShifts()) {
6214 ErrInfo = "Invalid dpp_ctrl value: "
6215 "wavefront shifts are not supported on GFX10+";
6216 return false;
6217 }
6218 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6219 !ST.hasDPPBroadcasts()) {
6220 ErrInfo = "Invalid dpp_ctrl value: "
6221 "broadcasts are not supported on GFX10+";
6222 return false;
6223 }
6224 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6225 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
6226 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6227 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6228 !ST.hasGFX90AInsts()) {
6229 ErrInfo = "Invalid dpp_ctrl value: "
6230 "row_newbroadcast/row_share is not supported before "
6231 "GFX90A/GFX10";
6232 return false;
6233 }
6234 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6235 ErrInfo = "Invalid dpp_ctrl value: "
6236 "row_share and row_xmask are not supported before GFX10";
6237 return false;
6238 }
6239 }
6240
6241 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6243 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6244 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
6245 ErrInfo = "Invalid dpp_ctrl value: "
6246 "DP ALU dpp only support row_newbcast";
6247 return false;
6248 }
6249 }
6250
6251 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
6252 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
6253 AMDGPU::OpName DataName =
6254 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6255 const MachineOperand *Data = getNamedOperand(MI, DataName);
6256 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
6257 if (Data && !Data->isReg())
6258 Data = nullptr;
6259
6260 if (!ST.hasGFX90AInsts()) {
6261 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6262 (Data && RI.isAGPR(MRI, Data->getReg())) ||
6263 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
6264 ErrInfo = "Invalid register class: "
6265 "agpr loads and stores not supported on this GPU";
6266 return false;
6267 }
6268 }
6269 }
6270
6271 if (ST.needsAlignedVGPRs()) {
6272 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
6274 if (!Op)
6275 return true;
6276 Register Reg = Op->getReg();
6277 if (Reg.isPhysical())
6278 return !(RI.getHWRegIndex(Reg) & 1);
6279 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
6280 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6281 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
6282 };
6283
6284 if (isMIMG(MI)) {
6285 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6286 ErrInfo = "Subtarget requires even aligned vector registers "
6287 "for vaddr operand of image instructions";
6288 return false;
6289 }
6290 }
6291 }
6292
6293 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6294 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
6295 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6296 ErrInfo = "Invalid register class: "
6297 "v_accvgpr_write with an SGPR is not supported on this GPU";
6298 return false;
6299 }
6300 }
6301
6302 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6303 const MachineOperand &SrcOp = MI.getOperand(1);
6304 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
6305 ErrInfo = "pseudo expects only physical SGPRs";
6306 return false;
6307 }
6308 }
6309
6310 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
6311 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
6312 if (!ST.hasScaleOffset()) {
6313 ErrInfo = "Subtarget does not support offset scaling";
6314 return false;
6315 }
6316 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
6317 ErrInfo = "Instruction does not support offset scaling";
6318 return false;
6319 }
6320 }
6321 }
6322
6323 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6324 if (AMDGPU::isSingleSGPRReadInst(Opcode)) {
6325 for (unsigned I = 0; I < 3; ++I) {
6327 return false;
6328 }
6329 }
6330
6331 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
6332 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
6333 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
6334 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6335 &AMDGPU::SReg_64RegClass) ||
6336 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6337 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
6338 return false;
6339 }
6340 }
6341
6342 // GFX950 v_pk_{add,mul,fma}_f32 must not have an invalid op_sel.
6343 if (!isLegalPkF32OpSel(*this, MI)) {
6344 ErrInfo = "GFX950 v_pk_{add,mul,fma}_f32 has an invalid op_sel.";
6345 return false;
6346 }
6347
6348 return true;
6349}
6350
6352 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
6353 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6354 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
6355 ? AMDGPU::COPY
6356 : AMDGPU::V_MOV_B32_e32;
6357 }
6358 return getVALUOp(MI.getOpcode());
6359}
6360
6361// It is more readable to list mapped opcodes on the same line.
6362// clang-format off
6363
6364unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
6365 switch (Opc) {
6366 default: return AMDGPU::INSTRUCTION_LIST_END;
6367 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
6368 case AMDGPU::COPY: return AMDGPU::COPY;
6369 case AMDGPU::PHI: return AMDGPU::PHI;
6370 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
6371 case AMDGPU::WQM: return AMDGPU::WQM;
6372 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
6373 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
6374 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
6375 case AMDGPU::S_ADD_I32:
6376 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6377 case AMDGPU::S_ADDC_U32:
6378 return AMDGPU::V_ADDC_U32_e32;
6379 case AMDGPU::S_SUB_I32:
6380 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6381 // FIXME: These are not consistently handled, and selected when the carry is
6382 // used.
6383 case AMDGPU::S_ADD_U32:
6384 return AMDGPU::V_ADD_CO_U32_e32;
6385 case AMDGPU::S_SUB_U32:
6386 return AMDGPU::V_SUB_CO_U32_e32;
6387 case AMDGPU::S_ADD_U64_PSEUDO:
6388 return AMDGPU::V_ADD_U64_PSEUDO;
6389 case AMDGPU::S_SUB_U64_PSEUDO:
6390 return AMDGPU::V_SUB_U64_PSEUDO;
6391 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
6392 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
6393 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
6394 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
6395 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
6396 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
6397 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
6398 case AMDGPU::S_XNOR_B32:
6399 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6400 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
6401 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
6402 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
6403 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
6404 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
6405 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
6406 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
6407 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
6408 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
6409 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
6410 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
6411 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
6412 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
6413 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
6414 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
6415 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
6416 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
6417 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
6418 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
6419 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
6420 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
6421 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
6422 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
6423 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
6424 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
6425 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
6426 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
6427 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
6428 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
6429 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
6430 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
6431 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
6432 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
6433 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
6434 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
6435 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
6436 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
6437 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
6438 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
6439 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
6440 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
6441 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
6442 case AMDGPU::S_CVT_F32_F16:
6443 case AMDGPU::S_CVT_HI_F32_F16:
6444 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6445 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6446 case AMDGPU::S_CVT_F16_F32:
6447 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6448 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6449 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
6450 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
6451 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
6452 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
6453 case AMDGPU::S_CEIL_F16:
6454 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6455 : AMDGPU::V_CEIL_F16_fake16_e64;
6456 case AMDGPU::S_FLOOR_F16:
6457 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6458 : AMDGPU::V_FLOOR_F16_fake16_e64;
6459 case AMDGPU::S_TRUNC_F16:
6460 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6461 : AMDGPU::V_TRUNC_F16_fake16_e64;
6462 case AMDGPU::S_RNDNE_F16:
6463 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6464 : AMDGPU::V_RNDNE_F16_fake16_e64;
6465 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6466 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6467 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6468 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6469 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6470 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6471 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6472 case AMDGPU::S_ADD_F16:
6473 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6474 : AMDGPU::V_ADD_F16_fake16_e64;
6475 case AMDGPU::S_SUB_F16:
6476 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6477 : AMDGPU::V_SUB_F16_fake16_e64;
6478 case AMDGPU::S_MIN_F16:
6479 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6480 : AMDGPU::V_MIN_F16_fake16_e64;
6481 case AMDGPU::S_MAX_F16:
6482 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6483 : AMDGPU::V_MAX_F16_fake16_e64;
6484 case AMDGPU::S_MINIMUM_F16:
6485 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6486 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6487 case AMDGPU::S_MAXIMUM_F16:
6488 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6489 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6490 case AMDGPU::S_MUL_F16:
6491 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6492 : AMDGPU::V_MUL_F16_fake16_e64;
6493 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6494 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6495 case AMDGPU::S_FMAC_F16:
6496 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6497 : AMDGPU::V_FMAC_F16_fake16_e64;
6498 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6499 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6500 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6501 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6502 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6503 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6504 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6505 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6506 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6507 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6508 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6509 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6510 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6511 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6512 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6513 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6514 case AMDGPU::S_CMP_LT_F16:
6515 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6516 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6517 case AMDGPU::S_CMP_EQ_F16:
6518 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6519 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6520 case AMDGPU::S_CMP_LE_F16:
6521 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6522 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6523 case AMDGPU::S_CMP_GT_F16:
6524 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6525 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6526 case AMDGPU::S_CMP_LG_F16:
6527 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6528 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6529 case AMDGPU::S_CMP_GE_F16:
6530 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6531 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6532 case AMDGPU::S_CMP_O_F16:
6533 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6534 : AMDGPU::V_CMP_O_F16_fake16_e64;
6535 case AMDGPU::S_CMP_U_F16:
6536 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6537 : AMDGPU::V_CMP_U_F16_fake16_e64;
6538 case AMDGPU::S_CMP_NGE_F16:
6539 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6540 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6541 case AMDGPU::S_CMP_NLG_F16:
6542 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6543 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6544 case AMDGPU::S_CMP_NGT_F16:
6545 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6546 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6547 case AMDGPU::S_CMP_NLE_F16:
6548 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6549 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6550 case AMDGPU::S_CMP_NEQ_F16:
6551 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6552 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6553 case AMDGPU::S_CMP_NLT_F16:
6554 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6555 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6556 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6557 case AMDGPU::V_S_EXP_F16_e64:
6558 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6559 : AMDGPU::V_EXP_F16_fake16_e64;
6560 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6561 case AMDGPU::V_S_LOG_F16_e64:
6562 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6563 : AMDGPU::V_LOG_F16_fake16_e64;
6564 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6565 case AMDGPU::V_S_RCP_F16_e64:
6566 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6567 : AMDGPU::V_RCP_F16_fake16_e64;
6568 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6569 case AMDGPU::V_S_RSQ_F16_e64:
6570 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6571 : AMDGPU::V_RSQ_F16_fake16_e64;
6572 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6573 case AMDGPU::V_S_SQRT_F16_e64:
6574 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6575 : AMDGPU::V_SQRT_F16_fake16_e64;
6576 }
6578 "Unexpected scalar opcode without corresponding vector one!");
6579}
6580
6581// clang-format on
6582
6586 const DebugLoc &DL, Register Reg,
6587 bool IsSCCLive,
6588 SlotIndexes *Indexes) const {
6589 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6590 const SIInstrInfo *TII = ST.getInstrInfo();
6592 if (IsSCCLive) {
6593 // Insert two move instructions, one to save the original value of EXEC and
6594 // the other to turn on all bits in EXEC. This is required as we can't use
6595 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6596 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6598 auto FlipExecMI =
6599 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6600 if (Indexes) {
6601 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6602 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6603 }
6604 } else {
6605 auto SaveExec =
6606 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6607 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6608 if (Indexes)
6609 Indexes->insertMachineInstrInMaps(*SaveExec);
6610 }
6611}
6612
6615 const DebugLoc &DL, Register Reg,
6616 SlotIndexes *Indexes) const {
6618 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6619 .addReg(Reg, RegState::Kill);
6620 if (Indexes)
6621 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6622}
6623
6627 "Not a whole wave func");
6628 MachineBasicBlock &MBB = *MF.begin();
6629 for (MachineInstr &MI : MBB)
6630 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6631 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6632 return &MI;
6633
6634 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6635}
6636
6638 unsigned OpNo) const {
6639 const MCInstrDesc &Desc = get(MI.getOpcode());
6640 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6641 Desc.operands()[OpNo].RegClass == -1) {
6642 Register Reg = MI.getOperand(OpNo).getReg();
6643
6644 if (Reg.isVirtual()) {
6645 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6646 return MRI.getRegClass(Reg);
6647 }
6648 return RI.getPhysRegBaseClass(Reg);
6649 }
6650
6651 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6652 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6653}
6654
6655// Convert VOP3 operand index to source number.
6656static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx) {
6657 constexpr AMDGPU::OpName OpNames[] = {
6658 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6659
6660 for (auto [I, OpName] : enumerate(OpNames)) {
6661 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6662 if (static_cast<unsigned>(SrcIdx) == OpIdx)
6663 return I;
6664 }
6665
6666 return UINT_MAX;
6667}
6668
6671 MachineBasicBlock *MBB = MI.getParent();
6672 MachineOperand &MO = MI.getOperand(OpIdx);
6673 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6674 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6675 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6676 unsigned Size = RI.getRegSizeInBits(*RC);
6677 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6678 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6679 : AMDGPU::V_MOV_B32_e32;
6680 if (MO.isReg())
6681 Opcode = AMDGPU::COPY;
6682 else if (RI.isSGPRClass(RC))
6683 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6684
6685 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6686 Register Reg = MRI.createVirtualRegister(VRC);
6687 DebugLoc DL = MBB->findDebugLoc(I);
6688
6689 if (Size == 128 && AMDGPU::isPackedSingleSGPR64BitInst(MI.getOpcode()) &&
6691 // Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
6692 // sources behave like OPSEL is set replicating low 64-bits into high. VGPR
6693 // sources in turn read actual 4 registers. To move operand from an SGPR to
6694 // a VGPR we need to replicate low half.
6695 // We also do not select immediates for these instructions so it always has
6696 // to be an SGPR register here.
6697 // Operands which are not legal as per isLegalSingleSGPRReadInstOperand()
6698 // sent here specifically to fix a non-splat SGPR and shall perform a full
6699 // copy.
6700
6701 const TargetRegisterClass *VRC64 = RI.getVGPRClassForBitWidth(64);
6702 Register Low64 = MRI.createVirtualRegister(VRC64);
6703 assert(MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()));
6704 BuildMI(*MBB, I, DL, get(TargetOpcode::COPY), Low64)
6705 .addReg(MO.getReg(), {}, AMDGPU::sub0_sub1);
6706 BuildMI(*MBB, I, DL, get(TargetOpcode::REG_SEQUENCE), Reg)
6707 .addReg(Low64)
6708 .addImm(AMDGPU::sub0_sub1)
6709 .addReg(Low64)
6710 .addImm(AMDGPU::sub2_sub3);
6711 } else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6712 BuildMI(*MBB, I, DL, get(Opcode), Reg)
6713 .addImm(0) // src0_modifiers
6714 .add(MO)
6715 .addImm(0); // op_sel
6716 } else {
6717 BuildMI(*MBB, I, DL, get(Opcode), Reg).add(MO);
6718 }
6719
6720 MO.ChangeToRegister(Reg, false);
6721}
6722
6725 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6726 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6727 if (!SuperReg.getReg().isVirtual())
6728 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6729
6730 MachineBasicBlock *MBB = MI->getParent();
6731 const DebugLoc &DL = MI->getDebugLoc();
6732 Register SubReg = MRI.createVirtualRegister(SubRC);
6733
6734 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6735 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6736 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6737 return SubReg;
6738}
6739
6742 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6743 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6744 if (Op.isImm()) {
6745 if (SubIdx == AMDGPU::sub0)
6746 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6747 if (SubIdx == AMDGPU::sub1)
6748 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6749
6750 llvm_unreachable("Unhandled register index for immediate");
6751 }
6752
6753 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6754 SubIdx, SubRC);
6755 return MachineOperand::CreateReg(SubReg, false);
6756}
6757
6758// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6759void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6760 assert(Inst.getNumExplicitOperands() == 3);
6761 MachineOperand Op1 = Inst.getOperand(1);
6762 Inst.removeOperand(1);
6763 Inst.addOperand(Op1);
6764}
6765
6767 const MCOperandInfo &OpInfo,
6768 const MachineOperand &MO) const {
6769 if (!MO.isReg())
6770 return false;
6771
6772 Register Reg = MO.getReg();
6773
6774 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6775 if (Reg.isPhysical())
6776 return DRC->contains(Reg);
6777
6778 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6779
6780 if (MO.getSubReg()) {
6781 const TargetRegisterClass *SuperRC =
6782 RI.getLargestLegalSuperClass(RC, MRI.getMF());
6783 if (!SuperRC)
6784 return false;
6785 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6786 }
6787
6788 return RI.getCommonSubClass(DRC, RC) != nullptr;
6789}
6790
6792 const MachineOperand &MO) const {
6793 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6794 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6795 unsigned Opc = MI.getOpcode();
6796
6797 // See SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
6798 if (MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
6799 AMDGPU::isSingleSGPRReadInst(MI.getOpcode()) &&
6801 &MO))
6802 return false;
6803
6804 if (!isLegalRegOperand(MRI, OpInfo, MO))
6805 return false;
6806
6807 // check Accumulate GPR operand
6808 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6809 if (IsAGPR && !ST.hasMAIInsts())
6810 return false;
6811 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6812 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6813 return false;
6814 // Atomics should have both vdst and vdata either vgpr or agpr.
6815 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6816 const int DataIdx = AMDGPU::getNamedOperandIdx(
6817 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6818 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6819 MI.getOperand(DataIdx).isReg() &&
6820 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6821 return false;
6822 if ((int)OpIdx == DataIdx) {
6823 if (VDstIdx != -1 &&
6824 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6825 return false;
6826 // DS instructions with 2 src operands also must have tied RC.
6827 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6828 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6829 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6830 return false;
6831 }
6832
6833 // Check V_ACCVGPR_WRITE_B32_e64
6834 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6835 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6836 RI.isSGPRReg(MRI, MO.getReg()))
6837 return false;
6838
6839 if (ST.hasFlatScratchHiInB64InstHazard() &&
6840 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6841 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6842 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6843 64)
6844 return false;
6845 }
6846 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6847 return false;
6848 }
6849 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6850 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6851 return false;
6852
6853 return true;
6854}
6855
6857 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6858 const MachineOperand *MO) const {
6859 constexpr unsigned NumOps = 3;
6860 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6861 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6862 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6863 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6864
6865 assert(SrcN < NumOps);
6866
6867 if (!MO) {
6868 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6869 if (SrcIdx == -1)
6870 return true;
6871 MO = &MI.getOperand(SrcIdx);
6872 }
6873
6874 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6875 return true;
6876
6877 int ModsIdx =
6878 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6879 if (ModsIdx == -1)
6880 return false;
6881
6882 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6883 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6884 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6885
6886 return !OpSel && !OpSelHi;
6887}
6888
6889bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
6890 const MachineOperand *MO) const {
6891 const MachineFunction &MF = *MI.getMF();
6892 const MachineRegisterInfo &MRI = MF.getRegInfo();
6893 const MCInstrDesc &InstDesc = MI.getDesc();
6894 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6895 int64_t RegClass = getOpRegClassID(OpInfo);
6896 const TargetRegisterClass *DefinedRC =
6897 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6898 if (!MO)
6899 MO = &MI.getOperand(OpIdx);
6900
6901 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6902
6903 if (isVALU(MI, /*AllowLDSDMA=*/false) && !IsInlineConst &&
6904 usesConstantBus(MRI, *MO, OpInfo)) {
6905 const MachineOperand *UsedLiteral = nullptr;
6906
6907 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6908 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6909
6910 // TODO: Be more permissive with frame indexes.
6911 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6912 if (!LiteralLimit--)
6913 return false;
6914
6915 UsedLiteral = MO;
6916 }
6917
6919 if (MO->isReg())
6920 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6921
6922 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6923 if (i == OpIdx)
6924 continue;
6925 const MachineOperand &Op = MI.getOperand(i);
6926 if (Op.isReg()) {
6927 if (Op.isUse()) {
6928 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6929 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6930 if (--ConstantBusLimit <= 0)
6931 return false;
6932 }
6933 }
6934 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6935 !isInlineConstant(Op, InstDesc.operands()[i])) {
6936 // The same literal may be used multiple times.
6937 if (!UsedLiteral)
6938 UsedLiteral = &Op;
6939 else if (UsedLiteral->isIdenticalTo(Op))
6940 continue;
6941
6942 if (!LiteralLimit--)
6943 return false;
6944 if (--ConstantBusLimit <= 0)
6945 return false;
6946 }
6947 }
6948 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6949 // There can be at most one literal operand, but it can be repeated.
6950 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6951 if (i == OpIdx)
6952 continue;
6953 const MachineOperand &Op = MI.getOperand(i);
6954 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6955 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6956 !Op.isIdenticalTo(*MO))
6957 return false;
6958
6959 // Do not fold a non-inlineable and non-register operand into an
6960 // instruction that already has a frame index. The frame index handling
6961 // code could not handle well when a frame index co-exists with another
6962 // non-register operand, unless that operand is an inlineable immediate.
6963 if (Op.isFI())
6964 return false;
6965 }
6966 }
6967
6968 if (MO->isReg()) {
6969 if (!DefinedRC)
6970 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6971 return isLegalRegOperand(MI, OpIdx, *MO);
6972 }
6973
6974 if (MO->isImm()) {
6975 uint64_t Imm = MO->getImm();
6976 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6977 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6978 bool Is64BitOp = Is64BitFPOp ||
6979 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6980 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6981 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6982 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6983 if (Is64BitOp &&
6984 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6985 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6986 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6987 return false;
6988
6989 // FIXME: We can use sign extended 64-bit literals, but only for signed
6990 // operands. At the moment we do not know if an operand is signed.
6991 // Such operand will be encoded as its low 32 bits and then either
6992 // correctly sign extended or incorrectly zero extended by HW.
6993 // If 64-bit literals are supported and the literal will be encoded
6994 // as full 64 bit we still can use it.
6995 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6996 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
6997 return false;
6998 }
6999 }
7000
7001 // Handle non-register types that are treated like immediates.
7002 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
7003
7004 if (!DefinedRC) {
7005 // This operand expects an immediate.
7006 return true;
7007 }
7008
7009 return isImmOperandLegal(MI, OpIdx, *MO);
7010}
7011
7013 bool IsGFX950Only = ST.hasGFX950Insts();
7014 bool IsGFX940Only = ST.hasGFX940Insts();
7015
7016 if (!IsGFX950Only && !IsGFX940Only)
7017 return false;
7018
7019 if (!isVALU(MI, /*AllowLDSDMA=*/false))
7020 return false;
7021
7022 // V_COS, V_EXP, V_RCP, etc.
7023 if (isTRANS(MI))
7024 return true;
7025
7026 // DOT2, DOT2C, DOT4, etc.
7027 if (isDOT(MI))
7028 return true;
7029
7030 // MFMA, SMFMA
7031 if (isMFMA(MI))
7032 return true;
7033
7034 unsigned Opcode = MI.getOpcode();
7035 switch (Opcode) {
7036 case AMDGPU::V_CVT_PK_BF8_F32_e64:
7037 case AMDGPU::V_CVT_PK_FP8_F32_e64:
7038 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
7039 case AMDGPU::V_MQSAD_U32_U8_e64:
7040 case AMDGPU::V_PK_ADD_F16:
7041 case AMDGPU::V_PK_ADD_F32:
7042 case AMDGPU::V_PK_ADD_I16:
7043 case AMDGPU::V_PK_ADD_U16:
7044 case AMDGPU::V_PK_ASHRREV_I16:
7045 case AMDGPU::V_PK_FMA_F16:
7046 case AMDGPU::V_PK_FMA_F32:
7047 case AMDGPU::V_PK_FMAC_F16_e32:
7048 case AMDGPU::V_PK_FMAC_F16_e64:
7049 case AMDGPU::V_PK_LSHLREV_B16:
7050 case AMDGPU::V_PK_LSHRREV_B16:
7051 case AMDGPU::V_PK_MAD_I16:
7052 case AMDGPU::V_PK_MAD_U16:
7053 case AMDGPU::V_PK_MAX_F16:
7054 case AMDGPU::V_PK_MAX_I16:
7055 case AMDGPU::V_PK_MAX_U16:
7056 case AMDGPU::V_PK_MIN_F16:
7057 case AMDGPU::V_PK_MIN_I16:
7058 case AMDGPU::V_PK_MIN_U16:
7059 case AMDGPU::V_PK_MOV_B32:
7060 case AMDGPU::V_PK_MUL_F16:
7061 case AMDGPU::V_PK_MUL_F32:
7062 case AMDGPU::V_PK_MUL_LO_U16:
7063 case AMDGPU::V_PK_SUB_I16:
7064 case AMDGPU::V_PK_SUB_U16:
7065 case AMDGPU::V_QSAD_PK_U16_U8_e64:
7066 return true;
7067 default:
7068 return false;
7069 }
7070}
7071
7073 MachineInstr &MI) const {
7074 unsigned Opc = MI.getOpcode();
7075 const MCInstrDesc &InstrDesc = get(Opc);
7076
7077 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
7078 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7079
7080 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
7081 MachineOperand &Src1 = MI.getOperand(Src1Idx);
7082
7083 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
7084 // we need to only have one constant bus use before GFX10.
7085 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
7086 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
7087 RI.isSGPRReg(MRI, Src0.getReg()))
7088 legalizeOpWithMove(MI, Src0Idx);
7089
7090 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
7091 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
7092 // src0/src1 with V_READFIRSTLANE.
7093 if (Opc == AMDGPU::V_WRITELANE_B32) {
7094 const DebugLoc &DL = MI.getDebugLoc();
7095 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
7096 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7097 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7098 .add(Src0);
7099 Src0.ChangeToRegister(Reg, false);
7100 }
7101 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
7102 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7103 const DebugLoc &DL = MI.getDebugLoc();
7104 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7105 .add(Src1);
7106 Src1.ChangeToRegister(Reg, false);
7107 }
7108 return;
7109 }
7110
7111 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
7112 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
7113 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
7114 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
7115 legalizeOpWithMove(MI, Src2Idx);
7116 }
7117
7118 // VOP2 src0 instructions support all operand types, so we don't need to check
7119 // their legality. If src1 is already legal, we don't need to do anything.
7120 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
7121 return;
7122
7123 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
7124 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
7125 // select is uniform.
7126 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
7127 RI.isVGPR(MRI, Src1.getReg())) {
7128 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7129 const DebugLoc &DL = MI.getDebugLoc();
7130 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7131 .add(Src1);
7132 Src1.ChangeToRegister(Reg, false);
7133 return;
7134 }
7135
7136 // We do not use commuteInstruction here because it is too aggressive and will
7137 // commute if it is possible. We only want to commute here if it improves
7138 // legality. This can be called a fairly large number of times so don't waste
7139 // compile time pointlessly swapping and checking legality again.
7140 if (HasImplicitSGPR || !MI.isCommutable()) {
7141 legalizeOpWithMove(MI, Src1Idx);
7142 return;
7143 }
7144
7145 // If src0 can be used as src1, commuting will make the operands legal.
7146 // Otherwise we have to give up and insert a move.
7147 //
7148 // TODO: Other immediate-like operand kinds could be commuted if there was a
7149 // MachineOperand::ChangeTo* for them.
7150 if ((!Src1.isImm() && !Src1.isReg()) ||
7151 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
7152 legalizeOpWithMove(MI, Src1Idx);
7153 return;
7154 }
7155
7156 int CommutedOpc = commuteOpcode(MI);
7157 if (CommutedOpc == -1) {
7158 legalizeOpWithMove(MI, Src1Idx);
7159 return;
7160 }
7161
7162 MI.setDesc(get(CommutedOpc));
7163
7164 Register Src0Reg = Src0.getReg();
7165 unsigned Src0SubReg = Src0.getSubReg();
7166 bool Src0Kill = Src0.isKill();
7167
7168 if (Src1.isImm())
7169 Src0.ChangeToImmediate(Src1.getImm());
7170 else if (Src1.isReg()) {
7171 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
7172 Src0.setSubReg(Src1.getSubReg());
7173 } else
7174 llvm_unreachable("Should only have register or immediate operands");
7175
7176 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
7177 Src1.setSubReg(Src0SubReg);
7179}
7180
7181// Legalize VOP3 operands. All operand types are supported for any operand
7182// but only one literal constant and only starting from GFX10.
7184 MachineInstr &MI) const {
7185 unsigned Opc = MI.getOpcode();
7186
7187 int VOP3Idx[3] = {
7188 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
7189 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
7190 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
7191 };
7192
7193 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7194 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7195 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7196 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7197 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7198 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7199 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7200 // src1 and src2 must be scalar
7201 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
7202 const DebugLoc &DL = MI.getDebugLoc();
7203 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
7204 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7205 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7206 .add(Src1);
7207 Src1.ChangeToRegister(Reg, false);
7208 }
7209 if (VOP3Idx[2] != -1) {
7210 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
7211 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
7212 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7213 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7214 .add(Src2);
7215 Src2.ChangeToRegister(Reg, false);
7216 }
7217 }
7218 }
7219
7220 // Find the one SGPR operand we are allowed to use.
7221 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
7222 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7223 SmallDenseSet<unsigned> SGPRsUsed;
7224 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
7225 if (SGPRReg) {
7226 SGPRsUsed.insert(SGPRReg);
7227 --ConstantBusLimit;
7228 }
7229
7230 for (int Idx : VOP3Idx) {
7231 if (Idx == -1)
7232 break;
7233 MachineOperand &MO = MI.getOperand(Idx);
7234
7235 if (!MO.isReg()) {
7236 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
7237 continue;
7238
7239 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7240 --LiteralLimit;
7241 --ConstantBusLimit;
7242 continue;
7243 }
7244
7245 --LiteralLimit;
7246 --ConstantBusLimit;
7247 legalizeOpWithMove(MI, Idx);
7248 continue;
7249 }
7250
7251 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
7252 continue; // VGPRs are legal
7253
7254 // We can use one SGPR in each VOP3 instruction prior to GFX10
7255 // and two starting from GFX10.
7256 if (SGPRsUsed.count(MO.getReg()))
7257 continue;
7258 if (ConstantBusLimit > 0) {
7259 SGPRsUsed.insert(MO.getReg());
7260 --ConstantBusLimit;
7261 continue;
7262 }
7263
7264 // If we make it this far, then the operand is not legal and we must
7265 // legalize it.
7266 legalizeOpWithMove(MI, Idx);
7267 }
7268
7269 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
7270 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
7271 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
7272 Opc == AMDGPU::V_FMAC_F16_t16_e64) &&
7273 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
7274 legalizeOpWithMove(MI, VOP3Idx[2]);
7275
7276 // Fix the register class of single-sgpr-read instructions on gfx12+. See
7277 // SIInstrInfo::isLegalSingleSGPRReadInstOperand for more information.
7279 for (unsigned I = 0; I < 3; ++I) {
7280 if (!isLegalSingleSGPRReadInstOperand(MRI, MI, /*SrcN=*/I))
7281 legalizeOpWithMove(MI, VOP3Idx[I]);
7282 }
7283 }
7284}
7285
7288 const TargetRegisterClass *DstRC /*=nullptr*/) const {
7289 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
7290 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
7291 if (DstRC)
7292 SRC = RI.getCommonSubClass(SRC, DstRC);
7293
7294 Register DstReg = MRI.createVirtualRegister(SRC);
7295 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7296
7297 if (RI.hasAGPRs(VRC)) {
7298 VRC = RI.getEquivalentVGPRClass(VRC);
7299 Register NewSrcReg = MRI.createVirtualRegister(VRC);
7300 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7301 get(TargetOpcode::COPY), NewSrcReg)
7302 .addReg(SrcReg);
7303 SrcReg = NewSrcReg;
7304 }
7305
7306 if (SubRegs == 1) {
7307 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7308 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7309 .addReg(SrcReg);
7310 return DstReg;
7311 }
7312
7314 for (unsigned i = 0; i < SubRegs; ++i) {
7315 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7316 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7317 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7318 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7319 SRegs.push_back(SGPR);
7320 }
7321
7323 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
7324 get(AMDGPU::REG_SEQUENCE), DstReg);
7325 for (unsigned i = 0; i < SubRegs; ++i) {
7326 MIB.addReg(SRegs[i]);
7327 MIB.addImm(RI.getSubRegFromChannel(i));
7328 }
7329 return DstReg;
7330}
7331
7333 MachineInstr &MI) const {
7334
7335 // If the pointer is store in VGPRs, then we need to move them to
7336 // SGPRs using v_readfirstlane. This is safe because we only select
7337 // loads with uniform pointers to SMRD instruction so we know the
7338 // pointer value is uniform.
7339 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
7340 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
7341 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
7342 SBase->setReg(SGPR);
7343 }
7344 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
7345 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
7346 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
7347 SOff->setReg(SGPR);
7348 }
7349}
7350
7352 unsigned Opc = Inst.getOpcode();
7353 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
7354 if (OldSAddrIdx < 0)
7355 return false;
7356
7357 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
7358
7359 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
7360 if (NewOpc < 0)
7362 if (NewOpc < 0)
7363 return false;
7364
7366 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
7367 if (RI.isSGPRReg(MRI, SAddr.getReg()))
7368 return false;
7369
7370 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7371 if (NewVAddrIdx < 0)
7372 return false;
7373
7374 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
7375
7376 // Check vaddr, it shall be zero or absent.
7377 MachineInstr *VAddrDef = nullptr;
7378 if (OldVAddrIdx >= 0) {
7379 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
7380 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
7381 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
7382 !VAddrDef->getOperand(1).isImm() ||
7383 VAddrDef->getOperand(1).getImm() != 0)
7384 return false;
7385 }
7386
7387 const MCInstrDesc &NewDesc = get(NewOpc);
7388 Inst.setDesc(NewDesc);
7389
7390 // Callers expect iterator to be valid after this call, so modify the
7391 // instruction in place.
7392 if (OldVAddrIdx == NewVAddrIdx) {
7393 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
7394 // Clear use list from the old vaddr holding a zero register.
7395 MRI.removeRegOperandFromUseList(&NewVAddr);
7396 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7397 Inst.removeOperand(OldSAddrIdx);
7398 // Update the use list with the pointer we have just moved from vaddr to
7399 // saddr position. Otherwise new vaddr will be missing from the use list.
7400 MRI.removeRegOperandFromUseList(&NewVAddr);
7401 MRI.addRegOperandToUseList(&NewVAddr);
7402 } else {
7403 assert(OldSAddrIdx == NewVAddrIdx);
7404
7405 if (OldVAddrIdx >= 0) {
7406 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7407 AMDGPU::OpName::vdst_in);
7408
7409 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
7410 // it asserts. Untie the operands for now and retie them afterwards.
7411 if (NewVDstIn != -1) {
7412 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
7413 Inst.untieRegOperand(OldVDstIn);
7414 }
7415
7416 Inst.removeOperand(OldVAddrIdx);
7417
7418 if (NewVDstIn != -1) {
7419 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7420 Inst.tieOperands(NewVDst, NewVDstIn);
7421 }
7422 }
7423 }
7424
7425 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
7426 VAddrDef->eraseFromParent();
7427
7428 return true;
7429}
7430
7431// FIXME: Remove this when SelectionDAG is obsoleted.
7433 MachineInstr &MI) const {
7434 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
7435 return;
7436
7437 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
7438 // thinks they are uniform, so a readfirstlane should be valid.
7439 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
7440 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
7441 return;
7442
7444 return;
7445
7446 const TargetRegisterClass *DeclaredRC =
7447 getRegClass(MI.getDesc(), SAddr->getOperandNo());
7448
7449 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
7450 SAddr->setReg(ToSGPR);
7451}
7452
7455 const TargetRegisterClass *DstRC,
7458 const DebugLoc &DL) const {
7459 Register OpReg = Op.getReg();
7460 unsigned OpSubReg = Op.getSubReg();
7461
7462 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
7463 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7464
7465 // Check if operand is already the correct register class.
7466 if (DstRC == OpRC)
7467 return;
7468
7469 Register DstReg = MRI.createVirtualRegister(DstRC);
7470 auto Copy = BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg)
7471 .addReg(OpReg, {}, OpSubReg);
7472 Op.setReg(DstReg);
7473 Op.setSubReg(AMDGPU::NoSubRegister);
7474
7475 MachineInstr *Def = MRI.getVRegDef(OpReg);
7476 if (!Def)
7477 return;
7478
7479 // Try to eliminate the copy if it is copying an immediate value.
7480 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7481 foldImmediate(*Copy, *Def, OpReg, &MRI);
7482
7483 bool ImpDef = Def->isImplicitDef();
7484 while (!ImpDef && Def && Def->isCopy()) {
7485 if (Def->getOperand(1).getReg().isPhysical())
7486 break;
7487 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7488 ImpDef = Def && Def->isImplicitDef();
7489 }
7490 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7491 !ImpDef)
7492 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7493}
7494
7495// Emit the actual waterfall loop, executing the wrapped instruction for each
7496// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7497// iteration, in the worst case we execute 64 (once per lane).
7500 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7501 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7502 MachineFunction &MF = *LoopBB.getParent();
7504 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7506 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7507
7508 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7509 // available. Otherwise, use the previous pattern of v_cmp_eq,
7510 // s_and_saveexec, and s_xor.
7511 bool UseNewExecInstructions =
7512 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7513
7515 Register CondReg;
7516
7517 Register PhiExec;
7518 Register NewExec;
7519
7520 if (UseNewExecInstructions) {
7521 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7522 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7523 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7524 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7525 .addReg(LMC.ExecReg);
7526
7527 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7528 .addReg(InitExec)
7529 .addMBB(&PredBB)
7530 .addReg(NewExec)
7531 .addMBB(&BodyBB);
7532 }
7533
7534 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7535 // involves a trade-off between register pressure and latency:
7536 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7537 // register pressure because arguments and results of all
7538 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7539 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7540 // increase latency by placing v_readfirstlane instructions
7541 // immediately before v_cmpx instruction that directly depend on it.
7542 ///
7543 // Emitting interleaved v_cmpx and v_readfirstlane requires
7544 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7545 // v_cmpx needs to be treated as terminator until after register allocation
7546 // (spill placement) and instruction reordering.
7547 //
7548 // Current implementation defers v_cmpx and leaves other instruction
7549 // scheduling decisions to later passes, where register pressure is known or
7550 // easier to approximate.
7551 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7552 // v_cmpx instructions are inserted at the end of LoopBB.
7553 // After the first v_cmpx is emitted, I is updated to point to it
7554 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7555 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7556 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7557 unsigned NumSubRegs = RegSize / 32;
7558 Register VScalarOp = ScalarOp->getReg();
7559
7560 const TargetRegisterClass *RFLSrcRC =
7561 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7562
7563 if (NumSubRegs == 1) {
7564 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7565 if (const TargetRegisterClass *Common =
7566 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7567 Common != VScalarOpRC) {
7568 Register VRReg = MRI.createVirtualRegister(Common);
7569 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7570 VScalarOp = VRReg;
7571 }
7572 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7573
7574 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7575 .addReg(VScalarOp);
7576
7577 if (UseNewExecInstructions) {
7578 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7579 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7580 .addReg(CurReg)
7581 .addReg(VScalarOp);
7582 if (I == LoopBB.end())
7583 I = CmpxMI.getInstr()->getIterator();
7584 } else {
7585 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7586
7587 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7588 .addReg(CurReg)
7589 .addReg(VScalarOp);
7590
7591 // Combine the comparison results with AND.
7592 if (!CondReg) { // First.
7593 CondReg = NewCondReg;
7594 } else { // If not the first, we create an AND.
7595 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7596 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7597 .addReg(CondReg)
7598 .addReg(NewCondReg)
7599 .setOperandDead(3);
7600 CondReg = AndReg;
7601 }
7602 }
7603
7604 // Update ScalarOp operand to use the SGPR ScalarOp.
7605 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7606 ScalarOp->setReg(CurReg);
7607 else {
7608 // Insert into the same block of use
7609 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7610 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7611 .addReg(CurReg);
7612 ScalarOp->setReg(PhySGPRs[Idx]);
7613 }
7614 } else {
7615 SmallVector<Register, 8> ReadlanePieces;
7616 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7617 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7618 "Unhandled register size");
7619
7620 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7621 Register CurRegLo =
7622 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7623 Register CurRegHi =
7624 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7625
7626 // Read the next variant <- also loop target.
7627 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7628 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7629
7630 // Read the next variant <- also loop target.
7631 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7632 .addReg(VScalarOp, VScalarOpUndef,
7633 TRI->getSubRegFromChannel(Idx + 1));
7634
7635 ReadlanePieces.push_back(CurRegLo);
7636 ReadlanePieces.push_back(CurRegHi);
7637
7638 // Comparison is to be done as 64-bit.
7639 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7640 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7641 .addReg(CurRegLo)
7642 .addImm(AMDGPU::sub0)
7643 .addReg(CurRegHi)
7644 .addImm(AMDGPU::sub1);
7645
7646 unsigned SubReg =
7647 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7648
7649 if (UseNewExecInstructions) {
7650 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7651 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7652 .addReg(CurReg)
7653 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7654 if (I == LoopBB.end())
7655 I = CmpxMI.getInstr()->getIterator();
7656 } else {
7657 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7658 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7659 .addReg(CurReg)
7660 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7661
7662 // Combine the comparison results with AND.
7663 if (!CondReg) { // First.
7664 CondReg = NewCondReg;
7665 } else { // If not the first, we create an AND.
7666 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7667 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7668 .addReg(CondReg)
7669 .addReg(NewCondReg)
7670 .setOperandDead(3);
7671 CondReg = AndReg;
7672 }
7673 }
7674 } // End for loop.
7675
7676 const auto *SScalarOpRC =
7677 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7678 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7679
7680 // Build scalar ScalarOp.
7681 auto Merge =
7682 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7683 unsigned Channel = 0;
7684 for (Register Piece : ReadlanePieces) {
7685 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7686 }
7687
7688 // Update ScalarOp operand to use the SGPR ScalarOp.
7689 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7690 ScalarOp->setReg(SScalarOp);
7691 else {
7692 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7693 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7694 .addReg(SScalarOp);
7695 ScalarOp->setReg(PhySGPRs[Idx]);
7696 }
7697 }
7698 }
7699
7700 // AndSaveExecOpc modifies EXEC but can't be isTerminator=1: terminators
7701 // that define virtual registers aren't supported.
7702 Register SaveExec;
7703 if (!UseNewExecInstructions) {
7704 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7705 MRI.setSimpleHint(SaveExec, CondReg);
7706
7707 // Update EXEC to matching lanes, saving original to SaveExec.
7708 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7709 .addReg(CondReg)
7710 .setOperandDead(3);
7711 }
7712
7713 // The original instruction is here; we insert the terminators after it.
7714 I = BodyBB.end();
7715
7716 if (UseNewExecInstructions) {
7717 // Compute the remaining lanes into a plain virtual register and write EXEC
7718 // from a terminator, so spill code for NewExec is placed before EXEC
7719 // changes. SIOptimizeExecMasking opportunistically folds the pair back
7720 // into S_ANDN2_WREXEC after register allocation.
7721 MRI.setSimpleHint(NewExec, PhiExec);
7722 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2Opc), NewExec)
7723 .addReg(PhiExec)
7724 .addReg(LMC.ExecReg)
7725 .setOperandDead(3);
7726 BuildMI(BodyBB, I, DL, TII.get(LMC.MovTermOpc), LMC.ExecReg)
7727 .addReg(NewExec);
7728 } else {
7729 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7730 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7731 .addReg(LMC.ExecReg)
7732 .addReg(SaveExec)
7733 .setOperandDead(3);
7734 }
7735
7736 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7737}
7738
7739// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7740// with SGPRs by iterating over all unique values across all lanes.
7741// Returns the loop basic block that now contains \p MI.
7742static MachineBasicBlock *
7746 MachineBasicBlock::iterator Begin = nullptr,
7748 ArrayRef<Register> PhySGPRs = {}) {
7749 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7750 "Physical SGPRs must be empty or match the number of scalar operands");
7752 MachineFunction &MF = *MBB.getParent();
7754 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7756 if (!Begin.isValid())
7757 Begin = &MI;
7758 if (!End.isValid()) {
7759 End = &MI;
7760 ++End;
7761 }
7762 const DebugLoc &DL = MI.getDebugLoc();
7764 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7765
7766 // Save SCC. Waterfall Loop may overwrite SCC.
7767 Register SaveSCCReg;
7768
7769 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7770 // rather than unlimited scan everywhere
7771 bool SCCNotDead =
7772 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7773 std::numeric_limits<unsigned>::max()) !=
7775 if (SCCNotDead) {
7776 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7777 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7778 .addImm(1)
7779 .addImm(0);
7780 }
7781
7782 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7783
7784 // Save the EXEC mask
7785 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7786
7787 // To insert the loop we need to split the block. Move everything after this
7788 // point to a new block, and insert a new empty block between the two.
7791 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7793 ++MBBI;
7794
7795 MF.insert(MBBI, LoopBB);
7796 MF.insert(MBBI, BodyBB);
7797 MF.insert(MBBI, RemainderBB);
7798
7799 LoopBB->addSuccessor(BodyBB);
7800 BodyBB->addSuccessor(LoopBB);
7801 BodyBB->addSuccessor(RemainderBB);
7802
7803 // Move Begin to MI to the BodyBB, and the remainder of the block to
7804 // RemainderBB.
7805 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7806 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7807 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7808
7809 MBB.addSuccessor(LoopBB);
7810
7811 // Update dominators. We know that MBB immediately dominates LoopBB, that
7812 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7813 // RemainderBB. RemainderBB immediately dominates all of the successors
7814 // transferred to it from MBB that MBB used to properly dominate.
7815 if (MDT) {
7816 MDT->addNewBlock(LoopBB, &MBB);
7817 MDT->addNewBlock(BodyBB, LoopBB);
7818 MDT->addNewBlock(RemainderBB, BodyBB);
7819 for (auto &Succ : RemainderBB->successors()) {
7820 if (MDT->properlyDominates(&MBB, Succ)) {
7821 MDT->changeImmediateDominator(Succ, RemainderBB);
7822 }
7823 }
7824 }
7825
7826 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7827 PhySGPRs);
7828
7829 MachineBasicBlock::iterator First = RemainderBB->begin();
7830 // Restore SCC
7831 if (SCCNotDead) {
7832 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7833 .addReg(SaveSCCReg)
7834 .addImm(0);
7835 }
7836
7837 // Restore the EXEC mask
7838 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7839 .addReg(SaveExec);
7840 return BodyBB;
7841}
7842
7843// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7844static std::tuple<unsigned, unsigned>
7846 MachineBasicBlock &MBB = *MI.getParent();
7847 MachineFunction &MF = *MBB.getParent();
7849
7850 // Extract the ptr from the resource descriptor.
7851 unsigned RsrcPtr =
7852 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7853 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7854
7855 // Create an empty resource descriptor
7856 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7857 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7858 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7859 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7860 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7861
7862 // Zero64 = 0
7863 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7864 .addImm(0);
7865
7866 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7867 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7868 .addImm(Lo_32(RsrcDataFormat));
7869
7870 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7871 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7872 .addImm(Hi_32(RsrcDataFormat));
7873
7874 // NewSRsrc = {Zero64, SRsrcFormat}
7875 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7876 .addReg(Zero64)
7877 .addImm(AMDGPU::sub0_sub1)
7878 .addReg(SRsrcFormatLo)
7879 .addImm(AMDGPU::sub2)
7880 .addReg(SRsrcFormatHi)
7881 .addImm(AMDGPU::sub3);
7882
7883 return std::tuple(RsrcPtr, NewSRsrc);
7884}
7885
7888 MachineDominatorTree *MDT) const {
7889 MachineFunction &MF = *MI.getMF();
7891 MachineBasicBlock *CreatedBB = nullptr;
7892
7893 // Legalize True16
7894 if (ST.useRealTrue16Insts())
7896
7897 // Legalize VOP2
7898 if (isVOP2(MI) || isVOPC(MI)) {
7900 return CreatedBB;
7901 }
7902
7903 // Legalize VOP3
7904 if (isVOP3(MI)) {
7906 return CreatedBB;
7907 }
7908
7909 // Legalize SMRD
7910 if (isSMRD(MI)) {
7912 return CreatedBB;
7913 }
7914
7915 // Legalize FLAT
7916 if (isFLAT(MI)) {
7918 return CreatedBB;
7919 }
7920
7921 // Legalize PHI
7922 // The register class of the operands must be the same type as the register
7923 // class of the output.
7924 if (MI.getOpcode() == AMDGPU::PHI) {
7925 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7926 assert(!RI.isSGPRClass(VRC));
7927
7928 // Update all the operands so they have the same type.
7929 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7930 MachineOperand &Op = MI.getOperand(I);
7931 if (!Op.isReg() || !Op.getReg().isVirtual())
7932 continue;
7933
7934 // MI is a PHI instruction.
7935 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7937
7938 // Avoid creating no-op copies with the same src and dst reg class. These
7939 // confuse some of the machine passes.
7940 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7941 }
7942 }
7943
7944 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7945 // VGPR dest type and SGPR sources, insert copies so all operands are
7946 // VGPRs. This seems to help operand folding / the register coalescer.
7947 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7948 MachineBasicBlock *MBB = MI.getParent();
7949 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7950 if (RI.hasVGPRs(DstRC)) {
7951 // Update all the operands so they are VGPR register classes. These may
7952 // not be the same register class because REG_SEQUENCE supports mixing
7953 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7954 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7955 MachineOperand &Op = MI.getOperand(I);
7956 if (!Op.isReg() || !Op.getReg().isVirtual())
7957 continue;
7958
7959 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7960 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7961 if (VRC == OpRC)
7962 continue;
7963
7964 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7965 }
7966 }
7967
7968 return CreatedBB;
7969 }
7970
7971 // Legalize INSERT_SUBREG
7972 // src0 must have the same register class as dst
7973 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7974 Register Dst = MI.getOperand(0).getReg();
7975 Register Src0 = MI.getOperand(1).getReg();
7976 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7977 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7978 if (DstRC != Src0RC) {
7979 MachineBasicBlock *MBB = MI.getParent();
7980 MachineOperand &Op = MI.getOperand(1);
7981 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7982 }
7983 return CreatedBB;
7984 }
7985
7986 // Legalize SI_INIT_M0
7987 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7988 MachineOperand &Src = MI.getOperand(0);
7989 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7990 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7991 return CreatedBB;
7992 }
7993
7994 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
7995 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7996 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7997 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7998 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7999 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
8000 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
8001 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
8002 MachineOperand &Src = MI.getOperand(1);
8003 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
8004 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
8005 return CreatedBB;
8006 }
8007
8008 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
8009 //
8010 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
8011 // scratch memory access. In both cases, the legalization never involves
8012 // conversion to the addr64 form.
8014 (isMUBUF(MI) || isMTBUF(MI)))) {
8015 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
8016 ? AMDGPU::OpName::rsrc
8017 : AMDGPU::OpName::srsrc;
8018 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
8019 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
8020 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
8021
8022 AMDGPU::OpName SampOpName =
8023 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
8024 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
8025 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
8026 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
8027
8028 return CreatedBB;
8029 }
8030
8031 // Legalize SI_CALL
8032 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
8033 MachineOperand *Dest = &MI.getOperand(0);
8034 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
8035 createWaterFallForSiCall(&MI, MDT, {Dest});
8036 }
8037 }
8038
8039 // Legalize s_sleep_var.
8040 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
8041 const DebugLoc &DL = MI.getDebugLoc();
8042 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8043 int Src0Idx =
8044 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
8045 MachineOperand &Src0 = MI.getOperand(Src0Idx);
8046 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
8047 .add(Src0);
8048 Src0.ChangeToRegister(Reg, false);
8049 return nullptr;
8050 }
8051
8052 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
8053 // operands are scalar.
8054 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
8055 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
8056 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
8057 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
8058 for (MachineOperand &Src : MI.explicit_operands()) {
8059 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
8060 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
8061 }
8062 return CreatedBB;
8063 }
8064
8065 // Legalize MUBUF instructions.
8066 bool isSoffsetLegal = true;
8067 int SoffsetIdx =
8068 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
8069 if (SoffsetIdx != -1) {
8070 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
8071 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
8072 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
8073 isSoffsetLegal = false;
8074 }
8075 }
8076
8077 bool isRsrcLegal = true;
8078 int RsrcIdx =
8079 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
8080 if (RsrcIdx != -1) {
8081 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
8082 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
8083 isRsrcLegal = false;
8084 }
8085
8086 // The operands are legal.
8087 if (isRsrcLegal && isSoffsetLegal)
8088 return CreatedBB;
8089
8090 if (!isRsrcLegal) {
8091 // Legalize a VGPR Rsrc
8092 //
8093 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
8094 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
8095 // a zero-value SRsrc.
8096 //
8097 // If the instruction is _OFFSET (both idxen and offen disabled), and we
8098 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
8099 // above.
8100 //
8101 // Otherwise we are on non-ADDR64 hardware, and/or we have
8102 // idxen/offen/bothen and we fall back to a waterfall loop.
8103
8104 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
8105 MachineBasicBlock &MBB = *MI.getParent();
8106
8107 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
8108 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
8109 // This is already an ADDR64 instruction so we need to add the pointer
8110 // extracted from the resource descriptor to the current value of VAddr.
8111 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8112 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8113 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8114
8115 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
8116 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
8117 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
8118
8119 unsigned RsrcPtr, NewSRsrc;
8120 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
8121
8122 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
8123 const DebugLoc &DL = MI.getDebugLoc();
8124 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
8125 .addDef(CondReg0)
8126 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8127 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
8128 .addImm(0);
8129
8130 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
8131 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
8132 .addDef(CondReg1, RegState::Dead)
8133 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8134 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
8135 .addReg(CondReg0)
8136 .addImm(0);
8137
8138 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8139 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
8140 .addReg(NewVAddrLo)
8141 .addImm(AMDGPU::sub0)
8142 .addReg(NewVAddrHi)
8143 .addImm(AMDGPU::sub1);
8144
8145 VAddr->setReg(NewVAddr);
8146 Rsrc->setReg(NewSRsrc);
8147 } else if (!VAddr && ST.hasAddr64()) {
8148 // This instructions is the _OFFSET variant, so we need to convert it to
8149 // ADDR64.
8150 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
8151 "FIXME: Need to emit flat atomics here");
8152
8153 unsigned RsrcPtr, NewSRsrc;
8154 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
8155
8156 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8157 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
8158 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
8159 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8160 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
8161
8162 // Atomics with return have an additional tied operand and are
8163 // missing some of the special bits.
8164 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
8165 MachineInstr *Addr64;
8166
8167 if (!VDataIn) {
8168 // Regular buffer load / store.
8170 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
8171 .add(*VData)
8172 .addReg(NewVAddr)
8173 .addReg(NewSRsrc)
8174 .add(*SOffset)
8175 .add(*Offset);
8176
8177 if (const MachineOperand *CPol =
8178 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
8179 MIB.addImm(CPol->getImm());
8180 }
8181
8182 if (const MachineOperand *TFE =
8183 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
8184 MIB.addImm(TFE->getImm());
8185 }
8186
8187 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
8188
8189 MIB.cloneMemRefs(MI);
8190 Addr64 = MIB;
8191 } else {
8192 // Atomics with return.
8193 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
8194 .add(*VData)
8195 .add(*VDataIn)
8196 .addReg(NewVAddr)
8197 .addReg(NewSRsrc)
8198 .add(*SOffset)
8199 .add(*Offset)
8200 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
8201 .cloneMemRefs(MI);
8202 }
8203
8204 MI.removeFromParent();
8205
8206 // NewVaddr = {NewVaddrHi, NewVaddrLo}
8207 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
8208 NewVAddr)
8209 .addReg(RsrcPtr, {}, AMDGPU::sub0)
8210 .addImm(AMDGPU::sub0)
8211 .addReg(RsrcPtr, {}, AMDGPU::sub1)
8212 .addImm(AMDGPU::sub1);
8213 } else {
8214 // Legalize a VGPR Rsrc and soffset together.
8215 if (!isSoffsetLegal) {
8216 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8217 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
8218 return CreatedBB;
8219 }
8220 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
8221 return CreatedBB;
8222 }
8223 }
8224
8225 // Legalize a VGPR soffset.
8226 if (!isSoffsetLegal) {
8227 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
8228 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
8229 return CreatedBB;
8230 }
8231 return CreatedBB;
8232}
8233
8235 if (InSet.insert(MI).second)
8236 InstrList.push_back(MI);
8237 // Add MBUF instructiosn to deferred list.
8238 int RsrcIdx =
8239 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
8240 if (RsrcIdx != -1) {
8241 DeferredList.insert(MI);
8242 }
8243}
8244
8246 return DeferredList.contains(MI);
8247}
8248
8249// Legalize size mismatches between 16bit and 32bit registers in v2s copy
8250// lowering (change sgpr to vgpr).
8251// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
8252// size. Need to legalize the size of the operands during the vgpr lowering
8253// chain. This can be removed after we have sgpr16 in place
8255 MachineRegisterInfo &MRI) const {
8256 if (!ST.useRealTrue16Insts())
8257 return;
8258
8259 unsigned Opcode = MI.getOpcode();
8260 MachineBasicBlock *MBB = MI.getParent();
8261 // Legalize operands and check for size mismatch
8262 if (OpIdx >= MI.getNumExplicitOperands() ||
8263 OpIdx >= get(Opcode).getNumOperands() ||
8264 get(Opcode).operands()[OpIdx].RegClass == -1)
8265 return;
8266
8267 MachineOperand &Op = MI.getOperand(OpIdx);
8268 if (!Op.isReg() || !Op.getReg().isVirtual() || Op.isDef())
8269 return;
8270
8271 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
8272 if (!RI.isVGPRClass(CurrRC))
8273 return;
8274
8275 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
8276 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
8277 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8278 // Default to the lo16 only if the subregister is not specified.
8279 if (Op.getSubReg() == AMDGPU::NoSubRegister)
8280 Op.setSubReg(AMDGPU::lo16);
8281 return;
8282 }
8283
8284 const TargetRegisterClass *CurrSRC =
8285 RI.getSubRegisterClass(CurrRC, Op.getSubReg());
8286 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8287 const DebugLoc &DL = MI.getDebugLoc();
8288 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8289 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8290 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
8291 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
8292 .addReg(Op.getReg(), {}, Op.getSubReg())
8293 .addImm(AMDGPU::lo16)
8294 .addReg(Undef)
8295 .addImm(AMDGPU::hi16);
8296 Op.setReg(NewDstReg);
8297 Op.setSubReg(AMDGPU::NoSubRegister);
8298 }
8299}
8301 MachineRegisterInfo &MRI) const {
8302 for (unsigned OpIdx = 0; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
8304}
8305
8309 ArrayRef<Register> PhySGPRs) const {
8310 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8311 "This only handle waterfall for SI_CALL_ISEL");
8312 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
8313 // following copies, we also need to move copies from and to physical
8314 // registers into the loop block.
8315 // Also move the copies to physical registers into the loop block
8316 MachineBasicBlock &MBB = *MI->getParent();
8318 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8319 --Start;
8321 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8322 ++End;
8323
8324 // Also include following copies of the return value
8325 ++End;
8326 while (End != MBB.end() && End->isCopy() &&
8327 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8328 ++End;
8329
8330 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
8331}
8332
8334 MachineDominatorTree *MDT) const {
8336 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
8337 while (!Worklist.empty()) {
8338 MachineInstr &Inst = *Worklist.top();
8339 Worklist.erase_top();
8340 // Skip MachineInstr in the deferred list.
8341 if (Worklist.isDeferred(&Inst))
8342 continue;
8343 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8344 }
8345
8346 // Deferred list of instructions will be processed once
8347 // all the MachineInstr in the worklist are done.
8348 for (MachineInstr *Inst : Worklist.getDeferredList()) {
8349 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8350 assert(Worklist.empty() &&
8351 "Deferred MachineInstr are not supposed to re-populate worklist");
8352 }
8353
8354 for (auto &Entry : WaterFalls) {
8355 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8356 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
8357 Entry.second.SGPRs);
8358 }
8359
8360 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8361 if (Entry.second)
8362 Entry.first->eraseFromParent();
8363}
8365 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
8366 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
8367 // hope for the best.
8368 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
8369 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
8370 if (SubRegIndices.size() <= 1) {
8371 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8372 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8373 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8374 .add(Inst.getOperand(1));
8375 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
8376 DstReg)
8377 .addReg(NewDst);
8378 } else {
8380 for (int16_t Indice : SubRegIndices) {
8381 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8382 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8383 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8384 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
8385
8386 DstRegs.push_back(NewDst);
8387 }
8389 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8390 get(AMDGPU::REG_SEQUENCE), DstReg);
8391 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
8392 MIB.addReg(DstRegs[i]);
8393 MIB.addImm(RI.getSubRegFromChannel(i));
8394 }
8395 }
8396}
8397
8399 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
8402 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8403 if (DstReg == AMDGPU::M0) {
8405 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8406 return;
8407 }
8408 Register SrcReg = Inst.getOperand(1).getReg();
8409 // Only search current block since phyreg's def & use cannot cross
8410 // blocks when MF.NoPhi = false.
8411 for (MachineInstr &MI :
8413 Inst.getParent()->end())) {
8414 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
8415 // and record the operand for later waterfall loop generation.
8416 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
8417 MachineInstr *UseMI = &MI;
8418 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
8419 if (UseMI->getOperand(i).isReg() &&
8420 UseMI->getOperand(i).getReg() == DstReg) {
8421 MachineOperand *MO = &UseMI->getOperand(i);
8422 MO->setReg(SrcReg);
8423 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
8424 V2SCopyInfo.MOs.push_back(MO);
8425 V2SCopyInfo.SGPRs.push_back(DstReg);
8426 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8427 }
8428 }
8429 } else if (MI.getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8430 MI.getOperand(0).isReg() &&
8431 MI.getOperand(0).getReg() == DstReg) {
8433 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8434 } else if (MI.readsRegister(DstReg, &RI)) {
8435 // COPY cannot be erased if other type of inst uses it.
8436 V2SPhyCopiesToErase[&Inst] = false;
8437 }
8438 if (MI.modifiesRegister(DstReg, &RI))
8439 break;
8440 }
8441}
8442
8444 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
8446 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8447
8449 if (!MBB)
8450 return;
8451 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
8452 unsigned Opcode = Inst.getOpcode();
8453 unsigned NewOpcode = getVALUOp(Inst);
8454 const DebugLoc &DL = Inst.getDebugLoc();
8455
8456 // Handle some special cases
8457 switch (Opcode) {
8458 default:
8459 break;
8460 case AMDGPU::S_ADD_I32:
8461 case AMDGPU::S_SUB_I32: {
8462 // FIXME: The u32 versions currently selected use the carry.
8463 bool Changed;
8464 MachineBasicBlock *CreatedBBTmp = nullptr;
8465 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8466 if (Changed)
8467 return;
8468
8469 // Default handling
8470 break;
8471 }
8472
8473 case AMDGPU::S_MUL_U64:
8474 if (ST.useVMulU64Inst()) {
8475 NewOpcode = AMDGPU::V_MUL_U64_e64;
8476 break;
8477 }
8478 // Split s_mul_u64 in 32-bit vector multiplications.
8479 splitScalarSMulU64(Worklist, Inst, MDT);
8480 Inst.eraseFromParent();
8481 return;
8482
8483 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8484 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8485 // This is a special case of s_mul_u64 where all the operands are either
8486 // zero extended or sign extended.
8487 splitScalarSMulPseudo(Worklist, Inst, MDT);
8488 Inst.eraseFromParent();
8489 return;
8490
8491 case AMDGPU::S_AND_B64:
8492 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8493 Inst.eraseFromParent();
8494 return;
8495
8496 case AMDGPU::S_OR_B64:
8497 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8498 Inst.eraseFromParent();
8499 return;
8500
8501 case AMDGPU::S_XOR_B64:
8502 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8503 Inst.eraseFromParent();
8504 return;
8505
8506 case AMDGPU::S_NAND_B64:
8507 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8508 Inst.eraseFromParent();
8509 return;
8510
8511 case AMDGPU::S_NOR_B64:
8512 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8513 Inst.eraseFromParent();
8514 return;
8515
8516 case AMDGPU::S_XNOR_B64:
8517 if (ST.hasDLInsts())
8518 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8519 else
8520 splitScalar64BitXnor(Worklist, Inst, MDT);
8521 Inst.eraseFromParent();
8522 return;
8523
8524 case AMDGPU::S_ANDN2_B64:
8525 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8526 Inst.eraseFromParent();
8527 return;
8528
8529 case AMDGPU::S_ORN2_B64:
8530 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8531 Inst.eraseFromParent();
8532 return;
8533
8534 case AMDGPU::S_BREV_B64:
8535 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8536 Inst.eraseFromParent();
8537 return;
8538
8539 case AMDGPU::S_NOT_B64:
8540 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8541 Inst.eraseFromParent();
8542 return;
8543
8544 case AMDGPU::S_BCNT1_I32_B64:
8545 splitScalar64BitBCNT(Worklist, Inst);
8546 Inst.eraseFromParent();
8547 return;
8548
8549 case AMDGPU::S_BFE_I64:
8550 splitScalar64BitBFE(Worklist, Inst);
8551 Inst.eraseFromParent();
8552 return;
8553
8554 case AMDGPU::S_FLBIT_I32_B64:
8555 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8556 Inst.eraseFromParent();
8557 return;
8558 case AMDGPU::S_FF1_I32_B64:
8559 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8560 Inst.eraseFromParent();
8561 return;
8562
8563 case AMDGPU::S_LSHL_B32:
8564 if (ST.hasOnlyRevVALUShifts()) {
8565 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8566 swapOperands(Inst);
8567 }
8568 break;
8569 case AMDGPU::S_ASHR_I32:
8570 if (ST.hasOnlyRevVALUShifts()) {
8571 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8572 swapOperands(Inst);
8573 }
8574 break;
8575 case AMDGPU::S_LSHR_B32:
8576 if (ST.hasOnlyRevVALUShifts()) {
8577 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8578 swapOperands(Inst);
8579 }
8580 break;
8581 case AMDGPU::S_LSHL_B64:
8582 if (ST.hasOnlyRevVALUShifts()) {
8583 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8584 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8585 : AMDGPU::V_LSHLREV_B64_e64;
8586 swapOperands(Inst);
8587 }
8588 break;
8589 case AMDGPU::S_ASHR_I64:
8590 if (ST.hasOnlyRevVALUShifts()) {
8591 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8592 swapOperands(Inst);
8593 }
8594 break;
8595 case AMDGPU::S_LSHR_B64:
8596 if (ST.hasOnlyRevVALUShifts()) {
8597 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8598 swapOperands(Inst);
8599 }
8600 break;
8601
8602 case AMDGPU::S_ABS_I32:
8603 lowerScalarAbs(Worklist, Inst);
8604 Inst.eraseFromParent();
8605 return;
8606
8607 case AMDGPU::S_ABSDIFF_I32:
8608 lowerScalarAbsDiff(Worklist, Inst);
8609 Inst.eraseFromParent();
8610 return;
8611
8612 case AMDGPU::S_CBRANCH_SCC0:
8613 case AMDGPU::S_CBRANCH_SCC1: {
8614 // Clear unused bits of vcc
8615 Register CondReg = Inst.getOperand(1).getReg();
8616 bool IsSCC = CondReg == AMDGPU::SCC;
8618 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8619 .addReg(LMC.ExecReg)
8620 .addReg(IsSCC ? LMC.VccReg : CondReg)
8621 .setOperandDead(3); // implicit-def $scc
8622 Inst.removeOperand(1);
8623 } break;
8624
8625 case AMDGPU::S_BFE_U64:
8626 case AMDGPU::S_BFM_B64:
8627 llvm_unreachable("Moving this op to VALU not implemented");
8628
8629 case AMDGPU::S_PACK_LL_B32_B16:
8630 case AMDGPU::S_PACK_LH_B32_B16:
8631 case AMDGPU::S_PACK_HL_B32_B16:
8632 case AMDGPU::S_PACK_HH_B32_B16:
8633 movePackToVALU(Worklist, MRI, Inst);
8634 Inst.eraseFromParent();
8635 return;
8636
8637 case AMDGPU::S_XNOR_B32:
8638 lowerScalarXnor(Worklist, Inst);
8639 Inst.eraseFromParent();
8640 return;
8641
8642 case AMDGPU::S_NAND_B32:
8643 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8644 Inst.eraseFromParent();
8645 return;
8646
8647 case AMDGPU::S_NOR_B32:
8648 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8649 Inst.eraseFromParent();
8650 return;
8651
8652 case AMDGPU::S_ANDN2_B32:
8653 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8654 Inst.eraseFromParent();
8655 return;
8656
8657 case AMDGPU::S_ORN2_B32:
8658 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8659 Inst.eraseFromParent();
8660 return;
8661
8662 // TODO: remove as soon as everything is ready
8663 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8664 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8665 // can only be selected from the uniform SDNode.
8666 case AMDGPU::S_ADD_CO_PSEUDO:
8667 case AMDGPU::S_SUB_CO_PSEUDO: {
8668 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8669 ? AMDGPU::V_ADDC_U32_e64
8670 : AMDGPU::V_SUBB_U32_e64;
8671 const auto *CarryRC = RI.getWaveMaskRegClass();
8672
8673 Register CarryInReg = Inst.getOperand(4).getReg();
8674 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8675 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8676 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8677 .addReg(CarryInReg);
8678 }
8679
8680 Register CarryOutReg = Inst.getOperand(1).getReg();
8681
8682 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8683 MRI.getRegClass(Inst.getOperand(0).getReg())));
8684 MachineInstr *CarryOp =
8685 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8686 .addReg(CarryOutReg, RegState::Define)
8687 .add(Inst.getOperand(2))
8688 .add(Inst.getOperand(3))
8689 .addReg(CarryInReg)
8690 .addImm(0);
8691 legalizeOperands(*CarryOp);
8692 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8693 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8694 Inst.eraseFromParent();
8695 }
8696 return;
8697 case AMDGPU::S_UADDO_PSEUDO:
8698 case AMDGPU::S_USUBO_PSEUDO: {
8699 MachineOperand &Dest0 = Inst.getOperand(0);
8700 MachineOperand &Dest1 = Inst.getOperand(1);
8701 MachineOperand &Src0 = Inst.getOperand(2);
8702 MachineOperand &Src1 = Inst.getOperand(3);
8703
8704 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8705 ? AMDGPU::V_ADD_CO_U32_e64
8706 : AMDGPU::V_SUB_CO_U32_e64;
8707 const TargetRegisterClass *NewRC =
8708 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8709 Register DestReg = MRI.createVirtualRegister(NewRC);
8710 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8711 .addReg(Dest1.getReg(), RegState::Define)
8712 .add(Src0)
8713 .add(Src1)
8714 .addImm(0); // clamp bit
8715
8716 legalizeOperands(*NewInstr, MDT);
8717 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8718 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8719 Inst.eraseFromParent();
8720 }
8721 return;
8722 case AMDGPU::S_LSHL1_ADD_U32:
8723 case AMDGPU::S_LSHL2_ADD_U32:
8724 case AMDGPU::S_LSHL3_ADD_U32:
8725 case AMDGPU::S_LSHL4_ADD_U32: {
8726 MachineOperand &Dest = Inst.getOperand(0);
8727 MachineOperand &Src0 = Inst.getOperand(1);
8728 MachineOperand &Src1 = Inst.getOperand(2);
8729 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8730 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8731 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8732 : 4);
8733
8734 const TargetRegisterClass *NewRC =
8735 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8736 Register DestReg = MRI.createVirtualRegister(NewRC);
8737 MachineInstr *NewInstr =
8738 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8739 .add(Src0)
8740 .addImm(ShiftAmt)
8741 .add(Src1);
8742
8743 legalizeOperands(*NewInstr, MDT);
8744 MRI.replaceRegWith(Dest.getReg(), DestReg);
8745 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8746 Inst.eraseFromParent();
8747 }
8748 return;
8749 case AMDGPU::S_CSELECT_B32:
8750 case AMDGPU::S_CSELECT_B64:
8751 lowerSelect(Worklist, Inst, MDT);
8752 Inst.eraseFromParent();
8753 return;
8754 case AMDGPU::S_CMP_EQ_I32:
8755 case AMDGPU::S_CMP_LG_I32:
8756 case AMDGPU::S_CMP_GT_I32:
8757 case AMDGPU::S_CMP_GE_I32:
8758 case AMDGPU::S_CMP_LT_I32:
8759 case AMDGPU::S_CMP_LE_I32:
8760 case AMDGPU::S_CMP_EQ_U32:
8761 case AMDGPU::S_CMP_LG_U32:
8762 case AMDGPU::S_CMP_GT_U32:
8763 case AMDGPU::S_CMP_GE_U32:
8764 case AMDGPU::S_CMP_LT_U32:
8765 case AMDGPU::S_CMP_LE_U32:
8766 case AMDGPU::S_CMP_EQ_U64:
8767 case AMDGPU::S_CMP_LG_U64:
8768 case AMDGPU::S_CMP_LT_F32:
8769 case AMDGPU::S_CMP_EQ_F32:
8770 case AMDGPU::S_CMP_LE_F32:
8771 case AMDGPU::S_CMP_GT_F32:
8772 case AMDGPU::S_CMP_LG_F32:
8773 case AMDGPU::S_CMP_GE_F32:
8774 case AMDGPU::S_CMP_O_F32:
8775 case AMDGPU::S_CMP_U_F32:
8776 case AMDGPU::S_CMP_NGE_F32:
8777 case AMDGPU::S_CMP_NLG_F32:
8778 case AMDGPU::S_CMP_NGT_F32:
8779 case AMDGPU::S_CMP_NLE_F32:
8780 case AMDGPU::S_CMP_NEQ_F32:
8781 case AMDGPU::S_CMP_NLT_F32: {
8782 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8783 auto NewInstr =
8784 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8785 .setMIFlags(Inst.getFlags());
8786 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8787 0) {
8788 NewInstr
8789 .addImm(0) // src0_modifiers
8790 .add(Inst.getOperand(0)) // src0
8791 .addImm(0) // src1_modifiers
8792 .add(Inst.getOperand(1)) // src1
8793 .addImm(0); // clamp
8794 } else {
8795 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8796 }
8797 legalizeOperands(*NewInstr, MDT);
8798 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8799 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8800 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8801 Inst.eraseFromParent();
8802 return;
8803 }
8804 case AMDGPU::S_CMP_LT_F16:
8805 case AMDGPU::S_CMP_EQ_F16:
8806 case AMDGPU::S_CMP_LE_F16:
8807 case AMDGPU::S_CMP_GT_F16:
8808 case AMDGPU::S_CMP_LG_F16:
8809 case AMDGPU::S_CMP_GE_F16:
8810 case AMDGPU::S_CMP_O_F16:
8811 case AMDGPU::S_CMP_U_F16:
8812 case AMDGPU::S_CMP_NGE_F16:
8813 case AMDGPU::S_CMP_NLG_F16:
8814 case AMDGPU::S_CMP_NGT_F16:
8815 case AMDGPU::S_CMP_NLE_F16:
8816 case AMDGPU::S_CMP_NEQ_F16:
8817 case AMDGPU::S_CMP_NLT_F16: {
8818 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8819 auto NewInstr =
8820 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8821 .setMIFlags(Inst.getFlags());
8822 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8823 NewInstr
8824 .addImm(0) // src0_modifiers
8825 .add(Inst.getOperand(0)) // src0
8826 .addImm(0) // src1_modifiers
8827 .add(Inst.getOperand(1)) // src1
8828 .addImm(0); // clamp
8829 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8830 NewInstr.addImm(0); // op_sel0
8831 } else {
8832 NewInstr
8833 .add(Inst.getOperand(0))
8834 .add(Inst.getOperand(1));
8835 }
8836 legalizeOperands(*NewInstr, MDT);
8837 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8838 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8839 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8840 Inst.eraseFromParent();
8841 return;
8842 }
8843 case AMDGPU::S_CVT_HI_F32_F16: {
8844 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8845 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8846 if (ST.useRealTrue16Insts()) {
8847 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8848 .add(Inst.getOperand(1));
8849 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8850 .addImm(0) // src0_modifiers
8851 .addReg(TmpReg, {}, AMDGPU::hi16)
8852 .addImm(0) // clamp
8853 .addImm(0) // omod
8854 .addImm(0); // op_sel0
8855 } else {
8856 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8857 .addImm(16)
8858 .add(Inst.getOperand(1));
8859 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8860 .addImm(0) // src0_modifiers
8861 .addReg(TmpReg)
8862 .addImm(0) // clamp
8863 .addImm(0); // omod
8864 }
8865
8866 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8867 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8868 Inst.eraseFromParent();
8869 return;
8870 }
8871 case AMDGPU::S_MINIMUM_F32:
8872 case AMDGPU::S_MAXIMUM_F32: {
8873 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8874 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8875 .addImm(0) // src0_modifiers
8876 .add(Inst.getOperand(1))
8877 .addImm(0) // src1_modifiers
8878 .add(Inst.getOperand(2))
8879 .addImm(0) // clamp
8880 .addImm(0); // omod
8881 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8882
8883 legalizeOperands(*NewInstr, MDT);
8884 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8885 Inst.eraseFromParent();
8886 return;
8887 }
8888 case AMDGPU::S_MINIMUM_F16:
8889 case AMDGPU::S_MAXIMUM_F16: {
8890 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8891 ? &AMDGPU::VGPR_16RegClass
8892 : &AMDGPU::VGPR_32RegClass);
8893 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8894 .addImm(0) // src0_modifiers
8895 .add(Inst.getOperand(1))
8896 .addImm(0) // src1_modifiers
8897 .add(Inst.getOperand(2))
8898 .addImm(0) // clamp
8899 .addImm(0) // omod
8900 .addImm(0); // opsel0
8901 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8902 legalizeOperands(*NewInstr, MDT);
8903 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8904 Inst.eraseFromParent();
8905 return;
8906 }
8907 case AMDGPU::V_S_EXP_F16_e64:
8908 case AMDGPU::V_S_LOG_F16_e64:
8909 case AMDGPU::V_S_RCP_F16_e64:
8910 case AMDGPU::V_S_RSQ_F16_e64:
8911 case AMDGPU::V_S_SQRT_F16_e64: {
8912 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8913 ? &AMDGPU::VGPR_16RegClass
8914 : &AMDGPU::VGPR_32RegClass);
8915 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8916 .add(Inst.getOperand(1)) // src0_modifiers
8917 .add(Inst.getOperand(2))
8918 .add(Inst.getOperand(3)) // clamp
8919 .add(Inst.getOperand(4)) // omod
8920 .setMIFlags(Inst.getFlags());
8921 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8922 NewInstr.addImm(0); // opsel0
8923 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8924 legalizeOperands(*NewInstr, MDT);
8925 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8926 Inst.eraseFromParent();
8927 return;
8928 }
8929 }
8930
8931 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8932 // We cannot move this instruction to the VALU, so we should try to
8933 // legalize its operands instead.
8934 legalizeOperands(Inst, MDT);
8935 return;
8936 }
8937 // Handle converting generic instructions like COPY-to-SGPR into
8938 // COPY-to-VGPR.
8939 if (NewOpcode == Opcode) {
8940 Register DstReg = Inst.getOperand(0).getReg();
8941 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8942
8943 if (Inst.isCopy() && DstReg.isPhysical() &&
8944 Inst.getOperand(1).getReg().isVirtual()) {
8945 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8946 V2SPhyCopiesToErase);
8947 return;
8948 }
8949
8950 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8951 Register NewDstReg = Inst.getOperand(1).getReg();
8952 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8953 if (const TargetRegisterClass *CommonRC =
8954 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8955 // Instead of creating a copy where src and dst are the same register
8956 // class, we just replace all uses of dst with src. These kinds of
8957 // copies interfere with the heuristics MachineSink uses to decide
8958 // whether or not to split a critical edge. Since the pass assumes
8959 // that copies will end up as machine instructions and not be
8960 // eliminated.
8961 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8962 unsigned SrcSubReg = Inst.getOperand(1).getSubReg();
8963 bool IsUndef = Inst.getOperand(1).isUndef();
8964 for (MachineOperand &UseMO :
8965 make_early_inc_range(MRI.use_operands(DstReg))) {
8966 UseMO.setSubReg(
8967 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8968 UseMO.setReg(NewDstReg);
8969 if (IsUndef)
8970 UseMO.setIsUndef();
8971 }
8972
8973 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8974 llvm_unreachable("failed to constrain register");
8975
8976 Inst.eraseFromParent();
8977
8978 for (MachineOperand &UseMO :
8979 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8980 MachineInstr &UseMI = *UseMO.getParent();
8981
8982 // Legalize t16 operands since replaceReg is called after
8983 // addUsersToVALU.
8985
8986 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
8987 if (const TargetRegisterClass *OpRC =
8988 getRegClass(UseMI.getDesc(), OpIdx))
8989 MRI.constrainRegClass(NewDstReg, OpRC);
8990 }
8991
8992 return;
8993 }
8994 }
8995
8996 // If this is a v2s copy between 16bit and 32bit reg,
8997 // replace vgpr copy to reg_sequence/extract_subreg
8998 // This can be remove after we have sgpr16 in place
8999 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
9000 Inst.getOperand(1).getReg().isVirtual() &&
9001 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
9002 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
9003 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
9004 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9005 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
9006 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
9007 get(AMDGPU::IMPLICIT_DEF), Undef);
9008 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
9009 get(AMDGPU::REG_SEQUENCE), NewDstReg)
9010 .addReg(Inst.getOperand(1).getReg())
9011 .addImm(AMDGPU::lo16)
9012 .addReg(Undef)
9013 .addImm(AMDGPU::hi16);
9014 Inst.eraseFromParent();
9015 MRI.replaceRegWith(DstReg, NewDstReg);
9016 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9017 return;
9018 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
9019 AMDGPU::lo16)) {
9020 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
9021 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9022 MRI.replaceRegWith(DstReg, NewDstReg);
9023 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9024 return;
9025 }
9026 }
9027
9028 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
9029 MRI.replaceRegWith(DstReg, NewDstReg);
9030 legalizeOperands(Inst, MDT);
9031 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9032 return;
9033 }
9034
9035 // Use the new VALU Opcode.
9036 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
9037 .setMIFlags(Inst.getFlags());
9038 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
9039 // Intersperse VOP3 modifiers among the SALU operands.
9040 NewInstr->addOperand(Inst.getOperand(0));
9041 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9042 AMDGPU::OpName::src0_modifiers) >= 0)
9043 NewInstr.addImm(0);
9044 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
9045 const MachineOperand &Src = Inst.getOperand(1);
9046 NewInstr->addOperand(Src);
9047 }
9048
9049 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
9050 // We are converting these to a BFE, so we need to add the missing
9051 // operands for the size and offset.
9052 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
9053 NewInstr.addImm(0);
9054 NewInstr.addImm(Size);
9055 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
9056 // The VALU version adds the second operand to the result, so insert an
9057 // extra 0 operand.
9058 NewInstr.addImm(0);
9059 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
9060 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
9061 // If we need to move this to VGPRs, we need to unpack the second
9062 // operand back into the 2 separate ones for bit offset and width.
9063 assert(OffsetWidthOp.isImm() &&
9064 "Scalar BFE is only implemented for constant width and offset");
9065 uint32_t Imm = OffsetWidthOp.getImm();
9066
9067 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9068 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9069 NewInstr.addImm(Offset);
9070 NewInstr.addImm(BitWidth);
9071 } else {
9072 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9073 AMDGPU::OpName::src1_modifiers) >= 0)
9074 NewInstr.addImm(0);
9075 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
9076 NewInstr->addOperand(Inst.getOperand(2));
9077 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9078 AMDGPU::OpName::src2_modifiers) >= 0)
9079 NewInstr.addImm(0);
9080 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
9081 NewInstr->addOperand(Inst.getOperand(3));
9082 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
9083 NewInstr.addImm(0);
9084 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
9085 NewInstr.addImm(0);
9086 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
9087 NewInstr.addImm(0);
9088 }
9089 } else {
9090 // Just copy the SALU operands.
9091 for (const MachineOperand &Op : Inst.explicit_operands())
9092 NewInstr->addOperand(Op);
9093 }
9094
9095 // Remove any references to SCC. Vector instructions can't read from it, and
9096 // We're just about to add the implicit use / defs of VCC, and we don't want
9097 // both.
9098 bool DeadSCCDef = false;
9099 for (MachineOperand &Op : Inst.implicit_operands()) {
9100 if (Op.getReg() == AMDGPU::SCC) {
9101 // Only propagate through live-def of SCC.
9102 if (Op.isDef()) {
9103 if (Op.isDead())
9104 DeadSCCDef = true;
9105 else
9106 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
9107 continue;
9108 }
9109
9110 addSCCDefsToVALUWorklist(NewInstr, Worklist);
9111 }
9112 }
9113 Inst.eraseFromParent();
9114 Register NewDstReg;
9115 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
9116 Register DstReg = NewInstr->getOperand(0).getReg();
9117 assert(DstReg.isVirtual());
9118 // Update the destination register class.
9119 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
9120 assert(NewDstRC);
9121 NewDstReg = MRI.createVirtualRegister(NewDstRC);
9122 MRI.replaceRegWith(DstReg, NewDstReg);
9123 }
9124 fixImplicitOperands(*NewInstr);
9125
9126 if (DeadSCCDef) {
9127 // A scalar op with a dead SCC def lowers to a VALU op whose VCC def will
9128 // also be dead.
9129 if (MachineOperand *VCCDef =
9130 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
9131 VCCDef->setIsDead();
9132 }
9133
9134 // Legalize the operands
9135 legalizeOperands(*NewInstr, MDT);
9136 if (NewDstReg)
9137 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
9138}
9139
9140// Add/sub require special handling to deal with carry outs.
9141std::pair<bool, MachineBasicBlock *>
9142SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
9143 MachineDominatorTree *MDT) const {
9144 if (ST.hasAddNoCarryInsts()) {
9145 // Assume there is no user of scc since we don't select this in that case.
9146 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
9147 // is used.
9148
9149 MachineBasicBlock &MBB = *Inst.getParent();
9150 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9151
9152 Register OldDstReg = Inst.getOperand(0).getReg();
9153 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9154
9155 unsigned Opc = Inst.getOpcode();
9156 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
9157
9158 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
9159 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9160
9161 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
9162 Inst.removeOperand(3);
9163
9164 Inst.setDesc(get(NewOpc));
9165 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
9166 Inst.addImplicitDefUseOperands(*MBB.getParent());
9167 MRI.replaceRegWith(OldDstReg, ResultReg);
9168 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
9169
9170 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9171 return std::pair(true, NewBB);
9172 }
9173
9174 return std::pair(false, nullptr);
9175}
9176
9177void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
9178 MachineDominatorTree *MDT) const {
9179
9180 MachineBasicBlock &MBB = *Inst.getParent();
9181 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9182 MachineBasicBlock::iterator MII = Inst;
9183 const DebugLoc &DL = Inst.getDebugLoc();
9184
9185 MachineOperand &Dest = Inst.getOperand(0);
9186 MachineOperand &Src0 = Inst.getOperand(1);
9187 MachineOperand &Src1 = Inst.getOperand(2);
9188 MachineOperand &Cond = Inst.getOperand(3);
9189
9190 Register CondReg = Cond.getReg();
9191 bool IsSCC = (CondReg == AMDGPU::SCC);
9192
9193 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
9194 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
9195 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
9196 // output directly into the V_CNDMASK.
9197 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
9198 (Src1.getImm() == 0)) {
9199 for (MachineOperand &UseMO :
9201 MachineInstr &UseMI = *UseMO.getParent();
9202 switch (UseMI.getOpcode()) {
9203 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9204 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9205 case AMDGPU::V_CNDMASK_B16_t16_e32:
9206 case AMDGPU::V_CNDMASK_B16_t16_e64:
9207 case AMDGPU::V_CNDMASK_B32_e32:
9208 case AMDGPU::V_CNDMASK_B32_e64:
9209 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9210 if (UseMO.isImplicit() ||
9211 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
9212 UseMO.setReg(CondReg);
9213 }
9214 }
9215 if (MRI.use_nodbg_empty(Dest.getReg()))
9216 return;
9217 }
9218
9219 Register NewCondReg = CondReg;
9220 if (IsSCC) {
9221 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
9222 NewCondReg = MRI.createVirtualRegister(TC);
9223
9224 // Now look for the closest SCC def if it is a copy
9225 // replacing the CondReg with the COPY source register
9226 bool CopyFound = false;
9227 for (MachineInstr &CandI :
9229 Inst.getParent()->rend())) {
9230 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
9231 -1) {
9232 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9233 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
9234 .addReg(CandI.getOperand(1).getReg());
9235 CopyFound = true;
9236 }
9237 break;
9238 }
9239 }
9240 if (!CopyFound) {
9241 // SCC def is not a copy
9242 // Insert a trivial select instead of creating a copy, because a copy from
9243 // SCC would semantically mean just copying a single bit, but we may need
9244 // the result to be a vector condition mask that needs preserving.
9245 unsigned Opcode =
9246 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9247 auto NewSelect =
9248 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
9249 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
9250 }
9251 }
9252
9253 Register NewDestReg = MRI.createVirtualRegister(
9254 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
9255 MachineInstr *NewInst;
9256 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
9257 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9258 .addImm(0)
9259 .add(Src1) // False
9260 .addImm(0)
9261 .add(Src0) // True
9262 .addReg(NewCondReg);
9263 } else {
9264 NewInst =
9265 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
9266 .add(Src1) // False
9267 .add(Src0) // True
9268 .addReg(NewCondReg);
9269 }
9270 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
9271 legalizeOperands(*NewInst, MDT);
9272 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9273}
9274
9275void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
9276 MachineInstr &Inst) const {
9277 MachineBasicBlock &MBB = *Inst.getParent();
9278 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9279 MachineBasicBlock::iterator MII = Inst;
9280 const DebugLoc &DL = Inst.getDebugLoc();
9281
9282 MachineOperand &Dest = Inst.getOperand(0);
9283 MachineOperand &Src = Inst.getOperand(1);
9284 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9285 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9286
9287 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9288 unsigned SubOp =
9289 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9290
9291 MachineInstrBuilder Sub =
9292 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(Src.getReg());
9293 if (HasCarryOut)
9294 Sub.setOperandDead(3); // Dead vcc
9295
9296 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9297 .addReg(Src.getReg())
9298 .addReg(TmpReg);
9299
9300 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9301 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9302}
9303
9304void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
9305 MachineInstr &Inst) const {
9306 MachineBasicBlock &MBB = *Inst.getParent();
9307 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9308 MachineBasicBlock::iterator MII = Inst;
9309 const DebugLoc &DL = Inst.getDebugLoc();
9310
9311 MachineOperand &Dest = Inst.getOperand(0);
9312 MachineOperand &Src1 = Inst.getOperand(1);
9313 MachineOperand &Src2 = Inst.getOperand(2);
9314 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9315 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9316 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9317
9318 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9319 unsigned SubOp =
9320 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9321
9322 MachineInstrBuilder Sub1 = BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
9323 .addReg(Src1.getReg())
9324 .addReg(Src2.getReg());
9325
9326 MachineInstrBuilder Sub2 =
9327 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
9328
9329 if (HasCarryOut) {
9330 Sub1.setOperandDead(3); // Dead vcc
9331 Sub2.setOperandDead(3); // Dead vcc
9332 }
9333
9334 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
9335 .addReg(SubResultReg)
9336 .addReg(TmpReg);
9337
9338 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9339 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9340}
9341
9342void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
9343 MachineInstr &Inst) const {
9344 MachineBasicBlock &MBB = *Inst.getParent();
9345 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9346 MachineBasicBlock::iterator MII = Inst;
9347 const DebugLoc &DL = Inst.getDebugLoc();
9348
9349 MachineOperand &Dest = Inst.getOperand(0);
9350 MachineOperand &Src0 = Inst.getOperand(1);
9351 MachineOperand &Src1 = Inst.getOperand(2);
9352
9353 if (ST.hasDLInsts()) {
9354 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9355 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
9356 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
9357
9358 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
9359 .add(Src0)
9360 .add(Src1);
9361
9362 MRI.replaceRegWith(Dest.getReg(), NewDest);
9363 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9364 } else {
9365 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
9366 // invert either source and then perform the XOR. If either source is a
9367 // scalar register, then we can leave the inversion on the scalar unit to
9368 // achieve a better distribution of scalar and vector instructions.
9369 bool Src0IsSGPR = Src0.isReg() &&
9370 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
9371 bool Src1IsSGPR = Src1.isReg() &&
9372 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
9373 MachineInstr *Xor;
9374 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9375 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9376
9377 // Build a pair of scalar instructions and add them to the work list.
9378 // The next iteration over the work list will lower these to the vector
9379 // unit as necessary.
9380 if (Src0IsSGPR) {
9381 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
9382 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9383 .addReg(Temp)
9384 .add(Src1);
9385 } else if (Src1IsSGPR) {
9386 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
9387 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
9388 .add(Src0)
9389 .addReg(Temp);
9390 } else {
9391 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
9392 .add(Src0)
9393 .add(Src1);
9394 MachineInstr *Not =
9395 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
9396 Worklist.insert(Not);
9397 }
9398
9399 MRI.replaceRegWith(Dest.getReg(), NewDest);
9400
9401 Worklist.insert(Xor);
9402
9403 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9404 }
9405}
9406
9407void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
9408 MachineInstr &Inst,
9409 unsigned Opcode) const {
9410 MachineBasicBlock &MBB = *Inst.getParent();
9411 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9412 MachineBasicBlock::iterator MII = Inst;
9413 const DebugLoc &DL = Inst.getDebugLoc();
9414
9415 MachineOperand &Dest = Inst.getOperand(0);
9416 MachineOperand &Src0 = Inst.getOperand(1);
9417 MachineOperand &Src1 = Inst.getOperand(2);
9418
9419 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9420 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9421
9422 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
9423 .add(Src0)
9424 .add(Src1);
9425
9426 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
9427 .addReg(Interm);
9428
9429 Worklist.insert(&Op);
9430 Worklist.insert(&Not);
9431
9432 MRI.replaceRegWith(Dest.getReg(), NewDest);
9433 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9434}
9435
9436void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
9437 MachineInstr &Inst,
9438 unsigned Opcode) const {
9439 MachineBasicBlock &MBB = *Inst.getParent();
9440 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9441 MachineBasicBlock::iterator MII = Inst;
9442 const DebugLoc &DL = Inst.getDebugLoc();
9443
9444 MachineOperand &Dest = Inst.getOperand(0);
9445 MachineOperand &Src0 = Inst.getOperand(1);
9446 MachineOperand &Src1 = Inst.getOperand(2);
9447
9448 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9449 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9450
9451 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
9452 .add(Src1);
9453
9454 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
9455 .add(Src0)
9456 .addReg(Interm);
9457
9458 Worklist.insert(&Not);
9459 Worklist.insert(&Op);
9460
9461 MRI.replaceRegWith(Dest.getReg(), NewDest);
9462 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9463}
9464
9465void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
9466 MachineInstr &Inst, unsigned Opcode,
9467 bool Swap) const {
9468 MachineBasicBlock &MBB = *Inst.getParent();
9469 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9470
9471 MachineOperand &Dest = Inst.getOperand(0);
9472 MachineOperand &Src0 = Inst.getOperand(1);
9473 const DebugLoc &DL = Inst.getDebugLoc();
9474
9475 MachineBasicBlock::iterator MII = Inst;
9476
9477 const MCInstrDesc &InstDesc = get(Opcode);
9478 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9479 MRI.getRegClass(Src0.getReg()) :
9480 &AMDGPU::SGPR_32RegClass;
9481
9482 const TargetRegisterClass *Src0SubRC =
9483 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9484
9485 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9486 AMDGPU::sub0, Src0SubRC);
9487
9488 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9489 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9490 const TargetRegisterClass *NewDestSubRC =
9491 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9492
9493 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9494 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
9495
9496 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9497 AMDGPU::sub1, Src0SubRC);
9498
9499 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9500 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
9501
9502 if (Swap)
9503 std::swap(DestSub0, DestSub1);
9504
9505 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9506 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9507 .addReg(DestSub0)
9508 .addImm(AMDGPU::sub0)
9509 .addReg(DestSub1)
9510 .addImm(AMDGPU::sub1);
9511
9512 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9513
9514 Worklist.insert(&LoHalf);
9515 Worklist.insert(&HiHalf);
9516
9517 // We don't need to legalizeOperands here because for a single operand, src0
9518 // will support any kind of input.
9519
9520 // Move all users of this moved value.
9521 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9522}
9523
9524// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9525// split the s_mul_u64 in 32-bit vector multiplications.
9526void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9527 MachineInstr &Inst,
9528 MachineDominatorTree *MDT) const {
9529 MachineBasicBlock &MBB = *Inst.getParent();
9530 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9531
9532 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9533 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9534 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9535
9536 MachineOperand &Dest = Inst.getOperand(0);
9537 MachineOperand &Src0 = Inst.getOperand(1);
9538 MachineOperand &Src1 = Inst.getOperand(2);
9539 const DebugLoc &DL = Inst.getDebugLoc();
9540 MachineBasicBlock::iterator MII = Inst;
9541
9542 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9543 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9544 const TargetRegisterClass *Src0SubRC =
9545 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9546 if (RI.isSGPRClass(Src0SubRC))
9547 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9548 const TargetRegisterClass *Src1SubRC =
9549 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9550 if (RI.isSGPRClass(Src1SubRC))
9551 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9552
9553 // First, we extract the low 32-bit and high 32-bit values from each of the
9554 // operands.
9555 MachineOperand Op0L =
9556 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9557 MachineOperand Op1L =
9558 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9559 MachineOperand Op0H =
9560 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9561 MachineOperand Op1H =
9562 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9563
9564 // The multilication is done as follows:
9565 //
9566 // Op1H Op1L
9567 // * Op0H Op0L
9568 // --------------------
9569 // Op1H*Op0L Op1L*Op0L
9570 // + Op1H*Op0H Op1L*Op0H
9571 // -----------------------------------------
9572 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9573 //
9574 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9575 // value and that would overflow.
9576 // The low 32-bit value is Op1L*Op0L.
9577 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9578
9579 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9580 MachineInstr *Op1L_Op0H =
9581 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9582 .add(Op1L)
9583 .add(Op0H);
9584
9585 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9586 MachineInstr *Op1H_Op0L =
9587 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9588 .add(Op1H)
9589 .add(Op0L);
9590
9591 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9592 MachineInstr *Carry =
9593 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9594 .add(Op1L)
9595 .add(Op0L);
9596
9597 MachineInstr *LoHalf =
9598 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9599 .add(Op1L)
9600 .add(Op0L);
9601
9602 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9603 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9604 .addReg(Op1L_Op0H_Reg)
9605 .addReg(Op1H_Op0L_Reg);
9606
9607 MachineInstr *HiHalf =
9608 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9609 .addReg(AddReg)
9610 .addReg(CarryReg);
9611
9612 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9613 .addReg(DestSub0)
9614 .addImm(AMDGPU::sub0)
9615 .addReg(DestSub1)
9616 .addImm(AMDGPU::sub1);
9617
9618 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9619
9620 // Try to legalize the operands in case we need to swap the order to keep it
9621 // valid.
9622 legalizeOperands(*Op1L_Op0H, MDT);
9623 legalizeOperands(*Op1H_Op0L, MDT);
9624 legalizeOperands(*Carry, MDT);
9625 legalizeOperands(*LoHalf, MDT);
9626 legalizeOperands(*Add, MDT);
9627 legalizeOperands(*HiHalf, MDT);
9628
9629 // Move all users of this moved value.
9630 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9631}
9632
9633// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9634// multiplications.
9635void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9636 MachineInstr &Inst,
9637 MachineDominatorTree *MDT) const {
9638 MachineBasicBlock &MBB = *Inst.getParent();
9639 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9640
9641 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9642 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9643 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9644
9645 MachineOperand &Dest = Inst.getOperand(0);
9646 MachineOperand &Src0 = Inst.getOperand(1);
9647 MachineOperand &Src1 = Inst.getOperand(2);
9648 const DebugLoc &DL = Inst.getDebugLoc();
9649 MachineBasicBlock::iterator MII = Inst;
9650
9651 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9652 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9653 const TargetRegisterClass *Src0SubRC =
9654 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9655 if (RI.isSGPRClass(Src0SubRC))
9656 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9657 const TargetRegisterClass *Src1SubRC =
9658 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9659 if (RI.isSGPRClass(Src1SubRC))
9660 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9661
9662 // First, we extract the low 32-bit and high 32-bit values from each of the
9663 // operands.
9664 MachineOperand Op0L =
9665 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9666 MachineOperand Op1L =
9667 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9668
9669 unsigned Opc = Inst.getOpcode();
9670 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9671 ? AMDGPU::V_MUL_HI_U32_e64
9672 : AMDGPU::V_MUL_HI_I32_e64;
9673 MachineInstr *HiHalf =
9674 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9675
9676 MachineInstr *LoHalf =
9677 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9678 .add(Op1L)
9679 .add(Op0L);
9680
9681 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9682 .addReg(DestSub0)
9683 .addImm(AMDGPU::sub0)
9684 .addReg(DestSub1)
9685 .addImm(AMDGPU::sub1);
9686
9687 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9688
9689 // Try to legalize the operands in case we need to swap the order to keep it
9690 // valid.
9691 legalizeOperands(*HiHalf, MDT);
9692 legalizeOperands(*LoHalf, MDT);
9693
9694 // Move all users of this moved value.
9695 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9696}
9697
9698void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9699 MachineInstr &Inst, unsigned Opcode,
9700 MachineDominatorTree *MDT) const {
9701 MachineBasicBlock &MBB = *Inst.getParent();
9702 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9703
9704 MachineOperand &Dest = Inst.getOperand(0);
9705 MachineOperand &Src0 = Inst.getOperand(1);
9706 MachineOperand &Src1 = Inst.getOperand(2);
9707 const DebugLoc &DL = Inst.getDebugLoc();
9708
9709 MachineBasicBlock::iterator MII = Inst;
9710
9711 const MCInstrDesc &InstDesc = get(Opcode);
9712 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9713 MRI.getRegClass(Src0.getReg()) :
9714 &AMDGPU::SGPR_32RegClass;
9715
9716 const TargetRegisterClass *Src0SubRC =
9717 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9718 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9719 MRI.getRegClass(Src1.getReg()) :
9720 &AMDGPU::SGPR_32RegClass;
9721
9722 const TargetRegisterClass *Src1SubRC =
9723 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9724
9725 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9726 AMDGPU::sub0, Src0SubRC);
9727 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9728 AMDGPU::sub0, Src1SubRC);
9729 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9730 AMDGPU::sub1, Src0SubRC);
9731 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9732 AMDGPU::sub1, Src1SubRC);
9733
9734 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9735 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9736 const TargetRegisterClass *NewDestSubRC =
9737 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9738
9739 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9740 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9741 .add(SrcReg0Sub0)
9742 .add(SrcReg1Sub0);
9743
9744 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9745 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9746 .add(SrcReg0Sub1)
9747 .add(SrcReg1Sub1);
9748
9749 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9750 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9751 .addReg(DestSub0)
9752 .addImm(AMDGPU::sub0)
9753 .addReg(DestSub1)
9754 .addImm(AMDGPU::sub1);
9755
9756 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9757
9758 Worklist.insert(&LoHalf);
9759 Worklist.insert(&HiHalf);
9760
9761 // Move all users of this moved value.
9762 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9763}
9764
9765void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9766 MachineInstr &Inst,
9767 MachineDominatorTree *MDT) const {
9768 MachineBasicBlock &MBB = *Inst.getParent();
9769 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9770
9771 MachineOperand &Dest = Inst.getOperand(0);
9772 MachineOperand &Src0 = Inst.getOperand(1);
9773 MachineOperand &Src1 = Inst.getOperand(2);
9774 const DebugLoc &DL = Inst.getDebugLoc();
9775
9776 MachineBasicBlock::iterator MII = Inst;
9777
9778 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9779
9780 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9781
9782 MachineOperand* Op0;
9783 MachineOperand* Op1;
9784
9785 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9786 Op0 = &Src0;
9787 Op1 = &Src1;
9788 } else {
9789 Op0 = &Src1;
9790 Op1 = &Src0;
9791 }
9792
9793 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9794 .add(*Op0);
9795
9796 Register NewDest = MRI.createVirtualRegister(DestRC);
9797
9798 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9799 .addReg(Interm)
9800 .add(*Op1);
9801
9802 MRI.replaceRegWith(Dest.getReg(), NewDest);
9803
9804 Worklist.insert(&Xor);
9805}
9806
9807void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9808 MachineInstr &Inst) const {
9809 MachineBasicBlock &MBB = *Inst.getParent();
9810 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9811
9812 MachineBasicBlock::iterator MII = Inst;
9813 const DebugLoc &DL = Inst.getDebugLoc();
9814
9815 MachineOperand &Dest = Inst.getOperand(0);
9816 MachineOperand &Src = Inst.getOperand(1);
9817
9818 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9819 const TargetRegisterClass *SrcRC = Src.isReg() ?
9820 MRI.getRegClass(Src.getReg()) :
9821 &AMDGPU::SGPR_32RegClass;
9822
9823 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9824 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9825
9826 const TargetRegisterClass *SrcSubRC =
9827 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9828
9829 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9830 AMDGPU::sub0, SrcSubRC);
9831 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9832 AMDGPU::sub1, SrcSubRC);
9833
9834 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9835
9836 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9837
9838 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9839
9840 // We don't need to legalize operands here. src0 for either instruction can be
9841 // an SGPR, and the second input is unused or determined here.
9842 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9843}
9844
9845void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9846 MachineInstr &Inst) const {
9847 MachineBasicBlock &MBB = *Inst.getParent();
9848 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9849 MachineBasicBlock::iterator MII = Inst;
9850 const DebugLoc &DL = Inst.getDebugLoc();
9851
9852 MachineOperand &Dest = Inst.getOperand(0);
9853 uint32_t Imm = Inst.getOperand(2).getImm();
9854 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9855 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9856
9857 (void) Offset;
9858
9859 // Only sext_inreg cases handled.
9860 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9861 Offset == 0 && "Not implemented");
9862
9863 if (BitWidth < 32) {
9864 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9865 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9866 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9867
9868 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9869 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9870 .addImm(0)
9871 .addImm(BitWidth);
9872
9873 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9874 .addImm(31)
9875 .addReg(MidRegLo);
9876
9877 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9878 .addReg(MidRegLo)
9879 .addImm(AMDGPU::sub0)
9880 .addReg(MidRegHi)
9881 .addImm(AMDGPU::sub1);
9882
9883 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9884 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9885 return;
9886 }
9887
9888 MachineOperand &Src = Inst.getOperand(1);
9889 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9890 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9891
9892 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9893 .addImm(31)
9894 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9895
9896 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9897 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9898 .addImm(AMDGPU::sub0)
9899 .addReg(TmpReg)
9900 .addImm(AMDGPU::sub1);
9901
9902 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9903 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9904}
9905
9906void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9907 MachineInstr &Inst, unsigned Opcode,
9908 MachineDominatorTree *MDT) const {
9909 // (S_FLBIT_I32_B64 hi:lo) ->
9910 // -> (umin (V_FFBH_U32_e32 hi), (or (V_FFBH_U32_e32 lo), 32))
9911 // (S_FF1_I32_B64 hi:lo) ->
9912 // ->(umin (or (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9913
9914 MachineBasicBlock &MBB = *Inst.getParent();
9915 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9916 MachineBasicBlock::iterator MII = Inst;
9917 const DebugLoc &DL = Inst.getDebugLoc();
9918
9919 MachineOperand &Dest = Inst.getOperand(0);
9920 MachineOperand &Src = Inst.getOperand(1);
9921
9922 const MCInstrDesc &InstDesc = get(Opcode);
9923
9924 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9925
9926 const TargetRegisterClass *SrcRC =
9927 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9928 const TargetRegisterClass *SrcSubRC =
9929 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9930
9931 MachineOperand SrcRegSub0 =
9932 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9933 MachineOperand SrcRegSub1 =
9934 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9935
9936 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9937 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9938 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9939 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9940
9941 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9942
9943 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9944
9945 BuildMI(MBB, MII, DL, get(AMDGPU::V_OR_B32_e32), MidReg3)
9946 .addImm(32)
9947 .addReg(IsCtlz ? MidReg1 : MidReg2);
9948
9949 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9950 .addReg(MidReg3)
9951 .addReg(IsCtlz ? MidReg2 : MidReg1);
9952
9953 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9954
9955 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9956}
9957
9958void SIInstrInfo::addUsersToMoveToVALUWorklist(
9960 SIInstrWorklist &Worklist) const {
9961 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9962 MachineInstr &UseMI = *MO.getParent();
9963
9964 unsigned OpNo = 0;
9965
9966 switch (UseMI.getOpcode()) {
9967 case AMDGPU::COPY:
9968 case AMDGPU::WQM:
9969 case AMDGPU::SOFT_WQM:
9970 case AMDGPU::STRICT_WWM:
9971 case AMDGPU::STRICT_WQM:
9972 case AMDGPU::REG_SEQUENCE:
9973 case AMDGPU::PHI:
9974 case AMDGPU::INSERT_SUBREG:
9975 break;
9976 default:
9977 OpNo = MO.getOperandNo();
9978 break;
9979 }
9980
9981 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9982 MRI.constrainRegClass(DstReg, OpRC);
9983
9984 if (!RI.hasVectorRegisters(OpRC))
9985 Worklist.insert(&UseMI);
9986 else
9987 // Legalization could change user list.
9989 }
9990}
9991
9992void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
9994 MachineInstr &Inst) const {
9995 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9996 MachineBasicBlock *MBB = Inst.getParent();
9997 MachineOperand &Src0 = Inst.getOperand(1);
9998 MachineOperand &Src1 = Inst.getOperand(2);
9999 const DebugLoc &DL = Inst.getDebugLoc();
10000
10001 if (ST.useRealTrue16Insts()) {
10002 Register SrcReg0, SrcReg1;
10003 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
10004 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10005 BuildMI(*MBB, Inst, DL,
10006 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
10007 .add(Src0);
10008 } else {
10009 SrcReg0 = Src0.getReg();
10010 }
10011
10012 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
10013 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10014 BuildMI(*MBB, Inst, DL,
10015 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
10016 .add(Src1);
10017 } else {
10018 SrcReg1 = Src1.getReg();
10019 }
10020
10021 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
10022 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
10023
10024 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
10025 switch (Inst.getOpcode()) {
10026 case AMDGPU::S_PACK_LL_B32_B16:
10027 NewMI
10028 .addReg(SrcReg0, {},
10029 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10030 .addImm(AMDGPU::lo16)
10031 .addReg(SrcReg1, {},
10032 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10033 .addImm(AMDGPU::hi16);
10034 break;
10035 case AMDGPU::S_PACK_LH_B32_B16:
10036 NewMI
10037 .addReg(SrcReg0, {},
10038 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10039 .addImm(AMDGPU::lo16)
10040 .addReg(SrcReg1, {}, AMDGPU::hi16)
10041 .addImm(AMDGPU::hi16);
10042 break;
10043 case AMDGPU::S_PACK_HL_B32_B16:
10044 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10045 .addImm(AMDGPU::lo16)
10046 .addReg(SrcReg1, {},
10047 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10048 .addImm(AMDGPU::hi16);
10049 break;
10050 case AMDGPU::S_PACK_HH_B32_B16:
10051 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10052 .addImm(AMDGPU::lo16)
10053 .addReg(SrcReg1, {}, AMDGPU::hi16)
10054 .addImm(AMDGPU::hi16);
10055 break;
10056 default:
10057 llvm_unreachable("unhandled s_pack_* instruction");
10058 }
10059
10060 MachineOperand &Dest = Inst.getOperand(0);
10061 MRI.replaceRegWith(Dest.getReg(), ResultReg);
10062 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10063 return;
10064 }
10065
10066 switch (Inst.getOpcode()) {
10067 case AMDGPU::S_PACK_LL_B32_B16: {
10068 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10069 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10070
10071 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
10072 // 0.
10073 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10074 .addImm(0xffff);
10075
10076 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
10077 .addReg(ImmReg)
10078 .add(Src0);
10079
10080 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
10081 .add(Src1)
10082 .addImm(16)
10083 .addReg(TmpReg);
10084 break;
10085 }
10086 case AMDGPU::S_PACK_LH_B32_B16: {
10087 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10088 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10089 .addImm(0xffff);
10090 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
10091 .addReg(ImmReg)
10092 .add(Src0)
10093 .add(Src1);
10094 break;
10095 }
10096 case AMDGPU::S_PACK_HL_B32_B16: {
10097 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10098 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
10099 .addImm(16)
10100 .add(Src0);
10101 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
10102 .add(Src1)
10103 .addImm(16)
10104 .addReg(TmpReg);
10105 break;
10106 }
10107 case AMDGPU::S_PACK_HH_B32_B16: {
10108 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10109 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
10110 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
10111 .addImm(16)
10112 .add(Src0);
10113 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
10114 .addImm(0xffff0000);
10115 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
10116 .add(Src1)
10117 .addReg(ImmReg)
10118 .addReg(TmpReg);
10119 break;
10120 }
10121 default:
10122 llvm_unreachable("unhandled s_pack_* instruction");
10123 }
10124
10125 MachineOperand &Dest = Inst.getOperand(0);
10126 MRI.replaceRegWith(Dest.getReg(), ResultReg);
10127 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
10128}
10129
10130void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
10131 MachineInstr &SCCDefInst,
10132 SIInstrWorklist &Worklist,
10133 Register NewCond) const {
10134
10135 // Ensure that def inst defines SCC, which is still live.
10136 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
10137 !Op.isDead() && Op.getParent() == &SCCDefInst);
10138 SmallVector<MachineInstr *, 4> CopyToDelete;
10139 // This assumes that all the users of SCC are in the same block
10140 // as the SCC def.
10141 for (MachineInstr &MI : // Skip the def inst itself.
10142 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
10143 SCCDefInst.getParent()->end())) {
10144 // Check if SCC is used first.
10145 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
10146 if (SCCIdx != -1) {
10147 if (MI.isCopy()) {
10148 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10149 Register DestReg = MI.getOperand(0).getReg();
10150
10151 MRI.replaceRegWith(DestReg, NewCond);
10152 CopyToDelete.push_back(&MI);
10153 } else {
10154
10155 if (NewCond.isValid())
10156 MI.getOperand(SCCIdx).setReg(NewCond);
10157
10158 Worklist.insert(&MI);
10159 }
10160 }
10161 // Exit if we find another SCC def.
10162 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
10163 break;
10164 }
10165 for (auto &Copy : CopyToDelete)
10166 Copy->eraseFromParent();
10167}
10168
10169// Instructions that use SCC may be converted to VALU instructions. When that
10170// happens, the SCC register is changed to VCC_LO. The instruction that defines
10171// SCC must be changed to an instruction that defines VCC. This function makes
10172// sure that the instruction that defines SCC is added to the moveToVALU
10173// worklist.
10174void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
10175 SIInstrWorklist &Worklist) const {
10176 // Look for a preceding instruction that either defines VCC or SCC. If VCC
10177 // then there is nothing to do because the defining instruction has been
10178 // converted to a VALU already. If SCC then that instruction needs to be
10179 // converted to a VALU.
10180 for (MachineInstr &MI :
10181 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
10182 SCCUseInst->getParent()->rend())) {
10183 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
10184 break;
10185 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
10186 Worklist.insert(&MI);
10187 break;
10188 }
10189 }
10190}
10191
10192const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
10193 const MachineInstr &Inst) const {
10194 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
10195
10196 switch (Inst.getOpcode()) {
10197 // For target instructions, getOpRegClass just returns the virtual register
10198 // class associated with the operand, so we need to find an equivalent VGPR
10199 // register class in order to move the instruction to the VALU.
10200 case AMDGPU::COPY:
10201 case AMDGPU::PHI:
10202 case AMDGPU::REG_SEQUENCE:
10203 case AMDGPU::INSERT_SUBREG:
10204 case AMDGPU::WQM:
10205 case AMDGPU::SOFT_WQM:
10206 case AMDGPU::STRICT_WWM:
10207 case AMDGPU::STRICT_WQM: {
10208 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
10209 if (RI.isAGPRClass(SrcRC)) {
10210 if (RI.isAGPRClass(NewDstRC))
10211 return nullptr;
10212
10213 switch (Inst.getOpcode()) {
10214 case AMDGPU::PHI:
10215 case AMDGPU::REG_SEQUENCE:
10216 case AMDGPU::INSERT_SUBREG:
10217 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10218 break;
10219 default:
10220 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10221 }
10222
10223 if (!NewDstRC)
10224 return nullptr;
10225 } else {
10226 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10227 return nullptr;
10228
10229 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10230 if (!NewDstRC)
10231 return nullptr;
10232 }
10233
10234 return NewDstRC;
10235 }
10236 default:
10237 return NewDstRC;
10238 }
10239}
10240
10241// Find the one SGPR operand we are allowed to use.
10242Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
10243 int OpIndices[3]) const {
10244 const MCInstrDesc &Desc = MI.getDesc();
10245
10246 // Find the one SGPR operand we are allowed to use.
10247 //
10248 // First we need to consider the instruction's operand requirements before
10249 // legalizing. Some operands are required to be SGPRs, such as implicit uses
10250 // of VCC, but we are still bound by the constant bus requirement to only use
10251 // one.
10252 //
10253 // If the operand's class is an SGPR, we can never move it.
10254
10255 Register SGPRReg = findImplicitSGPRRead(MI);
10256 if (SGPRReg)
10257 return SGPRReg;
10258
10259 Register UsedSGPRs[3] = {Register()};
10260 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10261
10262 for (unsigned i = 0; i < 3; ++i) {
10263 int Idx = OpIndices[i];
10264 if (Idx == -1)
10265 break;
10266
10267 const MachineOperand &MO = MI.getOperand(Idx);
10268 if (!MO.isReg())
10269 continue;
10270
10271 // Is this operand statically required to be an SGPR based on the operand
10272 // constraints?
10273 const TargetRegisterClass *OpRC =
10274 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
10275 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10276 if (IsRequiredSGPR)
10277 return MO.getReg();
10278
10279 // If this could be a VGPR or an SGPR, Check the dynamic register class.
10280 Register Reg = MO.getReg();
10281 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
10282 if (RI.isSGPRClass(RegRC))
10283 UsedSGPRs[i] = Reg;
10284 }
10285
10286 // We don't have a required SGPR operand, so we have a bit more freedom in
10287 // selecting operands to move.
10288
10289 // Try to select the most used SGPR. If an SGPR is equal to one of the
10290 // others, we choose that.
10291 //
10292 // e.g.
10293 // V_FMA_F32 v0, s0, s0, s0 -> No moves
10294 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
10295
10296 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
10297 // prefer those.
10298
10299 if (UsedSGPRs[0]) {
10300 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10301 SGPRReg = UsedSGPRs[0];
10302 }
10303
10304 if (!SGPRReg && UsedSGPRs[1]) {
10305 if (UsedSGPRs[1] == UsedSGPRs[2])
10306 SGPRReg = UsedSGPRs[1];
10307 }
10308
10309 return SGPRReg;
10310}
10311
10313 AMDGPU::OpName OperandName) const {
10314 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10315 return nullptr;
10316
10317 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
10318 if (Idx == -1)
10319 return nullptr;
10320
10321 return &MI.getOperand(Idx);
10322}
10323
10325 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
10326 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
10329 return (Format << 44) |
10330 (1ULL << 56) | // RESOURCE_LEVEL = 1
10331 (3ULL << 60); // OOB_SELECT = 3
10332 }
10333
10334 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
10335 if (ST.isAmdHsaOS()) {
10336 // Set ATC = 1. GFX9 doesn't have this bit.
10337 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
10338 RsrcDataFormat |= (1ULL << 56);
10339
10340 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
10341 // BTW, it disables TC L2 and therefore decreases performance.
10342 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
10343 RsrcDataFormat |= (2ULL << 59);
10344 }
10345
10346 return RsrcDataFormat;
10347}
10348
10350 uint64_t Rsrc23 = getDefaultRsrcDataFormat() |
10352 0xffffffff; // Size;
10353
10354 // GFX9 doesn't have ELEMENT_SIZE.
10355 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
10356 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
10357 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
10358 }
10359
10360 // IndexStride = 64 / 32.
10361 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10362 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
10363
10364 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
10365 // Clear them unless we want a huge stride.
10366 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
10367 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
10368 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
10369
10370 return Rsrc23;
10371}
10372
10374 unsigned Opc = MI.getOpcode();
10375
10376 return isSMRD(Opc);
10377}
10378
10380 return get(Opc).mayLoad() &&
10381 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
10382}
10383
10385 TypeSize &MemBytes) const {
10386 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
10387 if (!Addr || !Addr->isFI())
10388 return Register();
10389
10390 assert(!MI.memoperands_empty() &&
10391 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
10392
10393 FrameIndex = Addr->getIndex();
10394
10395 int VDataIdx =
10396 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
10397 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
10398 return MI.getOperand(VDataIdx).getReg();
10399}
10400
10402 TypeSize &MemBytes) const {
10403 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
10404 assert(Addr && Addr->isFI());
10405 FrameIndex = Addr->getIndex();
10406
10407 int DataIdx =
10408 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
10409 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
10410 return MI.getOperand(DataIdx).getReg();
10411}
10412
10414 int &FrameIndex,
10415 TypeSize &MemBytes) const {
10416 if (!MI.mayLoad())
10417 return Register();
10418
10419 if (isMUBUF(MI) || isVGPRSpill(MI))
10420 return isStackAccess(MI, FrameIndex, MemBytes);
10421
10422 if (isSGPRSpill(MI))
10423 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10424
10425 return Register();
10426}
10427
10429 int &FrameIndex,
10430 TypeSize &MemBytes) const {
10431 if (!MI.mayStore())
10432 return Register();
10433
10434 if (isMUBUF(MI) || isVGPRSpill(MI))
10435 return isStackAccess(MI, FrameIndex, MemBytes);
10436
10437 if (isSGPRSpill(MI))
10438 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10439
10440 return Register();
10441}
10442
10444 unsigned Opc = MI.getOpcode();
10446 unsigned DescSize = Desc.getSize();
10447
10448 // If we have a definitive size, we can use it. Otherwise we need to inspect
10449 // the operands to know the size.
10450 if (isFixedSize(MI)) {
10451 unsigned Size = DescSize;
10452
10453 // If we hit the buggy offset, an extra nop will be inserted in MC so
10454 // estimate the worst case.
10455 if (MI.isBranch() && ST.hasOffset3fBug())
10456 Size += 4;
10457
10458 return Size;
10459 }
10460
10461 // Instructions may have a 32-bit literal encoded after them. Check
10462 // operands that could ever be literals.
10463 if (isVALU(MI, /*AllowLDSDMA=*/false) || isSALU(MI)) {
10464 if (isDPP(MI))
10465 return DescSize;
10466 bool HasLiteral = false;
10467 unsigned LiteralSize = 4;
10468 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
10469 const MachineOperand &Op = MI.getOperand(I);
10470 const MCOperandInfo &OpInfo = Desc.operands()[I];
10471 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
10472 HasLiteral = true;
10473 if (ST.has64BitLiterals()) {
10474 switch (OpInfo.OperandType) {
10475 default:
10476 break;
10479 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
10480 LiteralSize = 8;
10481 break;
10484 // A 32-bit literal is only valid when the value fits in BOTH signed
10485 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
10486 // emitter's getLit64Encoding logic. This is because of the lack of
10487 // abilility to tell signedness of the literal, therefore we need to
10488 // be conservative and assume values outside this range require a
10489 // 64-bit literal encoding (8 bytes).
10490 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
10491 !isUInt<32>(Op.getImm()))
10492 LiteralSize = 8;
10493 break;
10494 }
10495 }
10496 break;
10497 }
10498 }
10499 return HasLiteral ? DescSize + LiteralSize : DescSize;
10500 }
10501
10502 // Check whether we have extra NSA words.
10503 if (isMIMG(MI)) {
10504 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
10505 if (VAddr0Idx < 0)
10506 return 8;
10507
10508 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
10509 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10510 }
10511
10512 switch (Opc) {
10513 case TargetOpcode::BUNDLE:
10514 return getInstBundleSize(MI);
10515 case TargetOpcode::INLINEASM:
10516 case TargetOpcode::INLINEASM_BR: {
10517 const MachineFunction *MF = MI.getMF();
10518 const char *AsmStr = MI.getOperand(0).getSymbolName();
10519 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10520 }
10521 default:
10522 if (MI.isMetaInstruction())
10523 return 0;
10524
10525 // If D16 Pseudo inst, get correct MC code size
10526 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10527 if (D16Info) {
10528 // Assume d16_lo/hi inst are always in same size
10529 unsigned LoInstOpcode = D16Info->LoOp;
10530 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10531 DescSize = Desc.getSize();
10532 }
10533
10534 // If FMA Pseudo inst, get correct MC code size
10535 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10536 // All potential lowerings are the same size; arbitrarily pick one.
10537 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10538 DescSize = Desc.getSize();
10539 }
10540
10541 return DescSize;
10542 }
10543}
10544
10547 if (MI.isBranch() && ST.hasOffset3fBug())
10548 return InstSizeVerifyMode::NoVerify;
10549 return InstSizeVerifyMode::ExactSize;
10550}
10551
10554 static const std::pair<int, const char *> TargetIndices[] = {
10555 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10556 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10557 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10558 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10559 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10560 return ArrayRef(TargetIndices);
10561}
10562
10563/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10564/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10567 const ScheduleDAG *DAG) const {
10568 return new GCNHazardRecognizer(DAG->MF);
10569}
10570
10571/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10572/// pass.
10579
10580// Called during:
10581// - pre-RA scheduling and post-RA scheduling
10584 const ScheduleDAGMI *DAG) const {
10585 // Borrowed from Arm Target
10586 // We would like to restrict this hazard recognizer to only
10587 // post-RA scheduling; we can tell that we're post-RA because we don't
10588 // track VRegLiveness.
10589 if (!DAG->hasVRegLiveness())
10590 return new GCNHazardRecognizer(DAG->MF);
10592}
10593
10594std::pair<unsigned, unsigned>
10596 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10597}
10598
10601 static const std::pair<unsigned, const char *> TargetFlags[] = {
10602 {MO_GOTPCREL, "amdgpu-gotprel"},
10603 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10604 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10605 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10606 {MO_REL32_LO, "amdgpu-rel32-lo"},
10607 {MO_REL32_HI, "amdgpu-rel32-hi"},
10608 {MO_REL64, "amdgpu-rel64"},
10609 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10610 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10611 {MO_ABS64, "amdgpu-abs64"},
10612 };
10613
10614 return ArrayRef(TargetFlags);
10615}
10616
10619 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10620 {
10621 {MONoClobber, "amdgpu-noclobber"},
10622 {MOLastUse, "amdgpu-last-use"},
10623 {MOCooperative, "amdgpu-cooperative"},
10624 {MOThreadPrivate, "amdgpu-thread-private"},
10625 {MOCFSB0, "amdgpu-cfs0"},
10626 {MOCFSB1, "amdgpu-cfs1"},
10627 };
10628
10629 return ArrayRef(TargetFlags);
10630}
10631
10633 const MachineFunction &MF) const {
10635 assert(SrcReg.isVirtual());
10636 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10637 return AMDGPU::WWM_COPY;
10638
10639 return AMDGPU::COPY;
10640}
10641
10643 uint32_t Opcode = MI.getOpcode();
10644 // Check if it is SGPR spill or wwm-register spill Opcode.
10645 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10646 return true;
10647
10648 const MachineFunction *MF = MI.getMF();
10649 const MachineRegisterInfo &MRI = MF->getRegInfo();
10651
10652 // See if this is Liverange split instruction inserted for SGPR or
10653 // wwm-register. The implicit def inserted for wwm-registers should also be
10654 // included as they can appear at the bb begin.
10655 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10656 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10657 return false;
10658
10659 Register Reg = MI.getOperand(0).getReg();
10660 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10661 return IsLRSplitInst;
10662
10663 return MFI->isWWMReg(Reg);
10664}
10665
10667 Register Reg) const {
10668 // We need to handle instructions which may be inserted during register
10669 // allocation to handle the prolog. The initial prolog instruction may have
10670 // been separated from the start of the block by spills and copies inserted
10671 // needed by the prolog. However, the insertions for scalar registers can
10672 // always be placed at the BB top as they are independent of the exec mask
10673 // value.
10674 bool IsNullOrVectorRegister = true;
10675 if (Reg) {
10676 const MachineFunction *MF = MI.getMF();
10677 const MachineRegisterInfo &MRI = MF->getRegInfo();
10678 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10679 }
10680
10681 return IsNullOrVectorRegister &&
10682 (canAddToBBProlog(MI) ||
10683 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10684 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10685}
10686
10690 const DebugLoc &DL,
10691 Register DestReg) const {
10692 if (ST.hasAddNoCarryInsts())
10693 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10694
10695 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10696 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10697 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10698
10699 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10700 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10701}
10702
10705 const DebugLoc &DL,
10706 Register DestReg,
10707 RegScavenger &RS) const {
10708 if (ST.hasAddNoCarryInsts())
10709 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10710
10711 // If available, prefer to use vcc.
10712 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10713 ? Register(RI.getVCC())
10714 : RS.scavengeRegisterBackwards(
10715 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10716 0, /* AllowSpill */ false);
10717
10718 // TODO: Users need to deal with this.
10719 if (!UnusedCarry.isValid())
10720 return MachineInstrBuilder();
10721
10722 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10723 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10724}
10725
10726bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10727 switch (Opcode) {
10728 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10729 case AMDGPU::SI_KILL_I1_TERMINATOR:
10730 return true;
10731 default:
10732 return false;
10733 }
10734}
10735
10737 switch (Opcode) {
10738 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10739 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10740 case AMDGPU::SI_KILL_I1_PSEUDO:
10741 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10742 default:
10743 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10744 }
10745}
10746
10748 return Imm <= getMaxMUBUFImmOffset(ST);
10749}
10750
10752 // GFX12 field is non-negative 24-bit signed byte offset.
10753 const unsigned OffsetBits =
10754 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10755 return (1 << OffsetBits) - 1;
10756}
10757
10759 if (!ST.isWave32())
10760 return;
10761
10762 if (MI.isInlineAsm())
10763 return;
10764
10765 if (MI.getNumOperands() < MI.getDesc().getNumOperands())
10766 return;
10767
10768 for (auto &Op : MI.implicit_operands()) {
10769 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10770 Op.setReg(AMDGPU::VCC_LO);
10771 }
10772}
10773
10775 if (!isSMRD(MI))
10776 return false;
10777
10778 // Check that it is using a buffer resource.
10779 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10780 if (Idx == -1) // e.g. s_memtime
10781 return false;
10782
10783 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10784 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10785}
10786
10787// Given Imm, split it into the values to put into the SOffset and ImmOffset
10788// fields in an MUBUF instruction. Return false if it is not possible (due to a
10789// hardware bug needing a workaround).
10790//
10791// The required alignment ensures that individual address components remain
10792// aligned if they are aligned to begin with. It also ensures that additional
10793// offsets within the given alignment can be added to the resulting ImmOffset.
10795 uint32_t &ImmOffset, Align Alignment) const {
10796 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10797 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10798 uint32_t Overflow = 0;
10799
10800 if (Imm > MaxImm) {
10801 if (Imm <= MaxImm + 64) {
10802 // Use an SOffset inline constant for 4..64
10803 Overflow = Imm - MaxImm;
10804 Imm = MaxImm;
10805 } else {
10806 // Try to keep the same value in SOffset for adjacent loads, so that
10807 // the corresponding register contents can be re-used.
10808 //
10809 // Load values with all low-bits (except for alignment bits) set into
10810 // SOffset, so that a larger range of values can be covered using
10811 // s_movk_i32.
10812 //
10813 // Atomic operations fail to work correctly when individual address
10814 // components are unaligned, even if their sum is aligned.
10815 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10816 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10817 Imm = Low;
10818 Overflow = High - Alignment.value();
10819 }
10820 }
10821
10822 if (Overflow > 0) {
10823 // There is a hardware bug in SI and CI which prevents address clamping in
10824 // MUBUF instructions from working correctly with SOffsets. The immediate
10825 // offset is unaffected.
10826 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10827 return false;
10828
10829 // It is not possible to set immediate in SOffset field on some targets.
10830 if (ST.hasRestrictedSOffset())
10831 return false;
10832 }
10833
10834 ImmOffset = Imm;
10835 SOffset = Overflow;
10836 return true;
10837}
10838
10839// Depending on the used address space and instructions, some immediate offsets
10840// are allowed and some are not.
10841// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10842// scratch instruction offsets can also be negative. On GFX12, offsets can be
10843// negative for all variants.
10844//
10845// There are several bugs related to these offsets:
10846// On gfx10.1, flat instructions that go into the global address space cannot
10847// use an offset.
10848//
10849// For scratch instructions, the address can be either an SGPR or a VGPR.
10850// The following offsets can be used, depending on the architecture (x means
10851// cannot be used):
10852// +----------------------------+------+------+
10853// | Address-Mode | SGPR | VGPR |
10854// +----------------------------+------+------+
10855// | gfx9 | | |
10856// | negative, 4-aligned offset | x | ok |
10857// | negative, unaligned offset | x | ok |
10858// +----------------------------+------+------+
10859// | gfx10 | | |
10860// | negative, 4-aligned offset | ok | ok |
10861// | negative, unaligned offset | ok | x |
10862// +----------------------------+------+------+
10863// | gfx10.3 | | |
10864// | negative, 4-aligned offset | ok | ok |
10865// | negative, unaligned offset | ok | ok |
10866// +----------------------------+------+------+
10867//
10868// This function ignores the addressing mode, so if an offset cannot be used in
10869// one addressing mode, it is considered illegal.
10870bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10871 AMDGPU::FlatAddrSpace FlatVariant) const {
10872 // TODO: Should 0 be special cased?
10873 if (!ST.hasFlatInstOffsets())
10874 return false;
10875
10877 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10878 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10879 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10880 return false;
10881
10882 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10883 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10884 (Offset % 4) != 0) {
10885 return false;
10886 }
10887
10888 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10889 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10890 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10891}
10892
10893// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10894std::pair<int64_t, int64_t>
10895SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10896 AMDGPU::FlatAddrSpace FlatVariant) const {
10897 int64_t RemainderOffset = COffsetVal;
10898 int64_t ImmField = 0;
10899
10900 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10901 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10902
10903 if (AllowNegative) {
10904 // Use signed division by a power of two to truncate towards 0.
10905 int64_t D = 1LL << NumBits;
10906 RemainderOffset = (COffsetVal / D) * D;
10907 ImmField = COffsetVal - RemainderOffset;
10908
10909 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10910 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10911 (ImmField % 4) != 0) {
10912 // Make ImmField a multiple of 4
10913 RemainderOffset += ImmField % 4;
10914 ImmField -= ImmField % 4;
10915 }
10916 } else if (COffsetVal >= 0) {
10917 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10918 RemainderOffset = COffsetVal - ImmField;
10919 }
10920
10921 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10922 assert(RemainderOffset + ImmField == COffsetVal);
10923 return {ImmField, RemainderOffset};
10924}
10925
10927 AMDGPU::FlatAddrSpace FlatVariant) const {
10928 if (ST.hasNegativeScratchOffsetBug() &&
10930 return false;
10931
10932 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10933}
10934
10935static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10936 switch (ST.getGeneration()) {
10937 default:
10938 break;
10941 return SIEncodingFamily::SI;
10943 // The GFX80 encoding family only contains buffer instructions with unpacked
10944 // D16 data; pseudoToMCOpcode falls back on VI for everything else.
10945 // TODO: remove this when we discard GFX80 encoding.
10946 return ST.hasUnpackedD16VMem() ? SIEncodingFamily::GFX80
10949 return SIEncodingFamily::VI;
10953 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10956 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10960 }
10961 llvm_unreachable("Unknown subtarget generation!");
10962}
10963
10964bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10965 switch(MCOp) {
10966 // These opcodes use indirect register addressing so
10967 // they need special handling by codegen (currently missing).
10968 // Therefore it is too risky to allow these opcodes
10969 // to be selected by dpp combiner or sdwa peepholer.
10970 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10971 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10972 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10973 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10974 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10975 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10976 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10977 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10978 return true;
10979 default:
10980 return false;
10981 }
10982}
10983
10984#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10985 case OPCODE##_dpp: \
10986 case OPCODE##_e32: \
10987 case OPCODE##_e64:
10988
10989static bool isRenamedInGFX9(int Opcode) {
10990 switch (Opcode) {
10991 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
10992 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
10993 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
10994 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
10995 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
10996 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
10997 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
10998 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
10999 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
11000 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
11001 case AMDGPU::V_FMA_F16_gfx9_e64:
11002 case AMDGPU::V_INTERP_P2_F16:
11003 case AMDGPU::V_MAD_F16_e64:
11004 case AMDGPU::V_MAD_U16_e64:
11005 case AMDGPU::V_MAD_I16_e64:
11006 case AMDGPU::V_MAD_U16_gfx9_e64:
11007 case AMDGPU::V_MAD_I16_gfx9_e64:
11008 return true;
11009 default:
11010 return false;
11011 }
11012}
11013
11014int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
11015 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
11016 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
11017
11018 unsigned Gen = subtargetEncodingFamily(ST);
11019
11020 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
11022
11023 if (SIInstrFlags::isSDWA(get(Opcode))) {
11024 switch (ST.getGeneration()) {
11025 default:
11027 break;
11030 break;
11033 break;
11034 }
11035 }
11036
11037 if (isMAI(Opcode)) {
11038 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
11039 if (MFMAOp != -1)
11040 Opcode = MFMAOp;
11041 }
11042
11043 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
11044
11045 // Only buffer instructions with unpacked D16 data have a GFX80 encoding.
11046 // Anything else on such a subtarget uses the plain VI encoding.
11047 // TODO: remove this when we discard GFX80 encoding.
11048 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && Gen == SIEncodingFamily::GFX80)
11050
11051 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
11053
11054 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
11056
11057 // -1 means that Opcode is already a native instruction.
11058 if (MCOp == -1)
11059 return Opcode;
11060
11061 if (ST.hasGFX90AInsts()) {
11062 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
11063 if (ST.hasGFX940Insts())
11065 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11067 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11069 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
11070 MCOp = NMCOp;
11071 }
11072
11073 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
11074 // encoding in the given subtarget generation.
11075 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
11076 return -1;
11077
11078 if (isAsmOnlyOpcode(MCOp))
11079 return -1;
11080
11081 return MCOp;
11082}
11083
11084static
11086 assert(RegOpnd.isReg());
11087 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
11088 getRegSubRegPair(RegOpnd);
11089}
11090
11093 assert(MI.isRegSequence());
11094 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
11095 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
11096 auto &RegOp = MI.getOperand(1 + 2 * I);
11097 return getRegOrUndef(RegOp);
11098 }
11100}
11101
11102// Try to find the definition of reg:subreg in subreg-manipulation pseudos
11103// Following a subreg of reg:subreg isn't supported
11106 if (!RSR.SubReg)
11107 return false;
11108 switch (MI.getOpcode()) {
11109 default: break;
11110 case AMDGPU::REG_SEQUENCE:
11111 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
11112 return true;
11113 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
11114 case AMDGPU::INSERT_SUBREG:
11115 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
11116 // inserted the subreg we're looking for
11117 RSR = getRegOrUndef(MI.getOperand(2));
11118 else { // the subreg in the rest of the reg
11119 auto R1 = getRegOrUndef(MI.getOperand(1));
11120 if (R1.SubReg) // subreg of subreg isn't supported
11121 return false;
11122 RSR.Reg = R1.Reg;
11123 }
11124 return true;
11125 }
11126 return false;
11127}
11128
11130 const MachineRegisterInfo &MRI) {
11131 assert(MRI.isSSA());
11132 if (!P.Reg.isVirtual())
11133 return nullptr;
11134
11135 auto RSR = P;
11136 auto *DefInst = MRI.getVRegDef(RSR.Reg);
11137 while (auto *MI = DefInst) {
11138 DefInst = nullptr;
11139 switch (MI->getOpcode()) {
11140 case AMDGPU::COPY:
11141 case AMDGPU::V_MOV_B32_e32: {
11142 auto &Op1 = MI->getOperand(1);
11143 if (Op1.isReg() && Op1.getReg().isVirtual()) {
11144 if (Op1.isUndef())
11145 return nullptr;
11146 RSR = getRegSubRegPair(Op1);
11147 DefInst = MRI.getVRegDef(RSR.Reg);
11148 }
11149 break;
11150 }
11151 default:
11152 if (followSubRegDef(*MI, RSR)) {
11153 if (!RSR.Reg)
11154 return nullptr;
11155 DefInst = MRI.getVRegDef(RSR.Reg);
11156 }
11157 }
11158 if (!DefInst)
11159 return MI;
11160 }
11161 return nullptr;
11162}
11163
11165 Register VReg,
11166 const MachineInstr &DefMI,
11167 const MachineInstr &UseMI) {
11168 assert(MRI.isSSA() && "Must be run on SSA");
11169
11170 auto *TRI = MRI.getTargetRegisterInfo();
11171 auto *DefBB = DefMI.getParent();
11172
11173 // Don't bother searching between blocks, although it is possible this block
11174 // doesn't modify exec.
11175 if (UseMI.getParent() != DefBB)
11176 return true;
11177
11178 const int MaxInstScan = 20;
11179 int NumInst = 0;
11180
11181 // Stop scan at the use.
11182 auto E = UseMI.getIterator();
11183 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
11184 if (I->isDebugInstr())
11185 continue;
11186
11187 if (++NumInst > MaxInstScan)
11188 return true;
11189
11190 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
11191 return true;
11192 }
11193
11194 return false;
11195}
11196
11198 Register VReg,
11199 const MachineInstr &DefMI) {
11200 assert(MRI.isSSA() && "Must be run on SSA");
11201
11202 auto *TRI = MRI.getTargetRegisterInfo();
11203 auto *DefBB = DefMI.getParent();
11204
11205 const int MaxUseScan = 10;
11206 int NumUse = 0;
11207
11208 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
11209 auto &UseInst = *Use.getParent();
11210 // Don't bother searching between blocks, although it is possible this block
11211 // doesn't modify exec.
11212 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11213 return true;
11214
11215 if (++NumUse > MaxUseScan)
11216 return true;
11217 }
11218
11219 if (NumUse == 0)
11220 return false;
11221
11222 const int MaxInstScan = 20;
11223 int NumInst = 0;
11224
11225 // Stop scan when we have seen all the uses.
11226 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
11227 assert(I != DefBB->end());
11228
11229 if (I->isDebugInstr())
11230 continue;
11231
11232 if (++NumInst > MaxInstScan)
11233 return true;
11234
11235 for (const MachineOperand &Op : I->operands()) {
11236 // We don't check reg masks here as they're used only on calls:
11237 // 1. EXEC is only considered const within one BB
11238 // 2. Call should be a terminator instruction if present in a BB
11239
11240 if (!Op.isReg())
11241 continue;
11242
11243 Register Reg = Op.getReg();
11244 if (Op.isUse()) {
11245 if (Reg == VReg && --NumUse == 0)
11246 return false;
11247 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
11248 return true;
11249 }
11250 }
11251}
11252
11255 const DebugLoc &DL, Register Src, Register Dst) const {
11256 auto Cur = MBB.begin();
11257 if (Cur != MBB.end())
11258 do {
11259 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
11260 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
11261 ++Cur;
11262 } while (Cur != MBB.end() && Cur != LastPHIIt);
11263
11264 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
11265 Dst);
11266}
11267
11270 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
11271 if (InsPt != MBB.end() &&
11272 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11273 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11274 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11275 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
11276 InsPt++;
11277 return BuildMI(MBB, InsPt, DL,
11278 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
11279 .addReg(Src, {}, SrcSubReg)
11280 .addReg(AMDGPU::EXEC, RegState::Implicit);
11281 }
11282 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
11283 Dst);
11284}
11285
11286bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
11287
11289 const MachineInstr &SecondMI) const {
11290 for (const auto &Use : SecondMI.all_uses()) {
11291 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
11292 return true;
11293 }
11294 return false;
11295}
11296
11297/// If OpX is multicycle, anti-dependencies are not allowed.
11298/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
11299/// purpose.
11301 const MachineInstr &OpX) const {
11303}
11304
11307 ArrayRef<unsigned> Ops, int FrameIndex,
11308 MachineInstr *&CopyMI, LiveIntervals *LIS,
11309 VirtRegMap *VRM) const {
11310 // This is a bit of a hack (copied from AArch64). Consider this instruction:
11311 //
11312 // %0:sreg_32 = COPY $m0
11313 //
11314 // We explicitly chose SReg_32 for the virtual register so such a copy might
11315 // be eliminated by RegisterCoalescer. However, that may not be possible, and
11316 // %0 may even spill. We can't spill $m0 normally (it would require copying to
11317 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
11318 // TargetInstrInfo::foldMemoryOperand() is going to try.
11319 // A similar issue also exists with spilling and reloading $exec registers.
11320 //
11321 // To prevent that, constrain the %0 register class here.
11322 if (isFullCopyInstr(MI)) {
11323 Register DstReg = MI.getOperand(0).getReg();
11324 Register SrcReg = MI.getOperand(1).getReg();
11325 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
11326 (DstReg.isVirtual() != SrcReg.isVirtual())) {
11328 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
11329 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
11330 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
11331 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11332 return nullptr;
11333 }
11334 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
11335 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11336 return nullptr;
11337 }
11338 }
11339 }
11340
11341 return nullptr;
11342}
11343
11345 const MachineInstr &MI,
11346 unsigned *PredCost) const {
11347 if (MI.isBundle()) {
11349 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
11350 unsigned Lat = 0, Count = 0;
11351 for (++I; I != E && I->isBundledWithPred(); ++I) {
11352 ++Count;
11353 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
11354 }
11355 return Lat + Count - 1;
11356 }
11357
11358 return SchedModel.computeInstrLatency(&MI);
11359}
11360
11362 if (!ST.hasGFX1250VALUBlockingCycles())
11363 return 0;
11365}
11366
11367unsigned
11369 if (const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(MI.getOpcode()))
11370 return Entry->GFX1250BlockingCycles;
11371 return 0;
11372}
11373
11374const MachineOperand &
11376 if (const MachineOperand *CallAddrOp =
11377 getNamedOperand(MI, AMDGPU::OpName::src0))
11378 return *CallAddrOp;
11380}
11381
11384 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11385 unsigned Opcode = MI.getOpcode();
11386
11387 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
11388 Register Dst = MI.getOperand(0).getReg();
11389 Register Src = MI.getOperand(1).getReg();
11390 LLT DstTy = MRI.getType(Dst);
11391 LLT SrcTy = MRI.getType(Src);
11392 unsigned DstAS = DstTy.getAddressSpace();
11393 unsigned SrcAS = SrcTy.getAddressSpace();
11394 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
11395 DstAS == AMDGPUAS::FLAT_ADDRESS &&
11396 ST.hasGloballyAddressableScratch()
11399 };
11400
11401 // If the target supports globally addressable scratch, the mapping from
11402 // scratch memory to the flat aperture changes therefore an address space cast
11403 // is no longer uniform.
11404 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11405 return HandleAddrSpaceCast(MI);
11406
11407 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
11408 auto IID = GI->getIntrinsicID();
11413
11414 switch (IID) {
11415 case Intrinsic::amdgcn_if:
11416 case Intrinsic::amdgcn_else:
11417 // FIXME: Uniform if second result
11418 break;
11419 }
11420
11422 }
11423
11424 // Loads from the private and flat address spaces are divergent, because
11425 // threads can execute the load instruction with the same inputs and get
11426 // different results.
11427 //
11428 // All other loads are not divergent, because if threads issue loads with the
11429 // same arguments, they will always get the same result.
11430 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11431 Opcode == AMDGPU::G_SEXTLOAD) {
11432 if (MI.memoperands_empty())
11433 return ValueUniformity::NeverUniform; // conservative assumption
11434
11435 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11436 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11437 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11438 })) {
11439 // At least one MMO in a non-global address space.
11441 }
11443 }
11444
11445 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11446 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11447 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11448 AMDGPU::isGenericAtomic(Opcode)) {
11450 }
11451
11452 // Result is computed from uniform SP and uniform wave-wide max size.
11453 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11455
11456 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11458
11460}
11461
11463 if (!Formatter)
11464 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11465 return Formatter.get();
11466}
11467
11469
11470 if (isNeverUniform(MI))
11472
11473 unsigned opcode = MI.getOpcode();
11474 if (opcode == AMDGPU::V_READLANE_B32 ||
11475 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11476 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11478
11479 // If any of defs is divergent, report as NeverUniform. isUniformReg will
11480 // calculate in more detail for each def from its reg class, if available.
11481 if (MI.isInlineAsm()) {
11482 for (const MachineOperand &MO : MI.operands()) {
11483 if (!MO.isReg() || !MO.isDef())
11484 continue;
11485 const TargetRegisterClass *RC =
11486 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
11487 if (!RC || !RI.isSGPRClass(RC))
11489 }
11490 }
11491
11492 if (isCopyInstr(MI)) {
11493 const MachineOperand &srcOp = MI.getOperand(1);
11494 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
11495 const TargetRegisterClass *regClass =
11496 RI.getPhysRegBaseClass(srcOp.getReg());
11497 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
11499 }
11501 }
11502
11503 // GMIR handling
11504 if (MI.isPreISelOpcode())
11506
11507 // Atomics are divergent because they are executed sequentially: when an
11508 // atomic operation refers to the same address in each thread, then each
11509 // thread after the first sees the value written by the previous thread as
11510 // original value.
11511
11512 if (isAtomic(MI))
11514
11515 // Loads from the private and flat address spaces are divergent, because
11516 // threads can execute the load instruction with the same inputs and get
11517 // different results.
11518 if (isFLAT(MI) && MI.mayLoad()) {
11519 if (MI.memoperands_empty())
11520 return ValueUniformity::NeverUniform; // conservative assumption
11521
11522 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11523 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11524 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11525 })) {
11526 // At least one MMO in a non-global address space.
11528 }
11529
11531 }
11532
11533 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11534 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11535
11536 // FIXME: It's conceptually broken to report this for an instruction, and not
11537 // a specific def operand. For inline asm in particular, there could be mixed
11538 // uniform and divergent results.
11539 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11540 const MachineOperand &SrcOp = MI.getOperand(I);
11541 if (!SrcOp.isReg())
11542 continue;
11543
11544 Register Reg = SrcOp.getReg();
11545 if (!Reg || !SrcOp.readsReg())
11546 continue;
11547
11548 // If RegBank is null, this is unassigned or an unallocatable special
11549 // register, which are all scalars.
11550 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11551 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11553 }
11554
11555 // TODO: Uniformity check condtions above can be rearranged for more
11556 // redability
11557
11558 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11559 // currently turned into no-op COPYs by SelectionDAG ISel and are
11560 // therefore no longer recognizable.
11561
11563}
11564
11566 switch (MF.getFunction().getCallingConv()) {
11568 return 1;
11570 return 2;
11572 return 3;
11576 const Function &F = MF.getFunction();
11577 F.getContext().diagnose(DiagnosticInfoUnsupported(
11578 F, "ds_ordered_count unsupported for this calling conv"));
11579 [[fallthrough]];
11580 }
11583 case CallingConv::C:
11584 case CallingConv::Fast:
11585 default:
11586 // Assume other calling conventions are various compute callable functions
11587 return 0;
11588 }
11589}
11590
11592 Register &SrcReg2, int64_t &CmpMask,
11593 int64_t &CmpValue) const {
11594 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11595 return false;
11596
11597 switch (MI.getOpcode()) {
11598 default:
11599 break;
11600 case AMDGPU::S_CMP_EQ_U32:
11601 case AMDGPU::S_CMP_EQ_I32:
11602 case AMDGPU::S_CMP_LG_U32:
11603 case AMDGPU::S_CMP_LG_I32:
11604 case AMDGPU::S_CMP_LT_U32:
11605 case AMDGPU::S_CMP_LT_I32:
11606 case AMDGPU::S_CMP_GT_U32:
11607 case AMDGPU::S_CMP_GT_I32:
11608 case AMDGPU::S_CMP_LE_U32:
11609 case AMDGPU::S_CMP_LE_I32:
11610 case AMDGPU::S_CMP_GE_U32:
11611 case AMDGPU::S_CMP_GE_I32:
11612 case AMDGPU::S_CMP_EQ_U64:
11613 case AMDGPU::S_CMP_LG_U64:
11614 SrcReg = MI.getOperand(0).getReg();
11615 if (MI.getOperand(1).isReg()) {
11616 if (MI.getOperand(1).getSubReg())
11617 return false;
11618 SrcReg2 = MI.getOperand(1).getReg();
11619 CmpValue = 0;
11620 } else if (MI.getOperand(1).isImm()) {
11621 SrcReg2 = Register();
11622 CmpValue = MI.getOperand(1).getImm();
11623 } else {
11624 return false;
11625 }
11626 CmpMask = ~0;
11627 return true;
11628 case AMDGPU::S_CMPK_EQ_U32:
11629 case AMDGPU::S_CMPK_EQ_I32:
11630 case AMDGPU::S_CMPK_LG_U32:
11631 case AMDGPU::S_CMPK_LG_I32:
11632 case AMDGPU::S_CMPK_LT_U32:
11633 case AMDGPU::S_CMPK_LT_I32:
11634 case AMDGPU::S_CMPK_GT_U32:
11635 case AMDGPU::S_CMPK_GT_I32:
11636 case AMDGPU::S_CMPK_LE_U32:
11637 case AMDGPU::S_CMPK_LE_I32:
11638 case AMDGPU::S_CMPK_GE_U32:
11639 case AMDGPU::S_CMPK_GE_I32:
11640 SrcReg = MI.getOperand(0).getReg();
11641 SrcReg2 = Register();
11642 CmpValue = MI.getOperand(1).getImm();
11643 CmpMask = ~0;
11644 return true;
11645 }
11646
11647 return false;
11648}
11649
11651 for (MachineBasicBlock *S : MBB->successors()) {
11652 if (S->isLiveIn(AMDGPU::SCC))
11653 return false;
11654 }
11655 return true;
11656}
11657
11658// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11659// (incoming SCC) = !(SCC defined by SCCDef).
11660// Return true if all uses can be re-written, false otherwise.
11661bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11662 MachineBasicBlock *MBB = SCCDef->getParent();
11663 SmallVector<MachineInstr *> InvertInstr;
11664 bool SCCIsDead = false;
11665
11666 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11667 constexpr unsigned ScanLimit = 12;
11668 unsigned Count = 0;
11669 for (MachineInstr &MI : instructionsWithoutDebug(
11670 std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11671 if (++Count > ScanLimit)
11672 return false;
11673 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11674 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11675 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11676 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11677 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11678 InvertInstr.push_back(&MI);
11679 else
11680 return false;
11681 }
11682 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11683 SCCIsDead = true;
11684 break;
11685 }
11686 }
11687 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11688 SCCIsDead = true;
11689
11690 // SCC may have more uses. Can't invert all of them.
11691 if (!SCCIsDead)
11692 return false;
11693
11694 // Invert uses
11695 for (MachineInstr *MI : InvertInstr) {
11696 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11697 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11698 swapOperands(*MI);
11699 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11700 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11701 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11702 ? AMDGPU::S_CBRANCH_SCC1
11703 : AMDGPU::S_CBRANCH_SCC0));
11704 } else {
11705 llvm_unreachable("SCC used but no inversion handling");
11706 }
11707 }
11708 return true;
11709}
11710
11711// SCC is already valid after SCCValid.
11712// SCCRedefine will redefine SCC to the same value already available after
11713// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11714// update kill/dead flags if necessary.
11715bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11716 bool NeedInversion) const {
11717 MachineInstr *KillsSCC = nullptr;
11718 if (SCCValid->getParent() != SCCRedefine->getParent())
11719 return false;
11720 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11721 SCCRedefine->getIterator())) {
11722 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11723 return false;
11724 if (MI.killsRegister(AMDGPU::SCC, &RI))
11725 KillsSCC = &MI;
11726 }
11727 if (NeedInversion && !invertSCCUse(SCCRedefine))
11728 return false;
11729 if (MachineOperand *SccDef =
11730 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11731 SccDef->setIsDead(false);
11732 if (KillsSCC)
11733 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11734 SCCRedefine->eraseFromParent();
11735 return true;
11736}
11737
11738/// If \p Sel is an S_CSELECT* of two different constants A and B, return them,
11739/// truncated to the width of the select.
11740static std::optional<std::pair<int64_t, int64_t>>
11742 const MachineInstr &Sel) {
11743 unsigned Opc = Sel.getOpcode();
11744 if (Opc != AMDGPU::S_CSELECT_B32 && Opc != AMDGPU::S_CSELECT_B64)
11745 return {};
11746 std::optional<int64_t> A =
11747 TII.getImmOrMaterializedImm(MRI, Sel.getOperand(1));
11748 if (!A)
11749 return {};
11750 std::optional<int64_t> B =
11751 TII.getImmOrMaterializedImm(MRI, Sel.getOperand(2));
11752 if (!B)
11753 return {};
11754 if (Opc == AMDGPU::S_CSELECT_B32) {
11755 A = Lo_32(*A);
11756 B = Lo_32(*B);
11757 }
11758 if (*A == *B)
11759 return {};
11760 return std::pair(*A, *B);
11761}
11762
11763static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11764 unsigned &NewDefOpc) {
11765 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11766 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11767 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11768 Def.getOpcode() != AMDGPU::S_ADD_U32)
11769 return false;
11770 const MachineOperand &AddSrc1 = Def.getOperand(1);
11771 const MachineOperand &AddSrc2 = Def.getOperand(2);
11772 const MachineRegisterInfo &MRI = Def.getMF()->getRegInfo();
11773 const SIInstrInfo *TII = static_cast<const SIInstrInfo *>(
11774 Def.getMF()->getSubtarget().getInstrInfo());
11775
11776 auto Imm1 = TII->getImmOrMaterializedImm(MRI, AddSrc1);
11777 auto Imm2 = TII->getImmOrMaterializedImm(MRI, AddSrc2);
11778 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11779 return false;
11780
11781 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11782 const MachineOperand *SccDef =
11783 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11784 if (!SccDef->isDead())
11785 return false;
11786 NewDefOpc = AMDGPU::S_ADD_U32;
11787 }
11788 NeedInversion = !NeedInversion;
11789 return true;
11790}
11791
11793 Register SrcReg2, int64_t CmpMask,
11794 int64_t CmpValue,
11795 const MachineRegisterInfo *MRI) const {
11796 if (!SrcReg || SrcReg.isPhysical())
11797 return false;
11798
11799 if (SrcReg2) {
11800 auto ImmOpt = getImmOrMaterializedImm(*MRI, SrcReg2);
11801 if (!ImmOpt)
11802 return false;
11803 CmpValue = *ImmOpt;
11804 }
11805
11806 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11807 this](bool NeedInversion) -> bool {
11808 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11809 if (!Def)
11810 return false;
11811
11812 unsigned NewDefOpc = Def->getOpcode();
11813 if (auto Consts = getSelectConstants(*this, *MRI, *Def)) {
11814 // sX = S_CSELECT* A, B with A != B, so sX == A exactly when SCC was set.
11815 // Comparing sX with A or B recomputes SCC or its inverse:
11816 //
11817 // s_cmp_eq_* sX, A => SCC s_cmp_lg_* sX, A => !SCC
11818 // s_cmp_eq_* sX, B => !SCC s_cmp_lg_* sX, B => SCC
11819 auto [A, B] = *Consts;
11820 int64_t C = Def->getOpcode() == AMDGPU::S_CSELECT_B32 ? Lo_32(CmpValue)
11821 : CmpValue;
11822 if (C == A)
11823 NeedInversion = !NeedInversion;
11824 else if (C != B)
11825 return false;
11826 } else {
11827 // For S_OP that set SCC = DST!=0, do the transformation
11828 //
11829 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11830 //
11831 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11832 // do the transformation:
11833 //
11834 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11835 if (CmpValue != 0 ||
11836 (!setsSCCIfResultIsNonZero(*Def) &&
11837 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc)))
11838 return false;
11839 }
11840
11841 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11842 return false;
11843
11844 if (NewDefOpc != Def->getOpcode())
11845 Def->setDesc(get(NewDefOpc));
11846
11847 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11848 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11849 // 64-bit select then delete s_or_b32 in the sequence:
11850 // sX = s_cselect_b64 A, B (A != B, one of them 0)
11851 // sLo = copy sX.sub0
11852 // sHi = copy sX.sub1
11853 // sY = s_or_b32 sLo, sHi
11854 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11855 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11856 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11857 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11858 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11859 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11860 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11861 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11862 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11863 Def2->getOperand(1).isReg() &&
11864 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11865 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11866 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11867 if (MachineInstr *Select =
11868 MRI->getVRegDef(Def1->getOperand(1).getReg())) {
11869 if (auto Consts = getSelectConstants(*this, *MRI, *Select)) {
11870 auto [A, B] = *Consts;
11871 if (A == 0 || B == 0)
11872 optimizeSCC(Select, Def, /*NeedInversion=*/A == 0);
11873 }
11874 }
11875 }
11876 }
11877 }
11878 return true;
11879 };
11880
11881 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11882 this](int64_t ExpectedValue, unsigned SrcSize,
11883 bool IsReversible, bool IsSigned) -> bool {
11884 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11885 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11886 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11887 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11888 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11889 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11890 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11891 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11892 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11893 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11894 //
11895 // Signed ge/gt are not used for the sign bit.
11896 //
11897 // If result of the AND is unused except in the compare:
11898 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11899 //
11900 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11901 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11902 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11903 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11904 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11905 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11906
11907 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11908 if (!Def)
11909 return false;
11910
11911 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11912 Def->getOpcode() != AMDGPU::S_AND_B64)
11913 return false;
11914
11915 int64_t Mask;
11916 const auto isMask = [&Mask, SrcSize, MRI,
11917 this](const MachineOperand *MO) -> bool {
11918 auto ImmOpt = this->getImmOrMaterializedImm(*MRI, *MO);
11919 if (!ImmOpt)
11920 return false;
11921 Mask = *ImmOpt;
11922 Mask &= maxUIntN(SrcSize);
11923 return isPowerOf2_64(Mask);
11924 };
11925
11926 MachineOperand *SrcOp = &Def->getOperand(1);
11927 if (isMask(SrcOp))
11928 SrcOp = &Def->getOperand(2);
11929 else if (isMask(&Def->getOperand(2)))
11930 SrcOp = &Def->getOperand(1);
11931 else
11932 return false;
11933
11934 // A valid Mask is required to have a single bit set, hence a non-zero and
11935 // power-of-two value. This verifies that we will not do 64-bit shift below.
11936 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11937 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11938 if (IsSigned && BitNo == SrcSize - 1)
11939 return false;
11940
11941 ExpectedValue <<= BitNo;
11942
11943 bool IsReversedCC = false;
11944 if (CmpValue != ExpectedValue) {
11945 if (!IsReversible)
11946 return false;
11947 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11948 if (!IsReversedCC)
11949 return false;
11950 }
11951
11952 Register DefReg = Def->getOperand(0).getReg();
11953 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11954 return false;
11955
11956 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11957 return false;
11958
11959 if (!MRI->use_nodbg_empty(DefReg)) {
11960 assert(!IsReversedCC);
11961 return true;
11962 }
11963
11964 // Replace AND with unused result with a S_BITCMP.
11965 MachineBasicBlock *MBB = Def->getParent();
11966
11967 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11968 : AMDGPU::S_BITCMP1_B32
11969 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11970 : AMDGPU::S_BITCMP1_B64;
11971
11972 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11973 .add(*SrcOp)
11974 .addImm(BitNo);
11975 Def->eraseFromParent();
11976
11977 return true;
11978 };
11979
11980 switch (CmpInstr.getOpcode()) {
11981 default:
11982 break;
11983 case AMDGPU::S_CMP_EQ_U32:
11984 case AMDGPU::S_CMP_EQ_I32:
11985 case AMDGPU::S_CMPK_EQ_U32:
11986 case AMDGPU::S_CMPK_EQ_I32:
11987 return optimizeCmpAnd(1, 32, true, false) ||
11988 optimizeCmpSelect(/*NeedInversion=*/true);
11989 case AMDGPU::S_CMP_GE_U32:
11990 case AMDGPU::S_CMPK_GE_U32:
11991 return optimizeCmpAnd(1, 32, false, false);
11992 case AMDGPU::S_CMP_GE_I32:
11993 case AMDGPU::S_CMPK_GE_I32:
11994 return optimizeCmpAnd(1, 32, false, true);
11995 case AMDGPU::S_CMP_EQ_U64:
11996 return optimizeCmpAnd(1, 64, true, false) ||
11997 optimizeCmpSelect(/*NeedInversion=*/true);
11998 case AMDGPU::S_CMP_LG_U32:
11999 case AMDGPU::S_CMP_LG_I32:
12000 case AMDGPU::S_CMPK_LG_U32:
12001 case AMDGPU::S_CMPK_LG_I32:
12002 return optimizeCmpAnd(0, 32, true, false) ||
12003 optimizeCmpSelect(/*NeedInversion=*/false);
12004 case AMDGPU::S_CMP_GT_U32:
12005 case AMDGPU::S_CMPK_GT_U32:
12006 return optimizeCmpAnd(0, 32, false, false);
12007 case AMDGPU::S_CMP_GT_I32:
12008 case AMDGPU::S_CMPK_GT_I32:
12009 return optimizeCmpAnd(0, 32, false, true);
12010 case AMDGPU::S_CMP_LG_U64:
12011 return optimizeCmpAnd(0, 64, true, false) ||
12012 optimizeCmpSelect(/*NeedInversion=*/false);
12013 }
12014
12015 return false;
12016}
12017
12019 AMDGPU::OpName OpName) const {
12020 if (!ST.needsAlignedVGPRs())
12021 return;
12022
12023 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
12024 if (OpNo < 0)
12025 return;
12026 MachineOperand &Op = MI.getOperand(OpNo);
12027 if (getOpSize(MI, OpNo) > 4)
12028 return;
12029
12030 // Add implicit aligned super-reg to force alignment on the data operand.
12031 const DebugLoc &DL = MI.getDebugLoc();
12032 MachineBasicBlock *BB = MI.getParent();
12034 Register DataReg = Op.getReg();
12035 bool IsAGPR = RI.isAGPR(MRI, DataReg);
12036 Register Undef = MRI.createVirtualRegister(
12037 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
12038 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
12039 Register NewVR =
12040 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
12041 : &AMDGPU::VReg_64_Align2RegClass);
12042 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
12043 .addReg(DataReg, {}, Op.getSubReg())
12044 .addImm(AMDGPU::sub0)
12045 .addReg(Undef)
12046 .addImm(AMDGPU::sub1);
12047 Op.setReg(NewVR);
12048 Op.setSubReg(AMDGPU::sub0);
12049 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
12050}
12051
12053 if (!SchedModel.hasInstrSchedModel())
12054 return 0;
12055
12056 // The repeat rate is the throughput-limiting resource occupancy: the largest
12057 // number of cycles any written processor resource is held.
12058 const MCSchedClassDesc *SCDesc = SchedModel.resolveSchedClass(&MI);
12059 unsigned RepeatRate = 0;
12061 PI = SchedModel.getWriteProcResBegin(SCDesc),
12062 PE = SchedModel.getWriteProcResEnd(SCDesc);
12063 PI != PE; ++PI) {
12064 RepeatRate = std::max(RepeatRate, (unsigned)PI->ReleaseAtCycle);
12065 }
12066
12067 return RepeatRate;
12068}
12069
12071 if (isIGLP(*MI))
12072 return false;
12073
12075}
12076
12078 if (!isWMMA(MI) && !isSWMMAC(MI))
12079 return false;
12080
12081 if (ST.hasGFX1250Insts())
12082 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
12083
12084 return true;
12085}
12086
12088 unsigned Opcode = MI.getOpcode();
12089
12090 if (AMDGPU::isGFX12Plus(ST))
12091 return isDOT(MI) || isXDLWMMA(MI);
12092
12093 if (!isMAI(MI) || isDGEMM(Opcode) ||
12094 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
12095 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
12096 return false;
12097
12098 if (!ST.hasGFX940Insts())
12099 return true;
12100
12101 return AMDGPU::getMAIIsGFX940XDL(Opcode);
12102}
12103
12105 constexpr unsigned MinOrderedXDLVAVDSTVGPRs = 8;
12106 if (!AMDGPU::isGFX1250(ST) || !isXDL(MI))
12107 return false;
12108
12109 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
12110 const TargetRegisterClass *DstRC =
12111 getRegClass(MI.getDesc(), Dst->getOperandNo());
12112 return DstRC && RI.isVGPRClass(DstRC) &&
12113 RI.getRegSizeInBits(*DstRC) >= MinOrderedXDLVAVDSTVGPRs * 32;
12114}
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!")
Shared AMDGPU asyncmark stage definitions.
uint64_t uint64_t
uint64_t Imm
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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
static Register UseReg(const MachineOperand &MO)
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
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
This file declares the machine register scavenger class.
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 std::optional< std::pair< int64_t, int64_t > > getSelectConstants(const SIInstrInfo &TII, const MachineRegisterInfo &MRI, const MachineInstr &Sel)
If Sel is an S_CSELECT* of two different constants A and B, return them, truncated to the width of th...
static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc)
static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize)
static bool compareMachineOp(const MachineOperand &Op0, const MachineOperand &Op1)
static bool isStride64(unsigned Opc)
static MachineBasicBlock * generateWaterFallLoop(const SIInstrInfo &TII, MachineInstr &MI, ArrayRef< MachineOperand * > ScalarOps, MachineDominatorTree *MDT, MachineBasicBlock::iterator Begin=nullptr, MachineBasicBlock::iterator End=nullptr, ArrayRef< Register > PhySGPRs={})
#define GENERATE_RENAMED_GFX9_CASES(OPCODE)
static std::tuple< unsigned, unsigned > extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc)
static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx)
static bool followSubRegDef(MachineInstr &MI, TargetInstrInfo::RegSubRegPair &RSR)
static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize)
static MachineInstr * swapImmOperands(MachineInstr &MI, MachineOperand &NonRegOp1, MachineOperand &NonRegOp2)
static void copyFlagsToImplicitVCC(MachineInstr &MI, const MachineOperand &Orig)
static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, LocationSize WidthB, int OffsetB)
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, RegScavenger &RS, bool RegsOverlap, Register ImpUseSuperReg=Register())
Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908.
static unsigned getWWMRegSpillSaveOpcode(unsigned Size, bool IsVectorSuperClass)
static bool memOpsHaveSameBaseOperands(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getWWMRegSpillRestoreOpcode(unsigned Size, bool IsVectorSuperClass)
static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion, unsigned &NewDefOpc)
static bool isSCCDeadOnExit(MachineBasicBlock *MBB)
static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize)
static unsigned subtargetEncodingFamily(const GCNSubtarget &ST)
static void preserveCondRegFlags(MachineOperand &CondReg, const MachineOperand &OrigCond)
static Register findImplicitSGPRRead(const MachineInstr &MI)
static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc)
static 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 bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI)
Return true if MI is a VALU comparison, i.e.
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 isLegalPkF32OpSel(const SIInstrInfo &TII, const MachineInstr &MI, bool CheckSwappedSrc=false)
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 bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
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 std::pair< unsigned, unsigned > splitGlobalAddressRelocFlags(const MachineOperand &SrcOp)
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:479
#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:185
Class for arbitrary precision integers.
Definition APInt.h:78
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
This class is the base class for the comparison instructions.
Definition InstrTypes.h:728
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A debug info location.
Definition DebugLoc.h:126
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:856
Diagnostic information for unsupported feature in backend.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:273
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:352
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:76
A live range for subregisters.
LiveInterval - This class represents the liveness of a register, or stack slot.
iterator_range< subrange_iterator > subranges()
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.
bool hasValue() const
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:347
static const MCBinaryExpr * createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:417
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
unsigned getOpcode() const
Return the opcode number for this descriptor.
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition MCInstrDesc.h:88
uint8_t OperandType
Information about the type of the operand.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition MCInstrDesc.h:94
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void setVariableValue(const MCExpr *Value)
Definition MCSymbol.cpp:51
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 & setOperandDead(unsigned OpIdx) const
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.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
const GlobalValue * getGlobal() const
LLVM_ABI void ChangeToFrameIndex(int Idx, unsigned TargetFlags=0)
Replace this operand with a frame index.
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
LLVM_ABI void ChangeToGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
ChangeToGA - Replace this operand with a new global address operand.
void setIsKill(bool Val=true)
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
void setOffset(int64_t Offset)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
bool isEarlyClobber() const
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,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
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 Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
const MachineFunction & getMF() const
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
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 replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
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 std::optional< unsigned > extractSubregFromGlobalAddressFlags(unsigned TargetFlags, unsigned SubRegIndex)
Return the target flags for a global address operand reading subregister SubRegIndex of a 64-bit glob...
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
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
bool isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
unsigned getGFX1250BlockingCyclesTable(const MachineInstr &MI) const
GFX1250 blocking-cycles table lookup with no occupancy subtarget gate.
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
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const final
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
static bool isDOT(const MachineInstr &MI)
std::unique_ptr< PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
static bool usesTENSOR_CNT(const MachineInstr &MI)
bool hasModifiers(unsigned Opcode) const
Return true if this instruction has any modifiers.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
static bool isSWMMAC(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
bool isWave32() const
bool isHighLatencyDef(int Opc) const override
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const
Legalize the OpIndex operand of this instruction by inserting a MOV.
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isVOPC(const MachineInstr &MI)
void removeModOperands(MachineInstr &MI) const
unsigned getRepeatRate(const MachineInstr &MI) const
Get the repeat rate for a VALU instruction from the scheduling model.
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool isLegalSingleSGPRReadInstOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for a single-SGPR-read instruction.
bool isXDL(const MachineInstr &MI) const
Register isStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
static bool isVIMAGE(const MachineInstr &MI)
void enforceOperandRCAlignment(MachineInstr &MI, AMDGPU::OpName OpName) const
static bool isSOP2(const MachineInstr &MI)
static bool isGWS(const MachineInstr &MI)
bool hasRAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI) const
bool isLegalAV64PseudoImm(uint64_t Imm) const
Check if this immediate value can be used for AV_MOV_B64_IMM_PSEUDO.
bool isNeverCoissue(MachineInstr &MI) const
static bool isBUF(const MachineInstr &MI)
bool isNonCommutableDPP(const MachineInstr &MI) const
void handleCopyToPhysHelper(SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst, MachineRegisterInfo &MRI, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
bool hasModifiersSet(const MachineInstr &MI, AMDGPU::OpName OpName) const
bool isLegalToSwap(const MachineInstr &MI, unsigned fromIdx, unsigned toIdx) const
static bool isFLATGlobal(const MachineInstr &MI)
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isGlobalMemoryObject(const MachineInstr *MI) const override
bool canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, SelectExpansion &Exp) 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 getBlockingCycles(const MachineInstr &MI) const
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 isVPermPk16(unsigned Opcode)
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const final
static bool isTRANS(const MachineInstr &MI)
static bool isImage(const MachineInstr &MI)
static bool isSOPK(const MachineInstr &MI)
const TargetRegisterClass * getOpRegClass(const MachineInstr &MI, unsigned OpNo) const
Return the correct register class for OpNo.
MachineBasicBlock * insertSimulatedTrap(MachineRegisterInfo &MRI, MachineBasicBlock &MBB, MachineInstr &MI, const DebugLoc &DL) const
Build instructions that simulate the behavior of a s_trap 2 instructions for hardware (namely,...
static unsigned getNonSoftWaitcntOpcode(unsigned Opcode)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static bool isFoldableCopy(const MachineInstr &MI)
static bool isMUBUF(const MachineInstr &MI)
bool expandPostRAPseudo(MachineInstr &MI) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
void createWaterFallForSiCall(MachineInstr *MI, MachineDominatorTree *MDT, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={}) const
Wrapper function for generating waterfall for instruction MI This function take into consideration of...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
AMDGPU::AsyncStages getAsyncStage(const MachineInstr &MI) const
static bool isSegmentSpecificFLAT(const MachineInstr &MI)
bool isReMaterializableImpl(const MachineInstr &MI) const override
static bool isVOP3(const MCInstrDesc &Desc)
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool physRegUsesConstantBus(const MachineOperand &Reg) const
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
bool mayAccessVMEMThroughFlat(const MachineInstr &MI) const
static bool isDPP(const MachineInstr &MI)
bool analyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
static bool isMFMA(const MachineInstr &MI)
bool isLowLatencyInstruction(const MachineInstr &MI) const
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is a instruction that moves/copies value from one register to ano...
void mutateAndCleanupImplicit(MachineInstr &MI, const MCInstrDesc &NewDesc) const
ValueUniformity getGenericValueUniformity(const MachineInstr &MI) const
static bool isMAI(const MCInstrDesc &Desc)
static bool isSrc1DPPRevOpcode(const GCNSubtarget &ST, uint32_t Opcode)
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const override
static bool usesLGKM_CNT(const MachineInstr &MI)
void legalizeOperandsVALUt16(MachineInstr &Inst, MachineRegisterInfo &MRI) const
Fix operands in Inst to fix 16bit SALU to VALU lowering.
bool isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo, const MachineOperand &MO) const
bool canShrink(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
const MachineOperand & getCalleeOperand(const MachineInstr &MI) const override
bool isAsmOnlyOpcode(int MCOp) const
Check if this instruction should only be used by assembler.
bool isAlwaysGDS(uint32_t Opcode) const
static bool isVGPRSpill(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
This is used by the post-RA scheduler (SchedulePostRAList.cpp).
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
unsigned getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr &MI, unsigned *PredCost=nullptr) const override
unsigned getVectorRegSpillSaveOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI, bool NeedsCFI) const
int64_t getNamedImmOperand(const MachineInstr &MI, AMDGPU::OpName OperandName) const
Get required immediate operand.
ArrayRef< std::pair< int, const char * > > getSerializableTargetIndices() const override
bool regUsesConstantBus(const MachineOperand &Reg, const MachineRegisterInfo &MRI) const
static bool isMIMG(const MachineInstr &MI)
MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isLegalRegOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO (a register operand) is a legal register for the given operand description or operand ind...
static unsigned getNumWaitStates(const MachineInstr &MI)
Return the number of wait states that result from executing this instruction.
bool isVAVDSTOrderedXDL(const MachineInstr &MI) const
On gfx1250, an XDL instruction whose destination spans at least eight VGPRs decrements VA_VDST only a...
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.
static bool usesASYNC_CNT(const MachineInstr &MI)
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool isMaskedByExec(Register Reg, const MachineInstr &Use, const MachineRegisterInfo &MRI, unsigned Depth=0) const
Return true if Reg is a lane mask that already has 0 in every bit corresponding to a lane that is ina...
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 isAsync(const MachineInstr &MI) const
bool memOpsHaveSameBase(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2) const
Return true if the memory operations described by BaseOps1 and BaseOps2 (as returned by getMemOperand...
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 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
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.
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveIntervals *LIS) const override
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx, const MachineOperand *MO=nullptr) const
Check if MO is a legal operand if it was the OpIdx Operand for MI.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool allowNegativeFlatOffset(AMDGPU::FlatAddrSpace FlatVariant) const
Returns true if negative offsets are allowed for the given FlatVariant.
void moveToVALUImpl(SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
static bool isLDSDMA(const MachineInstr &MI)
static bool isVOP1(const MachineInstr &MI)
SIInstrInfo(const GCNSubtarget &ST)
std::optional< int64_t > getImmOrMaterializedImm(const MachineRegisterInfo &MRI, const MachineOperand &Op, MachineInstr **DefMI=nullptr) const
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool hasAnyModifiersSet(const MachineInstr &MI) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
void setHasSpilledVGPRs(bool Spill=true)
bool isWWMReg(Register Reg) const
bool checkFlag(Register Reg, uint8_t Flag) const
void setHasSpilledSGPRs(bool Spill=true)
unsigned getScratchReservedForDynamicVGPRs() const
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
static unsigned getSubRegFromChannel(uint64_t Channel, uint64_t NumRegs=1)
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:70
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:295
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
int64_t getImm() const
Register getReg() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Object returned by analyzeLoopForPipelining.
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:352
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:210
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:188
self_iterator getIterator()
Definition ilist_node.h:123
#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)
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)
constexpr bool isValidAsyncStageMask(int64_t Mask)
AsyncStages
Bit mask of the async stages tracked by the asyncmark / wait_asyncmark intrinsics.
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)
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 bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
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.
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi, bool *IsBF16)
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:441
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:459
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:426
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:434
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:450
@ OPERAND_REG_IMM_NOINLINE_FP16
Definition SIDefines.h:432
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:447
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:452
@ OPERAND_REG_IMM_V2INT64
Definition SIDefines.h:437
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:436
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:430
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:425
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:433
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:431
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:435
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:446
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:444
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:438
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:429
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:453
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:464
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:465
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:439
@ OPERAND_SDWA_VOPC_DST
Definition SIDefines.h:476
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:428
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:449
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:445
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:451
@ OPERAND_INLINE_C_AV64_PSEUDO
Definition SIDefines.h:470
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:440
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:466
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:448
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:427
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:456
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:667
@ TI_SCRATCH_RSRC_DWORD3
Definition AMDGPU.h:669
@ TI_SCRATCH_RSRC_DWORD0
Definition AMDGPU.h:666
@ TI_SCRATCH_RSRC_DWORD2
Definition AMDGPU.h:668
@ TI_CONSTDATA_START
Definition AMDGPU.h:665
bool isGFX1250(const MCSubtargetInfo &STI)
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 isSDWA(const T &...O)
Definition SIDefines.h:249
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
Definition Threading.h:280
@ Offset
Definition DWP.cpp:577
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
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:2570
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:649
static const MachineMemOperand::Flags MOCFSB1
Definition SIInstrInfo.h:75
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:546
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:49
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:1762
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
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
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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:57
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
Definition SIInstrInfo.h:45
constexpr unsigned BitWidth
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
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:53
constexpr T reverseBits(T Val)
Reverse the bits in Val.
Definition MathExtras.h:119
static const MachineMemOperand::Flags MOCFSB0
Use two MMO flags to encode the 2-bit cache fill size field for GFX13+.
Definition SIInstrInfo.h:72
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
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:572
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
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320
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:68
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:881
#define N
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr bool all() const
Definition LaneBitmask.h:54
This represents a simple continuous liveness interval for a value.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:124
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:79
MachineInstr * top() const
Definition SIInstrInfo.h:84
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
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.