LLVM 24.0.0git
SIInstrInfo.cpp
Go to the documentation of this file.
1//===- SIInstrInfo.cpp - SI Instruction Information ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// SI Implementation of TargetInstrInfo.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SIInstrInfo.h"
15#include "AMDGPU.h"
16#include "AMDGPUInstrInfo.h"
17#include "AMDGPULaneMaskUtils.h"
18#include "GCNHazardRecognizer.h"
19#include "GCNSubtarget.h"
22#include "llvm/ADT/STLExtras.h"
34#include "llvm/IR/IntrinsicsAMDGPU.h"
35#include "llvm/MC/MCContext.h"
38#include <tuple>
39
40using namespace llvm;
41
42#define DEBUG_TYPE "si-instr-info"
43
44#define GET_INSTRINFO_CTOR_DTOR
45#include "AMDGPUGenInstrInfo.inc"
46
47namespace llvm::AMDGPU {
48#define GET_D16ImageDimIntrinsics_IMPL
49#define GET_ImageDimIntrinsicTable_IMPL
50#define GET_RsrcIntrinsics_IMPL
51#include "AMDGPUGenSearchableTables.inc"
52} // namespace llvm::AMDGPU
53
54// Must be at least 4 to be able to branch over minimum unconditional branch
55// code. This is only for making it possible to write reasonably small tests for
56// long branches.
58BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16),
59 cl::desc("Restrict range of branch instructions (DEBUG)"));
60
62 "amdgpu-fix-16-bit-physreg-copies",
63 cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"),
64 cl::init(true),
66
68 : AMDGPUGenInstrInfo(ST, RI, AMDGPU::ADJCALLSTACKUP,
69 AMDGPU::ADJCALLSTACKDOWN),
70 RI(ST), ST(ST) {
71 SchedModel.init(&ST);
72}
73
74//===----------------------------------------------------------------------===//
75// TargetInstrInfo callbacks
76//===----------------------------------------------------------------------===//
77
78static unsigned getNumOperandsNoGlue(SDNode *Node) {
79 unsigned N = Node->getNumOperands();
80 while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
81 --N;
82 return N;
83}
84
85/// Returns true if both nodes have the same value for the given
86/// operand \p Op, or if both nodes do not have this operand.
88 AMDGPU::OpName OpName) {
89 unsigned Opc0 = N0->getMachineOpcode();
90 unsigned Opc1 = N1->getMachineOpcode();
91
92 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName);
93 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName);
94
95 if (Op0Idx == -1 && Op1Idx == -1)
96 return true;
97
98
99 if ((Op0Idx == -1 && Op1Idx != -1) ||
100 (Op1Idx == -1 && Op0Idx != -1))
101 return false;
102
103 // getNamedOperandIdx returns the index for the MachineInstr's operands,
104 // which includes the result as the first operand. We are indexing into the
105 // MachineSDNode's operands, so we need to skip the result operand to get
106 // the real index.
107 --Op0Idx;
108 --Op1Idx;
109
110 return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx);
111}
112
113static bool canRemat(const MachineInstr &MI) {
114
118 return true;
119
120 if (SIInstrInfo::isSMRD(MI)) {
121 return !MI.memoperands_empty() &&
122 llvm::all_of(MI.memoperands(), [](const MachineMemOperand *MMO) {
123 return MMO->isLoad() && MMO->isInvariant();
124 });
125 }
126
127 return false;
128}
129
130// Split relocation flags for 64-bit global-address materialization into a
131// common base and the hi/lo relocation variants.
132static std::tuple<unsigned, unsigned, unsigned>
134 const MachineOperand &SrcOp) {
135 unsigned SrcFlags = SrcOp.getTargetFlags();
136
137 // Infer the relocation type from the existing flags on the global operand.
138 // The relocation type should have been determined earlier in the pipeline.
139 unsigned LoReloc = SIInstrInfo::MO_ABS32_LO;
140 unsigned HiReloc = SIInstrInfo::MO_ABS32_HI;
141
142 if (SrcFlags & SIInstrInfo::MO_REL32) {
143 LoReloc = SIInstrInfo::MO_REL32_LO;
144 HiReloc = SIInstrInfo::MO_REL32_HI;
145 } else if (SrcFlags & SIInstrInfo::MO_GOTPCREL32_LO) {
148 } else if (SrcFlags & SIInstrInfo::MO_GOTPCREL64) {
149 // For 64-bit GOT-relative, use the 64-bit relocation.
152 }
153
154 unsigned BaseFlags =
159
160 return std::make_tuple(BaseFlags, LoReloc, HiReloc);
161}
162
164 const MachineInstr &MI) const {
165
166 if (canRemat(MI)) {
167 // Normally VALU use of exec would block the rematerialization, but that
168 // is OK in this case to have an implicit exec read as all VALU do.
169 // We really want all of the generic logic for this except for this.
170
171 // Another potential implicit use is mode register. The core logic of
172 // the RA will not attempt rematerialization if mode is set anywhere
173 // in the function, otherwise it is safe since mode is not changed.
174
175 // There is difference to generic method which does not allow
176 // rematerialization if there are virtual register uses. We allow this,
177 // therefore this method includes SOP instructions as well.
178 if (!MI.hasImplicitDef() &&
179 MI.getNumImplicitOperands() == MI.getDesc().implicit_uses().size() &&
180 !MI.mayRaiseFPException())
181 return true;
182 }
183
185}
186
187// Returns true if the result of a VALU instruction depends on exec.
188bool SIInstrInfo::resultDependsOnExec(const MachineInstr &MI) const {
189 assert(isVALU(MI, /*AllowLDSDMA=*/true));
190
191 // If it is convergent it depends on EXEC.
192 if (MI.isConvergent())
193 return true;
194
195 // If it defines SGPR it depends on EXEC
196 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
197 for (const MachineOperand &Def : MI.defs()) {
198 if (!Def.isReg())
199 continue;
200
201 Register Reg = Def.getReg();
202 if (Reg && RI.isSGPRReg(MRI, Reg))
203 return true;
204 }
205
206 return false;
207}
208
210 // Any implicit use of exec by VALU is not a real register read.
211 return MO.getReg() == AMDGPU::EXEC && MO.isImplicit() &&
212 isVALU(*MO.getParent(), /*AllowLDSDMA=*/true) &&
213 !resultDependsOnExec(*MO.getParent());
214}
215
217 MachineBasicBlock *SuccToSinkTo,
218 MachineCycleInfo *CI) const {
219 // Allow sinking if MI edits lane mask (divergent i1 in sgpr).
220 if (MI.getOpcode() == AMDGPU::SI_IF_BREAK)
221 return true;
222
223 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
224 // Check if sinking of MI would create temporal divergent use.
225 for (auto Op : MI.uses()) {
226 if (Op.isReg() && Op.getReg().isVirtual() &&
227 RI.isSGPRClass(MRI.getRegClass(Op.getReg()))) {
228 MachineInstr *SgprDef = MRI.getVRegDef(Op.getReg());
229
230 // SgprDef defined inside cycle
231 CycleRef FromCycle = CI->getCycle(SgprDef->getParent());
232 if (!FromCycle)
233 continue;
234
235 CycleRef ToCycle = CI->getCycle(SuccToSinkTo);
236 // Check if there is a FromCycle that contains SgprDef's basic block but
237 // does not contain SuccToSinkTo and also has divergent exit condition.
238 while (FromCycle && !(ToCycle && CI->contains(FromCycle, ToCycle))) {
240 CI->getExitingBlocks(FromCycle, ExitingBlocks);
241
242 // FromCycle has divergent exit condition.
243 for (MachineBasicBlock *ExitingBlock : ExitingBlocks) {
244 if (hasDivergentBranch(ExitingBlock))
245 return false;
246 }
247
248 FromCycle = CI->getParentCycle(FromCycle);
249 }
250 }
251 }
252
253 return true;
254}
255
257 int64_t &Offset0,
258 int64_t &Offset1) const {
259 if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode())
260 return false;
261
262 unsigned Opc0 = Load0->getMachineOpcode();
263 unsigned Opc1 = Load1->getMachineOpcode();
264
265 // Make sure both are actually loads.
266 if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad())
267 return false;
268
269 // A mayLoad instruction without a def is not a load. Likely a prefetch.
270 if (!get(Opc0).getNumDefs() || !get(Opc1).getNumDefs())
271 return false;
272
273 if (isDS(Opc0) && isDS(Opc1)) {
274
275 // FIXME: Handle this case:
276 if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1))
277 return false;
278
279 // Check base reg.
280 if (Load0->getOperand(0) != Load1->getOperand(0))
281 return false;
282
283 // Skip read2 / write2 variants for simplicity.
284 // TODO: We should report true if the used offsets are adjacent (excluded
285 // st64 versions).
286 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
287 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
288 if (Offset0Idx == -1 || Offset1Idx == -1)
289 return false;
290
291 // XXX - be careful of dataless loads
292 // getNamedOperandIdx returns the index for MachineInstrs. Since they
293 // include the output in the operand list, but SDNodes don't, we need to
294 // subtract the index by one.
295 Offset0Idx -= get(Opc0).NumDefs;
296 Offset1Idx -= get(Opc1).NumDefs;
297 Offset0 = Load0->getConstantOperandVal(Offset0Idx);
298 Offset1 = Load1->getConstantOperandVal(Offset1Idx);
299 return true;
300 }
301
302 if (isSMRD(Opc0) && isSMRD(Opc1)) {
303 // Skip time and cache invalidation instructions.
304 if (!AMDGPU::hasNamedOperand(Opc0, AMDGPU::OpName::sbase) ||
305 !AMDGPU::hasNamedOperand(Opc1, AMDGPU::OpName::sbase))
306 return false;
307
308 unsigned NumOps = getNumOperandsNoGlue(Load0);
309 if (NumOps != getNumOperandsNoGlue(Load1))
310 return false;
311
312 // Check base reg.
313 if (Load0->getOperand(0) != Load1->getOperand(0))
314 return false;
315
316 // Match register offsets, if both register and immediate offsets present.
317 assert(NumOps == 4 || NumOps == 5);
318 if (NumOps == 5 && Load0->getOperand(1) != Load1->getOperand(1))
319 return false;
320
321 const ConstantSDNode *Load0Offset =
323 const ConstantSDNode *Load1Offset =
325
326 if (!Load0Offset || !Load1Offset)
327 return false;
328
329 Offset0 = Load0Offset->getZExtValue();
330 Offset1 = Load1Offset->getZExtValue();
331 return true;
332 }
333
334 // MUBUF and MTBUF can access the same addresses.
335 if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) {
336
337 // MUBUF and MTBUF have vaddr at different indices.
338 if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) ||
339 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) ||
340 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc))
341 return false;
342
343 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
344 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
345
346 if (OffIdx0 == -1 || OffIdx1 == -1)
347 return false;
348
349 // getNamedOperandIdx returns the index for MachineInstrs. Since they
350 // include the output in the operand list, but SDNodes don't, we need to
351 // subtract the index by one.
352 OffIdx0 -= get(Opc0).NumDefs;
353 OffIdx1 -= get(Opc1).NumDefs;
354
355 SDValue Off0 = Load0->getOperand(OffIdx0);
356 SDValue Off1 = Load1->getOperand(OffIdx1);
357
358 // The offset might be a FrameIndexSDNode.
359 if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1))
360 return false;
361
362 Offset0 = Off0->getAsZExtVal();
363 Offset1 = Off1->getAsZExtVal();
364 return true;
365 }
366
367 return false;
368}
369
370static bool isStride64(unsigned Opc) {
371 switch (Opc) {
372 case AMDGPU::DS_READ2ST64_B32:
373 case AMDGPU::DS_READ2ST64_B64:
374 case AMDGPU::DS_WRITE2ST64_B32:
375 case AMDGPU::DS_WRITE2ST64_B64:
376 return true;
377 default:
378 return false;
379 }
380}
381
384 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
385 const TargetRegisterInfo *TRI) const {
386 if (!LdSt.mayLoadOrStore())
387 return false;
388
389 unsigned Opc = LdSt.getOpcode();
390 OffsetIsScalable = false;
391 const MachineOperand *BaseOp, *OffsetOp;
392 int DataOpIdx;
393
394 if (isDS(LdSt)) {
395 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr);
396 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
397 if (OffsetOp) {
398 // Normal, single offset LDS instruction.
399 if (!BaseOp) {
400 // DS_CONSUME/DS_APPEND use M0 for the base address.
401 // TODO: find the implicit use operand for M0 and use that as BaseOp?
402 return false;
403 }
404 BaseOps.push_back(BaseOp);
405 Offset = OffsetOp->getImm();
406 // Get appropriate operand, and compute width accordingly.
407 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
408 if (DataOpIdx == -1)
409 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
410 if (Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
411 Width = LocationSize::precise(64);
412 else
413 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
414 } else {
415 // The 2 offset instructions use offset0 and offset1 instead. We can treat
416 // these as a load with a single offset if the 2 offsets are consecutive.
417 // We will use this for some partially aligned loads.
418 const MachineOperand *Offset0Op =
419 getNamedOperand(LdSt, AMDGPU::OpName::offset0);
420 const MachineOperand *Offset1Op =
421 getNamedOperand(LdSt, AMDGPU::OpName::offset1);
422
423 unsigned Offset0 = Offset0Op->getImm() & 0xff;
424 unsigned Offset1 = Offset1Op->getImm() & 0xff;
425 if (Offset0 + 1 != Offset1)
426 return false;
427
428 // Each of these offsets is in element sized units, so we need to convert
429 // to bytes of the individual reads.
430
431 unsigned EltSize;
432 if (LdSt.mayLoad())
433 EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16;
434 else {
435 assert(LdSt.mayStore());
436 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
437 EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8;
438 }
439
440 if (isStride64(Opc))
441 EltSize *= 64;
442
443 BaseOps.push_back(BaseOp);
444 Offset = EltSize * Offset0;
445 // Get appropriate operand(s), and compute width accordingly.
446 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
447 if (DataOpIdx == -1) {
448 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
449 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
450 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
451 Width = LocationSize::precise(
452 Width.getValue() + TypeSize::getFixed(getOpSize(LdSt, DataOpIdx)));
453 } else {
454 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
455 }
456 }
457 return true;
458 }
459
460 if (isMUBUF(LdSt) || isMTBUF(LdSt)) {
461 const MachineOperand *RSrc = getNamedOperand(LdSt, AMDGPU::OpName::srsrc);
462 if (!RSrc) // e.g. BUFFER_WBINVL1_VOL
463 return false;
464 BaseOps.push_back(RSrc);
465 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
466 if (BaseOp && !BaseOp->isFI())
467 BaseOps.push_back(BaseOp);
468 const MachineOperand *OffsetImm =
469 getNamedOperand(LdSt, AMDGPU::OpName::offset);
470 Offset = OffsetImm->getImm();
471 const MachineOperand *SOffset =
472 getNamedOperand(LdSt, AMDGPU::OpName::soffset);
473 if (SOffset) {
474 if (SOffset->isReg())
475 BaseOps.push_back(SOffset);
476 else
477 Offset += SOffset->getImm();
478 }
479 // Get appropriate operand, and compute width accordingly.
480 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
481 if (DataOpIdx == -1)
482 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
483 if (DataOpIdx == -1) // LDS DMA
484 return false;
485 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
486 return true;
487 }
488
489 if (isImage(LdSt)) {
490 auto RsrcOpName =
491 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
492 int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RsrcOpName);
493 BaseOps.push_back(&LdSt.getOperand(SRsrcIdx));
494 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
495 if (VAddr0Idx >= 0) {
496 // GFX10 possible NSA encoding.
497 for (int I = VAddr0Idx; I < SRsrcIdx; ++I)
498 BaseOps.push_back(&LdSt.getOperand(I));
499 } else {
500 BaseOps.push_back(getNamedOperand(LdSt, AMDGPU::OpName::vaddr));
501 }
502 Offset = 0;
503 // Get appropriate operand, and compute width accordingly.
504 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
505 if (DataOpIdx == -1)
506 return false; // no return sampler
507 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
508 return true;
509 }
510
511 if (isSMRD(LdSt)) {
512 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::sbase);
513 if (!BaseOp) // e.g. S_MEMTIME
514 return false;
515 BaseOps.push_back(BaseOp);
516 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
517 Offset = OffsetOp ? OffsetOp->getImm() : 0;
518 // Get appropriate operand, and compute width accordingly.
519 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
520 if (DataOpIdx == -1)
521 return false;
522 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
523 return true;
524 }
525
526 if (isFLAT(LdSt)) {
527 // Instructions have either vaddr or saddr or both or none.
528 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
529 if (BaseOp)
530 BaseOps.push_back(BaseOp);
531 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr);
532 if (BaseOp)
533 BaseOps.push_back(BaseOp);
534 Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm();
535 // Get appropriate operand, and compute width accordingly.
536 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
537 if (DataOpIdx == -1)
538 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
539 if (DataOpIdx == -1) // LDS DMA
540 return false;
541 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
542 return true;
543 }
544
545 return false;
546}
547
548static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
550 const MachineInstr &MI2,
552 // Only examine the first "base" operand of each instruction, on the
553 // assumption that it represents the real base address of the memory access.
554 // Other operands are typically offsets or indices from this base address.
555 if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
556 return true;
557
558 if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
559 return false;
560
561 auto *MO1 = *MI1.memoperands_begin();
562 auto *MO2 = *MI2.memoperands_begin();
563 if (MO1->getAddrSpace() != MO2->getAddrSpace())
564 return false;
565
566 const auto *Base1 = MO1->getValue();
567 const auto *Base2 = MO2->getValue();
568 if (!Base1 || !Base2)
569 return false;
570 Base1 = getUnderlyingObject(Base1);
571 Base2 = getUnderlyingObject(Base2);
572
573 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
574 return false;
575
576 return Base1 == Base2;
577}
578
580 int64_t Offset1, bool OffsetIsScalable1,
582 int64_t Offset2, bool OffsetIsScalable2,
583 unsigned ClusterSize,
584 unsigned NumBytes) const {
585 // If the mem ops (to be clustered) do not have the same base ptr, then they
586 // should not be clustered
587 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;
588 if (!BaseOps1.empty() && !BaseOps2.empty()) {
589 const MachineInstr &FirstLdSt = *BaseOps1.front()->getParent();
590 const MachineInstr &SecondLdSt = *BaseOps2.front()->getParent();
591 if (!memOpsHaveSameBasePtr(FirstLdSt, BaseOps1, SecondLdSt, BaseOps2))
592 return false;
593
594 const SIMachineFunctionInfo *MFI =
595 FirstLdSt.getMF()->getInfo<SIMachineFunctionInfo>();
596 MaxMemoryClusterDWords = MFI->getMaxMemoryClusterDWords();
597 } else if (!BaseOps1.empty() || !BaseOps2.empty()) {
598 // If only one base op is empty, they do not have the same base ptr
599 return false;
600 }
601
602 // In order to avoid register pressure, on an average, the number of DWORDS
603 // loaded together by all clustered mem ops should not exceed
604 // MaxMemoryClusterDWords. This is an empirical value based on certain
605 // observations and performance related experiments.
606 // The good thing about this heuristic is - it avoids clustering of too many
607 // sub-word loads, and also avoids clustering of wide loads. Below is the
608 // brief summary of how the heuristic behaves for various `LoadSize` when
609 // MaxMemoryClusterDWords is 8.
610 //
611 // (1) 1 <= LoadSize <= 4: cluster at max 8 mem ops
612 // (2) 5 <= LoadSize <= 8: cluster at max 4 mem ops
613 // (3) 9 <= LoadSize <= 12: cluster at max 2 mem ops
614 // (4) 13 <= LoadSize <= 16: cluster at max 2 mem ops
615 // (5) LoadSize >= 17: do not cluster
616 const unsigned LoadSize = NumBytes / ClusterSize;
617 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
618 return NumDWords <= MaxMemoryClusterDWords;
619}
620
621// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
622// the first 16 loads will be interleaved with the stores, and the next 16 will
623// be clustered as expected. It should really split into 2 16 store batches.
624//
625// Loads are clustered until this returns false, rather than trying to schedule
626// groups of stores. This also means we have to deal with saying different
627// address space loads should be clustered, and ones which might cause bank
628// conflicts.
629//
630// This might be deprecated so it might not be worth that much effort to fix.
632 int64_t Offset0, int64_t Offset1,
633 unsigned NumLoads) const {
634 assert(Offset1 > Offset0 &&
635 "Second offset should be larger than first offset!");
636 // If we have less than 16 loads in a row, and the offsets are within 64
637 // bytes, then schedule together.
638
639 // A cacheline is 64 bytes (for global memory).
640 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
641}
642
645 const DebugLoc &DL, MCRegister DestReg,
646 MCRegister SrcReg, bool KillSrc,
647 const char *Msg = "illegal VGPR to SGPR copy") {
648 MachineFunction *MF = MBB.getParent();
649
652
653 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg)
654 .addReg(SrcReg, getKillRegState(KillSrc));
655}
656
657/// Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908. It is not
658/// possible to have a direct copy in these cases on GFX908, so an intermediate
659/// VGPR copy is required.
662 const DebugLoc &DL, MCRegister DestReg,
663 MCRegister SrcReg, bool KillSrc,
664 RegScavenger &RS, bool RegsOverlap,
665 Register ImpUseSuperReg = Register()) {
666 assert((TII.getSubtarget().hasMAIInsts() &&
667 !TII.getSubtarget().hasGFX90AInsts()) &&
668 "Expected GFX908 subtarget.");
669
670 assert((AMDGPU::SReg_32RegClass.contains(SrcReg) ||
671 AMDGPU::AGPR_32RegClass.contains(SrcReg)) &&
672 "Source register of the copy should be either an SGPR or an AGPR.");
673
674 assert(AMDGPU::AGPR_32RegClass.contains(DestReg) &&
675 "Destination register of the copy should be an AGPR.");
676
677 const SIRegisterInfo &RI = TII.getRegisterInfo();
678
679 // First try to find defining accvgpr_write to avoid temporary registers.
680 // In the case of copies of overlapping AGPRs, we conservatively do not
681 // reuse previous accvgpr_writes. Otherwise, we may incorrectly pick up
682 // an accvgpr_write used for this same copy due to implicit-defs
683 if (!RegsOverlap) {
684 for (auto Def = MI, E = MBB.begin(); Def != E; ) {
685 --Def;
686
687 if (!Def->modifiesRegister(SrcReg, &RI))
688 continue;
689
690 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
691 Def->getOperand(0).getReg() != SrcReg)
692 break;
693
694 MachineOperand &DefOp = Def->getOperand(1);
695 assert(DefOp.isReg() || DefOp.isImm());
696
697 if (DefOp.isReg()) {
698 bool SafeToPropagate = true;
699 // Check that register source operand is not clobbered before MI.
700 // Immediate operands are always safe to propagate.
701 for (auto I = Def; I != MI && SafeToPropagate; ++I)
702 if (I->modifiesRegister(DefOp.getReg(), &RI))
703 SafeToPropagate = false;
704
705 if (!SafeToPropagate)
706 break;
707
708 for (auto I = Def; I != MI; ++I)
709 I->clearRegisterKills(DefOp.getReg(), &RI);
710 }
711
712 MachineInstrBuilder Builder =
713 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64),
714 DestReg)
715 .add(DefOp);
716
717 if (ImpUseSuperReg) {
718 Builder.addReg(ImpUseSuperReg,
720 }
721
722 return;
723 }
724 }
725
726 RS.enterBasicBlockEnd(MBB);
727 RS.backward(std::next(MI));
728
729 // Ideally we want to have three registers for a long reg_sequence copy
730 // to hide 2 waitstates between v_mov_b32 and accvgpr_write.
731 unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass,
732 *MBB.getParent());
733
734 // Registers in the sequence are allocated contiguously so we can just
735 // use register number to pick one of three round-robin temps.
736 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
737 Register Tmp =
738 MBB.getParent()->getInfo<SIMachineFunctionInfo>()->getVGPRForAGPRCopy();
739 assert(MBB.getParent()->getRegInfo().isReserved(Tmp) &&
740 "VGPR used for an intermediate copy should have been reserved.");
741
742 // Only loop through if there are any free registers left. We don't want to
743 // spill.
744 while (RegNo--) {
745 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI,
746 /* RestoreAfter */ false, 0,
747 /* AllowSpill */ false);
748 if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs)
749 break;
750 Tmp = Tmp2;
751 RS.setRegUsed(Tmp);
752 }
753
754 // Insert copy to temporary VGPR.
755 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
756 if (AMDGPU::AGPR_32RegClass.contains(SrcReg)) {
757 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
758 } else {
759 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
760 }
761
762 MachineInstrBuilder UseBuilder = BuildMI(MBB, MI, DL, TII.get(TmpCopyOp), Tmp)
763 .addReg(SrcReg, getKillRegState(KillSrc));
764 if (ImpUseSuperReg) {
765 UseBuilder.addReg(ImpUseSuperReg,
767 }
768
769 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
770 .addReg(Tmp, RegState::Kill);
771}
772
775 MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
776 const TargetRegisterClass *RC, bool Forward) {
777 const SIRegisterInfo &RI = TII.getRegisterInfo();
778 ArrayRef<int16_t> BaseIndices = RI.getRegSplitParts(RC, 4);
780 MachineInstr *FirstMI = nullptr, *LastMI = nullptr;
781
782 for (unsigned Idx = 0; Idx < BaseIndices.size(); ++Idx) {
783 int16_t SubIdx = BaseIndices[Idx];
784 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
785 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
786 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
787 unsigned Opcode = AMDGPU::S_MOV_B32;
788
789 // Is SGPR aligned? If so try to combine with next.
790 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
791 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
792 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.size())) {
793 // Can use SGPR64 copy
794 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
795 SubIdx = RI.getSubRegFromChannel(Channel, 2);
796 DestSubReg = RI.getSubReg(DestReg, SubIdx);
797 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
798 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
799 Opcode = AMDGPU::S_MOV_B64;
800 Idx++;
801 }
802
803 LastMI = BuildMI(MBB, I, DL, TII.get(Opcode), DestSubReg)
804 .addReg(SrcSubReg)
805 .addReg(SrcReg, RegState::Implicit);
806
807 if (!FirstMI)
808 FirstMI = LastMI;
809
810 if (!Forward)
811 I--;
812 }
813
814 assert(FirstMI && LastMI);
815 if (!Forward)
816 std::swap(FirstMI, LastMI);
817
818 if (KillSrc)
819 LastMI->addRegisterKilled(SrcReg, &RI);
820}
821
824 const DebugLoc &DL, Register DestReg,
825 Register SrcReg, bool KillSrc, bool RenamableDest,
826 bool RenamableSrc) const {
827 const TargetRegisterClass *RC = RI.getPhysRegBaseClass(DestReg);
828 unsigned Size = RI.getRegSizeInBits(*RC);
829 const TargetRegisterClass *SrcRC = RI.getPhysRegBaseClass(SrcReg);
830 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
831
832 // The rest of copyPhysReg assumes Src and Dst size are the same size.
833 // TODO-GFX11_16BIT If all true 16 bit instruction patterns are completed can
834 // we remove Fix16BitCopies and this code block?
835 if (Fix16BitCopies) {
836 if (((Size == 16) != (SrcSize == 16))) {
837 // Non-VGPR Src and Dst will later be expanded back to 32 bits.
838 assert(ST.useRealTrue16Insts());
839 Register &RegToFix = (Size == 32) ? DestReg : SrcReg;
840 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
841 RegToFix = SubReg;
842
843 if (DestReg == SrcReg) {
844 // Identity copy. Insert empty bundle since ExpandPostRA expects an
845 // instruction here.
846 BuildMI(MBB, MI, DL, get(AMDGPU::BUNDLE));
847 return;
848 }
849 RC = RI.getPhysRegBaseClass(DestReg);
850 Size = RI.getRegSizeInBits(*RC);
851 SrcRC = RI.getPhysRegBaseClass(SrcReg);
852 SrcSize = RI.getRegSizeInBits(*SrcRC);
853 }
854 }
855
856 if (RC == &AMDGPU::VGPR_32RegClass) {
857 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
858 AMDGPU::SReg_32RegClass.contains(SrcReg) ||
859 AMDGPU::AGPR_32RegClass.contains(SrcReg));
860 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
861 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
862 BuildMI(MBB, MI, DL, get(Opc), DestReg)
863 .addReg(SrcReg, getKillRegState(KillSrc));
864 return;
865 }
866
867 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
868 RC == &AMDGPU::SReg_32RegClass) {
869 if (SrcReg == AMDGPU::SCC) {
870 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg)
871 .addImm(1)
872 .addImm(0);
873 return;
874 }
875
876 if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) {
877 if (DestReg == AMDGPU::VCC_LO) {
878 // FIXME: Hack until VReg_1 removed.
879 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
880 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
881 .addImm(0)
882 .addReg(SrcReg, getKillRegState(KillSrc));
883 return;
884 }
885
886 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
887 return;
888 }
889
890 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
891 .addReg(SrcReg, getKillRegState(KillSrc));
892 return;
893 }
894
895 if (RC == &AMDGPU::SReg_64RegClass) {
896 if (SrcReg == AMDGPU::SCC) {
897 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B64), DestReg)
898 .addImm(1)
899 .addImm(0);
900 return;
901 }
902
903 if (!AMDGPU::SReg_64_EncodableRegClass.contains(SrcReg)) {
904 if (DestReg == AMDGPU::VCC) {
905 // FIXME: Hack until VReg_1 removed.
906 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
907 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
908 .addImm(0)
909 .addReg(SrcReg, getKillRegState(KillSrc));
910 return;
911 }
912
913 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
914 return;
915 }
916
917 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
918 .addReg(SrcReg, getKillRegState(KillSrc));
919 return;
920 }
921
922 if (DestReg == AMDGPU::SCC) {
923 // Copying 64-bit or 32-bit sources to SCC barely makes sense,
924 // but SelectionDAG emits such copies for i1 sources.
925 if (AMDGPU::SReg_64RegClass.contains(SrcReg)) {
926 // This copy can only be produced by patterns
927 // with explicit SCC, which are known to be enabled
928 // only for subtargets with S_CMP_LG_U64 present.
929 assert(ST.hasScalarCompareEq64());
930 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U64))
931 .addReg(SrcReg, getKillRegState(KillSrc))
932 .addImm(0);
933 } else {
934 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
935 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32))
936 .addReg(SrcReg, getKillRegState(KillSrc))
937 .addImm(0);
938 }
939
940 return;
941 }
942
943 if (RC == &AMDGPU::AGPR_32RegClass) {
944 if (AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
945 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
946 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
947 .addReg(SrcReg, getKillRegState(KillSrc));
948 return;
949 }
950
951 if (AMDGPU::AGPR_32RegClass.contains(SrcReg) && ST.hasGFX90AInsts()) {
952 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_MOV_B32), DestReg)
953 .addReg(SrcReg, getKillRegState(KillSrc));
954 return;
955 }
956
957 // FIXME: Pass should maintain scavenger to avoid scan through the block on
958 // every AGPR spill.
959 RegScavenger RS;
960 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
961 indirectCopyToAGPR(*this, MBB, MI, DL, DestReg, SrcReg, KillSrc, RS, Overlap);
962 return;
963 }
964
965 if (Size == 16) {
966 assert(AMDGPU::VGPR_16RegClass.contains(SrcReg) ||
967 AMDGPU::SReg_LO16RegClass.contains(SrcReg) ||
968 AMDGPU::AGPR_LO16RegClass.contains(SrcReg));
969
970 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
971 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
972 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
973 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
974 bool DstLow = !AMDGPU::isHi16Reg(DestReg, RI);
975 bool SrcLow = !AMDGPU::isHi16Reg(SrcReg, RI);
976 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
977 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
978
979 if (IsSGPRDst) {
980 if (!IsSGPRSrc) {
981 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
982 return;
983 }
984
985 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), NewDestReg)
986 .addReg(NewSrcReg, getKillRegState(KillSrc));
987 return;
988 }
989
990 if (IsAGPRDst || IsAGPRSrc) {
991 if (!DstLow || !SrcLow) {
992 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
993 "Cannot use hi16 subreg with an AGPR!");
994 }
995
996 copyPhysReg(MBB, MI, DL, NewDestReg, NewSrcReg, KillSrc);
997 return;
998 }
999
1000 if (ST.useRealTrue16Insts()) {
1001 if (IsSGPRSrc) {
1002 assert(SrcLow);
1003 SrcReg = NewSrcReg;
1004 }
1005 // Use the smaller instruction encoding if possible.
1006 if (AMDGPU::VGPR_16_Lo128RegClass.contains(DestReg) &&
1007 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.contains(SrcReg))) {
1008 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e32), DestReg)
1009 .addReg(SrcReg);
1010 } else {
1011 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e64), DestReg)
1012 .addImm(0) // src0_modifiers
1013 .addReg(SrcReg)
1014 .addImm(0); // op_sel
1015 }
1016 return;
1017 }
1018
1019 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1020 if (!DstLow || !SrcLow) {
1021 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
1022 "Cannot use hi16 subreg on VI!");
1023 }
1024
1025 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), NewDestReg)
1026 .addReg(NewSrcReg, getKillRegState(KillSrc));
1027 return;
1028 }
1029
1030 auto MIB = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_sdwa), NewDestReg)
1031 .addImm(0) // src0_modifiers
1032 .addReg(NewSrcReg)
1033 .addImm(0) // clamp
1040 // First implicit operand is $exec.
1041 MIB->tieOperands(0, MIB->getNumOperands() - 1);
1042 return;
1043 }
1044
1045 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1046 if (ST.hasVMovB64Inst()) {
1047 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_e32), DestReg)
1048 .addReg(SrcReg, getKillRegState(KillSrc));
1049 return;
1050 }
1051 if (ST.hasPkMovB32()) {
1052 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestReg)
1054 .addReg(SrcReg)
1056 .addReg(SrcReg)
1057 .addImm(0) // op_sel_lo
1058 .addImm(0) // op_sel_hi
1059 .addImm(0) // neg_lo
1060 .addImm(0) // neg_hi
1061 .addImm(0) // clamp
1062 .addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
1063 return;
1064 }
1065 }
1066
1067 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1068 if (RI.isSGPRClass(RC)) {
1069 if (!RI.isSGPRClass(SrcRC)) {
1070 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1071 return;
1072 }
1073 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1074 expandSGPRCopy(*this, MBB, MI, DL, DestReg, SrcReg, CanKillSuperReg, RC,
1075 Forward);
1076 return;
1077 }
1078
1079 unsigned EltSize = 4;
1080 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1081 if (RI.isAGPRClass(RC)) {
1082 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1083 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1084 else if (RI.hasVGPRs(SrcRC) ||
1085 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1086 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1087 else
1088 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1089 } else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1090 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1091 } else if ((Size % 64 == 0) && RI.hasVGPRs(RC) &&
1092 (RI.isProperlyAlignedRC(*RC) &&
1093 (SrcRC == RC || RI.isSGPRClass(SrcRC)))) {
1094 // TODO: In 96-bit case, could do a 64-bit mov and then a 32-bit mov.
1095 if (ST.hasVMovB64Inst()) {
1096 Opcode = AMDGPU::V_MOV_B64_e32;
1097 EltSize = 8;
1098 } else if (ST.hasPkMovB32()) {
1099 Opcode = AMDGPU::V_PK_MOV_B32;
1100 EltSize = 8;
1101 }
1102 }
1103
1104 // For the cases where we need an intermediate instruction/temporary register
1105 // (destination is an AGPR), we need a scavenger.
1106 //
1107 // FIXME: The pass should maintain this for us so we don't have to re-scan the
1108 // whole block for every handled copy.
1109 std::unique_ptr<RegScavenger> RS;
1110 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1111 RS = std::make_unique<RegScavenger>();
1112
1113 ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, EltSize);
1114
1115 // If there is an overlap, we can't kill the super-register on the last
1116 // instruction, since it will also kill the components made live by this def.
1117 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1118 const bool CanKillSuperReg = KillSrc && !Overlap;
1119
1120 for (unsigned Idx = 0; Idx < SubIndices.size(); ++Idx) {
1121 unsigned SubIdx;
1122 if (Forward)
1123 SubIdx = SubIndices[Idx];
1124 else
1125 SubIdx = SubIndices[SubIndices.size() - Idx - 1];
1126 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1127 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1128 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
1129
1130 bool UseKill = CanKillSuperReg && Idx == SubIndices.size() - 1;
1131
1132 if (Opcode == AMDGPU::INSTRUCTION_LIST_END) {
1133 Register ImpUseSuper = SrcReg;
1134 indirectCopyToAGPR(*this, MBB, MI, DL, DestSubReg, SrcSubReg, UseKill,
1135 *RS, Overlap, ImpUseSuper);
1136 } else if (Opcode == AMDGPU::V_PK_MOV_B32) {
1137 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestSubReg)
1139 .addReg(SrcSubReg)
1141 .addReg(SrcSubReg)
1142 .addImm(0) // op_sel_lo
1143 .addImm(0) // op_sel_hi
1144 .addImm(0) // neg_lo
1145 .addImm(0) // neg_hi
1146 .addImm(0) // clamp
1147 .addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1148 } else {
1149 MachineInstrBuilder Builder =
1150 BuildMI(MBB, MI, DL, get(Opcode), DestSubReg).addReg(SrcSubReg);
1151
1152 Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1153 }
1154 }
1155}
1156
1157int SIInstrInfo::commuteOpcode(unsigned Opcode) const {
1158 int32_t NewOpc;
1159
1160 // Try to map original to commuted opcode
1161 NewOpc = AMDGPU::getCommuteRev(Opcode);
1162 if (NewOpc != -1)
1163 // Check if the commuted (REV) opcode exists on the target.
1164 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1165
1166 // Try to map commuted to original opcode
1167 NewOpc = AMDGPU::getCommuteOrig(Opcode);
1168 if (NewOpc != -1)
1169 // Check if the original (non-REV) opcode exists on the target.
1170 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1171
1172 return Opcode;
1173}
1174
1176 const Register Reg,
1177 int64_t &ImmVal) const {
1178 switch (MI.getOpcode()) {
1179 case AMDGPU::V_MOV_B32_e32:
1180 case AMDGPU::S_MOV_B32:
1181 case AMDGPU::S_MOVK_I32:
1182 case AMDGPU::S_MOV_B64:
1183 case AMDGPU::V_MOV_B64_e32:
1184 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1185 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1186 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1187 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1188 case AMDGPU::V_MOV_B64_PSEUDO:
1189 case AMDGPU::V_MOV_B16_t16_e32: {
1190 const MachineOperand &Src0 = MI.getOperand(1);
1191 if (Src0.isImm()) {
1192 ImmVal = Src0.getImm();
1193 return MI.getOperand(0).getReg() == Reg;
1194 }
1195
1196 return false;
1197 }
1198 case AMDGPU::V_MOV_B16_t16_e64: {
1199 const MachineOperand &Src0 = MI.getOperand(2);
1200 if (Src0.isImm() && !MI.getOperand(1).getImm()) {
1201 ImmVal = Src0.getImm();
1202 return MI.getOperand(0).getReg() == Reg;
1203 }
1204
1205 return false;
1206 }
1207 case AMDGPU::S_BREV_B32:
1208 case AMDGPU::V_BFREV_B32_e32:
1209 case AMDGPU::V_BFREV_B32_e64: {
1210 const MachineOperand &Src0 = MI.getOperand(1);
1211 if (Src0.isImm()) {
1212 ImmVal = static_cast<int64_t>(reverseBits<int32_t>(Src0.getImm()));
1213 return MI.getOperand(0).getReg() == Reg;
1214 }
1215
1216 return false;
1217 }
1218 case AMDGPU::S_NOT_B32:
1219 case AMDGPU::V_NOT_B32_e32:
1220 case AMDGPU::V_NOT_B32_e64: {
1221 const MachineOperand &Src0 = MI.getOperand(1);
1222 if (Src0.isImm()) {
1223 ImmVal = static_cast<int64_t>(~static_cast<int32_t>(Src0.getImm()));
1224 return MI.getOperand(0).getReg() == Reg;
1225 }
1226
1227 return false;
1228 }
1229 default:
1230 return false;
1231 }
1232}
1233
1234std::optional<int64_t>
1236 if (Op.isImm())
1237 return Op.getImm();
1238
1239 if (!Op.isReg() || !Op.getReg().isVirtual())
1240 return std::nullopt;
1241 MachineRegisterInfo &MRI = Op.getParent()->getMF()->getRegInfo();
1242 const MachineInstr *Def = MRI.getVRegDef(Op.getReg());
1243 if (Def && Def->isMoveImmediate()) {
1244 const MachineOperand &ImmSrc = Def->getOperand(1);
1245 if (ImmSrc.isImm())
1246 return extractSubregFromImm(ImmSrc.getImm(), Op.getSubReg());
1247 }
1248
1249 return std::nullopt;
1250}
1251
1253
1254 if (RI.isAGPRClass(DstRC))
1255 return AMDGPU::COPY;
1256 if (RI.getRegSizeInBits(*DstRC) == 16) {
1257 // Assume hi bits are unneeded. Only _e64 true16 instructions are legal
1258 // before RA.
1259 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1260 }
1261 if (RI.getRegSizeInBits(*DstRC) == 32)
1262 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1263 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1264 return AMDGPU::S_MOV_B64;
1265 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1266 return AMDGPU::V_MOV_B64_PSEUDO;
1267 return AMDGPU::COPY;
1268}
1269
1270const MCInstrDesc &
1272 bool IsIndirectSrc) const {
1273 if (IsIndirectSrc) {
1274 if (VecSize <= 32) // 4 bytes
1275 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1276 if (VecSize <= 64) // 8 bytes
1277 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1278 if (VecSize <= 96) // 12 bytes
1279 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1280 if (VecSize <= 128) // 16 bytes
1281 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1282 if (VecSize <= 160) // 20 bytes
1283 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1284 if (VecSize <= 192) // 24 bytes
1285 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1286 if (VecSize <= 224) // 28 bytes
1287 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1288 if (VecSize <= 256) // 32 bytes
1289 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1290 if (VecSize <= 288) // 36 bytes
1291 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1292 if (VecSize <= 320) // 40 bytes
1293 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1294 if (VecSize <= 352) // 44 bytes
1295 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1296 if (VecSize <= 384) // 48 bytes
1297 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1298 if (VecSize <= 512) // 64 bytes
1299 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1300 if (VecSize <= 1024) // 128 bytes
1301 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1302
1303 llvm_unreachable("unsupported size for IndirectRegReadGPRIDX pseudos");
1304 }
1305
1306 if (VecSize <= 32) // 4 bytes
1307 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1308 if (VecSize <= 64) // 8 bytes
1309 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1310 if (VecSize <= 96) // 12 bytes
1311 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1312 if (VecSize <= 128) // 16 bytes
1313 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1314 if (VecSize <= 160) // 20 bytes
1315 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1316 if (VecSize <= 192) // 24 bytes
1317 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1318 if (VecSize <= 224) // 28 bytes
1319 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1320 if (VecSize <= 256) // 32 bytes
1321 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1322 if (VecSize <= 288) // 36 bytes
1323 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1324 if (VecSize <= 320) // 40 bytes
1325 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1326 if (VecSize <= 352) // 44 bytes
1327 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1328 if (VecSize <= 384) // 48 bytes
1329 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1330 if (VecSize <= 512) // 64 bytes
1331 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1332 if (VecSize <= 1024) // 128 bytes
1333 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1334
1335 llvm_unreachable("unsupported size for IndirectRegWriteGPRIDX pseudos");
1336}
1337
1338static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize) {
1339 if (VecSize <= 32) // 4 bytes
1340 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1341 if (VecSize <= 64) // 8 bytes
1342 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1343 if (VecSize <= 96) // 12 bytes
1344 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1345 if (VecSize <= 128) // 16 bytes
1346 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1347 if (VecSize <= 160) // 20 bytes
1348 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1349 if (VecSize <= 192) // 24 bytes
1350 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1351 if (VecSize <= 224) // 28 bytes
1352 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1353 if (VecSize <= 256) // 32 bytes
1354 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1355 if (VecSize <= 288) // 36 bytes
1356 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1357 if (VecSize <= 320) // 40 bytes
1358 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1359 if (VecSize <= 352) // 44 bytes
1360 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1361 if (VecSize <= 384) // 48 bytes
1362 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1363 if (VecSize <= 512) // 64 bytes
1364 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1365 if (VecSize <= 1024) // 128 bytes
1366 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1367
1368 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1369}
1370
1371static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize) {
1372 if (VecSize <= 32) // 4 bytes
1373 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1374 if (VecSize <= 64) // 8 bytes
1375 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1376 if (VecSize <= 96) // 12 bytes
1377 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1378 if (VecSize <= 128) // 16 bytes
1379 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1380 if (VecSize <= 160) // 20 bytes
1381 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1382 if (VecSize <= 192) // 24 bytes
1383 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1384 if (VecSize <= 224) // 28 bytes
1385 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1386 if (VecSize <= 256) // 32 bytes
1387 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1388 if (VecSize <= 288) // 36 bytes
1389 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1390 if (VecSize <= 320) // 40 bytes
1391 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1392 if (VecSize <= 352) // 44 bytes
1393 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1394 if (VecSize <= 384) // 48 bytes
1395 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1396 if (VecSize <= 512) // 64 bytes
1397 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1398 if (VecSize <= 1024) // 128 bytes
1399 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1400
1401 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1402}
1403
1404static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize) {
1405 if (VecSize <= 64) // 8 bytes
1406 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1407 if (VecSize <= 128) // 16 bytes
1408 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1409 if (VecSize <= 256) // 32 bytes
1410 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1411 if (VecSize <= 512) // 64 bytes
1412 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1413 if (VecSize <= 1024) // 128 bytes
1414 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1415
1416 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1417}
1418
1419const MCInstrDesc &
1420SIInstrInfo::getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize,
1421 bool IsSGPR) const {
1422 if (IsSGPR) {
1423 switch (EltSize) {
1424 case 32:
1425 return get(getIndirectSGPRWriteMovRelPseudo32(VecSize));
1426 case 64:
1427 return get(getIndirectSGPRWriteMovRelPseudo64(VecSize));
1428 default:
1429 llvm_unreachable("invalid reg indexing elt size");
1430 }
1431 }
1432
1433 assert(EltSize == 32 && "invalid reg indexing elt size");
1435}
1436
1437static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1438 switch (Size) {
1439 case 4:
1440 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1441 case 8:
1442 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1443 case 12:
1444 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1445 case 16:
1446 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1447 : AMDGPU::SI_SPILL_S128_SAVE;
1448 case 20:
1449 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1450 : AMDGPU::SI_SPILL_S160_SAVE;
1451 case 24:
1452 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1453 : AMDGPU::SI_SPILL_S192_SAVE;
1454 case 28:
1455 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1456 : AMDGPU::SI_SPILL_S224_SAVE;
1457 case 32:
1458 return AMDGPU::SI_SPILL_S256_SAVE;
1459 case 36:
1460 return AMDGPU::SI_SPILL_S288_SAVE;
1461 case 40:
1462 return AMDGPU::SI_SPILL_S320_SAVE;
1463 case 44:
1464 return AMDGPU::SI_SPILL_S352_SAVE;
1465 case 48:
1466 return AMDGPU::SI_SPILL_S384_SAVE;
1467 case 64:
1468 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1469 : AMDGPU::SI_SPILL_S512_SAVE;
1470 case 128:
1471 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1472 : AMDGPU::SI_SPILL_S1024_SAVE;
1473 default:
1474 llvm_unreachable("unknown register size");
1475 }
1476}
1477
1478static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1479 switch (Size) {
1480 case 2:
1481 return AMDGPU::SI_SPILL_V16_SAVE;
1482 case 4:
1483 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1484 case 8:
1485 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1486 case 12:
1487 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1488 case 16:
1489 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1490 : AMDGPU::SI_SPILL_V128_SAVE;
1491 case 20:
1492 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1493 : AMDGPU::SI_SPILL_V160_SAVE;
1494 case 24:
1495 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1496 : AMDGPU::SI_SPILL_V192_SAVE;
1497 case 28:
1498 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1499 : AMDGPU::SI_SPILL_V224_SAVE;
1500 case 32:
1501 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1502 : AMDGPU::SI_SPILL_V256_SAVE;
1503 case 36:
1504 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1505 : AMDGPU::SI_SPILL_V288_SAVE;
1506 case 40:
1507 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1508 : AMDGPU::SI_SPILL_V320_SAVE;
1509 case 44:
1510 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1511 : AMDGPU::SI_SPILL_V352_SAVE;
1512 case 48:
1513 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1514 : AMDGPU::SI_SPILL_V384_SAVE;
1515 case 64:
1516 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1517 : AMDGPU::SI_SPILL_V512_SAVE;
1518 case 128:
1519 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1520 : AMDGPU::SI_SPILL_V1024_SAVE;
1521 default:
1522 llvm_unreachable("unknown register size");
1523 }
1524}
1525
1526static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1527 switch (Size) {
1528 case 4:
1529 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1530 : AMDGPU::SI_SPILL_AV32_SAVE;
1531 case 8:
1532 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1533 : AMDGPU::SI_SPILL_AV64_SAVE;
1534 case 12:
1535 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1536 : AMDGPU::SI_SPILL_AV96_SAVE;
1537 case 16:
1538 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1539 : AMDGPU::SI_SPILL_AV128_SAVE;
1540 case 20:
1541 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1542 : AMDGPU::SI_SPILL_AV160_SAVE;
1543 case 24:
1544 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1545 : AMDGPU::SI_SPILL_AV192_SAVE;
1546 case 28:
1547 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1548 : AMDGPU::SI_SPILL_AV224_SAVE;
1549 case 32:
1550 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1551 : AMDGPU::SI_SPILL_AV256_SAVE;
1552 case 36:
1553 return AMDGPU::SI_SPILL_AV288_SAVE;
1554 case 40:
1555 return AMDGPU::SI_SPILL_AV320_SAVE;
1556 case 44:
1557 return AMDGPU::SI_SPILL_AV352_SAVE;
1558 case 48:
1559 return AMDGPU::SI_SPILL_AV384_SAVE;
1560 case 64:
1561 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1562 : AMDGPU::SI_SPILL_AV512_SAVE;
1563 case 128:
1564 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1565 : AMDGPU::SI_SPILL_AV1024_SAVE;
1566 default:
1567 llvm_unreachable("unknown register size");
1568 }
1569}
1570
1571static unsigned getWWMRegSpillSaveOpcode(unsigned Size,
1572 bool IsVectorSuperClass) {
1573 // Currently, there is only 32-bit WWM register spills needed.
1574 if (Size != 4)
1575 llvm_unreachable("unknown wwm register spill size");
1576
1577 if (IsVectorSuperClass)
1578 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1579
1580 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1581}
1582
1584 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1585 const SIMachineFunctionInfo &MFI, bool NeedsCFI) const {
1586 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1587
1588 // Choose the right opcode if spilling a WWM register.
1590 return getWWMRegSpillSaveOpcode(Size, IsVectorSuperClass);
1591
1592 // TODO: Check if AGPRs are available
1593 if (ST.hasMAIInsts())
1594 return getAVSpillSaveOpcode(Size, NeedsCFI);
1595
1596 return getVGPRSpillSaveOpcode(Size, NeedsCFI);
1597}
1598
1599void SIInstrInfo::storeRegToStackSlotImpl(
1601 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1602 MachineInstr::MIFlag Flags, bool NeedsCFI) const {
1603 MachineFunction *MF = MBB.getParent();
1605 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1606 const DebugLoc &DL = MBB.findDebugLoc(MI);
1607
1608 MachinePointerInfo PtrInfo
1609 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1611 PtrInfo, MachineMemOperand::MOStore, FrameInfo.getObjectSize(FrameIndex),
1612 FrameInfo.getObjectAlign(FrameIndex));
1613 unsigned SpillSize = RI.getSpillSize(*RC);
1614
1615 MachineRegisterInfo &MRI = MF->getRegInfo();
1616 if (RI.isSGPRClass(RC)) {
1617 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1618 MFI->setHasSpilledSGPRs();
1619 assert(SrcReg != AMDGPU::M0 && "m0 should not be spilled");
1620 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1621 SrcReg != AMDGPU::EXEC && "exec should not be spilled");
1622
1623 // We are only allowed to create one new instruction when spilling
1624 // registers, so we need to use pseudo instruction for spilling SGPRs.
1625 const MCInstrDesc &OpDesc =
1626 get(getSGPRSpillSaveOpcode(SpillSize, NeedsCFI));
1627
1628 // The SGPR spill/restore instructions only work on number sgprs, so we need
1629 // to make sure we are using the correct register class.
1630 if (SrcReg.isVirtual() && SpillSize == 4) {
1631 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1632 }
1633
1634 BuildMI(MBB, MI, DL, OpDesc)
1635 .addReg(SrcReg, getKillRegState(isKill)) // data
1636 .addFrameIndex(FrameIndex) // addr
1637 .addMemOperand(MMO)
1639
1640 return;
1641 }
1642
1643 unsigned Opcode = getVectorRegSpillSaveOpcode(VReg ? VReg : SrcReg, RC,
1644 SpillSize, *MFI, NeedsCFI);
1645 MFI->setHasSpilledVGPRs();
1646
1647 BuildMI(MBB, MI, DL, get(Opcode))
1648 .addReg(SrcReg, getKillRegState(isKill)) // data
1649 .addFrameIndex(FrameIndex) // addr
1650 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1651 .addImm(0) // offset
1652 .addMemOperand(MMO);
1653}
1654
1657 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1658 MachineInstr::MIFlag Flags) const {
1659 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1660 false);
1661}
1662
1665 Register SrcReg, bool isKill,
1666 int FrameIndex,
1667 const TargetRegisterClass *RC) const {
1668 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, Register(),
1669 MachineInstr::NoFlags, true);
1670}
1671
1672static unsigned getSGPRSpillRestoreOpcode(unsigned Size) {
1673 switch (Size) {
1674 case 4:
1675 return AMDGPU::SI_SPILL_S32_RESTORE;
1676 case 8:
1677 return AMDGPU::SI_SPILL_S64_RESTORE;
1678 case 12:
1679 return AMDGPU::SI_SPILL_S96_RESTORE;
1680 case 16:
1681 return AMDGPU::SI_SPILL_S128_RESTORE;
1682 case 20:
1683 return AMDGPU::SI_SPILL_S160_RESTORE;
1684 case 24:
1685 return AMDGPU::SI_SPILL_S192_RESTORE;
1686 case 28:
1687 return AMDGPU::SI_SPILL_S224_RESTORE;
1688 case 32:
1689 return AMDGPU::SI_SPILL_S256_RESTORE;
1690 case 36:
1691 return AMDGPU::SI_SPILL_S288_RESTORE;
1692 case 40:
1693 return AMDGPU::SI_SPILL_S320_RESTORE;
1694 case 44:
1695 return AMDGPU::SI_SPILL_S352_RESTORE;
1696 case 48:
1697 return AMDGPU::SI_SPILL_S384_RESTORE;
1698 case 64:
1699 return AMDGPU::SI_SPILL_S512_RESTORE;
1700 case 128:
1701 return AMDGPU::SI_SPILL_S1024_RESTORE;
1702 default:
1703 llvm_unreachable("unknown register size");
1704 }
1705}
1706
1707static unsigned getVGPRSpillRestoreOpcode(unsigned Size) {
1708 switch (Size) {
1709 case 2:
1710 return AMDGPU::SI_SPILL_V16_RESTORE;
1711 case 4:
1712 return AMDGPU::SI_SPILL_V32_RESTORE;
1713 case 8:
1714 return AMDGPU::SI_SPILL_V64_RESTORE;
1715 case 12:
1716 return AMDGPU::SI_SPILL_V96_RESTORE;
1717 case 16:
1718 return AMDGPU::SI_SPILL_V128_RESTORE;
1719 case 20:
1720 return AMDGPU::SI_SPILL_V160_RESTORE;
1721 case 24:
1722 return AMDGPU::SI_SPILL_V192_RESTORE;
1723 case 28:
1724 return AMDGPU::SI_SPILL_V224_RESTORE;
1725 case 32:
1726 return AMDGPU::SI_SPILL_V256_RESTORE;
1727 case 36:
1728 return AMDGPU::SI_SPILL_V288_RESTORE;
1729 case 40:
1730 return AMDGPU::SI_SPILL_V320_RESTORE;
1731 case 44:
1732 return AMDGPU::SI_SPILL_V352_RESTORE;
1733 case 48:
1734 return AMDGPU::SI_SPILL_V384_RESTORE;
1735 case 64:
1736 return AMDGPU::SI_SPILL_V512_RESTORE;
1737 case 128:
1738 return AMDGPU::SI_SPILL_V1024_RESTORE;
1739 default:
1740 llvm_unreachable("unknown register size");
1741 }
1742}
1743
1744static unsigned getAVSpillRestoreOpcode(unsigned Size) {
1745 switch (Size) {
1746 case 4:
1747 return AMDGPU::SI_SPILL_AV32_RESTORE;
1748 case 8:
1749 return AMDGPU::SI_SPILL_AV64_RESTORE;
1750 case 12:
1751 return AMDGPU::SI_SPILL_AV96_RESTORE;
1752 case 16:
1753 return AMDGPU::SI_SPILL_AV128_RESTORE;
1754 case 20:
1755 return AMDGPU::SI_SPILL_AV160_RESTORE;
1756 case 24:
1757 return AMDGPU::SI_SPILL_AV192_RESTORE;
1758 case 28:
1759 return AMDGPU::SI_SPILL_AV224_RESTORE;
1760 case 32:
1761 return AMDGPU::SI_SPILL_AV256_RESTORE;
1762 case 36:
1763 return AMDGPU::SI_SPILL_AV288_RESTORE;
1764 case 40:
1765 return AMDGPU::SI_SPILL_AV320_RESTORE;
1766 case 44:
1767 return AMDGPU::SI_SPILL_AV352_RESTORE;
1768 case 48:
1769 return AMDGPU::SI_SPILL_AV384_RESTORE;
1770 case 64:
1771 return AMDGPU::SI_SPILL_AV512_RESTORE;
1772 case 128:
1773 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1774 default:
1775 llvm_unreachable("unknown register size");
1776 }
1777}
1778
1779static unsigned getWWMRegSpillRestoreOpcode(unsigned Size,
1780 bool IsVectorSuperClass) {
1781 // Currently, there is only 32-bit WWM register spills needed.
1782 if (Size != 4)
1783 llvm_unreachable("unknown wwm register spill size");
1784
1785 if (IsVectorSuperClass) // TODO: Always use this if there are AGPRs
1786 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1787
1788 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1789}
1790
1792 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1793 const SIMachineFunctionInfo &MFI) const {
1794 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1795
1796 // Choose the right opcode if restoring a WWM register.
1798 return getWWMRegSpillRestoreOpcode(Size, IsVectorSuperClass);
1799
1800 // TODO: Check if AGPRs are available
1801 if (ST.hasMAIInsts())
1803
1804 assert(!RI.isAGPRClass(RC));
1806}
1807
1810 Register DestReg, int FrameIndex,
1811 const TargetRegisterClass *RC,
1812 Register VReg, unsigned SubReg,
1813 MachineInstr::MIFlag Flags) const {
1814 MachineFunction *MF = MBB.getParent();
1816 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1817 const DebugLoc &DL = MBB.findDebugLoc(MI);
1818 unsigned SpillSize = RI.getSpillSize(*RC);
1819
1820 MachinePointerInfo PtrInfo
1821 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1822
1824 PtrInfo, MachineMemOperand::MOLoad, FrameInfo.getObjectSize(FrameIndex),
1825 FrameInfo.getObjectAlign(FrameIndex));
1826
1827 if (RI.isSGPRClass(RC)) {
1828 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1829 MFI->setHasSpilledSGPRs();
1830 assert(DestReg != AMDGPU::M0 && "m0 should not be reloaded into");
1831 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1832 DestReg != AMDGPU::EXEC && "exec should not be spilled");
1833
1834 // FIXME: Maybe this should not include a memoperand because it will be
1835 // lowered to non-memory instructions.
1836 const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize));
1837 if (DestReg.isVirtual() && SpillSize == 4) {
1838 MachineRegisterInfo &MRI = MF->getRegInfo();
1839 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1840 }
1841
1842 BuildMI(MBB, MI, DL, OpDesc, DestReg)
1843 .addFrameIndex(FrameIndex) // addr
1844 .addMemOperand(MMO)
1846
1847 return;
1848 }
1849
1850 unsigned Opcode = getVectorRegSpillRestoreOpcode(VReg ? VReg : DestReg, RC,
1851 SpillSize, *MFI);
1852 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
1853 .addFrameIndex(FrameIndex) // vaddr
1854 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1855 .addImm(0) // offset
1856 .addMemOperand(MMO);
1857}
1858
1863
1866 unsigned Quantity) const {
1867 DebugLoc DL = MBB.findDebugLoc(MI);
1868 unsigned MaxSNopCount = 1u << ST.getSNopBits();
1869 while (Quantity > 0) {
1870 unsigned Arg = std::min(Quantity, MaxSNopCount);
1871 Quantity -= Arg;
1872 BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
1873 }
1874}
1875
1879 const DebugLoc &DL) const {
1880 MachineFunction *MF = MBB.getParent();
1881 constexpr unsigned DoorbellIDMask = 0x3ff;
1882 constexpr unsigned ECQueueWaveAbort = 0x400;
1883
1884 MachineBasicBlock *TrapBB = &MBB;
1885 MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock();
1886
1887 if (!MBB.succ_empty() || std::next(MI.getIterator()) != MBB.end()) {
1888 MBB.splitAt(MI, /*UpdateLiveIns=*/false);
1889 TrapBB = MF->CreateMachineBasicBlock();
1890 BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB);
1891 MF->push_back(TrapBB);
1892 MBB.addSuccessor(TrapBB);
1893 }
1894 // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this
1895 // will be a nop.
1896 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP))
1897 .addImm(static_cast<unsigned>(GCNSubtarget::TrapID::LLVMAMDHSATrap));
1898 Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1899 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32),
1900 DoorbellReg)
1902 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
1903 .addUse(AMDGPU::M0);
1904 Register DoorbellRegMasked =
1905 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1906 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked)
1907 .addUse(DoorbellReg)
1908 .addImm(DoorbellIDMask);
1909 Register SetWaveAbortBit =
1910 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1911 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit)
1912 .addUse(DoorbellRegMasked)
1913 .addImm(ECQueueWaveAbort);
1914 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1915 .addUse(SetWaveAbortBit);
1916 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG))
1918 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1919 .addUse(AMDGPU::TTMP2);
1920 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB);
1921 TrapBB->addSuccessor(HaltLoopBB);
1922
1923 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5);
1924 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH))
1925 .addMBB(HaltLoopBB);
1926 MF->push_back(HaltLoopBB);
1927 HaltLoopBB->addSuccessor(HaltLoopBB);
1928
1929 return MBB.getNextNode();
1930}
1931
1933 switch (MI.getOpcode()) {
1934 default:
1935 if (MI.isMetaInstruction())
1936 return 0;
1937 return 1; // FIXME: Do wait states equal cycles?
1938
1939 case AMDGPU::S_NOP:
1940 return MI.getOperand(0).getImm() + 1;
1941 // SI_RETURN_TO_EPILOG is a fallthrough to code outside of the function. The
1942 // hazard, even if one exist, won't really be visible. Should we handle it?
1943 }
1944}
1945
1947 MachineBasicBlock &MBB = *MI.getParent();
1948 DebugLoc DL = MBB.findDebugLoc(MI);
1950
1951 switch (MI.getOpcode()) {
1952 default: return TargetInstrInfo::expandPostRAPseudo(MI);
1953 case AMDGPU::S_MOV_B64_term:
1954 // This is only a terminator to get the correct spill code placement during
1955 // register allocation.
1956 MI.setDesc(get(AMDGPU::S_MOV_B64));
1957 break;
1958
1959 case AMDGPU::S_MOV_B32_term:
1960 // This is only a terminator to get the correct spill code placement during
1961 // register allocation.
1962 MI.setDesc(get(AMDGPU::S_MOV_B32));
1963 break;
1964
1965 case AMDGPU::S_XOR_B64_term:
1966 // This is only a terminator to get the correct spill code placement during
1967 // register allocation.
1968 MI.setDesc(get(AMDGPU::S_XOR_B64));
1969 break;
1970
1971 case AMDGPU::S_XOR_B32_term:
1972 // This is only a terminator to get the correct spill code placement during
1973 // register allocation.
1974 MI.setDesc(get(AMDGPU::S_XOR_B32));
1975 break;
1976 case AMDGPU::S_OR_B64_term:
1977 // This is only a terminator to get the correct spill code placement during
1978 // register allocation.
1979 MI.setDesc(get(AMDGPU::S_OR_B64));
1980 break;
1981 case AMDGPU::S_OR_B32_term:
1982 // This is only a terminator to get the correct spill code placement during
1983 // register allocation.
1984 MI.setDesc(get(AMDGPU::S_OR_B32));
1985 break;
1986
1987 case AMDGPU::S_ANDN2_B64_term:
1988 // This is only a terminator to get the correct spill code placement during
1989 // register allocation.
1990 MI.setDesc(get(AMDGPU::S_ANDN2_B64));
1991 break;
1992
1993 case AMDGPU::S_ANDN2_B32_term:
1994 // This is only a terminator to get the correct spill code placement during
1995 // register allocation.
1996 MI.setDesc(get(AMDGPU::S_ANDN2_B32));
1997 break;
1998
1999 case AMDGPU::S_AND_B64_term:
2000 // This is only a terminator to get the correct spill code placement during
2001 // register allocation.
2002 MI.setDesc(get(AMDGPU::S_AND_B64));
2003 break;
2004
2005 case AMDGPU::S_AND_B32_term:
2006 // This is only a terminator to get the correct spill code placement during
2007 // register allocation.
2008 MI.setDesc(get(AMDGPU::S_AND_B32));
2009 break;
2010
2011 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2012 // This is only a terminator to get the correct spill code placement during
2013 // register allocation.
2014 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B64));
2015 break;
2016
2017 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2018 // This is only a terminator to get the correct spill code placement during
2019 // register allocation.
2020 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B32));
2021 break;
2022
2023 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2024 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2025 break;
2026 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2027 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2028 break;
2029
2030 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2031 MI.setDesc(get(AMDGPU::V_WRITELANE_B32));
2032 break;
2033
2034 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2035 MI.setDesc(get(AMDGPU::V_READLANE_B32));
2036 break;
2037 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2038 Register Dst = MI.getOperand(0).getReg();
2039 bool IsAGPR = SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst));
2040 MI.setDesc(
2041 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2042 break;
2043 }
2044 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2045 Register Dst = MI.getOperand(0).getReg();
2046 if (SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst))) {
2047 int64_t Imm = MI.getOperand(1).getImm();
2048
2049 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2050 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2051 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstLo)
2052 .addImm(SignExtend64<32>(Imm));
2053 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstHi)
2054 .addImm(SignExtend64<32>(Imm >> 32));
2055 MI.eraseFromParent();
2056 break;
2057 }
2058
2059 [[fallthrough]];
2060 }
2061 case AMDGPU::V_MOV_B64_PSEUDO: {
2062 Register Dst = MI.getOperand(0).getReg();
2063 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2064 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2065
2066 const MCInstrDesc &Mov64Desc = get(AMDGPU::V_MOV_B64_e32);
2067 const TargetRegisterClass *Mov64RC = getRegClass(Mov64Desc, /*OpNum=*/0);
2068
2069 const MachineOperand &SrcOp = MI.getOperand(1);
2070 // FIXME: Will this work for 64-bit floating point immediates?
2071 assert(!SrcOp.isFPImm());
2072 if (ST.hasVMovB64Inst() && Mov64RC->contains(Dst)) {
2073 MI.setDesc(Mov64Desc);
2074 if (SrcOp.isReg() || isInlineConstant(MI, 1) ||
2075 (SrcOp.isImm() &&
2076 (isUInt<32>(SrcOp.getImm()) || ST.has64BitLiterals())) ||
2077 (SrcOp.isGlobal() && ST.has64BitLiterals()))
2078 break;
2079 }
2080 if (SrcOp.isGlobal()) {
2081 // The address is unknown until link time, so the PK_MOV inline-constant
2082 // shortcut cannot apply.
2083 const GlobalValue *GV = SrcOp.getGlobal();
2084 int64_t Offset = SrcOp.getOffset();
2085 unsigned BaseFlags, LoReloc, HiReloc;
2086 std::tie(BaseFlags, LoReloc, HiReloc) =
2088
2089 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2090 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2091 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2092 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2093 } else if (SrcOp.isImm()) {
2094 APInt Imm(64, SrcOp.getImm());
2095 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2096 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2097 const MCInstrDesc &PkMovDesc = get(AMDGPU::V_PK_MOV_B32);
2098 const TargetRegisterClass *PkMovRC = getRegClass(PkMovDesc, /*OpNum=*/0);
2099
2100 if (ST.hasPkMovB32() && Lo == Hi && isInlineConstant(Lo) &&
2101 PkMovRC->contains(Dst)) {
2102 BuildMI(MBB, MI, DL, PkMovDesc, Dst)
2104 .addImm(Lo.getSExtValue())
2106 .addImm(Lo.getSExtValue())
2107 .addImm(0) // op_sel_lo
2108 .addImm(0) // op_sel_hi
2109 .addImm(0) // neg_lo
2110 .addImm(0) // neg_hi
2111 .addImm(0); // clamp
2112 } else {
2113 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2114 .addImm(Lo.getSExtValue());
2115 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2116 .addImm(Hi.getSExtValue());
2117 }
2118 } else {
2119 assert(SrcOp.isReg());
2120 if (ST.hasPkMovB32() &&
2121 !RI.isAGPR(MBB.getParent()->getRegInfo(), SrcOp.getReg())) {
2122 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), Dst)
2123 .addImm(SISrcMods::OP_SEL_1) // src0_mod
2124 .addReg(SrcOp.getReg())
2126 .addReg(SrcOp.getReg())
2127 .addImm(0) // op_sel_lo
2128 .addImm(0) // op_sel_hi
2129 .addImm(0) // neg_lo
2130 .addImm(0) // neg_hi
2131 .addImm(0); // clamp
2132 } else {
2133 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2134 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0));
2135 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2136 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1));
2137 }
2138 }
2139 MI.eraseFromParent();
2140 break;
2141 }
2142 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2144 break;
2145 }
2146 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2147 const MachineOperand &SrcOp = MI.getOperand(1);
2148 assert(!SrcOp.isFPImm());
2149
2150 if (ST.has64BitLiterals()) {
2151 MI.setDesc(get(AMDGPU::S_MOV_B64));
2152 break;
2153 }
2154
2155 if (SrcOp.isGlobal()) {
2156 Register Dst = MI.getOperand(0).getReg();
2157 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2158 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2159 const GlobalValue *GV = SrcOp.getGlobal();
2160 int64_t Offset = SrcOp.getOffset();
2161 unsigned BaseFlags, LoReloc, HiReloc;
2162 std::tie(BaseFlags, LoReloc, HiReloc) =
2164
2165 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2166 .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
2167 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2168 .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
2169 MI.eraseFromParent();
2170 break;
2171 }
2172
2173 // SrcOp is immediate
2174 APInt Imm(64, SrcOp.getImm());
2175 if (Imm.isIntN(32) || isInlineConstant(Imm)) {
2176 MI.setDesc(get(AMDGPU::S_MOV_B64));
2177 break;
2178 }
2179
2180 Register Dst = MI.getOperand(0).getReg();
2181 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2182 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2183
2184 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2185 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2186 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2187 .addImm(Lo.getSExtValue());
2188 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2189 .addImm(Hi.getSExtValue());
2190 MI.eraseFromParent();
2191 break;
2192 }
2193 case AMDGPU::V_SET_INACTIVE_B32: {
2194 // Lower V_SET_INACTIVE_B32 to V_CNDMASK_B32.
2195 Register DstReg = MI.getOperand(0).getReg();
2196 BuildMI(MBB, MI, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2197 .add(MI.getOperand(3))
2198 .add(MI.getOperand(4))
2199 .add(MI.getOperand(1))
2200 .add(MI.getOperand(2))
2201 .add(MI.getOperand(5));
2202 MI.eraseFromParent();
2203 break;
2204 }
2205 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2206 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2207 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2208 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2209 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2210 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2211 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2212 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2213 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2214 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2215 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2216 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2217 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2218 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2219 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2220 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2221 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2222 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2223 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2224 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2225 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2226 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2227 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2228 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2229 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2230 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2231 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2232 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2233 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2234 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2235 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2236 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2237 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2238 const TargetRegisterClass *EltRC = getOpRegClass(MI, 2);
2239
2240 unsigned Opc;
2241 if (RI.hasVGPRs(EltRC)) {
2242 Opc = AMDGPU::V_MOVRELD_B32_e32;
2243 } else {
2244 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2245 : AMDGPU::S_MOVRELD_B32;
2246 }
2247
2248 const MCInstrDesc &OpDesc = get(Opc);
2249 Register VecReg = MI.getOperand(0).getReg();
2250 bool IsUndef = MI.getOperand(1).isUndef();
2251 unsigned SubReg = MI.getOperand(3).getImm();
2252 assert(VecReg == MI.getOperand(1).getReg());
2253
2255 BuildMI(MBB, MI, DL, OpDesc)
2256 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2257 .add(MI.getOperand(2))
2259 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2260
2261 const int ImpDefIdx =
2262 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2263 const int ImpUseIdx = ImpDefIdx + 1;
2264 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2265 MI.eraseFromParent();
2266 break;
2267 }
2268 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2269 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2270 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2271 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2272 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2273 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2274 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2275 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2276 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2277 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2278 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2279 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2280 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2281 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2282 assert(ST.useVGPRIndexMode());
2283 Register VecReg = MI.getOperand(0).getReg();
2284 bool IsUndef = MI.getOperand(1).isUndef();
2285 MachineOperand &Idx = MI.getOperand(3);
2286 Register SubReg = MI.getOperand(4).getImm();
2287
2288 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2289 .add(Idx)
2291 SetOn->getOperand(3).setIsUndef();
2292
2293 const MCInstrDesc &OpDesc = get(AMDGPU::V_MOV_B32_indirect_write);
2295 BuildMI(MBB, MI, DL, OpDesc)
2296 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2297 .add(MI.getOperand(2))
2299 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2300
2301 const int ImpDefIdx =
2302 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2303 const int ImpUseIdx = ImpDefIdx + 1;
2304 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2305
2306 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2307
2308 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2309
2310 MI.eraseFromParent();
2311 break;
2312 }
2313 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2314 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2315 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2316 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2317 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2318 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2319 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2320 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2321 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2322 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2323 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2324 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2325 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2326 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2327 assert(ST.useVGPRIndexMode());
2328 Register Dst = MI.getOperand(0).getReg();
2329 Register VecReg = MI.getOperand(1).getReg();
2330 bool IsUndef = MI.getOperand(1).isUndef();
2331 Register SubReg = MI.getOperand(3).getImm();
2332
2333 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2334 .add(MI.getOperand(2))
2336 SetOn->getOperand(3).setIsUndef();
2337
2338 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_indirect_read))
2339 .addDef(Dst)
2340 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2341 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2342
2343 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2344
2345 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2346
2347 MI.eraseFromParent();
2348 break;
2349 }
2350 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2351 MachineFunction &MF = *MBB.getParent();
2352 Register Reg = MI.getOperand(0).getReg();
2353 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2354 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2355 MachineOperand OpLo = MI.getOperand(1);
2356 MachineOperand OpHi = MI.getOperand(2);
2357
2358 // Create a bundle so these instructions won't be re-ordered by the
2359 // post-RA scheduler.
2360 MIBundleBuilder Bundler(MBB, MI);
2361 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2362
2363 // What we want here is an offset from the value returned by s_getpc (which
2364 // is the address of the s_add_u32 instruction) to the global variable, but
2365 // since the encoding of $symbol starts 4 bytes after the start of the
2366 // s_add_u32 instruction, we end up with an offset that is 4 bytes too
2367 // small. This requires us to add 4 to the global variable offset in order
2368 // to compute the correct address. Similarly for the s_addc_u32 instruction,
2369 // the encoding of $symbol starts 12 bytes after the start of the s_add_u32
2370 // instruction.
2371
2372 int64_t Adjust = 0;
2373 if (ST.hasGetPCZeroExtension()) {
2374 // Fix up hardware that does not sign-extend the 48-bit PC value by
2375 // inserting: s_sext_i32_i16 reghi, reghi
2376 Bundler.append(
2377 BuildMI(MF, DL, get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2378 Adjust += 4;
2379 }
2380
2381 if (OpLo.isGlobal())
2382 OpLo.setOffset(OpLo.getOffset() + Adjust + 4);
2383 Bundler.append(
2384 BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2385
2386 if (OpHi.isGlobal())
2387 OpHi.setOffset(OpHi.getOffset() + Adjust + 12);
2388 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi)
2389 .addReg(RegHi)
2390 .add(OpHi));
2391
2392 finalizeBundle(MBB, Bundler.begin());
2393
2394 MI.eraseFromParent();
2395 break;
2396 }
2397 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2398 MachineFunction &MF = *MBB.getParent();
2399 Register Reg = MI.getOperand(0).getReg();
2400 MachineOperand Op = MI.getOperand(1);
2401
2402 // Create a bundle so these instructions won't be re-ordered by the
2403 // post-RA scheduler.
2404 MIBundleBuilder Bundler(MBB, MI);
2405 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2406 if (Op.isGlobal())
2407 Op.setOffset(Op.getOffset() + 4);
2408 Bundler.append(
2409 BuildMI(MF, DL, get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(Op));
2410
2411 finalizeBundle(MBB, Bundler.begin());
2412
2413 MI.eraseFromParent();
2414 break;
2415 }
2416 case AMDGPU::ENTER_STRICT_WWM: {
2417 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2418 // Whole Wave Mode is entered.
2419 MI.setDesc(get(LMC.OrSaveExecOpc));
2420 break;
2421 }
2422 case AMDGPU::ENTER_STRICT_WQM: {
2423 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2424 // STRICT_WQM is entered.
2425 BuildMI(MBB, MI, DL, get(LMC.MovOpc), MI.getOperand(0).getReg())
2426 .addReg(LMC.ExecReg);
2427 BuildMI(MBB, MI, DL, get(LMC.WQMOpc), LMC.ExecReg).addReg(LMC.ExecReg);
2428
2429 MI.eraseFromParent();
2430 break;
2431 }
2432 case AMDGPU::EXIT_STRICT_WWM:
2433 case AMDGPU::EXIT_STRICT_WQM: {
2434 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2435 // WWM/STICT_WQM is exited.
2436 MI.setDesc(get(LMC.MovOpc));
2437 break;
2438 }
2439 case AMDGPU::SI_RETURN: {
2440 const MachineFunction *MF = MBB.getParent();
2441 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2442 const SIRegisterInfo *TRI = ST.getRegisterInfo();
2443 // Hiding the return address use with SI_RETURN may lead to extra kills in
2444 // the function and missing live-ins. We are fine in practice because callee
2445 // saved register handling ensures the register value is restored before
2446 // RET, but we need the undef flag here to appease the MachineVerifier
2447 // liveness checks.
2449 BuildMI(MBB, MI, DL, get(AMDGPU::S_SETPC_B64_return))
2450 .addReg(TRI->getReturnAddressReg(*MF), RegState::Undef);
2451
2452 MIB.copyImplicitOps(MI);
2453 MI.eraseFromParent();
2454 break;
2455 }
2456
2457 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2458 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2459 MI.setDesc(get(AMDGPU::S_MUL_U64));
2460 break;
2461
2462 case AMDGPU::S_GETPC_B64_pseudo:
2463 MI.setDesc(get(AMDGPU::S_GETPC_B64));
2464 if (ST.hasGetPCZeroExtension()) {
2465 Register Dst = MI.getOperand(0).getReg();
2466 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2467 // Fix up hardware that does not sign-extend the 48-bit PC value by
2468 // inserting: s_sext_i32_i16 dsthi, dsthi
2469 BuildMI(MBB, std::next(MI.getIterator()), DL, get(AMDGPU::S_SEXT_I32_I16),
2470 DstHi)
2471 .addReg(DstHi);
2472 }
2473 break;
2474
2475 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2476 assert(ST.hasBF16PackedInsts());
2477 MI.setDesc(get(AMDGPU::V_PK_MAX_NUM_BF16));
2478 MI.addOperand(MachineOperand::CreateImm(0)); // op_sel
2479 MI.addOperand(MachineOperand::CreateImm(0)); // neg_lo
2480 MI.addOperand(MachineOperand::CreateImm(0)); // neg_hi
2481 auto Op0 = getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
2482 Op0->setImm(Op0->getImm() | SISrcMods::OP_SEL_1);
2483 auto Op1 = getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
2484 Op1->setImm(Op1->getImm() | SISrcMods::OP_SEL_1);
2485 break;
2486 }
2487
2488 case AMDGPU::GET_STACK_BASE:
2489 // The stack starts at offset 0 unless we need to reserve some space at the
2490 // bottom.
2491 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*MBB.getParent())) {
2492 // When CWSR is used in dynamic VGPR mode, the trap handler needs to save
2493 // some of the VGPRs. The size of the required scratch space has already
2494 // been computed by prolog epilog insertion.
2495 const SIMachineFunctionInfo *MFI =
2496 MBB.getParent()->getInfo<SIMachineFunctionInfo>();
2497 unsigned VGPRSize = MFI->getScratchReservedForDynamicVGPRs();
2498 Register DestReg = MI.getOperand(0).getReg();
2499 BuildMI(MBB, MI, DL, get(AMDGPU::S_GETREG_B32), DestReg)
2502 // The MicroEngine ID is 0 for the graphics queue, and 1 or 2 for compute
2503 // (3 is unused, so we ignore it). Unfortunately, S_GETREG doesn't set
2504 // SCC, so we need to check for 0 manually.
2505 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)).addImm(0).addReg(DestReg);
2506 // Change the implicif-def of SCC to an explicit use (but first remove
2507 // the dead flag if present).
2508 MI.getOperand(MI.getNumExplicitOperands()).setIsDead(false);
2509 MI.getOperand(MI.getNumExplicitOperands()).setIsUse();
2510 MI.setDesc(get(AMDGPU::S_CMOVK_I32));
2511 MI.addOperand(MachineOperand::CreateImm(VGPRSize));
2512 } else {
2513 MI.setDesc(get(AMDGPU::S_MOV_B32));
2514 MI.addOperand(MachineOperand::CreateImm(0));
2515 MI.removeOperand(
2516 MI.getNumExplicitOperands()); // Drop implicit def of SCC.
2517 }
2518 break;
2519 }
2520
2521 return true;
2522}
2523
2526 unsigned SubIdx, const MachineInstr &Orig,
2527 LaneBitmask UsedLanes) const {
2528
2529 // Try shrinking the instruction to remat only the part needed for current
2530 // context.
2531 // TODO: Handle more cases.
2532 unsigned Opcode = Orig.getOpcode();
2533 switch (Opcode) {
2534 case AMDGPU::S_MOV_B64:
2535 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2536 if (SubIdx != 0)
2537 break;
2538
2539 if (!Orig.getOperand(1).isImm())
2540 break;
2541
2542 // Shrink S_MOV_B64 to S_MOV_B32 when UsedLanes indicates only a single
2543 // 32-bit lane of the 64-bit value is live at the rematerialization point.
2544 if (UsedLanes.all())
2545 break;
2546
2547 // Determine which half of the 64-bit immediate corresponds to the use.
2548 unsigned OrigSubReg = Orig.getOperand(0).getSubReg();
2549 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2550 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2551
2552 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2553 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2554
2555 if (NeedLo && NeedHi)
2556 break;
2557
2558 int64_t Imm64 = Orig.getOperand(1).getImm();
2559 int32_t Imm32 = NeedLo ? Lo_32(Imm64) : Hi_32(Imm64);
2560
2561 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2562
2563 // Emit S_MOV_B32 defining just the needed 32-bit subreg of DestReg.
2564 BuildMI(MBB, I, Orig.getDebugLoc(), get(AMDGPU::S_MOV_B32))
2565 .addReg(DestReg, RegState::Define | RegState::Undef, UseSubReg)
2566 .addImm(Imm32);
2567 return;
2568 }
2569
2570 case AMDGPU::S_LOAD_DWORDX16_IMM:
2571 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2572 if (SubIdx != 0)
2573 break;
2574
2575 if (I == MBB.end())
2576 break;
2577
2578 if (I->isBundled())
2579 break;
2580
2581 // Look for a single use of the register that is also a subreg.
2582 Register RegToFind = Orig.getOperand(0).getReg();
2583 MachineOperand *UseMO = nullptr;
2584 for (auto &CandMO : I->operands()) {
2585 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2586 continue;
2587 if (UseMO) {
2588 UseMO = nullptr;
2589 break;
2590 }
2591 UseMO = &CandMO;
2592 }
2593 if (!UseMO || UseMO->getSubReg() == AMDGPU::NoSubRegister)
2594 break;
2595
2596 unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
2597 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());
2598
2599 MachineFunction *MF = MBB.getParent();
2600 MachineRegisterInfo &MRI = MF->getRegInfo();
2601 assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");
2602
2603 unsigned NewOpcode = -1;
2604 if (SubregSize == 256)
2605 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2606 else if (SubregSize == 128)
2607 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2608 else
2609 break;
2610
2611 const MCInstrDesc &TID = get(NewOpcode);
2612 const TargetRegisterClass *NewRC =
2613 RI.getAllocatableClass(getRegClass(TID, 0));
2614 MRI.setRegClass(DestReg, NewRC);
2615
2616 UseMO->setReg(DestReg);
2617 UseMO->setSubReg(AMDGPU::NoSubRegister);
2618
2619 // Use a smaller load with the desired size, possibly with updated offset.
2620 MachineInstr *MI = MF->CloneMachineInstr(&Orig);
2621 MI->setDesc(TID);
2622 MI->getOperand(0).setReg(DestReg);
2623 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2624 if (Offset) {
2625 MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
2626 int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
2627 OffsetMO->setImm(FinalOffset);
2628 }
2630 for (const MachineMemOperand *MemOp : Orig.memoperands())
2631 NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
2632 SubregSize / 8));
2633 MI->setMemRefs(*MF, NewMMOs);
2634
2635 MBB.insert(I, MI);
2636 return;
2637 }
2638
2639 default:
2640 break;
2641 }
2642
2643 TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
2644}
2645
2646std::pair<MachineInstr*, MachineInstr*>
2648 assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2649
2650 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2652 ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
2653 MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
2654 return std::pair(&MI, nullptr);
2655 }
2656
2657 MachineBasicBlock &MBB = *MI.getParent();
2658 DebugLoc DL = MBB.findDebugLoc(MI);
2659 MachineFunction *MF = MBB.getParent();
2660 MachineRegisterInfo &MRI = MF->getRegInfo();
2661 Register Dst = MI.getOperand(0).getReg();
2662 unsigned Part = 0;
2663 MachineInstr *Split[2];
2664
2665 for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2666 auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
2667 if (Dst.isPhysical()) {
2668 MovDPP.addDef(RI.getSubReg(Dst, Sub));
2669 } else {
2670 assert(MRI.isSSA());
2671 auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2672 MovDPP.addDef(Tmp);
2673 }
2674
2675 for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
2676 const MachineOperand &SrcOp = MI.getOperand(I);
2677 assert(!SrcOp.isFPImm());
2678 if (SrcOp.isImm()) {
2679 APInt Imm(64, SrcOp.getImm());
2680 Imm.ashrInPlace(Part * 32);
2681 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2682 } else {
2683 assert(SrcOp.isReg());
2684 Register Src = SrcOp.getReg();
2685 if (Src.isPhysical())
2686 MovDPP.addReg(RI.getSubReg(Src, Sub));
2687 else
2688 MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
2689 }
2690 }
2691
2692 for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
2693 MovDPP.addImm(MO.getImm());
2694
2695 Split[Part] = MovDPP;
2696 ++Part;
2697 }
2698
2699 if (Dst.isVirtual())
2700 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
2701 .addReg(Split[0]->getOperand(0).getReg())
2702 .addImm(AMDGPU::sub0)
2703 .addReg(Split[1]->getOperand(0).getReg())
2704 .addImm(AMDGPU::sub1);
2705
2706 MI.eraseFromParent();
2707 return std::pair(Split[0], Split[1]);
2708}
2709
2710std::optional<DestSourcePair>
2712 if (MI.getOpcode() == AMDGPU::WWM_COPY)
2713 return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
2714
2715 return std::nullopt;
2716}
2717
2719 AMDGPU::OpName Src0OpName,
2720 MachineOperand &Src1,
2721 AMDGPU::OpName Src1OpName) const {
2722 MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
2723 if (!Src0Mods)
2724 return false;
2725
2726 MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
2727 assert(Src1Mods &&
2728 "All commutable instructions have both src0 and src1 modifiers");
2729
2730 int Src0ModsVal = Src0Mods->getImm();
2731 int Src1ModsVal = Src1Mods->getImm();
2732
2733 Src1Mods->setImm(Src0ModsVal);
2734 Src0Mods->setImm(Src1ModsVal);
2735 return true;
2736}
2737
2739 MachineOperand &RegOp,
2740 MachineOperand &NonRegOp) {
2741 Register Reg = RegOp.getReg();
2742 unsigned SubReg = RegOp.getSubReg();
2743 bool IsKill = RegOp.isKill();
2744 bool IsDead = RegOp.isDead();
2745 bool IsUndef = RegOp.isUndef();
2746 bool IsDebug = RegOp.isDebug();
2747
2748 if (NonRegOp.isImm())
2749 RegOp.ChangeToImmediate(NonRegOp.getImm());
2750 else if (NonRegOp.isFI())
2751 RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
2752 else if (NonRegOp.isGlobal()) {
2753 RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
2754 NonRegOp.getTargetFlags());
2755 } else
2756 return nullptr;
2757
2758 // Make sure we don't reinterpret a subreg index in the target flags.
2759 RegOp.setTargetFlags(NonRegOp.getTargetFlags());
2760
2761 NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
2762 NonRegOp.setSubReg(SubReg);
2763
2764 return &MI;
2765}
2766
2768 MachineOperand &NonRegOp1,
2769 MachineOperand &NonRegOp2) {
2770 unsigned TargetFlags = NonRegOp1.getTargetFlags();
2771 int64_t NonRegVal = NonRegOp1.getImm();
2772
2773 NonRegOp1.setImm(NonRegOp2.getImm());
2774 NonRegOp2.setImm(NonRegVal);
2775 NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
2776 NonRegOp2.setTargetFlags(TargetFlags);
2777 return &MI;
2778}
2779
2780bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
2781 unsigned OpIdx1) const {
2782 const MCInstrDesc &InstDesc = MI.getDesc();
2783 const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
2784 const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];
2785
2786 unsigned Opc = MI.getOpcode();
2787 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2788
2789 const MachineOperand &MO0 = MI.getOperand(OpIdx0);
2790 const MachineOperand &MO1 = MI.getOperand(OpIdx1);
2791
2792 // Swap doesn't breach constant bus or literal limits
2793 // It may move literal to position other than src0, this is not allowed
2794 // pre-gfx10 However, most test cases need literals in Src0 for VOP
2795 // FIXME: After gfx9, literal can be in place other than Src0
2796 if (isVALU(MI, /*AllowLDSDMA=*/true)) {
2797 if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
2798 !isInlineConstant(MO0, OpInfo1))
2799 return false;
2800 if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
2801 !isInlineConstant(MO1, OpInfo0))
2802 return false;
2803 }
2804
2805 if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
2806 if (OpInfo1.RegClass == -1)
2807 return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
2808 return isLegalRegOperand(MI, OpIdx1, MO0) &&
2809 (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
2810 }
2811 if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
2812 if (OpInfo0.RegClass == -1)
2813 return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
2814 return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
2815 isLegalRegOperand(MI, OpIdx0, MO1);
2816 }
2817
2818 // No need to check 64-bit literals since swapping does not bring new
2819 // 64-bit literals into current instruction to fold to 32-bit
2820
2821 return isImmOperandLegal(MI, OpIdx1, MO0);
2822}
2823
2825 unsigned Src0Idx,
2826 unsigned Src1Idx) const {
2827 assert(!NewMI && "this should never be used");
2828
2829 unsigned Opc = MI.getOpcode();
2830 int CommutedOpcode = commuteOpcode(Opc);
2831 if (CommutedOpcode == -1)
2832 return nullptr;
2833
2834 if (Src0Idx > Src1Idx)
2835 std::swap(Src0Idx, Src1Idx);
2836
2837 assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
2838 static_cast<int>(Src0Idx) &&
2839 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
2840 static_cast<int>(Src1Idx) &&
2841 "inconsistency with findCommutedOpIndices");
2842
2843 if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
2844 return nullptr;
2845
2846 MachineInstr *CommutedMI = nullptr;
2847 MachineOperand &Src0 = MI.getOperand(Src0Idx);
2848 MachineOperand &Src1 = MI.getOperand(Src1Idx);
2849 if (Src0.isReg() && Src1.isReg()) {
2850 // Be sure to copy the source modifiers to the right place.
2851 CommutedMI =
2852 TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
2853 } else if (Src0.isReg() && !Src1.isReg()) {
2854 CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
2855 } else if (!Src0.isReg() && Src1.isReg()) {
2856 CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
2857 } else if (Src0.isImm() && Src1.isImm()) {
2858 CommutedMI = swapImmOperands(MI, Src0, Src1);
2859 } else {
2860 // FIXME: Found two non registers to commute. This does happen.
2861 return nullptr;
2862 }
2863
2864 if (CommutedMI) {
2865 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
2866 Src1, AMDGPU::OpName::src1_modifiers);
2867
2868 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
2869 AMDGPU::OpName::src1_sel);
2870
2871 CommutedMI->setDesc(get(CommutedOpcode));
2872 }
2873
2874 return CommutedMI;
2875}
2876
2877// This needs to be implemented because the source modifiers may be inserted
2878// between the true commutable operands, and the base
2879// TargetInstrInfo::commuteInstruction uses it.
2881 unsigned &SrcOpIdx0,
2882 unsigned &SrcOpIdx1) const {
2883 return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
2884}
2885
2887 unsigned &SrcOpIdx0,
2888 unsigned &SrcOpIdx1) const {
2889 if (!Desc.isCommutable())
2890 return false;
2891
2892 unsigned Opc = Desc.getOpcode();
2893 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2894 if (Src0Idx == -1)
2895 return false;
2896
2897 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
2898 if (Src1Idx == -1)
2899 return false;
2900
2901 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
2902}
2903
2905 int64_t BrOffset) const {
2906 // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
2907 // because its dest block is unanalyzable.
2908 assert(isSOPP(BranchOp) || isSOPK(BranchOp));
2909
2910 // Convert to dwords.
2911 BrOffset /= 4;
2912
2913 // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
2914 // from the next instruction.
2915 BrOffset -= 1;
2916
2917 return isIntN(BranchOffsetBits, BrOffset);
2918}
2919
2922 return MI.getOperand(0).getMBB();
2923}
2924
2926 for (const MachineInstr &MI : MBB->terminators()) {
2927 if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
2928 MI.getOpcode() == AMDGPU::SI_LOOP)
2929 return true;
2930 }
2931 return false;
2932}
2933
2935 MachineBasicBlock &DestBB,
2936 MachineBasicBlock &RestoreBB,
2937 const DebugLoc &DL, int64_t BrOffset,
2938 RegScavenger *RS) const {
2939 assert(MBB.empty() &&
2940 "new block should be inserted for expanding unconditional branch");
2941 assert(MBB.pred_size() == 1);
2942 assert(RestoreBB.empty() &&
2943 "restore block should be inserted for restoring clobbered registers");
2944
2945 MachineFunction *MF = MBB.getParent();
2946 MachineRegisterInfo &MRI = MF->getRegInfo();
2948 auto I = MBB.end();
2949 auto &MCCtx = MF->getContext();
2950
2951 if (ST.useAddPC64Inst()) {
2952 MCSymbol *Offset =
2953 MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
2954 auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
2956 MCSymbol *PostAddPCLabel =
2957 MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
2958 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
2959 auto *OffsetExpr = MCBinaryExpr::createSub(
2960 MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
2961 MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
2962 Offset->setVariableValue(OffsetExpr);
2963 return;
2964 }
2965
2966 assert(RS && "RegScavenger required for long branching");
2967
2968 // FIXME: Virtual register workaround for RegScavenger not working with empty
2969 // blocks.
2970 Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
2971
2972 // Note: as this is used after hazard recognizer we need to apply some hazard
2973 // workarounds directly.
2974 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
2975 ST.hasVALUReadSGPRHazard();
2976 auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
2977 if (FlushSGPRWrites)
2978 BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
2980 };
2981
2982 // We need to compute the offset relative to the instruction immediately after
2983 // s_getpc_b64. Insert pc arithmetic code before last terminator.
2984 MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
2985 ApplyHazardWorkarounds();
2986
2987 MCSymbol *PostGetPCLabel =
2988 MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
2989 GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);
2990
2991 MCSymbol *OffsetLo =
2992 MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
2993 MCSymbol *OffsetHi =
2994 MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
2995 BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
2996 .addReg(PCReg, RegState::Define, AMDGPU::sub0)
2997 .addReg(PCReg, {}, AMDGPU::sub0)
2998 .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
2999 BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
3000 .addReg(PCReg, RegState::Define, AMDGPU::sub1)
3001 .addReg(PCReg, {}, AMDGPU::sub1)
3002 .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
3003 ApplyHazardWorkarounds();
3004
3005 // Insert the indirect branch after the other terminator.
3006 BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
3007 .addReg(PCReg);
3008
3009 // If a spill is needed for the pc register pair, we need to insert a spill
3010 // restore block right before the destination block, and insert a short branch
3011 // into the old destination block's fallthrough predecessor.
3012 // e.g.:
3013 //
3014 // s_cbranch_scc0 skip_long_branch:
3015 //
3016 // long_branch_bb:
3017 // spill s[8:9]
3018 // s_getpc_b64 s[8:9]
3019 // s_add_u32 s8, s8, restore_bb
3020 // s_addc_u32 s9, s9, 0
3021 // s_setpc_b64 s[8:9]
3022 //
3023 // skip_long_branch:
3024 // foo;
3025 //
3026 // .....
3027 //
3028 // dest_bb_fallthrough_predecessor:
3029 // bar;
3030 // s_branch dest_bb
3031 //
3032 // restore_bb:
3033 // restore s[8:9]
3034 // fallthrough dest_bb
3035 ///
3036 // dest_bb:
3037 // buzz;
3038
3039 Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
3040 Register Scav;
3041
3042 // If we've previously reserved a register for long branches
3043 // avoid running the scavenger and just use those registers
3044 if (LongBranchReservedReg) {
3045 RS->enterBasicBlock(MBB);
3046 Scav = LongBranchReservedReg;
3047 } else {
3048 RS->enterBasicBlockEnd(MBB);
3049 Scav = RS->scavengeRegisterBackwards(
3050 AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
3051 /* RestoreAfter */ false, 0, /* AllowSpill */ false);
3052 }
3053 if (Scav) {
3054 RS->setRegUsed(Scav);
3055 MRI.replaceRegWith(PCReg, Scav);
3056 MRI.clearVirtRegs();
3057 } else {
3058 // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
3059 // SGPR spill.
3060 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
3061 const SIRegisterInfo *TRI = ST.getRegisterInfo();
3062 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3063 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3064 MRI.clearVirtRegs();
3065 }
3066
3067 MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
3068 // Now, the distance could be defined.
3070 MCSymbolRefExpr::create(DestLabel, MCCtx),
3071 MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
3072 // Add offset assignments.
3073 auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
3074 OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
3075 auto *ShAmt = MCConstantExpr::create(32, MCCtx);
3076 OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
3077}
3078
3079unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
3080 switch (Cond) {
3081 case SIInstrInfo::SCC_TRUE:
3082 return AMDGPU::S_CBRANCH_SCC1;
3083 case SIInstrInfo::SCC_FALSE:
3084 return AMDGPU::S_CBRANCH_SCC0;
3085 case SIInstrInfo::VCCNZ:
3086 return AMDGPU::S_CBRANCH_VCCNZ;
3087 case SIInstrInfo::VCCZ:
3088 return AMDGPU::S_CBRANCH_VCCZ;
3089 case SIInstrInfo::EXECNZ:
3090 return AMDGPU::S_CBRANCH_EXECNZ;
3091 case SIInstrInfo::EXECZ:
3092 return AMDGPU::S_CBRANCH_EXECZ;
3093 default:
3094 llvm_unreachable("invalid branch predicate");
3095 }
3096}
3097
3098SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
3099 switch (Opcode) {
3100 case AMDGPU::S_CBRANCH_SCC0:
3101 return SCC_FALSE;
3102 case AMDGPU::S_CBRANCH_SCC1:
3103 return SCC_TRUE;
3104 case AMDGPU::S_CBRANCH_VCCNZ:
3105 return VCCNZ;
3106 case AMDGPU::S_CBRANCH_VCCZ:
3107 return VCCZ;
3108 case AMDGPU::S_CBRANCH_EXECNZ:
3109 return EXECNZ;
3110 case AMDGPU::S_CBRANCH_EXECZ:
3111 return EXECZ;
3112 default:
3113 return INVALID_BR;
3114 }
3115}
3116
3120 MachineBasicBlock *&FBB,
3122 bool AllowModify) const {
3123 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3124 // Unconditional Branch
3125 TBB = I->getOperand(0).getMBB();
3126 return false;
3127 }
3128
3129 BranchPredicate Pred = getBranchPredicate(I->getOpcode());
3130 if (Pred == INVALID_BR)
3131 return true;
3132
3133 MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
3134 Cond.push_back(MachineOperand::CreateImm(Pred));
3135 Cond.push_back(I->getOperand(1)); // Save the branch register.
3136
3137 ++I;
3138
3139 if (I == MBB.end()) {
3140 // Conditional branch followed by fall-through.
3141 TBB = CondBB;
3142 return false;
3143 }
3144
3145 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3146 TBB = CondBB;
3147 FBB = I->getOperand(0).getMBB();
3148 return false;
3149 }
3150
3151 return true;
3152}
3153
3155 MachineBasicBlock *&FBB,
3157 bool AllowModify) const {
3158 MachineBasicBlock::iterator I = MBB.getFirstTerminator();
3159 auto E = MBB.end();
3160 if (I == E)
3161 return false;
3162
3163 // Skip over the instructions that are artificially terminators for special
3164 // exec management.
3165 while (I != E && !I->isBranch() && !I->isReturn()) {
3166 switch (I->getOpcode()) {
3167 case AMDGPU::S_MOV_B64_term:
3168 case AMDGPU::S_XOR_B64_term:
3169 case AMDGPU::S_OR_B64_term:
3170 case AMDGPU::S_ANDN2_B64_term:
3171 case AMDGPU::S_AND_B64_term:
3172 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3173 case AMDGPU::S_MOV_B32_term:
3174 case AMDGPU::S_XOR_B32_term:
3175 case AMDGPU::S_OR_B32_term:
3176 case AMDGPU::S_ANDN2_B32_term:
3177 case AMDGPU::S_AND_B32_term:
3178 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3179 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3180 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3181 break;
3182 case AMDGPU::SI_IF:
3183 case AMDGPU::SI_ELSE:
3184 case AMDGPU::SI_KILL_I1_TERMINATOR:
3185 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3186 // FIXME: It's messy that these need to be considered here at all.
3187 return true;
3188 default:
3189 llvm_unreachable("unexpected non-branch terminator inst");
3190 }
3191
3192 ++I;
3193 }
3194
3195 if (I == E)
3196 return false;
3197
3198 return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
3199}
3200
3202 int *BytesRemoved) const {
3203 unsigned Count = 0;
3204 unsigned RemovedSize = 0;
3205 for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
3206 // Skip over artificial terminators when removing instructions.
3207 if (MI.isBranch() || MI.isReturn()) {
3208 RemovedSize += getInstSizeInBytes(MI);
3209 MI.eraseFromParent();
3210 ++Count;
3211 }
3212 }
3213
3214 if (BytesRemoved)
3215 *BytesRemoved = RemovedSize;
3216
3217 return Count;
3218}
3219
3220// Copy the flags onto the implicit condition register operand.
3222 const MachineOperand &OrigCond) {
3223 CondReg.setIsUndef(OrigCond.isUndef());
3224 CondReg.setIsKill(OrigCond.isKill());
3225}
3226
3229 MachineBasicBlock *FBB,
3231 const DebugLoc &DL,
3232 int *BytesAdded) const {
3233 if (!FBB && Cond.empty()) {
3234 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3235 .addMBB(TBB);
3236 if (BytesAdded)
3237 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3238 return 1;
3239 }
3240
3241 assert(TBB && Cond[0].isImm());
3242
3243 unsigned Opcode
3244 = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));
3245
3246 if (!FBB) {
3247 MachineInstr *CondBr =
3248 BuildMI(&MBB, DL, get(Opcode))
3249 .addMBB(TBB);
3250
3251 // Copy the flags onto the implicit condition register operand.
3252 preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
3253 fixImplicitOperands(*CondBr);
3254
3255 if (BytesAdded)
3256 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3257 return 1;
3258 }
3259
3260 assert(TBB && FBB);
3261
3262 MachineInstr *CondBr =
3263 BuildMI(&MBB, DL, get(Opcode))
3264 .addMBB(TBB);
3265 fixImplicitOperands(*CondBr);
3266 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3267 .addMBB(FBB);
3268
3269 MachineOperand &CondReg = CondBr->getOperand(1);
3270 CondReg.setIsUndef(Cond[1].isUndef());
3271 CondReg.setIsKill(Cond[1].isKill());
3272
3273 if (BytesAdded)
3274 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3275
3276 return 2;
3277}
3278
3281 if (Cond.size() != 2) {
3282 return true;
3283 }
3284
3285 if (Cond[0].isImm()) {
3286 Cond[0].setImm(-Cond[0].getImm());
3287 return false;
3288 }
3289
3290 return true;
3291}
3292
3295 Register DstReg, Register TrueReg,
3296 Register FalseReg, int &CondCycles,
3297 int &TrueCycles, int &FalseCycles) const {
3298 switch (Cond[0].getImm()) {
3299 case VCCNZ:
3300 case VCCZ: {
3301 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3302 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3303 if (MRI.getRegClass(FalseReg) != RC)
3304 return false;
3305
3306 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3307 CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
3308
3309 // Limit to equal cost for branch vs. N v_cndmask_b32s.
3310 return RI.hasVGPRs(RC) && NumInsts <= 6;
3311 }
3312 case SCC_TRUE:
3313 case SCC_FALSE: {
3314 // FIXME: We could insert for VGPRs if we could replace the original compare
3315 // with a vector one.
3316 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3317 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3318 if (MRI.getRegClass(FalseReg) != RC)
3319 return false;
3320
3321 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3322
3323 // Multiples of 8 can do s_cselect_b64
3324 if (NumInsts % 2 == 0)
3325 NumInsts /= 2;
3326
3327 CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
3328 return RI.isSGPRClass(RC);
3329 }
3330 default:
3331 return false;
3332 }
3333}
3334
3338 Register TrueReg, Register FalseReg) const {
3339 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3340 if (Pred == VCCZ || Pred == SCC_FALSE) {
3341 Pred = static_cast<BranchPredicate>(-Pred);
3342 std::swap(TrueReg, FalseReg);
3343 }
3344
3345 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3346 const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
3347 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3348
3349 if (DstSize == 32) {
3351 if (Pred == SCC_TRUE) {
3352 Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
3353 .addReg(TrueReg)
3354 .addReg(FalseReg);
3355 } else {
3356 // Instruction's operands are backwards from what is expected.
3357 Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
3358 .addReg(FalseReg)
3359 .addReg(TrueReg);
3360 }
3361
3362 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3363 return;
3364 }
3365
3366 if (DstSize == 64 && Pred == SCC_TRUE) {
3368 BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
3369 .addReg(TrueReg)
3370 .addReg(FalseReg);
3371
3372 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3373 return;
3374 }
3375
3376 static const int16_t Sub0_15[] = {
3377 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3378 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3379 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3380 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3381 };
3382
3383 static const int16_t Sub0_15_64[] = {
3384 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3385 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3386 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3387 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3388 };
3389
3390 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3391 const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
3392 const int16_t *SubIndices = Sub0_15;
3393 int NElts = DstSize / 32;
3394
3395 // 64-bit select is only available for SALU.
3396 // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
3397 if (Pred == SCC_TRUE) {
3398 if (NElts % 2) {
3399 SelOp = AMDGPU::S_CSELECT_B32;
3400 EltRC = &AMDGPU::SGPR_32RegClass;
3401 } else {
3402 SelOp = AMDGPU::S_CSELECT_B64;
3403 EltRC = &AMDGPU::SGPR_64RegClass;
3404 SubIndices = Sub0_15_64;
3405 NElts /= 2;
3406 }
3407 }
3408
3410 MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);
3411
3412 I = MIB->getIterator();
3413
3415 for (int Idx = 0; Idx != NElts; ++Idx) {
3416 Register DstElt = MRI.createVirtualRegister(EltRC);
3417 Regs.push_back(DstElt);
3418
3419 unsigned SubIdx = SubIndices[Idx];
3420
3422 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3423 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3424 .addReg(FalseReg, {}, SubIdx)
3425 .addReg(TrueReg, {}, SubIdx);
3426 } else {
3427 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3428 .addReg(TrueReg, {}, SubIdx)
3429 .addReg(FalseReg, {}, SubIdx);
3430 }
3431
3432 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3434
3435 MIB.addReg(DstElt)
3436 .addImm(SubIdx);
3437 }
3438}
3439
3441
3442 if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
3443 return true;
3444
3445 switch (MI.getOpcode()) {
3446 case AMDGPU::S_ENDPGM:
3447 case AMDGPU::S_ENDPGM_SAVED:
3448 case AMDGPU::S_TRAP:
3449 case AMDGPU::S_GETREG_B32:
3450 case AMDGPU::S_SETREG_B32:
3451 case AMDGPU::S_SETREG_B32_mode:
3452 case AMDGPU::S_SETREG_IMM32_B32:
3453 case AMDGPU::S_SETREG_IMM32_B32_mode:
3454 case AMDGPU::S_SENDMSG:
3455 case AMDGPU::S_SENDMSGHALT:
3456 case AMDGPU::S_SENDMSG_RTN_B32:
3457 case AMDGPU::S_SENDMSG_RTN_B64:
3458 case AMDGPU::S_BARRIER_WAIT:
3459 case AMDGPU::S_BARRIER_SIGNAL_M0:
3460 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3461 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3462 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3463 return true;
3464 default:
3465 return false;
3466 }
3467}
3468
3470 switch (MI.getOpcode()) {
3471 case AMDGPU::V_MOV_B16_t16_e32:
3472 case AMDGPU::V_MOV_B16_t16_e64:
3473 case AMDGPU::V_MOV_B32_e32:
3474 case AMDGPU::V_MOV_B32_e64:
3475 case AMDGPU::V_MOV_B64_PSEUDO:
3476 case AMDGPU::V_MOV_B64_e32:
3477 case AMDGPU::V_MOV_B64_e64:
3478 case AMDGPU::S_MOV_B32:
3479 case AMDGPU::S_MOV_B64:
3480 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3481 case AMDGPU::COPY:
3482 case AMDGPU::WWM_COPY:
3483 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3484 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3485 case AMDGPU::V_ACCVGPR_MOV_B32:
3486 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3487 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3488 return true;
3489 default:
3490 return false;
3491 }
3492}
3493
3495 switch (MI.getOpcode()) {
3496 case AMDGPU::V_MOV_B16_t16_e32:
3497 case AMDGPU::V_MOV_B16_t16_e64:
3498 return 2;
3499 case AMDGPU::V_MOV_B32_e32:
3500 case AMDGPU::V_MOV_B32_e64:
3501 case AMDGPU::V_MOV_B64_PSEUDO:
3502 case AMDGPU::V_MOV_B64_e32:
3503 case AMDGPU::V_MOV_B64_e64:
3504 case AMDGPU::S_MOV_B32:
3505 case AMDGPU::S_MOV_B64:
3506 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3507 case AMDGPU::COPY:
3508 case AMDGPU::WWM_COPY:
3509 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3510 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3511 case AMDGPU::V_ACCVGPR_MOV_B32:
3512 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3513 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3514 return 1;
3515 default:
3516 llvm_unreachable("MI is not a foldable copy");
3517 }
3518}
3519
3520static constexpr AMDGPU::OpName ModifierOpNames[] = {
3521 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3522 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3523 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3524
3526 unsigned Opc = MI.getOpcode();
3527 for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
3528 int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
3529 if (Idx >= 0)
3530 MI.removeOperand(Idx);
3531 }
3532}
3533
3535 const MCInstrDesc &NewDesc) const {
3536 MI.setDesc(NewDesc);
3537
3538 // Remove any leftover implicit operands from mutating the instruction. e.g.
3539 // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
3540 // anymore.
3541 const MCInstrDesc &Desc = MI.getDesc();
3542 unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
3543 Desc.implicit_defs().size();
3544
3545 for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
3546 MI.removeOperand(I);
3547}
3548
3549std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
3550 unsigned SubRegIndex) {
3551 switch (SubRegIndex) {
3552 case AMDGPU::NoSubRegister:
3553 return Imm;
3554 case AMDGPU::sub0:
3555 return SignExtend64<32>(Imm);
3556 case AMDGPU::sub1:
3557 return SignExtend64<32>(Imm >> 32);
3558 case AMDGPU::lo16:
3559 return SignExtend64<16>(Imm);
3560 case AMDGPU::hi16:
3561 return SignExtend64<16>(Imm >> 16);
3562 case AMDGPU::sub1_lo16:
3563 return SignExtend64<16>(Imm >> 32);
3564 case AMDGPU::sub1_hi16:
3565 return SignExtend64<16>(Imm >> 48);
3566 default:
3567 return std::nullopt;
3568 }
3569
3570 llvm_unreachable("covered subregister switch");
3571}
3572
3573static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
3574 switch (Opc) {
3575 case AMDGPU::V_MAC_F16_e32:
3576 case AMDGPU::V_MAC_F16_e64:
3577 case AMDGPU::V_MAD_F16_e64:
3578 return AMDGPU::V_MADAK_F16;
3579 case AMDGPU::V_MAC_F32_e32:
3580 case AMDGPU::V_MAC_F32_e64:
3581 case AMDGPU::V_MAD_F32_e64:
3582 return AMDGPU::V_MADAK_F32;
3583 case AMDGPU::V_FMAC_F32_e32:
3584 case AMDGPU::V_FMAC_F32_e64:
3585 case AMDGPU::V_FMA_F32_e64:
3586 return AMDGPU::V_FMAAK_F32;
3587 case AMDGPU::V_FMAC_F16_e32:
3588 case AMDGPU::V_FMAC_F16_e64:
3589 case AMDGPU::V_FMAC_F16_t16_e64:
3590 case AMDGPU::V_FMAC_F16_fake16_e64:
3591 case AMDGPU::V_FMAC_F16_t16_e32:
3592 case AMDGPU::V_FMAC_F16_fake16_e32:
3593 case AMDGPU::V_FMA_F16_e64:
3594 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3595 ? AMDGPU::V_FMAAK_F16_t16
3596 : AMDGPU::V_FMAAK_F16_fake16
3597 : AMDGPU::V_FMAAK_F16;
3598 case AMDGPU::V_FMAC_F64_e32:
3599 case AMDGPU::V_FMAC_F64_e64:
3600 case AMDGPU::V_FMA_F64_e64:
3601 return AMDGPU::V_FMAAK_F64;
3602 default:
3603 llvm_unreachable("invalid instruction");
3604 }
3605}
3606
3607static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
3608 switch (Opc) {
3609 case AMDGPU::V_MAC_F16_e32:
3610 case AMDGPU::V_MAC_F16_e64:
3611 case AMDGPU::V_MAD_F16_e64:
3612 return AMDGPU::V_MADMK_F16;
3613 case AMDGPU::V_MAC_F32_e32:
3614 case AMDGPU::V_MAC_F32_e64:
3615 case AMDGPU::V_MAD_F32_e64:
3616 return AMDGPU::V_MADMK_F32;
3617 case AMDGPU::V_FMAC_F32_e32:
3618 case AMDGPU::V_FMAC_F32_e64:
3619 case AMDGPU::V_FMA_F32_e64:
3620 return AMDGPU::V_FMAMK_F32;
3621 case AMDGPU::V_FMAC_F16_e32:
3622 case AMDGPU::V_FMAC_F16_e64:
3623 case AMDGPU::V_FMAC_F16_t16_e64:
3624 case AMDGPU::V_FMAC_F16_fake16_e64:
3625 case AMDGPU::V_FMAC_F16_t16_e32:
3626 case AMDGPU::V_FMAC_F16_fake16_e32:
3627 case AMDGPU::V_FMA_F16_e64:
3628 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3629 ? AMDGPU::V_FMAMK_F16_t16
3630 : AMDGPU::V_FMAMK_F16_fake16
3631 : AMDGPU::V_FMAMK_F16;
3632 case AMDGPU::V_FMAC_F64_e32:
3633 case AMDGPU::V_FMAC_F64_e64:
3634 case AMDGPU::V_FMA_F64_e64:
3635 return AMDGPU::V_FMAMK_F64;
3636 default:
3637 llvm_unreachable("invalid instruction");
3638 }
3639}
3640
3642 Register Reg, MachineRegisterInfo *MRI) const {
3643 int64_t Imm;
3644 if (!getConstValDefinedInReg(DefMI, Reg, Imm))
3645 return false;
3646
3647 const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);
3648
3649 assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");
3650
3651 unsigned Opc = UseMI.getOpcode();
3652 if (Opc == AMDGPU::COPY) {
3653 assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");
3654
3655 Register DstReg = UseMI.getOperand(0).getReg();
3656 Register UseSubReg = UseMI.getOperand(1).getSubReg();
3657
3658 const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);
3659
3660 if (HasMultipleUses) {
3661 // TODO: This should fold in more cases with multiple use, but we need to
3662 // more carefully consider what those uses are.
3663 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));
3664
3665 // Avoid breaking up a 64-bit inline immediate into a subregister extract.
3666 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3667 return false;
3668
3669 // Most of the time folding a 32-bit inline constant is free (though this
3670 // might not be true if we can't later fold it into a real user).
3671 //
3672 // FIXME: This isInlineConstant check is imprecise if
3673 // getConstValDefinedInReg handled the tricky non-mov cases.
3674 if (ImmDefSize == 32 &&
3676 return false;
3677 }
3678
3679 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3680 RI.getSubRegIdxSize(UseSubReg) == 16;
3681
3682 if (Is16Bit) {
3683 if (RI.hasVGPRs(DstRC))
3684 return false; // Do not clobber vgpr_hi16
3685
3686 if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
3687 return false;
3688 }
3689
3690 MachineFunction *MF = UseMI.getMF();
3691
3692 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3693 MCRegister MovDstPhysReg =
3694 DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();
3695
3696 std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);
3697
3698 // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
3699 for (unsigned MovOp :
3700 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3701 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3702 const MCInstrDesc &MovDesc = get(MovOp);
3703
3704 const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
3705 if (Is16Bit) {
3706 // We just need to find a correctly sized register class, so the
3707 // subregister index compatibility doesn't matter since we're statically
3708 // extracting the immediate value.
3709 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3710 if (!MovDstRC)
3711 continue;
3712
3713 if (MovDstPhysReg) {
3714 // FIXME: We probably should not do this. If there is a live value in
3715 // the high half of the register, it will be corrupted.
3716 MovDstPhysReg =
3717 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3718 if (!MovDstPhysReg)
3719 continue;
3720 }
3721 }
3722
3723 // Result class isn't the right size, try the next instruction.
3724 if (MovDstPhysReg) {
3725 if (!MovDstRC->contains(MovDstPhysReg))
3726 return false;
3727 } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
3728 // TODO: This will be overly conservative in the case of 16-bit virtual
3729 // SGPRs. We could hack up the virtual register uses to use a compatible
3730 // 32-bit class.
3731 continue;
3732 }
3733
3734 const MCOperandInfo &OpInfo = MovDesc.operands()[1];
3735
3736 // Ensure the interpreted immediate value is a valid operand in the new
3737 // mov.
3738 //
3739 // FIXME: isImmOperandLegal should have form that doesn't require existing
3740 // MachineInstr or MachineOperand
3741 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3742 !isInlineConstant(*SubRegImm, OpInfo.OperandType))
3743 break;
3744
3745 NewOpc = MovOp;
3746 break;
3747 }
3748
3749 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
3750 return false;
3751
3752 if (Is16Bit) {
3753 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
3754 if (MovDstPhysReg)
3755 UseMI.getOperand(0).setReg(MovDstPhysReg);
3756 assert(UseMI.getOperand(1).getReg().isVirtual());
3757 }
3758
3759 const MCInstrDesc &NewMCID = get(NewOpc);
3760 UseMI.setDesc(NewMCID);
3761 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
3762 UseMI.addImplicitDefUseOperands(*MF);
3763 return true;
3764 }
3765
3766 if (HasMultipleUses)
3767 return false;
3768
3769 if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
3770 Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
3771 Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
3772 Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
3773 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3774 Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
3775 Opc == AMDGPU::V_FMAC_F64_e64) {
3776 // Don't fold if we are using source or output modifiers. The new VOP2
3777 // instructions don't have them.
3779 return false;
3780
3781 // If this is a free constant, there's no reason to do this.
3782 // TODO: We could fold this here instead of letting SIFoldOperands do it
3783 // later.
3784 int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
3785
3786 // Any src operand can be used for the legality check.
3787 if (isInlineConstant(UseMI, Src0Idx, Imm))
3788 return false;
3789
3790 MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);
3791
3792 MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
3793 MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);
3794
3795 auto CopyRegOperandToNarrowerRC =
3796 [MRI, this](MachineInstr &MI, unsigned OpNo,
3797 const TargetRegisterClass *NewRC) -> void {
3798 if (!MI.getOperand(OpNo).isReg())
3799 return;
3800 Register Reg = MI.getOperand(OpNo).getReg();
3801 const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
3802 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
3803 return;
3804 Register Tmp = MRI->createVirtualRegister(NewRC);
3805 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
3806 get(AMDGPU::COPY), Tmp)
3807 .addReg(Reg);
3808 MI.getOperand(OpNo).setReg(Tmp);
3809 MI.getOperand(OpNo).setIsKill();
3810 };
3811
3812 // Multiplied part is the constant: Use v_madmk_{f16, f32}.
3813 if ((Src0->isReg() && Src0->getReg() == Reg) ||
3814 (Src1->isReg() && Src1->getReg() == Reg)) {
3815 MachineOperand *RegSrc =
3816 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
3817 if (!RegSrc->isReg())
3818 return false;
3819 if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
3820 ST.getConstantBusLimit(Opc) < 2)
3821 return false;
3822
3823 if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
3824 return false;
3825
3826 // If src2 is also a literal constant then we have to choose which one to
3827 // fold. In general it is better to choose madak so that the other literal
3828 // can be materialized in an sgpr instead of a vgpr:
3829 // s_mov_b32 s0, literal
3830 // v_madak_f32 v0, s0, v0, literal
3831 // Instead of:
3832 // v_mov_b32 v1, literal
3833 // v_madmk_f32 v0, v0, literal, v1
3834 MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
3835 if (Def && Def->isMoveImmediate() &&
3836 !isInlineConstant(Def->getOperand(1)))
3837 return false;
3838
3839 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
3840 if (pseudoToMCOpcode(NewOpc) == -1)
3841 return false;
3842
3843 const std::optional<int64_t> SubRegImm = extractSubregFromImm(
3844 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
3845
3846 // FIXME: This would be a lot easier if we could return a new instruction
3847 // instead of having to modify in place.
3848
3849 Register SrcReg = RegSrc->getReg();
3850 unsigned SrcSubReg = RegSrc->getSubReg();
3851 Src0->setReg(SrcReg);
3852 Src0->setSubReg(SrcSubReg);
3853 Src0->setIsKill(RegSrc->isKill());
3854
3855 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
3856 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3857 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3858 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
3859 UseMI.untieRegOperand(
3860 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
3861
3862 Src1->ChangeToImmediate(*SubRegImm);
3863
3865 UseMI.setDesc(get(NewOpc));
3866
3867 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
3868 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
3869 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
3870 Register Tmp = MRI->createVirtualRegister(NewRC);
3871 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
3872 UseMI.getDebugLoc(), get(AMDGPU::COPY),
3873 UseMI.getOperand(0).getReg())
3874 .addReg(Tmp, RegState::Kill);
3875 UseMI.getOperand(0).setReg(Tmp);
3876 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
3877 CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
3878 }
3879
3880 bool DeleteDef = MRI->use_nodbg_empty(Reg);
3881 if (DeleteDef)
3882 DefMI.eraseFromParent();
3883
3884 return true;
3885 }
3886
3887 // Added part is the constant: Use v_madak_{f16, f32}.
3888 if (Src2->isReg() && Src2->getReg() == Reg) {
3889 if (ST.getConstantBusLimit(Opc) < 2) {
3890 // Not allowed to use constant bus for another operand.
3891 // We can however allow an inline immediate as src0.
3892 bool Src0Inlined = false;
3893 if (Src0->isReg()) {
3894 // Try to inline constant if possible.
3895 // If the Def moves immediate and the use is single
3896 // We are saving VGPR here.
3897 MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
3898 if (Def && Def->isMoveImmediate() &&
3899 isInlineConstant(Def->getOperand(1)) &&
3900 MRI->hasOneNonDBGUse(Src0->getReg())) {
3901 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
3902 Src0Inlined = true;
3903 } else if (ST.getConstantBusLimit(Opc) <= 1 &&
3904 RI.isSGPRReg(*MRI, Src0->getReg())) {
3905 return false;
3906 }
3907 // VGPR is okay as Src0 - fallthrough
3908 }
3909
3910 if (Src1->isReg() && !Src0Inlined) {
3911 // We have one slot for inlinable constant so far - try to fill it
3912 MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
3913 if (Def && Def->isMoveImmediate() &&
3914 isInlineConstant(Def->getOperand(1)) &&
3915 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
3916 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
3917 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
3918 return false;
3919 // VGPR is okay as Src1 - fallthrough
3920 }
3921 }
3922
3923 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
3924 if (pseudoToMCOpcode(NewOpc) == -1)
3925 return false;
3926
3927 // FIXME: This would be a lot easier if we could return a new instruction
3928 // instead of having to modify in place.
3929
3930 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
3931 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3932 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3933 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
3934 UseMI.untieRegOperand(
3935 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
3936
3937 const std::optional<int64_t> SubRegImm =
3938 extractSubregFromImm(Imm, Src2->getSubReg());
3939
3940 // ChangingToImmediate adds Src2 back to the instruction.
3941 Src2->ChangeToImmediate(*SubRegImm);
3942
3943 // These come before src2.
3945 UseMI.setDesc(get(NewOpc));
3946
3947 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
3948 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
3949 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
3950 Register Tmp = MRI->createVirtualRegister(NewRC);
3951 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
3952 UseMI.getDebugLoc(), get(AMDGPU::COPY),
3953 UseMI.getOperand(0).getReg())
3954 .addReg(Tmp, RegState::Kill);
3955 UseMI.getOperand(0).setReg(Tmp);
3956 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
3957 CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
3958 }
3959
3960 // It might happen that UseMI was commuted
3961 // and we now have SGPR as SRC1. If so 2 inlined
3962 // constant and SGPR are illegal.
3964
3965 bool DeleteDef = MRI->use_nodbg_empty(Reg);
3966 if (DeleteDef)
3967 DefMI.eraseFromParent();
3968
3969 return true;
3970 }
3971 }
3972
3973 return false;
3974}
3975
3976static bool
3979 if (BaseOps1.size() != BaseOps2.size())
3980 return false;
3981 for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
3982 if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
3983 return false;
3984 }
3985 return true;
3986}
3987
3988static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
3989 LocationSize WidthB, int OffsetB) {
3990 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
3991 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
3992 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
3993 return LowWidth.hasValue() &&
3994 LowOffset + (int)LowWidth.getValue() <= HighOffset;
3995}
3996
3997bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
3998 const MachineInstr &MIb) const {
3999 SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
4000 int64_t Offset0, Offset1;
4001 LocationSize Dummy0 = LocationSize::precise(0);
4002 LocationSize Dummy1 = LocationSize::precise(0);
4003 bool Offset0IsScalable, Offset1IsScalable;
4004 if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
4005 Dummy0, &RI) ||
4006 !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
4007 Dummy1, &RI))
4008 return false;
4009
4010 if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
4011 return false;
4012
4013 if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
4014 // FIXME: Handle ds_read2 / ds_write2.
4015 return false;
4016 }
4017 LocationSize Width0 = MIa.memoperands().front()->getSize();
4018 LocationSize Width1 = MIb.memoperands().front()->getSize();
4019 return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
4020}
4021
4023 const MachineInstr &MIb) const {
4024 assert(MIa.mayLoadOrStore() &&
4025 "MIa must load from or modify a memory location");
4026 assert(MIb.mayLoadOrStore() &&
4027 "MIb must load from or modify a memory location");
4028
4030 return false;
4031
4032 // XXX - Can we relax this between address spaces?
4033 if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
4034 return false;
4035
4036 if (isLDSDMA(MIa) || isLDSDMA(MIb))
4037 return false;
4038
4039 if (MIa.isBundle() || MIb.isBundle())
4040 return false;
4041
4042 // TODO: Should we check the address space from the MachineMemOperand? That
4043 // would allow us to distinguish objects we know don't alias based on the
4044 // underlying address space, even if it was lowered to a different one,
4045 // e.g. private accesses lowered to use MUBUF instructions on a scratch
4046 // buffer.
4047 if (isDS(MIa)) {
4048 if (isDS(MIb))
4049 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4050
4051 return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
4052 }
4053
4054 if (isMUBUF(MIa) || isMTBUF(MIa)) {
4055 if (isMUBUF(MIb) || isMTBUF(MIb))
4056 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4057
4058 if (isFLAT(MIb))
4059 return isFLATScratch(MIb);
4060
4061 return !isSMRD(MIb);
4062 }
4063
4064 if (isSMRD(MIa)) {
4065 if (isSMRD(MIb))
4066 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4067
4068 if (isFLAT(MIb))
4069 return isFLATScratch(MIb);
4070
4071 return !isMUBUF(MIb) && !isMTBUF(MIb);
4072 }
4073
4074 if (isFLAT(MIa)) {
4075 if (isFLAT(MIb)) {
4076 if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
4077 (isFLATGlobal(MIa) && isFLATScratch(MIb)))
4078 return true;
4079
4080 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4081 }
4082
4083 return false;
4084 }
4085
4086 return false;
4087}
4088
4090 int64_t &Imm, MachineInstr **DefMI = nullptr) {
4091 if (Reg.isPhysical())
4092 return false;
4093 auto *Def = MRI.getUniqueVRegDef(Reg);
4094 if (Def && SIInstrInfo::isFoldableCopy(*Def) && Def->getOperand(1).isImm()) {
4095 Imm = Def->getOperand(1).getImm();
4096 if (DefMI)
4097 *DefMI = Def;
4098 return true;
4099 }
4100 return false;
4101}
4102
4103static bool getFoldableImm(const MachineOperand *MO, int64_t &Imm,
4104 MachineInstr **DefMI = nullptr) {
4105 if (!MO->isReg())
4106 return false;
4107 const MachineFunction *MF = MO->getParent()->getMF();
4108 const MachineRegisterInfo &MRI = MF->getRegInfo();
4109 return getFoldableImm(MO->getReg(), MRI, Imm, DefMI);
4110}
4111
4113 MachineInstr &NewMI) {
4114 if (LV) {
4115 unsigned NumOps = MI.getNumOperands();
4116 for (unsigned I = 1; I < NumOps; ++I) {
4117 MachineOperand &Op = MI.getOperand(I);
4118 if (Op.isReg() && Op.isKill())
4119 LV->replaceKillInstruction(Op.getReg(), MI, NewMI);
4120 }
4121 }
4122}
4123
4124static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
4125 switch (Opc) {
4126 case AMDGPU::V_MAC_F16_e32:
4127 case AMDGPU::V_MAC_F16_e64:
4128 return AMDGPU::V_MAD_F16_e64;
4129 case AMDGPU::V_MAC_F32_e32:
4130 case AMDGPU::V_MAC_F32_e64:
4131 return AMDGPU::V_MAD_F32_e64;
4132 case AMDGPU::V_MAC_LEGACY_F32_e32:
4133 case AMDGPU::V_MAC_LEGACY_F32_e64:
4134 return AMDGPU::V_MAD_LEGACY_F32_e64;
4135 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4136 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4137 return AMDGPU::V_FMA_LEGACY_F32_e64;
4138 case AMDGPU::V_FMAC_F16_e32:
4139 case AMDGPU::V_FMAC_F16_e64:
4140 case AMDGPU::V_FMAC_F16_t16_e64:
4141 case AMDGPU::V_FMAC_F16_fake16_e64:
4142 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4143 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4144 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4145 : AMDGPU::V_FMA_F16_gfx9_e64;
4146 case AMDGPU::V_FMAC_F32_e32:
4147 case AMDGPU::V_FMAC_F32_e64:
4148 return AMDGPU::V_FMA_F32_e64;
4149 case AMDGPU::V_FMAC_F64_e32:
4150 case AMDGPU::V_FMAC_F64_e64:
4151 return AMDGPU::V_FMA_F64_e64;
4152 default:
4153 llvm_unreachable("invalid instruction");
4154 }
4155}
4156
4157/// Helper struct for the implementation of 3-address conversion to communicate
4158/// updates made to instruction operands.
4160 /// Other instruction whose def is no longer used by the converted
4161 /// instruction.
4163};
4164
4166 LiveVariables *LV,
4167 LiveIntervals *LIS) const {
4168 MachineBasicBlock &MBB = *MI.getParent();
4169 MachineInstr *CandidateMI = &MI;
4170
4171 if (MI.isBundle()) {
4172 // This is a temporary placeholder for bundle handling that enables us to
4173 // exercise the relevant code paths in the two-address instruction pass.
4174 if (MI.getBundleSize() != 1)
4175 return nullptr;
4176 CandidateMI = MI.getNextNode();
4177 }
4178
4180 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4181 if (!NewMI)
4182 return nullptr;
4183
4184 if (MI.isBundle()) {
4185 CandidateMI->eraseFromBundle();
4186
4187 for (MachineOperand &MO : MI.all_defs()) {
4188 if (MO.isTied())
4189 MI.untieRegOperand(MO.getOperandNo());
4190 }
4191 } else {
4192 updateLiveVariables(LV, MI, *NewMI);
4193 if (LIS) {
4194 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
4195 // SlotIndex of defs needs to be updated when converting to early-clobber
4196 MachineOperand &Def = NewMI->getOperand(0);
4197 if (Def.isEarlyClobber() && Def.isReg() &&
4198 LIS->hasInterval(Def.getReg())) {
4199 SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
4200 SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
4201 auto &LI = LIS->getInterval(Def.getReg());
4202 auto UpdateDefIndex = [&](LiveRange &LR) {
4203 auto *S = LR.find(OldIndex);
4204 if (S != LR.end() && S->start == OldIndex) {
4205 assert(S->valno && S->valno->def == OldIndex);
4206 S->start = NewIndex;
4207 S->valno->def = NewIndex;
4208 }
4209 };
4210 UpdateDefIndex(LI);
4211 for (auto &SR : LI.subranges())
4212 UpdateDefIndex(SR);
4213 }
4214 }
4215 }
4216
4217 if (U.RemoveMIUse) {
4218 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4219 // The only user is the instruction which will be killed.
4220 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4221
4222 if (MRI.hasOneNonDBGUse(DefReg)) {
4223 // We cannot just remove the DefMI here, calling pass will crash.
4224 U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
4225 U.RemoveMIUse->getOperand(0).setIsDead(true);
4226 for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
4227 U.RemoveMIUse->removeOperand(I);
4228 if (LV)
4229 LV->getVarInfo(DefReg).AliveBlocks.clear();
4230 }
4231
4232 if (MI.isBundle()) {
4233 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4234 if (!VRI.Reads && !VRI.Writes) {
4235 for (MachineOperand &MO : MI.all_uses()) {
4236 if (MO.isReg() && MO.getReg() == DefReg) {
4237 assert(MO.getSubReg() == 0 &&
4238 "tied sub-registers in bundles currently not supported");
4239 MI.removeOperand(MO.getOperandNo());
4240 break;
4241 }
4242 }
4243
4244 if (LIS)
4245 LIS->shrinkToUses(&LIS->getInterval(DefReg));
4246 }
4247 } else if (LIS) {
4248 LiveInterval &DefLI = LIS->getInterval(DefReg);
4249
4250 // We cannot delete the original instruction here, so hack out the use
4251 // in the original instruction with a dummy register so we can use
4252 // shrinkToUses to deal with any multi-use edge cases. Other targets do
4253 // not have the complexity of deleting a use to consider here.
4254 Register DummyReg = MRI.cloneVirtualRegister(DefReg);
4255 for (MachineOperand &MIOp : MI.uses()) {
4256 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4257 MIOp.setIsUndef(true);
4258 MIOp.setReg(DummyReg);
4259 }
4260 }
4261
4262 if (MI.isBundle()) {
4263 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4264 if (!VRI.Reads && !VRI.Writes) {
4265 for (MachineOperand &MIOp : MI.uses()) {
4266 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4267 MIOp.setIsUndef(true);
4268 MIOp.setReg(DummyReg);
4269 }
4270 }
4271 }
4272
4273 MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
4274 false, /*isUndef=*/true));
4275 }
4276
4277 LIS->shrinkToUses(&DefLI);
4278 }
4279 }
4280
4281 return MI.isBundle() ? &MI : NewMI;
4282}
4283
4285SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
4286 ThreeAddressUpdates &U) const {
4287 MachineBasicBlock &MBB = *MI.getParent();
4288 unsigned Opc = MI.getOpcode();
4289
4290 // Handle MFMA.
4291 int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
4292 if (NewMFMAOpc != -1) {
4294 BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
4295 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4296 MIB.add(MI.getOperand(I));
4297 return MIB;
4298 }
4299
4300 if (SIInstrInfo::isWMMA(MI)) {
4301 unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
4302 MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4303 .setMIFlags(MI.getFlags());
4304 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4305 MIB->addOperand(MI.getOperand(I));
4306 return MIB;
4307 }
4308
4309 assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4310 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4311 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4312 "present pre-RA");
4313
4314 // Handle MAC/FMAC.
4315 bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
4316 bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4317 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4318 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4319 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4320 bool Src0Literal = false;
4321
4322 switch (Opc) {
4323 default:
4324 return nullptr;
4325 case AMDGPU::V_MAC_F16_e64:
4326 case AMDGPU::V_FMAC_F16_e64:
4327 case AMDGPU::V_FMAC_F16_t16_e64:
4328 case AMDGPU::V_FMAC_F16_fake16_e64:
4329 case AMDGPU::V_MAC_F32_e64:
4330 case AMDGPU::V_MAC_LEGACY_F32_e64:
4331 case AMDGPU::V_FMAC_F32_e64:
4332 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4333 case AMDGPU::V_FMAC_F64_e64:
4334 break;
4335 case AMDGPU::V_MAC_F16_e32:
4336 case AMDGPU::V_FMAC_F16_e32:
4337 case AMDGPU::V_MAC_F32_e32:
4338 case AMDGPU::V_MAC_LEGACY_F32_e32:
4339 case AMDGPU::V_FMAC_F32_e32:
4340 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4341 case AMDGPU::V_FMAC_F64_e32: {
4342 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
4343 AMDGPU::OpName::src0);
4344 const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
4345 if (!Src0->isReg() && !Src0->isImm())
4346 return nullptr;
4347
4348 if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
4349 Src0Literal = true;
4350
4351 break;
4352 }
4353 }
4354
4355 MachineInstrBuilder MIB;
4356 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
4357 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
4358 const MachineOperand *Src0Mods =
4359 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
4360 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4361 const MachineOperand *Src1Mods =
4362 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
4363 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4364 const MachineOperand *Src2Mods =
4365 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
4366 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
4367 const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
4368 const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);
4369
4370 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4371 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4372 // If we have an SGPR input, we will violate the constant bus restriction.
4373 (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
4374 !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
4375 MachineInstr *DefMI = nullptr;
4376
4377 int64_t Imm;
4378 if (!Src0Literal && getFoldableImm(Src2, Imm, &DefMI)) {
4379 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4380 if (pseudoToMCOpcode(NewOpc) != -1) {
4381 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4382 .add(*Dst)
4383 .add(*Src0)
4384 .add(*Src1)
4385 .addImm(Imm)
4386 .setMIFlags(MI.getFlags());
4387 U.RemoveMIUse = DefMI;
4388 return MIB;
4389 }
4390 }
4391 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4392 if (!Src0Literal && getFoldableImm(Src1, Imm, &DefMI)) {
4393 if (pseudoToMCOpcode(NewOpc) != -1) {
4394 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4395 .add(*Dst)
4396 .add(*Src0)
4397 .addImm(Imm)
4398 .add(*Src2)
4399 .setMIFlags(MI.getFlags());
4400 U.RemoveMIUse = DefMI;
4401 return MIB;
4402 }
4403 }
4404 if (Src0Literal || getFoldableImm(Src0, Imm, &DefMI)) {
4405 if (Src0Literal) {
4406 Imm = Src0->getImm();
4407 DefMI = nullptr;
4408 }
4409 if (pseudoToMCOpcode(NewOpc) != -1 &&
4411 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4412 Src1)) {
4413 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4414 .add(*Dst)
4415 .add(*Src1)
4416 .addImm(Imm)
4417 .add(*Src2)
4418 .setMIFlags(MI.getFlags());
4419 U.RemoveMIUse = DefMI;
4420 return MIB;
4421 }
4422 }
4423 }
4424
4425 // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
4426 // if VOP3 does not allow a literal operand.
4427 if (Src0Literal && !ST.hasVOP3Literal())
4428 return nullptr;
4429
4430 unsigned NewOpc = getNewFMAInst(ST, Opc);
4431
4432 if (pseudoToMCOpcode(NewOpc) == -1)
4433 return nullptr;
4434
4435 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4436 .add(*Dst)
4437 .addImm(Src0Mods ? Src0Mods->getImm() : 0)
4438 .add(*Src0)
4439 .addImm(Src1Mods ? Src1Mods->getImm() : 0)
4440 .add(*Src1)
4441 .addImm(Src2Mods ? Src2Mods->getImm() : 0)
4442 .add(*Src2)
4443 .addImm(Clamp ? Clamp->getImm() : 0)
4444 .addImm(Omod ? Omod->getImm() : 0)
4445 .setMIFlags(MI.getFlags());
4446 if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
4447 MIB.addImm(OpSel ? OpSel->getImm() : 0);
4448 return MIB;
4449}
4450
4451// It's not generally safe to move VALU instructions across these since it will
4452// start using the register as a base index rather than directly.
4453// XXX - Why isn't hasSideEffects sufficient for these?
4455 switch (MI.getOpcode()) {
4456 case AMDGPU::S_SET_GPR_IDX_ON:
4457 case AMDGPU::S_SET_GPR_IDX_MODE:
4458 case AMDGPU::S_SET_GPR_IDX_OFF:
4459 return true;
4460 default:
4461 return false;
4462 }
4463}
4464
4466 const MachineBasicBlock *MBB,
4467 const MachineFunction &MF) const {
4468 // Skipping the check for SP writes in the base implementation. The reason it
4469 // was added was apparently due to compile time concerns.
4470 //
4471 // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
4472 // but is probably avoidable.
4473
4474 // Copied from base implementation.
4475 // Terminators and labels can't be scheduled around.
4476 if (MI.isTerminator() || MI.isPosition())
4477 return true;
4478
4479 // INLINEASM_BR can jump to another block
4480 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4481 return true;
4482
4483 if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
4484 return true;
4485
4486 // Target-independent instructions do not have an implicit-use of EXEC, even
4487 // when they operate on VGPRs. Treating EXEC modifications as scheduling
4488 // boundaries prevents incorrect movements of such instructions.
4489 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4490 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4491 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4492 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4493 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4495}
4496
4498 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4499 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4500 Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
4501}
4502
4504 // Instructions that access scratch use FLAT encoding or BUF encodings.
4505 if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
4506 return false;
4507
4508 // SCRATCH instructions always access scratch.
4509 if (isFLATScratch(MI))
4510 return true;
4511
4512 // If FLAT_SCRATCH registers are not initialized, we can never access scratch
4513 // via the aperture.
4514 if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
4515 return false;
4516
4517 // If there are no memory operands then conservatively assume the flat
4518 // operation may access scratch.
4519 if (MI.memoperands_empty())
4520 return true;
4521
4522 // See if any memory operand specifies an address space that involves scratch.
4523 return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
4524 unsigned AS = Memop->getAddrSpace();
4525 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4526 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4527 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4528 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4529 }
4530 return AS == AMDGPUAS::PRIVATE_ADDRESS;
4531 });
4532}
4533
4535 assert(isFLAT(MI));
4536
4537 // All flat instructions use the VMEM counter except prefetch.
4538 if (!usesVM_CNT(MI))
4539 return false;
4540
4541 // If there are no memory operands then conservatively assume the flat
4542 // operation may access VMEM.
4543 if (MI.memoperands_empty())
4544 return true;
4545
4546 // See if any memory operand specifies an address space that involves VMEM.
4547 // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
4548 // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
4549 // (GDS) address space is not supported by flat operations. Therefore, simply
4550 // return true unless only the LDS address space is found.
4551 for (const MachineMemOperand *Memop : MI.memoperands()) {
4552 unsigned AS = Memop->getAddrSpace();
4554 if (AS != AMDGPUAS::LOCAL_ADDRESS)
4555 return true;
4556 }
4557
4558 return false;
4559}
4560
4562 bool TgSplit) const {
4563 assert(isFLAT(MI));
4564
4565 // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
4566 if (!usesLGKM_CNT(MI))
4567 return false;
4568
4569 // If in tgsplit mode then there can be no use of LDS.
4570 if (TgSplit)
4571 return false;
4572
4573 // If there are no memory operands then conservatively assume the flat
4574 // operation may access LDS.
4575 if (MI.memoperands_empty())
4576 return true;
4577
4578 // See if any memory operand specifies an address space that involves LDS.
4579 for (const MachineMemOperand *Memop : MI.memoperands()) {
4580 unsigned AS = Memop->getAddrSpace();
4582 return true;
4583 }
4584
4585 return false;
4586}
4587
4589 // Skip the full operand and register alias search modifiesRegister
4590 // does. There's only a handful of instructions that touch this, it's only an
4591 // implicit def, and doesn't alias any other registers.
4592 return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
4593}
4594
4596 unsigned Opcode = MI.getOpcode();
4597
4598 if (MI.mayStore() && isSMRD(MI))
4599 return true; // scalar store or atomic
4600
4601 // This will terminate the function when other lanes may need to continue.
4602 if (MI.isReturn())
4603 return true;
4604
4605 // These instructions cause shader I/O that may cause hardware lockups
4606 // when executed with an empty EXEC mask.
4607 //
4608 // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
4609 // EXEC = 0, but checking for that case here seems not worth it
4610 // given the typical code patterns.
4611 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4612 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4613 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4614 Opcode == AMDGPU::S_SETHALT)
4615 return true;
4616
4617 if (MI.isCall() || MI.isInlineAsm())
4618 return true; // conservative assumption
4619
4620 // Assume that barrier interactions are only intended with active lanes.
4621 if (isBarrier(Opcode))
4622 return true;
4623
4624 // A mode change is a scalar operation that influences vector instructions.
4626 return true;
4627
4628 // These are like SALU instructions in terms of effects, so it's questionable
4629 // whether we should return true for those.
4630 //
4631 // However, executing them with EXEC = 0 causes them to operate on undefined
4632 // data, which we avoid by returning true here.
4633 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4634 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4635 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4636 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4637 return true;
4638
4639 return false;
4640}
4641
4643 const MachineInstr &MI) const {
4644 if (MI.isMetaInstruction())
4645 return false;
4646
4647 // This won't read exec if this is an SGPR->SGPR copy.
4648 if (MI.isCopyLike()) {
4649 if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
4650 return true;
4651
4652 // Make sure this isn't copying exec as a normal operand
4653 return MI.readsRegister(AMDGPU::EXEC, &RI);
4654 }
4655
4656 // Make a conservative assumption about the callee.
4657 if (MI.isCall())
4658 return true;
4659
4660 // Be conservative with any unhandled generic opcodes.
4661 if (!isTargetSpecificOpcode(MI.getOpcode()))
4662 return true;
4663
4664 return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
4665}
4666
4667bool SIInstrInfo::isInlineConstant(const APInt &Imm) const {
4668 switch (Imm.getBitWidth()) {
4669 case 1: // This likely will be a condition code mask.
4670 return true;
4671
4672 case 32:
4673 return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
4674 ST.hasInv2PiInlineImm());
4675 case 64:
4676 return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
4677 ST.hasInv2PiInlineImm());
4678 case 16:
4679 return ST.has16BitInsts() &&
4680 AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
4681 ST.hasInv2PiInlineImm());
4682 default:
4683 llvm_unreachable("invalid bitwidth");
4684 }
4685}
4686
4688 APInt IntImm = Imm.bitcastToAPInt();
4689 int64_t IntImmVal = IntImm.getSExtValue();
4690 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4691 switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
4692 default:
4693 llvm_unreachable("invalid fltSemantics");
4696 return isInlineConstant(IntImm);
4698 return ST.has16BitInsts() &&
4699 AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
4701 return ST.has16BitInsts() &&
4702 AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
4703 }
4704}
4705
4706bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
4707 // MachineOperand provides no way to tell the true operand size, since it only
4708 // records a 64-bit value. We need to know the size to determine if a 32-bit
4709 // floating point immediate bit pattern is legal for an integer immediate. It
4710 // would be for any 32-bit integer operand, but would not be for a 64-bit one.
4711 switch (OperandType) {
4721 int32_t Trunc = static_cast<int32_t>(Imm);
4722 return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
4723 }
4731 return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
4734 // We would expect inline immediates to not be concerned with an integer/fp
4735 // distinction. However, in the case of 16-bit integer operations, the
4736 // "floating point" values appear to not work. It seems read the low 16-bits
4737 // of 32-bit immediates, which happens to always work for the integer
4738 // values.
4739 //
4740 // See llvm bugzilla 46302.
4741 //
4742 // TODO: Theoretically we could use op-sel to use the high bits of the
4743 // 32-bit FP values.
4752 return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
4757 return false;
4760 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
4761 // A few special case instructions have 16-bit operands on subtargets
4762 // where 16-bit instructions are not legal.
4763 // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
4764 // constants in these cases
4765 int16_t Trunc = static_cast<int16_t>(Imm);
4766 return ST.has16BitInsts() &&
4767 AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
4768 }
4769
4770 return false;
4771 }
4774 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
4775 int16_t Trunc = static_cast<int16_t>(Imm);
4776 return ST.has16BitInsts() &&
4777 AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
4778 }
4779 return false;
4780 }
4784 return false;
4786 return isLegalAV64PseudoImm(Imm);
4789 // Always embedded in the instruction for free.
4790 return true;
4800 // Just ignore anything else.
4801 return false;
4802 default:
4803 llvm_unreachable("invalid operand type");
4804 }
4805}
4806
4807static bool compareMachineOp(const MachineOperand &Op0,
4808 const MachineOperand &Op1) {
4809 if (Op0.getType() != Op1.getType())
4810 return false;
4811
4812 switch (Op0.getType()) {
4814 return Op0.getReg() == Op1.getReg();
4816 return Op0.getImm() == Op1.getImm();
4817 default:
4818 llvm_unreachable("Didn't expect to be comparing these operand types");
4819 }
4820}
4821
4823 const MCOperandInfo &OpInfo) const {
4824 if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
4825 return true;
4826
4827 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
4828 return false;
4829
4830 if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
4831 return true;
4832
4833 return ST.hasVOP3Literal();
4834}
4835
4836bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
4837 int64_t ImmVal) const {
4838 const unsigned Opc = InstDesc.getOpcode();
4839 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
4840 if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
4841 OpNo == static_cast<unsigned>(Src1Idx))
4842 return false;
4843
4844 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
4845 if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
4846 if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
4847 OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
4848 AMDGPU::OpName::src2))
4849 return false;
4850 return RI.opCanUseInlineConstant(OpInfo.OperandType);
4851 }
4852
4853 return isLiteralOperandLegal(InstDesc, OpInfo);
4854}
4855
4856bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
4857 const MachineOperand &MO) const {
4858 if (MO.isImm())
4859 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
4860
4861 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
4862 "unexpected imm-like operand kind");
4863 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
4864 return isLiteralOperandLegal(InstDesc, OpInfo);
4865}
4866
4868 // 2 32-bit inline constants packed into one.
4869 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
4870 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
4871}
4872
4873bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
4874 // GFX90A does not have V_MUL_LEGACY_F32_e32.
4875 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
4876 return false;
4877
4878 int Op32 = AMDGPU::getVOPe32(Opcode);
4879 if (Op32 == -1)
4880 return false;
4881
4882 return pseudoToMCOpcode(Op32) != -1;
4883}
4884
4885bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
4886 // The src0_modifier operand is present on all instructions
4887 // that have modifiers.
4888
4889 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
4890}
4891
4893 AMDGPU::OpName OpName) const {
4894 const MachineOperand *Mods = getNamedOperand(MI, OpName);
4895 return Mods && Mods->getImm();
4896}
4897
4899 return any_of(ModifierOpNames,
4900 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
4901}
4902
4904 const MachineRegisterInfo &MRI) const {
4905 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4906 // Can't shrink instruction with three operands.
4907 if (Src2) {
4908 switch (MI.getOpcode()) {
4909 default: return false;
4910
4911 case AMDGPU::V_ADDC_U32_e64:
4912 case AMDGPU::V_SUBB_U32_e64:
4913 case AMDGPU::V_SUBBREV_U32_e64: {
4914 const MachineOperand *Src1
4915 = getNamedOperand(MI, AMDGPU::OpName::src1);
4916 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
4917 return false;
4918 // Additional verification is needed for sdst/src2.
4919 return true;
4920 }
4921 case AMDGPU::V_MAC_F16_e64:
4922 case AMDGPU::V_MAC_F32_e64:
4923 case AMDGPU::V_MAC_LEGACY_F32_e64:
4924 case AMDGPU::V_FMAC_F16_e64:
4925 case AMDGPU::V_FMAC_F16_t16_e64:
4926 case AMDGPU::V_FMAC_F16_fake16_e64:
4927 case AMDGPU::V_FMAC_F32_e64:
4928 case AMDGPU::V_FMAC_F64_e64:
4929 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4930 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
4931 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
4932 return false;
4933 break;
4934
4935 case AMDGPU::V_CNDMASK_B32_e64:
4936 break;
4937 }
4938 }
4939
4940 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4941 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
4942 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
4943 return false;
4944
4945 // We don't need to check src0, all input types are legal, so just make sure
4946 // src0 isn't using any modifiers.
4947 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
4948 return false;
4949
4950 // Can it be shrunk to a valid 32 bit opcode?
4951 if (!hasVALU32BitEncoding(MI.getOpcode()))
4952 return false;
4953
4954 // Check output modifiers
4955 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
4956 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
4957 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
4958 // TODO: Can we avoid checking bound_ctrl/fi here?
4959 // They are only used by permlane*_swap special case.
4960 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
4961 !hasModifiersSet(MI, AMDGPU::OpName::fi);
4962}
4963
4964// Set VCC operand with all flags from \p Orig, except for setting it as
4965// implicit.
4967 const MachineOperand &Orig) {
4968
4969 for (MachineOperand &Use : MI.implicit_operands()) {
4970 if (Use.isUse() &&
4971 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
4972 Use.setIsUndef(Orig.isUndef());
4973 Use.setIsKill(Orig.isKill());
4974 return;
4975 }
4976 }
4977}
4978
4980 unsigned Op32) const {
4981 MachineBasicBlock *MBB = MI.getParent();
4982
4983 const MCInstrDesc &Op32Desc = get(Op32);
4984 MachineInstrBuilder Inst32 =
4985 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
4986 .setMIFlags(MI.getFlags());
4987
4988 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
4989 // For VOPC instructions, this is replaced by an implicit def of vcc.
4990
4991 // We assume the defs of the shrunk opcode are in the same order, and the
4992 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
4993 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
4994 Inst32.add(MI.getOperand(I));
4995
4996 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4997
4998 int Idx = MI.getNumExplicitDefs();
4999 for (const MachineOperand &Use : MI.explicit_uses()) {
5000 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
5002 continue;
5003
5004 if (&Use == Src2) {
5005 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5006 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
5007 // replaced with an implicit read of vcc or vcc_lo. The implicit read
5008 // of vcc was already added during the initial BuildMI, but we
5009 // 1) may need to change vcc to vcc_lo to preserve the original register
5010 // 2) have to preserve the original flags.
5011 copyFlagsToImplicitVCC(*Inst32, *Src2);
5012 continue;
5013 }
5014 }
5015
5016 Inst32.add(Use);
5017 }
5018
5019 // FIXME: Losing implicit operands
5020 fixImplicitOperands(*Inst32);
5021 return Inst32;
5022}
5023
5025 // Null is free
5026 Register Reg = RegOp.getReg();
5027 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5028 return false;
5029
5030 // SGPRs use the constant bus
5031
5032 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
5033 // physical register operands should also count, except for exec.
5034 if (RegOp.isImplicit())
5035 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5036
5037 // SGPRs use the constant bus
5038 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5039 AMDGPU::SReg_64RegClass.contains(Reg);
5040}
5041
5043 const MachineRegisterInfo &MRI) const {
5044 Register Reg = RegOp.getReg();
5045 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5046 : physRegUsesConstantBus(RegOp);
5047}
5048
5050 const MachineOperand &MO,
5051 const MCOperandInfo &OpInfo) const {
5052 // Literal constants use the constant bus.
5053 if (!MO.isReg())
5054 return !isInlineConstant(MO, OpInfo);
5055
5056 Register Reg = MO.getReg();
5057 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
5059}
5060
5062 for (const MachineOperand &MO : MI.implicit_operands()) {
5063 // We only care about reads.
5064 if (MO.isDef())
5065 continue;
5066
5067 switch (MO.getReg()) {
5068 case AMDGPU::VCC:
5069 case AMDGPU::VCC_LO:
5070 case AMDGPU::VCC_HI:
5071 case AMDGPU::M0:
5072 case AMDGPU::FLAT_SCR:
5073 return MO.getReg();
5074
5075 default:
5076 break;
5077 }
5078 }
5079
5080 return Register();
5081}
5082
5083static bool shouldReadExec(const MachineInstr &MI) {
5084 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5085 switch (MI.getOpcode()) {
5086 case AMDGPU::V_READLANE_B32:
5087 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5088 case AMDGPU::V_WRITELANE_B32:
5089 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5090 return false;
5091 }
5092
5093 return true;
5094 }
5095
5096 if (MI.isPreISelOpcode() ||
5097 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5100 return false;
5101
5102 return true;
5103}
5104
5105static bool isRegOrFI(const MachineOperand &MO) {
5106 return MO.isReg() || MO.isFI();
5107}
5108
5109static bool isSubRegOf(const SIRegisterInfo &TRI,
5110 const MachineOperand &SuperVec,
5111 const MachineOperand &SubReg) {
5112 if (SubReg.getReg().isPhysical())
5113 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5114
5115 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5116 SubReg.getReg() == SuperVec.getReg();
5117}
5118
5119// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5120bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5121 const MachineRegisterInfo &MRI,
5122 StringRef &ErrInfo) const {
5123 Register DstReg = MI.getOperand(0).getReg();
5124 Register SrcReg = MI.getOperand(1).getReg();
5125 // This is a check for copy from vector register to SGPR
5126 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5127 ErrInfo = "illegal copy from vector register to SGPR";
5128 return false;
5129 }
5130 return true;
5131}
5132
5134 StringRef &ErrInfo) const {
5135 uint32_t Opcode = MI.getOpcode();
5136 const MachineFunction *MF = MI.getMF();
5137 const MachineRegisterInfo &MRI = MF->getRegInfo();
5138
5139 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5140 // Find a better property to recognize the point where instruction selection
5141 // is just done.
5142 // We can only enforce this check after SIFixSGPRCopies pass so that the
5143 // illegal copies are legalized and thereafter we don't expect a pass
5144 // inserting similar copies.
5145 if (!MRI.isSSA() && MI.isCopy())
5146 return verifyCopy(MI, MRI, ErrInfo);
5147
5148 if (SIInstrInfo::isGenericOpcode(Opcode))
5149 return true;
5150
5151 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5152 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5153 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5154 int Src3Idx = -1;
5155 if (Src0Idx == -1) {
5156 // VOPD V_DUAL_* instructions use different operand names.
5157 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5158 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5159 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5160 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5161 }
5162
5163 // Make sure the number of operands is correct.
5164 const MCInstrDesc &Desc = get(Opcode);
5165 if (!Desc.isVariadic() &&
5166 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5167 ErrInfo = "Instruction has wrong number of operands.";
5168 return false;
5169 }
5170
5171 if (MI.isInlineAsm()) {
5172 // Verify register classes for inlineasm constraints.
5173 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5174 I != E; ++I) {
5175 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5176 if (!RC)
5177 continue;
5178
5179 const MachineOperand &Op = MI.getOperand(I);
5180 if (!Op.isReg())
5181 continue;
5182
5183 Register Reg = Op.getReg();
5184 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5185 ErrInfo = "inlineasm operand has incorrect register class.";
5186 return false;
5187 }
5188 }
5189
5190 return true;
5191 }
5192
5193 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5194 ErrInfo = "missing memory operand from image instruction.";
5195 return false;
5196 }
5197
5198 // Make sure the register classes are correct.
5199 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5200 const MachineOperand &MO = MI.getOperand(i);
5201 if (MO.isFPImm()) {
5202 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5203 "all fp values to integers.";
5204 return false;
5205 }
5206
5207 const MCOperandInfo &OpInfo = Desc.operands()[i];
5208 int16_t RegClass = getOpRegClassID(OpInfo);
5209
5210 switch (OpInfo.OperandType) {
5212 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5213 ErrInfo = "Illegal immediate value for operand.";
5214 return false;
5215 }
5216 break;
5228 break;
5230 break;
5231 break;
5245 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5246 ErrInfo = "Illegal immediate value for operand.";
5247 return false;
5248 }
5249 break;
5250 }
5255 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5256 !isInlineConstant(MI, i) &&
5258 OpInfo.OperandType ==
5260 ErrInfo = "illegal 64-bit immediate value for operand.";
5261 return false;
5262 }
5263 break;
5266 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5267 ErrInfo = "Expected inline constant for operand.";
5268 return false;
5269 }
5270 break;
5273 break;
5278 // Check if this operand is an immediate.
5279 // FrameIndex operands will be replaced by immediates, so they are
5280 // allowed.
5281 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5282 ErrInfo = "Expected immediate, but got non-immediate";
5283 return false;
5284 }
5285 break;
5289 break;
5290 default:
5291 if (OpInfo.isGenericType())
5292 continue;
5293 break;
5294 }
5295
5296 if (!MO.isReg())
5297 continue;
5298 Register Reg = MO.getReg();
5299 if (!Reg)
5300 continue;
5301
5302 // FIXME: Ideally we would have separate instruction definitions with the
5303 // aligned register constraint.
5304 // FIXME: We do not verify inline asm operands, but custom inline asm
5305 // verification is broken anyway
5306 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5307 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !isSpill(MI)) {
5308 const TargetRegisterClass *RC = RI.getRegClassForReg(MRI, Reg);
5309 if (RI.hasVectorRegisters(RC) && MO.getSubReg()) {
5310 if (const TargetRegisterClass *SubRC =
5311 RI.getSubRegisterClass(RC, MO.getSubReg())) {
5312 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.getSubReg());
5313 if (RC)
5314 RC = SubRC;
5315 }
5316 }
5317
5318 // Check that this is the aligned version of the class.
5319 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5320 ErrInfo = "Subtarget requires even aligned vector registers";
5321 return false;
5322 }
5323 }
5324
5325 if (RegClass != -1) {
5326 if (Reg.isVirtual())
5327 continue;
5328
5329 const TargetRegisterClass *RC = RI.getRegClass(RegClass);
5330 if (!RC->contains(Reg)) {
5331 ErrInfo = "Operand has incorrect register class.";
5332 return false;
5333 }
5334 }
5335 }
5336
5337 // Verify SDWA
5338 if (isSDWA(MI)) {
5339 if (!ST.hasSDWA()) {
5340 ErrInfo = "SDWA is not supported on this target";
5341 return false;
5342 }
5343
5344 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5345 AMDGPU::OpName::dst_sel}) {
5346 const MachineOperand *MO = getNamedOperand(MI, Op);
5347 if (!MO)
5348 continue;
5349 int64_t Imm = MO->getImm();
5350 if (Imm < 0 || Imm > AMDGPU::SDWA::SdwaSel::DWORD) {
5351 ErrInfo = "Invalid SDWA selection";
5352 return false;
5353 }
5354 }
5355
5356 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5357
5358 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5359 if (OpIdx == -1)
5360 continue;
5361 const MachineOperand &MO = MI.getOperand(OpIdx);
5362
5363 if (!ST.hasSDWAScalar()) {
5364 // Only VGPRS on VI
5365 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5366 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5367 return false;
5368 }
5369 } else {
5370 // No immediates on GFX9
5371 if (!MO.isReg()) {
5372 ErrInfo =
5373 "Only reg allowed as operands in SDWA instructions on GFX9+";
5374 return false;
5375 }
5376 }
5377 }
5378
5379 if (!ST.hasSDWAOmod()) {
5380 // No omod allowed on VI
5381 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5382 if (OMod != nullptr &&
5383 (!OMod->isImm() || OMod->getImm() != 0)) {
5384 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5385 return false;
5386 }
5387 }
5388
5389 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5390 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5391 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5392 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5393 const MachineOperand *Src0ModsMO =
5394 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5395 unsigned Mods = Src0ModsMO->getImm();
5396 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5397 Mods & SISrcMods::SEXT) {
5398 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5399 return false;
5400 }
5401 }
5402
5403 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5404 if (isVOPC(BasicOpcode)) {
5405 if (!ST.hasSDWASdst() && DstIdx != -1) {
5406 // Only vcc allowed as dst on VI for VOPC
5407 const MachineOperand &Dst = MI.getOperand(DstIdx);
5408 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5409 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5410 return false;
5411 }
5412 } else if (!ST.hasSDWAOutModsVOPC()) {
5413 // No clamp allowed on GFX9 for VOPC
5414 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5415 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5416 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5417 return false;
5418 }
5419
5420 // No omod allowed on GFX9 for VOPC
5421 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5422 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5423 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5424 return false;
5425 }
5426 }
5427 }
5428
5429 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5430 if (DstUnused && DstUnused->isImm() &&
5431 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5432 const MachineOperand &Dst = MI.getOperand(DstIdx);
5433 if (!Dst.isReg() || !Dst.isTied()) {
5434 ErrInfo = "Dst register should have tied register";
5435 return false;
5436 }
5437
5438 const MachineOperand &TiedMO =
5439 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5440 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5441 ErrInfo =
5442 "Dst register should be tied to implicit use of preserved register";
5443 return false;
5444 }
5445 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5446 ErrInfo = "Dst register should use same physical register as preserved";
5447 return false;
5448 }
5449 }
5450 }
5451
5452 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5453 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5454 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5455 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5456 return false;
5457 }
5458 if (Src1MO.isImm()) {
5459 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5460 return false;
5461 }
5462 }
5463
5464 // Verify MIMG / VIMAGE / VSAMPLE
5465 if (isImage(Opcode) && !MI.mayStore()) {
5466 // Ensure that the return type used is large enough for all the options
5467 // being used TFE/LWE require an extra result register.
5468 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5469 if (DMask) {
5470 uint64_t DMaskImm = DMask->getImm();
5471 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5472 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5473 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5474 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5475
5476 // Adjust for packed 16 bit values
5477 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5478 RegCount = divideCeil(RegCount, 2);
5479
5480 // Adjust if using LWE or TFE
5481 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5482 RegCount += 1;
5483
5484 const uint32_t DstIdx =
5485 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5486 const MachineOperand &Dst = MI.getOperand(DstIdx);
5487 if (Dst.isReg()) {
5488 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5489 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5490 if (RegCount > DstSize) {
5491 ErrInfo = "Image instruction returns too many registers for dst "
5492 "register class";
5493 return false;
5494 }
5495 }
5496 }
5497 }
5498
5499 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5500 if (isVALU(MI, /*AllowLDSDMA=*/true) &&
5501 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5502 unsigned ConstantBusCount = 0;
5503 bool UsesLiteral = false;
5504 const MachineOperand *LiteralVal = nullptr;
5505
5506 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5507 if (ImmIdx != -1) {
5508 ++ConstantBusCount;
5509 UsesLiteral = true;
5510 LiteralVal = &MI.getOperand(ImmIdx);
5511 }
5512
5513 SmallVector<Register, 2> SGPRsUsed;
5514 Register SGPRUsed;
5515
5516 // Only look at the true operands. Only a real operand can use the constant
5517 // bus, and we don't want to check pseudo-operands like the source modifier
5518 // flags.
5519 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5520 if (OpIdx == -1)
5521 continue;
5522 const MachineOperand &MO = MI.getOperand(OpIdx);
5523 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5524 if (MO.isReg()) {
5525 SGPRUsed = MO.getReg();
5526 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5527 ++ConstantBusCount;
5528 SGPRsUsed.push_back(SGPRUsed);
5529 }
5530 } else if (!MO.isFI()) { // Treat FI like a register.
5531 if (!UsesLiteral) {
5532 ++ConstantBusCount;
5533 UsesLiteral = true;
5534 LiteralVal = &MO;
5535 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5536 assert(isVOP2(MI) || isVOP3(MI));
5537 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5538 return false;
5539 }
5540 }
5541 }
5542 }
5543
5544 SGPRUsed = findImplicitSGPRRead(MI);
5545 if (SGPRUsed) {
5546 // Implicit uses may safely overlap true operands
5547 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5548 return !RI.regsOverlap(SGPRUsed, SGPR);
5549 })) {
5550 ++ConstantBusCount;
5551 SGPRsUsed.push_back(SGPRUsed);
5552 }
5553 }
5554
5555 // v_writelane_b32 is an exception from constant bus restriction:
5556 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5557 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5558 Opcode != AMDGPU::V_WRITELANE_B32) {
5559 ErrInfo = "VOP* instruction violates constant bus restriction";
5560 return false;
5561 }
5562
5563 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5564 ErrInfo = "VOP3 instruction uses literal";
5565 return false;
5566 }
5567 }
5568
5569 // Special case for writelane - this can break the multiple constant bus rule,
5570 // but still can't use more than one SGPR register
5571 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5572 unsigned SGPRCount = 0;
5573 Register SGPRUsed;
5574
5575 for (int OpIdx : {Src0Idx, Src1Idx}) {
5576 if (OpIdx == -1)
5577 break;
5578
5579 const MachineOperand &MO = MI.getOperand(OpIdx);
5580
5581 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5582 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5583 if (MO.getReg() != SGPRUsed)
5584 ++SGPRCount;
5585 SGPRUsed = MO.getReg();
5586 }
5587 }
5588 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5589 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5590 return false;
5591 }
5592 }
5593 }
5594
5595 // Verify misc. restrictions on specific instructions.
5596 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5597 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5598 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5599 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5600 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
5601 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5602 if (!compareMachineOp(Src0, Src1) &&
5603 !compareMachineOp(Src0, Src2)) {
5604 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
5605 return false;
5606 }
5607 }
5608 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
5609 SISrcMods::ABS) ||
5610 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
5611 SISrcMods::ABS) ||
5612 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
5613 SISrcMods::ABS)) {
5614 ErrInfo = "ABS not allowed in VOP3B instructions";
5615 return false;
5616 }
5617 }
5618
5619 if (isSOP2(MI) || isSOPC(MI)) {
5620 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5621 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5622
5623 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
5624 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
5625 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
5626 !Src0.isIdenticalTo(Src1)) {
5627 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
5628 return false;
5629 }
5630 }
5631
5632 if (isSOPK(MI)) {
5633 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
5634 if (Desc.isBranch()) {
5635 if (!Op->isMBB()) {
5636 ErrInfo = "invalid branch target for SOPK instruction";
5637 return false;
5638 }
5639 } else {
5640 uint64_t Imm = Op->getImm();
5641 if (sopkIsZext(Opcode)) {
5642 if (!isUInt<16>(Imm)) {
5643 ErrInfo = "invalid immediate for SOPK instruction";
5644 return false;
5645 }
5646 } else {
5647 if (!isInt<16>(Imm)) {
5648 ErrInfo = "invalid immediate for SOPK instruction";
5649 return false;
5650 }
5651 }
5652 }
5653 }
5654
5655 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5656 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5657 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5658 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5659 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5660 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5661
5662 const unsigned StaticNumOps =
5663 Desc.getNumOperands() + Desc.implicit_uses().size();
5664 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5665
5666 // Require additional implicit operands. This allows a fixup done by the
5667 // post RA scheduler where the main implicit operand is killed and
5668 // implicit-defs are added for sub-registers that remain live after this
5669 // instruction.
5670 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5671 ErrInfo = "missing implicit register operands";
5672 return false;
5673 }
5674
5675 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5676 if (IsDst) {
5677 if (!Dst->isUse()) {
5678 ErrInfo = "v_movreld_b32 vdst should be a use operand";
5679 return false;
5680 }
5681
5682 unsigned UseOpIdx;
5683 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5684 UseOpIdx != StaticNumOps + 1) {
5685 ErrInfo = "movrel implicit operands should be tied";
5686 return false;
5687 }
5688 }
5689
5690 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5691 const MachineOperand &ImpUse
5692 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5693 if (!ImpUse.isReg() || !ImpUse.isUse() ||
5694 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5695 ErrInfo = "src0 should be subreg of implicit vector use";
5696 return false;
5697 }
5698 }
5699
5700 // Make sure we aren't losing exec uses in the td files. This mostly requires
5701 // being careful when using let Uses to try to add other use registers.
5702 if (shouldReadExec(MI)) {
5703 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5704 ErrInfo = "VALU instruction does not implicitly read exec mask";
5705 return false;
5706 }
5707 }
5708
5709 if (isSMRD(MI)) {
5710 if (MI.mayStore() &&
5711 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
5712 // The register offset form of scalar stores may only use m0 as the
5713 // soffset register.
5714 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
5715 if (Soff && Soff->getReg() != AMDGPU::M0) {
5716 ErrInfo = "scalar stores must use m0 as offset register";
5717 return false;
5718 }
5719 }
5720 }
5721
5722 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
5723 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
5724 if (Offset->getImm() != 0) {
5725 ErrInfo = "subtarget does not support offsets in flat instructions";
5726 return false;
5727 }
5728 }
5729
5730 if (isDS(MI) && !ST.hasGDS()) {
5731 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
5732 if (GDSOp && GDSOp->getImm() != 0) {
5733 ErrInfo = "GDS is not supported on this subtarget";
5734 return false;
5735 }
5736 }
5737
5738 if (isImage(MI)) {
5739 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
5740 if (DimOp) {
5741 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5742 AMDGPU::OpName::vaddr0);
5743 AMDGPU::OpName RSrcOpName =
5744 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5745 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5746 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
5747 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
5748 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
5749 const AMDGPU::MIMGDimInfo *Dim =
5751
5752 if (!Dim) {
5753 ErrInfo = "dim is out of range";
5754 return false;
5755 }
5756
5757 bool IsA16 = false;
5758 if (ST.hasR128A16()) {
5759 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
5760 IsA16 = R128A16->getImm() != 0;
5761 } else if (ST.hasA16()) {
5762 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
5763 IsA16 = A16->getImm() != 0;
5764 }
5765
5766 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5767
5768 unsigned AddrWords =
5769 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
5770
5771 unsigned VAddrWords;
5772 if (IsNSA) {
5773 VAddrWords = RsrcIdx - VAddr0Idx;
5774 if (ST.hasPartialNSAEncoding() &&
5775 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
5776 unsigned LastVAddrIdx = RsrcIdx - 1;
5777 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
5778 }
5779 } else {
5780 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
5781 if (AddrWords > 12)
5782 AddrWords = 16;
5783 }
5784
5785 if (VAddrWords != AddrWords) {
5786 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
5787 << " but got " << VAddrWords << "\n");
5788 ErrInfo = "bad vaddr size";
5789 return false;
5790 }
5791 }
5792 }
5793
5794 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
5795 if (DppCt) {
5796 using namespace AMDGPU::DPP;
5797
5798 unsigned DC = DppCt->getImm();
5799 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5800 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5801 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5802 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5803 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5804 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5805 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5806 ErrInfo = "Invalid dpp_ctrl value";
5807 return false;
5808 }
5809 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5810 !ST.hasDPPWavefrontShifts()) {
5811 ErrInfo = "Invalid dpp_ctrl value: "
5812 "wavefront shifts are not supported on GFX10+";
5813 return false;
5814 }
5815 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5816 !ST.hasDPPBroadcasts()) {
5817 ErrInfo = "Invalid dpp_ctrl value: "
5818 "broadcasts are not supported on GFX10+";
5819 return false;
5820 }
5821 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
5822 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
5823 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
5824 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
5825 !ST.hasGFX90AInsts()) {
5826 ErrInfo = "Invalid dpp_ctrl value: "
5827 "row_newbroadcast/row_share is not supported before "
5828 "GFX90A/GFX10";
5829 return false;
5830 }
5831 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
5832 ErrInfo = "Invalid dpp_ctrl value: "
5833 "row_share and row_xmask are not supported before GFX10";
5834 return false;
5835 }
5836 }
5837
5838 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
5840 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
5841 ErrInfo = "Invalid dpp_ctrl value: "
5842 "DP ALU dpp only support row_newbcast";
5843 return false;
5844 }
5845 }
5846
5847 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
5848 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5849 AMDGPU::OpName DataName =
5850 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
5851 const MachineOperand *Data = getNamedOperand(MI, DataName);
5852 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
5853 if (Data && !Data->isReg())
5854 Data = nullptr;
5855
5856 if (ST.hasGFX90AInsts()) {
5857 if (Dst && Data && !Dst->isTied() && !Data->isTied() &&
5858 (RI.isAGPR(MRI, Dst->getReg()) != RI.isAGPR(MRI, Data->getReg()))) {
5859 ErrInfo = "Invalid register class: "
5860 "vdata and vdst should be both VGPR or AGPR";
5861 return false;
5862 }
5863 if (Data && Data2 &&
5864 (RI.isAGPR(MRI, Data->getReg()) != RI.isAGPR(MRI, Data2->getReg()))) {
5865 ErrInfo = "Invalid register class: "
5866 "both data operands should be VGPR or AGPR";
5867 return false;
5868 }
5869 } else {
5870 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
5871 (Data && RI.isAGPR(MRI, Data->getReg())) ||
5872 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
5873 ErrInfo = "Invalid register class: "
5874 "agpr loads and stores not supported on this GPU";
5875 return false;
5876 }
5877 }
5878 }
5879
5880 if (ST.needsAlignedVGPRs()) {
5881 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
5883 if (!Op)
5884 return true;
5885 Register Reg = Op->getReg();
5886 if (Reg.isPhysical())
5887 return !(RI.getHWRegIndex(Reg) & 1);
5888 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
5889 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
5890 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
5891 };
5892
5893 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
5894 Opcode == AMDGPU::DS_GWS_BARRIER) {
5895
5896 if (!isAlignedReg(AMDGPU::OpName::data0)) {
5897 ErrInfo = "Subtarget requires even aligned vector registers "
5898 "for DS_GWS instructions";
5899 return false;
5900 }
5901 }
5902
5903 if (isMIMG(MI)) {
5904 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
5905 ErrInfo = "Subtarget requires even aligned vector registers "
5906 "for vaddr operand of image instructions";
5907 return false;
5908 }
5909 }
5910 }
5911
5912 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
5913 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
5914 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
5915 ErrInfo = "Invalid register class: "
5916 "v_accvgpr_write with an SGPR is not supported on this GPU";
5917 return false;
5918 }
5919 }
5920
5921 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
5922 const MachineOperand &SrcOp = MI.getOperand(1);
5923 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
5924 ErrInfo = "pseudo expects only physical SGPRs";
5925 return false;
5926 }
5927 }
5928
5929 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
5930 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
5931 if (!ST.hasScaleOffset()) {
5932 ErrInfo = "Subtarget does not support offset scaling";
5933 return false;
5934 }
5935 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
5936 ErrInfo = "Instruction does not support offset scaling";
5937 return false;
5938 }
5939 }
5940 }
5941
5942 // See SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand for more
5943 // information.
5945 for (unsigned I = 0; I < 3; ++I) {
5947 return false;
5948 }
5949 }
5950
5951 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
5952 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
5953 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
5954 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
5955 &AMDGPU::SReg_64RegClass) ||
5956 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
5957 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
5958 return false;
5959 }
5960 }
5961
5962 return true;
5963}
5964
5966 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
5967 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
5968 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
5969 ? AMDGPU::COPY
5970 : AMDGPU::V_MOV_B32_e32;
5971 }
5972 return getVALUOp(MI.getOpcode());
5973}
5974
5975// It is more readable to list mapped opcodes on the same line.
5976// clang-format off
5977
5978unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
5979 switch (Opc) {
5980 default: return AMDGPU::INSTRUCTION_LIST_END;
5981 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
5982 case AMDGPU::COPY: return AMDGPU::COPY;
5983 case AMDGPU::PHI: return AMDGPU::PHI;
5984 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
5985 case AMDGPU::WQM: return AMDGPU::WQM;
5986 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
5987 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
5988 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
5989 case AMDGPU::S_ADD_I32:
5990 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
5991 case AMDGPU::S_ADDC_U32:
5992 return AMDGPU::V_ADDC_U32_e32;
5993 case AMDGPU::S_SUB_I32:
5994 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
5995 // FIXME: These are not consistently handled, and selected when the carry is
5996 // used.
5997 case AMDGPU::S_ADD_U32:
5998 return AMDGPU::V_ADD_CO_U32_e32;
5999 case AMDGPU::S_SUB_U32:
6000 return AMDGPU::V_SUB_CO_U32_e32;
6001 case AMDGPU::S_ADD_U64_PSEUDO:
6002 return AMDGPU::V_ADD_U64_PSEUDO;
6003 case AMDGPU::S_SUB_U64_PSEUDO:
6004 return AMDGPU::V_SUB_U64_PSEUDO;
6005 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
6006 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
6007 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
6008 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
6009 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
6010 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
6011 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
6012 case AMDGPU::S_XNOR_B32:
6013 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6014 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
6015 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
6016 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
6017 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
6018 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
6019 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
6020 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
6021 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
6022 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
6023 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
6024 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
6025 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
6026 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
6027 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
6028 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
6029 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
6030 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
6031 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
6032 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
6033 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
6034 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
6035 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
6036 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
6037 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
6038 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
6039 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
6040 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
6041 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
6042 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
6043 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
6044 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
6045 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
6046 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
6047 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
6048 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
6049 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
6050 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
6051 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
6052 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
6053 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
6054 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
6055 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
6056 case AMDGPU::S_CVT_F32_F16:
6057 case AMDGPU::S_CVT_HI_F32_F16:
6058 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6059 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6060 case AMDGPU::S_CVT_F16_F32:
6061 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6062 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6063 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
6064 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
6065 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
6066 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
6067 case AMDGPU::S_CEIL_F16:
6068 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6069 : AMDGPU::V_CEIL_F16_fake16_e64;
6070 case AMDGPU::S_FLOOR_F16:
6071 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6072 : AMDGPU::V_FLOOR_F16_fake16_e64;
6073 case AMDGPU::S_TRUNC_F16:
6074 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6075 : AMDGPU::V_TRUNC_F16_fake16_e64;
6076 case AMDGPU::S_RNDNE_F16:
6077 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6078 : AMDGPU::V_RNDNE_F16_fake16_e64;
6079 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6080 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6081 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6082 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6083 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6084 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6085 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6086 case AMDGPU::S_ADD_F16:
6087 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6088 : AMDGPU::V_ADD_F16_fake16_e64;
6089 case AMDGPU::S_SUB_F16:
6090 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6091 : AMDGPU::V_SUB_F16_fake16_e64;
6092 case AMDGPU::S_MIN_F16:
6093 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6094 : AMDGPU::V_MIN_F16_fake16_e64;
6095 case AMDGPU::S_MAX_F16:
6096 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6097 : AMDGPU::V_MAX_F16_fake16_e64;
6098 case AMDGPU::S_MINIMUM_F16:
6099 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6100 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6101 case AMDGPU::S_MAXIMUM_F16:
6102 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6103 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6104 case AMDGPU::S_MUL_F16:
6105 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6106 : AMDGPU::V_MUL_F16_fake16_e64;
6107 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6108 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6109 case AMDGPU::S_FMAC_F16:
6110 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6111 : AMDGPU::V_FMAC_F16_fake16_e64;
6112 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6113 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6114 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6115 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6116 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6117 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6118 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6119 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6120 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6121 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6122 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6123 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6124 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6125 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6126 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6127 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6128 case AMDGPU::S_CMP_LT_F16:
6129 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6130 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6131 case AMDGPU::S_CMP_EQ_F16:
6132 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6133 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6134 case AMDGPU::S_CMP_LE_F16:
6135 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6136 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6137 case AMDGPU::S_CMP_GT_F16:
6138 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6139 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6140 case AMDGPU::S_CMP_LG_F16:
6141 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6142 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6143 case AMDGPU::S_CMP_GE_F16:
6144 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6145 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6146 case AMDGPU::S_CMP_O_F16:
6147 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6148 : AMDGPU::V_CMP_O_F16_fake16_e64;
6149 case AMDGPU::S_CMP_U_F16:
6150 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6151 : AMDGPU::V_CMP_U_F16_fake16_e64;
6152 case AMDGPU::S_CMP_NGE_F16:
6153 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6154 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6155 case AMDGPU::S_CMP_NLG_F16:
6156 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6157 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6158 case AMDGPU::S_CMP_NGT_F16:
6159 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6160 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6161 case AMDGPU::S_CMP_NLE_F16:
6162 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6163 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6164 case AMDGPU::S_CMP_NEQ_F16:
6165 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6166 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6167 case AMDGPU::S_CMP_NLT_F16:
6168 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6169 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6170 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6171 case AMDGPU::V_S_EXP_F16_e64:
6172 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6173 : AMDGPU::V_EXP_F16_fake16_e64;
6174 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6175 case AMDGPU::V_S_LOG_F16_e64:
6176 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6177 : AMDGPU::V_LOG_F16_fake16_e64;
6178 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6179 case AMDGPU::V_S_RCP_F16_e64:
6180 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6181 : AMDGPU::V_RCP_F16_fake16_e64;
6182 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6183 case AMDGPU::V_S_RSQ_F16_e64:
6184 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6185 : AMDGPU::V_RSQ_F16_fake16_e64;
6186 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6187 case AMDGPU::V_S_SQRT_F16_e64:
6188 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6189 : AMDGPU::V_SQRT_F16_fake16_e64;
6190 }
6192 "Unexpected scalar opcode without corresponding vector one!");
6193}
6194
6195// clang-format on
6196
6200 const DebugLoc &DL, Register Reg,
6201 bool IsSCCLive,
6202 SlotIndexes *Indexes) const {
6203 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6204 const SIInstrInfo *TII = ST.getInstrInfo();
6206 if (IsSCCLive) {
6207 // Insert two move instructions, one to save the original value of EXEC and
6208 // the other to turn on all bits in EXEC. This is required as we can't use
6209 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6210 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6212 auto FlipExecMI =
6213 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6214 if (Indexes) {
6215 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6216 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6217 }
6218 } else {
6219 auto SaveExec =
6220 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6221 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6222 if (Indexes)
6223 Indexes->insertMachineInstrInMaps(*SaveExec);
6224 }
6225}
6226
6229 const DebugLoc &DL, Register Reg,
6230 SlotIndexes *Indexes) const {
6232 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6233 .addReg(Reg, RegState::Kill);
6234 if (Indexes)
6235 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6236}
6237
6241 "Not a whole wave func");
6242 MachineBasicBlock &MBB = *MF.begin();
6243 for (MachineInstr &MI : MBB)
6244 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6245 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6246 return &MI;
6247
6248 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6249}
6250
6252 unsigned OpNo) const {
6253 const MCInstrDesc &Desc = get(MI.getOpcode());
6254 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6255 Desc.operands()[OpNo].RegClass == -1) {
6256 Register Reg = MI.getOperand(OpNo).getReg();
6257
6258 if (Reg.isVirtual()) {
6259 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6260 return MRI.getRegClass(Reg);
6261 }
6262 return RI.getPhysRegBaseClass(Reg);
6263 }
6264
6265 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6266 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6267}
6268
6269// Convert VOP3 operand index to source number.
6270static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx) {
6271 constexpr AMDGPU::OpName OpNames[] = {
6272 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6273
6274 for (auto [I, OpName] : enumerate(OpNames)) {
6275 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6276 if (static_cast<unsigned>(SrcIdx) == OpIdx)
6277 return I;
6278 }
6279
6280 return UINT_MAX;
6281}
6282
6285 MachineBasicBlock *MBB = MI.getParent();
6286 MachineOperand &MO = MI.getOperand(OpIdx);
6287 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6288 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6289 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6290 unsigned Size = RI.getRegSizeInBits(*RC);
6291 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6292 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6293 : AMDGPU::V_MOV_B32_e32;
6294 if (MO.isReg())
6295 Opcode = AMDGPU::COPY;
6296 else if (RI.isSGPRClass(RC))
6297 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6298
6299 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6300 Register Reg = MRI.createVirtualRegister(VRC);
6301 DebugLoc DL = MBB->findDebugLoc(I);
6302
6303 if (Size == 128 && AMDGPU::isPacked64BitInst(MI.getOpcode()) &&
6305 MRI, MI, VOP3OpIdxToSrcN(MI, OpIdx))) {
6306 // Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
6307 // sources behave like OPSEL is set replicating low 64-bits into high. VGPR
6308 // sources in turn read actual 4 registers. To move operand from an SGPR to
6309 // a VGPR we need to replicate low half.
6310 // We also do not select immediates for these instructions so it always has
6311 // to be an SGPR register here.
6312 // Operands which are not legal as per
6313 // isLegalGFX12PlusPackedMathFP32or64BitOperand() sent here specifically to
6314 // fix a non-splat SGPR and shall perform a full copy.
6315
6316 const TargetRegisterClass *VRC64 = RI.getVGPRClassForBitWidth(64);
6317 Register Low64 = MRI.createVirtualRegister(VRC64);
6318 assert(MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()));
6319 BuildMI(*MBB, I, DL, get(TargetOpcode::COPY), Low64)
6320 .addReg(MO.getReg(), {}, AMDGPU::sub0_sub1);
6321 BuildMI(*MBB, I, DL, get(TargetOpcode::REG_SEQUENCE), Reg)
6322 .addReg(Low64)
6323 .addImm(AMDGPU::sub0_sub1)
6324 .addReg(Low64, RegState::Kill)
6325 .addImm(AMDGPU::sub2_sub3);
6326 } else {
6327 BuildMI(*MBB, I, DL, get(Opcode), Reg).add(MO);
6328 }
6329
6330 MO.ChangeToRegister(Reg, false);
6331}
6332
6335 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6336 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6337 if (!SuperReg.getReg().isVirtual())
6338 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6339
6340 MachineBasicBlock *MBB = MI->getParent();
6341 const DebugLoc &DL = MI->getDebugLoc();
6342 Register SubReg = MRI.createVirtualRegister(SubRC);
6343
6344 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6345 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6346 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6347 return SubReg;
6348}
6349
6352 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6353 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6354 if (Op.isImm()) {
6355 if (SubIdx == AMDGPU::sub0)
6356 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6357 if (SubIdx == AMDGPU::sub1)
6358 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6359
6360 llvm_unreachable("Unhandled register index for immediate");
6361 }
6362
6363 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6364 SubIdx, SubRC);
6365 return MachineOperand::CreateReg(SubReg, false);
6366}
6367
6368// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6369void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6370 assert(Inst.getNumExplicitOperands() == 3);
6371 MachineOperand Op1 = Inst.getOperand(1);
6372 Inst.removeOperand(1);
6373 Inst.addOperand(Op1);
6374}
6375
6377 const MCOperandInfo &OpInfo,
6378 const MachineOperand &MO) const {
6379 if (!MO.isReg())
6380 return false;
6381
6382 Register Reg = MO.getReg();
6383
6384 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6385 if (Reg.isPhysical())
6386 return DRC->contains(Reg);
6387
6388 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6389
6390 if (MO.getSubReg()) {
6391 const MachineFunction *MF = MO.getParent()->getMF();
6392 const TargetRegisterClass *SuperRC = RI.getLargestLegalSuperClass(RC, *MF);
6393 if (!SuperRC)
6394 return false;
6395 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6396 }
6397
6398 return RI.getCommonSubClass(DRC, RC) != nullptr;
6399}
6400
6402 const MachineOperand &MO) const {
6403 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6404 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6405 unsigned Opc = MI.getOpcode();
6406
6407 // See SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand for more
6408 // information.
6409 if (AMDGPU::isPackedFP32or64BitInst(MI.getOpcode()) &&
6410 AMDGPU::isGFX12Plus(ST) && MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
6412 MRI, MI, VOP3OpIdxToSrcN(MI, OpIdx), &MO))
6413 return false;
6414
6415 if (!isLegalRegOperand(MRI, OpInfo, MO))
6416 return false;
6417
6418 // check Accumulate GPR operand
6419 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6420 if (IsAGPR && !ST.hasMAIInsts())
6421 return false;
6422 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6423 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6424 return false;
6425 // Atomics should have both vdst and vdata either vgpr or agpr.
6426 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6427 const int DataIdx = AMDGPU::getNamedOperandIdx(
6428 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6429 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6430 MI.getOperand(DataIdx).isReg() &&
6431 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6432 return false;
6433 if ((int)OpIdx == DataIdx) {
6434 if (VDstIdx != -1 &&
6435 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6436 return false;
6437 // DS instructions with 2 src operands also must have tied RC.
6438 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6439 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6440 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6441 return false;
6442 }
6443
6444 // Check V_ACCVGPR_WRITE_B32_e64
6445 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6446 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6447 RI.isSGPRReg(MRI, MO.getReg()))
6448 return false;
6449
6450 if (ST.hasFlatScratchHiInB64InstHazard() &&
6451 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6452 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6453 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6454 64)
6455 return false;
6456 }
6457 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6458 return false;
6459 }
6460 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6461 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6462 return false;
6463
6464 return true;
6465}
6466
6468 const MCOperandInfo &OpInfo,
6469 const MachineOperand &MO) const {
6470 if (MO.isReg())
6471 return isLegalRegOperand(MRI, OpInfo, MO);
6472
6473 // Handle non-register types that are treated like immediates.
6474 assert(MO.isImm() || MO.isTargetIndex() || MO.isFI() || MO.isGlobal());
6475 return true;
6476}
6477
6479 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6480 const MachineOperand *MO) const {
6481 constexpr unsigned NumOps = 3;
6482 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6483 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6484 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6485 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6486
6487 assert(SrcN < NumOps);
6488
6489 if (!MO) {
6490 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6491 if (SrcIdx == -1)
6492 return true;
6493 MO = &MI.getOperand(SrcIdx);
6494 }
6495
6496 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6497 return true;
6498
6499 int ModsIdx =
6500 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6501 if (ModsIdx == -1)
6502 return false;
6503
6504 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6505 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6506 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6507
6508 return !OpSel && !OpSelHi;
6509}
6510
6512 const MachineOperand *MO) const {
6513 const MachineFunction &MF = *MI.getMF();
6514 const MachineRegisterInfo &MRI = MF.getRegInfo();
6515 const MCInstrDesc &InstDesc = MI.getDesc();
6516 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6517 int64_t RegClass = getOpRegClassID(OpInfo);
6518 const TargetRegisterClass *DefinedRC =
6519 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6520 if (!MO)
6521 MO = &MI.getOperand(OpIdx);
6522
6523 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6524
6525 if (isVALU(MI, /*AllowLDSDMA=*/true) && !IsInlineConst &&
6526 usesConstantBus(MRI, *MO, OpInfo)) {
6527 const MachineOperand *UsedLiteral = nullptr;
6528
6529 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6530 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6531
6532 // TODO: Be more permissive with frame indexes.
6533 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6534 if (!LiteralLimit--)
6535 return false;
6536
6537 UsedLiteral = MO;
6538 }
6539
6541 if (MO->isReg())
6542 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6543
6544 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6545 if (i == OpIdx)
6546 continue;
6547 const MachineOperand &Op = MI.getOperand(i);
6548 if (Op.isReg()) {
6549 if (Op.isUse()) {
6550 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6551 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6552 if (--ConstantBusLimit <= 0)
6553 return false;
6554 }
6555 }
6556 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6557 !isInlineConstant(Op, InstDesc.operands()[i])) {
6558 // The same literal may be used multiple times.
6559 if (!UsedLiteral)
6560 UsedLiteral = &Op;
6561 else if (UsedLiteral->isIdenticalTo(Op))
6562 continue;
6563
6564 if (!LiteralLimit--)
6565 return false;
6566 if (--ConstantBusLimit <= 0)
6567 return false;
6568 }
6569 }
6570 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6571 // There can be at most one literal operand, but it can be repeated.
6572 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6573 if (i == OpIdx)
6574 continue;
6575 const MachineOperand &Op = MI.getOperand(i);
6576 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6577 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6578 !Op.isIdenticalTo(*MO))
6579 return false;
6580
6581 // Do not fold a non-inlineable and non-register operand into an
6582 // instruction that already has a frame index. The frame index handling
6583 // code could not handle well when a frame index co-exists with another
6584 // non-register operand, unless that operand is an inlineable immediate.
6585 if (Op.isFI())
6586 return false;
6587 }
6588 } else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6589 isF16PseudoScalarTrans(MI.getOpcode())) {
6590 return false;
6591 }
6592
6593 if (MO->isReg()) {
6594 if (!DefinedRC)
6595 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6596 return isLegalRegOperand(MI, OpIdx, *MO);
6597 }
6598
6599 if (MO->isImm()) {
6600 uint64_t Imm = MO->getImm();
6601 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6602 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6603 bool Is64BitOp = Is64BitFPOp ||
6604 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6605 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6606 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6607 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6608 if (Is64BitOp &&
6609 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6610 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6611 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6612 return false;
6613
6614 // FIXME: We can use sign extended 64-bit literals, but only for signed
6615 // operands. At the moment we do not know if an operand is signed.
6616 // Such operand will be encoded as its low 32 bits and then either
6617 // correctly sign extended or incorrectly zero extended by HW.
6618 // If 64-bit literals are supported and the literal will be encoded
6619 // as full 64 bit we still can use it.
6620 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6621 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
6622 return false;
6623 }
6624 }
6625
6626 // Handle non-register types that are treated like immediates.
6627 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
6628
6629 if (!DefinedRC) {
6630 // This operand expects an immediate.
6631 return true;
6632 }
6633
6634 return isImmOperandLegal(MI, OpIdx, *MO);
6635}
6636
6638 bool IsGFX950Only = ST.hasGFX950Insts();
6639 bool IsGFX940Only = ST.hasGFX940Insts();
6640
6641 if (!IsGFX950Only && !IsGFX940Only)
6642 return false;
6643
6644 if (!isVALU(MI, /*AllowLDSDMA=*/true))
6645 return false;
6646
6647 // V_COS, V_EXP, V_RCP, etc.
6648 if (isTRANS(MI))
6649 return true;
6650
6651 // DOT2, DOT2C, DOT4, etc.
6652 if (isDOT(MI))
6653 return true;
6654
6655 // MFMA, SMFMA
6656 if (isMFMA(MI))
6657 return true;
6658
6659 unsigned Opcode = MI.getOpcode();
6660 switch (Opcode) {
6661 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6662 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6663 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6664 case AMDGPU::V_MQSAD_U32_U8_e64:
6665 case AMDGPU::V_PK_ADD_F16:
6666 case AMDGPU::V_PK_ADD_F32:
6667 case AMDGPU::V_PK_ADD_I16:
6668 case AMDGPU::V_PK_ADD_U16:
6669 case AMDGPU::V_PK_ASHRREV_I16:
6670 case AMDGPU::V_PK_FMA_F16:
6671 case AMDGPU::V_PK_FMA_F32:
6672 case AMDGPU::V_PK_FMAC_F16_e32:
6673 case AMDGPU::V_PK_FMAC_F16_e64:
6674 case AMDGPU::V_PK_LSHLREV_B16:
6675 case AMDGPU::V_PK_LSHRREV_B16:
6676 case AMDGPU::V_PK_MAD_I16:
6677 case AMDGPU::V_PK_MAD_U16:
6678 case AMDGPU::V_PK_MAX_F16:
6679 case AMDGPU::V_PK_MAX_I16:
6680 case AMDGPU::V_PK_MAX_U16:
6681 case AMDGPU::V_PK_MIN_F16:
6682 case AMDGPU::V_PK_MIN_I16:
6683 case AMDGPU::V_PK_MIN_U16:
6684 case AMDGPU::V_PK_MOV_B32:
6685 case AMDGPU::V_PK_MUL_F16:
6686 case AMDGPU::V_PK_MUL_F32:
6687 case AMDGPU::V_PK_MUL_LO_U16:
6688 case AMDGPU::V_PK_SUB_I16:
6689 case AMDGPU::V_PK_SUB_U16:
6690 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6691 return true;
6692 default:
6693 return false;
6694 }
6695}
6696
6698 MachineInstr &MI) const {
6699 unsigned Opc = MI.getOpcode();
6700 const MCInstrDesc &InstrDesc = get(Opc);
6701
6702 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
6703 MachineOperand &Src0 = MI.getOperand(Src0Idx);
6704
6705 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
6706 MachineOperand &Src1 = MI.getOperand(Src1Idx);
6707
6708 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
6709 // we need to only have one constant bus use before GFX10.
6710 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
6711 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
6712 RI.isSGPRReg(MRI, Src0.getReg()))
6713 legalizeOpWithMove(MI, Src0Idx);
6714
6715 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
6716 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
6717 // src0/src1 with V_READFIRSTLANE.
6718 if (Opc == AMDGPU::V_WRITELANE_B32) {
6719 const DebugLoc &DL = MI.getDebugLoc();
6720 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
6721 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6722 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6723 .add(Src0);
6724 Src0.ChangeToRegister(Reg, false);
6725 }
6726 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
6727 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6728 const DebugLoc &DL = MI.getDebugLoc();
6729 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6730 .add(Src1);
6731 Src1.ChangeToRegister(Reg, false);
6732 }
6733 return;
6734 }
6735
6736 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
6737 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
6738 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
6739 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
6740 legalizeOpWithMove(MI, Src2Idx);
6741 }
6742
6743 // VOP2 src0 instructions support all operand types, so we don't need to check
6744 // their legality. If src1 is already legal, we don't need to do anything.
6745 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
6746 return;
6747
6748 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
6749 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
6750 // select is uniform.
6751 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
6752 RI.isVGPR(MRI, Src1.getReg())) {
6753 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6754 const DebugLoc &DL = MI.getDebugLoc();
6755 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6756 .add(Src1);
6757 Src1.ChangeToRegister(Reg, false);
6758 return;
6759 }
6760
6761 // We do not use commuteInstruction here because it is too aggressive and will
6762 // commute if it is possible. We only want to commute here if it improves
6763 // legality. This can be called a fairly large number of times so don't waste
6764 // compile time pointlessly swapping and checking legality again.
6765 if (HasImplicitSGPR || !MI.isCommutable()) {
6766 legalizeOpWithMove(MI, Src1Idx);
6767 return;
6768 }
6769
6770 // If src0 can be used as src1, commuting will make the operands legal.
6771 // Otherwise we have to give up and insert a move.
6772 //
6773 // TODO: Other immediate-like operand kinds could be commuted if there was a
6774 // MachineOperand::ChangeTo* for them.
6775 if ((!Src1.isImm() && !Src1.isReg()) ||
6776 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
6777 legalizeOpWithMove(MI, Src1Idx);
6778 return;
6779 }
6780
6781 int CommutedOpc = commuteOpcode(MI);
6782 if (CommutedOpc == -1) {
6783 legalizeOpWithMove(MI, Src1Idx);
6784 return;
6785 }
6786
6787 MI.setDesc(get(CommutedOpc));
6788
6789 Register Src0Reg = Src0.getReg();
6790 unsigned Src0SubReg = Src0.getSubReg();
6791 bool Src0Kill = Src0.isKill();
6792
6793 if (Src1.isImm())
6794 Src0.ChangeToImmediate(Src1.getImm());
6795 else if (Src1.isReg()) {
6796 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
6797 Src0.setSubReg(Src1.getSubReg());
6798 } else
6799 llvm_unreachable("Should only have register or immediate operands");
6800
6801 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
6802 Src1.setSubReg(Src0SubReg);
6804}
6805
6806// Legalize VOP3 operands. All operand types are supported for any operand
6807// but only one literal constant and only starting from GFX10.
6809 MachineInstr &MI) const {
6810 unsigned Opc = MI.getOpcode();
6811
6812 int VOP3Idx[3] = {
6813 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
6814 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
6815 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
6816 };
6817
6818 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6819 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6820 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6821 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6822 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6823 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6824 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6825 // src1 and src2 must be scalar
6826 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
6827 const DebugLoc &DL = MI.getDebugLoc();
6828 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
6829 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6830 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6831 .add(Src1);
6832 Src1.ChangeToRegister(Reg, false);
6833 }
6834 if (VOP3Idx[2] != -1) {
6835 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
6836 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
6837 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6838 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6839 .add(Src2);
6840 Src2.ChangeToRegister(Reg, false);
6841 }
6842 }
6843 }
6844
6845 // Find the one SGPR operand we are allowed to use.
6846 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
6847 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
6848 SmallDenseSet<unsigned> SGPRsUsed;
6849 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
6850 if (SGPRReg) {
6851 SGPRsUsed.insert(SGPRReg);
6852 --ConstantBusLimit;
6853 }
6854
6855 for (int Idx : VOP3Idx) {
6856 if (Idx == -1)
6857 break;
6858 MachineOperand &MO = MI.getOperand(Idx);
6859
6860 if (!MO.isReg()) {
6861 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
6862 continue;
6863
6864 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
6865 --LiteralLimit;
6866 --ConstantBusLimit;
6867 continue;
6868 }
6869
6870 --LiteralLimit;
6871 --ConstantBusLimit;
6872 legalizeOpWithMove(MI, Idx);
6873 continue;
6874 }
6875
6876 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
6877 continue; // VGPRs are legal
6878
6879 // We can use one SGPR in each VOP3 instruction prior to GFX10
6880 // and two starting from GFX10.
6881 if (SGPRsUsed.count(MO.getReg()))
6882 continue;
6883 if (ConstantBusLimit > 0) {
6884 SGPRsUsed.insert(MO.getReg());
6885 --ConstantBusLimit;
6886 continue;
6887 }
6888
6889 // If we make it this far, then the operand is not legal and we must
6890 // legalize it.
6891 legalizeOpWithMove(MI, Idx);
6892 }
6893
6894 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
6895 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64) &&
6896 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
6897 legalizeOpWithMove(MI, VOP3Idx[2]);
6898
6899 // Fix the register class of packed FP32 instructions on gfx12+. See
6900 // SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand for more
6901 // information.
6903 for (unsigned I = 0; I < 3; ++I) {
6905 legalizeOpWithMove(MI, VOP3Idx[I]);
6906 }
6907 }
6908}
6909
6912 const TargetRegisterClass *DstRC /*=nullptr*/) const {
6913 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
6914 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
6915 if (DstRC)
6916 SRC = RI.getCommonSubClass(SRC, DstRC);
6917
6918 Register DstReg = MRI.createVirtualRegister(SRC);
6919 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
6920
6921 if (RI.hasAGPRs(VRC)) {
6922 VRC = RI.getEquivalentVGPRClass(VRC);
6923 Register NewSrcReg = MRI.createVirtualRegister(VRC);
6924 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6925 get(TargetOpcode::COPY), NewSrcReg)
6926 .addReg(SrcReg);
6927 SrcReg = NewSrcReg;
6928 }
6929
6930 if (SubRegs == 1) {
6931 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6932 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6933 .addReg(SrcReg);
6934 return DstReg;
6935 }
6936
6938 for (unsigned i = 0; i < SubRegs; ++i) {
6939 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
6940 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6941 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
6942 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
6943 SRegs.push_back(SGPR);
6944 }
6945
6947 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6948 get(AMDGPU::REG_SEQUENCE), DstReg);
6949 for (unsigned i = 0; i < SubRegs; ++i) {
6950 MIB.addReg(SRegs[i]);
6951 MIB.addImm(RI.getSubRegFromChannel(i));
6952 }
6953 return DstReg;
6954}
6955
6957 MachineInstr &MI) const {
6958
6959 // If the pointer is store in VGPRs, then we need to move them to
6960 // SGPRs using v_readfirstlane. This is safe because we only select
6961 // loads with uniform pointers to SMRD instruction so we know the
6962 // pointer value is uniform.
6963 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
6964 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
6965 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
6966 SBase->setReg(SGPR);
6967 }
6968 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
6969 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
6970 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
6971 SOff->setReg(SGPR);
6972 }
6973}
6974
6976 unsigned Opc = Inst.getOpcode();
6977 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
6978 if (OldSAddrIdx < 0)
6979 return false;
6980
6981 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
6982
6983 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
6984 if (NewOpc < 0)
6986 if (NewOpc < 0)
6987 return false;
6988
6989 MachineRegisterInfo &MRI = Inst.getMF()->getRegInfo();
6990 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
6991 if (RI.isSGPRReg(MRI, SAddr.getReg()))
6992 return false;
6993
6994 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
6995 if (NewVAddrIdx < 0)
6996 return false;
6997
6998 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
6999
7000 // Check vaddr, it shall be zero or absent.
7001 MachineInstr *VAddrDef = nullptr;
7002 if (OldVAddrIdx >= 0) {
7003 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
7004 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
7005 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
7006 !VAddrDef->getOperand(1).isImm() ||
7007 VAddrDef->getOperand(1).getImm() != 0)
7008 return false;
7009 }
7010
7011 const MCInstrDesc &NewDesc = get(NewOpc);
7012 Inst.setDesc(NewDesc);
7013
7014 // Callers expect iterator to be valid after this call, so modify the
7015 // instruction in place.
7016 if (OldVAddrIdx == NewVAddrIdx) {
7017 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
7018 // Clear use list from the old vaddr holding a zero register.
7019 MRI.removeRegOperandFromUseList(&NewVAddr);
7020 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7021 Inst.removeOperand(OldSAddrIdx);
7022 // Update the use list with the pointer we have just moved from vaddr to
7023 // saddr position. Otherwise new vaddr will be missing from the use list.
7024 MRI.removeRegOperandFromUseList(&NewVAddr);
7025 MRI.addRegOperandToUseList(&NewVAddr);
7026 } else {
7027 assert(OldSAddrIdx == NewVAddrIdx);
7028
7029 if (OldVAddrIdx >= 0) {
7030 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7031 AMDGPU::OpName::vdst_in);
7032
7033 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
7034 // it asserts. Untie the operands for now and retie them afterwards.
7035 if (NewVDstIn != -1) {
7036 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
7037 Inst.untieRegOperand(OldVDstIn);
7038 }
7039
7040 Inst.removeOperand(OldVAddrIdx);
7041
7042 if (NewVDstIn != -1) {
7043 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7044 Inst.tieOperands(NewVDst, NewVDstIn);
7045 }
7046 }
7047 }
7048
7049 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
7050 VAddrDef->eraseFromParent();
7051
7052 return true;
7053}
7054
7055// FIXME: Remove this when SelectionDAG is obsoleted.
7057 MachineInstr &MI) const {
7058 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
7059 return;
7060
7061 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
7062 // thinks they are uniform, so a readfirstlane should be valid.
7063 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
7064 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
7065 return;
7066
7068 return;
7069
7070 const TargetRegisterClass *DeclaredRC =
7071 getRegClass(MI.getDesc(), SAddr->getOperandNo());
7072
7073 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
7074 SAddr->setReg(ToSGPR);
7075}
7076
7079 const TargetRegisterClass *DstRC,
7082 const DebugLoc &DL) const {
7083 Register OpReg = Op.getReg();
7084 unsigned OpSubReg = Op.getSubReg();
7085
7086 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
7087 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7088
7089 // Check if operand is already the correct register class.
7090 if (DstRC == OpRC)
7091 return;
7092
7093 Register DstReg = MRI.createVirtualRegister(DstRC);
7094 auto Copy =
7095 BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg).addReg(OpReg);
7096 Op.setReg(DstReg);
7097
7098 MachineInstr *Def = MRI.getVRegDef(OpReg);
7099 if (!Def)
7100 return;
7101
7102 // Try to eliminate the copy if it is copying an immediate value.
7103 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7104 foldImmediate(*Copy, *Def, OpReg, &MRI);
7105
7106 bool ImpDef = Def->isImplicitDef();
7107 while (!ImpDef && Def && Def->isCopy()) {
7108 if (Def->getOperand(1).getReg().isPhysical())
7109 break;
7110 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7111 ImpDef = Def && Def->isImplicitDef();
7112 }
7113 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7114 !ImpDef)
7115 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7116}
7117
7118// Emit the actual waterfall loop, executing the wrapped instruction for each
7119// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7120// iteration, in the worst case we execute 64 (once per lane).
7123 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7124 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7125 MachineFunction &MF = *LoopBB.getParent();
7127 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7129 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7130
7131 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7132 // available. Otherwise, use the previous pattern of v_cmp_eq,
7133 // s_and_saveexec, and s_xor.
7134 bool UseNewExecInstructions =
7135 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7136
7138 Register CondReg;
7139
7140 Register PhiExec;
7141 Register NewExec;
7142
7143 if (UseNewExecInstructions) {
7144 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7145 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7146 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7147 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7148 .addReg(LMC.ExecReg);
7149
7150 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7151 .addReg(InitExec)
7152 .addMBB(&PredBB)
7153 .addReg(NewExec)
7154 .addMBB(&BodyBB);
7155 }
7156
7157 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7158 // involves a trade-off between register pressure and latency:
7159 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7160 // register pressure because arguments and results of all
7161 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7162 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7163 // increase latency by placing v_readfirstlane instructions
7164 // immediately before v_cmpx instruction that directly depend on it.
7165 ///
7166 // Emitting interleaved v_cmpx and v_readfirstlane requires
7167 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7168 // v_cmpx needs to be treated as terminator until after register allocation
7169 // (spill placement) and instruction reordering.
7170 //
7171 // Current implementation defers v_cmpx and leaves other instruction
7172 // scheduling decisions to later passes, where register pressure is known or
7173 // easier to approximate.
7174 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7175 // v_cmpx instructions are inserted at the end of LoopBB.
7176 // After the first v_cmpx is emitted, I is updated to point to it
7177 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7178 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7179 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7180 unsigned NumSubRegs = RegSize / 32;
7181 Register VScalarOp = ScalarOp->getReg();
7182
7183 const TargetRegisterClass *RFLSrcRC =
7184 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7185
7186 if (NumSubRegs == 1) {
7187 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7188 if (const TargetRegisterClass *Common =
7189 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7190 Common != VScalarOpRC) {
7191 Register VRReg = MRI.createVirtualRegister(Common);
7192 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7193 VScalarOp = VRReg;
7194 }
7195 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7196
7197 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7198 .addReg(VScalarOp);
7199
7200 if (UseNewExecInstructions) {
7201 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7202 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7203 .addReg(CurReg)
7204 .addReg(VScalarOp);
7205 if (I == LoopBB.end())
7206 I = CmpxMI.getInstr()->getIterator();
7207 } else {
7208 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7209
7210 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7211 .addReg(CurReg)
7212 .addReg(VScalarOp);
7213
7214 // Combine the comparison results with AND.
7215 if (!CondReg) { // First.
7216 CondReg = NewCondReg;
7217 } else { // If not the first, we create an AND.
7218 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7219 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7220 .addReg(CondReg)
7221 .addReg(NewCondReg);
7222 CondReg = AndReg;
7223 }
7224 }
7225
7226 // Update ScalarOp operand to use the SGPR ScalarOp.
7227 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7228 ScalarOp->setReg(CurReg);
7229 else {
7230 // Insert into the same block of use
7231 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7232 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7233 .addReg(CurReg);
7234 ScalarOp->setReg(PhySGPRs[Idx]);
7235 }
7236 ScalarOp->setIsKill();
7237 } else {
7238 SmallVector<Register, 8> ReadlanePieces;
7239 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7240 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7241 "Unhandled register size");
7242
7243 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7244 Register CurRegLo =
7245 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7246 Register CurRegHi =
7247 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7248
7249 // Read the next variant <- also loop target.
7250 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7251 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7252
7253 // Read the next variant <- also loop target.
7254 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7255 .addReg(VScalarOp, VScalarOpUndef,
7256 TRI->getSubRegFromChannel(Idx + 1));
7257
7258 ReadlanePieces.push_back(CurRegLo);
7259 ReadlanePieces.push_back(CurRegHi);
7260
7261 // Comparison is to be done as 64-bit.
7262 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7263 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7264 .addReg(CurRegLo)
7265 .addImm(AMDGPU::sub0)
7266 .addReg(CurRegHi)
7267 .addImm(AMDGPU::sub1);
7268
7269 unsigned SubReg =
7270 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7271
7272 if (UseNewExecInstructions) {
7273 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7274 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7275 .addReg(CurReg)
7276 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7277 if (I == LoopBB.end())
7278 I = CmpxMI.getInstr()->getIterator();
7279 } else {
7280 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7281 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7282 .addReg(CurReg)
7283 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7284
7285 // Combine the comparison results with AND.
7286 if (!CondReg) { // First.
7287 CondReg = NewCondReg;
7288 } else { // If not the first, we create an AND.
7289 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7290 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7291 .addReg(CondReg)
7292 .addReg(NewCondReg);
7293 CondReg = AndReg;
7294 }
7295 }
7296 } // End for loop.
7297
7298 const auto *SScalarOpRC =
7299 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7300 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7301
7302 // Build scalar ScalarOp.
7303 auto Merge =
7304 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7305 unsigned Channel = 0;
7306 for (Register Piece : ReadlanePieces) {
7307 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7308 }
7309
7310 // Update ScalarOp operand to use the SGPR ScalarOp.
7311 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7312 ScalarOp->setReg(SScalarOp);
7313 else {
7314 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7315 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7316 .addReg(SScalarOp);
7317 ScalarOp->setReg(PhySGPRs[Idx]);
7318 }
7319 ScalarOp->setIsKill();
7320 }
7321 }
7322
7323 // Instructions AndSaveExecOpc and AndN2WrExecOpc that modify EXEC mask
7324 // should have isTerminator=1 but terminators that define
7325 // virtual registers are not supported.
7326 Register SaveExec;
7327 if (!UseNewExecInstructions) {
7328 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7329 MRI.setSimpleHint(SaveExec, CondReg);
7330
7331 // Update EXEC to matching lanes, saving original to SaveExec.
7332 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7333 .addReg(CondReg, RegState::Kill);
7334 }
7335
7336 // The original instruction is here; we insert the terminators after it.
7337 I = BodyBB.end();
7338
7339 if (UseNewExecInstructions) {
7340 MRI.setSimpleHint(NewExec, PhiExec);
7341 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2WrExecOpc), NewExec)
7342 .addReg(PhiExec);
7343 } else {
7344 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7345 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7346 .addReg(LMC.ExecReg)
7347 .addReg(SaveExec);
7348 }
7349
7350 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7351}
7352
7353// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7354// with SGPRs by iterating over all unique values across all lanes.
7355// Returns the loop basic block that now contains \p MI.
7356static MachineBasicBlock *
7360 MachineBasicBlock::iterator Begin = nullptr,
7361 MachineBasicBlock::iterator End = nullptr,
7362 ArrayRef<Register> PhySGPRs = {}) {
7363 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7364 "Physical SGPRs must be empty or match the number of scalar operands");
7365 MachineBasicBlock &MBB = *MI.getParent();
7366 MachineFunction &MF = *MBB.getParent();
7368 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7369 MachineRegisterInfo &MRI = MF.getRegInfo();
7370 if (!Begin.isValid())
7371 Begin = &MI;
7372 if (!End.isValid()) {
7373 End = &MI;
7374 ++End;
7375 }
7376 const DebugLoc &DL = MI.getDebugLoc();
7378 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7379
7380 // Save SCC. Waterfall Loop may overwrite SCC.
7381 Register SaveSCCReg;
7382
7383 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7384 // rather than unlimited scan everywhere
7385 bool SCCNotDead =
7386 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7387 std::numeric_limits<unsigned>::max()) !=
7389 if (SCCNotDead) {
7390 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7391 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7392 .addImm(1)
7393 .addImm(0);
7394 }
7395
7396 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7397
7398 // Save the EXEC mask
7399 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7400
7401 // Killed uses in the instruction we are waterfalling around will be
7402 // incorrect due to the added control-flow.
7404 ++AfterMI;
7405 for (auto I = Begin; I != AfterMI; I++) {
7406 for (auto &MO : I->all_uses())
7407 MRI.clearKillFlags(MO.getReg());
7408 }
7409
7410 // To insert the loop we need to split the block. Move everything after this
7411 // point to a new block, and insert a new empty block between the two.
7414 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7416 ++MBBI;
7417
7418 MF.insert(MBBI, LoopBB);
7419 MF.insert(MBBI, BodyBB);
7420 MF.insert(MBBI, RemainderBB);
7421
7422 LoopBB->addSuccessor(BodyBB);
7423 BodyBB->addSuccessor(LoopBB);
7424 BodyBB->addSuccessor(RemainderBB);
7425
7426 // Move Begin to MI to the BodyBB, and the remainder of the block to
7427 // RemainderBB.
7428 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7429 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7430 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7431
7432 MBB.addSuccessor(LoopBB);
7433
7434 // Update dominators. We know that MBB immediately dominates LoopBB, that
7435 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7436 // RemainderBB. RemainderBB immediately dominates all of the successors
7437 // transferred to it from MBB that MBB used to properly dominate.
7438 if (MDT) {
7439 MDT->addNewBlock(LoopBB, &MBB);
7440 MDT->addNewBlock(BodyBB, LoopBB);
7441 MDT->addNewBlock(RemainderBB, BodyBB);
7442 for (auto &Succ : RemainderBB->successors()) {
7443 if (MDT->properlyDominates(&MBB, Succ)) {
7444 MDT->changeImmediateDominator(Succ, RemainderBB);
7445 }
7446 }
7447 }
7448
7449 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7450 PhySGPRs);
7451
7452 MachineBasicBlock::iterator First = RemainderBB->begin();
7453 // Restore SCC
7454 if (SCCNotDead) {
7455 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7456 .addReg(SaveSCCReg, RegState::Kill)
7457 .addImm(0);
7458 }
7459
7460 // Restore the EXEC mask
7461 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7462 .addReg(SaveExec);
7463 return BodyBB;
7464}
7465
7466// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7467static std::tuple<unsigned, unsigned>
7469 MachineBasicBlock &MBB = *MI.getParent();
7470 MachineFunction &MF = *MBB.getParent();
7471 MachineRegisterInfo &MRI = MF.getRegInfo();
7472
7473 // Extract the ptr from the resource descriptor.
7474 unsigned RsrcPtr =
7475 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7476 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7477
7478 // Create an empty resource descriptor
7479 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7480 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7481 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7482 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7483 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7484
7485 // Zero64 = 0
7486 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7487 .addImm(0);
7488
7489 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7490 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7491 .addImm(Lo_32(RsrcDataFormat));
7492
7493 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7494 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7495 .addImm(Hi_32(RsrcDataFormat));
7496
7497 // NewSRsrc = {Zero64, SRsrcFormat}
7498 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7499 .addReg(Zero64)
7500 .addImm(AMDGPU::sub0_sub1)
7501 .addReg(SRsrcFormatLo)
7502 .addImm(AMDGPU::sub2)
7503 .addReg(SRsrcFormatHi)
7504 .addImm(AMDGPU::sub3);
7505
7506 return std::tuple(RsrcPtr, NewSRsrc);
7507}
7508
7511 MachineDominatorTree *MDT) const {
7512 MachineFunction &MF = *MI.getMF();
7513 MachineRegisterInfo &MRI = MF.getRegInfo();
7514 MachineBasicBlock *CreatedBB = nullptr;
7515
7516 // Legalize VOP2
7517 if (isVOP2(MI) || isVOPC(MI)) {
7519 return CreatedBB;
7520 }
7521
7522 // Legalize VOP3
7523 if (isVOP3(MI)) {
7525 return CreatedBB;
7526 }
7527
7528 // Legalize SMRD
7529 if (isSMRD(MI)) {
7531 return CreatedBB;
7532 }
7533
7534 // Legalize FLAT
7535 if (isFLAT(MI)) {
7537 return CreatedBB;
7538 }
7539
7540 // Legalize PHI
7541 // The register class of the operands must be the same type as the register
7542 // class of the output.
7543 if (MI.getOpcode() == AMDGPU::PHI) {
7544 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7545 assert(!RI.isSGPRClass(VRC));
7546
7547 // Update all the operands so they have the same type.
7548 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7549 MachineOperand &Op = MI.getOperand(I);
7550 if (!Op.isReg() || !Op.getReg().isVirtual())
7551 continue;
7552
7553 // MI is a PHI instruction.
7554 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7556
7557 // Avoid creating no-op copies with the same src and dst reg class. These
7558 // confuse some of the machine passes.
7559 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7560 }
7561 }
7562
7563 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7564 // VGPR dest type and SGPR sources, insert copies so all operands are
7565 // VGPRs. This seems to help operand folding / the register coalescer.
7566 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7567 MachineBasicBlock *MBB = MI.getParent();
7568 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7569 if (RI.hasVGPRs(DstRC)) {
7570 // Update all the operands so they are VGPR register classes. These may
7571 // not be the same register class because REG_SEQUENCE supports mixing
7572 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7573 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7574 MachineOperand &Op = MI.getOperand(I);
7575 if (!Op.isReg() || !Op.getReg().isVirtual())
7576 continue;
7577
7578 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7579 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7580 if (VRC == OpRC)
7581 continue;
7582
7583 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7584 Op.setIsKill();
7585 }
7586 }
7587
7588 return CreatedBB;
7589 }
7590
7591 // Legalize INSERT_SUBREG
7592 // src0 must have the same register class as dst
7593 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7594 Register Dst = MI.getOperand(0).getReg();
7595 Register Src0 = MI.getOperand(1).getReg();
7596 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7597 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7598 if (DstRC != Src0RC) {
7599 MachineBasicBlock *MBB = MI.getParent();
7600 MachineOperand &Op = MI.getOperand(1);
7601 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7602 }
7603 return CreatedBB;
7604 }
7605
7606 // Legalize SI_INIT_M0
7607 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7608 MachineOperand &Src = MI.getOperand(0);
7609 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7610 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7611 return CreatedBB;
7612 }
7613
7614 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
7615 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7616 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7617 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7618 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7619 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7620 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7621 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7622 MachineOperand &Src = MI.getOperand(1);
7623 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7624 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7625 return CreatedBB;
7626 }
7627
7628 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
7629 //
7630 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
7631 // scratch memory access. In both cases, the legalization never involves
7632 // conversion to the addr64 form.
7634 (isMUBUF(MI) || isMTBUF(MI)))) {
7635 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
7636 ? AMDGPU::OpName::rsrc
7637 : AMDGPU::OpName::srsrc;
7638 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
7639 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
7640 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
7641
7642 AMDGPU::OpName SampOpName =
7643 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7644 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
7645 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
7646 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
7647
7648 return CreatedBB;
7649 }
7650
7651 // Legalize SI_CALL
7652 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7653 MachineOperand *Dest = &MI.getOperand(0);
7654 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
7655 createWaterFallForSiCall(&MI, MDT, {Dest});
7656 }
7657 }
7658
7659 // Legalize s_sleep_var.
7660 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7661 const DebugLoc &DL = MI.getDebugLoc();
7662 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7663 int Src0Idx =
7664 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
7665 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7666 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7667 .add(Src0);
7668 Src0.ChangeToRegister(Reg, false);
7669 return nullptr;
7670 }
7671
7672 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
7673 // operands are scalar.
7674 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7675 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7676 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7677 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7678 for (MachineOperand &Src : MI.explicit_operands()) {
7679 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7680 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7681 }
7682 return CreatedBB;
7683 }
7684
7685 // Legalize MUBUF instructions.
7686 bool isSoffsetLegal = true;
7687 int SoffsetIdx =
7688 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
7689 if (SoffsetIdx != -1) {
7690 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
7691 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
7692 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
7693 isSoffsetLegal = false;
7694 }
7695 }
7696
7697 bool isRsrcLegal = true;
7698 int RsrcIdx =
7699 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
7700 if (RsrcIdx != -1) {
7701 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7702 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
7703 isRsrcLegal = false;
7704 }
7705
7706 // The operands are legal.
7707 if (isRsrcLegal && isSoffsetLegal)
7708 return CreatedBB;
7709
7710 if (!isRsrcLegal) {
7711 // Legalize a VGPR Rsrc
7712 //
7713 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
7714 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
7715 // a zero-value SRsrc.
7716 //
7717 // If the instruction is _OFFSET (both idxen and offen disabled), and we
7718 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
7719 // above.
7720 //
7721 // Otherwise we are on non-ADDR64 hardware, and/or we have
7722 // idxen/offen/bothen and we fall back to a waterfall loop.
7723
7724 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7725 MachineBasicBlock &MBB = *MI.getParent();
7726
7727 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
7728 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
7729 // This is already an ADDR64 instruction so we need to add the pointer
7730 // extracted from the resource descriptor to the current value of VAddr.
7731 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7732 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7733 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7734
7735 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7736 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
7737 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
7738
7739 unsigned RsrcPtr, NewSRsrc;
7740 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7741
7742 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
7743 const DebugLoc &DL = MI.getDebugLoc();
7744 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
7745 .addDef(CondReg0)
7746 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7747 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
7748 .addImm(0);
7749
7750 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
7751 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
7752 .addDef(CondReg1, RegState::Dead)
7753 .addReg(RsrcPtr, {}, AMDGPU::sub1)
7754 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
7755 .addReg(CondReg0, RegState::Kill)
7756 .addImm(0);
7757
7758 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7759 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
7760 .addReg(NewVAddrLo)
7761 .addImm(AMDGPU::sub0)
7762 .addReg(NewVAddrHi)
7763 .addImm(AMDGPU::sub1);
7764
7765 VAddr->setReg(NewVAddr);
7766 Rsrc->setReg(NewSRsrc);
7767 } else if (!VAddr && ST.hasAddr64()) {
7768 // This instructions is the _OFFSET variant, so we need to convert it to
7769 // ADDR64.
7770 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
7771 "FIXME: Need to emit flat atomics here");
7772
7773 unsigned RsrcPtr, NewSRsrc;
7774 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7775
7776 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7777 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
7778 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
7779 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7780 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
7781
7782 // Atomics with return have an additional tied operand and are
7783 // missing some of the special bits.
7784 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
7785 MachineInstr *Addr64;
7786
7787 if (!VDataIn) {
7788 // Regular buffer load / store.
7790 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7791 .add(*VData)
7792 .addReg(NewVAddr)
7793 .addReg(NewSRsrc)
7794 .add(*SOffset)
7795 .add(*Offset);
7796
7797 if (const MachineOperand *CPol =
7798 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
7799 MIB.addImm(CPol->getImm());
7800 }
7801
7802 if (const MachineOperand *TFE =
7803 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
7804 MIB.addImm(TFE->getImm());
7805 }
7806
7807 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
7808
7809 MIB.cloneMemRefs(MI);
7810 Addr64 = MIB;
7811 } else {
7812 // Atomics with return.
7813 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7814 .add(*VData)
7815 .add(*VDataIn)
7816 .addReg(NewVAddr)
7817 .addReg(NewSRsrc)
7818 .add(*SOffset)
7819 .add(*Offset)
7820 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
7821 .cloneMemRefs(MI);
7822 }
7823
7824 MI.removeFromParent();
7825
7826 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7827 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
7828 NewVAddr)
7829 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7830 .addImm(AMDGPU::sub0)
7831 .addReg(RsrcPtr, {}, AMDGPU::sub1)
7832 .addImm(AMDGPU::sub1);
7833 } else {
7834 // Legalize a VGPR Rsrc and soffset together.
7835 if (!isSoffsetLegal) {
7836 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7837 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
7838 return CreatedBB;
7839 }
7840 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
7841 return CreatedBB;
7842 }
7843 }
7844
7845 // Legalize a VGPR soffset.
7846 if (!isSoffsetLegal) {
7847 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7848 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
7849 return CreatedBB;
7850 }
7851 return CreatedBB;
7852}
7853
7855 if (InSet.insert(MI).second)
7856 InstrList.push_back(MI);
7857 // Add MBUF instructiosn to deferred list.
7858 int RsrcIdx =
7859 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
7860 if (RsrcIdx != -1) {
7861 DeferredList.insert(MI);
7862 }
7863}
7864
7866 return DeferredList.contains(MI);
7867}
7868
7869// Legalize size mismatches between 16bit and 32bit registers in v2s copy
7870// lowering (change sgpr to vgpr).
7871// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
7872// size. Need to legalize the size of the operands during the vgpr lowering
7873// chain. This can be removed after we have sgpr16 in place
7875 MachineRegisterInfo &MRI) const {
7876 if (!ST.useRealTrue16Insts())
7877 return;
7878
7879 unsigned Opcode = MI.getOpcode();
7880 MachineBasicBlock *MBB = MI.getParent();
7881 // Legalize operands and check for size mismatch
7882 if (!OpIdx || OpIdx >= MI.getNumExplicitOperands() ||
7883 OpIdx >= get(Opcode).getNumOperands() ||
7884 get(Opcode).operands()[OpIdx].RegClass == -1)
7885 return;
7886
7887 MachineOperand &Op = MI.getOperand(OpIdx);
7888 if (!Op.isReg() || !Op.getReg().isVirtual())
7889 return;
7890
7891 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
7892 if (!RI.isVGPRClass(CurrRC))
7893 return;
7894
7895 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
7896 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
7897 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
7898 Op.setSubReg(AMDGPU::lo16);
7899 } else if (RI.getMatchingSuperRegClass(ExpectedRC, CurrRC, AMDGPU::lo16)) {
7900 const DebugLoc &DL = MI.getDebugLoc();
7901 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7902 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
7903 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
7904 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
7905 .addReg(Op.getReg())
7906 .addImm(AMDGPU::lo16)
7907 .addReg(Undef)
7908 .addImm(AMDGPU::hi16);
7909 Op.setReg(NewDstReg);
7910 }
7911}
7913 MachineRegisterInfo &MRI) const {
7914 for (unsigned OpIdx = 1; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
7916}
7917
7921 ArrayRef<Register> PhySGPRs) const {
7922 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
7923 "This only handle waterfall for SI_CALL_ISEL");
7924 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
7925 // following copies, we also need to move copies from and to physical
7926 // registers into the loop block.
7927 // Also move the copies to physical registers into the loop block
7928 MachineBasicBlock &MBB = *MI->getParent();
7930 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
7931 --Start;
7933 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
7934 ++End;
7935
7936 // Also include following copies of the return value
7937 ++End;
7938 while (End != MBB.end() && End->isCopy() &&
7939 MI->definesRegister(End->getOperand(1).getReg(), &RI))
7940 ++End;
7941
7942 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
7943}
7944
7946 MachineDominatorTree *MDT) const {
7948 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
7949 while (!Worklist.empty()) {
7950 MachineInstr &Inst = *Worklist.top();
7951 Worklist.erase_top();
7952 // Skip MachineInstr in the deferred list.
7953 if (Worklist.isDeferred(&Inst))
7954 continue;
7955 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
7956 }
7957
7958 // Deferred list of instructions will be processed once
7959 // all the MachineInstr in the worklist are done.
7960 for (MachineInstr *Inst : Worklist.getDeferredList()) {
7961 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
7962 assert(Worklist.empty() &&
7963 "Deferred MachineInstr are not supposed to re-populate worklist");
7964 }
7965
7966 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
7967 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
7968 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
7969 Entry.second.SGPRs);
7970 }
7971
7972 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
7973 if (Entry.second)
7974 Entry.first->eraseFromParent();
7975}
7977 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
7978 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
7979 // hope for the best.
7980 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
7981 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
7982 if (SubRegIndices.size() <= 1) {
7983 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7984 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
7985 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
7986 .add(Inst.getOperand(1));
7987 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
7988 DstReg)
7989 .addReg(NewDst);
7990 } else {
7992 for (int16_t Indice : SubRegIndices) {
7993 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7994 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
7995 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
7996 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
7997
7998 DstRegs.push_back(NewDst);
7999 }
8001 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8002 get(AMDGPU::REG_SEQUENCE), DstReg);
8003 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
8004 MIB.addReg(DstRegs[i]);
8005 MIB.addImm(RI.getSubRegFromChannel(i));
8006 }
8007 }
8008}
8009
8011 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
8014 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8015 if (DstReg == AMDGPU::M0) {
8016 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8017 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8018 return;
8019 }
8020 Register SrcReg = Inst.getOperand(1).getReg();
8023 // Only search current block since phyreg's def & use cannot cross
8024 // blocks when MF.NoPhi = false.
8025 while (++I != E) {
8026 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
8027 // and record the operand for later waterfall loop generation.
8028 if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8029 MachineInstr *UseMI = &*I;
8030 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
8031 if (UseMI->getOperand(i).isReg() &&
8032 UseMI->getOperand(i).getReg() == DstReg) {
8033 MachineOperand *MO = &UseMI->getOperand(i);
8034 MO->setReg(SrcReg);
8035 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
8036 V2SCopyInfo.MOs.push_back(MO);
8037 V2SCopyInfo.SGPRs.push_back(DstReg);
8038 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8039 }
8040 }
8041 } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8042 I->getOperand(0).isReg() &&
8043 I->getOperand(0).getReg() == DstReg) {
8044 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
8045 V2SPhyCopiesToErase.try_emplace(&Inst, true);
8046 } else if (I->readsRegister(DstReg, &RI)) {
8047 // COPY cannot be erased if other type of inst uses it.
8048 V2SPhyCopiesToErase[&Inst] = false;
8049 }
8050 if (I->findRegisterDefOperand(DstReg, &RI))
8051 break;
8052 }
8053}
8054
8056 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
8058 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
8059
8061 if (!MBB)
8062 return;
8063 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
8064 unsigned Opcode = Inst.getOpcode();
8065 unsigned NewOpcode = getVALUOp(Inst);
8066 const DebugLoc &DL = Inst.getDebugLoc();
8067
8068 // Handle some special cases
8069 switch (Opcode) {
8070 default:
8071 break;
8072 case AMDGPU::S_ADD_I32:
8073 case AMDGPU::S_SUB_I32: {
8074 // FIXME: The u32 versions currently selected use the carry.
8075 bool Changed;
8076 MachineBasicBlock *CreatedBBTmp = nullptr;
8077 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8078 if (Changed)
8079 return;
8080
8081 // Default handling
8082 break;
8083 }
8084
8085 case AMDGPU::S_MUL_U64:
8086 if (ST.hasVMulU64Inst()) {
8087 NewOpcode = AMDGPU::V_MUL_U64_e64;
8088 break;
8089 }
8090 // Split s_mul_u64 in 32-bit vector multiplications.
8091 splitScalarSMulU64(Worklist, Inst, MDT);
8092 Inst.eraseFromParent();
8093 return;
8094
8095 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8096 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8097 // This is a special case of s_mul_u64 where all the operands are either
8098 // zero extended or sign extended.
8099 splitScalarSMulPseudo(Worklist, Inst, MDT);
8100 Inst.eraseFromParent();
8101 return;
8102
8103 case AMDGPU::S_AND_B64:
8104 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8105 Inst.eraseFromParent();
8106 return;
8107
8108 case AMDGPU::S_OR_B64:
8109 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8110 Inst.eraseFromParent();
8111 return;
8112
8113 case AMDGPU::S_XOR_B64:
8114 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8115 Inst.eraseFromParent();
8116 return;
8117
8118 case AMDGPU::S_NAND_B64:
8119 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8120 Inst.eraseFromParent();
8121 return;
8122
8123 case AMDGPU::S_NOR_B64:
8124 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8125 Inst.eraseFromParent();
8126 return;
8127
8128 case AMDGPU::S_XNOR_B64:
8129 if (ST.hasDLInsts())
8130 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8131 else
8132 splitScalar64BitXnor(Worklist, Inst, MDT);
8133 Inst.eraseFromParent();
8134 return;
8135
8136 case AMDGPU::S_ANDN2_B64:
8137 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8138 Inst.eraseFromParent();
8139 return;
8140
8141 case AMDGPU::S_ORN2_B64:
8142 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8143 Inst.eraseFromParent();
8144 return;
8145
8146 case AMDGPU::S_BREV_B64:
8147 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8148 Inst.eraseFromParent();
8149 return;
8150
8151 case AMDGPU::S_NOT_B64:
8152 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8153 Inst.eraseFromParent();
8154 return;
8155
8156 case AMDGPU::S_BCNT1_I32_B64:
8157 splitScalar64BitBCNT(Worklist, Inst);
8158 Inst.eraseFromParent();
8159 return;
8160
8161 case AMDGPU::S_BFE_I64:
8162 splitScalar64BitBFE(Worklist, Inst);
8163 Inst.eraseFromParent();
8164 return;
8165
8166 case AMDGPU::S_FLBIT_I32_B64:
8167 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8168 Inst.eraseFromParent();
8169 return;
8170 case AMDGPU::S_FF1_I32_B64:
8171 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8172 Inst.eraseFromParent();
8173 return;
8174
8175 case AMDGPU::S_LSHL_B32:
8176 if (ST.hasOnlyRevVALUShifts()) {
8177 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8178 swapOperands(Inst);
8179 }
8180 break;
8181 case AMDGPU::S_ASHR_I32:
8182 if (ST.hasOnlyRevVALUShifts()) {
8183 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8184 swapOperands(Inst);
8185 }
8186 break;
8187 case AMDGPU::S_LSHR_B32:
8188 if (ST.hasOnlyRevVALUShifts()) {
8189 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8190 swapOperands(Inst);
8191 }
8192 break;
8193 case AMDGPU::S_LSHL_B64:
8194 if (ST.hasOnlyRevVALUShifts()) {
8195 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8196 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8197 : AMDGPU::V_LSHLREV_B64_e64;
8198 swapOperands(Inst);
8199 }
8200 break;
8201 case AMDGPU::S_ASHR_I64:
8202 if (ST.hasOnlyRevVALUShifts()) {
8203 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8204 swapOperands(Inst);
8205 }
8206 break;
8207 case AMDGPU::S_LSHR_B64:
8208 if (ST.hasOnlyRevVALUShifts()) {
8209 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8210 swapOperands(Inst);
8211 }
8212 break;
8213
8214 case AMDGPU::S_ABS_I32:
8215 lowerScalarAbs(Worklist, Inst);
8216 Inst.eraseFromParent();
8217 return;
8218
8219 case AMDGPU::S_ABSDIFF_I32:
8220 lowerScalarAbsDiff(Worklist, Inst);
8221 Inst.eraseFromParent();
8222 return;
8223
8224 case AMDGPU::S_CBRANCH_SCC0:
8225 case AMDGPU::S_CBRANCH_SCC1: {
8226 // Clear unused bits of vcc
8227 Register CondReg = Inst.getOperand(1).getReg();
8228 bool IsSCC = CondReg == AMDGPU::SCC;
8230 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8231 .addReg(LMC.ExecReg)
8232 .addReg(IsSCC ? LMC.VccReg : CondReg);
8233 Inst.removeOperand(1);
8234 } break;
8235
8236 case AMDGPU::S_BFE_U64:
8237 case AMDGPU::S_BFM_B64:
8238 llvm_unreachable("Moving this op to VALU not implemented");
8239
8240 case AMDGPU::S_PACK_LL_B32_B16:
8241 case AMDGPU::S_PACK_LH_B32_B16:
8242 case AMDGPU::S_PACK_HL_B32_B16:
8243 case AMDGPU::S_PACK_HH_B32_B16:
8244 movePackToVALU(Worklist, MRI, Inst);
8245 Inst.eraseFromParent();
8246 return;
8247
8248 case AMDGPU::S_XNOR_B32:
8249 lowerScalarXnor(Worklist, Inst);
8250 Inst.eraseFromParent();
8251 return;
8252
8253 case AMDGPU::S_NAND_B32:
8254 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8255 Inst.eraseFromParent();
8256 return;
8257
8258 case AMDGPU::S_NOR_B32:
8259 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8260 Inst.eraseFromParent();
8261 return;
8262
8263 case AMDGPU::S_ANDN2_B32:
8264 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8265 Inst.eraseFromParent();
8266 return;
8267
8268 case AMDGPU::S_ORN2_B32:
8269 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8270 Inst.eraseFromParent();
8271 return;
8272
8273 // TODO: remove as soon as everything is ready
8274 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8275 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8276 // can only be selected from the uniform SDNode.
8277 case AMDGPU::S_ADD_CO_PSEUDO:
8278 case AMDGPU::S_SUB_CO_PSEUDO: {
8279 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8280 ? AMDGPU::V_ADDC_U32_e64
8281 : AMDGPU::V_SUBB_U32_e64;
8282 const auto *CarryRC = RI.getWaveMaskRegClass();
8283
8284 Register CarryInReg = Inst.getOperand(4).getReg();
8285 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8286 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8287 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8288 .addReg(CarryInReg);
8289 }
8290
8291 Register CarryOutReg = Inst.getOperand(1).getReg();
8292
8293 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8294 MRI.getRegClass(Inst.getOperand(0).getReg())));
8295 MachineInstr *CarryOp =
8296 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8297 .addReg(CarryOutReg, RegState::Define)
8298 .add(Inst.getOperand(2))
8299 .add(Inst.getOperand(3))
8300 .addReg(CarryInReg)
8301 .addImm(0);
8302 legalizeOperands(*CarryOp);
8303 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8304 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8305 Inst.eraseFromParent();
8306 }
8307 return;
8308 case AMDGPU::S_UADDO_PSEUDO:
8309 case AMDGPU::S_USUBO_PSEUDO: {
8310 MachineOperand &Dest0 = Inst.getOperand(0);
8311 MachineOperand &Dest1 = Inst.getOperand(1);
8312 MachineOperand &Src0 = Inst.getOperand(2);
8313 MachineOperand &Src1 = Inst.getOperand(3);
8314
8315 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8316 ? AMDGPU::V_ADD_CO_U32_e64
8317 : AMDGPU::V_SUB_CO_U32_e64;
8318 const TargetRegisterClass *NewRC =
8319 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8320 Register DestReg = MRI.createVirtualRegister(NewRC);
8321 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8322 .addReg(Dest1.getReg(), RegState::Define)
8323 .add(Src0)
8324 .add(Src1)
8325 .addImm(0); // clamp bit
8326
8327 legalizeOperands(*NewInstr, MDT);
8328 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8329 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8330 Inst.eraseFromParent();
8331 }
8332 return;
8333 case AMDGPU::S_LSHL1_ADD_U32:
8334 case AMDGPU::S_LSHL2_ADD_U32:
8335 case AMDGPU::S_LSHL3_ADD_U32:
8336 case AMDGPU::S_LSHL4_ADD_U32: {
8337 MachineOperand &Dest = Inst.getOperand(0);
8338 MachineOperand &Src0 = Inst.getOperand(1);
8339 MachineOperand &Src1 = Inst.getOperand(2);
8340 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8341 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8342 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8343 : 4);
8344
8345 const TargetRegisterClass *NewRC =
8346 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8347 Register DestReg = MRI.createVirtualRegister(NewRC);
8348 MachineInstr *NewInstr =
8349 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8350 .add(Src0)
8351 .addImm(ShiftAmt)
8352 .add(Src1);
8353
8354 legalizeOperands(*NewInstr, MDT);
8355 MRI.replaceRegWith(Dest.getReg(), DestReg);
8356 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8357 Inst.eraseFromParent();
8358 }
8359 return;
8360 case AMDGPU::S_CSELECT_B32:
8361 case AMDGPU::S_CSELECT_B64:
8362 lowerSelect(Worklist, Inst, MDT);
8363 Inst.eraseFromParent();
8364 return;
8365 case AMDGPU::S_CMP_EQ_I32:
8366 case AMDGPU::S_CMP_LG_I32:
8367 case AMDGPU::S_CMP_GT_I32:
8368 case AMDGPU::S_CMP_GE_I32:
8369 case AMDGPU::S_CMP_LT_I32:
8370 case AMDGPU::S_CMP_LE_I32:
8371 case AMDGPU::S_CMP_EQ_U32:
8372 case AMDGPU::S_CMP_LG_U32:
8373 case AMDGPU::S_CMP_GT_U32:
8374 case AMDGPU::S_CMP_GE_U32:
8375 case AMDGPU::S_CMP_LT_U32:
8376 case AMDGPU::S_CMP_LE_U32:
8377 case AMDGPU::S_CMP_EQ_U64:
8378 case AMDGPU::S_CMP_LG_U64:
8379 case AMDGPU::S_CMP_LT_F32:
8380 case AMDGPU::S_CMP_EQ_F32:
8381 case AMDGPU::S_CMP_LE_F32:
8382 case AMDGPU::S_CMP_GT_F32:
8383 case AMDGPU::S_CMP_LG_F32:
8384 case AMDGPU::S_CMP_GE_F32:
8385 case AMDGPU::S_CMP_O_F32:
8386 case AMDGPU::S_CMP_U_F32:
8387 case AMDGPU::S_CMP_NGE_F32:
8388 case AMDGPU::S_CMP_NLG_F32:
8389 case AMDGPU::S_CMP_NGT_F32:
8390 case AMDGPU::S_CMP_NLE_F32:
8391 case AMDGPU::S_CMP_NEQ_F32:
8392 case AMDGPU::S_CMP_NLT_F32: {
8393 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8394 auto NewInstr =
8395 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8396 .setMIFlags(Inst.getFlags());
8397 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8398 0) {
8399 NewInstr
8400 .addImm(0) // src0_modifiers
8401 .add(Inst.getOperand(0)) // src0
8402 .addImm(0) // src1_modifiers
8403 .add(Inst.getOperand(1)) // src1
8404 .addImm(0); // clamp
8405 } else {
8406 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8407 }
8408 legalizeOperands(*NewInstr, MDT);
8409 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8410 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8411 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8412 Inst.eraseFromParent();
8413 return;
8414 }
8415 case AMDGPU::S_CMP_LT_F16:
8416 case AMDGPU::S_CMP_EQ_F16:
8417 case AMDGPU::S_CMP_LE_F16:
8418 case AMDGPU::S_CMP_GT_F16:
8419 case AMDGPU::S_CMP_LG_F16:
8420 case AMDGPU::S_CMP_GE_F16:
8421 case AMDGPU::S_CMP_O_F16:
8422 case AMDGPU::S_CMP_U_F16:
8423 case AMDGPU::S_CMP_NGE_F16:
8424 case AMDGPU::S_CMP_NLG_F16:
8425 case AMDGPU::S_CMP_NGT_F16:
8426 case AMDGPU::S_CMP_NLE_F16:
8427 case AMDGPU::S_CMP_NEQ_F16:
8428 case AMDGPU::S_CMP_NLT_F16: {
8429 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8430 auto NewInstr =
8431 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8432 .setMIFlags(Inst.getFlags());
8433 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8434 NewInstr
8435 .addImm(0) // src0_modifiers
8436 .add(Inst.getOperand(0)) // src0
8437 .addImm(0) // src1_modifiers
8438 .add(Inst.getOperand(1)) // src1
8439 .addImm(0); // clamp
8440 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8441 NewInstr.addImm(0); // op_sel0
8442 } else {
8443 NewInstr
8444 .add(Inst.getOperand(0))
8445 .add(Inst.getOperand(1));
8446 }
8447 legalizeOperandsVALUt16(*NewInstr, MRI);
8448 legalizeOperands(*NewInstr, MDT);
8449 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8450 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8451 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8452 Inst.eraseFromParent();
8453 return;
8454 }
8455 case AMDGPU::S_CVT_HI_F32_F16: {
8456 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8457 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8458 if (ST.useRealTrue16Insts()) {
8459 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8460 .add(Inst.getOperand(1));
8461 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8462 .addImm(0) // src0_modifiers
8463 .addReg(TmpReg, {}, AMDGPU::hi16)
8464 .addImm(0) // clamp
8465 .addImm(0) // omod
8466 .addImm(0); // op_sel0
8467 } else {
8468 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8469 .addImm(16)
8470 .add(Inst.getOperand(1));
8471 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8472 .addImm(0) // src0_modifiers
8473 .addReg(TmpReg)
8474 .addImm(0) // clamp
8475 .addImm(0); // omod
8476 }
8477
8478 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8479 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8480 Inst.eraseFromParent();
8481 return;
8482 }
8483 case AMDGPU::S_MINIMUM_F32:
8484 case AMDGPU::S_MAXIMUM_F32: {
8485 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8486 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8487 .addImm(0) // src0_modifiers
8488 .add(Inst.getOperand(1))
8489 .addImm(0) // src1_modifiers
8490 .add(Inst.getOperand(2))
8491 .addImm(0) // clamp
8492 .addImm(0); // omod
8493 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8494
8495 legalizeOperands(*NewInstr, MDT);
8496 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8497 Inst.eraseFromParent();
8498 return;
8499 }
8500 case AMDGPU::S_MINIMUM_F16:
8501 case AMDGPU::S_MAXIMUM_F16: {
8502 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8503 ? &AMDGPU::VGPR_16RegClass
8504 : &AMDGPU::VGPR_32RegClass);
8505 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8506 .addImm(0) // src0_modifiers
8507 .add(Inst.getOperand(1))
8508 .addImm(0) // src1_modifiers
8509 .add(Inst.getOperand(2))
8510 .addImm(0) // clamp
8511 .addImm(0) // omod
8512 .addImm(0); // opsel0
8513 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8514 legalizeOperandsVALUt16(*NewInstr, MRI);
8515 legalizeOperands(*NewInstr, MDT);
8516 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8517 Inst.eraseFromParent();
8518 return;
8519 }
8520 case AMDGPU::V_S_EXP_F16_e64:
8521 case AMDGPU::V_S_LOG_F16_e64:
8522 case AMDGPU::V_S_RCP_F16_e64:
8523 case AMDGPU::V_S_RSQ_F16_e64:
8524 case AMDGPU::V_S_SQRT_F16_e64: {
8525 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8526 ? &AMDGPU::VGPR_16RegClass
8527 : &AMDGPU::VGPR_32RegClass);
8528 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8529 .add(Inst.getOperand(1)) // src0_modifiers
8530 .add(Inst.getOperand(2))
8531 .add(Inst.getOperand(3)) // clamp
8532 .add(Inst.getOperand(4)) // omod
8533 .setMIFlags(Inst.getFlags());
8534 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8535 NewInstr.addImm(0); // opsel0
8536 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8537 legalizeOperandsVALUt16(*NewInstr, MRI);
8538 legalizeOperands(*NewInstr, MDT);
8539 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8540 Inst.eraseFromParent();
8541 return;
8542 }
8543 }
8544
8545 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8546 // We cannot move this instruction to the VALU, so we should try to
8547 // legalize its operands instead.
8548 legalizeOperands(Inst, MDT);
8549 return;
8550 }
8551 // Handle converting generic instructions like COPY-to-SGPR into
8552 // COPY-to-VGPR.
8553 if (NewOpcode == Opcode) {
8554 Register DstReg = Inst.getOperand(0).getReg();
8555 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8556
8557 if (Inst.isCopy() && DstReg.isPhysical() &&
8558 Inst.getOperand(1).getReg().isVirtual()) {
8559 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8560 V2SPhyCopiesToErase);
8561 return;
8562 }
8563
8564 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8565 Register NewDstReg = Inst.getOperand(1).getReg();
8566 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8567 if (const TargetRegisterClass *CommonRC =
8568 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8569 // Instead of creating a copy where src and dst are the same register
8570 // class, we just replace all uses of dst with src. These kinds of
8571 // copies interfere with the heuristics MachineSink uses to decide
8572 // whether or not to split a critical edge. Since the pass assumes
8573 // that copies will end up as machine instructions and not be
8574 // eliminated.
8575 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8576 MRI.replaceRegWith(DstReg, NewDstReg);
8577 MRI.clearKillFlags(NewDstReg);
8578 Inst.getOperand(0).setReg(DstReg);
8579
8580 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8581 llvm_unreachable("failed to constrain register");
8582
8583 Inst.eraseFromParent();
8584
8585 for (MachineOperand &UseMO :
8586 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8587 MachineInstr &UseMI = *UseMO.getParent();
8588
8589 // Legalize t16 operands since replaceReg is called after
8590 // addUsersToVALU.
8592
8593 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
8594 if (const TargetRegisterClass *OpRC =
8595 getRegClass(UseMI.getDesc(), OpIdx))
8596 MRI.constrainRegClass(NewDstReg, OpRC);
8597 }
8598
8599 return;
8600 }
8601 }
8602
8603 // If this is a v2s copy between 16bit and 32bit reg,
8604 // replace vgpr copy to reg_sequence/extract_subreg
8605 // This can be remove after we have sgpr16 in place
8606 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
8607 Inst.getOperand(1).getReg().isVirtual() &&
8608 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
8609 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
8610 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8611 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8612 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8613 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8614 get(AMDGPU::IMPLICIT_DEF), Undef);
8615 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8616 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8617 .addReg(Inst.getOperand(1).getReg())
8618 .addImm(AMDGPU::lo16)
8619 .addReg(Undef)
8620 .addImm(AMDGPU::hi16);
8621 Inst.eraseFromParent();
8622 MRI.replaceRegWith(DstReg, NewDstReg);
8623 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8624 return;
8625 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8626 AMDGPU::lo16)) {
8627 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
8628 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8629 MRI.replaceRegWith(DstReg, NewDstReg);
8630 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8631 return;
8632 }
8633 }
8634
8635 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8636 MRI.replaceRegWith(DstReg, NewDstReg);
8637 legalizeOperands(Inst, MDT);
8638 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8639 return;
8640 }
8641
8642 // Use the new VALU Opcode.
8643 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
8644 .setMIFlags(Inst.getFlags());
8645 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
8646 // Intersperse VOP3 modifiers among the SALU operands.
8647 NewInstr->addOperand(Inst.getOperand(0));
8648 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8649 AMDGPU::OpName::src0_modifiers) >= 0)
8650 NewInstr.addImm(0);
8651 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
8652 const MachineOperand &Src = Inst.getOperand(1);
8653 NewInstr->addOperand(Src);
8654 }
8655
8656 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8657 // We are converting these to a BFE, so we need to add the missing
8658 // operands for the size and offset.
8659 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8660 NewInstr.addImm(0);
8661 NewInstr.addImm(Size);
8662 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8663 // The VALU version adds the second operand to the result, so insert an
8664 // extra 0 operand.
8665 NewInstr.addImm(0);
8666 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8667 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
8668 // If we need to move this to VGPRs, we need to unpack the second
8669 // operand back into the 2 separate ones for bit offset and width.
8670 assert(OffsetWidthOp.isImm() &&
8671 "Scalar BFE is only implemented for constant width and offset");
8672 uint32_t Imm = OffsetWidthOp.getImm();
8673
8674 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
8675 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
8676 NewInstr.addImm(Offset);
8677 NewInstr.addImm(BitWidth);
8678 } else {
8679 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8680 AMDGPU::OpName::src1_modifiers) >= 0)
8681 NewInstr.addImm(0);
8682 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8683 NewInstr->addOperand(Inst.getOperand(2));
8684 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8685 AMDGPU::OpName::src2_modifiers) >= 0)
8686 NewInstr.addImm(0);
8687 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8688 NewInstr->addOperand(Inst.getOperand(3));
8689 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8690 NewInstr.addImm(0);
8691 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8692 NewInstr.addImm(0);
8693 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8694 NewInstr.addImm(0);
8695 }
8696 } else {
8697 // Just copy the SALU operands.
8698 for (const MachineOperand &Op : Inst.explicit_operands())
8699 NewInstr->addOperand(Op);
8700 }
8701
8702 // Remove any references to SCC. Vector instructions can't read from it, and
8703 // We're just about to add the implicit use / defs of VCC, and we don't want
8704 // both.
8705 for (MachineOperand &Op : Inst.implicit_operands()) {
8706 if (Op.getReg() == AMDGPU::SCC) {
8707 // Only propagate through live-def of SCC.
8708 if (Op.isDef() && !Op.isDead())
8709 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
8710 if (Op.isUse())
8711 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8712 }
8713 }
8714 Inst.eraseFromParent();
8715 Register NewDstReg;
8716 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8717 Register DstReg = NewInstr->getOperand(0).getReg();
8718 assert(DstReg.isVirtual());
8719 // Update the destination register class.
8720 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
8721 assert(NewDstRC);
8722 NewDstReg = MRI.createVirtualRegister(NewDstRC);
8723 MRI.replaceRegWith(DstReg, NewDstReg);
8724 }
8725 fixImplicitOperands(*NewInstr);
8726
8727 legalizeOperandsVALUt16(*NewInstr, MRI);
8728
8729 // Legalize the operands
8730 legalizeOperands(*NewInstr, MDT);
8731 if (NewDstReg)
8732 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8733}
8734
8735// Add/sub require special handling to deal with carry outs.
8736std::pair<bool, MachineBasicBlock *>
8737SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
8738 MachineDominatorTree *MDT) const {
8739 if (ST.hasAddNoCarryInsts()) {
8740 // Assume there is no user of scc since we don't select this in that case.
8741 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
8742 // is used.
8743
8744 MachineBasicBlock &MBB = *Inst.getParent();
8745 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8746
8747 Register OldDstReg = Inst.getOperand(0).getReg();
8748 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8749
8750 unsigned Opc = Inst.getOpcode();
8751 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
8752
8753 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
8754 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8755
8756 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
8757 Inst.removeOperand(3);
8758
8759 Inst.setDesc(get(NewOpc));
8760 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
8761 Inst.addImplicitDefUseOperands(*MBB.getParent());
8762 MRI.replaceRegWith(OldDstReg, ResultReg);
8763 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
8764
8765 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8766 return std::pair(true, NewBB);
8767 }
8768
8769 return std::pair(false, nullptr);
8770}
8771
8772void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
8773 MachineDominatorTree *MDT) const {
8774
8775 MachineBasicBlock &MBB = *Inst.getParent();
8776 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8777 MachineBasicBlock::iterator MII = Inst;
8778 const DebugLoc &DL = Inst.getDebugLoc();
8779
8780 MachineOperand &Dest = Inst.getOperand(0);
8781 MachineOperand &Src0 = Inst.getOperand(1);
8782 MachineOperand &Src1 = Inst.getOperand(2);
8783 MachineOperand &Cond = Inst.getOperand(3);
8784
8785 Register CondReg = Cond.getReg();
8786 bool IsSCC = (CondReg == AMDGPU::SCC);
8787
8788 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
8789 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
8790 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
8791 // output directly into the V_CNDMASK.
8792 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
8793 (Src1.getImm() == 0)) {
8794 for (MachineOperand &UseMO :
8796 MachineInstr &UseMI = *UseMO.getParent();
8797 switch (UseMI.getOpcode()) {
8798 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8799 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8800 case AMDGPU::V_CNDMASK_B16_t16_e32:
8801 case AMDGPU::V_CNDMASK_B16_t16_e64:
8802 case AMDGPU::V_CNDMASK_B32_e32:
8803 case AMDGPU::V_CNDMASK_B32_e64:
8804 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8805 if (UseMO.isImplicit() ||
8806 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
8807 UseMO.setReg(CondReg);
8808 }
8809 }
8810 if (MRI.use_nodbg_empty(Dest.getReg()))
8811 return;
8812 }
8813
8814 Register NewCondReg = CondReg;
8815 if (IsSCC) {
8816 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
8817 NewCondReg = MRI.createVirtualRegister(TC);
8818
8819 // Now look for the closest SCC def if it is a copy
8820 // replacing the CondReg with the COPY source register
8821 bool CopyFound = false;
8822 for (MachineInstr &CandI :
8824 Inst.getParent()->rend())) {
8825 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
8826 -1) {
8827 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
8828 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
8829 .addReg(CandI.getOperand(1).getReg());
8830 CopyFound = true;
8831 }
8832 break;
8833 }
8834 }
8835 if (!CopyFound) {
8836 // SCC def is not a copy
8837 // Insert a trivial select instead of creating a copy, because a copy from
8838 // SCC would semantically mean just copying a single bit, but we may need
8839 // the result to be a vector condition mask that needs preserving.
8840 unsigned Opcode =
8841 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
8842 auto NewSelect =
8843 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
8844 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
8845 }
8846 }
8847
8848 Register NewDestReg = MRI.createVirtualRegister(
8849 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
8850 MachineInstr *NewInst;
8851 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
8852 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
8853 .addImm(0)
8854 .add(Src1) // False
8855 .addImm(0)
8856 .add(Src0) // True
8857 .addReg(NewCondReg);
8858 } else {
8859 NewInst =
8860 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
8861 .add(Src1) // False
8862 .add(Src0) // True
8863 .addReg(NewCondReg);
8864 }
8865 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
8866 legalizeOperands(*NewInst, MDT);
8867 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
8868}
8869
8870void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
8871 MachineInstr &Inst) const {
8872 MachineBasicBlock &MBB = *Inst.getParent();
8873 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8874 MachineBasicBlock::iterator MII = Inst;
8875 const DebugLoc &DL = Inst.getDebugLoc();
8876
8877 MachineOperand &Dest = Inst.getOperand(0);
8878 MachineOperand &Src = Inst.getOperand(1);
8879 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8880 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8881
8882 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8883 : AMDGPU::V_SUB_CO_U32_e32;
8884
8885 BuildMI(MBB, MII, DL, get(SubOp), TmpReg)
8886 .addImm(0)
8887 .addReg(Src.getReg());
8888
8889 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
8890 .addReg(Src.getReg())
8891 .addReg(TmpReg);
8892
8893 MRI.replaceRegWith(Dest.getReg(), ResultReg);
8894 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8895}
8896
8897void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
8898 MachineInstr &Inst) const {
8899 MachineBasicBlock &MBB = *Inst.getParent();
8900 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8901 MachineBasicBlock::iterator MII = Inst;
8902 const DebugLoc &DL = Inst.getDebugLoc();
8903
8904 MachineOperand &Dest = Inst.getOperand(0);
8905 MachineOperand &Src1 = Inst.getOperand(1);
8906 MachineOperand &Src2 = Inst.getOperand(2);
8907 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8908 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8909 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8910
8911 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8912 : AMDGPU::V_SUB_CO_U32_e32;
8913
8914 BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
8915 .addReg(Src1.getReg())
8916 .addReg(Src2.getReg());
8917
8918 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
8919
8920 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
8921 .addReg(SubResultReg)
8922 .addReg(TmpReg);
8923
8924 MRI.replaceRegWith(Dest.getReg(), ResultReg);
8925 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8926}
8927
8928void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
8929 MachineInstr &Inst) const {
8930 MachineBasicBlock &MBB = *Inst.getParent();
8931 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8932 MachineBasicBlock::iterator MII = Inst;
8933 const DebugLoc &DL = Inst.getDebugLoc();
8934
8935 MachineOperand &Dest = Inst.getOperand(0);
8936 MachineOperand &Src0 = Inst.getOperand(1);
8937 MachineOperand &Src1 = Inst.getOperand(2);
8938
8939 if (ST.hasDLInsts()) {
8940 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8941 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
8942 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
8943
8944 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
8945 .add(Src0)
8946 .add(Src1);
8947
8948 MRI.replaceRegWith(Dest.getReg(), NewDest);
8949 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
8950 } else {
8951 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
8952 // invert either source and then perform the XOR. If either source is a
8953 // scalar register, then we can leave the inversion on the scalar unit to
8954 // achieve a better distribution of scalar and vector instructions.
8955 bool Src0IsSGPR = Src0.isReg() &&
8956 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
8957 bool Src1IsSGPR = Src1.isReg() &&
8958 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
8959 MachineInstr *Xor;
8960 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
8961 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
8962
8963 // Build a pair of scalar instructions and add them to the work list.
8964 // The next iteration over the work list will lower these to the vector
8965 // unit as necessary.
8966 if (Src0IsSGPR) {
8967 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
8968 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
8969 .addReg(Temp)
8970 .add(Src1);
8971 } else if (Src1IsSGPR) {
8972 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
8973 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
8974 .add(Src0)
8975 .addReg(Temp);
8976 } else {
8977 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
8978 .add(Src0)
8979 .add(Src1);
8980 MachineInstr *Not =
8981 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
8982 Worklist.insert(Not);
8983 }
8984
8985 MRI.replaceRegWith(Dest.getReg(), NewDest);
8986
8987 Worklist.insert(Xor);
8988
8989 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
8990 }
8991}
8992
8993void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
8994 MachineInstr &Inst,
8995 unsigned Opcode) const {
8996 MachineBasicBlock &MBB = *Inst.getParent();
8997 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8998 MachineBasicBlock::iterator MII = Inst;
8999 const DebugLoc &DL = Inst.getDebugLoc();
9000
9001 MachineOperand &Dest = Inst.getOperand(0);
9002 MachineOperand &Src0 = Inst.getOperand(1);
9003 MachineOperand &Src1 = Inst.getOperand(2);
9004
9005 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9006 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
9007
9008 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
9009 .add(Src0)
9010 .add(Src1);
9011
9012 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
9013 .addReg(Interm);
9014
9015 Worklist.insert(&Op);
9016 Worklist.insert(&Not);
9017
9018 MRI.replaceRegWith(Dest.getReg(), NewDest);
9019 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9020}
9021
9022void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
9023 MachineInstr &Inst,
9024 unsigned Opcode) const {
9025 MachineBasicBlock &MBB = *Inst.getParent();
9026 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9027 MachineBasicBlock::iterator MII = Inst;
9028 const DebugLoc &DL = Inst.getDebugLoc();
9029
9030 MachineOperand &Dest = Inst.getOperand(0);
9031 MachineOperand &Src0 = Inst.getOperand(1);
9032 MachineOperand &Src1 = Inst.getOperand(2);
9033
9034 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9035 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
9036
9037 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
9038 .add(Src1);
9039
9040 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
9041 .add(Src0)
9042 .addReg(Interm);
9043
9044 Worklist.insert(&Not);
9045 Worklist.insert(&Op);
9046
9047 MRI.replaceRegWith(Dest.getReg(), NewDest);
9048 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9049}
9050
9051void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
9052 MachineInstr &Inst, unsigned Opcode,
9053 bool Swap) const {
9054 MachineBasicBlock &MBB = *Inst.getParent();
9055 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9056
9057 MachineOperand &Dest = Inst.getOperand(0);
9058 MachineOperand &Src0 = Inst.getOperand(1);
9059 const DebugLoc &DL = Inst.getDebugLoc();
9060
9061 MachineBasicBlock::iterator MII = Inst;
9062
9063 const MCInstrDesc &InstDesc = get(Opcode);
9064 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9065 MRI.getRegClass(Src0.getReg()) :
9066 &AMDGPU::SGPR_32RegClass;
9067
9068 const TargetRegisterClass *Src0SubRC =
9069 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9070
9071 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9072 AMDGPU::sub0, Src0SubRC);
9073
9074 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9075 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9076 const TargetRegisterClass *NewDestSubRC =
9077 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9078
9079 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9080 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
9081
9082 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9083 AMDGPU::sub1, Src0SubRC);
9084
9085 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9086 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
9087
9088 if (Swap)
9089 std::swap(DestSub0, DestSub1);
9090
9091 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9092 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9093 .addReg(DestSub0)
9094 .addImm(AMDGPU::sub0)
9095 .addReg(DestSub1)
9096 .addImm(AMDGPU::sub1);
9097
9098 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9099
9100 Worklist.insert(&LoHalf);
9101 Worklist.insert(&HiHalf);
9102
9103 // We don't need to legalizeOperands here because for a single operand, src0
9104 // will support any kind of input.
9105
9106 // Move all users of this moved value.
9107 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9108}
9109
9110// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9111// split the s_mul_u64 in 32-bit vector multiplications.
9112void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9113 MachineInstr &Inst,
9114 MachineDominatorTree *MDT) const {
9115 MachineBasicBlock &MBB = *Inst.getParent();
9116 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9117
9118 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9119 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9120 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9121
9122 MachineOperand &Dest = Inst.getOperand(0);
9123 MachineOperand &Src0 = Inst.getOperand(1);
9124 MachineOperand &Src1 = Inst.getOperand(2);
9125 const DebugLoc &DL = Inst.getDebugLoc();
9126 MachineBasicBlock::iterator MII = Inst;
9127
9128 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9129 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9130 const TargetRegisterClass *Src0SubRC =
9131 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9132 if (RI.isSGPRClass(Src0SubRC))
9133 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9134 const TargetRegisterClass *Src1SubRC =
9135 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9136 if (RI.isSGPRClass(Src1SubRC))
9137 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9138
9139 // First, we extract the low 32-bit and high 32-bit values from each of the
9140 // operands.
9141 MachineOperand Op0L =
9142 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9143 MachineOperand Op1L =
9144 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9145 MachineOperand Op0H =
9146 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9147 MachineOperand Op1H =
9148 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9149
9150 // The multilication is done as follows:
9151 //
9152 // Op1H Op1L
9153 // * Op0H Op0L
9154 // --------------------
9155 // Op1H*Op0L Op1L*Op0L
9156 // + Op1H*Op0H Op1L*Op0H
9157 // -----------------------------------------
9158 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9159 //
9160 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9161 // value and that would overflow.
9162 // The low 32-bit value is Op1L*Op0L.
9163 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9164
9165 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9166 MachineInstr *Op1L_Op0H =
9167 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9168 .add(Op1L)
9169 .add(Op0H);
9170
9171 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9172 MachineInstr *Op1H_Op0L =
9173 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9174 .add(Op1H)
9175 .add(Op0L);
9176
9177 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9178 MachineInstr *Carry =
9179 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9180 .add(Op1L)
9181 .add(Op0L);
9182
9183 MachineInstr *LoHalf =
9184 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9185 .add(Op1L)
9186 .add(Op0L);
9187
9188 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9189 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9190 .addReg(Op1L_Op0H_Reg)
9191 .addReg(Op1H_Op0L_Reg);
9192
9193 MachineInstr *HiHalf =
9194 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9195 .addReg(AddReg)
9196 .addReg(CarryReg);
9197
9198 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9199 .addReg(DestSub0)
9200 .addImm(AMDGPU::sub0)
9201 .addReg(DestSub1)
9202 .addImm(AMDGPU::sub1);
9203
9204 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9205
9206 // Try to legalize the operands in case we need to swap the order to keep it
9207 // valid.
9208 legalizeOperands(*Op1L_Op0H, MDT);
9209 legalizeOperands(*Op1H_Op0L, MDT);
9210 legalizeOperands(*Carry, MDT);
9211 legalizeOperands(*LoHalf, MDT);
9212 legalizeOperands(*Add, MDT);
9213 legalizeOperands(*HiHalf, MDT);
9214
9215 // Move all users of this moved value.
9216 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9217}
9218
9219// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9220// multiplications.
9221void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9222 MachineInstr &Inst,
9223 MachineDominatorTree *MDT) const {
9224 MachineBasicBlock &MBB = *Inst.getParent();
9225 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9226
9227 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9228 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9229 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9230
9231 MachineOperand &Dest = Inst.getOperand(0);
9232 MachineOperand &Src0 = Inst.getOperand(1);
9233 MachineOperand &Src1 = Inst.getOperand(2);
9234 const DebugLoc &DL = Inst.getDebugLoc();
9235 MachineBasicBlock::iterator MII = Inst;
9236
9237 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9238 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9239 const TargetRegisterClass *Src0SubRC =
9240 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9241 if (RI.isSGPRClass(Src0SubRC))
9242 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9243 const TargetRegisterClass *Src1SubRC =
9244 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9245 if (RI.isSGPRClass(Src1SubRC))
9246 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9247
9248 // First, we extract the low 32-bit and high 32-bit values from each of the
9249 // operands.
9250 MachineOperand Op0L =
9251 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9252 MachineOperand Op1L =
9253 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9254
9255 unsigned Opc = Inst.getOpcode();
9256 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9257 ? AMDGPU::V_MUL_HI_U32_e64
9258 : AMDGPU::V_MUL_HI_I32_e64;
9259 MachineInstr *HiHalf =
9260 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9261
9262 MachineInstr *LoHalf =
9263 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9264 .add(Op1L)
9265 .add(Op0L);
9266
9267 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9268 .addReg(DestSub0)
9269 .addImm(AMDGPU::sub0)
9270 .addReg(DestSub1)
9271 .addImm(AMDGPU::sub1);
9272
9273 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9274
9275 // Try to legalize the operands in case we need to swap the order to keep it
9276 // valid.
9277 legalizeOperands(*HiHalf, MDT);
9278 legalizeOperands(*LoHalf, MDT);
9279
9280 // Move all users of this moved value.
9281 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9282}
9283
9284void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9285 MachineInstr &Inst, unsigned Opcode,
9286 MachineDominatorTree *MDT) const {
9287 MachineBasicBlock &MBB = *Inst.getParent();
9288 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9289
9290 MachineOperand &Dest = Inst.getOperand(0);
9291 MachineOperand &Src0 = Inst.getOperand(1);
9292 MachineOperand &Src1 = Inst.getOperand(2);
9293 const DebugLoc &DL = Inst.getDebugLoc();
9294
9295 MachineBasicBlock::iterator MII = Inst;
9296
9297 const MCInstrDesc &InstDesc = get(Opcode);
9298 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9299 MRI.getRegClass(Src0.getReg()) :
9300 &AMDGPU::SGPR_32RegClass;
9301
9302 const TargetRegisterClass *Src0SubRC =
9303 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9304 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9305 MRI.getRegClass(Src1.getReg()) :
9306 &AMDGPU::SGPR_32RegClass;
9307
9308 const TargetRegisterClass *Src1SubRC =
9309 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9310
9311 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9312 AMDGPU::sub0, Src0SubRC);
9313 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9314 AMDGPU::sub0, Src1SubRC);
9315 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9316 AMDGPU::sub1, Src0SubRC);
9317 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9318 AMDGPU::sub1, Src1SubRC);
9319
9320 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9321 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9322 const TargetRegisterClass *NewDestSubRC =
9323 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9324
9325 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9326 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9327 .add(SrcReg0Sub0)
9328 .add(SrcReg1Sub0);
9329
9330 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9331 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9332 .add(SrcReg0Sub1)
9333 .add(SrcReg1Sub1);
9334
9335 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9336 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9337 .addReg(DestSub0)
9338 .addImm(AMDGPU::sub0)
9339 .addReg(DestSub1)
9340 .addImm(AMDGPU::sub1);
9341
9342 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9343
9344 Worklist.insert(&LoHalf);
9345 Worklist.insert(&HiHalf);
9346
9347 // Move all users of this moved value.
9348 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9349}
9350
9351void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9352 MachineInstr &Inst,
9353 MachineDominatorTree *MDT) const {
9354 MachineBasicBlock &MBB = *Inst.getParent();
9355 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9356
9357 MachineOperand &Dest = Inst.getOperand(0);
9358 MachineOperand &Src0 = Inst.getOperand(1);
9359 MachineOperand &Src1 = Inst.getOperand(2);
9360 const DebugLoc &DL = Inst.getDebugLoc();
9361
9362 MachineBasicBlock::iterator MII = Inst;
9363
9364 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9365
9366 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9367
9368 MachineOperand* Op0;
9369 MachineOperand* Op1;
9370
9371 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9372 Op0 = &Src0;
9373 Op1 = &Src1;
9374 } else {
9375 Op0 = &Src1;
9376 Op1 = &Src0;
9377 }
9378
9379 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9380 .add(*Op0);
9381
9382 Register NewDest = MRI.createVirtualRegister(DestRC);
9383
9384 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9385 .addReg(Interm)
9386 .add(*Op1);
9387
9388 MRI.replaceRegWith(Dest.getReg(), NewDest);
9389
9390 Worklist.insert(&Xor);
9391}
9392
9393void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9394 MachineInstr &Inst) const {
9395 MachineBasicBlock &MBB = *Inst.getParent();
9396 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9397
9398 MachineBasicBlock::iterator MII = Inst;
9399 const DebugLoc &DL = Inst.getDebugLoc();
9400
9401 MachineOperand &Dest = Inst.getOperand(0);
9402 MachineOperand &Src = Inst.getOperand(1);
9403
9404 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9405 const TargetRegisterClass *SrcRC = Src.isReg() ?
9406 MRI.getRegClass(Src.getReg()) :
9407 &AMDGPU::SGPR_32RegClass;
9408
9409 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9410 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9411
9412 const TargetRegisterClass *SrcSubRC =
9413 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9414
9415 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9416 AMDGPU::sub0, SrcSubRC);
9417 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9418 AMDGPU::sub1, SrcSubRC);
9419
9420 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9421
9422 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9423
9424 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9425
9426 // We don't need to legalize operands here. src0 for either instruction can be
9427 // an SGPR, and the second input is unused or determined here.
9428 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9429}
9430
9431void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9432 MachineInstr &Inst) const {
9433 MachineBasicBlock &MBB = *Inst.getParent();
9434 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9435 MachineBasicBlock::iterator MII = Inst;
9436 const DebugLoc &DL = Inst.getDebugLoc();
9437
9438 MachineOperand &Dest = Inst.getOperand(0);
9439 uint32_t Imm = Inst.getOperand(2).getImm();
9440 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9441 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9442
9443 (void) Offset;
9444
9445 // Only sext_inreg cases handled.
9446 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9447 Offset == 0 && "Not implemented");
9448
9449 if (BitWidth < 32) {
9450 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9451 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9452 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9453
9454 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9455 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9456 .addImm(0)
9457 .addImm(BitWidth);
9458
9459 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9460 .addImm(31)
9461 .addReg(MidRegLo);
9462
9463 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9464 .addReg(MidRegLo)
9465 .addImm(AMDGPU::sub0)
9466 .addReg(MidRegHi)
9467 .addImm(AMDGPU::sub1);
9468
9469 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9470 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9471 return;
9472 }
9473
9474 MachineOperand &Src = Inst.getOperand(1);
9475 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9476 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9477
9478 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9479 .addImm(31)
9480 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9481
9482 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9483 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9484 .addImm(AMDGPU::sub0)
9485 .addReg(TmpReg)
9486 .addImm(AMDGPU::sub1);
9487
9488 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9489 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9490}
9491
9492void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9493 MachineInstr &Inst, unsigned Opcode,
9494 MachineDominatorTree *MDT) const {
9495 // (S_FLBIT_I32_B64 hi:lo) ->
9496 // -> (umin (V_FFBH_U32_e32 hi), (uaddsat (V_FFBH_U32_e32 lo), 32))
9497 // (S_FF1_I32_B64 hi:lo) ->
9498 // ->(umin (uaddsat (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9499
9500 MachineBasicBlock &MBB = *Inst.getParent();
9501 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9502 MachineBasicBlock::iterator MII = Inst;
9503 const DebugLoc &DL = Inst.getDebugLoc();
9504
9505 MachineOperand &Dest = Inst.getOperand(0);
9506 MachineOperand &Src = Inst.getOperand(1);
9507
9508 const MCInstrDesc &InstDesc = get(Opcode);
9509
9510 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9511 unsigned OpcodeAdd = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64
9512 : AMDGPU::V_ADD_CO_U32_e32;
9513
9514 const TargetRegisterClass *SrcRC =
9515 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9516 const TargetRegisterClass *SrcSubRC =
9517 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9518
9519 MachineOperand SrcRegSub0 =
9520 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9521 MachineOperand SrcRegSub1 =
9522 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9523
9524 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9525 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9526 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9527 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9528
9529 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9530
9531 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9532
9533 BuildMI(MBB, MII, DL, get(OpcodeAdd), MidReg3)
9534 .addReg(IsCtlz ? MidReg1 : MidReg2)
9535 .addImm(32)
9536 .addImm(1); // enable clamp
9537
9538 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9539 .addReg(MidReg3)
9540 .addReg(IsCtlz ? MidReg2 : MidReg1);
9541
9542 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9543
9544 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9545}
9546
9547void SIInstrInfo::addUsersToMoveToVALUWorklist(
9548 Register DstReg, MachineRegisterInfo &MRI,
9549 SIInstrWorklist &Worklist) const {
9550 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9551 MachineInstr &UseMI = *MO.getParent();
9552
9553 unsigned OpNo = 0;
9554
9555 switch (UseMI.getOpcode()) {
9556 case AMDGPU::COPY:
9557 case AMDGPU::WQM:
9558 case AMDGPU::SOFT_WQM:
9559 case AMDGPU::STRICT_WWM:
9560 case AMDGPU::STRICT_WQM:
9561 case AMDGPU::REG_SEQUENCE:
9562 case AMDGPU::PHI:
9563 case AMDGPU::INSERT_SUBREG:
9564 break;
9565 default:
9566 OpNo = MO.getOperandNo();
9567 break;
9568 }
9569
9570 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9571 MRI.constrainRegClass(DstReg, OpRC);
9572
9573 if (!RI.hasVectorRegisters(OpRC))
9574 Worklist.insert(&UseMI);
9575 else
9576 // Legalization could change user list.
9577 legalizeOperandsVALUt16(UseMI, OpNo, MRI);
9578 }
9579}
9580
9581void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
9583 MachineInstr &Inst) const {
9584 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9585 MachineBasicBlock *MBB = Inst.getParent();
9586 MachineOperand &Src0 = Inst.getOperand(1);
9587 MachineOperand &Src1 = Inst.getOperand(2);
9588 const DebugLoc &DL = Inst.getDebugLoc();
9589
9590 if (ST.useRealTrue16Insts()) {
9591 Register SrcReg0, SrcReg1;
9592 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
9593 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9594 BuildMI(*MBB, Inst, DL,
9595 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9596 .add(Src0);
9597 } else {
9598 SrcReg0 = Src0.getReg();
9599 }
9600
9601 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
9602 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9603 BuildMI(*MBB, Inst, DL,
9604 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9605 .add(Src1);
9606 } else {
9607 SrcReg1 = Src1.getReg();
9608 }
9609
9610 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
9611 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
9612
9613 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
9614 switch (Inst.getOpcode()) {
9615 case AMDGPU::S_PACK_LL_B32_B16:
9616 NewMI
9617 .addReg(SrcReg0, {},
9618 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9619 .addImm(AMDGPU::lo16)
9620 .addReg(SrcReg1, {},
9621 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9622 .addImm(AMDGPU::hi16);
9623 break;
9624 case AMDGPU::S_PACK_LH_B32_B16:
9625 NewMI
9626 .addReg(SrcReg0, {},
9627 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9628 .addImm(AMDGPU::lo16)
9629 .addReg(SrcReg1, {}, AMDGPU::hi16)
9630 .addImm(AMDGPU::hi16);
9631 break;
9632 case AMDGPU::S_PACK_HL_B32_B16:
9633 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9634 .addImm(AMDGPU::lo16)
9635 .addReg(SrcReg1, {},
9636 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9637 .addImm(AMDGPU::hi16);
9638 break;
9639 case AMDGPU::S_PACK_HH_B32_B16:
9640 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9641 .addImm(AMDGPU::lo16)
9642 .addReg(SrcReg1, {}, AMDGPU::hi16)
9643 .addImm(AMDGPU::hi16);
9644 break;
9645 default:
9646 llvm_unreachable("unhandled s_pack_* instruction");
9647 }
9648
9649 MachineOperand &Dest = Inst.getOperand(0);
9650 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9651 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9652 return;
9653 }
9654
9655 switch (Inst.getOpcode()) {
9656 case AMDGPU::S_PACK_LL_B32_B16: {
9657 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9658 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9659
9660 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
9661 // 0.
9662 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9663 .addImm(0xffff);
9664
9665 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
9666 .addReg(ImmReg, RegState::Kill)
9667 .add(Src0);
9668
9669 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9670 .add(Src1)
9671 .addImm(16)
9672 .addReg(TmpReg, RegState::Kill);
9673 break;
9674 }
9675 case AMDGPU::S_PACK_LH_B32_B16: {
9676 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9677 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9678 .addImm(0xffff);
9679 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
9680 .addReg(ImmReg, RegState::Kill)
9681 .add(Src0)
9682 .add(Src1);
9683 break;
9684 }
9685 case AMDGPU::S_PACK_HL_B32_B16: {
9686 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9687 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9688 .addImm(16)
9689 .add(Src0);
9690 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9691 .add(Src1)
9692 .addImm(16)
9693 .addReg(TmpReg, RegState::Kill);
9694 break;
9695 }
9696 case AMDGPU::S_PACK_HH_B32_B16: {
9697 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9698 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9699 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9700 .addImm(16)
9701 .add(Src0);
9702 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9703 .addImm(0xffff0000);
9704 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
9705 .add(Src1)
9706 .addReg(ImmReg, RegState::Kill)
9707 .addReg(TmpReg, RegState::Kill);
9708 break;
9709 }
9710 default:
9711 llvm_unreachable("unhandled s_pack_* instruction");
9712 }
9713
9714 MachineOperand &Dest = Inst.getOperand(0);
9715 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9716 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9717}
9718
9719void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
9720 MachineInstr &SCCDefInst,
9721 SIInstrWorklist &Worklist,
9722 Register NewCond) const {
9723
9724 // Ensure that def inst defines SCC, which is still live.
9725 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
9726 !Op.isDead() && Op.getParent() == &SCCDefInst);
9727 SmallVector<MachineInstr *, 4> CopyToDelete;
9728 // This assumes that all the users of SCC are in the same block
9729 // as the SCC def.
9730 for (MachineInstr &MI : // Skip the def inst itself.
9731 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
9732 SCCDefInst.getParent()->end())) {
9733 // Check if SCC is used first.
9734 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
9735 if (SCCIdx != -1) {
9736 if (MI.isCopy()) {
9737 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
9738 Register DestReg = MI.getOperand(0).getReg();
9739
9740 MRI.replaceRegWith(DestReg, NewCond);
9741 CopyToDelete.push_back(&MI);
9742 } else {
9743
9744 if (NewCond.isValid())
9745 MI.getOperand(SCCIdx).setReg(NewCond);
9746
9747 Worklist.insert(&MI);
9748 }
9749 }
9750 // Exit if we find another SCC def.
9751 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
9752 break;
9753 }
9754 for (auto &Copy : CopyToDelete)
9755 Copy->eraseFromParent();
9756}
9757
9758// Instructions that use SCC may be converted to VALU instructions. When that
9759// happens, the SCC register is changed to VCC_LO. The instruction that defines
9760// SCC must be changed to an instruction that defines VCC. This function makes
9761// sure that the instruction that defines SCC is added to the moveToVALU
9762// worklist.
9763void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
9764 SIInstrWorklist &Worklist) const {
9765 // Look for a preceding instruction that either defines VCC or SCC. If VCC
9766 // then there is nothing to do because the defining instruction has been
9767 // converted to a VALU already. If SCC then that instruction needs to be
9768 // converted to a VALU.
9769 for (MachineInstr &MI :
9770 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
9771 SCCUseInst->getParent()->rend())) {
9772 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
9773 break;
9774 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
9775 Worklist.insert(&MI);
9776 break;
9777 }
9778 }
9779}
9780
9781const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
9782 const MachineInstr &Inst) const {
9783 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
9784
9785 switch (Inst.getOpcode()) {
9786 // For target instructions, getOpRegClass just returns the virtual register
9787 // class associated with the operand, so we need to find an equivalent VGPR
9788 // register class in order to move the instruction to the VALU.
9789 case AMDGPU::COPY:
9790 case AMDGPU::PHI:
9791 case AMDGPU::REG_SEQUENCE:
9792 case AMDGPU::INSERT_SUBREG:
9793 case AMDGPU::WQM:
9794 case AMDGPU::SOFT_WQM:
9795 case AMDGPU::STRICT_WWM:
9796 case AMDGPU::STRICT_WQM: {
9797 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
9798 if (RI.isAGPRClass(SrcRC)) {
9799 if (RI.isAGPRClass(NewDstRC))
9800 return nullptr;
9801
9802 switch (Inst.getOpcode()) {
9803 case AMDGPU::PHI:
9804 case AMDGPU::REG_SEQUENCE:
9805 case AMDGPU::INSERT_SUBREG:
9806 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9807 break;
9808 default:
9809 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9810 }
9811
9812 if (!NewDstRC)
9813 return nullptr;
9814 } else {
9815 if (RI.isVGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9816 return nullptr;
9817
9818 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9819 if (!NewDstRC)
9820 return nullptr;
9821 }
9822
9823 return NewDstRC;
9824 }
9825 default:
9826 return NewDstRC;
9827 }
9828}
9829
9830// Find the one SGPR operand we are allowed to use.
9831Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
9832 int OpIndices[3]) const {
9833 const MCInstrDesc &Desc = MI.getDesc();
9834
9835 // Find the one SGPR operand we are allowed to use.
9836 //
9837 // First we need to consider the instruction's operand requirements before
9838 // legalizing. Some operands are required to be SGPRs, such as implicit uses
9839 // of VCC, but we are still bound by the constant bus requirement to only use
9840 // one.
9841 //
9842 // If the operand's class is an SGPR, we can never move it.
9843
9844 Register SGPRReg = findImplicitSGPRRead(MI);
9845 if (SGPRReg)
9846 return SGPRReg;
9847
9848 Register UsedSGPRs[3] = {Register()};
9849 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
9850
9851 for (unsigned i = 0; i < 3; ++i) {
9852 int Idx = OpIndices[i];
9853 if (Idx == -1)
9854 break;
9855
9856 const MachineOperand &MO = MI.getOperand(Idx);
9857 if (!MO.isReg())
9858 continue;
9859
9860 // Is this operand statically required to be an SGPR based on the operand
9861 // constraints?
9862 const TargetRegisterClass *OpRC =
9863 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
9864 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
9865 if (IsRequiredSGPR)
9866 return MO.getReg();
9867
9868 // If this could be a VGPR or an SGPR, Check the dynamic register class.
9869 Register Reg = MO.getReg();
9870 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
9871 if (RI.isSGPRClass(RegRC))
9872 UsedSGPRs[i] = Reg;
9873 }
9874
9875 // We don't have a required SGPR operand, so we have a bit more freedom in
9876 // selecting operands to move.
9877
9878 // Try to select the most used SGPR. If an SGPR is equal to one of the
9879 // others, we choose that.
9880 //
9881 // e.g.
9882 // V_FMA_F32 v0, s0, s0, s0 -> No moves
9883 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
9884
9885 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
9886 // prefer those.
9887
9888 if (UsedSGPRs[0]) {
9889 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
9890 SGPRReg = UsedSGPRs[0];
9891 }
9892
9893 if (!SGPRReg && UsedSGPRs[1]) {
9894 if (UsedSGPRs[1] == UsedSGPRs[2])
9895 SGPRReg = UsedSGPRs[1];
9896 }
9897
9898 return SGPRReg;
9899}
9900
9902 AMDGPU::OpName OperandName) const {
9903 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
9904 return nullptr;
9905
9906 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
9907 if (Idx == -1)
9908 return nullptr;
9909
9910 return &MI.getOperand(Idx);
9911}
9912
9914 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
9915 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
9918 return (Format << 44) |
9919 (1ULL << 56) | // RESOURCE_LEVEL = 1
9920 (3ULL << 60); // OOB_SELECT = 3
9921 }
9922
9923 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
9924 if (ST.isAmdHsaOS()) {
9925 // Set ATC = 1. GFX9 doesn't have this bit.
9926 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
9927 RsrcDataFormat |= (1ULL << 56);
9928
9929 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
9930 // BTW, it disables TC L2 and therefore decreases performance.
9931 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
9932 RsrcDataFormat |= (2ULL << 59);
9933 }
9934
9935 return RsrcDataFormat;
9936}
9937
9941 0xffffffff; // Size;
9942
9943 // GFX9 doesn't have ELEMENT_SIZE.
9944 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
9945 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
9946 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
9947 }
9948
9949 // IndexStride = 64 / 32.
9950 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
9951 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
9952
9953 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
9954 // Clear them unless we want a huge stride.
9955 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
9956 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
9957 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
9958
9959 return Rsrc23;
9960}
9961
9963 unsigned Opc = MI.getOpcode();
9964
9965 return isSMRD(Opc);
9966}
9967
9969 return get(Opc).mayLoad() &&
9970 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
9971}
9972
9974 TypeSize &MemBytes) const {
9975 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
9976 if (!Addr || !Addr->isFI())
9977 return Register();
9978
9979 assert(!MI.memoperands_empty() &&
9980 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
9981
9982 FrameIndex = Addr->getIndex();
9983
9984 int VDataIdx =
9985 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
9986 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
9987 return MI.getOperand(VDataIdx).getReg();
9988}
9989
9991 TypeSize &MemBytes) const {
9992 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
9993 assert(Addr && Addr->isFI());
9994 FrameIndex = Addr->getIndex();
9995
9996 int DataIdx =
9997 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
9998 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
9999 return MI.getOperand(DataIdx).getReg();
10000}
10001
10003 int &FrameIndex,
10004 TypeSize &MemBytes) const {
10005 if (!MI.mayLoad())
10006 return Register();
10007
10008 if (isMUBUF(MI) || isVGPRSpill(MI))
10009 return isStackAccess(MI, FrameIndex, MemBytes);
10010
10011 if (isSGPRSpill(MI))
10012 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10013
10014 return Register();
10015}
10016
10018 int &FrameIndex,
10019 TypeSize &MemBytes) const {
10020 if (!MI.mayStore())
10021 return Register();
10022
10023 if (isMUBUF(MI) || isVGPRSpill(MI))
10024 return isStackAccess(MI, FrameIndex, MemBytes);
10025
10026 if (isSGPRSpill(MI))
10027 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
10028
10029 return Register();
10030}
10031
10033 unsigned Opc = MI.getOpcode();
10035 unsigned DescSize = Desc.getSize();
10036
10037 // If we have a definitive size, we can use it. Otherwise we need to inspect
10038 // the operands to know the size.
10039 if (isFixedSize(MI)) {
10040 unsigned Size = DescSize;
10041
10042 // If we hit the buggy offset, an extra nop will be inserted in MC so
10043 // estimate the worst case.
10044 if (MI.isBranch() && ST.hasOffset3fBug())
10045 Size += 4;
10046
10047 return Size;
10048 }
10049
10050 // Instructions may have a 32-bit literal encoded after them. Check
10051 // operands that could ever be literals.
10052 if (isVALU(MI, /*AllowLDSDMA=*/true) || isSALU(MI)) {
10053 if (isDPP(MI))
10054 return DescSize;
10055 bool HasLiteral = false;
10056 unsigned LiteralSize = 4;
10057 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
10058 const MachineOperand &Op = MI.getOperand(I);
10059 const MCOperandInfo &OpInfo = Desc.operands()[I];
10060 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
10061 HasLiteral = true;
10062 if (ST.has64BitLiterals()) {
10063 switch (OpInfo.OperandType) {
10064 default:
10065 break;
10068 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
10069 LiteralSize = 8;
10070 break;
10073 // A 32-bit literal is only valid when the value fits in BOTH signed
10074 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
10075 // emitter's getLit64Encoding logic. This is because of the lack of
10076 // abilility to tell signedness of the literal, therefore we need to
10077 // be conservative and assume values outside this range require a
10078 // 64-bit literal encoding (8 bytes).
10079 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
10080 !isUInt<32>(Op.getImm()))
10081 LiteralSize = 8;
10082 break;
10083 }
10084 }
10085 break;
10086 }
10087 }
10088 return HasLiteral ? DescSize + LiteralSize : DescSize;
10089 }
10090
10091 // Check whether we have extra NSA words.
10092 if (isMIMG(MI)) {
10093 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
10094 if (VAddr0Idx < 0)
10095 return 8;
10096
10097 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
10098 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10099 }
10100
10101 switch (Opc) {
10102 case TargetOpcode::BUNDLE:
10103 return getInstBundleSize(MI);
10104 case TargetOpcode::INLINEASM:
10105 case TargetOpcode::INLINEASM_BR: {
10106 const MachineFunction *MF = MI.getMF();
10107 const char *AsmStr = MI.getOperand(0).getSymbolName();
10108 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10109 }
10110 default:
10111 if (MI.isMetaInstruction())
10112 return 0;
10113
10114 // If D16 Pseudo inst, get correct MC code size
10115 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10116 if (D16Info) {
10117 // Assume d16_lo/hi inst are always in same size
10118 unsigned LoInstOpcode = D16Info->LoOp;
10119 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10120 DescSize = Desc.getSize();
10121 }
10122
10123 // If FMA Pseudo inst, get correct MC code size
10124 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10125 // All potential lowerings are the same size; arbitrarily pick one.
10126 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10127 DescSize = Desc.getSize();
10128 }
10129
10130 return DescSize;
10131 }
10132}
10133
10136 if (MI.isBranch() && ST.hasOffset3fBug())
10137 return InstSizeVerifyMode::NoVerify;
10138 return InstSizeVerifyMode::ExactSize;
10139}
10140
10142 if (!isFLAT(MI))
10143 return false;
10144
10145 if (MI.memoperands_empty())
10146 return true;
10147
10148 for (const MachineMemOperand *MMO : MI.memoperands()) {
10150 return true;
10151 }
10152 return false;
10153}
10154
10157 static const std::pair<int, const char *> TargetIndices[] = {
10158 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10159 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10160 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10161 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10162 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10163 return ArrayRef(TargetIndices);
10164}
10165
10166/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10167/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10170 const ScheduleDAG *DAG) const {
10171 return new GCNHazardRecognizer(DAG->MF);
10172}
10173
10174/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10175/// pass.
10178 MachineLoopInfo *MLI) const {
10179 return new GCNHazardRecognizer(MF, MLI);
10180}
10181
10182// Called during:
10183// - pre-RA scheduling and post-RA scheduling
10186 const ScheduleDAGMI *DAG) const {
10187 // Borrowed from Arm Target
10188 // We would like to restrict this hazard recognizer to only
10189 // post-RA scheduling; we can tell that we're post-RA because we don't
10190 // track VRegLiveness.
10191 if (!DAG->hasVRegLiveness())
10192 return new GCNHazardRecognizer(DAG->MF);
10194}
10195
10196std::pair<unsigned, unsigned>
10198 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10199}
10200
10203 static const std::pair<unsigned, const char *> TargetFlags[] = {
10204 {MO_GOTPCREL, "amdgpu-gotprel"},
10205 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10206 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10207 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10208 {MO_REL32_LO, "amdgpu-rel32-lo"},
10209 {MO_REL32_HI, "amdgpu-rel32-hi"},
10210 {MO_REL64, "amdgpu-rel64"},
10211 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10212 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10213 {MO_ABS64, "amdgpu-abs64"},
10214 };
10215
10216 return ArrayRef(TargetFlags);
10217}
10218
10221 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10222 {
10223 {MONoClobber, "amdgpu-noclobber"},
10224 {MOLastUse, "amdgpu-last-use"},
10225 {MOCooperative, "amdgpu-cooperative"},
10226 {MOThreadPrivate, "amdgpu-thread-private"},
10227 };
10228
10229 return ArrayRef(TargetFlags);
10230}
10231
10233 const MachineFunction &MF) const {
10235 assert(SrcReg.isVirtual());
10236 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10237 return AMDGPU::WWM_COPY;
10238
10239 return AMDGPU::COPY;
10240}
10241
10243 uint32_t Opcode = MI.getOpcode();
10244 // Check if it is SGPR spill or wwm-register spill Opcode.
10245 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10246 return true;
10247
10248 const MachineFunction *MF = MI.getMF();
10249 const MachineRegisterInfo &MRI = MF->getRegInfo();
10251
10252 // See if this is Liverange split instruction inserted for SGPR or
10253 // wwm-register. The implicit def inserted for wwm-registers should also be
10254 // included as they can appear at the bb begin.
10255 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10256 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10257 return false;
10258
10259 Register Reg = MI.getOperand(0).getReg();
10260 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10261 return IsLRSplitInst;
10262
10263 return MFI->isWWMReg(Reg);
10264}
10265
10267 Register Reg) const {
10268 // We need to handle instructions which may be inserted during register
10269 // allocation to handle the prolog. The initial prolog instruction may have
10270 // been separated from the start of the block by spills and copies inserted
10271 // needed by the prolog. However, the insertions for scalar registers can
10272 // always be placed at the BB top as they are independent of the exec mask
10273 // value.
10274 bool IsNullOrVectorRegister = true;
10275 if (Reg) {
10276 const MachineFunction *MF = MI.getMF();
10277 const MachineRegisterInfo &MRI = MF->getRegInfo();
10278 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10279 }
10280
10281 return IsNullOrVectorRegister &&
10282 (canAddToBBProlog(MI) ||
10283 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10284 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10285}
10286
10290 const DebugLoc &DL,
10291 Register DestReg) const {
10292 if (ST.hasAddNoCarryInsts())
10293 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10294
10295 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10296 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10297 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10298
10299 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10300 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10301}
10302
10305 const DebugLoc &DL,
10306 Register DestReg,
10307 RegScavenger &RS) const {
10308 if (ST.hasAddNoCarryInsts())
10309 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10310
10311 // If available, prefer to use vcc.
10312 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10313 ? Register(RI.getVCC())
10314 : RS.scavengeRegisterBackwards(
10315 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10316 0, /* AllowSpill */ false);
10317
10318 // TODO: Users need to deal with this.
10319 if (!UnusedCarry.isValid())
10320 return MachineInstrBuilder();
10321
10322 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10323 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10324}
10325
10326bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10327 switch (Opcode) {
10328 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10329 case AMDGPU::SI_KILL_I1_TERMINATOR:
10330 return true;
10331 default:
10332 return false;
10333 }
10334}
10335
10337 switch (Opcode) {
10338 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10339 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10340 case AMDGPU::SI_KILL_I1_PSEUDO:
10341 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10342 default:
10343 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10344 }
10345}
10346
10347bool SIInstrInfo::isLegalMUBUFImmOffset(unsigned Imm) const {
10348 return Imm <= getMaxMUBUFImmOffset(ST);
10349}
10350
10352 // GFX12 field is non-negative 24-bit signed byte offset.
10353 const unsigned OffsetBits =
10354 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10355 return (1 << OffsetBits) - 1;
10356}
10357
10359 if (!ST.isWave32())
10360 return;
10361
10362 if (MI.isInlineAsm())
10363 return;
10364
10365 if (MI.getNumOperands() < MI.getNumExplicitOperands())
10366 return;
10367
10368 for (auto &Op : MI.implicit_operands()) {
10369 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10370 Op.setReg(AMDGPU::VCC_LO);
10371 }
10372}
10373
10375 if (!isSMRD(MI))
10376 return false;
10377
10378 // Check that it is using a buffer resource.
10379 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10380 if (Idx == -1) // e.g. s_memtime
10381 return false;
10382
10383 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10384 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10385}
10386
10387// Given Imm, split it into the values to put into the SOffset and ImmOffset
10388// fields in an MUBUF instruction. Return false if it is not possible (due to a
10389// hardware bug needing a workaround).
10390//
10391// The required alignment ensures that individual address components remain
10392// aligned if they are aligned to begin with. It also ensures that additional
10393// offsets within the given alignment can be added to the resulting ImmOffset.
10395 uint32_t &ImmOffset, Align Alignment) const {
10396 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10397 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10398 uint32_t Overflow = 0;
10399
10400 if (Imm > MaxImm) {
10401 if (Imm <= MaxImm + 64) {
10402 // Use an SOffset inline constant for 4..64
10403 Overflow = Imm - MaxImm;
10404 Imm = MaxImm;
10405 } else {
10406 // Try to keep the same value in SOffset for adjacent loads, so that
10407 // the corresponding register contents can be re-used.
10408 //
10409 // Load values with all low-bits (except for alignment bits) set into
10410 // SOffset, so that a larger range of values can be covered using
10411 // s_movk_i32.
10412 //
10413 // Atomic operations fail to work correctly when individual address
10414 // components are unaligned, even if their sum is aligned.
10415 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10416 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10417 Imm = Low;
10418 Overflow = High - Alignment.value();
10419 }
10420 }
10421
10422 if (Overflow > 0) {
10423 // There is a hardware bug in SI and CI which prevents address clamping in
10424 // MUBUF instructions from working correctly with SOffsets. The immediate
10425 // offset is unaffected.
10426 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10427 return false;
10428
10429 // It is not possible to set immediate in SOffset field on some targets.
10430 if (ST.hasRestrictedSOffset())
10431 return false;
10432 }
10433
10434 ImmOffset = Imm;
10435 SOffset = Overflow;
10436 return true;
10437}
10438
10439// Depending on the used address space and instructions, some immediate offsets
10440// are allowed and some are not.
10441// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10442// scratch instruction offsets can also be negative. On GFX12, offsets can be
10443// negative for all variants.
10444//
10445// There are several bugs related to these offsets:
10446// On gfx10.1, flat instructions that go into the global address space cannot
10447// use an offset.
10448//
10449// For scratch instructions, the address can be either an SGPR or a VGPR.
10450// The following offsets can be used, depending on the architecture (x means
10451// cannot be used):
10452// +----------------------------+------+------+
10453// | Address-Mode | SGPR | VGPR |
10454// +----------------------------+------+------+
10455// | gfx9 | | |
10456// | negative, 4-aligned offset | x | ok |
10457// | negative, unaligned offset | x | ok |
10458// +----------------------------+------+------+
10459// | gfx10 | | |
10460// | negative, 4-aligned offset | ok | ok |
10461// | negative, unaligned offset | ok | x |
10462// +----------------------------+------+------+
10463// | gfx10.3 | | |
10464// | negative, 4-aligned offset | ok | ok |
10465// | negative, unaligned offset | ok | ok |
10466// +----------------------------+------+------+
10467//
10468// This function ignores the addressing mode, so if an offset cannot be used in
10469// one addressing mode, it is considered illegal.
10470bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10471 AMDGPU::FlatAddrSpace FlatVariant) const {
10472 // TODO: Should 0 be special cased?
10473 if (!ST.hasFlatInstOffsets())
10474 return false;
10475
10477 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10478 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10479 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10480 return false;
10481
10482 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10483 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10484 (Offset % 4) != 0) {
10485 return false;
10486 }
10487
10488 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10489 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10490 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10491}
10492
10493// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10494std::pair<int64_t, int64_t>
10495SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10496 AMDGPU::FlatAddrSpace FlatVariant) const {
10497 int64_t RemainderOffset = COffsetVal;
10498 int64_t ImmField = 0;
10499
10500 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10501 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10502
10503 if (AllowNegative) {
10504 // Use signed division by a power of two to truncate towards 0.
10505 int64_t D = 1LL << NumBits;
10506 RemainderOffset = (COffsetVal / D) * D;
10507 ImmField = COffsetVal - RemainderOffset;
10508
10509 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10510 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10511 (ImmField % 4) != 0) {
10512 // Make ImmField a multiple of 4
10513 RemainderOffset += ImmField % 4;
10514 ImmField -= ImmField % 4;
10515 }
10516 } else if (COffsetVal >= 0) {
10517 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10518 RemainderOffset = COffsetVal - ImmField;
10519 }
10520
10521 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10522 assert(RemainderOffset + ImmField == COffsetVal);
10523 return {ImmField, RemainderOffset};
10524}
10525
10527 AMDGPU::FlatAddrSpace FlatVariant) const {
10528 if (ST.hasNegativeScratchOffsetBug() &&
10530 return false;
10531
10532 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10533}
10534
10535static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10536 switch (ST.getGeneration()) {
10537 default:
10538 break;
10541 return SIEncodingFamily::SI;
10544 return SIEncodingFamily::VI;
10548 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10551 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10555 }
10556 llvm_unreachable("Unknown subtarget generation!");
10557}
10558
10559bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10560 switch(MCOp) {
10561 // These opcodes use indirect register addressing so
10562 // they need special handling by codegen (currently missing).
10563 // Therefore it is too risky to allow these opcodes
10564 // to be selected by dpp combiner or sdwa peepholer.
10565 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10566 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10567 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10568 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10569 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10570 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10571 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10572 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10573 return true;
10574 default:
10575 return false;
10576 }
10577}
10578
10579#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10580 case OPCODE##_dpp: \
10581 case OPCODE##_e32: \
10582 case OPCODE##_e64: \
10583 case OPCODE##_e64_dpp: \
10584 case OPCODE##_sdwa:
10585
10586static bool isRenamedInGFX9(int Opcode) {
10587 switch (Opcode) {
10588 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
10589 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
10590 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
10591 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
10592 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
10593 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
10594 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
10595 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
10596 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
10597 //
10598 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10599 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10600 case AMDGPU::V_FMA_F16_gfx9_e64:
10601 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10602 case AMDGPU::V_INTERP_P2_F16:
10603 case AMDGPU::V_MAD_F16_e64:
10604 case AMDGPU::V_MAD_U16_e64:
10605 case AMDGPU::V_MAD_I16_e64:
10606 return true;
10607 default:
10608 return false;
10609 }
10610}
10611
10612int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
10613 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
10614 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10615
10616 unsigned Gen = subtargetEncodingFamily(ST);
10617
10618 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
10620
10621 // Adjust the encoding family to GFX80 for D16 buffer instructions when the
10622 // subtarget has UnpackedD16VMem feature.
10623 // TODO: remove this when we discard GFX80 encoding.
10624 if (ST.hasUnpackedD16VMem() && SIInstrFlags::isD16Buf(get(Opcode)))
10626
10627 if (SIInstrFlags::isSDWA(get(Opcode))) {
10628 switch (ST.getGeneration()) {
10629 default:
10631 break;
10634 break;
10637 break;
10638 }
10639 }
10640
10641 if (isMAI(Opcode)) {
10642 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
10643 if (MFMAOp != -1)
10644 Opcode = MFMAOp;
10645 }
10646
10647 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
10648
10649 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10651
10652 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10654
10655 // -1 means that Opcode is already a native instruction.
10656 if (MCOp == -1)
10657 return Opcode;
10658
10659 if (ST.hasGFX90AInsts()) {
10660 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10661 if (ST.hasGFX940Insts())
10663 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10665 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10667 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10668 MCOp = NMCOp;
10669 }
10670
10671 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
10672 // encoding in the given subtarget generation.
10673 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10674 return -1;
10675
10676 if (isAsmOnlyOpcode(MCOp))
10677 return -1;
10678
10679 return MCOp;
10680}
10681
10682static
10684 assert(RegOpnd.isReg());
10685 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
10686 getRegSubRegPair(RegOpnd);
10687}
10688
10691 assert(MI.isRegSequence());
10692 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
10693 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
10694 auto &RegOp = MI.getOperand(1 + 2 * I);
10695 return getRegOrUndef(RegOp);
10696 }
10698}
10699
10700// Try to find the definition of reg:subreg in subreg-manipulation pseudos
10701// Following a subreg of reg:subreg isn't supported
10704 if (!RSR.SubReg)
10705 return false;
10706 switch (MI.getOpcode()) {
10707 default: break;
10708 case AMDGPU::REG_SEQUENCE:
10709 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
10710 return true;
10711 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
10712 case AMDGPU::INSERT_SUBREG:
10713 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
10714 // inserted the subreg we're looking for
10715 RSR = getRegOrUndef(MI.getOperand(2));
10716 else { // the subreg in the rest of the reg
10717 auto R1 = getRegOrUndef(MI.getOperand(1));
10718 if (R1.SubReg) // subreg of subreg isn't supported
10719 return false;
10720 RSR.Reg = R1.Reg;
10721 }
10722 return true;
10723 }
10724 return false;
10725}
10726
10728 const MachineRegisterInfo &MRI) {
10729 assert(MRI.isSSA());
10730 if (!P.Reg.isVirtual())
10731 return nullptr;
10732
10733 auto RSR = P;
10734 auto *DefInst = MRI.getVRegDef(RSR.Reg);
10735 while (auto *MI = DefInst) {
10736 DefInst = nullptr;
10737 switch (MI->getOpcode()) {
10738 case AMDGPU::COPY:
10739 case AMDGPU::V_MOV_B32_e32: {
10740 auto &Op1 = MI->getOperand(1);
10741 if (Op1.isReg() && Op1.getReg().isVirtual()) {
10742 if (Op1.isUndef())
10743 return nullptr;
10744 RSR = getRegSubRegPair(Op1);
10745 DefInst = MRI.getVRegDef(RSR.Reg);
10746 }
10747 break;
10748 }
10749 default:
10750 if (followSubRegDef(*MI, RSR)) {
10751 if (!RSR.Reg)
10752 return nullptr;
10753 DefInst = MRI.getVRegDef(RSR.Reg);
10754 }
10755 }
10756 if (!DefInst)
10757 return MI;
10758 }
10759 return nullptr;
10760}
10761
10763 Register VReg,
10764 const MachineInstr &DefMI,
10765 const MachineInstr &UseMI) {
10766 assert(MRI.isSSA() && "Must be run on SSA");
10767
10768 auto *TRI = MRI.getTargetRegisterInfo();
10769 auto *DefBB = DefMI.getParent();
10770
10771 // Don't bother searching between blocks, although it is possible this block
10772 // doesn't modify exec.
10773 if (UseMI.getParent() != DefBB)
10774 return true;
10775
10776 const int MaxInstScan = 20;
10777 int NumInst = 0;
10778
10779 // Stop scan at the use.
10780 auto E = UseMI.getIterator();
10781 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
10782 if (I->isDebugInstr())
10783 continue;
10784
10785 if (++NumInst > MaxInstScan)
10786 return true;
10787
10788 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
10789 return true;
10790 }
10791
10792 return false;
10793}
10794
10796 Register VReg,
10797 const MachineInstr &DefMI) {
10798 assert(MRI.isSSA() && "Must be run on SSA");
10799
10800 auto *TRI = MRI.getTargetRegisterInfo();
10801 auto *DefBB = DefMI.getParent();
10802
10803 const int MaxUseScan = 10;
10804 int NumUse = 0;
10805
10806 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
10807 auto &UseInst = *Use.getParent();
10808 // Don't bother searching between blocks, although it is possible this block
10809 // doesn't modify exec.
10810 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10811 return true;
10812
10813 if (++NumUse > MaxUseScan)
10814 return true;
10815 }
10816
10817 if (NumUse == 0)
10818 return false;
10819
10820 const int MaxInstScan = 20;
10821 int NumInst = 0;
10822
10823 // Stop scan when we have seen all the uses.
10824 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
10825 assert(I != DefBB->end());
10826
10827 if (I->isDebugInstr())
10828 continue;
10829
10830 if (++NumInst > MaxInstScan)
10831 return true;
10832
10833 for (const MachineOperand &Op : I->operands()) {
10834 // We don't check reg masks here as they're used only on calls:
10835 // 1. EXEC is only considered const within one BB
10836 // 2. Call should be a terminator instruction if present in a BB
10837
10838 if (!Op.isReg())
10839 continue;
10840
10841 Register Reg = Op.getReg();
10842 if (Op.isUse()) {
10843 if (Reg == VReg && --NumUse == 0)
10844 return false;
10845 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
10846 return true;
10847 }
10848 }
10849}
10850
10853 const DebugLoc &DL, Register Src, Register Dst) const {
10854 auto Cur = MBB.begin();
10855 if (Cur != MBB.end())
10856 do {
10857 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
10858 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
10859 ++Cur;
10860 } while (Cur != MBB.end() && Cur != LastPHIIt);
10861
10862 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
10863 Dst);
10864}
10865
10868 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
10869 if (InsPt != MBB.end() &&
10870 (InsPt->getOpcode() == AMDGPU::SI_IF ||
10871 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
10872 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
10873 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
10874 InsPt++;
10875 return BuildMI(MBB, InsPt, DL,
10876 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
10877 .addReg(Src, {}, SrcSubReg)
10878 .addReg(AMDGPU::EXEC, RegState::Implicit);
10879 }
10880 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
10881 Dst);
10882}
10883
10884bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
10885
10887 const MachineInstr &SecondMI) const {
10888 for (const auto &Use : SecondMI.all_uses()) {
10889 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
10890 return true;
10891 }
10892 return false;
10893}
10894
10895/// If OpX is multicycle, anti-dependencies are not allowed.
10896/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
10897/// purpose.
10899 const MachineInstr &OpX) const {
10901}
10902
10905 ArrayRef<unsigned> Ops, int FrameIndex,
10906 MachineInstr *&CopyMI, LiveIntervals *LIS,
10907 VirtRegMap *VRM) const {
10908 // This is a bit of a hack (copied from AArch64). Consider this instruction:
10909 //
10910 // %0:sreg_32 = COPY $m0
10911 //
10912 // We explicitly chose SReg_32 for the virtual register so such a copy might
10913 // be eliminated by RegisterCoalescer. However, that may not be possible, and
10914 // %0 may even spill. We can't spill $m0 normally (it would require copying to
10915 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
10916 // TargetInstrInfo::foldMemoryOperand() is going to try.
10917 // A similar issue also exists with spilling and reloading $exec registers.
10918 //
10919 // To prevent that, constrain the %0 register class here.
10920 if (isFullCopyInstr(MI)) {
10921 Register DstReg = MI.getOperand(0).getReg();
10922 Register SrcReg = MI.getOperand(1).getReg();
10923 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
10924 (DstReg.isVirtual() != SrcReg.isVirtual())) {
10925 MachineRegisterInfo &MRI = MF.getRegInfo();
10926 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
10927 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
10928 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
10929 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
10930 return nullptr;
10931 }
10932 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
10933 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
10934 return nullptr;
10935 }
10936 }
10937 }
10938
10939 return nullptr;
10940}
10941
10943 const MachineInstr &MI,
10944 unsigned *PredCost) const {
10945 if (MI.isBundle()) {
10947 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
10948 unsigned Lat = 0, Count = 0;
10949 for (++I; I != E && I->isBundledWithPred(); ++I) {
10950 ++Count;
10951 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
10952 }
10953 return Lat + Count - 1;
10954 }
10955
10956 return SchedModel.computeInstrLatency(&MI);
10957}
10958
10959const MachineOperand &
10961 if (const MachineOperand *CallAddrOp =
10962 getNamedOperand(MI, AMDGPU::OpName::src0))
10963 return *CallAddrOp;
10965}
10966
10969 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10970 unsigned Opcode = MI.getOpcode();
10971
10972 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
10973 Register Dst = MI.getOperand(0).getReg();
10974 Register Src = isa<GIntrinsic>(MI) ? MI.getOperand(2).getReg()
10975 : MI.getOperand(1).getReg();
10976 LLT DstTy = MRI.getType(Dst);
10977 LLT SrcTy = MRI.getType(Src);
10978 unsigned DstAS = DstTy.getAddressSpace();
10979 unsigned SrcAS = SrcTy.getAddressSpace();
10980 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
10981 DstAS == AMDGPUAS::FLAT_ADDRESS &&
10982 ST.hasGloballyAddressableScratch()
10985 };
10986
10987 // If the target supports globally addressable scratch, the mapping from
10988 // scratch memory to the flat aperture changes therefore an address space cast
10989 // is no longer uniform.
10990 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
10991 return HandleAddrSpaceCast(MI);
10992
10993 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
10994 auto IID = GI->getIntrinsicID();
10999
11000 switch (IID) {
11001 case Intrinsic::amdgcn_addrspacecast_nonnull:
11002 return HandleAddrSpaceCast(MI);
11003 case Intrinsic::amdgcn_if:
11004 case Intrinsic::amdgcn_else:
11005 // FIXME: Uniform if second result
11006 break;
11007 }
11008
11010 }
11011
11012 // Loads from the private and flat address spaces are divergent, because
11013 // threads can execute the load instruction with the same inputs and get
11014 // different results.
11015 //
11016 // All other loads are not divergent, because if threads issue loads with the
11017 // same arguments, they will always get the same result.
11018 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11019 Opcode == AMDGPU::G_SEXTLOAD) {
11020 if (MI.memoperands_empty())
11021 return ValueUniformity::NeverUniform; // conservative assumption
11022
11023 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11024 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11025 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11026 })) {
11027 // At least one MMO in a non-global address space.
11029 }
11031 }
11032
11033 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11034 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11035 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11036 AMDGPU::isGenericAtomic(Opcode)) {
11038 }
11039
11040 // Result is computed from uniform SP and uniform wave-wide max size.
11041 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11043
11044 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11046
11048}
11049
11051 if (!Formatter)
11052 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11053 return Formatter.get();
11054}
11055
11057
11058 if (isNeverUniform(MI))
11060
11061 unsigned opcode = MI.getOpcode();
11062 if (opcode == AMDGPU::V_READLANE_B32 ||
11063 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11064 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11066
11067 // If any of defs is divergent, report as NeverUniform. isUniformReg will
11068 // calculate in more detail for each def from its reg class, if available.
11069 if (MI.isInlineAsm()) {
11070 for (const MachineOperand &MO : MI.operands()) {
11071 if (!MO.isReg() || !MO.isDef())
11072 continue;
11073 const TargetRegisterClass *RC =
11074 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
11075 if (!RC || !RI.isSGPRClass(RC))
11077 }
11078 }
11079
11080 if (isCopyInstr(MI)) {
11081 const MachineOperand &srcOp = MI.getOperand(1);
11082 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
11083 const TargetRegisterClass *regClass =
11084 RI.getPhysRegBaseClass(srcOp.getReg());
11085 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
11087 }
11089 }
11090
11091 // GMIR handling
11092 if (MI.isPreISelOpcode())
11094
11095 // Atomics are divergent because they are executed sequentially: when an
11096 // atomic operation refers to the same address in each thread, then each
11097 // thread after the first sees the value written by the previous thread as
11098 // original value.
11099
11100 if (isAtomic(MI))
11102
11103 // Loads from the private and flat address spaces are divergent, because
11104 // threads can execute the load instruction with the same inputs and get
11105 // different results.
11106 if (isFLAT(MI) && MI.mayLoad()) {
11107 if (MI.memoperands_empty())
11108 return ValueUniformity::NeverUniform; // conservative assumption
11109
11110 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11111 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11112 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11113 })) {
11114 // At least one MMO in a non-global address space.
11116 }
11117
11119 }
11120
11121 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11122 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11123
11124 // FIXME: It's conceptually broken to report this for an instruction, and not
11125 // a specific def operand. For inline asm in particular, there could be mixed
11126 // uniform and divergent results.
11127 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11128 const MachineOperand &SrcOp = MI.getOperand(I);
11129 if (!SrcOp.isReg())
11130 continue;
11131
11132 Register Reg = SrcOp.getReg();
11133 if (!Reg || !SrcOp.readsReg())
11134 continue;
11135
11136 // If RegBank is null, this is unassigned or an unallocatable special
11137 // register, which are all scalars.
11138 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11139 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11141 }
11142
11143 // TODO: Uniformity check condtions above can be rearranged for more
11144 // redability
11145
11146 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11147 // currently turned into no-op COPYs by SelectionDAG ISel and are
11148 // therefore no longer recognizable.
11149
11151}
11152
11154 switch (MF.getFunction().getCallingConv()) {
11156 return 1;
11158 return 2;
11160 return 3;
11164 const Function &F = MF.getFunction();
11165 F.getContext().diagnose(DiagnosticInfoUnsupported(
11166 F, "ds_ordered_count unsupported for this calling conv"));
11167 [[fallthrough]];
11168 }
11171 case CallingConv::C:
11172 case CallingConv::Fast:
11173 default:
11174 // Assume other calling conventions are various compute callable functions
11175 return 0;
11176 }
11177}
11178
11180 Register &SrcReg2, int64_t &CmpMask,
11181 int64_t &CmpValue) const {
11182 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11183 return false;
11184
11185 switch (MI.getOpcode()) {
11186 default:
11187 break;
11188 case AMDGPU::S_CMP_EQ_U32:
11189 case AMDGPU::S_CMP_EQ_I32:
11190 case AMDGPU::S_CMP_LG_U32:
11191 case AMDGPU::S_CMP_LG_I32:
11192 case AMDGPU::S_CMP_LT_U32:
11193 case AMDGPU::S_CMP_LT_I32:
11194 case AMDGPU::S_CMP_GT_U32:
11195 case AMDGPU::S_CMP_GT_I32:
11196 case AMDGPU::S_CMP_LE_U32:
11197 case AMDGPU::S_CMP_LE_I32:
11198 case AMDGPU::S_CMP_GE_U32:
11199 case AMDGPU::S_CMP_GE_I32:
11200 case AMDGPU::S_CMP_EQ_U64:
11201 case AMDGPU::S_CMP_LG_U64:
11202 SrcReg = MI.getOperand(0).getReg();
11203 if (MI.getOperand(1).isReg()) {
11204 if (MI.getOperand(1).getSubReg())
11205 return false;
11206 SrcReg2 = MI.getOperand(1).getReg();
11207 CmpValue = 0;
11208 } else if (MI.getOperand(1).isImm()) {
11209 SrcReg2 = Register();
11210 CmpValue = MI.getOperand(1).getImm();
11211 } else {
11212 return false;
11213 }
11214 CmpMask = ~0;
11215 return true;
11216 case AMDGPU::S_CMPK_EQ_U32:
11217 case AMDGPU::S_CMPK_EQ_I32:
11218 case AMDGPU::S_CMPK_LG_U32:
11219 case AMDGPU::S_CMPK_LG_I32:
11220 case AMDGPU::S_CMPK_LT_U32:
11221 case AMDGPU::S_CMPK_LT_I32:
11222 case AMDGPU::S_CMPK_GT_U32:
11223 case AMDGPU::S_CMPK_GT_I32:
11224 case AMDGPU::S_CMPK_LE_U32:
11225 case AMDGPU::S_CMPK_LE_I32:
11226 case AMDGPU::S_CMPK_GE_U32:
11227 case AMDGPU::S_CMPK_GE_I32:
11228 SrcReg = MI.getOperand(0).getReg();
11229 SrcReg2 = Register();
11230 CmpValue = MI.getOperand(1).getImm();
11231 CmpMask = ~0;
11232 return true;
11233 }
11234
11235 return false;
11236}
11237
11239 for (MachineBasicBlock *S : MBB->successors()) {
11240 if (S->isLiveIn(AMDGPU::SCC))
11241 return false;
11242 }
11243 return true;
11244}
11245
11246// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11247// (incoming SCC) = !(SCC defined by SCCDef).
11248// Return true if all uses can be re-written, false otherwise.
11249bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11250 MachineBasicBlock *MBB = SCCDef->getParent();
11251 SmallVector<MachineInstr *> InvertInstr;
11252 bool SCCIsDead = false;
11253
11254 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11255 constexpr unsigned ScanLimit = 12;
11256 unsigned Count = 0;
11257 for (MachineInstr &MI :
11258 make_range(std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11259 if (++Count > ScanLimit)
11260 return false;
11261 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11262 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11263 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11264 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11265 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11266 InvertInstr.push_back(&MI);
11267 else
11268 return false;
11269 }
11270 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11271 SCCIsDead = true;
11272 break;
11273 }
11274 }
11275 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11276 SCCIsDead = true;
11277
11278 // SCC may have more uses. Can't invert all of them.
11279 if (!SCCIsDead)
11280 return false;
11281
11282 // Invert uses
11283 for (MachineInstr *MI : InvertInstr) {
11284 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11285 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11286 swapOperands(*MI);
11287 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11288 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11289 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11290 ? AMDGPU::S_CBRANCH_SCC1
11291 : AMDGPU::S_CBRANCH_SCC0));
11292 } else {
11293 llvm_unreachable("SCC used but no inversion handling");
11294 }
11295 }
11296 return true;
11297}
11298
11299// SCC is already valid after SCCValid.
11300// SCCRedefine will redefine SCC to the same value already available after
11301// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11302// update kill/dead flags if necessary.
11303bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11304 bool NeedInversion) const {
11305 MachineInstr *KillsSCC = nullptr;
11306 if (SCCValid->getParent() != SCCRedefine->getParent())
11307 return false;
11308 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11309 SCCRedefine->getIterator())) {
11310 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11311 return false;
11312 if (MI.killsRegister(AMDGPU::SCC, &RI))
11313 KillsSCC = &MI;
11314 }
11315 if (NeedInversion && !invertSCCUse(SCCRedefine))
11316 return false;
11317 if (MachineOperand *SccDef =
11318 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11319 SccDef->setIsDead(false);
11320 if (KillsSCC)
11321 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11322 SCCRedefine->eraseFromParent();
11323 return true;
11324}
11325
11326static bool foldableSelect(const MachineInstr &Def) {
11327 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11328 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11329 return false;
11330 bool Op1IsNonZeroImm =
11331 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11332 bool Op2IsZeroImm =
11333 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11334 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11335 return false;
11336 return true;
11337}
11338
11339static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11340 unsigned &NewDefOpc) {
11341 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11342 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11343 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11344 Def.getOpcode() != AMDGPU::S_ADD_U32)
11345 return false;
11346 const MachineOperand &AddSrc1 = Def.getOperand(1);
11347 const MachineOperand &AddSrc2 = Def.getOperand(2);
11348 int64_t addend;
11349
11350 if ((!AddSrc1.isImm() || AddSrc1.getImm() != 1) &&
11351 (!AddSrc2.isImm() || AddSrc2.getImm() != 1) &&
11352 (!getFoldableImm(&AddSrc1, addend) || addend != 1) &&
11353 (!getFoldableImm(&AddSrc2, addend) || addend != 1))
11354 return false;
11355
11356 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11357 const MachineOperand *SccDef =
11358 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11359 if (!SccDef->isDead())
11360 return false;
11361 NewDefOpc = AMDGPU::S_ADD_U32;
11362 }
11363 NeedInversion = !NeedInversion;
11364 return true;
11365}
11366
11368 Register SrcReg2, int64_t CmpMask,
11369 int64_t CmpValue,
11370 const MachineRegisterInfo *MRI) const {
11371 if (!SrcReg || SrcReg.isPhysical())
11372 return false;
11373
11374 if (SrcReg2 && !getFoldableImm(SrcReg2, *MRI, CmpValue))
11375 return false;
11376
11377 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11378 this](bool NeedInversion) -> bool {
11379 if (CmpValue != 0)
11380 return false;
11381
11382 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11383 if (!Def)
11384 return false;
11385
11386 // For S_OP that set SCC = DST!=0, do the transformation
11387 //
11388 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11389 //
11390 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11391 // do the transformation:
11392 //
11393 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11394 //
11395 // If foldableSelect, s_cmp_lg_* is redundant because the SCC input value
11396 // for S_CSELECT* already has the same value that will be calculated by
11397 // s_cmp_lg_*
11398 //
11399 // s_cmp_[lg|eq]_* (S_CSELECT* (non-zero imm), 0), 0 => (S_CSELECT*
11400 // (non-zero imm), 0)
11401
11402 unsigned NewDefOpc = Def->getOpcode();
11403 if (!setsSCCIfResultIsNonZero(*Def) &&
11404 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc) &&
11405 !foldableSelect(*Def))
11406 return false;
11407
11408 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11409 return false;
11410
11411 if (NewDefOpc != Def->getOpcode())
11412 Def->setDesc(get(NewDefOpc));
11413
11414 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11415 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11416 // 64-bit foldableSelect then delete s_or_b32 in the sequence:
11417 // sX = s_cselect_b64 (non-zero imm), 0
11418 // sLo = copy sX.sub0
11419 // sHi = copy sX.sub1
11420 // sY = s_or_b32 sLo, sHi
11421 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11422 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11423 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11424 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11425 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11426 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11427 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11428 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11429 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11430 Def2->getOperand(1).isReg() &&
11431 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11432 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11433 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11434 MachineInstr *Select = MRI->getVRegDef(Def1->getOperand(1).getReg());
11435 if (Select && foldableSelect(*Select))
11436 optimizeSCC(Select, Def, /*NeedInversion=*/false);
11437 }
11438 }
11439 }
11440 return true;
11441 };
11442
11443 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11444 this](int64_t ExpectedValue, unsigned SrcSize,
11445 bool IsReversible, bool IsSigned) -> bool {
11446 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11447 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11448 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11449 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11450 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11451 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11452 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11453 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11454 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11455 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11456 //
11457 // Signed ge/gt are not used for the sign bit.
11458 //
11459 // If result of the AND is unused except in the compare:
11460 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11461 //
11462 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11463 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11464 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11465 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11466 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11467 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11468
11469 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11470 if (!Def)
11471 return false;
11472
11473 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11474 Def->getOpcode() != AMDGPU::S_AND_B64)
11475 return false;
11476
11477 int64_t Mask;
11478 const auto isMask = [&Mask, SrcSize](const MachineOperand *MO) -> bool {
11479 if (MO->isImm())
11480 Mask = MO->getImm();
11481 else if (!getFoldableImm(MO, Mask))
11482 return false;
11483 Mask &= maxUIntN(SrcSize);
11484 return isPowerOf2_64(Mask);
11485 };
11486
11487 MachineOperand *SrcOp = &Def->getOperand(1);
11488 if (isMask(SrcOp))
11489 SrcOp = &Def->getOperand(2);
11490 else if (isMask(&Def->getOperand(2)))
11491 SrcOp = &Def->getOperand(1);
11492 else
11493 return false;
11494
11495 // A valid Mask is required to have a single bit set, hence a non-zero and
11496 // power-of-two value. This verifies that we will not do 64-bit shift below.
11497 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11498 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11499 if (IsSigned && BitNo == SrcSize - 1)
11500 return false;
11501
11502 ExpectedValue <<= BitNo;
11503
11504 bool IsReversedCC = false;
11505 if (CmpValue != ExpectedValue) {
11506 if (!IsReversible)
11507 return false;
11508 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11509 if (!IsReversedCC)
11510 return false;
11511 }
11512
11513 Register DefReg = Def->getOperand(0).getReg();
11514 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11515 return false;
11516
11517 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11518 return false;
11519
11520 if (!MRI->use_nodbg_empty(DefReg)) {
11521 assert(!IsReversedCC);
11522 return true;
11523 }
11524
11525 // Replace AND with unused result with a S_BITCMP.
11526 MachineBasicBlock *MBB = Def->getParent();
11527
11528 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11529 : AMDGPU::S_BITCMP1_B32
11530 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11531 : AMDGPU::S_BITCMP1_B64;
11532
11533 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11534 .add(*SrcOp)
11535 .addImm(BitNo);
11536 Def->eraseFromParent();
11537
11538 return true;
11539 };
11540
11541 switch (CmpInstr.getOpcode()) {
11542 default:
11543 break;
11544 case AMDGPU::S_CMP_EQ_U32:
11545 case AMDGPU::S_CMP_EQ_I32:
11546 case AMDGPU::S_CMPK_EQ_U32:
11547 case AMDGPU::S_CMPK_EQ_I32:
11548 return optimizeCmpAnd(1, 32, true, false) ||
11549 optimizeCmpSelect(/*NeedInversion=*/true);
11550 case AMDGPU::S_CMP_GE_U32:
11551 case AMDGPU::S_CMPK_GE_U32:
11552 return optimizeCmpAnd(1, 32, false, false);
11553 case AMDGPU::S_CMP_GE_I32:
11554 case AMDGPU::S_CMPK_GE_I32:
11555 return optimizeCmpAnd(1, 32, false, true);
11556 case AMDGPU::S_CMP_EQ_U64:
11557 return optimizeCmpAnd(1, 64, true, false);
11558 case AMDGPU::S_CMP_LG_U32:
11559 case AMDGPU::S_CMP_LG_I32:
11560 case AMDGPU::S_CMPK_LG_U32:
11561 case AMDGPU::S_CMPK_LG_I32:
11562 return optimizeCmpAnd(0, 32, true, false) ||
11563 optimizeCmpSelect(/*NeedInversion=*/false);
11564 case AMDGPU::S_CMP_GT_U32:
11565 case AMDGPU::S_CMPK_GT_U32:
11566 return optimizeCmpAnd(0, 32, false, false);
11567 case AMDGPU::S_CMP_GT_I32:
11568 case AMDGPU::S_CMPK_GT_I32:
11569 return optimizeCmpAnd(0, 32, false, true);
11570 case AMDGPU::S_CMP_LG_U64:
11571 return optimizeCmpAnd(0, 64, true, false) ||
11572 optimizeCmpSelect(/*NeedInversion=*/false);
11573 }
11574
11575 return false;
11576}
11577
11579 AMDGPU::OpName OpName) const {
11580 if (!ST.needsAlignedVGPRs())
11581 return;
11582
11583 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
11584 if (OpNo < 0)
11585 return;
11586 MachineOperand &Op = MI.getOperand(OpNo);
11587 if (getOpSize(MI, OpNo) > 4)
11588 return;
11589
11590 // Add implicit aligned super-reg to force alignment on the data operand.
11591 const DebugLoc &DL = MI.getDebugLoc();
11592 MachineBasicBlock *BB = MI.getParent();
11594 Register DataReg = Op.getReg();
11595 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11597 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11598 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
11599 Register NewVR =
11600 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
11601 : &AMDGPU::VReg_64_Align2RegClass);
11602 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
11603 .addReg(DataReg, {}, Op.getSubReg())
11604 .addImm(AMDGPU::sub0)
11605 .addReg(Undef)
11606 .addImm(AMDGPU::sub1);
11607 Op.setReg(NewVR);
11608 Op.setSubReg(AMDGPU::sub0);
11609 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
11610}
11611
11613 if (isIGLP(*MI))
11614 return false;
11615
11617}
11618
11620 if (!isWMMA(MI) && !isSWMMAC(MI))
11621 return false;
11622
11623 if (ST.hasGFX1250Insts())
11624 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
11625
11626 return true;
11627}
11628
11630 unsigned Opcode = MI.getOpcode();
11631
11632 if (AMDGPU::isGFX12Plus(ST))
11633 return isDOT(MI) || isXDLWMMA(MI);
11634
11635 if (!isMAI(MI) || isDGEMM(Opcode) ||
11636 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11637 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11638 return false;
11639
11640 if (!ST.hasGFX940Insts())
11641 return true;
11642
11643 return AMDGPU::getMAIIsGFX940XDL(Opcode);
11644}
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
AMDGPU Register Bank Select
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static bool isUndef(const MachineInstr &MI)
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineInstr unsigned OpIdx
uint64_t High
uint64_t IntrinsicInst * II
#define P(N)
R600 Clause Merge
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static cl::opt< bool > Fix16BitCopies("amdgpu-fix-16-bit-physreg-copies", cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"), cl::init(true), cl::ReallyHidden)
static void expandSGPRCopy(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RC, bool Forward)
static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc)
static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize)
static bool compareMachineOp(const MachineOperand &Op0, const MachineOperand &Op1)
static bool isStride64(unsigned Opc)
static MachineBasicBlock * generateWaterFallLoop(const SIInstrInfo &TII, MachineInstr &MI, ArrayRef< MachineOperand * > ScalarOps, MachineDominatorTree *MDT, MachineBasicBlock::iterator Begin=nullptr, MachineBasicBlock::iterator End=nullptr, ArrayRef< Register > PhySGPRs={})
#define GENERATE_RENAMED_GFX9_CASES(OPCODE)
static std::tuple< unsigned, unsigned > extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc)
static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx)
static bool followSubRegDef(MachineInstr &MI, TargetInstrInfo::RegSubRegPair &RSR)
static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize)
static MachineInstr * swapImmOperands(MachineInstr &MI, MachineOperand &NonRegOp1, MachineOperand &NonRegOp2)
static void copyFlagsToImplicitVCC(MachineInstr &MI, const MachineOperand &Orig)
static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, LocationSize WidthB, int OffsetB)
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, RegScavenger &RS, bool RegsOverlap, Register ImpUseSuperReg=Register())
Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908.
static unsigned getWWMRegSpillSaveOpcode(unsigned Size, bool IsVectorSuperClass)
static bool memOpsHaveSameBaseOperands(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getWWMRegSpillRestoreOpcode(unsigned Size, bool IsVectorSuperClass)
static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion, unsigned &NewDefOpc)
static bool isSCCDeadOnExit(MachineBasicBlock *MBB)
static bool getFoldableImm(Register Reg, const MachineRegisterInfo &MRI, int64_t &Imm, MachineInstr **DefMI=nullptr)
static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize)
static unsigned subtargetEncodingFamily(const GCNSubtarget &ST)
static void preserveCondRegFlags(MachineOperand &CondReg, const MachineOperand &OrigCond)
static Register findImplicitSGPRRead(const MachineInstr &MI)
static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc)
static cl::opt< unsigned > BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16), cl::desc("Restrict range of branch instructions (DEBUG)"))
static void updateLiveVariables(LiveVariables *LV, MachineInstr &MI, MachineInstr &NewMI)
static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getSGPRSpillRestoreOpcode(unsigned Size)
static bool isRegOrFI(const MachineOperand &MO)
static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static constexpr AMDGPU::OpName ModifierOpNames[]
static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const char *Msg="illegal VGPR to SGPR copy")
static MachineInstr * swapRegAndNonRegOperand(MachineInstr &MI, MachineOperand &RegOp, MachineOperand &NonRegOp)
static bool shouldReadExec(const MachineInstr &MI)
static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc)
static bool isRenamedInGFX9(int Opcode)
static TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd)
static std::tuple< unsigned, unsigned, unsigned > splitGlobalAddressRelocFlags(const GCNSubtarget &ST, const MachineOperand &SrcOp)
static bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
static bool foldableSelect(const MachineInstr &Def)
static bool nodesHaveSameOperandValue(SDNode *N0, SDNode *N1, AMDGPU::OpName OpName)
Returns true if both nodes have the same value for the given operand Op, or if both nodes do not have...
static unsigned getNumOperandsNoGlue(SDNode *Node)
static bool canRemat(const MachineInstr &MI)
static unsigned getAVSpillRestoreOpcode(unsigned Size)
static void emitLoadScalarOpsFromVGPRLoop(const SIInstrInfo &TII, MachineRegisterInfo &MRI, MachineBasicBlock &PredBB, MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={})
static unsigned getVGPRSpillRestoreOpcode(unsigned Size)
Interface definition for SIInstrInfo.
bool IsDead
const char * Msg
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
#define LLVM_DEBUG(...)
Definition Debug.h:119
static const LaneMaskConstants & get(const GCNSubtarget &ST)
static LLVM_ABI Semantics SemanticsToEnum(const llvm::fltSemantics &Sem)
Definition APFloat.cpp:170
Class for arbitrary precision integers.
Definition APInt.h:78
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1587
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A debug info location.
Definition DebugLoc.h:126
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:299
Diagnostic information for unsupported feature in backend.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:272
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:353
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
CycleRef getParentCycle(CycleRef C) const
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
Itinerary data supplied by a subtarget to be used by a target.
constexpr unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LiveInterval - This class represents the liveness of a register, or stack slot.
bool hasInterval(Register Reg) const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
LLVM_ABI bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
This class represents the liveness of a register, stack slot, etc.
LLVM_ABI void replaceKillInstruction(Register Reg, MachineInstr &OldMI, MachineInstr &NewMI)
replaceKillInstruction - Update register kill info by replacing a kill instruction with a new one.
LLVM_ABI VarInfo & getVarInfo(Register Reg)
getVarInfo - Return the VarInfo structure for the specified VIRTUAL register.
bool hasValue() const
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:347
static const MCBinaryExpr * createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:417
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
unsigned getOpcode() const
Return the opcode number for this descriptor.
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition MCInstrDesc.h:86
uint8_t OperandType
Information about the type of the operand.
Definition MCInstrDesc.h:98
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
Definition MCInstrDesc.h:92
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void setVariableValue(const MCExpr *Value)
Definition MCSymbol.cpp:50
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
MIRFormater - Interface to format MIR operand based on target.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
void push_back(MachineInstr *MI)
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
bool isCopy() const
const MachineBasicBlock * getParent() const
LLVM_ABI void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
bool isBundle() const
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromBundle()
Unlink 'this' from its basic block and delete it.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mop_range explicit_operands()
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just after the instruction itself.
LLVM_ABI void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo)
Clear all kill flags affecting Reg.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
A description of a memory reference used in the backend.
unsigned getAddrSpace() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
const GlobalValue * getGlobal() const
LLVM_ABI void ChangeToFrameIndex(int Idx, unsigned TargetFlags=0)
Replace this operand with a frame index.
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
LLVM_ABI void ChangeToGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
ChangeToGA - Replace this operand with a new global address operand.
void setIsKill(bool Val=true)
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
void setOffset(int64_t Offset)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isTargetIndex() const
isTargetIndex - Tests if this is a MO_TargetIndex operand.
void setTargetFlags(unsigned F)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps)
Move NumOps operands from Src to Dst, updating use-def lists as needed.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
LLVM_ABI void clearVirtRegs()
clearVirtRegs - Remove all virtual registers (after physreg assignment).
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void removeRegOperandFromUseList(MachineOperand *MO)
Remove MO from its use-def list.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI void addRegOperandToUseList(MachineOperand *MO)
Add MO to the linked list of operands for its register.
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const final
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
bool isSpill(uint32_t Opcode) const
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool mayAccessFlatAddressSpace(const MachineInstr &MI) const
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
bool isLegalVSrcOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO would be a valid operand for the given operand definition OpInfo.
static bool isDOT(const MachineInstr &MI)
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
bool hasModifiers(unsigned Opcode) const
Return true if this instruction has any modifiers.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
static bool isSWMMAC(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
bool isWave32() const
bool isHighLatencyDef(int Opc) const override
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const
Legalize the OpIndex operand of this instruction by inserting a MOV.
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isVOPC(const MachineInstr &MI)
void removeModOperands(MachineInstr &MI) const
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool isXDL(const MachineInstr &MI) const
Register isStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
static bool isVIMAGE(const MachineInstr &MI)
void enforceOperandRCAlignment(MachineInstr &MI, AMDGPU::OpName OpName) const
static bool isSOP2(const MachineInstr &MI)
static bool isGWS(const MachineInstr &MI)
bool hasRAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI) const
bool isLegalAV64PseudoImm(uint64_t Imm) const
Check if this immediate value can be used for AV_MOV_B64_IMM_PSEUDO.
bool isNeverCoissue(MachineInstr &MI) const
static bool isBUF(const MachineInstr &MI)
void handleCopyToPhysHelper(SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst, MachineRegisterInfo &MRI, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
bool hasModifiersSet(const MachineInstr &MI, AMDGPU::OpName OpName) const
bool isLegalToSwap(const MachineInstr &MI, unsigned fromIdx, unsigned toIdx) const
static bool isFLATGlobal(const MachineInstr &MI)
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isGlobalMemoryObject(const MachineInstr *MI) const override
static bool isVSAMPLE(const MachineInstr &MI)
bool isBufferSMRD(const MachineInstr &MI) const
static bool isKillTerminator(unsigned Opcode)
bool isVOPDAntidependencyAllowed(const MachineInstr &MI) const
If OpX is multicycle, anti-dependencies are not allowed.
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
void insertScratchExecCopy(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, bool IsSCCLive, SlotIndexes *Indexes=nullptr) const
bool hasVALU32BitEncoding(unsigned Opcode) const
Return true if this 64-bit VALU instruction has a 32-bit encoding.
unsigned getMovOpcode(const TargetRegisterClass *DstRC) const
Register isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
unsigned buildExtractSubReg(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const
Legalize operands in MI by either commuting it or inserting a copy of src1.
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const final
static bool isTRANS(const MachineInstr &MI)
static bool isImage(const MachineInstr &MI)
static bool isSOPK(const MachineInstr &MI)
const TargetRegisterClass * getOpRegClass(const MachineInstr &MI, unsigned OpNo) const
Return the correct register class for OpNo.
MachineBasicBlock * insertSimulatedTrap(MachineRegisterInfo &MRI, MachineBasicBlock &MBB, MachineInstr &MI, const DebugLoc &DL) const
Build instructions that simulate the behavior of a s_trap 2 instructions for hardware (namely,...
static unsigned getNonSoftWaitcntOpcode(unsigned Opcode)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static bool isFoldableCopy(const MachineInstr &MI)
bool isIgnorableUse(const MachineOperand &MO) const override
static bool isMUBUF(const MachineInstr &MI)
bool expandPostRAPseudo(MachineInstr &MI) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
void createWaterFallForSiCall(MachineInstr *MI, MachineDominatorTree *MDT, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={}) const
Wrapper function for generating waterfall for instruction MI This function take into consideration of...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSegmentSpecificFLAT(const MachineInstr &MI)
bool isReMaterializableImpl(const MachineInstr &MI) const override
static bool isVOP3(const MCInstrDesc &Desc)
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool physRegUsesConstantBus(const MachineOperand &Reg) const
static bool isF16PseudoScalarTrans(unsigned Opcode)
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
bool mayAccessVMEMThroughFlat(const MachineInstr &MI) const
static bool isDPP(const MachineInstr &MI)
bool analyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
static bool isMFMA(const MachineInstr &MI)
bool isLowLatencyInstruction(const MachineInstr &MI) const
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is a instruction that moves/copies value from one register to ano...
void mutateAndCleanupImplicit(MachineInstr &MI, const MCInstrDesc &NewDesc) const
ValueUniformity getGenericValueUniformity(const MachineInstr &MI) const
static bool isMAI(const MCInstrDesc &Desc)
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const override
static bool usesLGKM_CNT(const MachineInstr &MI)
void legalizeOperandsVALUt16(MachineInstr &Inst, MachineRegisterInfo &MRI) const
Fix operands in Inst to fix 16bit SALU to VALU lowering.
bool isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo, const MachineOperand &MO) const
bool canShrink(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
const MachineOperand & getCalleeOperand(const MachineInstr &MI) const override
bool isAsmOnlyOpcode(int MCOp) const
Check if this instruction should only be used by assembler.
bool isAlwaysGDS(uint32_t Opcode) const
static bool isVGPRSpill(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
This is used by the post-RA scheduler (SchedulePostRAList.cpp).
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
unsigned getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr &MI, unsigned *PredCost=nullptr) const override
bool isLegalGFX12PlusPackedMathFP32or64BitOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for gfx12+ packed math FP32 or 64 instructions.
unsigned getVectorRegSpillSaveOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI, bool NeedsCFI) const
int64_t getNamedImmOperand(const MachineInstr &MI, AMDGPU::OpName OperandName) const
Get required immediate operand.
ArrayRef< std::pair< int, const char * > > getSerializableTargetIndices() const override
bool regUsesConstantBus(const MachineOperand &Reg, const MachineRegisterInfo &MRI) const
static bool isMIMG(const MachineInstr &MI)
MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isLegalRegOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO (a register operand) is a legal register for the given operand description or operand ind...
static unsigned getNumWaitStates(const MachineInstr &MI)
Return the number of wait states that result from executing this instruction.
unsigned getVALUOp(const MachineInstr &MI) const
static bool modifiesModeRegister(const MachineInstr &MI)
Return true if the instruction modifies the mode register.q.
Register readlaneVGPRToSGPR(Register SrcReg, MachineInstr &UseMI, MachineRegisterInfo &MRI, const TargetRegisterClass *DstRC=nullptr) const
Copy a value from a VGPR (SrcReg) to SGPR.
bool hasDivergentBranch(const MachineBasicBlock *MBB) const
Return whether the block terminate with divergent branch.
std::pair< int64_t, int64_t > splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Split COffsetVal into {immediate offset field, remainder offset} values.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void fixImplicitOperands(MachineInstr &MI) const
bool moveFlatAddrToVGPR(MachineInstr &Inst) const
Change SADDR form of a FLAT Inst to its VADDR form if saddr operand was moved to VGPR.
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
void createReadFirstLaneFromCopyToPhysReg(MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const
bool swapSourceModifiers(MachineInstr &MI, MachineOperand &Src0, AMDGPU::OpName Src0OpName, MachineOperand &Src1, AMDGPU::OpName Src1OpName) const
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const
This function is used to determine if an instruction can be safely executed under EXEC = 0 without ha...
bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg, int64_t &ImmVal) const override
static bool isAtomic(const MachineInstr &MI)
bool canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, int &CondCycles, int &TrueCycles, int &FalseCycles) const override
bool isLiteralOperandLegal(const MCInstrDesc &InstDesc, const MCOperandInfo &OpInfo) const
static bool isWWMRegSpillOpcode(uint32_t Opcode)
static bool sopkIsZext(unsigned Opcode)
static bool isSGPRSpill(const MachineInstr &MI)
static bool isWMMA(const MachineInstr &MI)
ArrayRef< std::pair< MachineMemOperand::Flags, const char * > > getSerializableMachineMemOperandTargetFlags() const override
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, LiveIntervals *LIS) const override
bool mayReadEXEC(const MachineRegisterInfo &MRI, const MachineInstr &MI) const
Returns true if the instruction could potentially depend on the value of exec.
void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
std::pair< MachineInstr *, MachineInstr * > expandMovDPP64(MachineInstr &MI) const
static bool isSOPC(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
bool isBarrier(unsigned Opcode) const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx0, unsigned OpIdx1) const override
bool mayAccessLDSThroughFlat(const MachineInstr &MI, bool TgSplit) const
int pseudoToMCOpcode(int Opcode) const
Return a target-specific opcode if Opcode is a pseudo instruction.
const MCInstrDesc & getMCOpcodeFromPseudo(unsigned Opcode) const
Return the descriptor of the target-specific machine instruction that corresponds to the specified ps...
static bool usesVM_CNT(const MachineInstr &MI)
MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const override
static bool isFixedSize(const MachineInstr &MI)
bool isSafeToSink(MachineInstr &MI, MachineBasicBlock *SuccToSinkTo, MachineCycleInfo *CI) const override
LLVM_READONLY int commuteOpcode(unsigned Opc) const
ValueUniformity getValueUniformity(const MachineInstr &MI) const final
uint64_t getScratchRsrcWords23() const
LLVM_READONLY MachineOperand * getNamedOperand(MachineInstr &MI, AMDGPU::OpName OperandName) const
Returns the operand named Op.
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx, const MachineOperand *MO=nullptr) const
Check if MO is a legal operand if it was the OpIdx Operand for MI.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool allowNegativeFlatOffset(AMDGPU::FlatAddrSpace FlatVariant) const
Returns true if negative offsets are allowed for the given FlatVariant.
std::optional< int64_t > getImmOrMaterializedImm(MachineOperand &Op) const
void moveToVALUImpl(SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
static bool isLDSDMA(const MachineInstr &MI)
static bool isVOP1(const MachineInstr &MI)
SIInstrInfo(const GCNSubtarget &ST)
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool hasAnyModifiersSet(const MachineInstr &MI) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
void setHasSpilledVGPRs(bool Spill=true)
bool isWWMReg(Register Reg) const
bool checkFlag(Register Reg, uint8_t Flag) const
void setHasSpilledSGPRs(bool Spill=true)
unsigned getScratchReservedForDynamicVGPRs() const
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:66
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndexes pass.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:293
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
int64_t getImm() const
Register getReg() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual bool isReMaterializableImpl(const MachineInstr &MI) const
For instructions with opcodes for which the M_REMATERIALIZABLE flag is set, this hook lets the target...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:187
self_iterator getIterator()
Definition ilist_node.h:123
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
bool isPackedFP32or64BitInst(unsigned Opc)
@ OPERAND_REG_IMM_V2FP64
Definition SIDefines.h:439
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:457
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:425
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:432
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:448
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:445
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:450
@ OPERAND_REG_IMM_V2INT64
Definition SIDefines.h:435
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:434
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:429
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:424
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:431
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:430
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:433
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:444
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:442
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:436
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:428
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:451
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:462
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:463
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:437
@ OPERAND_SDWA_VOPC_DST
Definition SIDefines.h:474
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:427
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:447
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:443
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:449
@ OPERAND_INLINE_C_AV64_PSEUDO
Definition SIDefines.h:468
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:438
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:464
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:446
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:426
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:454
LLVM_READONLY int32_t getBasicFromSDWAOp(uint32_t Opcode)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
@ TI_SCRATCH_RSRC_DWORD1
Definition AMDGPU.h:612
@ TI_SCRATCH_RSRC_DWORD3
Definition AMDGPU.h:614
@ TI_SCRATCH_RSRC_DWORD0
Definition AMDGPU.h:611
@ TI_SCRATCH_RSRC_DWORD2
Definition AMDGPU.h:613
@ TI_CONSTDATA_START
Definition AMDGPU.h:610
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
const uint64_t RSRC_INDEX_STRIDE_SHIFT
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
bool isPacked64BitInst(unsigned Opc)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition CallingConv.h:41
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ OPERAND_GENERIC_4
Definition MCInstrDesc.h:71
@ OPERAND_GENERIC_2
Definition MCInstrDesc.h:69
@ OPERAND_GENERIC_1
Definition MCInstrDesc.h:68
@ OPERAND_GENERIC_3
Definition MCInstrDesc.h:70
@ OPERAND_IMMEDIATE
Definition MCInstrDesc.h:61
@ OPERAND_GENERIC_0
Definition MCInstrDesc.h:67
@ OPERAND_GENERIC_5
Definition MCInstrDesc.h:72
Not(const Pred &P) -> Not< Pred >
constexpr bool isD16Buf(const T &...O)
Definition SIDefines.h:336
constexpr bool isSDWA(const T &...O)
Definition SIDefines.h:246
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
Definition Threading.h:280
@ Offset
Definition DWP.cpp:578
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
constexpr uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
Definition MathExtras.h:208
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:547
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
Op::Description Desc
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg)
Return the SubReg component from REG_SEQUENCE.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
Definition SIInstrInfo.h:46
constexpr bool has_single_bit(T Value) noexcept
Definition bit.h:149
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
MachineInstr * getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, const MachineRegisterInfo &MRI)
Return the defining instruction for a given reg:subreg pair skipping copy like instructions and subre...
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI VirtRegInfo AnalyzeVirtRegInBundle(MachineInstr &MI, Register Reg, SmallVectorImpl< std::pair< MachineInstr *, unsigned > > *Ops=nullptr)
AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses a virtual register.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
Definition SIInstrInfo.h:54
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:395
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
Definition SIInstrInfo.h:42
constexpr unsigned BitWidth
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition SIInstrInfo.h:50
constexpr T reverseBits(T Val)
Reverse the bits in Val.
Definition MathExtras.h:119
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:573
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
constexpr RegState getUndefRegState(bool B)
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
Definition Uniformity.h:18
@ AlwaysUniform
The result value is always uniform.
Definition Uniformity.h:23
@ NeverUniform
The result value can never be assumed to be uniform.
Definition Uniformity.h:26
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
Definition SIInstrInfo.h:65
bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI)
Return false if EXEC is not changed between the def of VReg at DefMI and all its uses.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
constexpr bool all() const
Definition LaneBitmask.h:54
SparseBitVector AliveBlocks
AliveBlocks - Set of blocks in which this value is alive completely through.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Utility to store machine instructions worklist.
Definition SIInstrInfo.h:69
MachineInstr * top() const
Definition SIInstrInfo.h:74
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
Definition SIInstrInfo.h:92
void insert(MachineInstr *MI)
A pair composed of a register and a sub-register index.
VirtRegInfo - Information about a virtual register used by a set of operands.
bool Reads
Reads - One of the operands read the virtual register.
bool Writes
Writes - One of the operands writes the virtual register.