LLVM 23.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
39using namespace llvm;
40
41#define DEBUG_TYPE "si-instr-info"
42
43#define GET_INSTRINFO_CTOR_DTOR
44#include "AMDGPUGenInstrInfo.inc"
45
46namespace llvm::AMDGPU {
47#define GET_D16ImageDimIntrinsics_IMPL
48#define GET_ImageDimIntrinsicTable_IMPL
49#define GET_RsrcIntrinsics_IMPL
50#include "AMDGPUGenSearchableTables.inc"
51} // namespace llvm::AMDGPU
52
53// Must be at least 4 to be able to branch over minimum unconditional branch
54// code. This is only for making it possible to write reasonably small tests for
55// long branches.
57BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16),
58 cl::desc("Restrict range of branch instructions (DEBUG)"));
59
61 "amdgpu-fix-16-bit-physreg-copies",
62 cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"),
63 cl::init(true),
65
67 : AMDGPUGenInstrInfo(ST, RI, AMDGPU::ADJCALLSTACKUP,
68 AMDGPU::ADJCALLSTACKDOWN),
69 RI(ST), ST(ST) {
70 SchedModel.init(&ST);
71}
72
73//===----------------------------------------------------------------------===//
74// TargetInstrInfo callbacks
75//===----------------------------------------------------------------------===//
76
77static unsigned getNumOperandsNoGlue(SDNode *Node) {
78 unsigned N = Node->getNumOperands();
79 while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
80 --N;
81 return N;
82}
83
84/// Returns true if both nodes have the same value for the given
85/// operand \p Op, or if both nodes do not have this operand.
87 AMDGPU::OpName OpName) {
88 unsigned Opc0 = N0->getMachineOpcode();
89 unsigned Opc1 = N1->getMachineOpcode();
90
91 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName);
92 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName);
93
94 if (Op0Idx == -1 && Op1Idx == -1)
95 return true;
96
97
98 if ((Op0Idx == -1 && Op1Idx != -1) ||
99 (Op1Idx == -1 && Op0Idx != -1))
100 return false;
101
102 // getNamedOperandIdx returns the index for the MachineInstr's operands,
103 // which includes the result as the first operand. We are indexing into the
104 // MachineSDNode's operands, so we need to skip the result operand to get
105 // the real index.
106 --Op0Idx;
107 --Op1Idx;
108
109 return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx);
110}
111
112static bool canRemat(const MachineInstr &MI) {
113
117 return true;
118
119 if (SIInstrInfo::isSMRD(MI)) {
120 return !MI.memoperands_empty() &&
121 llvm::all_of(MI.memoperands(), [](const MachineMemOperand *MMO) {
122 return MMO->isLoad() && MMO->isInvariant();
123 });
124 }
125
126 return false;
127}
128
130 const MachineInstr &MI) const {
131
132 if (canRemat(MI)) {
133 // Normally VALU use of exec would block the rematerialization, but that
134 // is OK in this case to have an implicit exec read as all VALU do.
135 // We really want all of the generic logic for this except for this.
136
137 // Another potential implicit use is mode register. The core logic of
138 // the RA will not attempt rematerialization if mode is set anywhere
139 // in the function, otherwise it is safe since mode is not changed.
140
141 // There is difference to generic method which does not allow
142 // rematerialization if there are virtual register uses. We allow this,
143 // therefore this method includes SOP instructions as well.
144 if (!MI.hasImplicitDef() &&
145 MI.getNumImplicitOperands() == MI.getDesc().implicit_uses().size() &&
146 !MI.mayRaiseFPException())
147 return true;
148 }
149
151}
152
153// Returns true if the result of a VALU instruction depends on exec.
154bool SIInstrInfo::resultDependsOnExec(const MachineInstr &MI) const {
155 assert(isVALU(MI, /*AllowLDSDMA=*/true));
156
157 // If it is convergent it depends on EXEC.
158 if (MI.isConvergent())
159 return true;
160
161 // If it defines SGPR it depends on EXEC
162 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
163 for (const MachineOperand &Def : MI.defs()) {
164 if (!Def.isReg())
165 continue;
166
167 Register Reg = Def.getReg();
168 if (Reg && RI.isSGPRReg(MRI, Reg))
169 return true;
170 }
171
172 return false;
173}
174
176 // Any implicit use of exec by VALU is not a real register read.
177 return MO.getReg() == AMDGPU::EXEC && MO.isImplicit() &&
178 isVALU(*MO.getParent(), /*AllowLDSDMA=*/true) &&
179 !resultDependsOnExec(*MO.getParent());
180}
181
183 MachineBasicBlock *SuccToSinkTo,
184 MachineCycleInfo *CI) const {
185 // Allow sinking if MI edits lane mask (divergent i1 in sgpr).
186 if (MI.getOpcode() == AMDGPU::SI_IF_BREAK)
187 return true;
188
189 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
190 // Check if sinking of MI would create temporal divergent use.
191 for (auto Op : MI.uses()) {
192 if (Op.isReg() && Op.getReg().isVirtual() &&
193 RI.isSGPRClass(MRI.getRegClass(Op.getReg()))) {
194 MachineInstr *SgprDef = MRI.getVRegDef(Op.getReg());
195
196 // SgprDef defined inside cycle
197 MachineCycle *FromCycle = CI->getCycle(SgprDef->getParent());
198 if (FromCycle == nullptr)
199 continue;
200
201 MachineCycle *ToCycle = CI->getCycle(SuccToSinkTo);
202 // Check if there is a FromCycle that contains SgprDef's basic block but
203 // does not contain SuccToSinkTo and also has divergent exit condition.
204 while (FromCycle && !FromCycle->contains(ToCycle)) {
206 FromCycle->getExitingBlocks(ExitingBlocks);
207
208 // FromCycle has divergent exit condition.
209 for (MachineBasicBlock *ExitingBlock : ExitingBlocks) {
210 if (hasDivergentBranch(ExitingBlock))
211 return false;
212 }
213
214 FromCycle = FromCycle->getParentCycle();
215 }
216 }
217 }
218
219 return true;
220}
221
223 int64_t &Offset0,
224 int64_t &Offset1) const {
225 if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode())
226 return false;
227
228 unsigned Opc0 = Load0->getMachineOpcode();
229 unsigned Opc1 = Load1->getMachineOpcode();
230
231 // Make sure both are actually loads.
232 if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad())
233 return false;
234
235 // A mayLoad instruction without a def is not a load. Likely a prefetch.
236 if (!get(Opc0).getNumDefs() || !get(Opc1).getNumDefs())
237 return false;
238
239 if (isDS(Opc0) && isDS(Opc1)) {
240
241 // FIXME: Handle this case:
242 if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1))
243 return false;
244
245 // Check base reg.
246 if (Load0->getOperand(0) != Load1->getOperand(0))
247 return false;
248
249 // Skip read2 / write2 variants for simplicity.
250 // TODO: We should report true if the used offsets are adjacent (excluded
251 // st64 versions).
252 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
253 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
254 if (Offset0Idx == -1 || Offset1Idx == -1)
255 return false;
256
257 // XXX - be careful of dataless loads
258 // getNamedOperandIdx returns the index for MachineInstrs. Since they
259 // include the output in the operand list, but SDNodes don't, we need to
260 // subtract the index by one.
261 Offset0Idx -= get(Opc0).NumDefs;
262 Offset1Idx -= get(Opc1).NumDefs;
263 Offset0 = Load0->getConstantOperandVal(Offset0Idx);
264 Offset1 = Load1->getConstantOperandVal(Offset1Idx);
265 return true;
266 }
267
268 if (isSMRD(Opc0) && isSMRD(Opc1)) {
269 // Skip time and cache invalidation instructions.
270 if (!AMDGPU::hasNamedOperand(Opc0, AMDGPU::OpName::sbase) ||
271 !AMDGPU::hasNamedOperand(Opc1, AMDGPU::OpName::sbase))
272 return false;
273
274 unsigned NumOps = getNumOperandsNoGlue(Load0);
275 if (NumOps != getNumOperandsNoGlue(Load1))
276 return false;
277
278 // Check base reg.
279 if (Load0->getOperand(0) != Load1->getOperand(0))
280 return false;
281
282 // Match register offsets, if both register and immediate offsets present.
283 assert(NumOps == 4 || NumOps == 5);
284 if (NumOps == 5 && Load0->getOperand(1) != Load1->getOperand(1))
285 return false;
286
287 const ConstantSDNode *Load0Offset =
289 const ConstantSDNode *Load1Offset =
291
292 if (!Load0Offset || !Load1Offset)
293 return false;
294
295 Offset0 = Load0Offset->getZExtValue();
296 Offset1 = Load1Offset->getZExtValue();
297 return true;
298 }
299
300 // MUBUF and MTBUF can access the same addresses.
301 if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) {
302
303 // MUBUF and MTBUF have vaddr at different indices.
304 if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) ||
305 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) ||
306 !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc))
307 return false;
308
309 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
310 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
311
312 if (OffIdx0 == -1 || OffIdx1 == -1)
313 return false;
314
315 // getNamedOperandIdx returns the index for MachineInstrs. Since they
316 // include the output in the operand list, but SDNodes don't, we need to
317 // subtract the index by one.
318 OffIdx0 -= get(Opc0).NumDefs;
319 OffIdx1 -= get(Opc1).NumDefs;
320
321 SDValue Off0 = Load0->getOperand(OffIdx0);
322 SDValue Off1 = Load1->getOperand(OffIdx1);
323
324 // The offset might be a FrameIndexSDNode.
325 if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1))
326 return false;
327
328 Offset0 = Off0->getAsZExtVal();
329 Offset1 = Off1->getAsZExtVal();
330 return true;
331 }
332
333 return false;
334}
335
336static bool isStride64(unsigned Opc) {
337 switch (Opc) {
338 case AMDGPU::DS_READ2ST64_B32:
339 case AMDGPU::DS_READ2ST64_B64:
340 case AMDGPU::DS_WRITE2ST64_B32:
341 case AMDGPU::DS_WRITE2ST64_B64:
342 return true;
343 default:
344 return false;
345 }
346}
347
350 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
351 const TargetRegisterInfo *TRI) const {
352 if (!LdSt.mayLoadOrStore())
353 return false;
354
355 unsigned Opc = LdSt.getOpcode();
356 OffsetIsScalable = false;
357 const MachineOperand *BaseOp, *OffsetOp;
358 int DataOpIdx;
359
360 if (isDS(LdSt)) {
361 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr);
362 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
363 if (OffsetOp) {
364 // Normal, single offset LDS instruction.
365 if (!BaseOp) {
366 // DS_CONSUME/DS_APPEND use M0 for the base address.
367 // TODO: find the implicit use operand for M0 and use that as BaseOp?
368 return false;
369 }
370 BaseOps.push_back(BaseOp);
371 Offset = OffsetOp->getImm();
372 // Get appropriate operand, and compute width accordingly.
373 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
374 if (DataOpIdx == -1)
375 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
376 if (Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
377 Width = LocationSize::precise(64);
378 else
379 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
380 } else {
381 // The 2 offset instructions use offset0 and offset1 instead. We can treat
382 // these as a load with a single offset if the 2 offsets are consecutive.
383 // We will use this for some partially aligned loads.
384 const MachineOperand *Offset0Op =
385 getNamedOperand(LdSt, AMDGPU::OpName::offset0);
386 const MachineOperand *Offset1Op =
387 getNamedOperand(LdSt, AMDGPU::OpName::offset1);
388
389 unsigned Offset0 = Offset0Op->getImm() & 0xff;
390 unsigned Offset1 = Offset1Op->getImm() & 0xff;
391 if (Offset0 + 1 != Offset1)
392 return false;
393
394 // Each of these offsets is in element sized units, so we need to convert
395 // to bytes of the individual reads.
396
397 unsigned EltSize;
398 if (LdSt.mayLoad())
399 EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16;
400 else {
401 assert(LdSt.mayStore());
402 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
403 EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8;
404 }
405
406 if (isStride64(Opc))
407 EltSize *= 64;
408
409 BaseOps.push_back(BaseOp);
410 Offset = EltSize * Offset0;
411 // Get appropriate operand(s), and compute width accordingly.
412 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
413 if (DataOpIdx == -1) {
414 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
415 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
416 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
417 Width = LocationSize::precise(
418 Width.getValue() + TypeSize::getFixed(getOpSize(LdSt, DataOpIdx)));
419 } else {
420 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
421 }
422 }
423 return true;
424 }
425
426 if (isMUBUF(LdSt) || isMTBUF(LdSt)) {
427 const MachineOperand *RSrc = getNamedOperand(LdSt, AMDGPU::OpName::srsrc);
428 if (!RSrc) // e.g. BUFFER_WBINVL1_VOL
429 return false;
430 BaseOps.push_back(RSrc);
431 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
432 if (BaseOp && !BaseOp->isFI())
433 BaseOps.push_back(BaseOp);
434 const MachineOperand *OffsetImm =
435 getNamedOperand(LdSt, AMDGPU::OpName::offset);
436 Offset = OffsetImm->getImm();
437 const MachineOperand *SOffset =
438 getNamedOperand(LdSt, AMDGPU::OpName::soffset);
439 if (SOffset) {
440 if (SOffset->isReg())
441 BaseOps.push_back(SOffset);
442 else
443 Offset += SOffset->getImm();
444 }
445 // Get appropriate operand, and compute width accordingly.
446 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
447 if (DataOpIdx == -1)
448 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
449 if (DataOpIdx == -1) // LDS DMA
450 return false;
451 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
452 return true;
453 }
454
455 if (isImage(LdSt)) {
456 auto RsrcOpName =
457 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
458 int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RsrcOpName);
459 BaseOps.push_back(&LdSt.getOperand(SRsrcIdx));
460 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
461 if (VAddr0Idx >= 0) {
462 // GFX10 possible NSA encoding.
463 for (int I = VAddr0Idx; I < SRsrcIdx; ++I)
464 BaseOps.push_back(&LdSt.getOperand(I));
465 } else {
466 BaseOps.push_back(getNamedOperand(LdSt, AMDGPU::OpName::vaddr));
467 }
468 Offset = 0;
469 // Get appropriate operand, and compute width accordingly.
470 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
471 if (DataOpIdx == -1)
472 return false; // no return sampler
473 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
474 return true;
475 }
476
477 if (isSMRD(LdSt)) {
478 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::sbase);
479 if (!BaseOp) // e.g. S_MEMTIME
480 return false;
481 BaseOps.push_back(BaseOp);
482 OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
483 Offset = OffsetOp ? OffsetOp->getImm() : 0;
484 // Get appropriate operand, and compute width accordingly.
485 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
486 if (DataOpIdx == -1)
487 return false;
488 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
489 return true;
490 }
491
492 if (isFLAT(LdSt)) {
493 // Instructions have either vaddr or saddr or both or none.
494 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
495 if (BaseOp)
496 BaseOps.push_back(BaseOp);
497 BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr);
498 if (BaseOp)
499 BaseOps.push_back(BaseOp);
500 Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm();
501 // Get appropriate operand, and compute width accordingly.
502 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
503 if (DataOpIdx == -1)
504 DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
505 if (DataOpIdx == -1) // LDS DMA
506 return false;
507 Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
508 return true;
509 }
510
511 return false;
512}
513
514static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
516 const MachineInstr &MI2,
518 // Only examine the first "base" operand of each instruction, on the
519 // assumption that it represents the real base address of the memory access.
520 // Other operands are typically offsets or indices from this base address.
521 if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
522 return true;
523
524 if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
525 return false;
526
527 auto *MO1 = *MI1.memoperands_begin();
528 auto *MO2 = *MI2.memoperands_begin();
529 if (MO1->getAddrSpace() != MO2->getAddrSpace())
530 return false;
531
532 const auto *Base1 = MO1->getValue();
533 const auto *Base2 = MO2->getValue();
534 if (!Base1 || !Base2)
535 return false;
536 Base1 = getUnderlyingObject(Base1);
537 Base2 = getUnderlyingObject(Base2);
538
539 if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
540 return false;
541
542 return Base1 == Base2;
543}
544
546 int64_t Offset1, bool OffsetIsScalable1,
548 int64_t Offset2, bool OffsetIsScalable2,
549 unsigned ClusterSize,
550 unsigned NumBytes) const {
551 // If the mem ops (to be clustered) do not have the same base ptr, then they
552 // should not be clustered
553 unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;
554 if (!BaseOps1.empty() && !BaseOps2.empty()) {
555 const MachineInstr &FirstLdSt = *BaseOps1.front()->getParent();
556 const MachineInstr &SecondLdSt = *BaseOps2.front()->getParent();
557 if (!memOpsHaveSameBasePtr(FirstLdSt, BaseOps1, SecondLdSt, BaseOps2))
558 return false;
559
560 const SIMachineFunctionInfo *MFI =
561 FirstLdSt.getMF()->getInfo<SIMachineFunctionInfo>();
562 MaxMemoryClusterDWords = MFI->getMaxMemoryClusterDWords();
563 } else if (!BaseOps1.empty() || !BaseOps2.empty()) {
564 // If only one base op is empty, they do not have the same base ptr
565 return false;
566 }
567
568 // In order to avoid register pressure, on an average, the number of DWORDS
569 // loaded together by all clustered mem ops should not exceed
570 // MaxMemoryClusterDWords. This is an empirical value based on certain
571 // observations and performance related experiments.
572 // The good thing about this heuristic is - it avoids clustering of too many
573 // sub-word loads, and also avoids clustering of wide loads. Below is the
574 // brief summary of how the heuristic behaves for various `LoadSize` when
575 // MaxMemoryClusterDWords is 8.
576 //
577 // (1) 1 <= LoadSize <= 4: cluster at max 8 mem ops
578 // (2) 5 <= LoadSize <= 8: cluster at max 4 mem ops
579 // (3) 9 <= LoadSize <= 12: cluster at max 2 mem ops
580 // (4) 13 <= LoadSize <= 16: cluster at max 2 mem ops
581 // (5) LoadSize >= 17: do not cluster
582 const unsigned LoadSize = NumBytes / ClusterSize;
583 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
584 return NumDWords <= MaxMemoryClusterDWords;
585}
586
587// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
588// the first 16 loads will be interleaved with the stores, and the next 16 will
589// be clustered as expected. It should really split into 2 16 store batches.
590//
591// Loads are clustered until this returns false, rather than trying to schedule
592// groups of stores. This also means we have to deal with saying different
593// address space loads should be clustered, and ones which might cause bank
594// conflicts.
595//
596// This might be deprecated so it might not be worth that much effort to fix.
598 int64_t Offset0, int64_t Offset1,
599 unsigned NumLoads) const {
600 assert(Offset1 > Offset0 &&
601 "Second offset should be larger than first offset!");
602 // If we have less than 16 loads in a row, and the offsets are within 64
603 // bytes, then schedule together.
604
605 // A cacheline is 64 bytes (for global memory).
606 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
607}
608
611 const DebugLoc &DL, MCRegister DestReg,
612 MCRegister SrcReg, bool KillSrc,
613 const char *Msg = "illegal VGPR to SGPR copy") {
614 MachineFunction *MF = MBB.getParent();
615
618
619 BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg)
620 .addReg(SrcReg, getKillRegState(KillSrc));
621}
622
623/// Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908. It is not
624/// possible to have a direct copy in these cases on GFX908, so an intermediate
625/// VGPR copy is required.
628 const DebugLoc &DL, MCRegister DestReg,
629 MCRegister SrcReg, bool KillSrc,
630 RegScavenger &RS, bool RegsOverlap,
631 Register ImpUseSuperReg = Register()) {
632 assert((TII.getSubtarget().hasMAIInsts() &&
633 !TII.getSubtarget().hasGFX90AInsts()) &&
634 "Expected GFX908 subtarget.");
635
636 assert((AMDGPU::SReg_32RegClass.contains(SrcReg) ||
637 AMDGPU::AGPR_32RegClass.contains(SrcReg)) &&
638 "Source register of the copy should be either an SGPR or an AGPR.");
639
640 assert(AMDGPU::AGPR_32RegClass.contains(DestReg) &&
641 "Destination register of the copy should be an AGPR.");
642
643 const SIRegisterInfo &RI = TII.getRegisterInfo();
644
645 // First try to find defining accvgpr_write to avoid temporary registers.
646 // In the case of copies of overlapping AGPRs, we conservatively do not
647 // reuse previous accvgpr_writes. Otherwise, we may incorrectly pick up
648 // an accvgpr_write used for this same copy due to implicit-defs
649 if (!RegsOverlap) {
650 for (auto Def = MI, E = MBB.begin(); Def != E; ) {
651 --Def;
652
653 if (!Def->modifiesRegister(SrcReg, &RI))
654 continue;
655
656 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
657 Def->getOperand(0).getReg() != SrcReg)
658 break;
659
660 MachineOperand &DefOp = Def->getOperand(1);
661 assert(DefOp.isReg() || DefOp.isImm());
662
663 if (DefOp.isReg()) {
664 bool SafeToPropagate = true;
665 // Check that register source operand is not clobbered before MI.
666 // Immediate operands are always safe to propagate.
667 for (auto I = Def; I != MI && SafeToPropagate; ++I)
668 if (I->modifiesRegister(DefOp.getReg(), &RI))
669 SafeToPropagate = false;
670
671 if (!SafeToPropagate)
672 break;
673
674 for (auto I = Def; I != MI; ++I)
675 I->clearRegisterKills(DefOp.getReg(), &RI);
676 }
677
678 MachineInstrBuilder Builder =
679 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64),
680 DestReg)
681 .add(DefOp);
682
683 if (ImpUseSuperReg) {
684 Builder.addReg(ImpUseSuperReg,
686 }
687
688 return;
689 }
690 }
691
692 RS.enterBasicBlockEnd(MBB);
693 RS.backward(std::next(MI));
694
695 // Ideally we want to have three registers for a long reg_sequence copy
696 // to hide 2 waitstates between v_mov_b32 and accvgpr_write.
697 unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass,
698 *MBB.getParent());
699
700 // Registers in the sequence are allocated contiguously so we can just
701 // use register number to pick one of three round-robin temps.
702 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
703 Register Tmp =
704 MBB.getParent()->getInfo<SIMachineFunctionInfo>()->getVGPRForAGPRCopy();
705 assert(MBB.getParent()->getRegInfo().isReserved(Tmp) &&
706 "VGPR used for an intermediate copy should have been reserved.");
707
708 // Only loop through if there are any free registers left. We don't want to
709 // spill.
710 while (RegNo--) {
711 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI,
712 /* RestoreAfter */ false, 0,
713 /* AllowSpill */ false);
714 if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs)
715 break;
716 Tmp = Tmp2;
717 RS.setRegUsed(Tmp);
718 }
719
720 // Insert copy to temporary VGPR.
721 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
722 if (AMDGPU::AGPR_32RegClass.contains(SrcReg)) {
723 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
724 } else {
725 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
726 }
727
728 MachineInstrBuilder UseBuilder = BuildMI(MBB, MI, DL, TII.get(TmpCopyOp), Tmp)
729 .addReg(SrcReg, getKillRegState(KillSrc));
730 if (ImpUseSuperReg) {
731 UseBuilder.addReg(ImpUseSuperReg,
733 }
734
735 BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
736 .addReg(Tmp, RegState::Kill);
737}
738
741 MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
742 const TargetRegisterClass *RC, bool Forward) {
743 const SIRegisterInfo &RI = TII.getRegisterInfo();
744 ArrayRef<int16_t> BaseIndices = RI.getRegSplitParts(RC, 4);
746 MachineInstr *FirstMI = nullptr, *LastMI = nullptr;
747
748 for (unsigned Idx = 0; Idx < BaseIndices.size(); ++Idx) {
749 int16_t SubIdx = BaseIndices[Idx];
750 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
751 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
752 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
753 unsigned Opcode = AMDGPU::S_MOV_B32;
754
755 // Is SGPR aligned? If so try to combine with next.
756 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
757 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
758 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.size())) {
759 // Can use SGPR64 copy
760 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
761 SubIdx = RI.getSubRegFromChannel(Channel, 2);
762 DestSubReg = RI.getSubReg(DestReg, SubIdx);
763 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
764 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
765 Opcode = AMDGPU::S_MOV_B64;
766 Idx++;
767 }
768
769 LastMI = BuildMI(MBB, I, DL, TII.get(Opcode), DestSubReg)
770 .addReg(SrcSubReg)
771 .addReg(SrcReg, RegState::Implicit);
772
773 if (!FirstMI)
774 FirstMI = LastMI;
775
776 if (!Forward)
777 I--;
778 }
779
780 assert(FirstMI && LastMI);
781 if (!Forward)
782 std::swap(FirstMI, LastMI);
783
784 if (KillSrc)
785 LastMI->addRegisterKilled(SrcReg, &RI);
786}
787
790 const DebugLoc &DL, Register DestReg,
791 Register SrcReg, bool KillSrc, bool RenamableDest,
792 bool RenamableSrc) const {
793 const TargetRegisterClass *RC = RI.getPhysRegBaseClass(DestReg);
794 unsigned Size = RI.getRegSizeInBits(*RC);
795 const TargetRegisterClass *SrcRC = RI.getPhysRegBaseClass(SrcReg);
796 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
797
798 // The rest of copyPhysReg assumes Src and Dst size are the same size.
799 // TODO-GFX11_16BIT If all true 16 bit instruction patterns are completed can
800 // we remove Fix16BitCopies and this code block?
801 if (Fix16BitCopies) {
802 if (((Size == 16) != (SrcSize == 16))) {
803 // Non-VGPR Src and Dst will later be expanded back to 32 bits.
804 assert(ST.useRealTrue16Insts());
805 Register &RegToFix = (Size == 32) ? DestReg : SrcReg;
806 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
807 RegToFix = SubReg;
808
809 if (DestReg == SrcReg) {
810 // Identity copy. Insert empty bundle since ExpandPostRA expects an
811 // instruction here.
812 BuildMI(MBB, MI, DL, get(AMDGPU::BUNDLE));
813 return;
814 }
815 RC = RI.getPhysRegBaseClass(DestReg);
816 Size = RI.getRegSizeInBits(*RC);
817 SrcRC = RI.getPhysRegBaseClass(SrcReg);
818 SrcSize = RI.getRegSizeInBits(*SrcRC);
819 }
820 }
821
822 if (RC == &AMDGPU::VGPR_32RegClass) {
823 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
824 AMDGPU::SReg_32RegClass.contains(SrcReg) ||
825 AMDGPU::AGPR_32RegClass.contains(SrcReg));
826 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
827 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
828 BuildMI(MBB, MI, DL, get(Opc), DestReg)
829 .addReg(SrcReg, getKillRegState(KillSrc));
830 return;
831 }
832
833 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
834 RC == &AMDGPU::SReg_32RegClass) {
835 if (SrcReg == AMDGPU::SCC) {
836 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg)
837 .addImm(1)
838 .addImm(0);
839 return;
840 }
841
842 if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) {
843 if (DestReg == AMDGPU::VCC_LO) {
844 // FIXME: Hack until VReg_1 removed.
845 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
846 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
847 .addImm(0)
848 .addReg(SrcReg, getKillRegState(KillSrc));
849 return;
850 }
851
852 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
853 return;
854 }
855
856 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
857 .addReg(SrcReg, getKillRegState(KillSrc));
858 return;
859 }
860
861 if (RC == &AMDGPU::SReg_64RegClass) {
862 if (SrcReg == AMDGPU::SCC) {
863 BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B64), DestReg)
864 .addImm(1)
865 .addImm(0);
866 return;
867 }
868
869 if (!AMDGPU::SReg_64_EncodableRegClass.contains(SrcReg)) {
870 if (DestReg == AMDGPU::VCC) {
871 // FIXME: Hack until VReg_1 removed.
872 assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
873 BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
874 .addImm(0)
875 .addReg(SrcReg, getKillRegState(KillSrc));
876 return;
877 }
878
879 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
880 return;
881 }
882
883 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
884 .addReg(SrcReg, getKillRegState(KillSrc));
885 return;
886 }
887
888 if (DestReg == AMDGPU::SCC) {
889 // Copying 64-bit or 32-bit sources to SCC barely makes sense,
890 // but SelectionDAG emits such copies for i1 sources.
891 if (AMDGPU::SReg_64RegClass.contains(SrcReg)) {
892 // This copy can only be produced by patterns
893 // with explicit SCC, which are known to be enabled
894 // only for subtargets with S_CMP_LG_U64 present.
895 assert(ST.hasScalarCompareEq64());
896 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U64))
897 .addReg(SrcReg, getKillRegState(KillSrc))
898 .addImm(0);
899 } else {
900 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
901 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32))
902 .addReg(SrcReg, getKillRegState(KillSrc))
903 .addImm(0);
904 }
905
906 return;
907 }
908
909 if (RC == &AMDGPU::AGPR_32RegClass) {
910 if (AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
911 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
912 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
913 .addReg(SrcReg, getKillRegState(KillSrc));
914 return;
915 }
916
917 if (AMDGPU::AGPR_32RegClass.contains(SrcReg) && ST.hasGFX90AInsts()) {
918 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_MOV_B32), DestReg)
919 .addReg(SrcReg, getKillRegState(KillSrc));
920 return;
921 }
922
923 // FIXME: Pass should maintain scavenger to avoid scan through the block on
924 // every AGPR spill.
925 RegScavenger RS;
926 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
927 indirectCopyToAGPR(*this, MBB, MI, DL, DestReg, SrcReg, KillSrc, RS, Overlap);
928 return;
929 }
930
931 if (Size == 16) {
932 assert(AMDGPU::VGPR_16RegClass.contains(SrcReg) ||
933 AMDGPU::SReg_LO16RegClass.contains(SrcReg) ||
934 AMDGPU::AGPR_LO16RegClass.contains(SrcReg));
935
936 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
937 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
938 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
939 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
940 bool DstLow = !AMDGPU::isHi16Reg(DestReg, RI);
941 bool SrcLow = !AMDGPU::isHi16Reg(SrcReg, RI);
942 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
943 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
944
945 if (IsSGPRDst) {
946 if (!IsSGPRSrc) {
947 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
948 return;
949 }
950
951 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), NewDestReg)
952 .addReg(NewSrcReg, getKillRegState(KillSrc));
953 return;
954 }
955
956 if (IsAGPRDst || IsAGPRSrc) {
957 if (!DstLow || !SrcLow) {
958 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
959 "Cannot use hi16 subreg with an AGPR!");
960 }
961
962 copyPhysReg(MBB, MI, DL, NewDestReg, NewSrcReg, KillSrc);
963 return;
964 }
965
966 if (ST.useRealTrue16Insts()) {
967 if (IsSGPRSrc) {
968 assert(SrcLow);
969 SrcReg = NewSrcReg;
970 }
971 // Use the smaller instruction encoding if possible.
972 if (AMDGPU::VGPR_16_Lo128RegClass.contains(DestReg) &&
973 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.contains(SrcReg))) {
974 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e32), DestReg)
975 .addReg(SrcReg);
976 } else {
977 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e64), DestReg)
978 .addImm(0) // src0_modifiers
979 .addReg(SrcReg)
980 .addImm(0); // op_sel
981 }
982 return;
983 }
984
985 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
986 if (!DstLow || !SrcLow) {
987 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
988 "Cannot use hi16 subreg on VI!");
989 }
990
991 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), NewDestReg)
992 .addReg(NewSrcReg, getKillRegState(KillSrc));
993 return;
994 }
995
996 auto MIB = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_sdwa), NewDestReg)
997 .addImm(0) // src0_modifiers
998 .addReg(NewSrcReg)
999 .addImm(0) // clamp
1006 // First implicit operand is $exec.
1007 MIB->tieOperands(0, MIB->getNumOperands() - 1);
1008 return;
1009 }
1010
1011 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1012 if (ST.hasVMovB64Inst()) {
1013 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_e32), DestReg)
1014 .addReg(SrcReg, getKillRegState(KillSrc));
1015 return;
1016 }
1017 if (ST.hasPkMovB32()) {
1018 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestReg)
1020 .addReg(SrcReg)
1022 .addReg(SrcReg)
1023 .addImm(0) // op_sel_lo
1024 .addImm(0) // op_sel_hi
1025 .addImm(0) // neg_lo
1026 .addImm(0) // neg_hi
1027 .addImm(0) // clamp
1028 .addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
1029 return;
1030 }
1031 }
1032
1033 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1034 if (RI.isSGPRClass(RC)) {
1035 if (!RI.isSGPRClass(SrcRC)) {
1036 reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
1037 return;
1038 }
1039 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1040 expandSGPRCopy(*this, MBB, MI, DL, DestReg, SrcReg, CanKillSuperReg, RC,
1041 Forward);
1042 return;
1043 }
1044
1045 unsigned EltSize = 4;
1046 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1047 if (RI.isAGPRClass(RC)) {
1048 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1049 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1050 else if (RI.hasVGPRs(SrcRC) ||
1051 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1052 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1053 else
1054 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1055 } else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1056 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1057 } else if ((Size % 64 == 0) && RI.hasVGPRs(RC) &&
1058 (RI.isProperlyAlignedRC(*RC) &&
1059 (SrcRC == RC || RI.isSGPRClass(SrcRC)))) {
1060 // TODO: In 96-bit case, could do a 64-bit mov and then a 32-bit mov.
1061 if (ST.hasVMovB64Inst()) {
1062 Opcode = AMDGPU::V_MOV_B64_e32;
1063 EltSize = 8;
1064 } else if (ST.hasPkMovB32()) {
1065 Opcode = AMDGPU::V_PK_MOV_B32;
1066 EltSize = 8;
1067 }
1068 }
1069
1070 // For the cases where we need an intermediate instruction/temporary register
1071 // (destination is an AGPR), we need a scavenger.
1072 //
1073 // FIXME: The pass should maintain this for us so we don't have to re-scan the
1074 // whole block for every handled copy.
1075 std::unique_ptr<RegScavenger> RS;
1076 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1077 RS = std::make_unique<RegScavenger>();
1078
1079 ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, EltSize);
1080
1081 // If there is an overlap, we can't kill the super-register on the last
1082 // instruction, since it will also kill the components made live by this def.
1083 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1084 const bool CanKillSuperReg = KillSrc && !Overlap;
1085
1086 for (unsigned Idx = 0; Idx < SubIndices.size(); ++Idx) {
1087 unsigned SubIdx;
1088 if (Forward)
1089 SubIdx = SubIndices[Idx];
1090 else
1091 SubIdx = SubIndices[SubIndices.size() - Idx - 1];
1092 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1093 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1094 assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
1095
1096 bool UseKill = CanKillSuperReg && Idx == SubIndices.size() - 1;
1097
1098 if (Opcode == AMDGPU::INSTRUCTION_LIST_END) {
1099 Register ImpUseSuper = SrcReg;
1100 indirectCopyToAGPR(*this, MBB, MI, DL, DestSubReg, SrcSubReg, UseKill,
1101 *RS, Overlap, ImpUseSuper);
1102 } else if (Opcode == AMDGPU::V_PK_MOV_B32) {
1103 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestSubReg)
1105 .addReg(SrcSubReg)
1107 .addReg(SrcSubReg)
1108 .addImm(0) // op_sel_lo
1109 .addImm(0) // op_sel_hi
1110 .addImm(0) // neg_lo
1111 .addImm(0) // neg_hi
1112 .addImm(0) // clamp
1113 .addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1114 } else {
1115 MachineInstrBuilder Builder =
1116 BuildMI(MBB, MI, DL, get(Opcode), DestSubReg).addReg(SrcSubReg);
1117
1118 Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
1119 }
1120 }
1121}
1122
1123int SIInstrInfo::commuteOpcode(unsigned Opcode) const {
1124 int32_t NewOpc;
1125
1126 // Try to map original to commuted opcode
1127 NewOpc = AMDGPU::getCommuteRev(Opcode);
1128 if (NewOpc != -1)
1129 // Check if the commuted (REV) opcode exists on the target.
1130 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1131
1132 // Try to map commuted to original opcode
1133 NewOpc = AMDGPU::getCommuteOrig(Opcode);
1134 if (NewOpc != -1)
1135 // Check if the original (non-REV) opcode exists on the target.
1136 return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;
1137
1138 return Opcode;
1139}
1140
1142 const Register Reg,
1143 int64_t &ImmVal) const {
1144 switch (MI.getOpcode()) {
1145 case AMDGPU::V_MOV_B32_e32:
1146 case AMDGPU::S_MOV_B32:
1147 case AMDGPU::S_MOVK_I32:
1148 case AMDGPU::S_MOV_B64:
1149 case AMDGPU::V_MOV_B64_e32:
1150 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1151 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1152 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1153 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1154 case AMDGPU::V_MOV_B64_PSEUDO:
1155 case AMDGPU::V_MOV_B16_t16_e32: {
1156 const MachineOperand &Src0 = MI.getOperand(1);
1157 if (Src0.isImm()) {
1158 ImmVal = Src0.getImm();
1159 return MI.getOperand(0).getReg() == Reg;
1160 }
1161
1162 return false;
1163 }
1164 case AMDGPU::V_MOV_B16_t16_e64: {
1165 const MachineOperand &Src0 = MI.getOperand(2);
1166 if (Src0.isImm() && !MI.getOperand(1).getImm()) {
1167 ImmVal = Src0.getImm();
1168 return MI.getOperand(0).getReg() == Reg;
1169 }
1170
1171 return false;
1172 }
1173 case AMDGPU::S_BREV_B32:
1174 case AMDGPU::V_BFREV_B32_e32:
1175 case AMDGPU::V_BFREV_B32_e64: {
1176 const MachineOperand &Src0 = MI.getOperand(1);
1177 if (Src0.isImm()) {
1178 ImmVal = static_cast<int64_t>(reverseBits<int32_t>(Src0.getImm()));
1179 return MI.getOperand(0).getReg() == Reg;
1180 }
1181
1182 return false;
1183 }
1184 case AMDGPU::S_NOT_B32:
1185 case AMDGPU::V_NOT_B32_e32:
1186 case AMDGPU::V_NOT_B32_e64: {
1187 const MachineOperand &Src0 = MI.getOperand(1);
1188 if (Src0.isImm()) {
1189 ImmVal = static_cast<int64_t>(~static_cast<int32_t>(Src0.getImm()));
1190 return MI.getOperand(0).getReg() == Reg;
1191 }
1192
1193 return false;
1194 }
1195 default:
1196 return false;
1197 }
1198}
1199
1200std::optional<int64_t>
1202 if (Op.isImm())
1203 return Op.getImm();
1204
1205 if (!Op.isReg() || !Op.getReg().isVirtual())
1206 return std::nullopt;
1207 MachineRegisterInfo &MRI = Op.getParent()->getMF()->getRegInfo();
1208 const MachineInstr *Def = MRI.getVRegDef(Op.getReg());
1209 if (Def && Def->isMoveImmediate()) {
1210 const MachineOperand &ImmSrc = Def->getOperand(1);
1211 if (ImmSrc.isImm())
1212 return extractSubregFromImm(ImmSrc.getImm(), Op.getSubReg());
1213 }
1214
1215 return std::nullopt;
1216}
1217
1219
1220 if (RI.isAGPRClass(DstRC))
1221 return AMDGPU::COPY;
1222 if (RI.getRegSizeInBits(*DstRC) == 16) {
1223 // Assume hi bits are unneeded. Only _e64 true16 instructions are legal
1224 // before RA.
1225 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1226 }
1227 if (RI.getRegSizeInBits(*DstRC) == 32)
1228 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1229 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1230 return AMDGPU::S_MOV_B64;
1231 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1232 return AMDGPU::V_MOV_B64_PSEUDO;
1233 return AMDGPU::COPY;
1234}
1235
1236const MCInstrDesc &
1238 bool IsIndirectSrc) const {
1239 if (IsIndirectSrc) {
1240 if (VecSize <= 32) // 4 bytes
1241 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1242 if (VecSize <= 64) // 8 bytes
1243 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1244 if (VecSize <= 96) // 12 bytes
1245 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1246 if (VecSize <= 128) // 16 bytes
1247 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1248 if (VecSize <= 160) // 20 bytes
1249 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1250 if (VecSize <= 192) // 24 bytes
1251 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1252 if (VecSize <= 224) // 28 bytes
1253 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1254 if (VecSize <= 256) // 32 bytes
1255 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1256 if (VecSize <= 288) // 36 bytes
1257 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1258 if (VecSize <= 320) // 40 bytes
1259 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1260 if (VecSize <= 352) // 44 bytes
1261 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1262 if (VecSize <= 384) // 48 bytes
1263 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1264 if (VecSize <= 512) // 64 bytes
1265 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1266 if (VecSize <= 1024) // 128 bytes
1267 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1268
1269 llvm_unreachable("unsupported size for IndirectRegReadGPRIDX pseudos");
1270 }
1271
1272 if (VecSize <= 32) // 4 bytes
1273 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1274 if (VecSize <= 64) // 8 bytes
1275 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1276 if (VecSize <= 96) // 12 bytes
1277 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1278 if (VecSize <= 128) // 16 bytes
1279 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1280 if (VecSize <= 160) // 20 bytes
1281 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1282 if (VecSize <= 192) // 24 bytes
1283 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1284 if (VecSize <= 224) // 28 bytes
1285 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1286 if (VecSize <= 256) // 32 bytes
1287 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1288 if (VecSize <= 288) // 36 bytes
1289 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1290 if (VecSize <= 320) // 40 bytes
1291 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1292 if (VecSize <= 352) // 44 bytes
1293 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1294 if (VecSize <= 384) // 48 bytes
1295 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1296 if (VecSize <= 512) // 64 bytes
1297 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1298 if (VecSize <= 1024) // 128 bytes
1299 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1300
1301 llvm_unreachable("unsupported size for IndirectRegWriteGPRIDX pseudos");
1302}
1303
1304static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize) {
1305 if (VecSize <= 32) // 4 bytes
1306 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1307 if (VecSize <= 64) // 8 bytes
1308 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1309 if (VecSize <= 96) // 12 bytes
1310 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1311 if (VecSize <= 128) // 16 bytes
1312 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1313 if (VecSize <= 160) // 20 bytes
1314 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1315 if (VecSize <= 192) // 24 bytes
1316 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1317 if (VecSize <= 224) // 28 bytes
1318 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1319 if (VecSize <= 256) // 32 bytes
1320 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1321 if (VecSize <= 288) // 36 bytes
1322 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1323 if (VecSize <= 320) // 40 bytes
1324 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1325 if (VecSize <= 352) // 44 bytes
1326 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1327 if (VecSize <= 384) // 48 bytes
1328 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1329 if (VecSize <= 512) // 64 bytes
1330 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1331 if (VecSize <= 1024) // 128 bytes
1332 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1333
1334 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1335}
1336
1337static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize) {
1338 if (VecSize <= 32) // 4 bytes
1339 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1340 if (VecSize <= 64) // 8 bytes
1341 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1342 if (VecSize <= 96) // 12 bytes
1343 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1344 if (VecSize <= 128) // 16 bytes
1345 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1346 if (VecSize <= 160) // 20 bytes
1347 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1348 if (VecSize <= 192) // 24 bytes
1349 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1350 if (VecSize <= 224) // 28 bytes
1351 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1352 if (VecSize <= 256) // 32 bytes
1353 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1354 if (VecSize <= 288) // 36 bytes
1355 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1356 if (VecSize <= 320) // 40 bytes
1357 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1358 if (VecSize <= 352) // 44 bytes
1359 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1360 if (VecSize <= 384) // 48 bytes
1361 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1362 if (VecSize <= 512) // 64 bytes
1363 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1364 if (VecSize <= 1024) // 128 bytes
1365 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1366
1367 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1368}
1369
1370static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize) {
1371 if (VecSize <= 64) // 8 bytes
1372 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1373 if (VecSize <= 128) // 16 bytes
1374 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1375 if (VecSize <= 256) // 32 bytes
1376 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1377 if (VecSize <= 512) // 64 bytes
1378 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1379 if (VecSize <= 1024) // 128 bytes
1380 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1381
1382 llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
1383}
1384
1385const MCInstrDesc &
1386SIInstrInfo::getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize,
1387 bool IsSGPR) const {
1388 if (IsSGPR) {
1389 switch (EltSize) {
1390 case 32:
1391 return get(getIndirectSGPRWriteMovRelPseudo32(VecSize));
1392 case 64:
1393 return get(getIndirectSGPRWriteMovRelPseudo64(VecSize));
1394 default:
1395 llvm_unreachable("invalid reg indexing elt size");
1396 }
1397 }
1398
1399 assert(EltSize == 32 && "invalid reg indexing elt size");
1401}
1402
1403static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1404 switch (Size) {
1405 case 4:
1406 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1407 case 8:
1408 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1409 case 12:
1410 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1411 case 16:
1412 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1413 : AMDGPU::SI_SPILL_S128_SAVE;
1414 case 20:
1415 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1416 : AMDGPU::SI_SPILL_S160_SAVE;
1417 case 24:
1418 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1419 : AMDGPU::SI_SPILL_S192_SAVE;
1420 case 28:
1421 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1422 : AMDGPU::SI_SPILL_S224_SAVE;
1423 case 32:
1424 return AMDGPU::SI_SPILL_S256_SAVE;
1425 case 36:
1426 return AMDGPU::SI_SPILL_S288_SAVE;
1427 case 40:
1428 return AMDGPU::SI_SPILL_S320_SAVE;
1429 case 44:
1430 return AMDGPU::SI_SPILL_S352_SAVE;
1431 case 48:
1432 return AMDGPU::SI_SPILL_S384_SAVE;
1433 case 64:
1434 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1435 : AMDGPU::SI_SPILL_S512_SAVE;
1436 case 128:
1437 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1438 : AMDGPU::SI_SPILL_S1024_SAVE;
1439 default:
1440 llvm_unreachable("unknown register size");
1441 }
1442}
1443
1444static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1445 switch (Size) {
1446 case 2:
1447 return AMDGPU::SI_SPILL_V16_SAVE;
1448 case 4:
1449 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1450 case 8:
1451 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1452 case 12:
1453 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1454 case 16:
1455 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1456 : AMDGPU::SI_SPILL_V128_SAVE;
1457 case 20:
1458 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1459 : AMDGPU::SI_SPILL_V160_SAVE;
1460 case 24:
1461 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1462 : AMDGPU::SI_SPILL_V192_SAVE;
1463 case 28:
1464 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1465 : AMDGPU::SI_SPILL_V224_SAVE;
1466 case 32:
1467 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1468 : AMDGPU::SI_SPILL_V256_SAVE;
1469 case 36:
1470 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1471 : AMDGPU::SI_SPILL_V288_SAVE;
1472 case 40:
1473 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1474 : AMDGPU::SI_SPILL_V320_SAVE;
1475 case 44:
1476 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1477 : AMDGPU::SI_SPILL_V352_SAVE;
1478 case 48:
1479 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1480 : AMDGPU::SI_SPILL_V384_SAVE;
1481 case 64:
1482 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1483 : AMDGPU::SI_SPILL_V512_SAVE;
1484 case 128:
1485 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1486 : AMDGPU::SI_SPILL_V1024_SAVE;
1487 default:
1488 llvm_unreachable("unknown register size");
1489 }
1490}
1491
1492static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
1493 switch (Size) {
1494 case 4:
1495 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1496 : AMDGPU::SI_SPILL_AV32_SAVE;
1497 case 8:
1498 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1499 : AMDGPU::SI_SPILL_AV64_SAVE;
1500 case 12:
1501 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1502 : AMDGPU::SI_SPILL_AV96_SAVE;
1503 case 16:
1504 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1505 : AMDGPU::SI_SPILL_AV128_SAVE;
1506 case 20:
1507 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1508 : AMDGPU::SI_SPILL_AV160_SAVE;
1509 case 24:
1510 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1511 : AMDGPU::SI_SPILL_AV192_SAVE;
1512 case 28:
1513 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1514 : AMDGPU::SI_SPILL_AV224_SAVE;
1515 case 32:
1516 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1517 : AMDGPU::SI_SPILL_AV256_SAVE;
1518 case 36:
1519 return AMDGPU::SI_SPILL_AV288_SAVE;
1520 case 40:
1521 return AMDGPU::SI_SPILL_AV320_SAVE;
1522 case 44:
1523 return AMDGPU::SI_SPILL_AV352_SAVE;
1524 case 48:
1525 return AMDGPU::SI_SPILL_AV384_SAVE;
1526 case 64:
1527 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1528 : AMDGPU::SI_SPILL_AV512_SAVE;
1529 case 128:
1530 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1531 : AMDGPU::SI_SPILL_AV1024_SAVE;
1532 default:
1533 llvm_unreachable("unknown register size");
1534 }
1535}
1536
1537static unsigned getWWMRegSpillSaveOpcode(unsigned Size,
1538 bool IsVectorSuperClass) {
1539 // Currently, there is only 32-bit WWM register spills needed.
1540 if (Size != 4)
1541 llvm_unreachable("unknown wwm register spill size");
1542
1543 if (IsVectorSuperClass)
1544 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1545
1546 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1547}
1548
1550 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1551 const SIMachineFunctionInfo &MFI, bool NeedsCFI) const {
1552 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1553
1554 // Choose the right opcode if spilling a WWM register.
1556 return getWWMRegSpillSaveOpcode(Size, IsVectorSuperClass);
1557
1558 // TODO: Check if AGPRs are available
1559 if (ST.hasMAIInsts())
1560 return getAVSpillSaveOpcode(Size, NeedsCFI);
1561
1562 return getVGPRSpillSaveOpcode(Size, NeedsCFI);
1563}
1564
1565void SIInstrInfo::storeRegToStackSlotImpl(
1567 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1568 MachineInstr::MIFlag Flags, bool NeedsCFI) const {
1569 MachineFunction *MF = MBB.getParent();
1571 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1572 const DebugLoc &DL = MBB.findDebugLoc(MI);
1573
1574 MachinePointerInfo PtrInfo
1575 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1577 PtrInfo, MachineMemOperand::MOStore, FrameInfo.getObjectSize(FrameIndex),
1578 FrameInfo.getObjectAlign(FrameIndex));
1579 unsigned SpillSize = RI.getSpillSize(*RC);
1580
1581 MachineRegisterInfo &MRI = MF->getRegInfo();
1582 if (RI.isSGPRClass(RC)) {
1583 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1584 MFI->setHasSpilledSGPRs();
1585 assert(SrcReg != AMDGPU::M0 && "m0 should not be spilled");
1586 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1587 SrcReg != AMDGPU::EXEC && "exec should not be spilled");
1588
1589 // We are only allowed to create one new instruction when spilling
1590 // registers, so we need to use pseudo instruction for spilling SGPRs.
1591 const MCInstrDesc &OpDesc =
1592 get(getSGPRSpillSaveOpcode(SpillSize, NeedsCFI));
1593
1594 // The SGPR spill/restore instructions only work on number sgprs, so we need
1595 // to make sure we are using the correct register class.
1596 if (SrcReg.isVirtual() && SpillSize == 4) {
1597 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1598 }
1599
1600 BuildMI(MBB, MI, DL, OpDesc)
1601 .addReg(SrcReg, getKillRegState(isKill)) // data
1602 .addFrameIndex(FrameIndex) // addr
1603 .addMemOperand(MMO)
1605
1606 return;
1607 }
1608
1609 unsigned Opcode = getVectorRegSpillSaveOpcode(VReg ? VReg : SrcReg, RC,
1610 SpillSize, *MFI, NeedsCFI);
1611 MFI->setHasSpilledVGPRs();
1612
1613 BuildMI(MBB, MI, DL, get(Opcode))
1614 .addReg(SrcReg, getKillRegState(isKill)) // data
1615 .addFrameIndex(FrameIndex) // addr
1616 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1617 .addImm(0) // offset
1618 .addMemOperand(MMO);
1619}
1620
1623 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
1624 MachineInstr::MIFlag Flags) const {
1625 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1626 false);
1627}
1628
1631 Register SrcReg, bool isKill,
1632 int FrameIndex,
1633 const TargetRegisterClass *RC) const {
1634 storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, Register(),
1635 MachineInstr::NoFlags, true);
1636}
1637
1638static unsigned getSGPRSpillRestoreOpcode(unsigned Size) {
1639 switch (Size) {
1640 case 4:
1641 return AMDGPU::SI_SPILL_S32_RESTORE;
1642 case 8:
1643 return AMDGPU::SI_SPILL_S64_RESTORE;
1644 case 12:
1645 return AMDGPU::SI_SPILL_S96_RESTORE;
1646 case 16:
1647 return AMDGPU::SI_SPILL_S128_RESTORE;
1648 case 20:
1649 return AMDGPU::SI_SPILL_S160_RESTORE;
1650 case 24:
1651 return AMDGPU::SI_SPILL_S192_RESTORE;
1652 case 28:
1653 return AMDGPU::SI_SPILL_S224_RESTORE;
1654 case 32:
1655 return AMDGPU::SI_SPILL_S256_RESTORE;
1656 case 36:
1657 return AMDGPU::SI_SPILL_S288_RESTORE;
1658 case 40:
1659 return AMDGPU::SI_SPILL_S320_RESTORE;
1660 case 44:
1661 return AMDGPU::SI_SPILL_S352_RESTORE;
1662 case 48:
1663 return AMDGPU::SI_SPILL_S384_RESTORE;
1664 case 64:
1665 return AMDGPU::SI_SPILL_S512_RESTORE;
1666 case 128:
1667 return AMDGPU::SI_SPILL_S1024_RESTORE;
1668 default:
1669 llvm_unreachable("unknown register size");
1670 }
1671}
1672
1673static unsigned getVGPRSpillRestoreOpcode(unsigned Size) {
1674 switch (Size) {
1675 case 2:
1676 return AMDGPU::SI_SPILL_V16_RESTORE;
1677 case 4:
1678 return AMDGPU::SI_SPILL_V32_RESTORE;
1679 case 8:
1680 return AMDGPU::SI_SPILL_V64_RESTORE;
1681 case 12:
1682 return AMDGPU::SI_SPILL_V96_RESTORE;
1683 case 16:
1684 return AMDGPU::SI_SPILL_V128_RESTORE;
1685 case 20:
1686 return AMDGPU::SI_SPILL_V160_RESTORE;
1687 case 24:
1688 return AMDGPU::SI_SPILL_V192_RESTORE;
1689 case 28:
1690 return AMDGPU::SI_SPILL_V224_RESTORE;
1691 case 32:
1692 return AMDGPU::SI_SPILL_V256_RESTORE;
1693 case 36:
1694 return AMDGPU::SI_SPILL_V288_RESTORE;
1695 case 40:
1696 return AMDGPU::SI_SPILL_V320_RESTORE;
1697 case 44:
1698 return AMDGPU::SI_SPILL_V352_RESTORE;
1699 case 48:
1700 return AMDGPU::SI_SPILL_V384_RESTORE;
1701 case 64:
1702 return AMDGPU::SI_SPILL_V512_RESTORE;
1703 case 128:
1704 return AMDGPU::SI_SPILL_V1024_RESTORE;
1705 default:
1706 llvm_unreachable("unknown register size");
1707 }
1708}
1709
1710static unsigned getAVSpillRestoreOpcode(unsigned Size) {
1711 switch (Size) {
1712 case 4:
1713 return AMDGPU::SI_SPILL_AV32_RESTORE;
1714 case 8:
1715 return AMDGPU::SI_SPILL_AV64_RESTORE;
1716 case 12:
1717 return AMDGPU::SI_SPILL_AV96_RESTORE;
1718 case 16:
1719 return AMDGPU::SI_SPILL_AV128_RESTORE;
1720 case 20:
1721 return AMDGPU::SI_SPILL_AV160_RESTORE;
1722 case 24:
1723 return AMDGPU::SI_SPILL_AV192_RESTORE;
1724 case 28:
1725 return AMDGPU::SI_SPILL_AV224_RESTORE;
1726 case 32:
1727 return AMDGPU::SI_SPILL_AV256_RESTORE;
1728 case 36:
1729 return AMDGPU::SI_SPILL_AV288_RESTORE;
1730 case 40:
1731 return AMDGPU::SI_SPILL_AV320_RESTORE;
1732 case 44:
1733 return AMDGPU::SI_SPILL_AV352_RESTORE;
1734 case 48:
1735 return AMDGPU::SI_SPILL_AV384_RESTORE;
1736 case 64:
1737 return AMDGPU::SI_SPILL_AV512_RESTORE;
1738 case 128:
1739 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1740 default:
1741 llvm_unreachable("unknown register size");
1742 }
1743}
1744
1745static unsigned getWWMRegSpillRestoreOpcode(unsigned Size,
1746 bool IsVectorSuperClass) {
1747 // Currently, there is only 32-bit WWM register spills needed.
1748 if (Size != 4)
1749 llvm_unreachable("unknown wwm register spill size");
1750
1751 if (IsVectorSuperClass) // TODO: Always use this if there are AGPRs
1752 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1753
1754 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1755}
1756
1758 Register Reg, const TargetRegisterClass *RC, unsigned Size,
1759 const SIMachineFunctionInfo &MFI) const {
1760 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1761
1762 // Choose the right opcode if restoring a WWM register.
1764 return getWWMRegSpillRestoreOpcode(Size, IsVectorSuperClass);
1765
1766 // TODO: Check if AGPRs are available
1767 if (ST.hasMAIInsts())
1769
1770 assert(!RI.isAGPRClass(RC));
1772}
1773
1776 Register DestReg, int FrameIndex,
1777 const TargetRegisterClass *RC,
1778 Register VReg, unsigned SubReg,
1779 MachineInstr::MIFlag Flags) const {
1780 MachineFunction *MF = MBB.getParent();
1782 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
1783 const DebugLoc &DL = MBB.findDebugLoc(MI);
1784 unsigned SpillSize = RI.getSpillSize(*RC);
1785
1786 MachinePointerInfo PtrInfo
1787 = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
1788
1790 PtrInfo, MachineMemOperand::MOLoad, FrameInfo.getObjectSize(FrameIndex),
1791 FrameInfo.getObjectAlign(FrameIndex));
1792
1793 if (RI.isSGPRClass(RC)) {
1794 if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
1795 MFI->setHasSpilledSGPRs();
1796 assert(DestReg != AMDGPU::M0 && "m0 should not be reloaded into");
1797 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1798 DestReg != AMDGPU::EXEC && "exec should not be spilled");
1799
1800 // FIXME: Maybe this should not include a memoperand because it will be
1801 // lowered to non-memory instructions.
1802 const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize));
1803 if (DestReg.isVirtual() && SpillSize == 4) {
1804 MachineRegisterInfo &MRI = MF->getRegInfo();
1805 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1806 }
1807
1808 BuildMI(MBB, MI, DL, OpDesc, DestReg)
1809 .addFrameIndex(FrameIndex) // addr
1810 .addMemOperand(MMO)
1812
1813 return;
1814 }
1815
1816 unsigned Opcode = getVectorRegSpillRestoreOpcode(VReg ? VReg : DestReg, RC,
1817 SpillSize, *MFI);
1818 BuildMI(MBB, MI, DL, get(Opcode), DestReg)
1819 .addFrameIndex(FrameIndex) // vaddr
1820 .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
1821 .addImm(0) // offset
1822 .addMemOperand(MMO);
1823}
1824
1829
1832 unsigned Quantity) const {
1833 DebugLoc DL = MBB.findDebugLoc(MI);
1834 unsigned MaxSNopCount = 1u << ST.getSNopBits();
1835 while (Quantity > 0) {
1836 unsigned Arg = std::min(Quantity, MaxSNopCount);
1837 Quantity -= Arg;
1838 BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
1839 }
1840}
1841
1845 const DebugLoc &DL) const {
1846 MachineFunction *MF = MBB.getParent();
1847 constexpr unsigned DoorbellIDMask = 0x3ff;
1848 constexpr unsigned ECQueueWaveAbort = 0x400;
1849
1850 MachineBasicBlock *TrapBB = &MBB;
1851 MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock();
1852
1853 if (!MBB.succ_empty() || std::next(MI.getIterator()) != MBB.end()) {
1854 MBB.splitAt(MI, /*UpdateLiveIns=*/false);
1855 TrapBB = MF->CreateMachineBasicBlock();
1856 BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB);
1857 MF->push_back(TrapBB);
1858 MBB.addSuccessor(TrapBB);
1859 }
1860 // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this
1861 // will be a nop.
1862 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP))
1863 .addImm(static_cast<unsigned>(GCNSubtarget::TrapID::LLVMAMDHSATrap));
1864 Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1865 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32),
1866 DoorbellReg)
1868 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
1869 .addUse(AMDGPU::M0);
1870 Register DoorbellRegMasked =
1871 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1872 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked)
1873 .addUse(DoorbellReg)
1874 .addImm(DoorbellIDMask);
1875 Register SetWaveAbortBit =
1876 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
1877 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit)
1878 .addUse(DoorbellRegMasked)
1879 .addImm(ECQueueWaveAbort);
1880 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1881 .addUse(SetWaveAbortBit);
1882 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG))
1884 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
1885 .addUse(AMDGPU::TTMP2);
1886 BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB);
1887 TrapBB->addSuccessor(HaltLoopBB);
1888
1889 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5);
1890 BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH))
1891 .addMBB(HaltLoopBB);
1892 MF->push_back(HaltLoopBB);
1893 HaltLoopBB->addSuccessor(HaltLoopBB);
1894
1895 return MBB.getNextNode();
1896}
1897
1899 switch (MI.getOpcode()) {
1900 default:
1901 if (MI.isMetaInstruction())
1902 return 0;
1903 return 1; // FIXME: Do wait states equal cycles?
1904
1905 case AMDGPU::S_NOP:
1906 return MI.getOperand(0).getImm() + 1;
1907 // SI_RETURN_TO_EPILOG is a fallthrough to code outside of the function. The
1908 // hazard, even if one exist, won't really be visible. Should we handle it?
1909 }
1910}
1911
1913 MachineBasicBlock &MBB = *MI.getParent();
1914 DebugLoc DL = MBB.findDebugLoc(MI);
1916 switch (MI.getOpcode()) {
1917 default: return TargetInstrInfo::expandPostRAPseudo(MI);
1918 case AMDGPU::S_MOV_B64_term:
1919 // This is only a terminator to get the correct spill code placement during
1920 // register allocation.
1921 MI.setDesc(get(AMDGPU::S_MOV_B64));
1922 break;
1923
1924 case AMDGPU::S_MOV_B32_term:
1925 // This is only a terminator to get the correct spill code placement during
1926 // register allocation.
1927 MI.setDesc(get(AMDGPU::S_MOV_B32));
1928 break;
1929
1930 case AMDGPU::S_XOR_B64_term:
1931 // This is only a terminator to get the correct spill code placement during
1932 // register allocation.
1933 MI.setDesc(get(AMDGPU::S_XOR_B64));
1934 break;
1935
1936 case AMDGPU::S_XOR_B32_term:
1937 // This is only a terminator to get the correct spill code placement during
1938 // register allocation.
1939 MI.setDesc(get(AMDGPU::S_XOR_B32));
1940 break;
1941 case AMDGPU::S_OR_B64_term:
1942 // This is only a terminator to get the correct spill code placement during
1943 // register allocation.
1944 MI.setDesc(get(AMDGPU::S_OR_B64));
1945 break;
1946 case AMDGPU::S_OR_B32_term:
1947 // This is only a terminator to get the correct spill code placement during
1948 // register allocation.
1949 MI.setDesc(get(AMDGPU::S_OR_B32));
1950 break;
1951
1952 case AMDGPU::S_ANDN2_B64_term:
1953 // This is only a terminator to get the correct spill code placement during
1954 // register allocation.
1955 MI.setDesc(get(AMDGPU::S_ANDN2_B64));
1956 break;
1957
1958 case AMDGPU::S_ANDN2_B32_term:
1959 // This is only a terminator to get the correct spill code placement during
1960 // register allocation.
1961 MI.setDesc(get(AMDGPU::S_ANDN2_B32));
1962 break;
1963
1964 case AMDGPU::S_AND_B64_term:
1965 // This is only a terminator to get the correct spill code placement during
1966 // register allocation.
1967 MI.setDesc(get(AMDGPU::S_AND_B64));
1968 break;
1969
1970 case AMDGPU::S_AND_B32_term:
1971 // This is only a terminator to get the correct spill code placement during
1972 // register allocation.
1973 MI.setDesc(get(AMDGPU::S_AND_B32));
1974 break;
1975
1976 case AMDGPU::S_AND_SAVEEXEC_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_AND_SAVEEXEC_B64));
1980 break;
1981
1982 case AMDGPU::S_AND_SAVEEXEC_B32_term:
1983 // This is only a terminator to get the correct spill code placement during
1984 // register allocation.
1985 MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B32));
1986 break;
1987
1988 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
1989 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
1990 break;
1991 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
1992 MI.setDesc(get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
1993 break;
1994
1995 case AMDGPU::SI_SPILL_S32_TO_VGPR:
1996 MI.setDesc(get(AMDGPU::V_WRITELANE_B32));
1997 break;
1998
1999 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2000 MI.setDesc(get(AMDGPU::V_READLANE_B32));
2001 break;
2002 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2003 Register Dst = MI.getOperand(0).getReg();
2004 bool IsAGPR = SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst));
2005 MI.setDesc(
2006 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2007 break;
2008 }
2009 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2010 Register Dst = MI.getOperand(0).getReg();
2011 if (SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst))) {
2012 int64_t Imm = MI.getOperand(1).getImm();
2013
2014 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2015 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2016 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstLo)
2017 .addImm(SignExtend64<32>(Imm));
2018 BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstHi)
2019 .addImm(SignExtend64<32>(Imm >> 32));
2020 MI.eraseFromParent();
2021 break;
2022 }
2023
2024 [[fallthrough]];
2025 }
2026 case AMDGPU::V_MOV_B64_PSEUDO: {
2027 Register Dst = MI.getOperand(0).getReg();
2028 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2029 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2030
2031 const MCInstrDesc &Mov64Desc = get(AMDGPU::V_MOV_B64_e32);
2032 const TargetRegisterClass *Mov64RC = getRegClass(Mov64Desc, /*OpNum=*/0);
2033
2034 const MachineOperand &SrcOp = MI.getOperand(1);
2035 // FIXME: Will this work for 64-bit floating point immediates?
2036 assert(!SrcOp.isFPImm());
2037 if (ST.hasVMovB64Inst() && Mov64RC->contains(Dst)) {
2038 MI.setDesc(Mov64Desc);
2039 if (SrcOp.isReg() || isInlineConstant(MI, 1) ||
2040 isUInt<32>(SrcOp.getImm()) || ST.has64BitLiterals())
2041 break;
2042 }
2043 if (SrcOp.isImm()) {
2044 APInt Imm(64, SrcOp.getImm());
2045 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2046 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2047 const MCInstrDesc &PkMovDesc = get(AMDGPU::V_PK_MOV_B32);
2048 const TargetRegisterClass *PkMovRC = getRegClass(PkMovDesc, /*OpNum=*/0);
2049
2050 if (ST.hasPkMovB32() && Lo == Hi && isInlineConstant(Lo) &&
2051 PkMovRC->contains(Dst)) {
2052 BuildMI(MBB, MI, DL, PkMovDesc, Dst)
2054 .addImm(Lo.getSExtValue())
2056 .addImm(Lo.getSExtValue())
2057 .addImm(0) // op_sel_lo
2058 .addImm(0) // op_sel_hi
2059 .addImm(0) // neg_lo
2060 .addImm(0) // neg_hi
2061 .addImm(0); // clamp
2062 } else {
2063 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2064 .addImm(Lo.getSExtValue());
2065 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2066 .addImm(Hi.getSExtValue());
2067 }
2068 } else {
2069 assert(SrcOp.isReg());
2070 if (ST.hasPkMovB32() &&
2071 !RI.isAGPR(MBB.getParent()->getRegInfo(), SrcOp.getReg())) {
2072 BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), Dst)
2073 .addImm(SISrcMods::OP_SEL_1) // src0_mod
2074 .addReg(SrcOp.getReg())
2076 .addReg(SrcOp.getReg())
2077 .addImm(0) // op_sel_lo
2078 .addImm(0) // op_sel_hi
2079 .addImm(0) // neg_lo
2080 .addImm(0) // neg_hi
2081 .addImm(0); // clamp
2082 } else {
2083 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
2084 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0));
2085 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
2086 .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1));
2087 }
2088 }
2089 MI.eraseFromParent();
2090 break;
2091 }
2092 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2094 break;
2095 }
2096 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2097 const MachineOperand &SrcOp = MI.getOperand(1);
2098 assert(!SrcOp.isFPImm());
2099
2100 if (ST.has64BitLiterals()) {
2101 MI.setDesc(get(AMDGPU::S_MOV_B64));
2102 break;
2103 }
2104
2105 APInt Imm(64, SrcOp.getImm());
2106 if (Imm.isIntN(32) || isInlineConstant(Imm)) {
2107 MI.setDesc(get(AMDGPU::S_MOV_B64));
2108 break;
2109 }
2110
2111 Register Dst = MI.getOperand(0).getReg();
2112 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2113 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2114
2115 APInt Lo(32, Imm.getLoBits(32).getZExtValue());
2116 APInt Hi(32, Imm.getHiBits(32).getZExtValue());
2117 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
2118 .addImm(Lo.getSExtValue());
2119 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
2120 .addImm(Hi.getSExtValue());
2121 MI.eraseFromParent();
2122 break;
2123 }
2124 case AMDGPU::V_SET_INACTIVE_B32: {
2125 // Lower V_SET_INACTIVE_B32 to V_CNDMASK_B32.
2126 Register DstReg = MI.getOperand(0).getReg();
2127 BuildMI(MBB, MI, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2128 .add(MI.getOperand(3))
2129 .add(MI.getOperand(4))
2130 .add(MI.getOperand(1))
2131 .add(MI.getOperand(2))
2132 .add(MI.getOperand(5));
2133 MI.eraseFromParent();
2134 break;
2135 }
2136 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2137 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2138 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2139 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2140 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2141 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2142 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2143 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2144 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2145 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2146 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2147 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2148 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2149 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2150 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2151 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2152 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2153 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2154 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2155 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2156 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2157 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2158 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2159 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2160 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2161 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2162 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2163 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2164 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2165 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2166 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2167 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2168 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2169 const TargetRegisterClass *EltRC = getOpRegClass(MI, 2);
2170
2171 unsigned Opc;
2172 if (RI.hasVGPRs(EltRC)) {
2173 Opc = AMDGPU::V_MOVRELD_B32_e32;
2174 } else {
2175 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2176 : AMDGPU::S_MOVRELD_B32;
2177 }
2178
2179 const MCInstrDesc &OpDesc = get(Opc);
2180 Register VecReg = MI.getOperand(0).getReg();
2181 bool IsUndef = MI.getOperand(1).isUndef();
2182 unsigned SubReg = MI.getOperand(3).getImm();
2183 assert(VecReg == MI.getOperand(1).getReg());
2184
2186 BuildMI(MBB, MI, DL, OpDesc)
2187 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2188 .add(MI.getOperand(2))
2190 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2191
2192 const int ImpDefIdx =
2193 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2194 const int ImpUseIdx = ImpDefIdx + 1;
2195 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2196 MI.eraseFromParent();
2197 break;
2198 }
2199 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2200 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2201 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2202 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2203 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2204 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2205 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2206 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2207 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2208 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2209 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2210 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2211 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2212 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2213 assert(ST.useVGPRIndexMode());
2214 Register VecReg = MI.getOperand(0).getReg();
2215 bool IsUndef = MI.getOperand(1).isUndef();
2216 MachineOperand &Idx = MI.getOperand(3);
2217 Register SubReg = MI.getOperand(4).getImm();
2218
2219 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2220 .add(Idx)
2222 SetOn->getOperand(3).setIsUndef();
2223
2224 const MCInstrDesc &OpDesc = get(AMDGPU::V_MOV_B32_indirect_write);
2226 BuildMI(MBB, MI, DL, OpDesc)
2227 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2228 .add(MI.getOperand(2))
2230 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2231
2232 const int ImpDefIdx =
2233 OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
2234 const int ImpUseIdx = ImpDefIdx + 1;
2235 MIB->tieOperands(ImpDefIdx, ImpUseIdx);
2236
2237 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2238
2239 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2240
2241 MI.eraseFromParent();
2242 break;
2243 }
2244 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2245 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2246 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2247 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2248 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2249 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2250 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2251 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2252 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2253 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2254 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2255 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2256 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2257 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2258 assert(ST.useVGPRIndexMode());
2259 Register Dst = MI.getOperand(0).getReg();
2260 Register VecReg = MI.getOperand(1).getReg();
2261 bool IsUndef = MI.getOperand(1).isUndef();
2262 Register SubReg = MI.getOperand(3).getImm();
2263
2264 MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
2265 .add(MI.getOperand(2))
2267 SetOn->getOperand(3).setIsUndef();
2268
2269 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_indirect_read))
2270 .addDef(Dst)
2271 .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
2272 .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));
2273
2274 MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));
2275
2276 finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));
2277
2278 MI.eraseFromParent();
2279 break;
2280 }
2281 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2282 MachineFunction &MF = *MBB.getParent();
2283 Register Reg = MI.getOperand(0).getReg();
2284 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2285 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2286 MachineOperand OpLo = MI.getOperand(1);
2287 MachineOperand OpHi = MI.getOperand(2);
2288
2289 // Create a bundle so these instructions won't be re-ordered by the
2290 // post-RA scheduler.
2291 MIBundleBuilder Bundler(MBB, MI);
2292 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2293
2294 // What we want here is an offset from the value returned by s_getpc (which
2295 // is the address of the s_add_u32 instruction) to the global variable, but
2296 // since the encoding of $symbol starts 4 bytes after the start of the
2297 // s_add_u32 instruction, we end up with an offset that is 4 bytes too
2298 // small. This requires us to add 4 to the global variable offset in order
2299 // to compute the correct address. Similarly for the s_addc_u32 instruction,
2300 // the encoding of $symbol starts 12 bytes after the start of the s_add_u32
2301 // instruction.
2302
2303 int64_t Adjust = 0;
2304 if (ST.hasGetPCZeroExtension()) {
2305 // Fix up hardware that does not sign-extend the 48-bit PC value by
2306 // inserting: s_sext_i32_i16 reghi, reghi
2307 Bundler.append(
2308 BuildMI(MF, DL, get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2309 Adjust += 4;
2310 }
2311
2312 if (OpLo.isGlobal())
2313 OpLo.setOffset(OpLo.getOffset() + Adjust + 4);
2314 Bundler.append(
2315 BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2316
2317 if (OpHi.isGlobal())
2318 OpHi.setOffset(OpHi.getOffset() + Adjust + 12);
2319 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi)
2320 .addReg(RegHi)
2321 .add(OpHi));
2322
2323 finalizeBundle(MBB, Bundler.begin());
2324
2325 MI.eraseFromParent();
2326 break;
2327 }
2328 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2329 MachineFunction &MF = *MBB.getParent();
2330 Register Reg = MI.getOperand(0).getReg();
2331 MachineOperand Op = MI.getOperand(1);
2332
2333 // Create a bundle so these instructions won't be re-ordered by the
2334 // post-RA scheduler.
2335 MIBundleBuilder Bundler(MBB, MI);
2336 Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
2337 if (Op.isGlobal())
2338 Op.setOffset(Op.getOffset() + 4);
2339 Bundler.append(
2340 BuildMI(MF, DL, get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(Op));
2341
2342 finalizeBundle(MBB, Bundler.begin());
2343
2344 MI.eraseFromParent();
2345 break;
2346 }
2347 case AMDGPU::ENTER_STRICT_WWM: {
2348 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2349 // Whole Wave Mode is entered.
2350 MI.setDesc(get(LMC.OrSaveExecOpc));
2351 break;
2352 }
2353 case AMDGPU::ENTER_STRICT_WQM: {
2354 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2355 // STRICT_WQM is entered.
2356 BuildMI(MBB, MI, DL, get(LMC.MovOpc), MI.getOperand(0).getReg())
2357 .addReg(LMC.ExecReg);
2358 BuildMI(MBB, MI, DL, get(LMC.WQMOpc), LMC.ExecReg).addReg(LMC.ExecReg);
2359
2360 MI.eraseFromParent();
2361 break;
2362 }
2363 case AMDGPU::EXIT_STRICT_WWM:
2364 case AMDGPU::EXIT_STRICT_WQM: {
2365 // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
2366 // WWM/STICT_WQM is exited.
2367 MI.setDesc(get(LMC.MovOpc));
2368 break;
2369 }
2370 case AMDGPU::SI_RETURN: {
2371 const MachineFunction *MF = MBB.getParent();
2372 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2373 const SIRegisterInfo *TRI = ST.getRegisterInfo();
2374 // Hiding the return address use with SI_RETURN may lead to extra kills in
2375 // the function and missing live-ins. We are fine in practice because callee
2376 // saved register handling ensures the register value is restored before
2377 // RET, but we need the undef flag here to appease the MachineVerifier
2378 // liveness checks.
2380 BuildMI(MBB, MI, DL, get(AMDGPU::S_SETPC_B64_return))
2381 .addReg(TRI->getReturnAddressReg(*MF), RegState::Undef);
2382
2383 MIB.copyImplicitOps(MI);
2384 MI.eraseFromParent();
2385 break;
2386 }
2387
2388 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2389 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2390 MI.setDesc(get(AMDGPU::S_MUL_U64));
2391 break;
2392
2393 case AMDGPU::S_GETPC_B64_pseudo:
2394 MI.setDesc(get(AMDGPU::S_GETPC_B64));
2395 if (ST.hasGetPCZeroExtension()) {
2396 Register Dst = MI.getOperand(0).getReg();
2397 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2398 // Fix up hardware that does not sign-extend the 48-bit PC value by
2399 // inserting: s_sext_i32_i16 dsthi, dsthi
2400 BuildMI(MBB, std::next(MI.getIterator()), DL, get(AMDGPU::S_SEXT_I32_I16),
2401 DstHi)
2402 .addReg(DstHi);
2403 }
2404 break;
2405
2406 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2407 assert(ST.hasBF16PackedInsts());
2408 MI.setDesc(get(AMDGPU::V_PK_MAX_NUM_BF16));
2409 MI.addOperand(MachineOperand::CreateImm(0)); // op_sel
2410 MI.addOperand(MachineOperand::CreateImm(0)); // neg_lo
2411 MI.addOperand(MachineOperand::CreateImm(0)); // neg_hi
2412 auto Op0 = getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
2413 Op0->setImm(Op0->getImm() | SISrcMods::OP_SEL_1);
2414 auto Op1 = getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
2415 Op1->setImm(Op1->getImm() | SISrcMods::OP_SEL_1);
2416 break;
2417 }
2418
2419 case AMDGPU::GET_STACK_BASE:
2420 // The stack starts at offset 0 unless we need to reserve some space at the
2421 // bottom.
2422 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*MBB.getParent())) {
2423 // When CWSR is used in dynamic VGPR mode, the trap handler needs to save
2424 // some of the VGPRs. The size of the required scratch space has already
2425 // been computed by prolog epilog insertion.
2426 const SIMachineFunctionInfo *MFI =
2427 MBB.getParent()->getInfo<SIMachineFunctionInfo>();
2428 unsigned VGPRSize = MFI->getScratchReservedForDynamicVGPRs();
2429 Register DestReg = MI.getOperand(0).getReg();
2430 BuildMI(MBB, MI, DL, get(AMDGPU::S_GETREG_B32), DestReg)
2433 // The MicroEngine ID is 0 for the graphics queue, and 1 or 2 for compute
2434 // (3 is unused, so we ignore it). Unfortunately, S_GETREG doesn't set
2435 // SCC, so we need to check for 0 manually.
2436 BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)).addImm(0).addReg(DestReg);
2437 // Change the implicif-def of SCC to an explicit use (but first remove
2438 // the dead flag if present).
2439 MI.getOperand(MI.getNumExplicitOperands()).setIsDead(false);
2440 MI.getOperand(MI.getNumExplicitOperands()).setIsUse();
2441 MI.setDesc(get(AMDGPU::S_CMOVK_I32));
2442 MI.addOperand(MachineOperand::CreateImm(VGPRSize));
2443 } else {
2444 MI.setDesc(get(AMDGPU::S_MOV_B32));
2445 MI.addOperand(MachineOperand::CreateImm(0));
2446 MI.removeOperand(
2447 MI.getNumExplicitOperands()); // Drop implicit def of SCC.
2448 }
2449 break;
2450 }
2451
2452 return true;
2453}
2454
2457 unsigned SubIdx, const MachineInstr &Orig,
2458 LaneBitmask UsedLanes) const {
2459
2460 // Try shrinking the instruction to remat only the part needed for current
2461 // context.
2462 // TODO: Handle more cases.
2463 unsigned Opcode = Orig.getOpcode();
2464 switch (Opcode) {
2465 case AMDGPU::S_MOV_B64:
2466 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2467 if (SubIdx != 0)
2468 break;
2469
2470 if (!Orig.getOperand(1).isImm())
2471 break;
2472
2473 // Shrink S_MOV_B64 to S_MOV_B32 when UsedLanes indicates only a single
2474 // 32-bit lane of the 64-bit value is live at the rematerialization point.
2475 if (UsedLanes.all())
2476 break;
2477
2478 // Determine which half of the 64-bit immediate corresponds to the use.
2479 unsigned OrigSubReg = Orig.getOperand(0).getSubReg();
2480 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2481 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2482
2483 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2484 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2485
2486 if (NeedLo && NeedHi)
2487 break;
2488
2489 int64_t Imm64 = Orig.getOperand(1).getImm();
2490 int32_t Imm32 = NeedLo ? Lo_32(Imm64) : Hi_32(Imm64);
2491
2492 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2493
2494 // Emit S_MOV_B32 defining just the needed 32-bit subreg of DestReg.
2495 BuildMI(MBB, I, Orig.getDebugLoc(), get(AMDGPU::S_MOV_B32))
2496 .addReg(DestReg, RegState::Define | RegState::Undef, UseSubReg)
2497 .addImm(Imm32);
2498 return;
2499 }
2500
2501 case AMDGPU::S_LOAD_DWORDX16_IMM:
2502 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2503 if (SubIdx != 0)
2504 break;
2505
2506 if (I == MBB.end())
2507 break;
2508
2509 if (I->isBundled())
2510 break;
2511
2512 // Look for a single use of the register that is also a subreg.
2513 Register RegToFind = Orig.getOperand(0).getReg();
2514 MachineOperand *UseMO = nullptr;
2515 for (auto &CandMO : I->operands()) {
2516 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2517 continue;
2518 if (UseMO) {
2519 UseMO = nullptr;
2520 break;
2521 }
2522 UseMO = &CandMO;
2523 }
2524 if (!UseMO || UseMO->getSubReg() == AMDGPU::NoSubRegister)
2525 break;
2526
2527 unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
2528 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());
2529
2530 MachineFunction *MF = MBB.getParent();
2531 MachineRegisterInfo &MRI = MF->getRegInfo();
2532 assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");
2533
2534 unsigned NewOpcode = -1;
2535 if (SubregSize == 256)
2536 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2537 else if (SubregSize == 128)
2538 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2539 else
2540 break;
2541
2542 const MCInstrDesc &TID = get(NewOpcode);
2543 const TargetRegisterClass *NewRC =
2544 RI.getAllocatableClass(getRegClass(TID, 0));
2545 MRI.setRegClass(DestReg, NewRC);
2546
2547 UseMO->setReg(DestReg);
2548 UseMO->setSubReg(AMDGPU::NoSubRegister);
2549
2550 // Use a smaller load with the desired size, possibly with updated offset.
2551 MachineInstr *MI = MF->CloneMachineInstr(&Orig);
2552 MI->setDesc(TID);
2553 MI->getOperand(0).setReg(DestReg);
2554 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2555 if (Offset) {
2556 MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
2557 int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
2558 OffsetMO->setImm(FinalOffset);
2559 }
2561 for (const MachineMemOperand *MemOp : Orig.memoperands())
2562 NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
2563 SubregSize / 8));
2564 MI->setMemRefs(*MF, NewMMOs);
2565
2566 MBB.insert(I, MI);
2567 return;
2568 }
2569
2570 default:
2571 break;
2572 }
2573
2574 TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
2575}
2576
2577std::pair<MachineInstr*, MachineInstr*>
2579 assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2580
2581 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2583 ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
2584 MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
2585 return std::pair(&MI, nullptr);
2586 }
2587
2588 MachineBasicBlock &MBB = *MI.getParent();
2589 DebugLoc DL = MBB.findDebugLoc(MI);
2590 MachineFunction *MF = MBB.getParent();
2591 MachineRegisterInfo &MRI = MF->getRegInfo();
2592 Register Dst = MI.getOperand(0).getReg();
2593 unsigned Part = 0;
2594 MachineInstr *Split[2];
2595
2596 for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2597 auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
2598 if (Dst.isPhysical()) {
2599 MovDPP.addDef(RI.getSubReg(Dst, Sub));
2600 } else {
2601 assert(MRI.isSSA());
2602 auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2603 MovDPP.addDef(Tmp);
2604 }
2605
2606 for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
2607 const MachineOperand &SrcOp = MI.getOperand(I);
2608 assert(!SrcOp.isFPImm());
2609 if (SrcOp.isImm()) {
2610 APInt Imm(64, SrcOp.getImm());
2611 Imm.ashrInPlace(Part * 32);
2612 MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
2613 } else {
2614 assert(SrcOp.isReg());
2615 Register Src = SrcOp.getReg();
2616 if (Src.isPhysical())
2617 MovDPP.addReg(RI.getSubReg(Src, Sub));
2618 else
2619 MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
2620 }
2621 }
2622
2623 for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
2624 MovDPP.addImm(MO.getImm());
2625
2626 Split[Part] = MovDPP;
2627 ++Part;
2628 }
2629
2630 if (Dst.isVirtual())
2631 BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
2632 .addReg(Split[0]->getOperand(0).getReg())
2633 .addImm(AMDGPU::sub0)
2634 .addReg(Split[1]->getOperand(0).getReg())
2635 .addImm(AMDGPU::sub1);
2636
2637 MI.eraseFromParent();
2638 return std::pair(Split[0], Split[1]);
2639}
2640
2641std::optional<DestSourcePair>
2643 if (MI.getOpcode() == AMDGPU::WWM_COPY)
2644 return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};
2645
2646 return std::nullopt;
2647}
2648
2650 AMDGPU::OpName Src0OpName,
2651 MachineOperand &Src1,
2652 AMDGPU::OpName Src1OpName) const {
2653 MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
2654 if (!Src0Mods)
2655 return false;
2656
2657 MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
2658 assert(Src1Mods &&
2659 "All commutable instructions have both src0 and src1 modifiers");
2660
2661 int Src0ModsVal = Src0Mods->getImm();
2662 int Src1ModsVal = Src1Mods->getImm();
2663
2664 Src1Mods->setImm(Src0ModsVal);
2665 Src0Mods->setImm(Src1ModsVal);
2666 return true;
2667}
2668
2670 MachineOperand &RegOp,
2671 MachineOperand &NonRegOp) {
2672 Register Reg = RegOp.getReg();
2673 unsigned SubReg = RegOp.getSubReg();
2674 bool IsKill = RegOp.isKill();
2675 bool IsDead = RegOp.isDead();
2676 bool IsUndef = RegOp.isUndef();
2677 bool IsDebug = RegOp.isDebug();
2678
2679 if (NonRegOp.isImm())
2680 RegOp.ChangeToImmediate(NonRegOp.getImm());
2681 else if (NonRegOp.isFI())
2682 RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
2683 else if (NonRegOp.isGlobal()) {
2684 RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
2685 NonRegOp.getTargetFlags());
2686 } else
2687 return nullptr;
2688
2689 // Make sure we don't reinterpret a subreg index in the target flags.
2690 RegOp.setTargetFlags(NonRegOp.getTargetFlags());
2691
2692 NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
2693 NonRegOp.setSubReg(SubReg);
2694
2695 return &MI;
2696}
2697
2699 MachineOperand &NonRegOp1,
2700 MachineOperand &NonRegOp2) {
2701 unsigned TargetFlags = NonRegOp1.getTargetFlags();
2702 int64_t NonRegVal = NonRegOp1.getImm();
2703
2704 NonRegOp1.setImm(NonRegOp2.getImm());
2705 NonRegOp2.setImm(NonRegVal);
2706 NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
2707 NonRegOp2.setTargetFlags(TargetFlags);
2708 return &MI;
2709}
2710
2711bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
2712 unsigned OpIdx1) const {
2713 const MCInstrDesc &InstDesc = MI.getDesc();
2714 const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
2715 const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];
2716
2717 unsigned Opc = MI.getOpcode();
2718 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2719
2720 const MachineOperand &MO0 = MI.getOperand(OpIdx0);
2721 const MachineOperand &MO1 = MI.getOperand(OpIdx1);
2722
2723 // Swap doesn't breach constant bus or literal limits
2724 // It may move literal to position other than src0, this is not allowed
2725 // pre-gfx10 However, most test cases need literals in Src0 for VOP
2726 // FIXME: After gfx9, literal can be in place other than Src0
2727 if (isVALU(MI, /*AllowLDSDMA=*/true)) {
2728 if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
2729 !isInlineConstant(MO0, OpInfo1))
2730 return false;
2731 if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
2732 !isInlineConstant(MO1, OpInfo0))
2733 return false;
2734 }
2735
2736 if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
2737 if (OpInfo1.RegClass == -1)
2738 return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
2739 return isLegalRegOperand(MI, OpIdx1, MO0) &&
2740 (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
2741 }
2742 if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
2743 if (OpInfo0.RegClass == -1)
2744 return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
2745 return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
2746 isLegalRegOperand(MI, OpIdx0, MO1);
2747 }
2748
2749 // No need to check 64-bit literals since swapping does not bring new
2750 // 64-bit literals into current instruction to fold to 32-bit
2751
2752 return isImmOperandLegal(MI, OpIdx1, MO0);
2753}
2754
2756 unsigned Src0Idx,
2757 unsigned Src1Idx) const {
2758 assert(!NewMI && "this should never be used");
2759
2760 unsigned Opc = MI.getOpcode();
2761 int CommutedOpcode = commuteOpcode(Opc);
2762 if (CommutedOpcode == -1)
2763 return nullptr;
2764
2765 if (Src0Idx > Src1Idx)
2766 std::swap(Src0Idx, Src1Idx);
2767
2768 assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
2769 static_cast<int>(Src0Idx) &&
2770 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
2771 static_cast<int>(Src1Idx) &&
2772 "inconsistency with findCommutedOpIndices");
2773
2774 if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
2775 return nullptr;
2776
2777 MachineInstr *CommutedMI = nullptr;
2778 MachineOperand &Src0 = MI.getOperand(Src0Idx);
2779 MachineOperand &Src1 = MI.getOperand(Src1Idx);
2780 if (Src0.isReg() && Src1.isReg()) {
2781 // Be sure to copy the source modifiers to the right place.
2782 CommutedMI =
2783 TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
2784 } else if (Src0.isReg() && !Src1.isReg()) {
2785 CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
2786 } else if (!Src0.isReg() && Src1.isReg()) {
2787 CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
2788 } else if (Src0.isImm() && Src1.isImm()) {
2789 CommutedMI = swapImmOperands(MI, Src0, Src1);
2790 } else {
2791 // FIXME: Found two non registers to commute. This does happen.
2792 return nullptr;
2793 }
2794
2795 if (CommutedMI) {
2796 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
2797 Src1, AMDGPU::OpName::src1_modifiers);
2798
2799 swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
2800 AMDGPU::OpName::src1_sel);
2801
2802 CommutedMI->setDesc(get(CommutedOpcode));
2803 }
2804
2805 return CommutedMI;
2806}
2807
2808// This needs to be implemented because the source modifiers may be inserted
2809// between the true commutable operands, and the base
2810// TargetInstrInfo::commuteInstruction uses it.
2812 unsigned &SrcOpIdx0,
2813 unsigned &SrcOpIdx1) const {
2814 return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
2815}
2816
2818 unsigned &SrcOpIdx0,
2819 unsigned &SrcOpIdx1) const {
2820 if (!Desc.isCommutable())
2821 return false;
2822
2823 unsigned Opc = Desc.getOpcode();
2824 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
2825 if (Src0Idx == -1)
2826 return false;
2827
2828 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
2829 if (Src1Idx == -1)
2830 return false;
2831
2832 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
2833}
2834
2836 int64_t BrOffset) const {
2837 // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
2838 // because its dest block is unanalyzable.
2839 assert(isSOPP(BranchOp) || isSOPK(BranchOp));
2840
2841 // Convert to dwords.
2842 BrOffset /= 4;
2843
2844 // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
2845 // from the next instruction.
2846 BrOffset -= 1;
2847
2848 return isIntN(BranchOffsetBits, BrOffset);
2849}
2850
2853 return MI.getOperand(0).getMBB();
2854}
2855
2857 for (const MachineInstr &MI : MBB->terminators()) {
2858 if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
2859 MI.getOpcode() == AMDGPU::SI_LOOP)
2860 return true;
2861 }
2862 return false;
2863}
2864
2866 MachineBasicBlock &DestBB,
2867 MachineBasicBlock &RestoreBB,
2868 const DebugLoc &DL, int64_t BrOffset,
2869 RegScavenger *RS) const {
2870 assert(MBB.empty() &&
2871 "new block should be inserted for expanding unconditional branch");
2872 assert(MBB.pred_size() == 1);
2873 assert(RestoreBB.empty() &&
2874 "restore block should be inserted for restoring clobbered registers");
2875
2876 MachineFunction *MF = MBB.getParent();
2877 MachineRegisterInfo &MRI = MF->getRegInfo();
2879 auto I = MBB.end();
2880 auto &MCCtx = MF->getContext();
2881
2882 if (ST.useAddPC64Inst()) {
2883 MCSymbol *Offset =
2884 MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
2885 auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
2887 MCSymbol *PostAddPCLabel =
2888 MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
2889 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
2890 auto *OffsetExpr = MCBinaryExpr::createSub(
2891 MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
2892 MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
2893 Offset->setVariableValue(OffsetExpr);
2894 return;
2895 }
2896
2897 assert(RS && "RegScavenger required for long branching");
2898
2899 // FIXME: Virtual register workaround for RegScavenger not working with empty
2900 // blocks.
2901 Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
2902
2903 // Note: as this is used after hazard recognizer we need to apply some hazard
2904 // workarounds directly.
2905 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
2906 ST.hasVALUReadSGPRHazard();
2907 auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
2908 if (FlushSGPRWrites)
2909 BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
2911 };
2912
2913 // We need to compute the offset relative to the instruction immediately after
2914 // s_getpc_b64. Insert pc arithmetic code before last terminator.
2915 MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
2916 ApplyHazardWorkarounds();
2917
2918 MCSymbol *PostGetPCLabel =
2919 MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
2920 GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);
2921
2922 MCSymbol *OffsetLo =
2923 MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
2924 MCSymbol *OffsetHi =
2925 MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
2926 BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
2927 .addReg(PCReg, RegState::Define, AMDGPU::sub0)
2928 .addReg(PCReg, {}, AMDGPU::sub0)
2929 .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
2930 BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
2931 .addReg(PCReg, RegState::Define, AMDGPU::sub1)
2932 .addReg(PCReg, {}, AMDGPU::sub1)
2933 .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
2934 ApplyHazardWorkarounds();
2935
2936 // Insert the indirect branch after the other terminator.
2937 BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
2938 .addReg(PCReg);
2939
2940 // If a spill is needed for the pc register pair, we need to insert a spill
2941 // restore block right before the destination block, and insert a short branch
2942 // into the old destination block's fallthrough predecessor.
2943 // e.g.:
2944 //
2945 // s_cbranch_scc0 skip_long_branch:
2946 //
2947 // long_branch_bb:
2948 // spill s[8:9]
2949 // s_getpc_b64 s[8:9]
2950 // s_add_u32 s8, s8, restore_bb
2951 // s_addc_u32 s9, s9, 0
2952 // s_setpc_b64 s[8:9]
2953 //
2954 // skip_long_branch:
2955 // foo;
2956 //
2957 // .....
2958 //
2959 // dest_bb_fallthrough_predecessor:
2960 // bar;
2961 // s_branch dest_bb
2962 //
2963 // restore_bb:
2964 // restore s[8:9]
2965 // fallthrough dest_bb
2966 ///
2967 // dest_bb:
2968 // buzz;
2969
2970 Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
2971 Register Scav;
2972
2973 // If we've previously reserved a register for long branches
2974 // avoid running the scavenger and just use those registers
2975 if (LongBranchReservedReg) {
2976 RS->enterBasicBlock(MBB);
2977 Scav = LongBranchReservedReg;
2978 } else {
2979 RS->enterBasicBlockEnd(MBB);
2980 Scav = RS->scavengeRegisterBackwards(
2981 AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
2982 /* RestoreAfter */ false, 0, /* AllowSpill */ false);
2983 }
2984 if (Scav) {
2985 RS->setRegUsed(Scav);
2986 MRI.replaceRegWith(PCReg, Scav);
2987 MRI.clearVirtRegs();
2988 } else {
2989 // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
2990 // SGPR spill.
2991 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
2992 const SIRegisterInfo *TRI = ST.getRegisterInfo();
2993 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
2994 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
2995 MRI.clearVirtRegs();
2996 }
2997
2998 MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
2999 // Now, the distance could be defined.
3001 MCSymbolRefExpr::create(DestLabel, MCCtx),
3002 MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
3003 // Add offset assignments.
3004 auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
3005 OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
3006 auto *ShAmt = MCConstantExpr::create(32, MCCtx);
3007 OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
3008}
3009
3010unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
3011 switch (Cond) {
3012 case SIInstrInfo::SCC_TRUE:
3013 return AMDGPU::S_CBRANCH_SCC1;
3014 case SIInstrInfo::SCC_FALSE:
3015 return AMDGPU::S_CBRANCH_SCC0;
3016 case SIInstrInfo::VCCNZ:
3017 return AMDGPU::S_CBRANCH_VCCNZ;
3018 case SIInstrInfo::VCCZ:
3019 return AMDGPU::S_CBRANCH_VCCZ;
3020 case SIInstrInfo::EXECNZ:
3021 return AMDGPU::S_CBRANCH_EXECNZ;
3022 case SIInstrInfo::EXECZ:
3023 return AMDGPU::S_CBRANCH_EXECZ;
3024 default:
3025 llvm_unreachable("invalid branch predicate");
3026 }
3027}
3028
3029SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
3030 switch (Opcode) {
3031 case AMDGPU::S_CBRANCH_SCC0:
3032 return SCC_FALSE;
3033 case AMDGPU::S_CBRANCH_SCC1:
3034 return SCC_TRUE;
3035 case AMDGPU::S_CBRANCH_VCCNZ:
3036 return VCCNZ;
3037 case AMDGPU::S_CBRANCH_VCCZ:
3038 return VCCZ;
3039 case AMDGPU::S_CBRANCH_EXECNZ:
3040 return EXECNZ;
3041 case AMDGPU::S_CBRANCH_EXECZ:
3042 return EXECZ;
3043 default:
3044 return INVALID_BR;
3045 }
3046}
3047
3051 MachineBasicBlock *&FBB,
3053 bool AllowModify) const {
3054 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3055 // Unconditional Branch
3056 TBB = I->getOperand(0).getMBB();
3057 return false;
3058 }
3059
3060 BranchPredicate Pred = getBranchPredicate(I->getOpcode());
3061 if (Pred == INVALID_BR)
3062 return true;
3063
3064 MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
3065 Cond.push_back(MachineOperand::CreateImm(Pred));
3066 Cond.push_back(I->getOperand(1)); // Save the branch register.
3067
3068 ++I;
3069
3070 if (I == MBB.end()) {
3071 // Conditional branch followed by fall-through.
3072 TBB = CondBB;
3073 return false;
3074 }
3075
3076 if (I->getOpcode() == AMDGPU::S_BRANCH) {
3077 TBB = CondBB;
3078 FBB = I->getOperand(0).getMBB();
3079 return false;
3080 }
3081
3082 return true;
3083}
3084
3086 MachineBasicBlock *&FBB,
3088 bool AllowModify) const {
3089 MachineBasicBlock::iterator I = MBB.getFirstTerminator();
3090 auto E = MBB.end();
3091 if (I == E)
3092 return false;
3093
3094 // Skip over the instructions that are artificially terminators for special
3095 // exec management.
3096 while (I != E && !I->isBranch() && !I->isReturn()) {
3097 switch (I->getOpcode()) {
3098 case AMDGPU::S_MOV_B64_term:
3099 case AMDGPU::S_XOR_B64_term:
3100 case AMDGPU::S_OR_B64_term:
3101 case AMDGPU::S_ANDN2_B64_term:
3102 case AMDGPU::S_AND_B64_term:
3103 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3104 case AMDGPU::S_MOV_B32_term:
3105 case AMDGPU::S_XOR_B32_term:
3106 case AMDGPU::S_OR_B32_term:
3107 case AMDGPU::S_ANDN2_B32_term:
3108 case AMDGPU::S_AND_B32_term:
3109 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3110 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3111 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3112 break;
3113 case AMDGPU::SI_IF:
3114 case AMDGPU::SI_ELSE:
3115 case AMDGPU::SI_KILL_I1_TERMINATOR:
3116 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3117 // FIXME: It's messy that these need to be considered here at all.
3118 return true;
3119 default:
3120 llvm_unreachable("unexpected non-branch terminator inst");
3121 }
3122
3123 ++I;
3124 }
3125
3126 if (I == E)
3127 return false;
3128
3129 return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
3130}
3131
3133 int *BytesRemoved) const {
3134 unsigned Count = 0;
3135 unsigned RemovedSize = 0;
3136 for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
3137 // Skip over artificial terminators when removing instructions.
3138 if (MI.isBranch() || MI.isReturn()) {
3139 RemovedSize += getInstSizeInBytes(MI);
3140 MI.eraseFromParent();
3141 ++Count;
3142 }
3143 }
3144
3145 if (BytesRemoved)
3146 *BytesRemoved = RemovedSize;
3147
3148 return Count;
3149}
3150
3151// Copy the flags onto the implicit condition register operand.
3153 const MachineOperand &OrigCond) {
3154 CondReg.setIsUndef(OrigCond.isUndef());
3155 CondReg.setIsKill(OrigCond.isKill());
3156}
3157
3160 MachineBasicBlock *FBB,
3162 const DebugLoc &DL,
3163 int *BytesAdded) const {
3164 if (!FBB && Cond.empty()) {
3165 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3166 .addMBB(TBB);
3167 if (BytesAdded)
3168 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3169 return 1;
3170 }
3171
3172 assert(TBB && Cond[0].isImm());
3173
3174 unsigned Opcode
3175 = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));
3176
3177 if (!FBB) {
3178 MachineInstr *CondBr =
3179 BuildMI(&MBB, DL, get(Opcode))
3180 .addMBB(TBB);
3181
3182 // Copy the flags onto the implicit condition register operand.
3183 preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
3184 fixImplicitOperands(*CondBr);
3185
3186 if (BytesAdded)
3187 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3188 return 1;
3189 }
3190
3191 assert(TBB && FBB);
3192
3193 MachineInstr *CondBr =
3194 BuildMI(&MBB, DL, get(Opcode))
3195 .addMBB(TBB);
3196 fixImplicitOperands(*CondBr);
3197 BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
3198 .addMBB(FBB);
3199
3200 MachineOperand &CondReg = CondBr->getOperand(1);
3201 CondReg.setIsUndef(Cond[1].isUndef());
3202 CondReg.setIsKill(Cond[1].isKill());
3203
3204 if (BytesAdded)
3205 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3206
3207 return 2;
3208}
3209
3212 if (Cond.size() != 2) {
3213 return true;
3214 }
3215
3216 if (Cond[0].isImm()) {
3217 Cond[0].setImm(-Cond[0].getImm());
3218 return false;
3219 }
3220
3221 return true;
3222}
3223
3226 Register DstReg, Register TrueReg,
3227 Register FalseReg, int &CondCycles,
3228 int &TrueCycles, int &FalseCycles) const {
3229 switch (Cond[0].getImm()) {
3230 case VCCNZ:
3231 case VCCZ: {
3232 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3233 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3234 if (MRI.getRegClass(FalseReg) != RC)
3235 return false;
3236
3237 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3238 CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
3239
3240 // Limit to equal cost for branch vs. N v_cndmask_b32s.
3241 return RI.hasVGPRs(RC) && NumInsts <= 6;
3242 }
3243 case SCC_TRUE:
3244 case SCC_FALSE: {
3245 // FIXME: We could insert for VGPRs if we could replace the original compare
3246 // with a vector one.
3247 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3248 const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
3249 if (MRI.getRegClass(FalseReg) != RC)
3250 return false;
3251
3252 int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
3253
3254 // Multiples of 8 can do s_cselect_b64
3255 if (NumInsts % 2 == 0)
3256 NumInsts /= 2;
3257
3258 CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
3259 return RI.isSGPRClass(RC);
3260 }
3261 default:
3262 return false;
3263 }
3264}
3265
3269 Register TrueReg, Register FalseReg) const {
3270 BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
3271 if (Pred == VCCZ || Pred == SCC_FALSE) {
3272 Pred = static_cast<BranchPredicate>(-Pred);
3273 std::swap(TrueReg, FalseReg);
3274 }
3275
3276 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
3277 const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
3278 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3279
3280 if (DstSize == 32) {
3282 if (Pred == SCC_TRUE) {
3283 Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
3284 .addReg(TrueReg)
3285 .addReg(FalseReg);
3286 } else {
3287 // Instruction's operands are backwards from what is expected.
3288 Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
3289 .addReg(FalseReg)
3290 .addReg(TrueReg);
3291 }
3292
3293 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3294 return;
3295 }
3296
3297 if (DstSize == 64 && Pred == SCC_TRUE) {
3299 BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
3300 .addReg(TrueReg)
3301 .addReg(FalseReg);
3302
3303 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3304 return;
3305 }
3306
3307 static const int16_t Sub0_15[] = {
3308 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3309 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3310 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3311 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3312 };
3313
3314 static const int16_t Sub0_15_64[] = {
3315 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3316 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3317 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3318 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3319 };
3320
3321 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3322 const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
3323 const int16_t *SubIndices = Sub0_15;
3324 int NElts = DstSize / 32;
3325
3326 // 64-bit select is only available for SALU.
3327 // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
3328 if (Pred == SCC_TRUE) {
3329 if (NElts % 2) {
3330 SelOp = AMDGPU::S_CSELECT_B32;
3331 EltRC = &AMDGPU::SGPR_32RegClass;
3332 } else {
3333 SelOp = AMDGPU::S_CSELECT_B64;
3334 EltRC = &AMDGPU::SGPR_64RegClass;
3335 SubIndices = Sub0_15_64;
3336 NElts /= 2;
3337 }
3338 }
3339
3341 MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);
3342
3343 I = MIB->getIterator();
3344
3346 for (int Idx = 0; Idx != NElts; ++Idx) {
3347 Register DstElt = MRI.createVirtualRegister(EltRC);
3348 Regs.push_back(DstElt);
3349
3350 unsigned SubIdx = SubIndices[Idx];
3351
3353 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3354 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3355 .addReg(FalseReg, {}, SubIdx)
3356 .addReg(TrueReg, {}, SubIdx);
3357 } else {
3358 Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
3359 .addReg(TrueReg, {}, SubIdx)
3360 .addReg(FalseReg, {}, SubIdx);
3361 }
3362
3363 preserveCondRegFlags(Select->getOperand(3), Cond[1]);
3365
3366 MIB.addReg(DstElt)
3367 .addImm(SubIdx);
3368 }
3369}
3370
3372
3373 if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
3374 return true;
3375
3376 switch (MI.getOpcode()) {
3377 case AMDGPU::S_ENDPGM:
3378 case AMDGPU::S_ENDPGM_SAVED:
3379 case AMDGPU::S_TRAP:
3380 case AMDGPU::S_GETREG_B32:
3381 case AMDGPU::S_SETREG_B32:
3382 case AMDGPU::S_SETREG_B32_mode:
3383 case AMDGPU::S_SETREG_IMM32_B32:
3384 case AMDGPU::S_SETREG_IMM32_B32_mode:
3385 case AMDGPU::S_SENDMSG:
3386 case AMDGPU::S_SENDMSGHALT:
3387 case AMDGPU::S_SENDMSG_RTN_B32:
3388 case AMDGPU::S_SENDMSG_RTN_B64:
3389 case AMDGPU::S_BARRIER_WAIT:
3390 case AMDGPU::S_BARRIER_SIGNAL_M0:
3391 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3392 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3393 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3394 return true;
3395 default:
3396 return false;
3397 }
3398}
3399
3401 switch (MI.getOpcode()) {
3402 case AMDGPU::V_MOV_B16_t16_e32:
3403 case AMDGPU::V_MOV_B16_t16_e64:
3404 case AMDGPU::V_MOV_B32_e32:
3405 case AMDGPU::V_MOV_B32_e64:
3406 case AMDGPU::V_MOV_B64_PSEUDO:
3407 case AMDGPU::V_MOV_B64_e32:
3408 case AMDGPU::V_MOV_B64_e64:
3409 case AMDGPU::S_MOV_B32:
3410 case AMDGPU::S_MOV_B64:
3411 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3412 case AMDGPU::COPY:
3413 case AMDGPU::WWM_COPY:
3414 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3415 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3416 case AMDGPU::V_ACCVGPR_MOV_B32:
3417 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3418 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3419 return true;
3420 default:
3421 return false;
3422 }
3423}
3424
3426 switch (MI.getOpcode()) {
3427 case AMDGPU::V_MOV_B16_t16_e32:
3428 case AMDGPU::V_MOV_B16_t16_e64:
3429 return 2;
3430 case AMDGPU::V_MOV_B32_e32:
3431 case AMDGPU::V_MOV_B32_e64:
3432 case AMDGPU::V_MOV_B64_PSEUDO:
3433 case AMDGPU::V_MOV_B64_e32:
3434 case AMDGPU::V_MOV_B64_e64:
3435 case AMDGPU::S_MOV_B32:
3436 case AMDGPU::S_MOV_B64:
3437 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3438 case AMDGPU::COPY:
3439 case AMDGPU::WWM_COPY:
3440 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3441 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3442 case AMDGPU::V_ACCVGPR_MOV_B32:
3443 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3444 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3445 return 1;
3446 default:
3447 llvm_unreachable("MI is not a foldable copy");
3448 }
3449}
3450
3451static constexpr AMDGPU::OpName ModifierOpNames[] = {
3452 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3453 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3454 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3455
3457 unsigned Opc = MI.getOpcode();
3458 for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
3459 int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
3460 if (Idx >= 0)
3461 MI.removeOperand(Idx);
3462 }
3463}
3464
3466 const MCInstrDesc &NewDesc) const {
3467 MI.setDesc(NewDesc);
3468
3469 // Remove any leftover implicit operands from mutating the instruction. e.g.
3470 // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
3471 // anymore.
3472 const MCInstrDesc &Desc = MI.getDesc();
3473 unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
3474 Desc.implicit_defs().size();
3475
3476 for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
3477 MI.removeOperand(I);
3478}
3479
3480std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
3481 unsigned SubRegIndex) {
3482 switch (SubRegIndex) {
3483 case AMDGPU::NoSubRegister:
3484 return Imm;
3485 case AMDGPU::sub0:
3486 return SignExtend64<32>(Imm);
3487 case AMDGPU::sub1:
3488 return SignExtend64<32>(Imm >> 32);
3489 case AMDGPU::lo16:
3490 return SignExtend64<16>(Imm);
3491 case AMDGPU::hi16:
3492 return SignExtend64<16>(Imm >> 16);
3493 case AMDGPU::sub1_lo16:
3494 return SignExtend64<16>(Imm >> 32);
3495 case AMDGPU::sub1_hi16:
3496 return SignExtend64<16>(Imm >> 48);
3497 default:
3498 return std::nullopt;
3499 }
3500
3501 llvm_unreachable("covered subregister switch");
3502}
3503
3504static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
3505 switch (Opc) {
3506 case AMDGPU::V_MAC_F16_e32:
3507 case AMDGPU::V_MAC_F16_e64:
3508 case AMDGPU::V_MAD_F16_e64:
3509 return AMDGPU::V_MADAK_F16;
3510 case AMDGPU::V_MAC_F32_e32:
3511 case AMDGPU::V_MAC_F32_e64:
3512 case AMDGPU::V_MAD_F32_e64:
3513 return AMDGPU::V_MADAK_F32;
3514 case AMDGPU::V_FMAC_F32_e32:
3515 case AMDGPU::V_FMAC_F32_e64:
3516 case AMDGPU::V_FMA_F32_e64:
3517 return AMDGPU::V_FMAAK_F32;
3518 case AMDGPU::V_FMAC_F16_e32:
3519 case AMDGPU::V_FMAC_F16_e64:
3520 case AMDGPU::V_FMAC_F16_t16_e64:
3521 case AMDGPU::V_FMAC_F16_fake16_e64:
3522 case AMDGPU::V_FMAC_F16_t16_e32:
3523 case AMDGPU::V_FMAC_F16_fake16_e32:
3524 case AMDGPU::V_FMA_F16_e64:
3525 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3526 ? AMDGPU::V_FMAAK_F16_t16
3527 : AMDGPU::V_FMAAK_F16_fake16
3528 : AMDGPU::V_FMAAK_F16;
3529 case AMDGPU::V_FMAC_F64_e32:
3530 case AMDGPU::V_FMAC_F64_e64:
3531 case AMDGPU::V_FMA_F64_e64:
3532 return AMDGPU::V_FMAAK_F64;
3533 default:
3534 llvm_unreachable("invalid instruction");
3535 }
3536}
3537
3538static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
3539 switch (Opc) {
3540 case AMDGPU::V_MAC_F16_e32:
3541 case AMDGPU::V_MAC_F16_e64:
3542 case AMDGPU::V_MAD_F16_e64:
3543 return AMDGPU::V_MADMK_F16;
3544 case AMDGPU::V_MAC_F32_e32:
3545 case AMDGPU::V_MAC_F32_e64:
3546 case AMDGPU::V_MAD_F32_e64:
3547 return AMDGPU::V_MADMK_F32;
3548 case AMDGPU::V_FMAC_F32_e32:
3549 case AMDGPU::V_FMAC_F32_e64:
3550 case AMDGPU::V_FMA_F32_e64:
3551 return AMDGPU::V_FMAMK_F32;
3552 case AMDGPU::V_FMAC_F16_e32:
3553 case AMDGPU::V_FMAC_F16_e64:
3554 case AMDGPU::V_FMAC_F16_t16_e64:
3555 case AMDGPU::V_FMAC_F16_fake16_e64:
3556 case AMDGPU::V_FMAC_F16_t16_e32:
3557 case AMDGPU::V_FMAC_F16_fake16_e32:
3558 case AMDGPU::V_FMA_F16_e64:
3559 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3560 ? AMDGPU::V_FMAMK_F16_t16
3561 : AMDGPU::V_FMAMK_F16_fake16
3562 : AMDGPU::V_FMAMK_F16;
3563 case AMDGPU::V_FMAC_F64_e32:
3564 case AMDGPU::V_FMAC_F64_e64:
3565 case AMDGPU::V_FMA_F64_e64:
3566 return AMDGPU::V_FMAMK_F64;
3567 default:
3568 llvm_unreachable("invalid instruction");
3569 }
3570}
3571
3573 Register Reg, MachineRegisterInfo *MRI) const {
3574 int64_t Imm;
3575 if (!getConstValDefinedInReg(DefMI, Reg, Imm))
3576 return false;
3577
3578 const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);
3579
3580 assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");
3581
3582 unsigned Opc = UseMI.getOpcode();
3583 if (Opc == AMDGPU::COPY) {
3584 assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");
3585
3586 Register DstReg = UseMI.getOperand(0).getReg();
3587 Register UseSubReg = UseMI.getOperand(1).getSubReg();
3588
3589 const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);
3590
3591 if (HasMultipleUses) {
3592 // TODO: This should fold in more cases with multiple use, but we need to
3593 // more carefully consider what those uses are.
3594 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));
3595
3596 // Avoid breaking up a 64-bit inline immediate into a subregister extract.
3597 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3598 return false;
3599
3600 // Most of the time folding a 32-bit inline constant is free (though this
3601 // might not be true if we can't later fold it into a real user).
3602 //
3603 // FIXME: This isInlineConstant check is imprecise if
3604 // getConstValDefinedInReg handled the tricky non-mov cases.
3605 if (ImmDefSize == 32 &&
3607 return false;
3608 }
3609
3610 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3611 RI.getSubRegIdxSize(UseSubReg) == 16;
3612
3613 if (Is16Bit) {
3614 if (RI.hasVGPRs(DstRC))
3615 return false; // Do not clobber vgpr_hi16
3616
3617 if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
3618 return false;
3619 }
3620
3621 MachineFunction *MF = UseMI.getMF();
3622
3623 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3624 MCRegister MovDstPhysReg =
3625 DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();
3626
3627 std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);
3628
3629 // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
3630 for (unsigned MovOp :
3631 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3632 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3633 const MCInstrDesc &MovDesc = get(MovOp);
3634
3635 const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
3636 if (Is16Bit) {
3637 // We just need to find a correctly sized register class, so the
3638 // subregister index compatibility doesn't matter since we're statically
3639 // extracting the immediate value.
3640 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3641 if (!MovDstRC)
3642 continue;
3643
3644 if (MovDstPhysReg) {
3645 // FIXME: We probably should not do this. If there is a live value in
3646 // the high half of the register, it will be corrupted.
3647 MovDstPhysReg =
3648 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3649 if (!MovDstPhysReg)
3650 continue;
3651 }
3652 }
3653
3654 // Result class isn't the right size, try the next instruction.
3655 if (MovDstPhysReg) {
3656 if (!MovDstRC->contains(MovDstPhysReg))
3657 return false;
3658 } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
3659 // TODO: This will be overly conservative in the case of 16-bit virtual
3660 // SGPRs. We could hack up the virtual register uses to use a compatible
3661 // 32-bit class.
3662 continue;
3663 }
3664
3665 const MCOperandInfo &OpInfo = MovDesc.operands()[1];
3666
3667 // Ensure the interpreted immediate value is a valid operand in the new
3668 // mov.
3669 //
3670 // FIXME: isImmOperandLegal should have form that doesn't require existing
3671 // MachineInstr or MachineOperand
3672 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3673 !isInlineConstant(*SubRegImm, OpInfo.OperandType))
3674 break;
3675
3676 NewOpc = MovOp;
3677 break;
3678 }
3679
3680 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
3681 return false;
3682
3683 if (Is16Bit) {
3684 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
3685 if (MovDstPhysReg)
3686 UseMI.getOperand(0).setReg(MovDstPhysReg);
3687 assert(UseMI.getOperand(1).getReg().isVirtual());
3688 }
3689
3690 const MCInstrDesc &NewMCID = get(NewOpc);
3691 UseMI.setDesc(NewMCID);
3692 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
3693 UseMI.addImplicitDefUseOperands(*MF);
3694 return true;
3695 }
3696
3697 if (HasMultipleUses)
3698 return false;
3699
3700 if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
3701 Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
3702 Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
3703 Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
3704 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3705 Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
3706 Opc == AMDGPU::V_FMAC_F64_e64) {
3707 // Don't fold if we are using source or output modifiers. The new VOP2
3708 // instructions don't have them.
3710 return false;
3711
3712 // If this is a free constant, there's no reason to do this.
3713 // TODO: We could fold this here instead of letting SIFoldOperands do it
3714 // later.
3715 int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);
3716
3717 // Any src operand can be used for the legality check.
3718 if (isInlineConstant(UseMI, Src0Idx, Imm))
3719 return false;
3720
3721 MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);
3722
3723 MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
3724 MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);
3725
3726 auto CopyRegOperandToNarrowerRC =
3727 [MRI, this](MachineInstr &MI, unsigned OpNo,
3728 const TargetRegisterClass *NewRC) -> void {
3729 if (!MI.getOperand(OpNo).isReg())
3730 return;
3731 Register Reg = MI.getOperand(OpNo).getReg();
3732 const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
3733 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
3734 return;
3735 Register Tmp = MRI->createVirtualRegister(NewRC);
3736 BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
3737 get(AMDGPU::COPY), Tmp)
3738 .addReg(Reg);
3739 MI.getOperand(OpNo).setReg(Tmp);
3740 MI.getOperand(OpNo).setIsKill();
3741 };
3742
3743 // Multiplied part is the constant: Use v_madmk_{f16, f32}.
3744 if ((Src0->isReg() && Src0->getReg() == Reg) ||
3745 (Src1->isReg() && Src1->getReg() == Reg)) {
3746 MachineOperand *RegSrc =
3747 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
3748 if (!RegSrc->isReg())
3749 return false;
3750 if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
3751 ST.getConstantBusLimit(Opc) < 2)
3752 return false;
3753
3754 if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
3755 return false;
3756
3757 // If src2 is also a literal constant then we have to choose which one to
3758 // fold. In general it is better to choose madak so that the other literal
3759 // can be materialized in an sgpr instead of a vgpr:
3760 // s_mov_b32 s0, literal
3761 // v_madak_f32 v0, s0, v0, literal
3762 // Instead of:
3763 // v_mov_b32 v1, literal
3764 // v_madmk_f32 v0, v0, literal, v1
3765 MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
3766 if (Def && Def->isMoveImmediate() &&
3767 !isInlineConstant(Def->getOperand(1)))
3768 return false;
3769
3770 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
3771 if (pseudoToMCOpcode(NewOpc) == -1)
3772 return false;
3773
3774 const std::optional<int64_t> SubRegImm = extractSubregFromImm(
3775 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
3776
3777 // FIXME: This would be a lot easier if we could return a new instruction
3778 // instead of having to modify in place.
3779
3780 Register SrcReg = RegSrc->getReg();
3781 unsigned SrcSubReg = RegSrc->getSubReg();
3782 Src0->setReg(SrcReg);
3783 Src0->setSubReg(SrcSubReg);
3784 Src0->setIsKill(RegSrc->isKill());
3785
3786 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
3787 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3788 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3789 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
3790 UseMI.untieRegOperand(
3791 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
3792
3793 Src1->ChangeToImmediate(*SubRegImm);
3794
3796 UseMI.setDesc(get(NewOpc));
3797
3798 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
3799 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
3800 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
3801 Register Tmp = MRI->createVirtualRegister(NewRC);
3802 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
3803 UseMI.getDebugLoc(), get(AMDGPU::COPY),
3804 UseMI.getOperand(0).getReg())
3805 .addReg(Tmp, RegState::Kill);
3806 UseMI.getOperand(0).setReg(Tmp);
3807 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
3808 CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
3809 }
3810
3811 bool DeleteDef = MRI->use_nodbg_empty(Reg);
3812 if (DeleteDef)
3813 DefMI.eraseFromParent();
3814
3815 return true;
3816 }
3817
3818 // Added part is the constant: Use v_madak_{f16, f32}.
3819 if (Src2->isReg() && Src2->getReg() == Reg) {
3820 if (ST.getConstantBusLimit(Opc) < 2) {
3821 // Not allowed to use constant bus for another operand.
3822 // We can however allow an inline immediate as src0.
3823 bool Src0Inlined = false;
3824 if (Src0->isReg()) {
3825 // Try to inline constant if possible.
3826 // If the Def moves immediate and the use is single
3827 // We are saving VGPR here.
3828 MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
3829 if (Def && Def->isMoveImmediate() &&
3830 isInlineConstant(Def->getOperand(1)) &&
3831 MRI->hasOneNonDBGUse(Src0->getReg())) {
3832 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
3833 Src0Inlined = true;
3834 } else if (ST.getConstantBusLimit(Opc) <= 1 &&
3835 RI.isSGPRReg(*MRI, Src0->getReg())) {
3836 return false;
3837 }
3838 // VGPR is okay as Src0 - fallthrough
3839 }
3840
3841 if (Src1->isReg() && !Src0Inlined) {
3842 // We have one slot for inlinable constant so far - try to fill it
3843 MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
3844 if (Def && Def->isMoveImmediate() &&
3845 isInlineConstant(Def->getOperand(1)) &&
3846 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
3847 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
3848 else if (RI.isSGPRReg(*MRI, Src1->getReg()))
3849 return false;
3850 // VGPR is okay as Src1 - fallthrough
3851 }
3852 }
3853
3854 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
3855 if (pseudoToMCOpcode(NewOpc) == -1)
3856 return false;
3857
3858 // FIXME: This would be a lot easier if we could return a new instruction
3859 // instead of having to modify in place.
3860
3861 if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
3862 Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3863 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
3864 Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
3865 UseMI.untieRegOperand(
3866 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));
3867
3868 const std::optional<int64_t> SubRegImm =
3869 extractSubregFromImm(Imm, Src2->getSubReg());
3870
3871 // ChangingToImmediate adds Src2 back to the instruction.
3872 Src2->ChangeToImmediate(*SubRegImm);
3873
3874 // These come before src2.
3876 UseMI.setDesc(get(NewOpc));
3877
3878 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
3879 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
3880 const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
3881 Register Tmp = MRI->createVirtualRegister(NewRC);
3882 BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
3883 UseMI.getDebugLoc(), get(AMDGPU::COPY),
3884 UseMI.getOperand(0).getReg())
3885 .addReg(Tmp, RegState::Kill);
3886 UseMI.getOperand(0).setReg(Tmp);
3887 CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
3888 CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
3889 }
3890
3891 // It might happen that UseMI was commuted
3892 // and we now have SGPR as SRC1. If so 2 inlined
3893 // constant and SGPR are illegal.
3895
3896 bool DeleteDef = MRI->use_nodbg_empty(Reg);
3897 if (DeleteDef)
3898 DefMI.eraseFromParent();
3899
3900 return true;
3901 }
3902 }
3903
3904 return false;
3905}
3906
3907static bool
3910 if (BaseOps1.size() != BaseOps2.size())
3911 return false;
3912 for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
3913 if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
3914 return false;
3915 }
3916 return true;
3917}
3918
3919static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
3920 LocationSize WidthB, int OffsetB) {
3921 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
3922 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
3923 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
3924 return LowWidth.hasValue() &&
3925 LowOffset + (int)LowWidth.getValue() <= HighOffset;
3926}
3927
3928bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
3929 const MachineInstr &MIb) const {
3930 SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
3931 int64_t Offset0, Offset1;
3932 LocationSize Dummy0 = LocationSize::precise(0);
3933 LocationSize Dummy1 = LocationSize::precise(0);
3934 bool Offset0IsScalable, Offset1IsScalable;
3935 if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
3936 Dummy0, &RI) ||
3937 !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
3938 Dummy1, &RI))
3939 return false;
3940
3941 if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
3942 return false;
3943
3944 if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
3945 // FIXME: Handle ds_read2 / ds_write2.
3946 return false;
3947 }
3948 LocationSize Width0 = MIa.memoperands().front()->getSize();
3949 LocationSize Width1 = MIb.memoperands().front()->getSize();
3950 return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
3951}
3952
3954 const MachineInstr &MIb) const {
3955 assert(MIa.mayLoadOrStore() &&
3956 "MIa must load from or modify a memory location");
3957 assert(MIb.mayLoadOrStore() &&
3958 "MIb must load from or modify a memory location");
3959
3961 return false;
3962
3963 // XXX - Can we relax this between address spaces?
3964 if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
3965 return false;
3966
3967 if (isLDSDMA(MIa) || isLDSDMA(MIb))
3968 return false;
3969
3970 if (MIa.isBundle() || MIb.isBundle())
3971 return false;
3972
3973 // TODO: Should we check the address space from the MachineMemOperand? That
3974 // would allow us to distinguish objects we know don't alias based on the
3975 // underlying address space, even if it was lowered to a different one,
3976 // e.g. private accesses lowered to use MUBUF instructions on a scratch
3977 // buffer.
3978 if (isDS(MIa)) {
3979 if (isDS(MIb))
3980 return checkInstOffsetsDoNotOverlap(MIa, MIb);
3981
3982 return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
3983 }
3984
3985 if (isMUBUF(MIa) || isMTBUF(MIa)) {
3986 if (isMUBUF(MIb) || isMTBUF(MIb))
3987 return checkInstOffsetsDoNotOverlap(MIa, MIb);
3988
3989 if (isFLAT(MIb))
3990 return isFLATScratch(MIb);
3991
3992 return !isSMRD(MIb);
3993 }
3994
3995 if (isSMRD(MIa)) {
3996 if (isSMRD(MIb))
3997 return checkInstOffsetsDoNotOverlap(MIa, MIb);
3998
3999 if (isFLAT(MIb))
4000 return isFLATScratch(MIb);
4001
4002 return !isMUBUF(MIb) && !isMTBUF(MIb);
4003 }
4004
4005 if (isFLAT(MIa)) {
4006 if (isFLAT(MIb)) {
4007 if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
4008 (isFLATGlobal(MIa) && isFLATScratch(MIb)))
4009 return true;
4010
4011 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4012 }
4013
4014 return false;
4015 }
4016
4017 return false;
4018}
4019
4021 int64_t &Imm, MachineInstr **DefMI = nullptr) {
4022 if (Reg.isPhysical())
4023 return false;
4024 auto *Def = MRI.getUniqueVRegDef(Reg);
4025 if (Def && SIInstrInfo::isFoldableCopy(*Def) && Def->getOperand(1).isImm()) {
4026 Imm = Def->getOperand(1).getImm();
4027 if (DefMI)
4028 *DefMI = Def;
4029 return true;
4030 }
4031 return false;
4032}
4033
4034static bool getFoldableImm(const MachineOperand *MO, int64_t &Imm,
4035 MachineInstr **DefMI = nullptr) {
4036 if (!MO->isReg())
4037 return false;
4038 const MachineFunction *MF = MO->getParent()->getMF();
4039 const MachineRegisterInfo &MRI = MF->getRegInfo();
4040 return getFoldableImm(MO->getReg(), MRI, Imm, DefMI);
4041}
4042
4044 MachineInstr &NewMI) {
4045 if (LV) {
4046 unsigned NumOps = MI.getNumOperands();
4047 for (unsigned I = 1; I < NumOps; ++I) {
4048 MachineOperand &Op = MI.getOperand(I);
4049 if (Op.isReg() && Op.isKill())
4050 LV->replaceKillInstruction(Op.getReg(), MI, NewMI);
4051 }
4052 }
4053}
4054
4055static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
4056 switch (Opc) {
4057 case AMDGPU::V_MAC_F16_e32:
4058 case AMDGPU::V_MAC_F16_e64:
4059 return AMDGPU::V_MAD_F16_e64;
4060 case AMDGPU::V_MAC_F32_e32:
4061 case AMDGPU::V_MAC_F32_e64:
4062 return AMDGPU::V_MAD_F32_e64;
4063 case AMDGPU::V_MAC_LEGACY_F32_e32:
4064 case AMDGPU::V_MAC_LEGACY_F32_e64:
4065 return AMDGPU::V_MAD_LEGACY_F32_e64;
4066 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4067 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4068 return AMDGPU::V_FMA_LEGACY_F32_e64;
4069 case AMDGPU::V_FMAC_F16_e32:
4070 case AMDGPU::V_FMAC_F16_e64:
4071 case AMDGPU::V_FMAC_F16_t16_e64:
4072 case AMDGPU::V_FMAC_F16_fake16_e64:
4073 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4074 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4075 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4076 : AMDGPU::V_FMA_F16_gfx9_e64;
4077 case AMDGPU::V_FMAC_F32_e32:
4078 case AMDGPU::V_FMAC_F32_e64:
4079 return AMDGPU::V_FMA_F32_e64;
4080 case AMDGPU::V_FMAC_F64_e32:
4081 case AMDGPU::V_FMAC_F64_e64:
4082 return AMDGPU::V_FMA_F64_e64;
4083 default:
4084 llvm_unreachable("invalid instruction");
4085 }
4086}
4087
4088/// Helper struct for the implementation of 3-address conversion to communicate
4089/// updates made to instruction operands.
4091 /// Other instruction whose def is no longer used by the converted
4092 /// instruction.
4094};
4095
4097 LiveVariables *LV,
4098 LiveIntervals *LIS) const {
4099 MachineBasicBlock &MBB = *MI.getParent();
4100 MachineInstr *CandidateMI = &MI;
4101
4102 if (MI.isBundle()) {
4103 // This is a temporary placeholder for bundle handling that enables us to
4104 // exercise the relevant code paths in the two-address instruction pass.
4105 if (MI.getBundleSize() != 1)
4106 return nullptr;
4107 CandidateMI = MI.getNextNode();
4108 }
4109
4111 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4112 if (!NewMI)
4113 return nullptr;
4114
4115 if (MI.isBundle()) {
4116 CandidateMI->eraseFromBundle();
4117
4118 for (MachineOperand &MO : MI.all_defs()) {
4119 if (MO.isTied())
4120 MI.untieRegOperand(MO.getOperandNo());
4121 }
4122 } else {
4123 updateLiveVariables(LV, MI, *NewMI);
4124 if (LIS) {
4125 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
4126 // SlotIndex of defs needs to be updated when converting to early-clobber
4127 MachineOperand &Def = NewMI->getOperand(0);
4128 if (Def.isEarlyClobber() && Def.isReg() &&
4129 LIS->hasInterval(Def.getReg())) {
4130 SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
4131 SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
4132 auto &LI = LIS->getInterval(Def.getReg());
4133 auto UpdateDefIndex = [&](LiveRange &LR) {
4134 auto *S = LR.find(OldIndex);
4135 if (S != LR.end() && S->start == OldIndex) {
4136 assert(S->valno && S->valno->def == OldIndex);
4137 S->start = NewIndex;
4138 S->valno->def = NewIndex;
4139 }
4140 };
4141 UpdateDefIndex(LI);
4142 for (auto &SR : LI.subranges())
4143 UpdateDefIndex(SR);
4144 }
4145 }
4146 }
4147
4148 if (U.RemoveMIUse) {
4149 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
4150 // The only user is the instruction which will be killed.
4151 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4152
4153 if (MRI.hasOneNonDBGUse(DefReg)) {
4154 // We cannot just remove the DefMI here, calling pass will crash.
4155 U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
4156 U.RemoveMIUse->getOperand(0).setIsDead(true);
4157 for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
4158 U.RemoveMIUse->removeOperand(I);
4159 if (LV)
4160 LV->getVarInfo(DefReg).AliveBlocks.clear();
4161 }
4162
4163 if (MI.isBundle()) {
4164 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4165 if (!VRI.Reads && !VRI.Writes) {
4166 for (MachineOperand &MO : MI.all_uses()) {
4167 if (MO.isReg() && MO.getReg() == DefReg) {
4168 assert(MO.getSubReg() == 0 &&
4169 "tied sub-registers in bundles currently not supported");
4170 MI.removeOperand(MO.getOperandNo());
4171 break;
4172 }
4173 }
4174
4175 if (LIS)
4176 LIS->shrinkToUses(&LIS->getInterval(DefReg));
4177 }
4178 } else if (LIS) {
4179 LiveInterval &DefLI = LIS->getInterval(DefReg);
4180
4181 // We cannot delete the original instruction here, so hack out the use
4182 // in the original instruction with a dummy register so we can use
4183 // shrinkToUses to deal with any multi-use edge cases. Other targets do
4184 // not have the complexity of deleting a use to consider here.
4185 Register DummyReg = MRI.cloneVirtualRegister(DefReg);
4186 for (MachineOperand &MIOp : MI.uses()) {
4187 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4188 MIOp.setIsUndef(true);
4189 MIOp.setReg(DummyReg);
4190 }
4191 }
4192
4193 if (MI.isBundle()) {
4194 VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
4195 if (!VRI.Reads && !VRI.Writes) {
4196 for (MachineOperand &MIOp : MI.uses()) {
4197 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4198 MIOp.setIsUndef(true);
4199 MIOp.setReg(DummyReg);
4200 }
4201 }
4202 }
4203
4204 MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
4205 false, /*isUndef=*/true));
4206 }
4207
4208 LIS->shrinkToUses(&DefLI);
4209 }
4210 }
4211
4212 return MI.isBundle() ? &MI : NewMI;
4213}
4214
4216SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
4217 ThreeAddressUpdates &U) const {
4218 MachineBasicBlock &MBB = *MI.getParent();
4219 unsigned Opc = MI.getOpcode();
4220
4221 // Handle MFMA.
4222 int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
4223 if (NewMFMAOpc != -1) {
4225 BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
4226 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4227 MIB.add(MI.getOperand(I));
4228 return MIB;
4229 }
4230
4231 if (SIInstrInfo::isWMMA(MI)) {
4232 unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
4233 MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4234 .setMIFlags(MI.getFlags());
4235 for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
4236 MIB->addOperand(MI.getOperand(I));
4237 return MIB;
4238 }
4239
4240 assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4241 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4242 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4243 "present pre-RA");
4244
4245 // Handle MAC/FMAC.
4246 bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
4247 bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4248 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4249 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4250 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4251 bool Src0Literal = false;
4252
4253 switch (Opc) {
4254 default:
4255 return nullptr;
4256 case AMDGPU::V_MAC_F16_e64:
4257 case AMDGPU::V_FMAC_F16_e64:
4258 case AMDGPU::V_FMAC_F16_t16_e64:
4259 case AMDGPU::V_FMAC_F16_fake16_e64:
4260 case AMDGPU::V_MAC_F32_e64:
4261 case AMDGPU::V_MAC_LEGACY_F32_e64:
4262 case AMDGPU::V_FMAC_F32_e64:
4263 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4264 case AMDGPU::V_FMAC_F64_e64:
4265 break;
4266 case AMDGPU::V_MAC_F16_e32:
4267 case AMDGPU::V_FMAC_F16_e32:
4268 case AMDGPU::V_MAC_F32_e32:
4269 case AMDGPU::V_MAC_LEGACY_F32_e32:
4270 case AMDGPU::V_FMAC_F32_e32:
4271 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4272 case AMDGPU::V_FMAC_F64_e32: {
4273 int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
4274 AMDGPU::OpName::src0);
4275 const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
4276 if (!Src0->isReg() && !Src0->isImm())
4277 return nullptr;
4278
4279 if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
4280 Src0Literal = true;
4281
4282 break;
4283 }
4284 }
4285
4286 MachineInstrBuilder MIB;
4287 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
4288 const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
4289 const MachineOperand *Src0Mods =
4290 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
4291 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4292 const MachineOperand *Src1Mods =
4293 getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
4294 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4295 const MachineOperand *Src2Mods =
4296 getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
4297 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
4298 const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
4299 const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);
4300
4301 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4302 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4303 // If we have an SGPR input, we will violate the constant bus restriction.
4304 (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
4305 !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
4306 MachineInstr *DefMI = nullptr;
4307
4308 int64_t Imm;
4309 if (!Src0Literal && getFoldableImm(Src2, Imm, &DefMI)) {
4310 unsigned NewOpc = getNewFMAAKInst(ST, Opc);
4311 if (pseudoToMCOpcode(NewOpc) != -1) {
4312 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4313 .add(*Dst)
4314 .add(*Src0)
4315 .add(*Src1)
4316 .addImm(Imm)
4317 .setMIFlags(MI.getFlags());
4318 U.RemoveMIUse = DefMI;
4319 return MIB;
4320 }
4321 }
4322 unsigned NewOpc = getNewFMAMKInst(ST, Opc);
4323 if (!Src0Literal && getFoldableImm(Src1, Imm, &DefMI)) {
4324 if (pseudoToMCOpcode(NewOpc) != -1) {
4325 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4326 .add(*Dst)
4327 .add(*Src0)
4328 .addImm(Imm)
4329 .add(*Src2)
4330 .setMIFlags(MI.getFlags());
4331 U.RemoveMIUse = DefMI;
4332 return MIB;
4333 }
4334 }
4335 if (Src0Literal || getFoldableImm(Src0, Imm, &DefMI)) {
4336 if (Src0Literal) {
4337 Imm = Src0->getImm();
4338 DefMI = nullptr;
4339 }
4340 if (pseudoToMCOpcode(NewOpc) != -1 &&
4342 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4343 Src1)) {
4344 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4345 .add(*Dst)
4346 .add(*Src1)
4347 .addImm(Imm)
4348 .add(*Src2)
4349 .setMIFlags(MI.getFlags());
4350 U.RemoveMIUse = DefMI;
4351 return MIB;
4352 }
4353 }
4354 }
4355
4356 // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
4357 // if VOP3 does not allow a literal operand.
4358 if (Src0Literal && !ST.hasVOP3Literal())
4359 return nullptr;
4360
4361 unsigned NewOpc = getNewFMAInst(ST, Opc);
4362
4363 if (pseudoToMCOpcode(NewOpc) == -1)
4364 return nullptr;
4365
4366 MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
4367 .add(*Dst)
4368 .addImm(Src0Mods ? Src0Mods->getImm() : 0)
4369 .add(*Src0)
4370 .addImm(Src1Mods ? Src1Mods->getImm() : 0)
4371 .add(*Src1)
4372 .addImm(Src2Mods ? Src2Mods->getImm() : 0)
4373 .add(*Src2)
4374 .addImm(Clamp ? Clamp->getImm() : 0)
4375 .addImm(Omod ? Omod->getImm() : 0)
4376 .setMIFlags(MI.getFlags());
4377 if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
4378 MIB.addImm(OpSel ? OpSel->getImm() : 0);
4379 return MIB;
4380}
4381
4382// It's not generally safe to move VALU instructions across these since it will
4383// start using the register as a base index rather than directly.
4384// XXX - Why isn't hasSideEffects sufficient for these?
4386 switch (MI.getOpcode()) {
4387 case AMDGPU::S_SET_GPR_IDX_ON:
4388 case AMDGPU::S_SET_GPR_IDX_MODE:
4389 case AMDGPU::S_SET_GPR_IDX_OFF:
4390 return true;
4391 default:
4392 return false;
4393 }
4394}
4395
4397 const MachineBasicBlock *MBB,
4398 const MachineFunction &MF) const {
4399 // Skipping the check for SP writes in the base implementation. The reason it
4400 // was added was apparently due to compile time concerns.
4401 //
4402 // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
4403 // but is probably avoidable.
4404
4405 // Copied from base implementation.
4406 // Terminators and labels can't be scheduled around.
4407 if (MI.isTerminator() || MI.isPosition())
4408 return true;
4409
4410 // INLINEASM_BR can jump to another block
4411 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4412 return true;
4413
4414 if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
4415 return true;
4416
4417 // Target-independent instructions do not have an implicit-use of EXEC, even
4418 // when they operate on VGPRs. Treating EXEC modifications as scheduling
4419 // boundaries prevents incorrect movements of such instructions.
4420 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4421 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4422 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4423 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4424 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4426}
4427
4429 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4430 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4431 Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
4432}
4433
4435 // Instructions that access scratch use FLAT encoding or BUF encodings.
4436 if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
4437 return false;
4438
4439 // SCRATCH instructions always access scratch.
4440 if (isFLATScratch(MI))
4441 return true;
4442
4443 // If FLAT_SCRATCH registers are not initialized, we can never access scratch
4444 // via the aperture.
4445 if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
4446 return false;
4447
4448 // If there are no memory operands then conservatively assume the flat
4449 // operation may access scratch.
4450 if (MI.memoperands_empty())
4451 return true;
4452
4453 // See if any memory operand specifies an address space that involves scratch.
4454 return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
4455 unsigned AS = Memop->getAddrSpace();
4456 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4457 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4458 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4459 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4460 }
4461 return AS == AMDGPUAS::PRIVATE_ADDRESS;
4462 });
4463}
4464
4466 assert(isFLAT(MI));
4467
4468 // All flat instructions use the VMEM counter except prefetch.
4469 if (!usesVM_CNT(MI))
4470 return false;
4471
4472 // If there are no memory operands then conservatively assume the flat
4473 // operation may access VMEM.
4474 if (MI.memoperands_empty())
4475 return true;
4476
4477 // See if any memory operand specifies an address space that involves VMEM.
4478 // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
4479 // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
4480 // (GDS) address space is not supported by flat operations. Therefore, simply
4481 // return true unless only the LDS address space is found.
4482 for (const MachineMemOperand *Memop : MI.memoperands()) {
4483 unsigned AS = Memop->getAddrSpace();
4485 if (AS != AMDGPUAS::LOCAL_ADDRESS)
4486 return true;
4487 }
4488
4489 return false;
4490}
4491
4493 bool TgSplit) const {
4494 assert(isFLAT(MI));
4495
4496 // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
4497 if (!usesLGKM_CNT(MI))
4498 return false;
4499
4500 // If in tgsplit mode then there can be no use of LDS.
4501 if (TgSplit)
4502 return false;
4503
4504 // If there are no memory operands then conservatively assume the flat
4505 // operation may access LDS.
4506 if (MI.memoperands_empty())
4507 return true;
4508
4509 // See if any memory operand specifies an address space that involves LDS.
4510 for (const MachineMemOperand *Memop : MI.memoperands()) {
4511 unsigned AS = Memop->getAddrSpace();
4513 return true;
4514 }
4515
4516 return false;
4517}
4518
4520 // Skip the full operand and register alias search modifiesRegister
4521 // does. There's only a handful of instructions that touch this, it's only an
4522 // implicit def, and doesn't alias any other registers.
4523 return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
4524}
4525
4527 unsigned Opcode = MI.getOpcode();
4528
4529 if (MI.mayStore() && isSMRD(MI))
4530 return true; // scalar store or atomic
4531
4532 // This will terminate the function when other lanes may need to continue.
4533 if (MI.isReturn())
4534 return true;
4535
4536 // These instructions cause shader I/O that may cause hardware lockups
4537 // when executed with an empty EXEC mask.
4538 //
4539 // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
4540 // EXEC = 0, but checking for that case here seems not worth it
4541 // given the typical code patterns.
4542 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4543 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4544 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4545 Opcode == AMDGPU::S_SETHALT)
4546 return true;
4547
4548 if (MI.isCall() || MI.isInlineAsm())
4549 return true; // conservative assumption
4550
4551 // Assume that barrier interactions are only intended with active lanes.
4552 if (isBarrier(Opcode))
4553 return true;
4554
4555 // A mode change is a scalar operation that influences vector instructions.
4557 return true;
4558
4559 // These are like SALU instructions in terms of effects, so it's questionable
4560 // whether we should return true for those.
4561 //
4562 // However, executing them with EXEC = 0 causes them to operate on undefined
4563 // data, which we avoid by returning true here.
4564 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4565 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4566 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4567 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4568 return true;
4569
4570 return false;
4571}
4572
4574 const MachineInstr &MI) const {
4575 if (MI.isMetaInstruction())
4576 return false;
4577
4578 // This won't read exec if this is an SGPR->SGPR copy.
4579 if (MI.isCopyLike()) {
4580 if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
4581 return true;
4582
4583 // Make sure this isn't copying exec as a normal operand
4584 return MI.readsRegister(AMDGPU::EXEC, &RI);
4585 }
4586
4587 // Make a conservative assumption about the callee.
4588 if (MI.isCall())
4589 return true;
4590
4591 // Be conservative with any unhandled generic opcodes.
4592 if (!isTargetSpecificOpcode(MI.getOpcode()))
4593 return true;
4594
4595 return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
4596}
4597
4598bool SIInstrInfo::isInlineConstant(const APInt &Imm) const {
4599 switch (Imm.getBitWidth()) {
4600 case 1: // This likely will be a condition code mask.
4601 return true;
4602
4603 case 32:
4604 return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
4605 ST.hasInv2PiInlineImm());
4606 case 64:
4607 return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
4608 ST.hasInv2PiInlineImm());
4609 case 16:
4610 return ST.has16BitInsts() &&
4611 AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
4612 ST.hasInv2PiInlineImm());
4613 default:
4614 llvm_unreachable("invalid bitwidth");
4615 }
4616}
4617
4619 APInt IntImm = Imm.bitcastToAPInt();
4620 int64_t IntImmVal = IntImm.getSExtValue();
4621 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4622 switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
4623 default:
4624 llvm_unreachable("invalid fltSemantics");
4627 return isInlineConstant(IntImm);
4629 return ST.has16BitInsts() &&
4630 AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
4632 return ST.has16BitInsts() &&
4633 AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
4634 }
4635}
4636
4637bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
4638 // MachineOperand provides no way to tell the true operand size, since it only
4639 // records a 64-bit value. We need to know the size to determine if a 32-bit
4640 // floating point immediate bit pattern is legal for an integer immediate. It
4641 // would be for any 32-bit integer operand, but would not be for a 64-bit one.
4642 switch (OperandType) {
4652 int32_t Trunc = static_cast<int32_t>(Imm);
4653 return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
4654 }
4662 return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
4665 // We would expect inline immediates to not be concerned with an integer/fp
4666 // distinction. However, in the case of 16-bit integer operations, the
4667 // "floating point" values appear to not work. It seems read the low 16-bits
4668 // of 32-bit immediates, which happens to always work for the integer
4669 // values.
4670 //
4671 // See llvm bugzilla 46302.
4672 //
4673 // TODO: Theoretically we could use op-sel to use the high bits of the
4674 // 32-bit FP values.
4683 return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
4688 return false;
4691 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
4692 // A few special case instructions have 16-bit operands on subtargets
4693 // where 16-bit instructions are not legal.
4694 // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
4695 // constants in these cases
4696 int16_t Trunc = static_cast<int16_t>(Imm);
4697 return ST.has16BitInsts() &&
4698 AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
4699 }
4700
4701 return false;
4702 }
4705 if (isInt<16>(Imm) || isUInt<16>(Imm)) {
4706 int16_t Trunc = static_cast<int16_t>(Imm);
4707 return ST.has16BitInsts() &&
4708 AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
4709 }
4710 return false;
4711 }
4715 return false;
4717 return isLegalAV64PseudoImm(Imm);
4720 // Always embedded in the instruction for free.
4721 return true;
4731 // Just ignore anything else.
4732 return true;
4733 default:
4734 llvm_unreachable("invalid operand type");
4735 }
4736}
4737
4738static bool compareMachineOp(const MachineOperand &Op0,
4739 const MachineOperand &Op1) {
4740 if (Op0.getType() != Op1.getType())
4741 return false;
4742
4743 switch (Op0.getType()) {
4745 return Op0.getReg() == Op1.getReg();
4747 return Op0.getImm() == Op1.getImm();
4748 default:
4749 llvm_unreachable("Didn't expect to be comparing these operand types");
4750 }
4751}
4752
4754 const MCOperandInfo &OpInfo) const {
4755 if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
4756 return true;
4757
4758 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
4759 return false;
4760
4761 if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
4762 return true;
4763
4764 return ST.hasVOP3Literal();
4765}
4766
4767bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
4768 int64_t ImmVal) const {
4769 const unsigned Opc = InstDesc.getOpcode();
4770 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
4771 if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
4772 OpNo == static_cast<unsigned>(Src1Idx))
4773 return false;
4774
4775 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
4776 if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
4777 if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
4778 OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
4779 AMDGPU::OpName::src2))
4780 return false;
4781 return RI.opCanUseInlineConstant(OpInfo.OperandType);
4782 }
4783
4784 return isLiteralOperandLegal(InstDesc, OpInfo);
4785}
4786
4787bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
4788 const MachineOperand &MO) const {
4789 if (MO.isImm())
4790 return isImmOperandLegal(InstDesc, OpNo, MO.getImm());
4791
4792 assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
4793 "unexpected imm-like operand kind");
4794 const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
4795 return isLiteralOperandLegal(InstDesc, OpInfo);
4796}
4797
4799 // 2 32-bit inline constants packed into one.
4800 return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
4801 AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
4802}
4803
4804bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
4805 // GFX90A does not have V_MUL_LEGACY_F32_e32.
4806 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
4807 return false;
4808
4809 int Op32 = AMDGPU::getVOPe32(Opcode);
4810 if (Op32 == -1)
4811 return false;
4812
4813 return pseudoToMCOpcode(Op32) != -1;
4814}
4815
4816bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
4817 // The src0_modifier operand is present on all instructions
4818 // that have modifiers.
4819
4820 return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
4821}
4822
4824 AMDGPU::OpName OpName) const {
4825 const MachineOperand *Mods = getNamedOperand(MI, OpName);
4826 return Mods && Mods->getImm();
4827}
4828
4830 return any_of(ModifierOpNames,
4831 [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
4832}
4833
4835 const MachineRegisterInfo &MRI) const {
4836 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4837 // Can't shrink instruction with three operands.
4838 if (Src2) {
4839 switch (MI.getOpcode()) {
4840 default: return false;
4841
4842 case AMDGPU::V_ADDC_U32_e64:
4843 case AMDGPU::V_SUBB_U32_e64:
4844 case AMDGPU::V_SUBBREV_U32_e64: {
4845 const MachineOperand *Src1
4846 = getNamedOperand(MI, AMDGPU::OpName::src1);
4847 if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
4848 return false;
4849 // Additional verification is needed for sdst/src2.
4850 return true;
4851 }
4852 case AMDGPU::V_MAC_F16_e64:
4853 case AMDGPU::V_MAC_F32_e64:
4854 case AMDGPU::V_MAC_LEGACY_F32_e64:
4855 case AMDGPU::V_FMAC_F16_e64:
4856 case AMDGPU::V_FMAC_F16_t16_e64:
4857 case AMDGPU::V_FMAC_F16_fake16_e64:
4858 case AMDGPU::V_FMAC_F32_e64:
4859 case AMDGPU::V_FMAC_F64_e64:
4860 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4861 if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
4862 hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
4863 return false;
4864 break;
4865
4866 case AMDGPU::V_CNDMASK_B32_e64:
4867 break;
4868 }
4869 }
4870
4871 const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
4872 if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
4873 hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
4874 return false;
4875
4876 // We don't need to check src0, all input types are legal, so just make sure
4877 // src0 isn't using any modifiers.
4878 if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
4879 return false;
4880
4881 // Can it be shrunk to a valid 32 bit opcode?
4882 if (!hasVALU32BitEncoding(MI.getOpcode()))
4883 return false;
4884
4885 // Check output modifiers
4886 return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
4887 !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
4888 !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
4889 // TODO: Can we avoid checking bound_ctrl/fi here?
4890 // They are only used by permlane*_swap special case.
4891 !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
4892 !hasModifiersSet(MI, AMDGPU::OpName::fi);
4893}
4894
4895// Set VCC operand with all flags from \p Orig, except for setting it as
4896// implicit.
4898 const MachineOperand &Orig) {
4899
4900 for (MachineOperand &Use : MI.implicit_operands()) {
4901 if (Use.isUse() &&
4902 (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
4903 Use.setIsUndef(Orig.isUndef());
4904 Use.setIsKill(Orig.isKill());
4905 return;
4906 }
4907 }
4908}
4909
4911 unsigned Op32) const {
4912 MachineBasicBlock *MBB = MI.getParent();
4913
4914 const MCInstrDesc &Op32Desc = get(Op32);
4915 MachineInstrBuilder Inst32 =
4916 BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
4917 .setMIFlags(MI.getFlags());
4918
4919 // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
4920 // For VOPC instructions, this is replaced by an implicit def of vcc.
4921
4922 // We assume the defs of the shrunk opcode are in the same order, and the
4923 // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
4924 for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
4925 Inst32.add(MI.getOperand(I));
4926
4927 const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
4928
4929 int Idx = MI.getNumExplicitDefs();
4930 for (const MachineOperand &Use : MI.explicit_uses()) {
4931 int OpTy = MI.getDesc().operands()[Idx++].OperandType;
4933 continue;
4934
4935 if (&Use == Src2) {
4936 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
4937 // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
4938 // replaced with an implicit read of vcc or vcc_lo. The implicit read
4939 // of vcc was already added during the initial BuildMI, but we
4940 // 1) may need to change vcc to vcc_lo to preserve the original register
4941 // 2) have to preserve the original flags.
4942 copyFlagsToImplicitVCC(*Inst32, *Src2);
4943 continue;
4944 }
4945 }
4946
4947 Inst32.add(Use);
4948 }
4949
4950 // FIXME: Losing implicit operands
4951 fixImplicitOperands(*Inst32);
4952 return Inst32;
4953}
4954
4956 // Null is free
4957 Register Reg = RegOp.getReg();
4958 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
4959 return false;
4960
4961 // SGPRs use the constant bus
4962
4963 // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
4964 // physical register operands should also count, except for exec.
4965 if (RegOp.isImplicit())
4966 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
4967
4968 // SGPRs use the constant bus
4969 return AMDGPU::SReg_32RegClass.contains(Reg) ||
4970 AMDGPU::SReg_64RegClass.contains(Reg);
4971}
4972
4974 const MachineRegisterInfo &MRI) const {
4975 Register Reg = RegOp.getReg();
4976 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
4977 : physRegUsesConstantBus(RegOp);
4978}
4979
4981 const MachineOperand &MO,
4982 const MCOperandInfo &OpInfo) const {
4983 // Literal constants use the constant bus.
4984 if (!MO.isReg())
4985 return !isInlineConstant(MO, OpInfo);
4986
4987 Register Reg = MO.getReg();
4988 return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
4990}
4991
4993 for (const MachineOperand &MO : MI.implicit_operands()) {
4994 // We only care about reads.
4995 if (MO.isDef())
4996 continue;
4997
4998 switch (MO.getReg()) {
4999 case AMDGPU::VCC:
5000 case AMDGPU::VCC_LO:
5001 case AMDGPU::VCC_HI:
5002 case AMDGPU::M0:
5003 case AMDGPU::FLAT_SCR:
5004 return MO.getReg();
5005
5006 default:
5007 break;
5008 }
5009 }
5010
5011 return Register();
5012}
5013
5014static bool shouldReadExec(const MachineInstr &MI) {
5015 if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
5016 switch (MI.getOpcode()) {
5017 case AMDGPU::V_READLANE_B32:
5018 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5019 case AMDGPU::V_WRITELANE_B32:
5020 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5021 return false;
5022 }
5023
5024 return true;
5025 }
5026
5027 if (MI.isPreISelOpcode() ||
5028 SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
5031 return false;
5032
5033 return true;
5034}
5035
5036static bool isRegOrFI(const MachineOperand &MO) {
5037 return MO.isReg() || MO.isFI();
5038}
5039
5040static bool isSubRegOf(const SIRegisterInfo &TRI,
5041 const MachineOperand &SuperVec,
5042 const MachineOperand &SubReg) {
5043 if (SubReg.getReg().isPhysical())
5044 return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());
5045
5046 return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
5047 SubReg.getReg() == SuperVec.getReg();
5048}
5049
5050// Verify the illegal copy from vector register to SGPR for generic opcode COPY
5051bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
5052 const MachineRegisterInfo &MRI,
5053 StringRef &ErrInfo) const {
5054 Register DstReg = MI.getOperand(0).getReg();
5055 Register SrcReg = MI.getOperand(1).getReg();
5056 // This is a check for copy from vector register to SGPR
5057 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5058 ErrInfo = "illegal copy from vector register to SGPR";
5059 return false;
5060 }
5061 return true;
5062}
5063
5065 StringRef &ErrInfo) const {
5066 uint32_t Opcode = MI.getOpcode();
5067 const MachineFunction *MF = MI.getMF();
5068 const MachineRegisterInfo &MRI = MF->getRegInfo();
5069
5070 // FIXME: At this point the COPY verify is done only for non-ssa forms.
5071 // Find a better property to recognize the point where instruction selection
5072 // is just done.
5073 // We can only enforce this check after SIFixSGPRCopies pass so that the
5074 // illegal copies are legalized and thereafter we don't expect a pass
5075 // inserting similar copies.
5076 if (!MRI.isSSA() && MI.isCopy())
5077 return verifyCopy(MI, MRI, ErrInfo);
5078
5079 if (SIInstrInfo::isGenericOpcode(Opcode))
5080 return true;
5081
5082 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5083 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5084 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5085 int Src3Idx = -1;
5086 if (Src0Idx == -1) {
5087 // VOPD V_DUAL_* instructions use different operand names.
5088 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5089 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5090 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5091 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5092 }
5093
5094 // Make sure the number of operands is correct.
5095 const MCInstrDesc &Desc = get(Opcode);
5096 if (!Desc.isVariadic() &&
5097 Desc.getNumOperands() != MI.getNumExplicitOperands()) {
5098 ErrInfo = "Instruction has wrong number of operands.";
5099 return false;
5100 }
5101
5102 if (MI.isInlineAsm()) {
5103 // Verify register classes for inlineasm constraints.
5104 for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
5105 I != E; ++I) {
5106 const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
5107 if (!RC)
5108 continue;
5109
5110 const MachineOperand &Op = MI.getOperand(I);
5111 if (!Op.isReg())
5112 continue;
5113
5114 Register Reg = Op.getReg();
5115 if (!Reg.isVirtual() && !RC->contains(Reg)) {
5116 ErrInfo = "inlineasm operand has incorrect register class.";
5117 return false;
5118 }
5119 }
5120
5121 return true;
5122 }
5123
5124 if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
5125 ErrInfo = "missing memory operand from image instruction.";
5126 return false;
5127 }
5128
5129 // Make sure the register classes are correct.
5130 for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
5131 const MachineOperand &MO = MI.getOperand(i);
5132 if (MO.isFPImm()) {
5133 ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
5134 "all fp values to integers.";
5135 return false;
5136 }
5137
5138 const MCOperandInfo &OpInfo = Desc.operands()[i];
5139 int16_t RegClass = getOpRegClassID(OpInfo);
5140
5141 switch (OpInfo.OperandType) {
5143 if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
5144 ErrInfo = "Illegal immediate value for operand.";
5145 return false;
5146 }
5147 break;
5159 break;
5161 break;
5162 break;
5176 if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
5177 ErrInfo = "Illegal immediate value for operand.";
5178 return false;
5179 }
5180 break;
5181 }
5186 if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
5187 !isInlineConstant(MI, i) &&
5189 OpInfo.OperandType ==
5191 ErrInfo = "illegal 64-bit immediate value for operand.";
5192 return false;
5193 }
5194 break;
5197 if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
5198 ErrInfo = "Expected inline constant for operand.";
5199 return false;
5200 }
5201 break;
5204 break;
5209 // Check if this operand is an immediate.
5210 // FrameIndex operands will be replaced by immediates, so they are
5211 // allowed.
5212 if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
5213 ErrInfo = "Expected immediate, but got non-immediate";
5214 return false;
5215 }
5216 break;
5220 break;
5221 default:
5222 if (OpInfo.isGenericType())
5223 continue;
5224 break;
5225 }
5226
5227 if (!MO.isReg())
5228 continue;
5229 Register Reg = MO.getReg();
5230 if (!Reg)
5231 continue;
5232
5233 // FIXME: Ideally we would have separate instruction definitions with the
5234 // aligned register constraint.
5235 // FIXME: We do not verify inline asm operands, but custom inline asm
5236 // verification is broken anyway
5237 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5238 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !isSpill(MI)) {
5239 const TargetRegisterClass *RC = RI.getRegClassForReg(MRI, Reg);
5240 if (RI.hasVectorRegisters(RC) && MO.getSubReg()) {
5241 if (const TargetRegisterClass *SubRC =
5242 RI.getSubRegisterClass(RC, MO.getSubReg())) {
5243 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.getSubReg());
5244 if (RC)
5245 RC = SubRC;
5246 }
5247 }
5248
5249 // Check that this is the aligned version of the class.
5250 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5251 ErrInfo = "Subtarget requires even aligned vector registers";
5252 return false;
5253 }
5254 }
5255
5256 if (RegClass != -1) {
5257 if (Reg.isVirtual())
5258 continue;
5259
5260 const TargetRegisterClass *RC = RI.getRegClass(RegClass);
5261 if (!RC->contains(Reg)) {
5262 ErrInfo = "Operand has incorrect register class.";
5263 return false;
5264 }
5265 }
5266 }
5267
5268 // Verify SDWA
5269 if (isSDWA(MI)) {
5270 if (!ST.hasSDWA()) {
5271 ErrInfo = "SDWA is not supported on this target";
5272 return false;
5273 }
5274
5275 for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5276 AMDGPU::OpName::dst_sel}) {
5277 const MachineOperand *MO = getNamedOperand(MI, Op);
5278 if (!MO)
5279 continue;
5280 int64_t Imm = MO->getImm();
5281 if (Imm < 0 || Imm > AMDGPU::SDWA::SdwaSel::DWORD) {
5282 ErrInfo = "Invalid SDWA selection";
5283 return false;
5284 }
5285 }
5286
5287 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5288
5289 for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5290 if (OpIdx == -1)
5291 continue;
5292 const MachineOperand &MO = MI.getOperand(OpIdx);
5293
5294 if (!ST.hasSDWAScalar()) {
5295 // Only VGPRS on VI
5296 if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
5297 ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
5298 return false;
5299 }
5300 } else {
5301 // No immediates on GFX9
5302 if (!MO.isReg()) {
5303 ErrInfo =
5304 "Only reg allowed as operands in SDWA instructions on GFX9+";
5305 return false;
5306 }
5307 }
5308 }
5309
5310 if (!ST.hasSDWAOmod()) {
5311 // No omod allowed on VI
5312 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5313 if (OMod != nullptr &&
5314 (!OMod->isImm() || OMod->getImm() != 0)) {
5315 ErrInfo = "OMod not allowed in SDWA instructions on VI";
5316 return false;
5317 }
5318 }
5319
5320 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5321 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5322 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5323 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5324 const MachineOperand *Src0ModsMO =
5325 getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
5326 unsigned Mods = Src0ModsMO->getImm();
5327 if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
5328 Mods & SISrcMods::SEXT) {
5329 ErrInfo = "sext, abs and neg are not allowed on this instruction";
5330 return false;
5331 }
5332 }
5333
5334 uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
5335 if (isVOPC(BasicOpcode)) {
5336 if (!ST.hasSDWASdst() && DstIdx != -1) {
5337 // Only vcc allowed as dst on VI for VOPC
5338 const MachineOperand &Dst = MI.getOperand(DstIdx);
5339 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5340 ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
5341 return false;
5342 }
5343 } else if (!ST.hasSDWAOutModsVOPC()) {
5344 // No clamp allowed on GFX9 for VOPC
5345 const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
5346 if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
5347 ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
5348 return false;
5349 }
5350
5351 // No omod allowed on GFX9 for VOPC
5352 const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
5353 if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
5354 ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
5355 return false;
5356 }
5357 }
5358 }
5359
5360 const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
5361 if (DstUnused && DstUnused->isImm() &&
5362 DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
5363 const MachineOperand &Dst = MI.getOperand(DstIdx);
5364 if (!Dst.isReg() || !Dst.isTied()) {
5365 ErrInfo = "Dst register should have tied register";
5366 return false;
5367 }
5368
5369 const MachineOperand &TiedMO =
5370 MI.getOperand(MI.findTiedOperandIdx(DstIdx));
5371 if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
5372 ErrInfo =
5373 "Dst register should be tied to implicit use of preserved register";
5374 return false;
5375 }
5376 if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
5377 ErrInfo = "Dst register should use same physical register as preserved";
5378 return false;
5379 }
5380 }
5381 }
5382
5383 if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5384 const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
5385 if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
5386 ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
5387 return false;
5388 }
5389 if (Src1MO.isImm()) {
5390 ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
5391 return false;
5392 }
5393 }
5394
5395 // Verify MIMG / VIMAGE / VSAMPLE
5396 if (isImage(Opcode) && !MI.mayStore()) {
5397 // Ensure that the return type used is large enough for all the options
5398 // being used TFE/LWE require an extra result register.
5399 const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
5400 if (DMask) {
5401 uint64_t DMaskImm = DMask->getImm();
5402 uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
5403 const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
5404 const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
5405 const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);
5406
5407 // Adjust for packed 16 bit values
5408 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5409 RegCount = divideCeil(RegCount, 2);
5410
5411 // Adjust if using LWE or TFE
5412 if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
5413 RegCount += 1;
5414
5415 const uint32_t DstIdx =
5416 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5417 const MachineOperand &Dst = MI.getOperand(DstIdx);
5418 if (Dst.isReg()) {
5419 const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
5420 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5421 if (RegCount > DstSize) {
5422 ErrInfo = "Image instruction returns too many registers for dst "
5423 "register class";
5424 return false;
5425 }
5426 }
5427 }
5428 }
5429
5430 // Verify VOP*. Ignore multiple sgpr operands on writelane.
5431 if (isVALU(MI, /*AllowLDSDMA=*/true) &&
5432 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5433 unsigned ConstantBusCount = 0;
5434 bool UsesLiteral = false;
5435 const MachineOperand *LiteralVal = nullptr;
5436
5437 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5438 if (ImmIdx != -1) {
5439 ++ConstantBusCount;
5440 UsesLiteral = true;
5441 LiteralVal = &MI.getOperand(ImmIdx);
5442 }
5443
5444 SmallVector<Register, 2> SGPRsUsed;
5445 Register SGPRUsed;
5446
5447 // Only look at the true operands. Only a real operand can use the constant
5448 // bus, and we don't want to check pseudo-operands like the source modifier
5449 // flags.
5450 for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5451 if (OpIdx == -1)
5452 continue;
5453 const MachineOperand &MO = MI.getOperand(OpIdx);
5454 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5455 if (MO.isReg()) {
5456 SGPRUsed = MO.getReg();
5457 if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
5458 ++ConstantBusCount;
5459 SGPRsUsed.push_back(SGPRUsed);
5460 }
5461 } else if (!MO.isFI()) { // Treat FI like a register.
5462 if (!UsesLiteral) {
5463 ++ConstantBusCount;
5464 UsesLiteral = true;
5465 LiteralVal = &MO;
5466 } else if (!MO.isIdenticalTo(*LiteralVal)) {
5467 assert(isVOP2(MI) || isVOP3(MI));
5468 ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
5469 return false;
5470 }
5471 }
5472 }
5473 }
5474
5475 SGPRUsed = findImplicitSGPRRead(MI);
5476 if (SGPRUsed) {
5477 // Implicit uses may safely overlap true operands
5478 if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
5479 return !RI.regsOverlap(SGPRUsed, SGPR);
5480 })) {
5481 ++ConstantBusCount;
5482 SGPRsUsed.push_back(SGPRUsed);
5483 }
5484 }
5485
5486 // v_writelane_b32 is an exception from constant bus restriction:
5487 // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
5488 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5489 Opcode != AMDGPU::V_WRITELANE_B32) {
5490 ErrInfo = "VOP* instruction violates constant bus restriction";
5491 return false;
5492 }
5493
5494 if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5495 ErrInfo = "VOP3 instruction uses literal";
5496 return false;
5497 }
5498 }
5499
5500 // Special case for writelane - this can break the multiple constant bus rule,
5501 // but still can't use more than one SGPR register
5502 if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5503 unsigned SGPRCount = 0;
5504 Register SGPRUsed;
5505
5506 for (int OpIdx : {Src0Idx, Src1Idx}) {
5507 if (OpIdx == -1)
5508 break;
5509
5510 const MachineOperand &MO = MI.getOperand(OpIdx);
5511
5512 if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
5513 if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
5514 if (MO.getReg() != SGPRUsed)
5515 ++SGPRCount;
5516 SGPRUsed = MO.getReg();
5517 }
5518 }
5519 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5520 ErrInfo = "WRITELANE instruction violates constant bus restriction";
5521 return false;
5522 }
5523 }
5524 }
5525
5526 // Verify misc. restrictions on specific instructions.
5527 if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5528 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5529 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5530 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5531 const MachineOperand &Src2 = MI.getOperand(Src2Idx);
5532 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
5533 if (!compareMachineOp(Src0, Src1) &&
5534 !compareMachineOp(Src0, Src2)) {
5535 ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
5536 return false;
5537 }
5538 }
5539 if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
5540 SISrcMods::ABS) ||
5541 (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
5542 SISrcMods::ABS) ||
5543 (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
5544 SISrcMods::ABS)) {
5545 ErrInfo = "ABS not allowed in VOP3B instructions";
5546 return false;
5547 }
5548 }
5549
5550 if (isSOP2(MI) || isSOPC(MI)) {
5551 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5552 const MachineOperand &Src1 = MI.getOperand(Src1Idx);
5553
5554 if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
5555 !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
5556 !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
5557 !Src0.isIdenticalTo(Src1)) {
5558 ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
5559 return false;
5560 }
5561 }
5562
5563 if (isSOPK(MI)) {
5564 const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
5565 if (Desc.isBranch()) {
5566 if (!Op->isMBB()) {
5567 ErrInfo = "invalid branch target for SOPK instruction";
5568 return false;
5569 }
5570 } else {
5571 uint64_t Imm = Op->getImm();
5572 if (sopkIsZext(Opcode)) {
5573 if (!isUInt<16>(Imm)) {
5574 ErrInfo = "invalid immediate for SOPK instruction";
5575 return false;
5576 }
5577 } else {
5578 if (!isInt<16>(Imm)) {
5579 ErrInfo = "invalid immediate for SOPK instruction";
5580 return false;
5581 }
5582 }
5583 }
5584 }
5585
5586 if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5587 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5588 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5589 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5590 const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5591 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5592
5593 const unsigned StaticNumOps =
5594 Desc.getNumOperands() + Desc.implicit_uses().size();
5595 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5596
5597 // Require additional implicit operands. This allows a fixup done by the
5598 // post RA scheduler where the main implicit operand is killed and
5599 // implicit-defs are added for sub-registers that remain live after this
5600 // instruction.
5601 if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5602 ErrInfo = "missing implicit register operands";
5603 return false;
5604 }
5605
5606 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5607 if (IsDst) {
5608 if (!Dst->isUse()) {
5609 ErrInfo = "v_movreld_b32 vdst should be a use operand";
5610 return false;
5611 }
5612
5613 unsigned UseOpIdx;
5614 if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5615 UseOpIdx != StaticNumOps + 1) {
5616 ErrInfo = "movrel implicit operands should be tied";
5617 return false;
5618 }
5619 }
5620
5621 const MachineOperand &Src0 = MI.getOperand(Src0Idx);
5622 const MachineOperand &ImpUse
5623 = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5624 if (!ImpUse.isReg() || !ImpUse.isUse() ||
5625 !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5626 ErrInfo = "src0 should be subreg of implicit vector use";
5627 return false;
5628 }
5629 }
5630
5631 // Make sure we aren't losing exec uses in the td files. This mostly requires
5632 // being careful when using let Uses to try to add other use registers.
5633 if (shouldReadExec(MI)) {
5634 if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5635 ErrInfo = "VALU instruction does not implicitly read exec mask";
5636 return false;
5637 }
5638 }
5639
5640 if (isSMRD(MI)) {
5641 if (MI.mayStore() &&
5642 ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
5643 // The register offset form of scalar stores may only use m0 as the
5644 // soffset register.
5645 const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
5646 if (Soff && Soff->getReg() != AMDGPU::M0) {
5647 ErrInfo = "scalar stores must use m0 as offset register";
5648 return false;
5649 }
5650 }
5651 }
5652
5653 if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
5654 const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
5655 if (Offset->getImm() != 0) {
5656 ErrInfo = "subtarget does not support offsets in flat instructions";
5657 return false;
5658 }
5659 }
5660
5661 if (isDS(MI) && !ST.hasGDS()) {
5662 const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
5663 if (GDSOp && GDSOp->getImm() != 0) {
5664 ErrInfo = "GDS is not supported on this subtarget";
5665 return false;
5666 }
5667 }
5668
5669 if (isImage(MI)) {
5670 const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
5671 if (DimOp) {
5672 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5673 AMDGPU::OpName::vaddr0);
5674 AMDGPU::OpName RSrcOpName =
5675 isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5676 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5677 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
5678 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
5679 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
5680 const AMDGPU::MIMGDimInfo *Dim =
5682
5683 if (!Dim) {
5684 ErrInfo = "dim is out of range";
5685 return false;
5686 }
5687
5688 bool IsA16 = false;
5689 if (ST.hasR128A16()) {
5690 const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
5691 IsA16 = R128A16->getImm() != 0;
5692 } else if (ST.hasA16()) {
5693 const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
5694 IsA16 = A16->getImm() != 0;
5695 }
5696
5697 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5698
5699 unsigned AddrWords =
5700 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());
5701
5702 unsigned VAddrWords;
5703 if (IsNSA) {
5704 VAddrWords = RsrcIdx - VAddr0Idx;
5705 if (ST.hasPartialNSAEncoding() &&
5706 AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
5707 unsigned LastVAddrIdx = RsrcIdx - 1;
5708 VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
5709 }
5710 } else {
5711 VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
5712 if (AddrWords > 12)
5713 AddrWords = 16;
5714 }
5715
5716 if (VAddrWords != AddrWords) {
5717 LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
5718 << " but got " << VAddrWords << "\n");
5719 ErrInfo = "bad vaddr size";
5720 return false;
5721 }
5722 }
5723 }
5724
5725 const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
5726 if (DppCt) {
5727 using namespace AMDGPU::DPP;
5728
5729 unsigned DC = DppCt->getImm();
5730 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5731 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5732 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5733 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5734 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5735 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5736 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5737 ErrInfo = "Invalid dpp_ctrl value";
5738 return false;
5739 }
5740 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5741 !ST.hasDPPWavefrontShifts()) {
5742 ErrInfo = "Invalid dpp_ctrl value: "
5743 "wavefront shifts are not supported on GFX10+";
5744 return false;
5745 }
5746 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5747 !ST.hasDPPBroadcasts()) {
5748 ErrInfo = "Invalid dpp_ctrl value: "
5749 "broadcasts are not supported on GFX10+";
5750 return false;
5751 }
5752 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
5753 ST.getGeneration() < AMDGPUSubtarget::GFX10) {
5754 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
5755 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
5756 !ST.hasGFX90AInsts()) {
5757 ErrInfo = "Invalid dpp_ctrl value: "
5758 "row_newbroadcast/row_share is not supported before "
5759 "GFX90A/GFX10";
5760 return false;
5761 }
5762 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
5763 ErrInfo = "Invalid dpp_ctrl value: "
5764 "row_share and row_xmask are not supported before GFX10";
5765 return false;
5766 }
5767 }
5768
5769 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
5771 AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
5772 ErrInfo = "Invalid dpp_ctrl value: "
5773 "DP ALU dpp only support row_newbcast";
5774 return false;
5775 }
5776 }
5777
5778 if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
5779 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
5780 AMDGPU::OpName DataName =
5781 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
5782 const MachineOperand *Data = getNamedOperand(MI, DataName);
5783 const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
5784 if (Data && !Data->isReg())
5785 Data = nullptr;
5786
5787 if (ST.hasGFX90AInsts()) {
5788 if (Dst && Data && !Dst->isTied() && !Data->isTied() &&
5789 (RI.isAGPR(MRI, Dst->getReg()) != RI.isAGPR(MRI, Data->getReg()))) {
5790 ErrInfo = "Invalid register class: "
5791 "vdata and vdst should be both VGPR or AGPR";
5792 return false;
5793 }
5794 if (Data && Data2 &&
5795 (RI.isAGPR(MRI, Data->getReg()) != RI.isAGPR(MRI, Data2->getReg()))) {
5796 ErrInfo = "Invalid register class: "
5797 "both data operands should be VGPR or AGPR";
5798 return false;
5799 }
5800 } else {
5801 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
5802 (Data && RI.isAGPR(MRI, Data->getReg())) ||
5803 (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
5804 ErrInfo = "Invalid register class: "
5805 "agpr loads and stores not supported on this GPU";
5806 return false;
5807 }
5808 }
5809 }
5810
5811 if (ST.needsAlignedVGPRs()) {
5812 const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
5814 if (!Op)
5815 return true;
5816 Register Reg = Op->getReg();
5817 if (Reg.isPhysical())
5818 return !(RI.getHWRegIndex(Reg) & 1);
5819 const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
5820 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
5821 !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
5822 };
5823
5824 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
5825 Opcode == AMDGPU::DS_GWS_BARRIER) {
5826
5827 if (!isAlignedReg(AMDGPU::OpName::data0)) {
5828 ErrInfo = "Subtarget requires even aligned vector registers "
5829 "for DS_GWS instructions";
5830 return false;
5831 }
5832 }
5833
5834 if (isMIMG(MI)) {
5835 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
5836 ErrInfo = "Subtarget requires even aligned vector registers "
5837 "for vaddr operand of image instructions";
5838 return false;
5839 }
5840 }
5841 }
5842
5843 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
5844 const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
5845 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
5846 ErrInfo = "Invalid register class: "
5847 "v_accvgpr_write with an SGPR is not supported on this GPU";
5848 return false;
5849 }
5850 }
5851
5852 if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
5853 const MachineOperand &SrcOp = MI.getOperand(1);
5854 if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
5855 ErrInfo = "pseudo expects only physical SGPRs";
5856 return false;
5857 }
5858 }
5859
5860 if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
5861 if (CPol->getImm() & AMDGPU::CPol::SCAL) {
5862 if (!ST.hasScaleOffset()) {
5863 ErrInfo = "Subtarget does not support offset scaling";
5864 return false;
5865 }
5866 if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
5867 ErrInfo = "Instruction does not support offset scaling";
5868 return false;
5869 }
5870 }
5871 }
5872
5873 // See SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand for more
5874 // information.
5876 for (unsigned I = 0; I < 3; ++I) {
5878 return false;
5879 }
5880 }
5881
5882 if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
5883 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
5884 const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
5885 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
5886 &AMDGPU::SReg_64RegClass) ||
5887 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
5888 ErrInfo = "Instruction cannot read flat_scratch_base_hi";
5889 return false;
5890 }
5891 }
5892
5893 return true;
5894}
5895
5897 if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
5898 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
5899 return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
5900 ? AMDGPU::COPY
5901 : AMDGPU::V_MOV_B32_e32;
5902 }
5903 return getVALUOp(MI.getOpcode());
5904}
5905
5906// It is more readable to list mapped opcodes on the same line.
5907// clang-format off
5908
5909unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
5910 switch (Opc) {
5911 default: return AMDGPU::INSTRUCTION_LIST_END;
5912 case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
5913 case AMDGPU::COPY: return AMDGPU::COPY;
5914 case AMDGPU::PHI: return AMDGPU::PHI;
5915 case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
5916 case AMDGPU::WQM: return AMDGPU::WQM;
5917 case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
5918 case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
5919 case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
5920 case AMDGPU::S_ADD_I32:
5921 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
5922 case AMDGPU::S_ADDC_U32:
5923 return AMDGPU::V_ADDC_U32_e32;
5924 case AMDGPU::S_SUB_I32:
5925 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
5926 // FIXME: These are not consistently handled, and selected when the carry is
5927 // used.
5928 case AMDGPU::S_ADD_U32:
5929 return AMDGPU::V_ADD_CO_U32_e32;
5930 case AMDGPU::S_SUB_U32:
5931 return AMDGPU::V_SUB_CO_U32_e32;
5932 case AMDGPU::S_ADD_U64_PSEUDO:
5933 return AMDGPU::V_ADD_U64_PSEUDO;
5934 case AMDGPU::S_SUB_U64_PSEUDO:
5935 return AMDGPU::V_SUB_U64_PSEUDO;
5936 case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
5937 case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
5938 case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
5939 case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
5940 case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
5941 case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
5942 case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
5943 case AMDGPU::S_XNOR_B32:
5944 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
5945 case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
5946 case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
5947 case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
5948 case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
5949 case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
5950 case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
5951 case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
5952 case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
5953 case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
5954 case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
5955 case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
5956 case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
5957 case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
5958 case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
5959 case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
5960 case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
5961 case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
5962 case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
5963 case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
5964 case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
5965 case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
5966 case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
5967 case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
5968 case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
5969 case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
5970 case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
5971 case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
5972 case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
5973 case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
5974 case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
5975 case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
5976 case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
5977 case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
5978 case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
5979 case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
5980 case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
5981 case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
5982 case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
5983 case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
5984 case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
5985 case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
5986 case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
5987 case AMDGPU::S_CVT_F32_F16:
5988 case AMDGPU::S_CVT_HI_F32_F16:
5989 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
5990 : AMDGPU::V_CVT_F32_F16_fake16_e64;
5991 case AMDGPU::S_CVT_F16_F32:
5992 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
5993 : AMDGPU::V_CVT_F16_F32_fake16_e64;
5994 case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
5995 case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
5996 case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
5997 case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
5998 case AMDGPU::S_CEIL_F16:
5999 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6000 : AMDGPU::V_CEIL_F16_fake16_e64;
6001 case AMDGPU::S_FLOOR_F16:
6002 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6003 : AMDGPU::V_FLOOR_F16_fake16_e64;
6004 case AMDGPU::S_TRUNC_F16:
6005 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6006 : AMDGPU::V_TRUNC_F16_fake16_e64;
6007 case AMDGPU::S_RNDNE_F16:
6008 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6009 : AMDGPU::V_RNDNE_F16_fake16_e64;
6010 case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
6011 case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
6012 case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
6013 case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
6014 case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
6015 case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
6016 case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
6017 case AMDGPU::S_ADD_F16:
6018 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6019 : AMDGPU::V_ADD_F16_fake16_e64;
6020 case AMDGPU::S_SUB_F16:
6021 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6022 : AMDGPU::V_SUB_F16_fake16_e64;
6023 case AMDGPU::S_MIN_F16:
6024 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6025 : AMDGPU::V_MIN_F16_fake16_e64;
6026 case AMDGPU::S_MAX_F16:
6027 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6028 : AMDGPU::V_MAX_F16_fake16_e64;
6029 case AMDGPU::S_MINIMUM_F16:
6030 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6031 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6032 case AMDGPU::S_MAXIMUM_F16:
6033 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6034 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6035 case AMDGPU::S_MUL_F16:
6036 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6037 : AMDGPU::V_MUL_F16_fake16_e64;
6038 case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6039 case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
6040 case AMDGPU::S_FMAC_F16:
6041 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6042 : AMDGPU::V_FMAC_F16_fake16_e64;
6043 case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
6044 case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
6045 case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
6046 case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
6047 case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
6048 case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
6049 case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
6050 case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
6051 case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
6052 case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
6053 case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
6054 case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
6055 case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
6056 case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
6057 case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
6058 case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
6059 case AMDGPU::S_CMP_LT_F16:
6060 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6061 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6062 case AMDGPU::S_CMP_EQ_F16:
6063 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6064 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6065 case AMDGPU::S_CMP_LE_F16:
6066 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6067 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6068 case AMDGPU::S_CMP_GT_F16:
6069 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6070 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6071 case AMDGPU::S_CMP_LG_F16:
6072 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6073 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6074 case AMDGPU::S_CMP_GE_F16:
6075 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6076 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6077 case AMDGPU::S_CMP_O_F16:
6078 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6079 : AMDGPU::V_CMP_O_F16_fake16_e64;
6080 case AMDGPU::S_CMP_U_F16:
6081 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6082 : AMDGPU::V_CMP_U_F16_fake16_e64;
6083 case AMDGPU::S_CMP_NGE_F16:
6084 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6085 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6086 case AMDGPU::S_CMP_NLG_F16:
6087 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6088 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6089 case AMDGPU::S_CMP_NGT_F16:
6090 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6091 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6092 case AMDGPU::S_CMP_NLE_F16:
6093 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6094 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6095 case AMDGPU::S_CMP_NEQ_F16:
6096 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6097 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6098 case AMDGPU::S_CMP_NLT_F16:
6099 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6100 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6101 case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
6102 case AMDGPU::V_S_EXP_F16_e64:
6103 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6104 : AMDGPU::V_EXP_F16_fake16_e64;
6105 case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
6106 case AMDGPU::V_S_LOG_F16_e64:
6107 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6108 : AMDGPU::V_LOG_F16_fake16_e64;
6109 case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
6110 case AMDGPU::V_S_RCP_F16_e64:
6111 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6112 : AMDGPU::V_RCP_F16_fake16_e64;
6113 case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
6114 case AMDGPU::V_S_RSQ_F16_e64:
6115 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6116 : AMDGPU::V_RSQ_F16_fake16_e64;
6117 case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
6118 case AMDGPU::V_S_SQRT_F16_e64:
6119 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6120 : AMDGPU::V_SQRT_F16_fake16_e64;
6121 }
6123 "Unexpected scalar opcode without corresponding vector one!");
6124}
6125
6126// clang-format on
6127
6131 const DebugLoc &DL, Register Reg,
6132 bool IsSCCLive,
6133 SlotIndexes *Indexes) const {
6134 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
6135 const SIInstrInfo *TII = ST.getInstrInfo();
6137 if (IsSCCLive) {
6138 // Insert two move instructions, one to save the original value of EXEC and
6139 // the other to turn on all bits in EXEC. This is required as we can't use
6140 // the single instruction S_OR_SAVEEXEC that clobbers SCC.
6141 auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
6143 auto FlipExecMI =
6144 BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
6145 if (Indexes) {
6146 Indexes->insertMachineInstrInMaps(*StoreExecMI);
6147 Indexes->insertMachineInstrInMaps(*FlipExecMI);
6148 }
6149 } else {
6150 auto SaveExec =
6151 BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
6152 SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
6153 if (Indexes)
6154 Indexes->insertMachineInstrInMaps(*SaveExec);
6155 }
6156}
6157
6160 const DebugLoc &DL, Register Reg,
6161 SlotIndexes *Indexes) const {
6163 auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
6164 .addReg(Reg, RegState::Kill);
6165 if (Indexes)
6166 Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
6167}
6168
6172 "Not a whole wave func");
6173 MachineBasicBlock &MBB = *MF.begin();
6174 for (MachineInstr &MI : MBB)
6175 if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6176 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6177 return &MI;
6178
6179 llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
6180}
6181
6183 unsigned OpNo) const {
6184 const MCInstrDesc &Desc = get(MI.getOpcode());
6185 if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
6186 Desc.operands()[OpNo].RegClass == -1) {
6187 Register Reg = MI.getOperand(OpNo).getReg();
6188
6189 if (Reg.isVirtual()) {
6190 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6191 return MRI.getRegClass(Reg);
6192 }
6193 return RI.getPhysRegBaseClass(Reg);
6194 }
6195
6196 int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
6197 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6198}
6199
6202 MachineBasicBlock *MBB = MI.getParent();
6203 MachineOperand &MO = MI.getOperand(OpIdx);
6204 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
6205 unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
6206 const TargetRegisterClass *RC = RI.getRegClass(RCID);
6207 unsigned Size = RI.getRegSizeInBits(*RC);
6208 unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6209 : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6210 : AMDGPU::V_MOV_B32_e32;
6211 if (MO.isReg())
6212 Opcode = AMDGPU::COPY;
6213 else if (RI.isSGPRClass(RC))
6214 Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6215
6216 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
6217 Register Reg = MRI.createVirtualRegister(VRC);
6218 DebugLoc DL = MBB->findDebugLoc(I);
6219 BuildMI(*MI.getParent(), I, DL, get(Opcode), Reg).add(MO);
6220 MO.ChangeToRegister(Reg, false);
6221}
6222
6225 const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
6226 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6227 if (!SuperReg.getReg().isVirtual())
6228 return RI.getSubReg(SuperReg.getReg(), SubIdx);
6229
6230 MachineBasicBlock *MBB = MI->getParent();
6231 const DebugLoc &DL = MI->getDebugLoc();
6232 Register SubReg = MRI.createVirtualRegister(SubRC);
6233
6234 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
6235 BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
6236 .addReg(SuperReg.getReg(), {}, NewSubIdx);
6237 return SubReg;
6238}
6239
6242 const MachineOperand &Op, const TargetRegisterClass *SuperRC,
6243 unsigned SubIdx, const TargetRegisterClass *SubRC) const {
6244 if (Op.isImm()) {
6245 if (SubIdx == AMDGPU::sub0)
6246 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
6247 if (SubIdx == AMDGPU::sub1)
6248 return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));
6249
6250 llvm_unreachable("Unhandled register index for immediate");
6251 }
6252
6253 unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
6254 SubIdx, SubRC);
6255 return MachineOperand::CreateReg(SubReg, false);
6256}
6257
6258// Change the order of operands from (0, 1, 2) to (0, 2, 1)
6259void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
6260 assert(Inst.getNumExplicitOperands() == 3);
6261 MachineOperand Op1 = Inst.getOperand(1);
6262 Inst.removeOperand(1);
6263 Inst.addOperand(Op1);
6264}
6265
6267 const MCOperandInfo &OpInfo,
6268 const MachineOperand &MO) const {
6269 if (!MO.isReg())
6270 return false;
6271
6272 Register Reg = MO.getReg();
6273
6274 const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
6275 if (Reg.isPhysical())
6276 return DRC->contains(Reg);
6277
6278 const TargetRegisterClass *RC = MRI.getRegClass(Reg);
6279
6280 if (MO.getSubReg()) {
6281 const MachineFunction *MF = MO.getParent()->getMF();
6282 const TargetRegisterClass *SuperRC = RI.getLargestLegalSuperClass(RC, *MF);
6283 if (!SuperRC)
6284 return false;
6285 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
6286 }
6287
6288 return RI.getCommonSubClass(DRC, RC) != nullptr;
6289}
6290
6292 const MachineOperand &MO) const {
6293 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
6294 const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
6295 unsigned Opc = MI.getOpcode();
6296
6297 // See SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand for more
6298 // information.
6299 if (AMDGPU::isPackedFP32or64BitInst(MI.getOpcode()) &&
6300 AMDGPU::isGFX12Plus(ST) && MO.isReg() && RI.isSGPRReg(MRI, MO.getReg())) {
6301 constexpr AMDGPU::OpName OpNames[] = {
6302 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6303
6304 for (auto [I, OpName] : enumerate(OpNames)) {
6305 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
6306 if (static_cast<unsigned>(SrcIdx) == OpIdx &&
6308 return false;
6309 }
6310 }
6311
6312 if (!isLegalRegOperand(MRI, OpInfo, MO))
6313 return false;
6314
6315 // check Accumulate GPR operand
6316 bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
6317 if (IsAGPR && !ST.hasMAIInsts())
6318 return false;
6319 if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
6320 (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
6321 return false;
6322 // Atomics should have both vdst and vdata either vgpr or agpr.
6323 const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
6324 const int DataIdx = AMDGPU::getNamedOperandIdx(
6325 Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6326 if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
6327 MI.getOperand(DataIdx).isReg() &&
6328 RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
6329 return false;
6330 if ((int)OpIdx == DataIdx) {
6331 if (VDstIdx != -1 &&
6332 RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6333 return false;
6334 // DS instructions with 2 src operands also must have tied RC.
6335 const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
6336 if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
6337 RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6338 return false;
6339 }
6340
6341 // Check V_ACCVGPR_WRITE_B32_e64
6342 if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6343 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
6344 RI.isSGPRReg(MRI, MO.getReg()))
6345 return false;
6346
6347 if (ST.hasFlatScratchHiInB64InstHazard() &&
6348 MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
6349 if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
6350 if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
6351 64)
6352 return false;
6353 }
6354 if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
6355 return false;
6356 }
6357 if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
6358 (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
6359 return false;
6360
6361 return true;
6362}
6363
6365 const MCOperandInfo &OpInfo,
6366 const MachineOperand &MO) const {
6367 if (MO.isReg())
6368 return isLegalRegOperand(MRI, OpInfo, MO);
6369
6370 // Handle non-register types that are treated like immediates.
6371 assert(MO.isImm() || MO.isTargetIndex() || MO.isFI() || MO.isGlobal());
6372 return true;
6373}
6374
6376 const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
6377 const MachineOperand *MO) const {
6378 constexpr unsigned NumOps = 3;
6379 constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
6380 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6381 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6382 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6383
6384 assert(SrcN < NumOps);
6385
6386 if (!MO) {
6387 int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
6388 if (SrcIdx == -1)
6389 return true;
6390 MO = &MI.getOperand(SrcIdx);
6391 }
6392
6393 if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
6394 return true;
6395
6396 int ModsIdx =
6397 AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
6398 if (ModsIdx == -1)
6399 return false;
6400
6401 unsigned Mods = MI.getOperand(ModsIdx).getImm();
6402 bool OpSel = Mods & SISrcMods::OP_SEL_0;
6403 bool OpSelHi = Mods & SISrcMods::OP_SEL_1;
6404
6405 return !OpSel && !OpSelHi;
6406}
6407
6409 const MachineOperand *MO) const {
6410 const MachineFunction &MF = *MI.getMF();
6411 const MachineRegisterInfo &MRI = MF.getRegInfo();
6412 const MCInstrDesc &InstDesc = MI.getDesc();
6413 const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
6414 int64_t RegClass = getOpRegClassID(OpInfo);
6415 const TargetRegisterClass *DefinedRC =
6416 RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
6417 if (!MO)
6418 MO = &MI.getOperand(OpIdx);
6419
6420 const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);
6421
6422 if (isVALU(MI, /*AllowLDSDMA=*/true) && !IsInlineConst &&
6423 usesConstantBus(MRI, *MO, OpInfo)) {
6424 const MachineOperand *UsedLiteral = nullptr;
6425
6426 int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
6427 int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;
6428
6429 // TODO: Be more permissive with frame indexes.
6430 if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
6431 if (!LiteralLimit--)
6432 return false;
6433
6434 UsedLiteral = MO;
6435 }
6436
6438 if (MO->isReg())
6439 SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));
6440
6441 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6442 if (i == OpIdx)
6443 continue;
6444 const MachineOperand &Op = MI.getOperand(i);
6445 if (Op.isReg()) {
6446 if (Op.isUse()) {
6447 RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
6448 if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
6449 if (--ConstantBusLimit <= 0)
6450 return false;
6451 }
6452 }
6453 } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
6454 !isInlineConstant(Op, InstDesc.operands()[i])) {
6455 // The same literal may be used multiple times.
6456 if (!UsedLiteral)
6457 UsedLiteral = &Op;
6458 else if (UsedLiteral->isIdenticalTo(Op))
6459 continue;
6460
6461 if (!LiteralLimit--)
6462 return false;
6463 if (--ConstantBusLimit <= 0)
6464 return false;
6465 }
6466 }
6467 } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
6468 // There can be at most one literal operand, but it can be repeated.
6469 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
6470 if (i == OpIdx)
6471 continue;
6472 const MachineOperand &Op = MI.getOperand(i);
6473 if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
6474 !isInlineConstant(Op, InstDesc.operands()[i]) &&
6475 !Op.isIdenticalTo(*MO))
6476 return false;
6477
6478 // Do not fold a non-inlineable and non-register operand into an
6479 // instruction that already has a frame index. The frame index handling
6480 // code could not handle well when a frame index co-exists with another
6481 // non-register operand, unless that operand is an inlineable immediate.
6482 if (Op.isFI())
6483 return false;
6484 }
6485 } else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6486 isF16PseudoScalarTrans(MI.getOpcode())) {
6487 return false;
6488 }
6489
6490 if (MO->isReg()) {
6491 if (!DefinedRC)
6492 return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
6493 return isLegalRegOperand(MI, OpIdx, *MO);
6494 }
6495
6496 if (MO->isImm()) {
6497 uint64_t Imm = MO->getImm();
6498 bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
6499 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
6500 bool Is64BitOp = Is64BitFPOp ||
6501 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
6502 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
6503 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
6504 OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
6505 if (Is64BitOp &&
6506 !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
6507 if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
6508 (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
6509 return false;
6510
6511 // FIXME: We can use sign extended 64-bit literals, but only for signed
6512 // operands. At the moment we do not know if an operand is signed.
6513 // Such operand will be encoded as its low 32 bits and then either
6514 // correctly sign extended or incorrectly zero extended by HW.
6515 // If 64-bit literals are supported and the literal will be encoded
6516 // as full 64 bit we still can use it.
6517 if (!Is64BitFPOp && (int32_t)Imm < 0 &&
6518 (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
6519 return false;
6520 }
6521 }
6522
6523 // Handle non-register types that are treated like immediates.
6524 assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());
6525
6526 if (!DefinedRC) {
6527 // This operand expects an immediate.
6528 return true;
6529 }
6530
6531 return isImmOperandLegal(MI, OpIdx, *MO);
6532}
6533
6535 bool IsGFX950Only = ST.hasGFX950Insts();
6536 bool IsGFX940Only = ST.hasGFX940Insts();
6537
6538 if (!IsGFX950Only && !IsGFX940Only)
6539 return false;
6540
6541 if (!isVALU(MI, /*AllowLDSDMA=*/true))
6542 return false;
6543
6544 // V_COS, V_EXP, V_RCP, etc.
6545 if (isTRANS(MI))
6546 return true;
6547
6548 // DOT2, DOT2C, DOT4, etc.
6549 if (isDOT(MI))
6550 return true;
6551
6552 // MFMA, SMFMA
6553 if (isMFMA(MI))
6554 return true;
6555
6556 unsigned Opcode = MI.getOpcode();
6557 switch (Opcode) {
6558 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6559 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6560 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6561 case AMDGPU::V_MQSAD_U32_U8_e64:
6562 case AMDGPU::V_PK_ADD_F16:
6563 case AMDGPU::V_PK_ADD_F32:
6564 case AMDGPU::V_PK_ADD_I16:
6565 case AMDGPU::V_PK_ADD_U16:
6566 case AMDGPU::V_PK_ASHRREV_I16:
6567 case AMDGPU::V_PK_FMA_F16:
6568 case AMDGPU::V_PK_FMA_F32:
6569 case AMDGPU::V_PK_FMAC_F16_e32:
6570 case AMDGPU::V_PK_FMAC_F16_e64:
6571 case AMDGPU::V_PK_LSHLREV_B16:
6572 case AMDGPU::V_PK_LSHRREV_B16:
6573 case AMDGPU::V_PK_MAD_I16:
6574 case AMDGPU::V_PK_MAD_U16:
6575 case AMDGPU::V_PK_MAX_F16:
6576 case AMDGPU::V_PK_MAX_I16:
6577 case AMDGPU::V_PK_MAX_U16:
6578 case AMDGPU::V_PK_MIN_F16:
6579 case AMDGPU::V_PK_MIN_I16:
6580 case AMDGPU::V_PK_MIN_U16:
6581 case AMDGPU::V_PK_MOV_B32:
6582 case AMDGPU::V_PK_MUL_F16:
6583 case AMDGPU::V_PK_MUL_F32:
6584 case AMDGPU::V_PK_MUL_LO_U16:
6585 case AMDGPU::V_PK_SUB_I16:
6586 case AMDGPU::V_PK_SUB_U16:
6587 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6588 return true;
6589 default:
6590 return false;
6591 }
6592}
6593
6595 MachineInstr &MI) const {
6596 unsigned Opc = MI.getOpcode();
6597 const MCInstrDesc &InstrDesc = get(Opc);
6598
6599 int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
6600 MachineOperand &Src0 = MI.getOperand(Src0Idx);
6601
6602 int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
6603 MachineOperand &Src1 = MI.getOperand(Src1Idx);
6604
6605 // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
6606 // we need to only have one constant bus use before GFX10.
6607 bool HasImplicitSGPR = findImplicitSGPRRead(MI);
6608 if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
6609 RI.isSGPRReg(MRI, Src0.getReg()))
6610 legalizeOpWithMove(MI, Src0Idx);
6611
6612 // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
6613 // both the value to write (src0) and lane select (src1). Fix up non-SGPR
6614 // src0/src1 with V_READFIRSTLANE.
6615 if (Opc == AMDGPU::V_WRITELANE_B32) {
6616 const DebugLoc &DL = MI.getDebugLoc();
6617 if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
6618 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6619 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6620 .add(Src0);
6621 Src0.ChangeToRegister(Reg, false);
6622 }
6623 if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
6624 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6625 const DebugLoc &DL = MI.getDebugLoc();
6626 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6627 .add(Src1);
6628 Src1.ChangeToRegister(Reg, false);
6629 }
6630 return;
6631 }
6632
6633 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
6634 if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
6635 int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
6636 if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
6637 legalizeOpWithMove(MI, Src2Idx);
6638 }
6639
6640 // VOP2 src0 instructions support all operand types, so we don't need to check
6641 // their legality. If src1 is already legal, we don't need to do anything.
6642 if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
6643 return;
6644
6645 // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
6646 // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
6647 // select is uniform.
6648 if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
6649 RI.isVGPR(MRI, Src1.getReg())) {
6650 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6651 const DebugLoc &DL = MI.getDebugLoc();
6652 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6653 .add(Src1);
6654 Src1.ChangeToRegister(Reg, false);
6655 return;
6656 }
6657
6658 // We do not use commuteInstruction here because it is too aggressive and will
6659 // commute if it is possible. We only want to commute here if it improves
6660 // legality. This can be called a fairly large number of times so don't waste
6661 // compile time pointlessly swapping and checking legality again.
6662 if (HasImplicitSGPR || !MI.isCommutable()) {
6663 legalizeOpWithMove(MI, Src1Idx);
6664 return;
6665 }
6666
6667 // If src0 can be used as src1, commuting will make the operands legal.
6668 // Otherwise we have to give up and insert a move.
6669 //
6670 // TODO: Other immediate-like operand kinds could be commuted if there was a
6671 // MachineOperand::ChangeTo* for them.
6672 if ((!Src1.isImm() && !Src1.isReg()) ||
6673 !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
6674 legalizeOpWithMove(MI, Src1Idx);
6675 return;
6676 }
6677
6678 int CommutedOpc = commuteOpcode(MI);
6679 if (CommutedOpc == -1) {
6680 legalizeOpWithMove(MI, Src1Idx);
6681 return;
6682 }
6683
6684 MI.setDesc(get(CommutedOpc));
6685
6686 Register Src0Reg = Src0.getReg();
6687 unsigned Src0SubReg = Src0.getSubReg();
6688 bool Src0Kill = Src0.isKill();
6689
6690 if (Src1.isImm())
6691 Src0.ChangeToImmediate(Src1.getImm());
6692 else if (Src1.isReg()) {
6693 Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
6694 Src0.setSubReg(Src1.getSubReg());
6695 } else
6696 llvm_unreachable("Should only have register or immediate operands");
6697
6698 Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
6699 Src1.setSubReg(Src0SubReg);
6701}
6702
6703// Legalize VOP3 operands. All operand types are supported for any operand
6704// but only one literal constant and only starting from GFX10.
6706 MachineInstr &MI) const {
6707 unsigned Opc = MI.getOpcode();
6708
6709 int VOP3Idx[3] = {
6710 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
6711 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
6712 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
6713 };
6714
6715 if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6716 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6717 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6718 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6719 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6720 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6721 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6722 // src1 and src2 must be scalar
6723 MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
6724 const DebugLoc &DL = MI.getDebugLoc();
6725 if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
6726 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6727 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6728 .add(Src1);
6729 Src1.ChangeToRegister(Reg, false);
6730 }
6731 if (VOP3Idx[2] != -1) {
6732 MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
6733 if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
6734 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
6735 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
6736 .add(Src2);
6737 Src2.ChangeToRegister(Reg, false);
6738 }
6739 }
6740 }
6741
6742 // Find the one SGPR operand we are allowed to use.
6743 int ConstantBusLimit = ST.getConstantBusLimit(Opc);
6744 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
6745 SmallDenseSet<unsigned> SGPRsUsed;
6746 Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
6747 if (SGPRReg) {
6748 SGPRsUsed.insert(SGPRReg);
6749 --ConstantBusLimit;
6750 }
6751
6752 for (int Idx : VOP3Idx) {
6753 if (Idx == -1)
6754 break;
6755 MachineOperand &MO = MI.getOperand(Idx);
6756
6757 if (!MO.isReg()) {
6758 if (isInlineConstant(MO, get(Opc).operands()[Idx]))
6759 continue;
6760
6761 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
6762 --LiteralLimit;
6763 --ConstantBusLimit;
6764 continue;
6765 }
6766
6767 --LiteralLimit;
6768 --ConstantBusLimit;
6769 legalizeOpWithMove(MI, Idx);
6770 continue;
6771 }
6772
6773 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
6774 continue; // VGPRs are legal
6775
6776 // We can use one SGPR in each VOP3 instruction prior to GFX10
6777 // and two starting from GFX10.
6778 if (SGPRsUsed.count(MO.getReg()))
6779 continue;
6780 if (ConstantBusLimit > 0) {
6781 SGPRsUsed.insert(MO.getReg());
6782 --ConstantBusLimit;
6783 continue;
6784 }
6785
6786 // If we make it this far, then the operand is not legal and we must
6787 // legalize it.
6788 legalizeOpWithMove(MI, Idx);
6789 }
6790
6791 // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
6792 if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64) &&
6793 !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
6794 legalizeOpWithMove(MI, VOP3Idx[2]);
6795
6796 // Fix the register class of packed FP32 instructions on gfx12+. See
6797 // SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand for more
6798 // information.
6800 for (unsigned I = 0; I < 3; ++I) {
6802 legalizeOpWithMove(MI, VOP3Idx[I]);
6803 }
6804 }
6805}
6806
6809 const TargetRegisterClass *DstRC /*=nullptr*/) const {
6810 const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
6811 const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
6812 if (DstRC)
6813 SRC = RI.getCommonSubClass(SRC, DstRC);
6814
6815 Register DstReg = MRI.createVirtualRegister(SRC);
6816 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
6817
6818 if (RI.hasAGPRs(VRC)) {
6819 VRC = RI.getEquivalentVGPRClass(VRC);
6820 Register NewSrcReg = MRI.createVirtualRegister(VRC);
6821 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6822 get(TargetOpcode::COPY), NewSrcReg)
6823 .addReg(SrcReg);
6824 SrcReg = NewSrcReg;
6825 }
6826
6827 if (SubRegs == 1) {
6828 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6829 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
6830 .addReg(SrcReg);
6831 return DstReg;
6832 }
6833
6835 for (unsigned i = 0; i < SubRegs; ++i) {
6836 Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
6837 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6838 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
6839 .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
6840 SRegs.push_back(SGPR);
6841 }
6842
6844 BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
6845 get(AMDGPU::REG_SEQUENCE), DstReg);
6846 for (unsigned i = 0; i < SubRegs; ++i) {
6847 MIB.addReg(SRegs[i]);
6848 MIB.addImm(RI.getSubRegFromChannel(i));
6849 }
6850 return DstReg;
6851}
6852
6854 MachineInstr &MI) const {
6855
6856 // If the pointer is store in VGPRs, then we need to move them to
6857 // SGPRs using v_readfirstlane. This is safe because we only select
6858 // loads with uniform pointers to SMRD instruction so we know the
6859 // pointer value is uniform.
6860 MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
6861 if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
6862 Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
6863 SBase->setReg(SGPR);
6864 }
6865 MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
6866 if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
6867 Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
6868 SOff->setReg(SGPR);
6869 }
6870}
6871
6873 unsigned Opc = Inst.getOpcode();
6874 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
6875 if (OldSAddrIdx < 0)
6876 return false;
6877
6878 assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));
6879
6880 int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
6881 if (NewOpc < 0)
6883 if (NewOpc < 0)
6884 return false;
6885
6886 MachineRegisterInfo &MRI = Inst.getMF()->getRegInfo();
6887 MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
6888 if (RI.isSGPRReg(MRI, SAddr.getReg()))
6889 return false;
6890
6891 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
6892 if (NewVAddrIdx < 0)
6893 return false;
6894
6895 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);
6896
6897 // Check vaddr, it shall be zero or absent.
6898 MachineInstr *VAddrDef = nullptr;
6899 if (OldVAddrIdx >= 0) {
6900 MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
6901 VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
6902 if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
6903 !VAddrDef->getOperand(1).isImm() ||
6904 VAddrDef->getOperand(1).getImm() != 0)
6905 return false;
6906 }
6907
6908 const MCInstrDesc &NewDesc = get(NewOpc);
6909 Inst.setDesc(NewDesc);
6910
6911 // Callers expect iterator to be valid after this call, so modify the
6912 // instruction in place.
6913 if (OldVAddrIdx == NewVAddrIdx) {
6914 MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
6915 // Clear use list from the old vaddr holding a zero register.
6916 MRI.removeRegOperandFromUseList(&NewVAddr);
6917 MRI.moveOperands(&NewVAddr, &SAddr, 1);
6918 Inst.removeOperand(OldSAddrIdx);
6919 // Update the use list with the pointer we have just moved from vaddr to
6920 // saddr position. Otherwise new vaddr will be missing from the use list.
6921 MRI.removeRegOperandFromUseList(&NewVAddr);
6922 MRI.addRegOperandToUseList(&NewVAddr);
6923 } else {
6924 assert(OldSAddrIdx == NewVAddrIdx);
6925
6926 if (OldVAddrIdx >= 0) {
6927 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
6928 AMDGPU::OpName::vdst_in);
6929
6930 // removeOperand doesn't try to fixup tied operand indexes at it goes, so
6931 // it asserts. Untie the operands for now and retie them afterwards.
6932 if (NewVDstIn != -1) {
6933 int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
6934 Inst.untieRegOperand(OldVDstIn);
6935 }
6936
6937 Inst.removeOperand(OldVAddrIdx);
6938
6939 if (NewVDstIn != -1) {
6940 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
6941 Inst.tieOperands(NewVDst, NewVDstIn);
6942 }
6943 }
6944 }
6945
6946 if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
6947 VAddrDef->eraseFromParent();
6948
6949 return true;
6950}
6951
6952// FIXME: Remove this when SelectionDAG is obsoleted.
6954 MachineInstr &MI) const {
6955 if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
6956 return;
6957
6958 // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
6959 // thinks they are uniform, so a readfirstlane should be valid.
6960 MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
6961 if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
6962 return;
6963
6965 return;
6966
6967 const TargetRegisterClass *DeclaredRC =
6968 getRegClass(MI.getDesc(), SAddr->getOperandNo());
6969
6970 Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
6971 SAddr->setReg(ToSGPR);
6972}
6973
6976 const TargetRegisterClass *DstRC,
6979 const DebugLoc &DL) const {
6980 Register OpReg = Op.getReg();
6981 unsigned OpSubReg = Op.getSubReg();
6982
6983 const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
6984 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
6985
6986 // Check if operand is already the correct register class.
6987 if (DstRC == OpRC)
6988 return;
6989
6990 Register DstReg = MRI.createVirtualRegister(DstRC);
6991 auto Copy =
6992 BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg).addReg(OpReg);
6993 Op.setReg(DstReg);
6994
6995 MachineInstr *Def = MRI.getVRegDef(OpReg);
6996 if (!Def)
6997 return;
6998
6999 // Try to eliminate the copy if it is copying an immediate value.
7000 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7001 foldImmediate(*Copy, *Def, OpReg, &MRI);
7002
7003 bool ImpDef = Def->isImplicitDef();
7004 while (!ImpDef && Def && Def->isCopy()) {
7005 if (Def->getOperand(1).getReg().isPhysical())
7006 break;
7007 Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7008 ImpDef = Def && Def->isImplicitDef();
7009 }
7010 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7011 !ImpDef)
7012 Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
7013}
7014
7015// Emit the actual waterfall loop, executing the wrapped instruction for each
7016// unique value of \p ScalarOps across all lanes. In the best case we execute 1
7017// iteration, in the worst case we execute 64 (once per lane).
7020 MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
7021 ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
7022 MachineFunction &MF = *LoopBB.getParent();
7024 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7026 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7027
7028 // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
7029 // available. Otherwise, use the previous pattern of v_cmp_eq,
7030 // s_and_saveexec, and s_xor.
7031 bool UseNewExecInstructions =
7032 ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;
7033
7035 Register CondReg;
7036
7037 Register PhiExec;
7038 Register NewExec;
7039
7040 if (UseNewExecInstructions) {
7041 PhiExec = MRI.createVirtualRegister(BoolXExecRC);
7042 NewExec = MRI.createVirtualRegister(BoolXExecRC);
7043 Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
7044 BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
7045 .addReg(LMC.ExecReg);
7046
7047 BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
7048 .addReg(InitExec)
7049 .addMBB(&PredBB)
7050 .addReg(NewExec)
7051 .addMBB(&BodyBB);
7052 }
7053
7054 // Placement of v_cmpx instructions (when index is longer than 64 bit)
7055 // involves a trade-off between register pressure and latency:
7056 // (a) Defering all v_cmpx after all v_readfirstlane may increase
7057 // register pressure because arguments and results of all
7058 // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
7059 // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
7060 // increase latency by placing v_readfirstlane instructions
7061 // immediately before v_cmpx instruction that directly depend on it.
7062 ///
7063 // Emitting interleaved v_cmpx and v_readfirstlane requires
7064 // block splitting because v_cmpx changes EXEC mask and therefore for safety
7065 // v_cmpx needs to be treated as terminator until after register allocation
7066 // (spill placement) and instruction reordering.
7067 //
7068 // Current implementation defers v_cmpx and leaves other instruction
7069 // scheduling decisions to later passes, where register pressure is known or
7070 // easier to approximate.
7071 // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
7072 // v_cmpx instructions are inserted at the end of LoopBB.
7073 // After the first v_cmpx is emitted, I is updated to point to it
7074 // so subsequent non-terminators are inserted before all v_cmpx instructions.
7075 for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
7076 unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7077 unsigned NumSubRegs = RegSize / 32;
7078 Register VScalarOp = ScalarOp->getReg();
7079
7080 const TargetRegisterClass *RFLSrcRC =
7081 TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7082
7083 if (NumSubRegs == 1) {
7084 const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
7085 if (const TargetRegisterClass *Common =
7086 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7087 Common != VScalarOpRC) {
7088 Register VRReg = MRI.createVirtualRegister(Common);
7089 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
7090 VScalarOp = VRReg;
7091 }
7092 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7093
7094 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7095 .addReg(VScalarOp);
7096
7097 if (UseNewExecInstructions) {
7098 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7099 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7100 .addReg(CurReg)
7101 .addReg(VScalarOp);
7102 if (I == LoopBB.end())
7103 I = CmpxMI.getInstr()->getIterator();
7104 } else {
7105 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7106
7107 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7108 .addReg(CurReg)
7109 .addReg(VScalarOp);
7110
7111 // Combine the comparison results with AND.
7112 if (!CondReg) { // First.
7113 CondReg = NewCondReg;
7114 } else { // If not the first, we create an AND.
7115 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7116 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7117 .addReg(CondReg)
7118 .addReg(NewCondReg);
7119 CondReg = AndReg;
7120 }
7121 }
7122
7123 // Update ScalarOp operand to use the SGPR ScalarOp.
7124 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7125 ScalarOp->setReg(CurReg);
7126 else {
7127 // Insert into the same block of use
7128 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7129 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7130 .addReg(CurReg);
7131 ScalarOp->setReg(PhySGPRs[Idx]);
7132 }
7133 ScalarOp->setIsKill();
7134 } else {
7135 SmallVector<Register, 8> ReadlanePieces;
7136 RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
7137 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7138 "Unhandled register size");
7139
7140 for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7141 Register CurRegLo =
7142 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7143 Register CurRegHi =
7144 MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7145
7146 // Read the next variant <- also loop target.
7147 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7148 .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));
7149
7150 // Read the next variant <- also loop target.
7151 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7152 .addReg(VScalarOp, VScalarOpUndef,
7153 TRI->getSubRegFromChannel(Idx + 1));
7154
7155 ReadlanePieces.push_back(CurRegLo);
7156 ReadlanePieces.push_back(CurRegHi);
7157
7158 // Comparison is to be done as 64-bit.
7159 Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
7160 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7161 .addReg(CurRegLo)
7162 .addImm(AMDGPU::sub0)
7163 .addReg(CurRegHi)
7164 .addImm(AMDGPU::sub1);
7165
7166 unsigned SubReg =
7167 NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);
7168
7169 if (UseNewExecInstructions) {
7170 auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
7171 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7172 .addReg(CurReg)
7173 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7174 if (I == LoopBB.end())
7175 I = CmpxMI.getInstr()->getIterator();
7176 } else {
7177 Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
7178 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7179 .addReg(CurReg)
7180 .addReg(VScalarOp, VScalarOpUndef, SubReg);
7181
7182 // Combine the comparison results with AND.
7183 if (!CondReg) { // First.
7184 CondReg = NewCondReg;
7185 } else { // If not the first, we create an AND.
7186 Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
7187 BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
7188 .addReg(CondReg)
7189 .addReg(NewCondReg);
7190 CondReg = AndReg;
7191 }
7192 }
7193 } // End for loop.
7194
7195 const auto *SScalarOpRC =
7196 TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
7197 Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);
7198
7199 // Build scalar ScalarOp.
7200 auto Merge =
7201 BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7202 unsigned Channel = 0;
7203 for (Register Piece : ReadlanePieces) {
7204 Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
7205 }
7206
7207 // Update ScalarOp operand to use the SGPR ScalarOp.
7208 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7209 ScalarOp->setReg(SScalarOp);
7210 else {
7211 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
7212 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7213 .addReg(SScalarOp);
7214 ScalarOp->setReg(PhySGPRs[Idx]);
7215 }
7216 ScalarOp->setIsKill();
7217 }
7218 }
7219
7220 // Instructions AndSaveExecOpc and AndN2WrExecOpc that modify EXEC mask
7221 // should have isTerminator=1 but terminators that define
7222 // virtual registers are not supported.
7223 Register SaveExec;
7224 if (!UseNewExecInstructions) {
7225 SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7226 MRI.setSimpleHint(SaveExec, CondReg);
7227
7228 // Update EXEC to matching lanes, saving original to SaveExec.
7229 BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
7230 .addReg(CondReg, RegState::Kill);
7231 }
7232
7233 // The original instruction is here; we insert the terminators after it.
7234 I = BodyBB.end();
7235
7236 if (UseNewExecInstructions) {
7237 MRI.setSimpleHint(NewExec, PhiExec);
7238 BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2WrExecOpc), NewExec)
7239 .addReg(PhiExec);
7240 } else {
7241 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
7242 BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
7243 .addReg(LMC.ExecReg)
7244 .addReg(SaveExec);
7245 }
7246
7247 BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
7248}
7249
7250// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
7251// with SGPRs by iterating over all unique values across all lanes.
7252// Returns the loop basic block that now contains \p MI.
7253static MachineBasicBlock *
7257 MachineBasicBlock::iterator Begin = nullptr,
7258 MachineBasicBlock::iterator End = nullptr,
7259 ArrayRef<Register> PhySGPRs = {}) {
7260 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
7261 "Physical SGPRs must be empty or match the number of scalar operands");
7262 MachineBasicBlock &MBB = *MI.getParent();
7263 MachineFunction &MF = *MBB.getParent();
7265 const SIRegisterInfo *TRI = ST.getRegisterInfo();
7266 MachineRegisterInfo &MRI = MF.getRegInfo();
7267 if (!Begin.isValid())
7268 Begin = &MI;
7269 if (!End.isValid()) {
7270 End = &MI;
7271 ++End;
7272 }
7273 const DebugLoc &DL = MI.getDebugLoc();
7275 const auto *BoolXExecRC = TRI->getWaveMaskRegClass();
7276
7277 // Save SCC. Waterfall Loop may overwrite SCC.
7278 Register SaveSCCReg;
7279
7280 // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
7281 // rather than unlimited scan everywhere
7282 bool SCCNotDead =
7283 MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
7284 std::numeric_limits<unsigned>::max()) !=
7286 if (SCCNotDead) {
7287 SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
7288 BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
7289 .addImm(1)
7290 .addImm(0);
7291 }
7292
7293 Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);
7294
7295 // Save the EXEC mask
7296 BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);
7297
7298 // Killed uses in the instruction we are waterfalling around will be
7299 // incorrect due to the added control-flow.
7301 ++AfterMI;
7302 for (auto I = Begin; I != AfterMI; I++) {
7303 for (auto &MO : I->all_uses())
7304 MRI.clearKillFlags(MO.getReg());
7305 }
7306
7307 // To insert the loop we need to split the block. Move everything after this
7308 // point to a new block, and insert a new empty block between the two.
7311 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
7313 ++MBBI;
7314
7315 MF.insert(MBBI, LoopBB);
7316 MF.insert(MBBI, BodyBB);
7317 MF.insert(MBBI, RemainderBB);
7318
7319 LoopBB->addSuccessor(BodyBB);
7320 BodyBB->addSuccessor(LoopBB);
7321 BodyBB->addSuccessor(RemainderBB);
7322
7323 // Move Begin to MI to the BodyBB, and the remainder of the block to
7324 // RemainderBB.
7325 RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
7326 RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
7327 BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());
7328
7329 MBB.addSuccessor(LoopBB);
7330
7331 // Update dominators. We know that MBB immediately dominates LoopBB, that
7332 // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
7333 // RemainderBB. RemainderBB immediately dominates all of the successors
7334 // transferred to it from MBB that MBB used to properly dominate.
7335 if (MDT) {
7336 MDT->addNewBlock(LoopBB, &MBB);
7337 MDT->addNewBlock(BodyBB, LoopBB);
7338 MDT->addNewBlock(RemainderBB, BodyBB);
7339 for (auto &Succ : RemainderBB->successors()) {
7340 if (MDT->properlyDominates(&MBB, Succ)) {
7341 MDT->changeImmediateDominator(Succ, RemainderBB);
7342 }
7343 }
7344 }
7345
7346 emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
7347 PhySGPRs);
7348
7349 MachineBasicBlock::iterator First = RemainderBB->begin();
7350 // Restore SCC
7351 if (SCCNotDead) {
7352 BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
7353 .addReg(SaveSCCReg, RegState::Kill)
7354 .addImm(0);
7355 }
7356
7357 // Restore the EXEC mask
7358 BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
7359 .addReg(SaveExec);
7360 return BodyBB;
7361}
7362
7363// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
7364static std::tuple<unsigned, unsigned>
7366 MachineBasicBlock &MBB = *MI.getParent();
7367 MachineFunction &MF = *MBB.getParent();
7368 MachineRegisterInfo &MRI = MF.getRegInfo();
7369
7370 // Extract the ptr from the resource descriptor.
7371 unsigned RsrcPtr =
7372 TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7373 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7374
7375 // Create an empty resource descriptor
7376 Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7377 Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7378 Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7379 Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7380 uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();
7381
7382 // Zero64 = 0
7383 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
7384 .addImm(0);
7385
7386 // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
7387 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
7388 .addImm(Lo_32(RsrcDataFormat));
7389
7390 // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
7391 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
7392 .addImm(Hi_32(RsrcDataFormat));
7393
7394 // NewSRsrc = {Zero64, SRsrcFormat}
7395 BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
7396 .addReg(Zero64)
7397 .addImm(AMDGPU::sub0_sub1)
7398 .addReg(SRsrcFormatLo)
7399 .addImm(AMDGPU::sub2)
7400 .addReg(SRsrcFormatHi)
7401 .addImm(AMDGPU::sub3);
7402
7403 return std::tuple(RsrcPtr, NewSRsrc);
7404}
7405
7408 MachineDominatorTree *MDT) const {
7409 MachineFunction &MF = *MI.getMF();
7410 MachineRegisterInfo &MRI = MF.getRegInfo();
7411 MachineBasicBlock *CreatedBB = nullptr;
7412
7413 // Legalize VOP2
7414 if (isVOP2(MI) || isVOPC(MI)) {
7416 return CreatedBB;
7417 }
7418
7419 // Legalize VOP3
7420 if (isVOP3(MI)) {
7422 return CreatedBB;
7423 }
7424
7425 // Legalize SMRD
7426 if (isSMRD(MI)) {
7428 return CreatedBB;
7429 }
7430
7431 // Legalize FLAT
7432 if (isFLAT(MI)) {
7434 return CreatedBB;
7435 }
7436
7437 // Legalize PHI
7438 // The register class of the operands must be the same type as the register
7439 // class of the output.
7440 if (MI.getOpcode() == AMDGPU::PHI) {
7441 const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
7442 assert(!RI.isSGPRClass(VRC));
7443
7444 // Update all the operands so they have the same type.
7445 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7446 MachineOperand &Op = MI.getOperand(I);
7447 if (!Op.isReg() || !Op.getReg().isVirtual())
7448 continue;
7449
7450 // MI is a PHI instruction.
7451 MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
7453
7454 // Avoid creating no-op copies with the same src and dst reg class. These
7455 // confuse some of the machine passes.
7456 legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
7457 }
7458 }
7459
7460 // REG_SEQUENCE doesn't really require operand legalization, but if one has a
7461 // VGPR dest type and SGPR sources, insert copies so all operands are
7462 // VGPRs. This seems to help operand folding / the register coalescer.
7463 if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7464 MachineBasicBlock *MBB = MI.getParent();
7465 const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
7466 if (RI.hasVGPRs(DstRC)) {
7467 // Update all the operands so they are VGPR register classes. These may
7468 // not be the same register class because REG_SEQUENCE supports mixing
7469 // subregister index types e.g. sub0_sub1 + sub2 + sub3
7470 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
7471 MachineOperand &Op = MI.getOperand(I);
7472 if (!Op.isReg() || !Op.getReg().isVirtual())
7473 continue;
7474
7475 const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
7476 const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
7477 if (VRC == OpRC)
7478 continue;
7479
7480 legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
7481 Op.setIsKill();
7482 }
7483 }
7484
7485 return CreatedBB;
7486 }
7487
7488 // Legalize INSERT_SUBREG
7489 // src0 must have the same register class as dst
7490 if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7491 Register Dst = MI.getOperand(0).getReg();
7492 Register Src0 = MI.getOperand(1).getReg();
7493 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
7494 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
7495 if (DstRC != Src0RC) {
7496 MachineBasicBlock *MBB = MI.getParent();
7497 MachineOperand &Op = MI.getOperand(1);
7498 legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
7499 }
7500 return CreatedBB;
7501 }
7502
7503 // Legalize SI_INIT_M0
7504 if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7505 MachineOperand &Src = MI.getOperand(0);
7506 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7507 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7508 return CreatedBB;
7509 }
7510
7511 // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
7512 if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7513 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7514 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7515 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7516 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7517 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7518 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7519 MachineOperand &Src = MI.getOperand(1);
7520 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7521 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7522 return CreatedBB;
7523 }
7524
7525 // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
7526 //
7527 // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
7528 // scratch memory access. In both cases, the legalization never involves
7529 // conversion to the addr64 form.
7531 (isMUBUF(MI) || isMTBUF(MI)))) {
7532 AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
7533 ? AMDGPU::OpName::rsrc
7534 : AMDGPU::OpName::srsrc;
7535 MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
7536 if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
7537 CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);
7538
7539 AMDGPU::OpName SampOpName =
7540 isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7541 MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
7542 if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
7543 CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);
7544
7545 return CreatedBB;
7546 }
7547
7548 // Legalize SI_CALL
7549 if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7550 MachineOperand *Dest = &MI.getOperand(0);
7551 if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
7552 createWaterFallForSiCall(&MI, MDT, {Dest});
7553 }
7554 }
7555
7556 // Legalize s_sleep_var.
7557 if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7558 const DebugLoc &DL = MI.getDebugLoc();
7559 Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7560 int Src0Idx =
7561 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
7562 MachineOperand &Src0 = MI.getOperand(Src0Idx);
7563 BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
7564 .add(Src0);
7565 Src0.ChangeToRegister(Reg, false);
7566 return nullptr;
7567 }
7568
7569 // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
7570 // operands are scalar.
7571 if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7572 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7573 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7574 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7575 for (MachineOperand &Src : MI.explicit_operands()) {
7576 if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
7577 Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
7578 }
7579 return CreatedBB;
7580 }
7581
7582 // Legalize MUBUF instructions.
7583 bool isSoffsetLegal = true;
7584 int SoffsetIdx =
7585 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
7586 if (SoffsetIdx != -1) {
7587 MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
7588 if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
7589 !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
7590 isSoffsetLegal = false;
7591 }
7592 }
7593
7594 bool isRsrcLegal = true;
7595 int RsrcIdx =
7596 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
7597 if (RsrcIdx != -1) {
7598 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7599 if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
7600 isRsrcLegal = false;
7601 }
7602
7603 // The operands are legal.
7604 if (isRsrcLegal && isSoffsetLegal)
7605 return CreatedBB;
7606
7607 if (!isRsrcLegal) {
7608 // Legalize a VGPR Rsrc
7609 //
7610 // If the instruction is _ADDR64, we can avoid a waterfall by extracting
7611 // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
7612 // a zero-value SRsrc.
7613 //
7614 // If the instruction is _OFFSET (both idxen and offen disabled), and we
7615 // support ADDR64 instructions, we can convert to ADDR64 and do the same as
7616 // above.
7617 //
7618 // Otherwise we are on non-ADDR64 hardware, and/or we have
7619 // idxen/offen/bothen and we fall back to a waterfall loop.
7620
7621 MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
7622 MachineBasicBlock &MBB = *MI.getParent();
7623
7624 MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
7625 if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
7626 // This is already an ADDR64 instruction so we need to add the pointer
7627 // extracted from the resource descriptor to the current value of VAddr.
7628 Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7629 Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7630 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7631
7632 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7633 Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
7634 Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);
7635
7636 unsigned RsrcPtr, NewSRsrc;
7637 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7638
7639 // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
7640 const DebugLoc &DL = MI.getDebugLoc();
7641 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
7642 .addDef(CondReg0)
7643 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7644 .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
7645 .addImm(0);
7646
7647 // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
7648 BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
7649 .addDef(CondReg1, RegState::Dead)
7650 .addReg(RsrcPtr, {}, AMDGPU::sub1)
7651 .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
7652 .addReg(CondReg0, RegState::Kill)
7653 .addImm(0);
7654
7655 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7656 BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
7657 .addReg(NewVAddrLo)
7658 .addImm(AMDGPU::sub0)
7659 .addReg(NewVAddrHi)
7660 .addImm(AMDGPU::sub1);
7661
7662 VAddr->setReg(NewVAddr);
7663 Rsrc->setReg(NewSRsrc);
7664 } else if (!VAddr && ST.hasAddr64()) {
7665 // This instructions is the _OFFSET variant, so we need to convert it to
7666 // ADDR64.
7667 assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
7668 "FIXME: Need to emit flat atomics here");
7669
7670 unsigned RsrcPtr, NewSRsrc;
7671 std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);
7672
7673 Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
7674 MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
7675 MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
7676 MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7677 unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());
7678
7679 // Atomics with return have an additional tied operand and are
7680 // missing some of the special bits.
7681 MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
7682 MachineInstr *Addr64;
7683
7684 if (!VDataIn) {
7685 // Regular buffer load / store.
7687 BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7688 .add(*VData)
7689 .addReg(NewVAddr)
7690 .addReg(NewSRsrc)
7691 .add(*SOffset)
7692 .add(*Offset);
7693
7694 if (const MachineOperand *CPol =
7695 getNamedOperand(MI, AMDGPU::OpName::cpol)) {
7696 MIB.addImm(CPol->getImm());
7697 }
7698
7699 if (const MachineOperand *TFE =
7700 getNamedOperand(MI, AMDGPU::OpName::tfe)) {
7701 MIB.addImm(TFE->getImm());
7702 }
7703
7704 MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));
7705
7706 MIB.cloneMemRefs(MI);
7707 Addr64 = MIB;
7708 } else {
7709 // Atomics with return.
7710 Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
7711 .add(*VData)
7712 .add(*VDataIn)
7713 .addReg(NewVAddr)
7714 .addReg(NewSRsrc)
7715 .add(*SOffset)
7716 .add(*Offset)
7717 .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
7718 .cloneMemRefs(MI);
7719 }
7720
7721 MI.removeFromParent();
7722
7723 // NewVaddr = {NewVaddrHi, NewVaddrLo}
7724 BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
7725 NewVAddr)
7726 .addReg(RsrcPtr, {}, AMDGPU::sub0)
7727 .addImm(AMDGPU::sub0)
7728 .addReg(RsrcPtr, {}, AMDGPU::sub1)
7729 .addImm(AMDGPU::sub1);
7730 } else {
7731 // Legalize a VGPR Rsrc and soffset together.
7732 if (!isSoffsetLegal) {
7733 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7734 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
7735 return CreatedBB;
7736 }
7737 CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
7738 return CreatedBB;
7739 }
7740 }
7741
7742 // Legalize a VGPR soffset.
7743 if (!isSoffsetLegal) {
7744 MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
7745 CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
7746 return CreatedBB;
7747 }
7748 return CreatedBB;
7749}
7750
7752 InstrList.insert(MI);
7753 // Add MBUF instructiosn to deferred list.
7754 int RsrcIdx =
7755 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
7756 if (RsrcIdx != -1) {
7757 DeferredList.insert(MI);
7758 }
7759}
7760
7762 return DeferredList.contains(MI);
7763}
7764
7765// Legalize size mismatches between 16bit and 32bit registers in v2s copy
7766// lowering (change sgpr to vgpr).
7767// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
7768// size. Need to legalize the size of the operands during the vgpr lowering
7769// chain. This can be removed after we have sgpr16 in place
7771 MachineRegisterInfo &MRI) const {
7772 if (!ST.useRealTrue16Insts())
7773 return;
7774
7775 unsigned Opcode = MI.getOpcode();
7776 MachineBasicBlock *MBB = MI.getParent();
7777 // Legalize operands and check for size mismatch
7778 if (!OpIdx || OpIdx >= MI.getNumExplicitOperands() ||
7779 OpIdx >= get(Opcode).getNumOperands() ||
7780 get(Opcode).operands()[OpIdx].RegClass == -1)
7781 return;
7782
7783 MachineOperand &Op = MI.getOperand(OpIdx);
7784 if (!Op.isReg() || !Op.getReg().isVirtual())
7785 return;
7786
7787 const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
7788 if (!RI.isVGPRClass(CurrRC))
7789 return;
7790
7791 int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
7792 const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
7793 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
7794 Op.setSubReg(AMDGPU::lo16);
7795 } else if (RI.getMatchingSuperRegClass(ExpectedRC, CurrRC, AMDGPU::lo16)) {
7796 const DebugLoc &DL = MI.getDebugLoc();
7797 Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
7798 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
7799 BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
7800 BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
7801 .addReg(Op.getReg())
7802 .addImm(AMDGPU::lo16)
7803 .addReg(Undef)
7804 .addImm(AMDGPU::hi16);
7805 Op.setReg(NewDstReg);
7806 }
7807}
7809 MachineRegisterInfo &MRI) const {
7810 for (unsigned OpIdx = 1; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
7812}
7813
7817 ArrayRef<Register> PhySGPRs) const {
7818 assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
7819 "This only handle waterfall for SI_CALL_ISEL");
7820 // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
7821 // following copies, we also need to move copies from and to physical
7822 // registers into the loop block.
7823 // Also move the copies to physical registers into the loop block
7824 MachineBasicBlock &MBB = *MI->getParent();
7826 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
7827 --Start;
7829 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
7830 ++End;
7831
7832 // Also include following copies of the return value
7833 ++End;
7834 while (End != MBB.end() && End->isCopy() &&
7835 MI->definesRegister(End->getOperand(1).getReg(), &RI))
7836 ++End;
7837
7838 generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
7839}
7840
7842 MachineDominatorTree *MDT) const {
7844 DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
7845 while (!Worklist.empty()) {
7846 MachineInstr &Inst = *Worklist.top();
7847 Worklist.erase_top();
7848 // Skip MachineInstr in the deferred list.
7849 if (Worklist.isDeferred(&Inst))
7850 continue;
7851 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
7852 }
7853
7854 // Deferred list of instructions will be processed once
7855 // all the MachineInstr in the worklist are done.
7856 for (MachineInstr *Inst : Worklist.getDeferredList()) {
7857 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
7858 assert(Worklist.empty() &&
7859 "Deferred MachineInstr are not supposed to re-populate worklist");
7860 }
7861
7862 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
7863 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
7864 createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
7865 Entry.second.SGPRs);
7866 }
7867
7868 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
7869 if (Entry.second)
7870 Entry.first->eraseFromParent();
7871}
7873 MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
7874 // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
7875 // hope for the best.
7876 const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
7877 ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
7878 if (SubRegIndices.size() <= 1) {
7879 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7880 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
7881 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
7882 .add(Inst.getOperand(1));
7883 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
7884 DstReg)
7885 .addReg(NewDst);
7886 } else {
7888 for (int16_t Indice : SubRegIndices) {
7889 Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7890 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
7891 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
7892 .addReg(Inst.getOperand(1).getReg(), {}, Indice);
7893
7894 DstRegs.push_back(NewDst);
7895 }
7897 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
7898 get(AMDGPU::REG_SEQUENCE), DstReg);
7899 for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
7900 MIB.addReg(DstRegs[i]);
7901 MIB.addImm(RI.getSubRegFromChannel(i));
7902 }
7903 }
7904}
7905
7907 SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
7910 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
7911 if (DstReg == AMDGPU::M0) {
7912 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
7913 V2SPhyCopiesToErase.try_emplace(&Inst, true);
7914 return;
7915 }
7916 Register SrcReg = Inst.getOperand(1).getReg();
7919 // Only search current block since phyreg's def & use cannot cross
7920 // blocks when MF.NoPhi = false.
7921 while (++I != E) {
7922 // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
7923 // and record the operand for later waterfall loop generation.
7924 if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
7925 MachineInstr *UseMI = &*I;
7926 for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
7927 if (UseMI->getOperand(i).isReg() &&
7928 UseMI->getOperand(i).getReg() == DstReg) {
7929 MachineOperand *MO = &UseMI->getOperand(i);
7930 MO->setReg(SrcReg);
7931 V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
7932 V2SCopyInfo.MOs.push_back(MO);
7933 V2SCopyInfo.SGPRs.push_back(DstReg);
7934 V2SPhyCopiesToErase.try_emplace(&Inst, true);
7935 }
7936 }
7937 } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
7938 I->getOperand(0).isReg() &&
7939 I->getOperand(0).getReg() == DstReg) {
7940 createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
7941 V2SPhyCopiesToErase.try_emplace(&Inst, true);
7942 } else if (I->readsRegister(DstReg, &RI)) {
7943 // COPY cannot be erased if other type of inst uses it.
7944 V2SPhyCopiesToErase[&Inst] = false;
7945 }
7946 if (I->findRegisterDefOperand(DstReg, &RI))
7947 break;
7948 }
7949}
7950
7952 SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
7954 DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
7955
7957 if (!MBB)
7958 return;
7959 MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
7960 unsigned Opcode = Inst.getOpcode();
7961 unsigned NewOpcode = getVALUOp(Inst);
7962 const DebugLoc &DL = Inst.getDebugLoc();
7963
7964 // Handle some special cases
7965 switch (Opcode) {
7966 default:
7967 break;
7968 case AMDGPU::S_ADD_I32:
7969 case AMDGPU::S_SUB_I32: {
7970 // FIXME: The u32 versions currently selected use the carry.
7971 bool Changed;
7972 MachineBasicBlock *CreatedBBTmp = nullptr;
7973 std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
7974 if (Changed)
7975 return;
7976
7977 // Default handling
7978 break;
7979 }
7980
7981 case AMDGPU::S_MUL_U64:
7982 if (ST.hasVMulU64Inst()) {
7983 NewOpcode = AMDGPU::V_MUL_U64_e64;
7984 break;
7985 }
7986 // Split s_mul_u64 in 32-bit vector multiplications.
7987 splitScalarSMulU64(Worklist, Inst, MDT);
7988 Inst.eraseFromParent();
7989 return;
7990
7991 case AMDGPU::S_MUL_U64_U32_PSEUDO:
7992 case AMDGPU::S_MUL_I64_I32_PSEUDO:
7993 // This is a special case of s_mul_u64 where all the operands are either
7994 // zero extended or sign extended.
7995 splitScalarSMulPseudo(Worklist, Inst, MDT);
7996 Inst.eraseFromParent();
7997 return;
7998
7999 case AMDGPU::S_AND_B64:
8000 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8001 Inst.eraseFromParent();
8002 return;
8003
8004 case AMDGPU::S_OR_B64:
8005 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8006 Inst.eraseFromParent();
8007 return;
8008
8009 case AMDGPU::S_XOR_B64:
8010 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8011 Inst.eraseFromParent();
8012 return;
8013
8014 case AMDGPU::S_NAND_B64:
8015 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8016 Inst.eraseFromParent();
8017 return;
8018
8019 case AMDGPU::S_NOR_B64:
8020 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8021 Inst.eraseFromParent();
8022 return;
8023
8024 case AMDGPU::S_XNOR_B64:
8025 if (ST.hasDLInsts())
8026 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8027 else
8028 splitScalar64BitXnor(Worklist, Inst, MDT);
8029 Inst.eraseFromParent();
8030 return;
8031
8032 case AMDGPU::S_ANDN2_B64:
8033 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8034 Inst.eraseFromParent();
8035 return;
8036
8037 case AMDGPU::S_ORN2_B64:
8038 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8039 Inst.eraseFromParent();
8040 return;
8041
8042 case AMDGPU::S_BREV_B64:
8043 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
8044 Inst.eraseFromParent();
8045 return;
8046
8047 case AMDGPU::S_NOT_B64:
8048 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8049 Inst.eraseFromParent();
8050 return;
8051
8052 case AMDGPU::S_BCNT1_I32_B64:
8053 splitScalar64BitBCNT(Worklist, Inst);
8054 Inst.eraseFromParent();
8055 return;
8056
8057 case AMDGPU::S_BFE_I64:
8058 splitScalar64BitBFE(Worklist, Inst);
8059 Inst.eraseFromParent();
8060 return;
8061
8062 case AMDGPU::S_FLBIT_I32_B64:
8063 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8064 Inst.eraseFromParent();
8065 return;
8066 case AMDGPU::S_FF1_I32_B64:
8067 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8068 Inst.eraseFromParent();
8069 return;
8070
8071 case AMDGPU::S_LSHL_B32:
8072 if (ST.hasOnlyRevVALUShifts()) {
8073 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8074 swapOperands(Inst);
8075 }
8076 break;
8077 case AMDGPU::S_ASHR_I32:
8078 if (ST.hasOnlyRevVALUShifts()) {
8079 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8080 swapOperands(Inst);
8081 }
8082 break;
8083 case AMDGPU::S_LSHR_B32:
8084 if (ST.hasOnlyRevVALUShifts()) {
8085 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8086 swapOperands(Inst);
8087 }
8088 break;
8089 case AMDGPU::S_LSHL_B64:
8090 if (ST.hasOnlyRevVALUShifts()) {
8091 NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
8092 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8093 : AMDGPU::V_LSHLREV_B64_e64;
8094 swapOperands(Inst);
8095 }
8096 break;
8097 case AMDGPU::S_ASHR_I64:
8098 if (ST.hasOnlyRevVALUShifts()) {
8099 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8100 swapOperands(Inst);
8101 }
8102 break;
8103 case AMDGPU::S_LSHR_B64:
8104 if (ST.hasOnlyRevVALUShifts()) {
8105 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8106 swapOperands(Inst);
8107 }
8108 break;
8109
8110 case AMDGPU::S_ABS_I32:
8111 lowerScalarAbs(Worklist, Inst);
8112 Inst.eraseFromParent();
8113 return;
8114
8115 case AMDGPU::S_ABSDIFF_I32:
8116 lowerScalarAbsDiff(Worklist, Inst);
8117 Inst.eraseFromParent();
8118 return;
8119
8120 case AMDGPU::S_CBRANCH_SCC0:
8121 case AMDGPU::S_CBRANCH_SCC1: {
8122 // Clear unused bits of vcc
8123 Register CondReg = Inst.getOperand(1).getReg();
8124 bool IsSCC = CondReg == AMDGPU::SCC;
8126 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
8127 .addReg(LMC.ExecReg)
8128 .addReg(IsSCC ? LMC.VccReg : CondReg);
8129 Inst.removeOperand(1);
8130 } break;
8131
8132 case AMDGPU::S_BFE_U64:
8133 case AMDGPU::S_BFM_B64:
8134 llvm_unreachable("Moving this op to VALU not implemented");
8135
8136 case AMDGPU::S_PACK_LL_B32_B16:
8137 case AMDGPU::S_PACK_LH_B32_B16:
8138 case AMDGPU::S_PACK_HL_B32_B16:
8139 case AMDGPU::S_PACK_HH_B32_B16:
8140 movePackToVALU(Worklist, MRI, Inst);
8141 Inst.eraseFromParent();
8142 return;
8143
8144 case AMDGPU::S_XNOR_B32:
8145 lowerScalarXnor(Worklist, Inst);
8146 Inst.eraseFromParent();
8147 return;
8148
8149 case AMDGPU::S_NAND_B32:
8150 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8151 Inst.eraseFromParent();
8152 return;
8153
8154 case AMDGPU::S_NOR_B32:
8155 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8156 Inst.eraseFromParent();
8157 return;
8158
8159 case AMDGPU::S_ANDN2_B32:
8160 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8161 Inst.eraseFromParent();
8162 return;
8163
8164 case AMDGPU::S_ORN2_B32:
8165 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8166 Inst.eraseFromParent();
8167 return;
8168
8169 // TODO: remove as soon as everything is ready
8170 // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
8171 // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
8172 // can only be selected from the uniform SDNode.
8173 case AMDGPU::S_ADD_CO_PSEUDO:
8174 case AMDGPU::S_SUB_CO_PSEUDO: {
8175 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8176 ? AMDGPU::V_ADDC_U32_e64
8177 : AMDGPU::V_SUBB_U32_e64;
8178 const auto *CarryRC = RI.getWaveMaskRegClass();
8179
8180 Register CarryInReg = Inst.getOperand(4).getReg();
8181 if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
8182 Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
8183 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
8184 .addReg(CarryInReg);
8185 }
8186
8187 Register CarryOutReg = Inst.getOperand(1).getReg();
8188
8189 Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8190 MRI.getRegClass(Inst.getOperand(0).getReg())));
8191 MachineInstr *CarryOp =
8192 BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
8193 .addReg(CarryOutReg, RegState::Define)
8194 .add(Inst.getOperand(2))
8195 .add(Inst.getOperand(3))
8196 .addReg(CarryInReg)
8197 .addImm(0);
8198 legalizeOperands(*CarryOp);
8199 MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
8200 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8201 Inst.eraseFromParent();
8202 }
8203 return;
8204 case AMDGPU::S_UADDO_PSEUDO:
8205 case AMDGPU::S_USUBO_PSEUDO: {
8206 MachineOperand &Dest0 = Inst.getOperand(0);
8207 MachineOperand &Dest1 = Inst.getOperand(1);
8208 MachineOperand &Src0 = Inst.getOperand(2);
8209 MachineOperand &Src1 = Inst.getOperand(3);
8210
8211 unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8212 ? AMDGPU::V_ADD_CO_U32_e64
8213 : AMDGPU::V_SUB_CO_U32_e64;
8214 const TargetRegisterClass *NewRC =
8215 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
8216 Register DestReg = MRI.createVirtualRegister(NewRC);
8217 MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
8218 .addReg(Dest1.getReg(), RegState::Define)
8219 .add(Src0)
8220 .add(Src1)
8221 .addImm(0); // clamp bit
8222
8223 legalizeOperands(*NewInstr, MDT);
8224 MRI.replaceRegWith(Dest0.getReg(), DestReg);
8225 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8226 Inst.eraseFromParent();
8227 }
8228 return;
8229 case AMDGPU::S_LSHL1_ADD_U32:
8230 case AMDGPU::S_LSHL2_ADD_U32:
8231 case AMDGPU::S_LSHL3_ADD_U32:
8232 case AMDGPU::S_LSHL4_ADD_U32: {
8233 MachineOperand &Dest = Inst.getOperand(0);
8234 MachineOperand &Src0 = Inst.getOperand(1);
8235 MachineOperand &Src1 = Inst.getOperand(2);
8236 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8237 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8238 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8239 : 4);
8240
8241 const TargetRegisterClass *NewRC =
8242 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
8243 Register DestReg = MRI.createVirtualRegister(NewRC);
8244 MachineInstr *NewInstr =
8245 BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
8246 .add(Src0)
8247 .addImm(ShiftAmt)
8248 .add(Src1);
8249
8250 legalizeOperands(*NewInstr, MDT);
8251 MRI.replaceRegWith(Dest.getReg(), DestReg);
8252 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8253 Inst.eraseFromParent();
8254 }
8255 return;
8256 case AMDGPU::S_CSELECT_B32:
8257 case AMDGPU::S_CSELECT_B64:
8258 lowerSelect(Worklist, Inst, MDT);
8259 Inst.eraseFromParent();
8260 return;
8261 case AMDGPU::S_CMP_EQ_I32:
8262 case AMDGPU::S_CMP_LG_I32:
8263 case AMDGPU::S_CMP_GT_I32:
8264 case AMDGPU::S_CMP_GE_I32:
8265 case AMDGPU::S_CMP_LT_I32:
8266 case AMDGPU::S_CMP_LE_I32:
8267 case AMDGPU::S_CMP_EQ_U32:
8268 case AMDGPU::S_CMP_LG_U32:
8269 case AMDGPU::S_CMP_GT_U32:
8270 case AMDGPU::S_CMP_GE_U32:
8271 case AMDGPU::S_CMP_LT_U32:
8272 case AMDGPU::S_CMP_LE_U32:
8273 case AMDGPU::S_CMP_EQ_U64:
8274 case AMDGPU::S_CMP_LG_U64:
8275 case AMDGPU::S_CMP_LT_F32:
8276 case AMDGPU::S_CMP_EQ_F32:
8277 case AMDGPU::S_CMP_LE_F32:
8278 case AMDGPU::S_CMP_GT_F32:
8279 case AMDGPU::S_CMP_LG_F32:
8280 case AMDGPU::S_CMP_GE_F32:
8281 case AMDGPU::S_CMP_O_F32:
8282 case AMDGPU::S_CMP_U_F32:
8283 case AMDGPU::S_CMP_NGE_F32:
8284 case AMDGPU::S_CMP_NLG_F32:
8285 case AMDGPU::S_CMP_NGT_F32:
8286 case AMDGPU::S_CMP_NLE_F32:
8287 case AMDGPU::S_CMP_NEQ_F32:
8288 case AMDGPU::S_CMP_NLT_F32: {
8289 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8290 auto NewInstr =
8291 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8292 .setMIFlags(Inst.getFlags());
8293 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8294 0) {
8295 NewInstr
8296 .addImm(0) // src0_modifiers
8297 .add(Inst.getOperand(0)) // src0
8298 .addImm(0) // src1_modifiers
8299 .add(Inst.getOperand(1)) // src1
8300 .addImm(0); // clamp
8301 } else {
8302 NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
8303 }
8304 legalizeOperands(*NewInstr, MDT);
8305 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8306 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8307 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8308 Inst.eraseFromParent();
8309 return;
8310 }
8311 case AMDGPU::S_CMP_LT_F16:
8312 case AMDGPU::S_CMP_EQ_F16:
8313 case AMDGPU::S_CMP_LE_F16:
8314 case AMDGPU::S_CMP_GT_F16:
8315 case AMDGPU::S_CMP_LG_F16:
8316 case AMDGPU::S_CMP_GE_F16:
8317 case AMDGPU::S_CMP_O_F16:
8318 case AMDGPU::S_CMP_U_F16:
8319 case AMDGPU::S_CMP_NGE_F16:
8320 case AMDGPU::S_CMP_NLG_F16:
8321 case AMDGPU::S_CMP_NGT_F16:
8322 case AMDGPU::S_CMP_NLE_F16:
8323 case AMDGPU::S_CMP_NEQ_F16:
8324 case AMDGPU::S_CMP_NLT_F16: {
8325 Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8326 auto NewInstr =
8327 BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
8328 .setMIFlags(Inst.getFlags());
8329 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
8330 NewInstr
8331 .addImm(0) // src0_modifiers
8332 .add(Inst.getOperand(0)) // src0
8333 .addImm(0) // src1_modifiers
8334 .add(Inst.getOperand(1)) // src1
8335 .addImm(0); // clamp
8336 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8337 NewInstr.addImm(0); // op_sel0
8338 } else {
8339 NewInstr
8340 .add(Inst.getOperand(0))
8341 .add(Inst.getOperand(1));
8342 }
8343 legalizeOperandsVALUt16(*NewInstr, MRI);
8344 legalizeOperands(*NewInstr, MDT);
8345 int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
8346 const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
8347 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8348 Inst.eraseFromParent();
8349 return;
8350 }
8351 case AMDGPU::S_CVT_HI_F32_F16: {
8352 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8353 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8354 if (ST.useRealTrue16Insts()) {
8355 BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
8356 .add(Inst.getOperand(1));
8357 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8358 .addImm(0) // src0_modifiers
8359 .addReg(TmpReg, {}, AMDGPU::hi16)
8360 .addImm(0) // clamp
8361 .addImm(0) // omod
8362 .addImm(0); // op_sel0
8363 } else {
8364 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
8365 .addImm(16)
8366 .add(Inst.getOperand(1));
8367 BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8368 .addImm(0) // src0_modifiers
8369 .addReg(TmpReg)
8370 .addImm(0) // clamp
8371 .addImm(0); // omod
8372 }
8373
8374 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8375 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8376 Inst.eraseFromParent();
8377 return;
8378 }
8379 case AMDGPU::S_MINIMUM_F32:
8380 case AMDGPU::S_MAXIMUM_F32: {
8381 Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8382 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8383 .addImm(0) // src0_modifiers
8384 .add(Inst.getOperand(1))
8385 .addImm(0) // src1_modifiers
8386 .add(Inst.getOperand(2))
8387 .addImm(0) // clamp
8388 .addImm(0); // omod
8389 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8390
8391 legalizeOperands(*NewInstr, MDT);
8392 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8393 Inst.eraseFromParent();
8394 return;
8395 }
8396 case AMDGPU::S_MINIMUM_F16:
8397 case AMDGPU::S_MAXIMUM_F16: {
8398 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8399 ? &AMDGPU::VGPR_16RegClass
8400 : &AMDGPU::VGPR_32RegClass);
8401 MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8402 .addImm(0) // src0_modifiers
8403 .add(Inst.getOperand(1))
8404 .addImm(0) // src1_modifiers
8405 .add(Inst.getOperand(2))
8406 .addImm(0) // clamp
8407 .addImm(0) // omod
8408 .addImm(0); // opsel0
8409 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8410 legalizeOperandsVALUt16(*NewInstr, MRI);
8411 legalizeOperands(*NewInstr, MDT);
8412 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8413 Inst.eraseFromParent();
8414 return;
8415 }
8416 case AMDGPU::V_S_EXP_F16_e64:
8417 case AMDGPU::V_S_LOG_F16_e64:
8418 case AMDGPU::V_S_RCP_F16_e64:
8419 case AMDGPU::V_S_RSQ_F16_e64:
8420 case AMDGPU::V_S_SQRT_F16_e64: {
8421 Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
8422 ? &AMDGPU::VGPR_16RegClass
8423 : &AMDGPU::VGPR_32RegClass);
8424 auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
8425 .add(Inst.getOperand(1)) // src0_modifiers
8426 .add(Inst.getOperand(2))
8427 .add(Inst.getOperand(3)) // clamp
8428 .add(Inst.getOperand(4)) // omod
8429 .setMIFlags(Inst.getFlags());
8430 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
8431 NewInstr.addImm(0); // opsel0
8432 MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
8433 legalizeOperandsVALUt16(*NewInstr, MRI);
8434 legalizeOperands(*NewInstr, MDT);
8435 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8436 Inst.eraseFromParent();
8437 return;
8438 }
8439 }
8440
8441 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8442 // We cannot move this instruction to the VALU, so we should try to
8443 // legalize its operands instead.
8444 legalizeOperands(Inst, MDT);
8445 return;
8446 }
8447 // Handle converting generic instructions like COPY-to-SGPR into
8448 // COPY-to-VGPR.
8449 if (NewOpcode == Opcode) {
8450 Register DstReg = Inst.getOperand(0).getReg();
8451 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);
8452
8453 if (Inst.isCopy() && DstReg.isPhysical() &&
8454 Inst.getOperand(1).getReg().isVirtual()) {
8455 handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
8456 V2SPhyCopiesToErase);
8457 return;
8458 }
8459
8460 if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
8461 Register NewDstReg = Inst.getOperand(1).getReg();
8462 const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
8463 if (const TargetRegisterClass *CommonRC =
8464 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8465 // Instead of creating a copy where src and dst are the same register
8466 // class, we just replace all uses of dst with src. These kinds of
8467 // copies interfere with the heuristics MachineSink uses to decide
8468 // whether or not to split a critical edge. Since the pass assumes
8469 // that copies will end up as machine instructions and not be
8470 // eliminated.
8471 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8472 MRI.replaceRegWith(DstReg, NewDstReg);
8473 MRI.clearKillFlags(NewDstReg);
8474 Inst.getOperand(0).setReg(DstReg);
8475
8476 if (!MRI.constrainRegClass(NewDstReg, CommonRC))
8477 llvm_unreachable("failed to constrain register");
8478
8479 Inst.eraseFromParent();
8480
8481 for (MachineOperand &UseMO :
8482 make_early_inc_range(MRI.use_operands(NewDstReg))) {
8483 MachineInstr &UseMI = *UseMO.getParent();
8484
8485 // Legalize t16 operands since replaceReg is called after
8486 // addUsersToVALU.
8488
8489 unsigned OpIdx = UseMI.getOperandNo(&UseMO);
8490 if (const TargetRegisterClass *OpRC =
8491 getRegClass(UseMI.getDesc(), OpIdx))
8492 MRI.constrainRegClass(NewDstReg, OpRC);
8493 }
8494
8495 return;
8496 }
8497 }
8498
8499 // If this is a v2s copy between 16bit and 32bit reg,
8500 // replace vgpr copy to reg_sequence/extract_subreg
8501 // This can be remove after we have sgpr16 in place
8502 if (ST.useRealTrue16Insts() && Inst.isCopy() &&
8503 Inst.getOperand(1).getReg().isVirtual() &&
8504 RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
8505 const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
8506 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8507 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8508 Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
8509 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8510 get(AMDGPU::IMPLICIT_DEF), Undef);
8511 BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
8512 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8513 .addReg(Inst.getOperand(1).getReg())
8514 .addImm(AMDGPU::lo16)
8515 .addReg(Undef)
8516 .addImm(AMDGPU::hi16);
8517 Inst.eraseFromParent();
8518 MRI.replaceRegWith(DstReg, NewDstReg);
8519 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8520 return;
8521 } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8522 AMDGPU::lo16)) {
8523 Inst.getOperand(1).setSubReg(AMDGPU::lo16);
8524 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8525 MRI.replaceRegWith(DstReg, NewDstReg);
8526 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8527 return;
8528 }
8529 }
8530
8531 Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
8532 MRI.replaceRegWith(DstReg, NewDstReg);
8533 legalizeOperands(Inst, MDT);
8534 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8535 return;
8536 }
8537
8538 // Use the new VALU Opcode.
8539 auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
8540 .setMIFlags(Inst.getFlags());
8541 if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
8542 // Intersperse VOP3 modifiers among the SALU operands.
8543 NewInstr->addOperand(Inst.getOperand(0));
8544 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8545 AMDGPU::OpName::src0_modifiers) >= 0)
8546 NewInstr.addImm(0);
8547 if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
8548 const MachineOperand &Src = Inst.getOperand(1);
8549 NewInstr->addOperand(Src);
8550 }
8551
8552 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8553 // We are converting these to a BFE, so we need to add the missing
8554 // operands for the size and offset.
8555 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8556 NewInstr.addImm(0);
8557 NewInstr.addImm(Size);
8558 } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8559 // The VALU version adds the second operand to the result, so insert an
8560 // extra 0 operand.
8561 NewInstr.addImm(0);
8562 } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8563 const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
8564 // If we need to move this to VGPRs, we need to unpack the second
8565 // operand back into the 2 separate ones for bit offset and width.
8566 assert(OffsetWidthOp.isImm() &&
8567 "Scalar BFE is only implemented for constant width and offset");
8568 uint32_t Imm = OffsetWidthOp.getImm();
8569
8570 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
8571 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
8572 NewInstr.addImm(Offset);
8573 NewInstr.addImm(BitWidth);
8574 } else {
8575 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8576 AMDGPU::OpName::src1_modifiers) >= 0)
8577 NewInstr.addImm(0);
8578 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8579 NewInstr->addOperand(Inst.getOperand(2));
8580 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8581 AMDGPU::OpName::src2_modifiers) >= 0)
8582 NewInstr.addImm(0);
8583 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8584 NewInstr->addOperand(Inst.getOperand(3));
8585 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8586 NewInstr.addImm(0);
8587 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8588 NewInstr.addImm(0);
8589 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8590 NewInstr.addImm(0);
8591 }
8592 } else {
8593 // Just copy the SALU operands.
8594 for (const MachineOperand &Op : Inst.explicit_operands())
8595 NewInstr->addOperand(Op);
8596 }
8597
8598 // Remove any references to SCC. Vector instructions can't read from it, and
8599 // We're just about to add the implicit use / defs of VCC, and we don't want
8600 // both.
8601 for (MachineOperand &Op : Inst.implicit_operands()) {
8602 if (Op.getReg() == AMDGPU::SCC) {
8603 // Only propagate through live-def of SCC.
8604 if (Op.isDef() && !Op.isDead())
8605 addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
8606 if (Op.isUse())
8607 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8608 }
8609 }
8610 Inst.eraseFromParent();
8611 Register NewDstReg;
8612 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8613 Register DstReg = NewInstr->getOperand(0).getReg();
8614 assert(DstReg.isVirtual());
8615 // Update the destination register class.
8616 const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
8617 assert(NewDstRC);
8618 NewDstReg = MRI.createVirtualRegister(NewDstRC);
8619 MRI.replaceRegWith(DstReg, NewDstReg);
8620 }
8621 fixImplicitOperands(*NewInstr);
8622
8623 legalizeOperandsVALUt16(*NewInstr, MRI);
8624
8625 // Legalize the operands
8626 legalizeOperands(*NewInstr, MDT);
8627 if (NewDstReg)
8628 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8629}
8630
8631// Add/sub require special handling to deal with carry outs.
8632std::pair<bool, MachineBasicBlock *>
8633SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
8634 MachineDominatorTree *MDT) const {
8635 if (ST.hasAddNoCarryInsts()) {
8636 // Assume there is no user of scc since we don't select this in that case.
8637 // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
8638 // is used.
8639
8640 MachineBasicBlock &MBB = *Inst.getParent();
8641 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8642
8643 Register OldDstReg = Inst.getOperand(0).getReg();
8644 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8645
8646 unsigned Opc = Inst.getOpcode();
8647 assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);
8648
8649 unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
8650 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8651
8652 assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
8653 Inst.removeOperand(3);
8654
8655 Inst.setDesc(get(NewOpc));
8656 Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
8657 Inst.addImplicitDefUseOperands(*MBB.getParent());
8658 MRI.replaceRegWith(OldDstReg, ResultReg);
8659 MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);
8660
8661 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8662 return std::pair(true, NewBB);
8663 }
8664
8665 return std::pair(false, nullptr);
8666}
8667
8668void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
8669 MachineDominatorTree *MDT) const {
8670
8671 MachineBasicBlock &MBB = *Inst.getParent();
8672 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8673 MachineBasicBlock::iterator MII = Inst;
8674 const DebugLoc &DL = Inst.getDebugLoc();
8675
8676 MachineOperand &Dest = Inst.getOperand(0);
8677 MachineOperand &Src0 = Inst.getOperand(1);
8678 MachineOperand &Src1 = Inst.getOperand(2);
8679 MachineOperand &Cond = Inst.getOperand(3);
8680
8681 Register CondReg = Cond.getReg();
8682 bool IsSCC = (CondReg == AMDGPU::SCC);
8683
8684 // Remove S_CSELECT instructions that we previously inserted to feed the SCC
8685 // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
8686 // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
8687 // output directly into the V_CNDMASK.
8688 if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
8689 (Src1.getImm() == 0)) {
8690 for (MachineOperand &UseMO :
8692 MachineInstr &UseMI = *UseMO.getParent();
8693 switch (UseMI.getOpcode()) {
8694 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8695 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8696 case AMDGPU::V_CNDMASK_B16_t16_e32:
8697 case AMDGPU::V_CNDMASK_B16_t16_e64:
8698 case AMDGPU::V_CNDMASK_B32_e32:
8699 case AMDGPU::V_CNDMASK_B32_e64:
8700 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8701 if (UseMO.isImplicit() ||
8702 &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
8703 UseMO.setReg(CondReg);
8704 }
8705 }
8706 if (MRI.use_nodbg_empty(Dest.getReg()))
8707 return;
8708 }
8709
8710 Register NewCondReg = CondReg;
8711 if (IsSCC) {
8712 const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
8713 NewCondReg = MRI.createVirtualRegister(TC);
8714
8715 // Now look for the closest SCC def if it is a copy
8716 // replacing the CondReg with the COPY source register
8717 bool CopyFound = false;
8718 for (MachineInstr &CandI :
8720 Inst.getParent()->rend())) {
8721 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
8722 -1) {
8723 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
8724 BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
8725 .addReg(CandI.getOperand(1).getReg());
8726 CopyFound = true;
8727 }
8728 break;
8729 }
8730 }
8731 if (!CopyFound) {
8732 // SCC def is not a copy
8733 // Insert a trivial select instead of creating a copy, because a copy from
8734 // SCC would semantically mean just copying a single bit, but we may need
8735 // the result to be a vector condition mask that needs preserving.
8736 unsigned Opcode =
8737 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
8738 auto NewSelect =
8739 BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
8740 NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
8741 }
8742 }
8743
8744 Register NewDestReg = MRI.createVirtualRegister(
8745 RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
8746 MachineInstr *NewInst;
8747 if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
8748 NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
8749 .addImm(0)
8750 .add(Src1) // False
8751 .addImm(0)
8752 .add(Src0) // True
8753 .addReg(NewCondReg);
8754 } else {
8755 NewInst =
8756 BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
8757 .add(Src1) // False
8758 .add(Src0) // True
8759 .addReg(NewCondReg);
8760 }
8761 MRI.replaceRegWith(Dest.getReg(), NewDestReg);
8762 legalizeOperands(*NewInst, MDT);
8763 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
8764}
8765
8766void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
8767 MachineInstr &Inst) const {
8768 MachineBasicBlock &MBB = *Inst.getParent();
8769 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8770 MachineBasicBlock::iterator MII = Inst;
8771 const DebugLoc &DL = Inst.getDebugLoc();
8772
8773 MachineOperand &Dest = Inst.getOperand(0);
8774 MachineOperand &Src = Inst.getOperand(1);
8775 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8776 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8777
8778 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8779 : AMDGPU::V_SUB_CO_U32_e32;
8780
8781 BuildMI(MBB, MII, DL, get(SubOp), TmpReg)
8782 .addImm(0)
8783 .addReg(Src.getReg());
8784
8785 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
8786 .addReg(Src.getReg())
8787 .addReg(TmpReg);
8788
8789 MRI.replaceRegWith(Dest.getReg(), ResultReg);
8790 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8791}
8792
8793void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
8794 MachineInstr &Inst) const {
8795 MachineBasicBlock &MBB = *Inst.getParent();
8796 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8797 MachineBasicBlock::iterator MII = Inst;
8798 const DebugLoc &DL = Inst.getDebugLoc();
8799
8800 MachineOperand &Dest = Inst.getOperand(0);
8801 MachineOperand &Src1 = Inst.getOperand(1);
8802 MachineOperand &Src2 = Inst.getOperand(2);
8803 Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8804 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8805 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8806
8807 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
8808 : AMDGPU::V_SUB_CO_U32_e32;
8809
8810 BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
8811 .addReg(Src1.getReg())
8812 .addReg(Src2.getReg());
8813
8814 BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
8815
8816 BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
8817 .addReg(SubResultReg)
8818 .addReg(TmpReg);
8819
8820 MRI.replaceRegWith(Dest.getReg(), ResultReg);
8821 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8822}
8823
8824void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
8825 MachineInstr &Inst) const {
8826 MachineBasicBlock &MBB = *Inst.getParent();
8827 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8828 MachineBasicBlock::iterator MII = Inst;
8829 const DebugLoc &DL = Inst.getDebugLoc();
8830
8831 MachineOperand &Dest = Inst.getOperand(0);
8832 MachineOperand &Src0 = Inst.getOperand(1);
8833 MachineOperand &Src1 = Inst.getOperand(2);
8834
8835 if (ST.hasDLInsts()) {
8836 Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8837 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
8838 legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);
8839
8840 BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
8841 .add(Src0)
8842 .add(Src1);
8843
8844 MRI.replaceRegWith(Dest.getReg(), NewDest);
8845 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
8846 } else {
8847 // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
8848 // invert either source and then perform the XOR. If either source is a
8849 // scalar register, then we can leave the inversion on the scalar unit to
8850 // achieve a better distribution of scalar and vector instructions.
8851 bool Src0IsSGPR = Src0.isReg() &&
8852 RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
8853 bool Src1IsSGPR = Src1.isReg() &&
8854 RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
8855 MachineInstr *Xor;
8856 Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
8857 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
8858
8859 // Build a pair of scalar instructions and add them to the work list.
8860 // The next iteration over the work list will lower these to the vector
8861 // unit as necessary.
8862 if (Src0IsSGPR) {
8863 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
8864 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
8865 .addReg(Temp)
8866 .add(Src1);
8867 } else if (Src1IsSGPR) {
8868 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
8869 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
8870 .add(Src0)
8871 .addReg(Temp);
8872 } else {
8873 Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
8874 .add(Src0)
8875 .add(Src1);
8876 MachineInstr *Not =
8877 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
8878 Worklist.insert(Not);
8879 }
8880
8881 MRI.replaceRegWith(Dest.getReg(), NewDest);
8882
8883 Worklist.insert(Xor);
8884
8885 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
8886 }
8887}
8888
8889void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
8890 MachineInstr &Inst,
8891 unsigned Opcode) const {
8892 MachineBasicBlock &MBB = *Inst.getParent();
8893 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8894 MachineBasicBlock::iterator MII = Inst;
8895 const DebugLoc &DL = Inst.getDebugLoc();
8896
8897 MachineOperand &Dest = Inst.getOperand(0);
8898 MachineOperand &Src0 = Inst.getOperand(1);
8899 MachineOperand &Src1 = Inst.getOperand(2);
8900
8901 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
8902 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
8903
8904 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
8905 .add(Src0)
8906 .add(Src1);
8907
8908 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
8909 .addReg(Interm);
8910
8911 Worklist.insert(&Op);
8912 Worklist.insert(&Not);
8913
8914 MRI.replaceRegWith(Dest.getReg(), NewDest);
8915 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
8916}
8917
8918void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
8919 MachineInstr &Inst,
8920 unsigned Opcode) const {
8921 MachineBasicBlock &MBB = *Inst.getParent();
8922 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8923 MachineBasicBlock::iterator MII = Inst;
8924 const DebugLoc &DL = Inst.getDebugLoc();
8925
8926 MachineOperand &Dest = Inst.getOperand(0);
8927 MachineOperand &Src0 = Inst.getOperand(1);
8928 MachineOperand &Src1 = Inst.getOperand(2);
8929
8930 Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8931 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8932
8933 MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
8934 .add(Src1);
8935
8936 MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
8937 .add(Src0)
8938 .addReg(Interm);
8939
8940 Worklist.insert(&Not);
8941 Worklist.insert(&Op);
8942
8943 MRI.replaceRegWith(Dest.getReg(), NewDest);
8944 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
8945}
8946
8947void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
8948 MachineInstr &Inst, unsigned Opcode,
8949 bool Swap) const {
8950 MachineBasicBlock &MBB = *Inst.getParent();
8951 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8952
8953 MachineOperand &Dest = Inst.getOperand(0);
8954 MachineOperand &Src0 = Inst.getOperand(1);
8955 const DebugLoc &DL = Inst.getDebugLoc();
8956
8957 MachineBasicBlock::iterator MII = Inst;
8958
8959 const MCInstrDesc &InstDesc = get(Opcode);
8960 const TargetRegisterClass *Src0RC = Src0.isReg() ?
8961 MRI.getRegClass(Src0.getReg()) :
8962 &AMDGPU::SGPR_32RegClass;
8963
8964 const TargetRegisterClass *Src0SubRC =
8965 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
8966
8967 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
8968 AMDGPU::sub0, Src0SubRC);
8969
8970 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
8971 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
8972 const TargetRegisterClass *NewDestSubRC =
8973 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
8974
8975 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
8976 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);
8977
8978 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
8979 AMDGPU::sub1, Src0SubRC);
8980
8981 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
8982 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);
8983
8984 if (Swap)
8985 std::swap(DestSub0, DestSub1);
8986
8987 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
8988 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
8989 .addReg(DestSub0)
8990 .addImm(AMDGPU::sub0)
8991 .addReg(DestSub1)
8992 .addImm(AMDGPU::sub1);
8993
8994 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
8995
8996 Worklist.insert(&LoHalf);
8997 Worklist.insert(&HiHalf);
8998
8999 // We don't need to legalizeOperands here because for a single operand, src0
9000 // will support any kind of input.
9001
9002 // Move all users of this moved value.
9003 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9004}
9005
9006// There is not a vector equivalent of s_mul_u64. For this reason, we need to
9007// split the s_mul_u64 in 32-bit vector multiplications.
9008void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
9009 MachineInstr &Inst,
9010 MachineDominatorTree *MDT) const {
9011 MachineBasicBlock &MBB = *Inst.getParent();
9012 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9013
9014 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9015 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9016 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9017
9018 MachineOperand &Dest = Inst.getOperand(0);
9019 MachineOperand &Src0 = Inst.getOperand(1);
9020 MachineOperand &Src1 = Inst.getOperand(2);
9021 const DebugLoc &DL = Inst.getDebugLoc();
9022 MachineBasicBlock::iterator MII = Inst;
9023
9024 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9025 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9026 const TargetRegisterClass *Src0SubRC =
9027 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9028 if (RI.isSGPRClass(Src0SubRC))
9029 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9030 const TargetRegisterClass *Src1SubRC =
9031 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9032 if (RI.isSGPRClass(Src1SubRC))
9033 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9034
9035 // First, we extract the low 32-bit and high 32-bit values from each of the
9036 // operands.
9037 MachineOperand Op0L =
9038 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9039 MachineOperand Op1L =
9040 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9041 MachineOperand Op0H =
9042 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
9043 MachineOperand Op1H =
9044 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);
9045
9046 // The multilication is done as follows:
9047 //
9048 // Op1H Op1L
9049 // * Op0H Op0L
9050 // --------------------
9051 // Op1H*Op0L Op1L*Op0L
9052 // + Op1H*Op0H Op1L*Op0H
9053 // -----------------------------------------
9054 // (Op1H*Op0L + Op1L*Op0H + carry) Op1L*Op0L
9055 //
9056 // We drop Op1H*Op0H because the result of the multiplication is a 64-bit
9057 // value and that would overflow.
9058 // The low 32-bit value is Op1L*Op0L.
9059 // The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).
9060
9061 Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9062 MachineInstr *Op1L_Op0H =
9063 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
9064 .add(Op1L)
9065 .add(Op0H);
9066
9067 Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9068 MachineInstr *Op1H_Op0L =
9069 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
9070 .add(Op1H)
9071 .add(Op0L);
9072
9073 Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9074 MachineInstr *Carry =
9075 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
9076 .add(Op1L)
9077 .add(Op0L);
9078
9079 MachineInstr *LoHalf =
9080 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9081 .add(Op1L)
9082 .add(Op0L);
9083
9084 Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9085 MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
9086 .addReg(Op1L_Op0H_Reg)
9087 .addReg(Op1H_Op0L_Reg);
9088
9089 MachineInstr *HiHalf =
9090 BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
9091 .addReg(AddReg)
9092 .addReg(CarryReg);
9093
9094 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9095 .addReg(DestSub0)
9096 .addImm(AMDGPU::sub0)
9097 .addReg(DestSub1)
9098 .addImm(AMDGPU::sub1);
9099
9100 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9101
9102 // Try to legalize the operands in case we need to swap the order to keep it
9103 // valid.
9104 legalizeOperands(*Op1L_Op0H, MDT);
9105 legalizeOperands(*Op1H_Op0L, MDT);
9106 legalizeOperands(*Carry, MDT);
9107 legalizeOperands(*LoHalf, MDT);
9108 legalizeOperands(*Add, MDT);
9109 legalizeOperands(*HiHalf, MDT);
9110
9111 // Move all users of this moved value.
9112 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9113}
9114
9115// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
9116// multiplications.
9117void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
9118 MachineInstr &Inst,
9119 MachineDominatorTree *MDT) const {
9120 MachineBasicBlock &MBB = *Inst.getParent();
9121 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9122
9123 Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9124 Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9125 Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9126
9127 MachineOperand &Dest = Inst.getOperand(0);
9128 MachineOperand &Src0 = Inst.getOperand(1);
9129 MachineOperand &Src1 = Inst.getOperand(2);
9130 const DebugLoc &DL = Inst.getDebugLoc();
9131 MachineBasicBlock::iterator MII = Inst;
9132
9133 const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
9134 const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
9135 const TargetRegisterClass *Src0SubRC =
9136 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9137 if (RI.isSGPRClass(Src0SubRC))
9138 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9139 const TargetRegisterClass *Src1SubRC =
9140 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9141 if (RI.isSGPRClass(Src1SubRC))
9142 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9143
9144 // First, we extract the low 32-bit and high 32-bit values from each of the
9145 // operands.
9146 MachineOperand Op0L =
9147 buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
9148 MachineOperand Op1L =
9149 buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
9150
9151 unsigned Opc = Inst.getOpcode();
9152 unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9153 ? AMDGPU::V_MUL_HI_U32_e64
9154 : AMDGPU::V_MUL_HI_I32_e64;
9155 MachineInstr *HiHalf =
9156 BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);
9157
9158 MachineInstr *LoHalf =
9159 BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
9160 .add(Op1L)
9161 .add(Op0L);
9162
9163 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9164 .addReg(DestSub0)
9165 .addImm(AMDGPU::sub0)
9166 .addReg(DestSub1)
9167 .addImm(AMDGPU::sub1);
9168
9169 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9170
9171 // Try to legalize the operands in case we need to swap the order to keep it
9172 // valid.
9173 legalizeOperands(*HiHalf, MDT);
9174 legalizeOperands(*LoHalf, MDT);
9175
9176 // Move all users of this moved value.
9177 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9178}
9179
9180void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
9181 MachineInstr &Inst, unsigned Opcode,
9182 MachineDominatorTree *MDT) const {
9183 MachineBasicBlock &MBB = *Inst.getParent();
9184 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9185
9186 MachineOperand &Dest = Inst.getOperand(0);
9187 MachineOperand &Src0 = Inst.getOperand(1);
9188 MachineOperand &Src1 = Inst.getOperand(2);
9189 const DebugLoc &DL = Inst.getDebugLoc();
9190
9191 MachineBasicBlock::iterator MII = Inst;
9192
9193 const MCInstrDesc &InstDesc = get(Opcode);
9194 const TargetRegisterClass *Src0RC = Src0.isReg() ?
9195 MRI.getRegClass(Src0.getReg()) :
9196 &AMDGPU::SGPR_32RegClass;
9197
9198 const TargetRegisterClass *Src0SubRC =
9199 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9200 const TargetRegisterClass *Src1RC = Src1.isReg() ?
9201 MRI.getRegClass(Src1.getReg()) :
9202 &AMDGPU::SGPR_32RegClass;
9203
9204 const TargetRegisterClass *Src1SubRC =
9205 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9206
9207 MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9208 AMDGPU::sub0, Src0SubRC);
9209 MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9210 AMDGPU::sub0, Src1SubRC);
9211 MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
9212 AMDGPU::sub1, Src0SubRC);
9213 MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
9214 AMDGPU::sub1, Src1SubRC);
9215
9216 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9217 const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
9218 const TargetRegisterClass *NewDestSubRC =
9219 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9220
9221 Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
9222 MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
9223 .add(SrcReg0Sub0)
9224 .add(SrcReg1Sub0);
9225
9226 Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
9227 MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
9228 .add(SrcReg0Sub1)
9229 .add(SrcReg1Sub1);
9230
9231 Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
9232 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
9233 .addReg(DestSub0)
9234 .addImm(AMDGPU::sub0)
9235 .addReg(DestSub1)
9236 .addImm(AMDGPU::sub1);
9237
9238 MRI.replaceRegWith(Dest.getReg(), FullDestReg);
9239
9240 Worklist.insert(&LoHalf);
9241 Worklist.insert(&HiHalf);
9242
9243 // Move all users of this moved value.
9244 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9245}
9246
9247void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
9248 MachineInstr &Inst,
9249 MachineDominatorTree *MDT) const {
9250 MachineBasicBlock &MBB = *Inst.getParent();
9251 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9252
9253 MachineOperand &Dest = Inst.getOperand(0);
9254 MachineOperand &Src0 = Inst.getOperand(1);
9255 MachineOperand &Src1 = Inst.getOperand(2);
9256 const DebugLoc &DL = Inst.getDebugLoc();
9257
9258 MachineBasicBlock::iterator MII = Inst;
9259
9260 const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
9261
9262 Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
9263
9264 MachineOperand* Op0;
9265 MachineOperand* Op1;
9266
9267 if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
9268 Op0 = &Src0;
9269 Op1 = &Src1;
9270 } else {
9271 Op0 = &Src1;
9272 Op1 = &Src0;
9273 }
9274
9275 BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
9276 .add(*Op0);
9277
9278 Register NewDest = MRI.createVirtualRegister(DestRC);
9279
9280 MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
9281 .addReg(Interm)
9282 .add(*Op1);
9283
9284 MRI.replaceRegWith(Dest.getReg(), NewDest);
9285
9286 Worklist.insert(&Xor);
9287}
9288
9289void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
9290 MachineInstr &Inst) const {
9291 MachineBasicBlock &MBB = *Inst.getParent();
9292 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9293
9294 MachineBasicBlock::iterator MII = Inst;
9295 const DebugLoc &DL = Inst.getDebugLoc();
9296
9297 MachineOperand &Dest = Inst.getOperand(0);
9298 MachineOperand &Src = Inst.getOperand(1);
9299
9300 const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
9301 const TargetRegisterClass *SrcRC = Src.isReg() ?
9302 MRI.getRegClass(Src.getReg()) :
9303 &AMDGPU::SGPR_32RegClass;
9304
9305 Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9306 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9307
9308 const TargetRegisterClass *SrcSubRC =
9309 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9310
9311 MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9312 AMDGPU::sub0, SrcSubRC);
9313 MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
9314 AMDGPU::sub1, SrcSubRC);
9315
9316 BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);
9317
9318 BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);
9319
9320 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9321
9322 // We don't need to legalize operands here. src0 for either instruction can be
9323 // an SGPR, and the second input is unused or determined here.
9324 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9325}
9326
9327void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
9328 MachineInstr &Inst) const {
9329 MachineBasicBlock &MBB = *Inst.getParent();
9330 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9331 MachineBasicBlock::iterator MII = Inst;
9332 const DebugLoc &DL = Inst.getDebugLoc();
9333
9334 MachineOperand &Dest = Inst.getOperand(0);
9335 uint32_t Imm = Inst.getOperand(2).getImm();
9336 uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
9337 uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
9338
9339 (void) Offset;
9340
9341 // Only sext_inreg cases handled.
9342 assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
9343 Offset == 0 && "Not implemented");
9344
9345 if (BitWidth < 32) {
9346 Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9347 Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9348 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9349
9350 BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
9351 .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
9352 .addImm(0)
9353 .addImm(BitWidth);
9354
9355 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
9356 .addImm(31)
9357 .addReg(MidRegLo);
9358
9359 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9360 .addReg(MidRegLo)
9361 .addImm(AMDGPU::sub0)
9362 .addReg(MidRegHi)
9363 .addImm(AMDGPU::sub1);
9364
9365 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9366 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9367 return;
9368 }
9369
9370 MachineOperand &Src = Inst.getOperand(1);
9371 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9372 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
9373
9374 BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
9375 .addImm(31)
9376 .addReg(Src.getReg(), {}, AMDGPU::sub0);
9377
9378 BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
9379 .addReg(Src.getReg(), {}, AMDGPU::sub0)
9380 .addImm(AMDGPU::sub0)
9381 .addReg(TmpReg)
9382 .addImm(AMDGPU::sub1);
9383
9384 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9385 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9386}
9387
9388void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
9389 MachineInstr &Inst, unsigned Opcode,
9390 MachineDominatorTree *MDT) const {
9391 // (S_FLBIT_I32_B64 hi:lo) ->
9392 // -> (umin (V_FFBH_U32_e32 hi), (uaddsat (V_FFBH_U32_e32 lo), 32))
9393 // (S_FF1_I32_B64 hi:lo) ->
9394 // ->(umin (uaddsat (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))
9395
9396 MachineBasicBlock &MBB = *Inst.getParent();
9397 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
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(Opcode);
9405
9406 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9407 unsigned OpcodeAdd = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64
9408 : AMDGPU::V_ADD_CO_U32_e32;
9409
9410 const TargetRegisterClass *SrcRC =
9411 Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9412 const TargetRegisterClass *SrcSubRC =
9413 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9414
9415 MachineOperand SrcRegSub0 =
9416 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
9417 MachineOperand SrcRegSub1 =
9418 buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);
9419
9420 Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9421 Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9422 Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9423 Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9424
9425 BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);
9426
9427 BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);
9428
9429 BuildMI(MBB, MII, DL, get(OpcodeAdd), MidReg3)
9430 .addReg(IsCtlz ? MidReg1 : MidReg2)
9431 .addImm(32)
9432 .addImm(1); // enable clamp
9433
9434 BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
9435 .addReg(MidReg3)
9436 .addReg(IsCtlz ? MidReg2 : MidReg1);
9437
9438 MRI.replaceRegWith(Dest.getReg(), MidReg4);
9439
9440 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9441}
9442
9443void SIInstrInfo::addUsersToMoveToVALUWorklist(
9444 Register DstReg, MachineRegisterInfo &MRI,
9445 SIInstrWorklist &Worklist) const {
9446 for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
9447 MachineInstr &UseMI = *MO.getParent();
9448
9449 unsigned OpNo = 0;
9450
9451 switch (UseMI.getOpcode()) {
9452 case AMDGPU::COPY:
9453 case AMDGPU::WQM:
9454 case AMDGPU::SOFT_WQM:
9455 case AMDGPU::STRICT_WWM:
9456 case AMDGPU::STRICT_WQM:
9457 case AMDGPU::REG_SEQUENCE:
9458 case AMDGPU::PHI:
9459 case AMDGPU::INSERT_SUBREG:
9460 break;
9461 default:
9462 OpNo = MO.getOperandNo();
9463 break;
9464 }
9465
9466 const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
9467 MRI.constrainRegClass(DstReg, OpRC);
9468
9469 if (!RI.hasVectorRegisters(OpRC))
9470 Worklist.insert(&UseMI);
9471 else
9472 // Legalization could change user list.
9473 legalizeOperandsVALUt16(UseMI, OpNo, MRI);
9474 }
9475}
9476
9477void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
9479 MachineInstr &Inst) const {
9480 Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9481 MachineBasicBlock *MBB = Inst.getParent();
9482 MachineOperand &Src0 = Inst.getOperand(1);
9483 MachineOperand &Src1 = Inst.getOperand(2);
9484 const DebugLoc &DL = Inst.getDebugLoc();
9485
9486 if (ST.useRealTrue16Insts()) {
9487 Register SrcReg0, SrcReg1;
9488 if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
9489 SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9490 BuildMI(*MBB, Inst, DL,
9491 get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9492 .add(Src0);
9493 } else {
9494 SrcReg0 = Src0.getReg();
9495 }
9496
9497 if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
9498 SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9499 BuildMI(*MBB, Inst, DL,
9500 get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9501 .add(Src1);
9502 } else {
9503 SrcReg1 = Src1.getReg();
9504 }
9505
9506 bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
9507 bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);
9508
9509 auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
9510 switch (Inst.getOpcode()) {
9511 case AMDGPU::S_PACK_LL_B32_B16:
9512 NewMI
9513 .addReg(SrcReg0, {},
9514 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9515 .addImm(AMDGPU::lo16)
9516 .addReg(SrcReg1, {},
9517 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9518 .addImm(AMDGPU::hi16);
9519 break;
9520 case AMDGPU::S_PACK_LH_B32_B16:
9521 NewMI
9522 .addReg(SrcReg0, {},
9523 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9524 .addImm(AMDGPU::lo16)
9525 .addReg(SrcReg1, {}, AMDGPU::hi16)
9526 .addImm(AMDGPU::hi16);
9527 break;
9528 case AMDGPU::S_PACK_HL_B32_B16:
9529 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9530 .addImm(AMDGPU::lo16)
9531 .addReg(SrcReg1, {},
9532 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9533 .addImm(AMDGPU::hi16);
9534 break;
9535 case AMDGPU::S_PACK_HH_B32_B16:
9536 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9537 .addImm(AMDGPU::lo16)
9538 .addReg(SrcReg1, {}, AMDGPU::hi16)
9539 .addImm(AMDGPU::hi16);
9540 break;
9541 default:
9542 llvm_unreachable("unhandled s_pack_* instruction");
9543 }
9544
9545 MachineOperand &Dest = Inst.getOperand(0);
9546 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9547 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9548 return;
9549 }
9550
9551 switch (Inst.getOpcode()) {
9552 case AMDGPU::S_PACK_LL_B32_B16: {
9553 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9554 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9555
9556 // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
9557 // 0.
9558 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9559 .addImm(0xffff);
9560
9561 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
9562 .addReg(ImmReg, RegState::Kill)
9563 .add(Src0);
9564
9565 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9566 .add(Src1)
9567 .addImm(16)
9568 .addReg(TmpReg, RegState::Kill);
9569 break;
9570 }
9571 case AMDGPU::S_PACK_LH_B32_B16: {
9572 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9573 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9574 .addImm(0xffff);
9575 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
9576 .addReg(ImmReg, RegState::Kill)
9577 .add(Src0)
9578 .add(Src1);
9579 break;
9580 }
9581 case AMDGPU::S_PACK_HL_B32_B16: {
9582 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9583 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9584 .addImm(16)
9585 .add(Src0);
9586 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
9587 .add(Src1)
9588 .addImm(16)
9589 .addReg(TmpReg, RegState::Kill);
9590 break;
9591 }
9592 case AMDGPU::S_PACK_HH_B32_B16: {
9593 Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9594 Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9595 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
9596 .addImm(16)
9597 .add(Src0);
9598 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
9599 .addImm(0xffff0000);
9600 BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
9601 .add(Src1)
9602 .addReg(ImmReg, RegState::Kill)
9603 .addReg(TmpReg, RegState::Kill);
9604 break;
9605 }
9606 default:
9607 llvm_unreachable("unhandled s_pack_* instruction");
9608 }
9609
9610 MachineOperand &Dest = Inst.getOperand(0);
9611 MRI.replaceRegWith(Dest.getReg(), ResultReg);
9612 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9613}
9614
9615void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
9616 MachineInstr &SCCDefInst,
9617 SIInstrWorklist &Worklist,
9618 Register NewCond) const {
9619
9620 // Ensure that def inst defines SCC, which is still live.
9621 assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
9622 !Op.isDead() && Op.getParent() == &SCCDefInst);
9623 SmallVector<MachineInstr *, 4> CopyToDelete;
9624 // This assumes that all the users of SCC are in the same block
9625 // as the SCC def.
9626 for (MachineInstr &MI : // Skip the def inst itself.
9627 make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
9628 SCCDefInst.getParent()->end())) {
9629 // Check if SCC is used first.
9630 int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
9631 if (SCCIdx != -1) {
9632 if (MI.isCopy()) {
9633 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
9634 Register DestReg = MI.getOperand(0).getReg();
9635
9636 MRI.replaceRegWith(DestReg, NewCond);
9637 CopyToDelete.push_back(&MI);
9638 } else {
9639
9640 if (NewCond.isValid())
9641 MI.getOperand(SCCIdx).setReg(NewCond);
9642
9643 Worklist.insert(&MI);
9644 }
9645 }
9646 // Exit if we find another SCC def.
9647 if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
9648 break;
9649 }
9650 for (auto &Copy : CopyToDelete)
9651 Copy->eraseFromParent();
9652}
9653
9654// Instructions that use SCC may be converted to VALU instructions. When that
9655// happens, the SCC register is changed to VCC_LO. The instruction that defines
9656// SCC must be changed to an instruction that defines VCC. This function makes
9657// sure that the instruction that defines SCC is added to the moveToVALU
9658// worklist.
9659void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
9660 SIInstrWorklist &Worklist) const {
9661 // Look for a preceding instruction that either defines VCC or SCC. If VCC
9662 // then there is nothing to do because the defining instruction has been
9663 // converted to a VALU already. If SCC then that instruction needs to be
9664 // converted to a VALU.
9665 for (MachineInstr &MI :
9666 make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
9667 SCCUseInst->getParent()->rend())) {
9668 if (MI.modifiesRegister(AMDGPU::VCC, &RI))
9669 break;
9670 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
9671 Worklist.insert(&MI);
9672 break;
9673 }
9674 }
9675}
9676
9677const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
9678 const MachineInstr &Inst) const {
9679 const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);
9680
9681 switch (Inst.getOpcode()) {
9682 // For target instructions, getOpRegClass just returns the virtual register
9683 // class associated with the operand, so we need to find an equivalent VGPR
9684 // register class in order to move the instruction to the VALU.
9685 case AMDGPU::COPY:
9686 case AMDGPU::PHI:
9687 case AMDGPU::REG_SEQUENCE:
9688 case AMDGPU::INSERT_SUBREG:
9689 case AMDGPU::WQM:
9690 case AMDGPU::SOFT_WQM:
9691 case AMDGPU::STRICT_WWM:
9692 case AMDGPU::STRICT_WQM: {
9693 const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
9694 if (RI.isAGPRClass(SrcRC)) {
9695 if (RI.isAGPRClass(NewDstRC))
9696 return nullptr;
9697
9698 switch (Inst.getOpcode()) {
9699 case AMDGPU::PHI:
9700 case AMDGPU::REG_SEQUENCE:
9701 case AMDGPU::INSERT_SUBREG:
9702 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9703 break;
9704 default:
9705 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9706 }
9707
9708 if (!NewDstRC)
9709 return nullptr;
9710 } else {
9711 if (RI.isVGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9712 return nullptr;
9713
9714 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9715 if (!NewDstRC)
9716 return nullptr;
9717 }
9718
9719 return NewDstRC;
9720 }
9721 default:
9722 return NewDstRC;
9723 }
9724}
9725
9726// Find the one SGPR operand we are allowed to use.
9727Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
9728 int OpIndices[3]) const {
9729 const MCInstrDesc &Desc = MI.getDesc();
9730
9731 // Find the one SGPR operand we are allowed to use.
9732 //
9733 // First we need to consider the instruction's operand requirements before
9734 // legalizing. Some operands are required to be SGPRs, such as implicit uses
9735 // of VCC, but we are still bound by the constant bus requirement to only use
9736 // one.
9737 //
9738 // If the operand's class is an SGPR, we can never move it.
9739
9740 Register SGPRReg = findImplicitSGPRRead(MI);
9741 if (SGPRReg)
9742 return SGPRReg;
9743
9744 Register UsedSGPRs[3] = {Register()};
9745 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
9746
9747 for (unsigned i = 0; i < 3; ++i) {
9748 int Idx = OpIndices[i];
9749 if (Idx == -1)
9750 break;
9751
9752 const MachineOperand &MO = MI.getOperand(Idx);
9753 if (!MO.isReg())
9754 continue;
9755
9756 // Is this operand statically required to be an SGPR based on the operand
9757 // constraints?
9758 const TargetRegisterClass *OpRC =
9759 RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
9760 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
9761 if (IsRequiredSGPR)
9762 return MO.getReg();
9763
9764 // If this could be a VGPR or an SGPR, Check the dynamic register class.
9765 Register Reg = MO.getReg();
9766 const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
9767 if (RI.isSGPRClass(RegRC))
9768 UsedSGPRs[i] = Reg;
9769 }
9770
9771 // We don't have a required SGPR operand, so we have a bit more freedom in
9772 // selecting operands to move.
9773
9774 // Try to select the most used SGPR. If an SGPR is equal to one of the
9775 // others, we choose that.
9776 //
9777 // e.g.
9778 // V_FMA_F32 v0, s0, s0, s0 -> No moves
9779 // V_FMA_F32 v0, s0, s1, s0 -> Move s1
9780
9781 // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
9782 // prefer those.
9783
9784 if (UsedSGPRs[0]) {
9785 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
9786 SGPRReg = UsedSGPRs[0];
9787 }
9788
9789 if (!SGPRReg && UsedSGPRs[1]) {
9790 if (UsedSGPRs[1] == UsedSGPRs[2])
9791 SGPRReg = UsedSGPRs[1];
9792 }
9793
9794 return SGPRReg;
9795}
9796
9798 AMDGPU::OpName OperandName) const {
9799 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
9800 return nullptr;
9801
9802 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
9803 if (Idx == -1)
9804 return nullptr;
9805
9806 return &MI.getOperand(Idx);
9807}
9808
9810 if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
9811 int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
9814 return (Format << 44) |
9815 (1ULL << 56) | // RESOURCE_LEVEL = 1
9816 (3ULL << 60); // OOB_SELECT = 3
9817 }
9818
9819 uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
9820 if (ST.isAmdHsaOS()) {
9821 // Set ATC = 1. GFX9 doesn't have this bit.
9822 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
9823 RsrcDataFormat |= (1ULL << 56);
9824
9825 // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
9826 // BTW, it disables TC L2 and therefore decreases performance.
9827 if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
9828 RsrcDataFormat |= (2ULL << 59);
9829 }
9830
9831 return RsrcDataFormat;
9832}
9833
9837 0xffffffff; // Size;
9838
9839 // GFX9 doesn't have ELEMENT_SIZE.
9840 if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
9841 uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
9842 Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
9843 }
9844
9845 // IndexStride = 64 / 32.
9846 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
9847 Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;
9848
9849 // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
9850 // Clear them unless we want a huge stride.
9851 if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
9852 ST.getGeneration() <= AMDGPUSubtarget::GFX9)
9853 Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;
9854
9855 return Rsrc23;
9856}
9857
9859 unsigned Opc = MI.getOpcode();
9860
9861 return isSMRD(Opc);
9862}
9863
9865 return get(Opc).mayLoad() &&
9866 (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
9867}
9868
9870 TypeSize &MemBytes) const {
9871 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
9872 if (!Addr || !Addr->isFI())
9873 return Register();
9874
9875 assert(!MI.memoperands_empty() &&
9876 (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);
9877
9878 FrameIndex = Addr->getIndex();
9879
9880 int VDataIdx =
9881 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
9882 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
9883 return MI.getOperand(VDataIdx).getReg();
9884}
9885
9887 TypeSize &MemBytes) const {
9888 const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
9889 assert(Addr && Addr->isFI());
9890 FrameIndex = Addr->getIndex();
9891
9892 int DataIdx =
9893 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
9894 MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
9895 return MI.getOperand(DataIdx).getReg();
9896}
9897
9899 int &FrameIndex,
9900 TypeSize &MemBytes) const {
9901 if (!MI.mayLoad())
9902 return Register();
9903
9904 if (isMUBUF(MI) || isVGPRSpill(MI))
9905 return isStackAccess(MI, FrameIndex, MemBytes);
9906
9907 if (isSGPRSpill(MI))
9908 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
9909
9910 return Register();
9911}
9912
9914 int &FrameIndex,
9915 TypeSize &MemBytes) const {
9916 if (!MI.mayStore())
9917 return Register();
9918
9919 if (isMUBUF(MI) || isVGPRSpill(MI))
9920 return isStackAccess(MI, FrameIndex, MemBytes);
9921
9922 if (isSGPRSpill(MI))
9923 return isSGPRStackAccess(MI, FrameIndex, MemBytes);
9924
9925 return Register();
9926}
9927
9929 unsigned Opc = MI.getOpcode();
9931 unsigned DescSize = Desc.getSize();
9932
9933 // If we have a definitive size, we can use it. Otherwise we need to inspect
9934 // the operands to know the size.
9935 if (isFixedSize(MI)) {
9936 unsigned Size = DescSize;
9937
9938 // If we hit the buggy offset, an extra nop will be inserted in MC so
9939 // estimate the worst case.
9940 if (MI.isBranch() && ST.hasOffset3fBug())
9941 Size += 4;
9942
9943 return Size;
9944 }
9945
9946 // Instructions may have a 32-bit literal encoded after them. Check
9947 // operands that could ever be literals.
9948 if (isVALU(MI, /*AllowLDSDMA=*/true) || isSALU(MI)) {
9949 if (isDPP(MI))
9950 return DescSize;
9951 bool HasLiteral = false;
9952 unsigned LiteralSize = 4;
9953 for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
9954 const MachineOperand &Op = MI.getOperand(I);
9955 const MCOperandInfo &OpInfo = Desc.operands()[I];
9956 if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
9957 HasLiteral = true;
9958 if (ST.has64BitLiterals()) {
9959 switch (OpInfo.OperandType) {
9960 default:
9961 break;
9964 if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
9965 LiteralSize = 8;
9966 break;
9969 // A 32-bit literal is only valid when the value fits in BOTH signed
9970 // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
9971 // emitter's getLit64Encoding logic. This is because of the lack of
9972 // abilility to tell signedness of the literal, therefore we need to
9973 // be conservative and assume values outside this range require a
9974 // 64-bit literal encoding (8 bytes).
9975 if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
9976 !isUInt<32>(Op.getImm()))
9977 LiteralSize = 8;
9978 break;
9979 }
9980 }
9981 break;
9982 }
9983 }
9984 return HasLiteral ? DescSize + LiteralSize : DescSize;
9985 }
9986
9987 // Check whether we have extra NSA words.
9988 if (isMIMG(MI)) {
9989 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
9990 if (VAddr0Idx < 0)
9991 return 8;
9992
9993 int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
9994 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
9995 }
9996
9997 switch (Opc) {
9998 case TargetOpcode::BUNDLE:
9999 return getInstBundleSize(MI);
10000 case TargetOpcode::INLINEASM:
10001 case TargetOpcode::INLINEASM_BR: {
10002 const MachineFunction *MF = MI.getMF();
10003 const char *AsmStr = MI.getOperand(0).getSymbolName();
10004 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
10005 }
10006 default:
10007 if (MI.isMetaInstruction())
10008 return 0;
10009
10010 // If D16 Pseudo inst, get correct MC code size
10011 const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
10012 if (D16Info) {
10013 // Assume d16_lo/hi inst are always in same size
10014 unsigned LoInstOpcode = D16Info->LoOp;
10015 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
10016 DescSize = Desc.getSize();
10017 }
10018
10019 // If FMA Pseudo inst, get correct MC code size
10020 if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10021 // All potential lowerings are the same size; arbitrarily pick one.
10022 const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
10023 DescSize = Desc.getSize();
10024 }
10025
10026 return DescSize;
10027 }
10028}
10029
10032 if (MI.isBranch() && ST.hasOffset3fBug())
10033 return InstSizeVerifyMode::NoVerify;
10034 return InstSizeVerifyMode::ExactSize;
10035}
10036
10038 if (!isFLAT(MI))
10039 return false;
10040
10041 if (MI.memoperands_empty())
10042 return true;
10043
10044 for (const MachineMemOperand *MMO : MI.memoperands()) {
10046 return true;
10047 }
10048 return false;
10049}
10050
10053 static const std::pair<int, const char *> TargetIndices[] = {
10054 {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
10055 {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
10056 {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
10057 {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
10058 {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
10059 return ArrayRef(TargetIndices);
10060}
10061
10062/// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The
10063/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
10066 const ScheduleDAG *DAG) const {
10067 return new GCNHazardRecognizer(DAG->MF);
10068}
10069
10070/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
10071/// pass.
10074 MachineLoopInfo *MLI) const {
10075 return new GCNHazardRecognizer(MF, MLI);
10076}
10077
10078// Called during:
10079// - pre-RA scheduling and post-RA scheduling
10082 const ScheduleDAGMI *DAG) const {
10083 // Borrowed from Arm Target
10084 // We would like to restrict this hazard recognizer to only
10085 // post-RA scheduling; we can tell that we're post-RA because we don't
10086 // track VRegLiveness.
10087 if (!DAG->hasVRegLiveness())
10088 return new GCNHazardRecognizer(DAG->MF);
10090}
10091
10092std::pair<unsigned, unsigned>
10094 return std::pair(TF & MO_MASK, TF & ~MO_MASK);
10095}
10096
10099 static const std::pair<unsigned, const char *> TargetFlags[] = {
10100 {MO_GOTPCREL, "amdgpu-gotprel"},
10101 {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
10102 {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
10103 {MO_GOTPCREL64, "amdgpu-gotprel64"},
10104 {MO_REL32_LO, "amdgpu-rel32-lo"},
10105 {MO_REL32_HI, "amdgpu-rel32-hi"},
10106 {MO_REL64, "amdgpu-rel64"},
10107 {MO_ABS32_LO, "amdgpu-abs32-lo"},
10108 {MO_ABS32_HI, "amdgpu-abs32-hi"},
10109 {MO_ABS64, "amdgpu-abs64"},
10110 };
10111
10112 return ArrayRef(TargetFlags);
10113}
10114
10117 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10118 {
10119 {MONoClobber, "amdgpu-noclobber"},
10120 {MOLastUse, "amdgpu-last-use"},
10121 {MOCooperative, "amdgpu-cooperative"},
10122 {MOThreadPrivate, "amdgpu-thread-private"},
10123 };
10124
10125 return ArrayRef(TargetFlags);
10126}
10127
10129 const MachineFunction &MF) const {
10131 assert(SrcReg.isVirtual());
10132 if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
10133 return AMDGPU::WWM_COPY;
10134
10135 return AMDGPU::COPY;
10136}
10137
10139 uint32_t Opcode = MI.getOpcode();
10140 // Check if it is SGPR spill or wwm-register spill Opcode.
10141 if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
10142 return true;
10143
10144 const MachineFunction *MF = MI.getMF();
10145 const MachineRegisterInfo &MRI = MF->getRegInfo();
10147
10148 // See if this is Liverange split instruction inserted for SGPR or
10149 // wwm-register. The implicit def inserted for wwm-registers should also be
10150 // included as they can appear at the bb begin.
10151 bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
10152 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10153 return false;
10154
10155 Register Reg = MI.getOperand(0).getReg();
10156 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10157 return IsLRSplitInst;
10158
10159 return MFI->isWWMReg(Reg);
10160}
10161
10163 Register Reg) const {
10164 // We need to handle instructions which may be inserted during register
10165 // allocation to handle the prolog. The initial prolog instruction may have
10166 // been separated from the start of the block by spills and copies inserted
10167 // needed by the prolog. However, the insertions for scalar registers can
10168 // always be placed at the BB top as they are independent of the exec mask
10169 // value.
10170 bool IsNullOrVectorRegister = true;
10171 if (Reg) {
10172 const MachineFunction *MF = MI.getMF();
10173 const MachineRegisterInfo &MRI = MF->getRegInfo();
10174 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10175 }
10176
10177 return IsNullOrVectorRegister &&
10178 (canAddToBBProlog(MI) ||
10179 (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
10180 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10181}
10182
10186 const DebugLoc &DL,
10187 Register DestReg) const {
10188 if (ST.hasAddNoCarryInsts())
10189 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);
10190
10191 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
10192 Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
10193 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10194
10195 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10196 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10197}
10198
10201 const DebugLoc &DL,
10202 Register DestReg,
10203 RegScavenger &RS) const {
10204 if (ST.hasAddNoCarryInsts())
10205 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);
10206
10207 // If available, prefer to use vcc.
10208 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10209 ? Register(RI.getVCC())
10210 : RS.scavengeRegisterBackwards(
10211 *RI.getBoolRC(), I, /* RestoreAfter */ false,
10212 0, /* AllowSpill */ false);
10213
10214 // TODO: Users need to deal with this.
10215 if (!UnusedCarry.isValid())
10216 return MachineInstrBuilder();
10217
10218 return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
10219 .addReg(UnusedCarry, RegState::Define | RegState::Dead);
10220}
10221
10222bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
10223 switch (Opcode) {
10224 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10225 case AMDGPU::SI_KILL_I1_TERMINATOR:
10226 return true;
10227 default:
10228 return false;
10229 }
10230}
10231
10233 switch (Opcode) {
10234 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10235 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10236 case AMDGPU::SI_KILL_I1_PSEUDO:
10237 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10238 default:
10239 llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
10240 }
10241}
10242
10243bool SIInstrInfo::isLegalMUBUFImmOffset(unsigned Imm) const {
10244 return Imm <= getMaxMUBUFImmOffset(ST);
10245}
10246
10248 // GFX12 field is non-negative 24-bit signed byte offset.
10249 const unsigned OffsetBits =
10250 ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
10251 return (1 << OffsetBits) - 1;
10252}
10253
10255 if (!ST.isWave32())
10256 return;
10257
10258 if (MI.isInlineAsm())
10259 return;
10260
10261 if (MI.getNumOperands() < MI.getNumExplicitOperands())
10262 return;
10263
10264 for (auto &Op : MI.implicit_operands()) {
10265 if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
10266 Op.setReg(AMDGPU::VCC_LO);
10267 }
10268}
10269
10271 if (!isSMRD(MI))
10272 return false;
10273
10274 // Check that it is using a buffer resource.
10275 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
10276 if (Idx == -1) // e.g. s_memtime
10277 return false;
10278
10279 const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
10280 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10281}
10282
10283// Given Imm, split it into the values to put into the SOffset and ImmOffset
10284// fields in an MUBUF instruction. Return false if it is not possible (due to a
10285// hardware bug needing a workaround).
10286//
10287// The required alignment ensures that individual address components remain
10288// aligned if they are aligned to begin with. It also ensures that additional
10289// offsets within the given alignment can be added to the resulting ImmOffset.
10291 uint32_t &ImmOffset, Align Alignment) const {
10292 const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
10293 const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
10294 uint32_t Overflow = 0;
10295
10296 if (Imm > MaxImm) {
10297 if (Imm <= MaxImm + 64) {
10298 // Use an SOffset inline constant for 4..64
10299 Overflow = Imm - MaxImm;
10300 Imm = MaxImm;
10301 } else {
10302 // Try to keep the same value in SOffset for adjacent loads, so that
10303 // the corresponding register contents can be re-used.
10304 //
10305 // Load values with all low-bits (except for alignment bits) set into
10306 // SOffset, so that a larger range of values can be covered using
10307 // s_movk_i32.
10308 //
10309 // Atomic operations fail to work correctly when individual address
10310 // components are unaligned, even if their sum is aligned.
10311 uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
10312 uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
10313 Imm = Low;
10314 Overflow = High - Alignment.value();
10315 }
10316 }
10317
10318 if (Overflow > 0) {
10319 // There is a hardware bug in SI and CI which prevents address clamping in
10320 // MUBUF instructions from working correctly with SOffsets. The immediate
10321 // offset is unaffected.
10322 if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
10323 return false;
10324
10325 // It is not possible to set immediate in SOffset field on some targets.
10326 if (ST.hasRestrictedSOffset())
10327 return false;
10328 }
10329
10330 ImmOffset = Imm;
10331 SOffset = Overflow;
10332 return true;
10333}
10334
10335// Depending on the used address space and instructions, some immediate offsets
10336// are allowed and some are not.
10337// Pre-GFX12, flat instruction offsets can only be non-negative, global and
10338// scratch instruction offsets can also be negative. On GFX12, offsets can be
10339// negative for all variants.
10340//
10341// There are several bugs related to these offsets:
10342// On gfx10.1, flat instructions that go into the global address space cannot
10343// use an offset.
10344//
10345// For scratch instructions, the address can be either an SGPR or a VGPR.
10346// The following offsets can be used, depending on the architecture (x means
10347// cannot be used):
10348// +----------------------------+------+------+
10349// | Address-Mode | SGPR | VGPR |
10350// +----------------------------+------+------+
10351// | gfx9 | | |
10352// | negative, 4-aligned offset | x | ok |
10353// | negative, unaligned offset | x | ok |
10354// +----------------------------+------+------+
10355// | gfx10 | | |
10356// | negative, 4-aligned offset | ok | ok |
10357// | negative, unaligned offset | ok | x |
10358// +----------------------------+------+------+
10359// | gfx10.3 | | |
10360// | negative, 4-aligned offset | ok | ok |
10361// | negative, unaligned offset | ok | ok |
10362// +----------------------------+------+------+
10363//
10364// This function ignores the addressing mode, so if an offset cannot be used in
10365// one addressing mode, it is considered illegal.
10366bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
10367 AMDGPU::FlatAddrSpace FlatVariant) const {
10368 // TODO: Should 0 be special cased?
10369 if (!ST.hasFlatInstOffsets())
10370 return false;
10371
10373 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10374 (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
10375 AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
10376 return false;
10377
10378 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10379 FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
10380 (Offset % 4) != 0) {
10381 return false;
10382 }
10383
10384 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10385 unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
10386 return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
10387}
10388
10389// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
10390std::pair<int64_t, int64_t>
10391SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
10392 AMDGPU::FlatAddrSpace FlatVariant) const {
10393 int64_t RemainderOffset = COffsetVal;
10394 int64_t ImmField = 0;
10395
10396 bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
10397 const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;
10398
10399 if (AllowNegative) {
10400 // Use signed division by a power of two to truncate towards 0.
10401 int64_t D = 1LL << NumBits;
10402 RemainderOffset = (COffsetVal / D) * D;
10403 ImmField = COffsetVal - RemainderOffset;
10404
10405 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10406 FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
10407 (ImmField % 4) != 0) {
10408 // Make ImmField a multiple of 4
10409 RemainderOffset += ImmField % 4;
10410 ImmField -= ImmField % 4;
10411 }
10412 } else if (COffsetVal >= 0) {
10413 ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
10414 RemainderOffset = COffsetVal - ImmField;
10415 }
10416
10417 assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
10418 assert(RemainderOffset + ImmField == COffsetVal);
10419 return {ImmField, RemainderOffset};
10420}
10421
10423 AMDGPU::FlatAddrSpace FlatVariant) const {
10424 if (ST.hasNegativeScratchOffsetBug() &&
10426 return false;
10427
10428 return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
10429}
10430
10431static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
10432 switch (ST.getGeneration()) {
10433 default:
10434 break;
10437 return SIEncodingFamily::SI;
10440 return SIEncodingFamily::VI;
10444 return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
10447 return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
10451 }
10452 llvm_unreachable("Unknown subtarget generation!");
10453}
10454
10455bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
10456 switch(MCOp) {
10457 // These opcodes use indirect register addressing so
10458 // they need special handling by codegen (currently missing).
10459 // Therefore it is too risky to allow these opcodes
10460 // to be selected by dpp combiner or sdwa peepholer.
10461 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10462 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10463 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10464 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10465 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10466 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10467 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10468 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10469 return true;
10470 default:
10471 return false;
10472 }
10473}
10474
10475#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10476 case OPCODE##_dpp: \
10477 case OPCODE##_e32: \
10478 case OPCODE##_e64: \
10479 case OPCODE##_e64_dpp: \
10480 case OPCODE##_sdwa:
10481
10482static bool isRenamedInGFX9(int Opcode) {
10483 switch (Opcode) {
10484 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
10485 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
10486 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
10487 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
10488 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
10489 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
10490 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
10491 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
10492 GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
10493 //
10494 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10495 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10496 case AMDGPU::V_FMA_F16_gfx9_e64:
10497 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10498 case AMDGPU::V_INTERP_P2_F16:
10499 case AMDGPU::V_MAD_F16_e64:
10500 case AMDGPU::V_MAD_U16_e64:
10501 case AMDGPU::V_MAD_I16_e64:
10502 return true;
10503 default:
10504 return false;
10505 }
10506}
10507
10508int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
10509 assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
10510 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10511
10512 unsigned Gen = subtargetEncodingFamily(ST);
10513
10514 if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
10516
10517 // Adjust the encoding family to GFX80 for D16 buffer instructions when the
10518 // subtarget has UnpackedD16VMem feature.
10519 // TODO: remove this when we discard GFX80 encoding.
10520 if (ST.hasUnpackedD16VMem() && SIInstrFlags::isD16Buf(get(Opcode)))
10522
10523 if (SIInstrFlags::isSDWA(get(Opcode))) {
10524 switch (ST.getGeneration()) {
10525 default:
10527 break;
10530 break;
10533 break;
10534 }
10535 }
10536
10537 if (isMAI(Opcode)) {
10538 int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
10539 if (MFMAOp != -1)
10540 Opcode = MFMAOp;
10541 }
10542
10543 int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);
10544
10545 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10547
10548 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10550
10551 // -1 means that Opcode is already a native instruction.
10552 if (MCOp == -1)
10553 return Opcode;
10554
10555 if (ST.hasGFX90AInsts()) {
10556 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10557 if (ST.hasGFX940Insts())
10559 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10561 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10563 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10564 MCOp = NMCOp;
10565 }
10566
10567 // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
10568 // encoding in the given subtarget generation.
10569 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10570 return -1;
10571
10572 if (isAsmOnlyOpcode(MCOp))
10573 return -1;
10574
10575 return MCOp;
10576}
10577
10578static
10580 assert(RegOpnd.isReg());
10581 return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
10582 getRegSubRegPair(RegOpnd);
10583}
10584
10587 assert(MI.isRegSequence());
10588 for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
10589 if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
10590 auto &RegOp = MI.getOperand(1 + 2 * I);
10591 return getRegOrUndef(RegOp);
10592 }
10594}
10595
10596// Try to find the definition of reg:subreg in subreg-manipulation pseudos
10597// Following a subreg of reg:subreg isn't supported
10600 if (!RSR.SubReg)
10601 return false;
10602 switch (MI.getOpcode()) {
10603 default: break;
10604 case AMDGPU::REG_SEQUENCE:
10605 RSR = getRegSequenceSubReg(MI, RSR.SubReg);
10606 return true;
10607 // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
10608 case AMDGPU::INSERT_SUBREG:
10609 if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
10610 // inserted the subreg we're looking for
10611 RSR = getRegOrUndef(MI.getOperand(2));
10612 else { // the subreg in the rest of the reg
10613 auto R1 = getRegOrUndef(MI.getOperand(1));
10614 if (R1.SubReg) // subreg of subreg isn't supported
10615 return false;
10616 RSR.Reg = R1.Reg;
10617 }
10618 return true;
10619 }
10620 return false;
10621}
10622
10624 const MachineRegisterInfo &MRI) {
10625 assert(MRI.isSSA());
10626 if (!P.Reg.isVirtual())
10627 return nullptr;
10628
10629 auto RSR = P;
10630 auto *DefInst = MRI.getVRegDef(RSR.Reg);
10631 while (auto *MI = DefInst) {
10632 DefInst = nullptr;
10633 switch (MI->getOpcode()) {
10634 case AMDGPU::COPY:
10635 case AMDGPU::V_MOV_B32_e32: {
10636 auto &Op1 = MI->getOperand(1);
10637 if (Op1.isReg() && Op1.getReg().isVirtual()) {
10638 if (Op1.isUndef())
10639 return nullptr;
10640 RSR = getRegSubRegPair(Op1);
10641 DefInst = MRI.getVRegDef(RSR.Reg);
10642 }
10643 break;
10644 }
10645 default:
10646 if (followSubRegDef(*MI, RSR)) {
10647 if (!RSR.Reg)
10648 return nullptr;
10649 DefInst = MRI.getVRegDef(RSR.Reg);
10650 }
10651 }
10652 if (!DefInst)
10653 return MI;
10654 }
10655 return nullptr;
10656}
10657
10659 Register VReg,
10660 const MachineInstr &DefMI,
10661 const MachineInstr &UseMI) {
10662 assert(MRI.isSSA() && "Must be run on SSA");
10663
10664 auto *TRI = MRI.getTargetRegisterInfo();
10665 auto *DefBB = DefMI.getParent();
10666
10667 // Don't bother searching between blocks, although it is possible this block
10668 // doesn't modify exec.
10669 if (UseMI.getParent() != DefBB)
10670 return true;
10671
10672 const int MaxInstScan = 20;
10673 int NumInst = 0;
10674
10675 // Stop scan at the use.
10676 auto E = UseMI.getIterator();
10677 for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
10678 if (I->isDebugInstr())
10679 continue;
10680
10681 if (++NumInst > MaxInstScan)
10682 return true;
10683
10684 if (I->modifiesRegister(AMDGPU::EXEC, TRI))
10685 return true;
10686 }
10687
10688 return false;
10689}
10690
10692 Register VReg,
10693 const MachineInstr &DefMI) {
10694 assert(MRI.isSSA() && "Must be run on SSA");
10695
10696 auto *TRI = MRI.getTargetRegisterInfo();
10697 auto *DefBB = DefMI.getParent();
10698
10699 const int MaxUseScan = 10;
10700 int NumUse = 0;
10701
10702 for (auto &Use : MRI.use_nodbg_operands(VReg)) {
10703 auto &UseInst = *Use.getParent();
10704 // Don't bother searching between blocks, although it is possible this block
10705 // doesn't modify exec.
10706 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10707 return true;
10708
10709 if (++NumUse > MaxUseScan)
10710 return true;
10711 }
10712
10713 if (NumUse == 0)
10714 return false;
10715
10716 const int MaxInstScan = 20;
10717 int NumInst = 0;
10718
10719 // Stop scan when we have seen all the uses.
10720 for (auto I = std::next(DefMI.getIterator()); ; ++I) {
10721 assert(I != DefBB->end());
10722
10723 if (I->isDebugInstr())
10724 continue;
10725
10726 if (++NumInst > MaxInstScan)
10727 return true;
10728
10729 for (const MachineOperand &Op : I->operands()) {
10730 // We don't check reg masks here as they're used only on calls:
10731 // 1. EXEC is only considered const within one BB
10732 // 2. Call should be a terminator instruction if present in a BB
10733
10734 if (!Op.isReg())
10735 continue;
10736
10737 Register Reg = Op.getReg();
10738 if (Op.isUse()) {
10739 if (Reg == VReg && --NumUse == 0)
10740 return false;
10741 } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
10742 return true;
10743 }
10744 }
10745}
10746
10749 const DebugLoc &DL, Register Src, Register Dst) const {
10750 auto Cur = MBB.begin();
10751 if (Cur != MBB.end())
10752 do {
10753 if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
10754 return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
10755 ++Cur;
10756 } while (Cur != MBB.end() && Cur != LastPHIIt);
10757
10758 return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
10759 Dst);
10760}
10761
10764 const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
10765 if (InsPt != MBB.end() &&
10766 (InsPt->getOpcode() == AMDGPU::SI_IF ||
10767 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
10768 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
10769 InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
10770 InsPt++;
10771 return BuildMI(MBB, InsPt, DL,
10772 get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
10773 .addReg(Src, {}, SrcSubReg)
10774 .addReg(AMDGPU::EXEC, RegState::Implicit);
10775 }
10776 return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
10777 Dst);
10778}
10779
10780bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }
10781
10783 const MachineInstr &SecondMI) const {
10784 for (const auto &Use : SecondMI.all_uses()) {
10785 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
10786 return true;
10787 }
10788 return false;
10789}
10790
10791/// If OpX is multicycle, anti-dependencies are not allowed.
10792/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
10793/// purpose.
10795 const MachineInstr &OpX) const {
10797}
10798
10801 ArrayRef<unsigned> Ops, int FrameIndex,
10802 MachineInstr *&CopyMI, LiveIntervals *LIS,
10803 VirtRegMap *VRM) const {
10804 // This is a bit of a hack (copied from AArch64). Consider this instruction:
10805 //
10806 // %0:sreg_32 = COPY $m0
10807 //
10808 // We explicitly chose SReg_32 for the virtual register so such a copy might
10809 // be eliminated by RegisterCoalescer. However, that may not be possible, and
10810 // %0 may even spill. We can't spill $m0 normally (it would require copying to
10811 // a numbered SGPR anyway), and since it is in the SReg_32 register class,
10812 // TargetInstrInfo::foldMemoryOperand() is going to try.
10813 // A similar issue also exists with spilling and reloading $exec registers.
10814 //
10815 // To prevent that, constrain the %0 register class here.
10816 if (isFullCopyInstr(MI)) {
10817 Register DstReg = MI.getOperand(0).getReg();
10818 Register SrcReg = MI.getOperand(1).getReg();
10819 if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
10820 (DstReg.isVirtual() != SrcReg.isVirtual())) {
10821 MachineRegisterInfo &MRI = MF.getRegInfo();
10822 Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
10823 const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
10824 if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
10825 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
10826 return nullptr;
10827 }
10828 if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
10829 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
10830 return nullptr;
10831 }
10832 }
10833 }
10834
10835 return nullptr;
10836}
10837
10839 const MachineInstr &MI,
10840 unsigned *PredCost) const {
10841 if (MI.isBundle()) {
10843 MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
10844 unsigned Lat = 0, Count = 0;
10845 for (++I; I != E && I->isBundledWithPred(); ++I) {
10846 ++Count;
10847 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
10848 }
10849 return Lat + Count - 1;
10850 }
10851
10852 return SchedModel.computeInstrLatency(&MI);
10853}
10854
10855const MachineOperand &
10857 if (const MachineOperand *CallAddrOp =
10858 getNamedOperand(MI, AMDGPU::OpName::src0))
10859 return *CallAddrOp;
10861}
10862
10865 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
10866 unsigned Opcode = MI.getOpcode();
10867
10868 auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
10869 Register Dst = MI.getOperand(0).getReg();
10870 Register Src = isa<GIntrinsic>(MI) ? MI.getOperand(2).getReg()
10871 : MI.getOperand(1).getReg();
10872 LLT DstTy = MRI.getType(Dst);
10873 LLT SrcTy = MRI.getType(Src);
10874 unsigned DstAS = DstTy.getAddressSpace();
10875 unsigned SrcAS = SrcTy.getAddressSpace();
10876 return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
10877 DstAS == AMDGPUAS::FLAT_ADDRESS &&
10878 ST.hasGloballyAddressableScratch()
10881 };
10882
10883 // If the target supports globally addressable scratch, the mapping from
10884 // scratch memory to the flat aperture changes therefore an address space cast
10885 // is no longer uniform.
10886 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
10887 return HandleAddrSpaceCast(MI);
10888
10889 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
10890 auto IID = GI->getIntrinsicID();
10895
10896 switch (IID) {
10897 case Intrinsic::amdgcn_addrspacecast_nonnull:
10898 return HandleAddrSpaceCast(MI);
10899 case Intrinsic::amdgcn_if:
10900 case Intrinsic::amdgcn_else:
10901 // FIXME: Uniform if second result
10902 break;
10903 }
10904
10906 }
10907
10908 // Loads from the private and flat address spaces are divergent, because
10909 // threads can execute the load instruction with the same inputs and get
10910 // different results.
10911 //
10912 // All other loads are not divergent, because if threads issue loads with the
10913 // same arguments, they will always get the same result.
10914 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
10915 Opcode == AMDGPU::G_SEXTLOAD) {
10916 if (MI.memoperands_empty())
10917 return ValueUniformity::NeverUniform; // conservative assumption
10918
10919 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
10920 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
10921 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
10922 })) {
10923 // At least one MMO in a non-global address space.
10925 }
10927 }
10928
10929 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
10930 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
10931 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
10932 AMDGPU::isGenericAtomic(Opcode)) {
10934 }
10935
10936 // Result is computed from uniform SP and uniform wave-wide max size.
10937 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
10939
10940 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
10942
10944}
10945
10947 if (!Formatter)
10948 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
10949 return Formatter.get();
10950}
10951
10953
10954 if (isNeverUniform(MI))
10956
10957 unsigned opcode = MI.getOpcode();
10958 if (opcode == AMDGPU::V_READLANE_B32 ||
10959 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
10960 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
10962
10963 // If any of defs is divergent, report as NeverUniform. isUniformReg will
10964 // calculate in more detail for each def from its reg class, if available.
10965 if (MI.isInlineAsm()) {
10966 for (const MachineOperand &MO : MI.operands()) {
10967 if (!MO.isReg() || !MO.isDef())
10968 continue;
10969 const TargetRegisterClass *RC =
10970 MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
10971 if (!RC || !RI.isSGPRClass(RC))
10973 }
10974 }
10975
10976 if (isCopyInstr(MI)) {
10977 const MachineOperand &srcOp = MI.getOperand(1);
10978 if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
10979 const TargetRegisterClass *regClass =
10980 RI.getPhysRegBaseClass(srcOp.getReg());
10981 return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
10983 }
10985 }
10986
10987 // GMIR handling
10988 if (MI.isPreISelOpcode())
10990
10991 // Atomics are divergent because they are executed sequentially: when an
10992 // atomic operation refers to the same address in each thread, then each
10993 // thread after the first sees the value written by the previous thread as
10994 // original value.
10995
10996 if (isAtomic(MI))
10998
10999 // Loads from the private and flat address spaces are divergent, because
11000 // threads can execute the load instruction with the same inputs and get
11001 // different results.
11002 if (isFLAT(MI) && MI.mayLoad()) {
11003 if (MI.memoperands_empty())
11004 return ValueUniformity::NeverUniform; // conservative assumption
11005
11006 if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
11007 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11008 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11009 })) {
11010 // At least one MMO in a non-global address space.
11012 }
11013
11015 }
11016
11017 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
11018 const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
11019
11020 // FIXME: It's conceptually broken to report this for an instruction, and not
11021 // a specific def operand. For inline asm in particular, there could be mixed
11022 // uniform and divergent results.
11023 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
11024 const MachineOperand &SrcOp = MI.getOperand(I);
11025 if (!SrcOp.isReg())
11026 continue;
11027
11028 Register Reg = SrcOp.getReg();
11029 if (!Reg || !SrcOp.readsReg())
11030 continue;
11031
11032 // If RegBank is null, this is unassigned or an unallocatable special
11033 // register, which are all scalars.
11034 const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
11035 if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
11037 }
11038
11039 // TODO: Uniformity check condtions above can be rearranged for more
11040 // redability
11041
11042 // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
11043 // currently turned into no-op COPYs by SelectionDAG ISel and are
11044 // therefore no longer recognizable.
11045
11047}
11048
11050 switch (MF.getFunction().getCallingConv()) {
11052 return 1;
11054 return 2;
11056 return 3;
11060 const Function &F = MF.getFunction();
11061 F.getContext().diagnose(DiagnosticInfoUnsupported(
11062 F, "ds_ordered_count unsupported for this calling conv"));
11063 [[fallthrough]];
11064 }
11067 case CallingConv::C:
11068 case CallingConv::Fast:
11069 default:
11070 // Assume other calling conventions are various compute callable functions
11071 return 0;
11072 }
11073}
11074
11076 Register &SrcReg2, int64_t &CmpMask,
11077 int64_t &CmpValue) const {
11078 if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
11079 return false;
11080
11081 switch (MI.getOpcode()) {
11082 default:
11083 break;
11084 case AMDGPU::S_CMP_EQ_U32:
11085 case AMDGPU::S_CMP_EQ_I32:
11086 case AMDGPU::S_CMP_LG_U32:
11087 case AMDGPU::S_CMP_LG_I32:
11088 case AMDGPU::S_CMP_LT_U32:
11089 case AMDGPU::S_CMP_LT_I32:
11090 case AMDGPU::S_CMP_GT_U32:
11091 case AMDGPU::S_CMP_GT_I32:
11092 case AMDGPU::S_CMP_LE_U32:
11093 case AMDGPU::S_CMP_LE_I32:
11094 case AMDGPU::S_CMP_GE_U32:
11095 case AMDGPU::S_CMP_GE_I32:
11096 case AMDGPU::S_CMP_EQ_U64:
11097 case AMDGPU::S_CMP_LG_U64:
11098 SrcReg = MI.getOperand(0).getReg();
11099 if (MI.getOperand(1).isReg()) {
11100 if (MI.getOperand(1).getSubReg())
11101 return false;
11102 SrcReg2 = MI.getOperand(1).getReg();
11103 CmpValue = 0;
11104 } else if (MI.getOperand(1).isImm()) {
11105 SrcReg2 = Register();
11106 CmpValue = MI.getOperand(1).getImm();
11107 } else {
11108 return false;
11109 }
11110 CmpMask = ~0;
11111 return true;
11112 case AMDGPU::S_CMPK_EQ_U32:
11113 case AMDGPU::S_CMPK_EQ_I32:
11114 case AMDGPU::S_CMPK_LG_U32:
11115 case AMDGPU::S_CMPK_LG_I32:
11116 case AMDGPU::S_CMPK_LT_U32:
11117 case AMDGPU::S_CMPK_LT_I32:
11118 case AMDGPU::S_CMPK_GT_U32:
11119 case AMDGPU::S_CMPK_GT_I32:
11120 case AMDGPU::S_CMPK_LE_U32:
11121 case AMDGPU::S_CMPK_LE_I32:
11122 case AMDGPU::S_CMPK_GE_U32:
11123 case AMDGPU::S_CMPK_GE_I32:
11124 SrcReg = MI.getOperand(0).getReg();
11125 SrcReg2 = Register();
11126 CmpValue = MI.getOperand(1).getImm();
11127 CmpMask = ~0;
11128 return true;
11129 }
11130
11131 return false;
11132}
11133
11135 for (MachineBasicBlock *S : MBB->successors()) {
11136 if (S->isLiveIn(AMDGPU::SCC))
11137 return false;
11138 }
11139 return true;
11140}
11141
11142// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
11143// (incoming SCC) = !(SCC defined by SCCDef).
11144// Return true if all uses can be re-written, false otherwise.
11145bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
11146 MachineBasicBlock *MBB = SCCDef->getParent();
11147 SmallVector<MachineInstr *> InvertInstr;
11148 bool SCCIsDead = false;
11149
11150 // Scan instructions for SCC uses that need to be inverted until SCC is dead.
11151 constexpr unsigned ScanLimit = 12;
11152 unsigned Count = 0;
11153 for (MachineInstr &MI :
11154 make_range(std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
11155 if (++Count > ScanLimit)
11156 return false;
11157 if (MI.readsRegister(AMDGPU::SCC, &RI)) {
11158 if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11159 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11160 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11161 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11162 InvertInstr.push_back(&MI);
11163 else
11164 return false;
11165 }
11166 if (MI.definesRegister(AMDGPU::SCC, &RI)) {
11167 SCCIsDead = true;
11168 break;
11169 }
11170 }
11171 if (!SCCIsDead && isSCCDeadOnExit(MBB))
11172 SCCIsDead = true;
11173
11174 // SCC may have more uses. Can't invert all of them.
11175 if (!SCCIsDead)
11176 return false;
11177
11178 // Invert uses
11179 for (MachineInstr *MI : InvertInstr) {
11180 if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11181 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11182 swapOperands(*MI);
11183 } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11184 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11185 MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11186 ? AMDGPU::S_CBRANCH_SCC1
11187 : AMDGPU::S_CBRANCH_SCC0));
11188 } else {
11189 llvm_unreachable("SCC used but no inversion handling");
11190 }
11191 }
11192 return true;
11193}
11194
11195// SCC is already valid after SCCValid.
11196// SCCRedefine will redefine SCC to the same value already available after
11197// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
11198// update kill/dead flags if necessary.
11199bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
11200 bool NeedInversion) const {
11201 MachineInstr *KillsSCC = nullptr;
11202 if (SCCValid->getParent() != SCCRedefine->getParent())
11203 return false;
11204 for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
11205 SCCRedefine->getIterator())) {
11206 if (MI.modifiesRegister(AMDGPU::SCC, &RI))
11207 return false;
11208 if (MI.killsRegister(AMDGPU::SCC, &RI))
11209 KillsSCC = &MI;
11210 }
11211 if (NeedInversion && !invertSCCUse(SCCRedefine))
11212 return false;
11213 if (MachineOperand *SccDef =
11214 SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
11215 SccDef->setIsDead(false);
11216 if (KillsSCC)
11217 KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
11218 SCCRedefine->eraseFromParent();
11219 return true;
11220}
11221
11222static bool foldableSelect(const MachineInstr &Def) {
11223 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11224 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11225 return false;
11226 bool Op1IsNonZeroImm =
11227 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11228 bool Op2IsZeroImm =
11229 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11230 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11231 return false;
11232 return true;
11233}
11234
11235static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
11236 unsigned &NewDefOpc) {
11237 // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
11238 // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
11239 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11240 Def.getOpcode() != AMDGPU::S_ADD_U32)
11241 return false;
11242 const MachineOperand &AddSrc1 = Def.getOperand(1);
11243 const MachineOperand &AddSrc2 = Def.getOperand(2);
11244 int64_t addend;
11245
11246 if ((!AddSrc1.isImm() || AddSrc1.getImm() != 1) &&
11247 (!AddSrc2.isImm() || AddSrc2.getImm() != 1) &&
11248 (!getFoldableImm(&AddSrc1, addend) || addend != 1) &&
11249 (!getFoldableImm(&AddSrc2, addend) || addend != 1))
11250 return false;
11251
11252 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11253 const MachineOperand *SccDef =
11254 Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
11255 if (!SccDef->isDead())
11256 return false;
11257 NewDefOpc = AMDGPU::S_ADD_U32;
11258 }
11259 NeedInversion = !NeedInversion;
11260 return true;
11261}
11262
11264 Register SrcReg2, int64_t CmpMask,
11265 int64_t CmpValue,
11266 const MachineRegisterInfo *MRI) const {
11267 if (!SrcReg || SrcReg.isPhysical())
11268 return false;
11269
11270 if (SrcReg2 && !getFoldableImm(SrcReg2, *MRI, CmpValue))
11271 return false;
11272
11273 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11274 this](bool NeedInversion) -> bool {
11275 if (CmpValue != 0)
11276 return false;
11277
11278 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11279 if (!Def)
11280 return false;
11281
11282 // For S_OP that set SCC = DST!=0, do the transformation
11283 //
11284 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11285 //
11286 // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
11287 // do the transformation:
11288 //
11289 // s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
11290 //
11291 // If foldableSelect, s_cmp_lg_* is redundant because the SCC input value
11292 // for S_CSELECT* already has the same value that will be calculated by
11293 // s_cmp_lg_*
11294 //
11295 // s_cmp_[lg|eq]_* (S_CSELECT* (non-zero imm), 0), 0 => (S_CSELECT*
11296 // (non-zero imm), 0)
11297
11298 unsigned NewDefOpc = Def->getOpcode();
11299 if (!setsSCCIfResultIsNonZero(*Def) &&
11300 !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc) &&
11301 !foldableSelect(*Def))
11302 return false;
11303
11304 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11305 return false;
11306
11307 if (NewDefOpc != Def->getOpcode())
11308 Def->setDesc(get(NewDefOpc));
11309
11310 // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
11311 // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
11312 // 64-bit foldableSelect then delete s_or_b32 in the sequence:
11313 // sX = s_cselect_b64 (non-zero imm), 0
11314 // sLo = copy sX.sub0
11315 // sHi = copy sX.sub1
11316 // sY = s_or_b32 sLo, sHi
11317 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11318 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11319 const MachineOperand &OrOpnd1 = Def->getOperand(1);
11320 const MachineOperand &OrOpnd2 = Def->getOperand(2);
11321 if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
11322 MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
11323 MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
11324 if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
11325 Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
11326 Def2->getOperand(1).isReg() &&
11327 Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
11328 Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
11329 Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
11330 MachineInstr *Select = MRI->getVRegDef(Def1->getOperand(1).getReg());
11331 if (Select && foldableSelect(*Select))
11332 optimizeSCC(Select, Def, /*NeedInversion=*/false);
11333 }
11334 }
11335 }
11336 return true;
11337 };
11338
11339 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11340 this](int64_t ExpectedValue, unsigned SrcSize,
11341 bool IsReversible, bool IsSigned) -> bool {
11342 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11343 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11344 // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11345 // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
11346 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
11347 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11348 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11349 // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11350 // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
11351 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
11352 //
11353 // Signed ge/gt are not used for the sign bit.
11354 //
11355 // If result of the AND is unused except in the compare:
11356 // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
11357 //
11358 // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11359 // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
11360 // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
11361 // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11362 // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
11363 // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n
11364
11365 MachineInstr *Def = MRI->getVRegDef(SrcReg);
11366 if (!Def)
11367 return false;
11368
11369 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11370 Def->getOpcode() != AMDGPU::S_AND_B64)
11371 return false;
11372
11373 int64_t Mask;
11374 const auto isMask = [&Mask, SrcSize](const MachineOperand *MO) -> bool {
11375 if (MO->isImm())
11376 Mask = MO->getImm();
11377 else if (!getFoldableImm(MO, Mask))
11378 return false;
11379 Mask &= maxUIntN(SrcSize);
11380 return isPowerOf2_64(Mask);
11381 };
11382
11383 MachineOperand *SrcOp = &Def->getOperand(1);
11384 if (isMask(SrcOp))
11385 SrcOp = &Def->getOperand(2);
11386 else if (isMask(&Def->getOperand(2)))
11387 SrcOp = &Def->getOperand(1);
11388 else
11389 return false;
11390
11391 // A valid Mask is required to have a single bit set, hence a non-zero and
11392 // power-of-two value. This verifies that we will not do 64-bit shift below.
11393 assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
11394 unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
11395 if (IsSigned && BitNo == SrcSize - 1)
11396 return false;
11397
11398 ExpectedValue <<= BitNo;
11399
11400 bool IsReversedCC = false;
11401 if (CmpValue != ExpectedValue) {
11402 if (!IsReversible)
11403 return false;
11404 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11405 if (!IsReversedCC)
11406 return false;
11407 }
11408
11409 Register DefReg = Def->getOperand(0).getReg();
11410 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11411 return false;
11412
11413 if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
11414 return false;
11415
11416 if (!MRI->use_nodbg_empty(DefReg)) {
11417 assert(!IsReversedCC);
11418 return true;
11419 }
11420
11421 // Replace AND with unused result with a S_BITCMP.
11422 MachineBasicBlock *MBB = Def->getParent();
11423
11424 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11425 : AMDGPU::S_BITCMP1_B32
11426 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11427 : AMDGPU::S_BITCMP1_B64;
11428
11429 BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
11430 .add(*SrcOp)
11431 .addImm(BitNo);
11432 Def->eraseFromParent();
11433
11434 return true;
11435 };
11436
11437 switch (CmpInstr.getOpcode()) {
11438 default:
11439 break;
11440 case AMDGPU::S_CMP_EQ_U32:
11441 case AMDGPU::S_CMP_EQ_I32:
11442 case AMDGPU::S_CMPK_EQ_U32:
11443 case AMDGPU::S_CMPK_EQ_I32:
11444 return optimizeCmpAnd(1, 32, true, false) ||
11445 optimizeCmpSelect(/*NeedInversion=*/true);
11446 case AMDGPU::S_CMP_GE_U32:
11447 case AMDGPU::S_CMPK_GE_U32:
11448 return optimizeCmpAnd(1, 32, false, false);
11449 case AMDGPU::S_CMP_GE_I32:
11450 case AMDGPU::S_CMPK_GE_I32:
11451 return optimizeCmpAnd(1, 32, false, true);
11452 case AMDGPU::S_CMP_EQ_U64:
11453 return optimizeCmpAnd(1, 64, true, false);
11454 case AMDGPU::S_CMP_LG_U32:
11455 case AMDGPU::S_CMP_LG_I32:
11456 case AMDGPU::S_CMPK_LG_U32:
11457 case AMDGPU::S_CMPK_LG_I32:
11458 return optimizeCmpAnd(0, 32, true, false) ||
11459 optimizeCmpSelect(/*NeedInversion=*/false);
11460 case AMDGPU::S_CMP_GT_U32:
11461 case AMDGPU::S_CMPK_GT_U32:
11462 return optimizeCmpAnd(0, 32, false, false);
11463 case AMDGPU::S_CMP_GT_I32:
11464 case AMDGPU::S_CMPK_GT_I32:
11465 return optimizeCmpAnd(0, 32, false, true);
11466 case AMDGPU::S_CMP_LG_U64:
11467 return optimizeCmpAnd(0, 64, true, false) ||
11468 optimizeCmpSelect(/*NeedInversion=*/false);
11469 }
11470
11471 return false;
11472}
11473
11475 AMDGPU::OpName OpName) const {
11476 if (!ST.needsAlignedVGPRs())
11477 return;
11478
11479 int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
11480 if (OpNo < 0)
11481 return;
11482 MachineOperand &Op = MI.getOperand(OpNo);
11483 if (getOpSize(MI, OpNo) > 4)
11484 return;
11485
11486 // Add implicit aligned super-reg to force alignment on the data operand.
11487 const DebugLoc &DL = MI.getDebugLoc();
11488 MachineBasicBlock *BB = MI.getParent();
11490 Register DataReg = Op.getReg();
11491 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11493 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11494 BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
11495 Register NewVR =
11496 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
11497 : &AMDGPU::VReg_64_Align2RegClass);
11498 BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
11499 .addReg(DataReg, {}, Op.getSubReg())
11500 .addImm(AMDGPU::sub0)
11501 .addReg(Undef)
11502 .addImm(AMDGPU::sub1);
11503 Op.setReg(NewVR);
11504 Op.setSubReg(AMDGPU::sub0);
11505 MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
11506}
11507
11509 if (isIGLP(*MI))
11510 return false;
11511
11513}
11514
11516 if (!isWMMA(MI) && !isSWMMAC(MI))
11517 return false;
11518
11519 if (ST.hasGFX1250Insts())
11520 return AMDGPU::getWMMAIsXDL(MI.getOpcode());
11521
11522 return true;
11523}
11524
11526 unsigned Opcode = MI.getOpcode();
11527
11528 if (AMDGPU::isGFX12Plus(ST))
11529 return isDOT(MI) || isXDLWMMA(MI);
11530
11531 if (!isMAI(MI) || isDGEMM(Opcode) ||
11532 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11533 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11534 return false;
11535
11536 if (!ST.hasGFX940Insts())
11537 return true;
11538
11539 return AMDGPU::getMAIIsGFX940XDL(Opcode);
11540}
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 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 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
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
CycleT * getCycle(const BlockT *Block) const
Find the innermost cycle containing a given block.
void getExitingBlocks(SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of this cycle that have successor outside of this cycle.
bool contains(const BlockT *Block) const
Return whether Block is contained in the cycle.
const GenericCycle * getParentCycle() const
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.
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
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 & 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:433
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
Definition SIDefines.h:451
@ OPERAND_REG_IMM_INT64
Definition SIDefines.h:419
@ OPERAND_REG_IMM_V2FP16
Definition SIDefines.h:426
@ OPERAND_REG_INLINE_C_FP64
Definition SIDefines.h:442
@ OPERAND_REG_INLINE_C_BF16
Definition SIDefines.h:439
@ OPERAND_REG_INLINE_C_V2BF16
Definition SIDefines.h:444
@ OPERAND_REG_IMM_V2INT64
Definition SIDefines.h:429
@ OPERAND_REG_IMM_V2INT16
Definition SIDefines.h:428
@ OPERAND_REG_IMM_BF16
Definition SIDefines.h:423
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
Definition SIDefines.h:418
@ OPERAND_REG_IMM_V2BF16
Definition SIDefines.h:425
@ OPERAND_REG_IMM_FP16
Definition SIDefines.h:424
@ OPERAND_REG_IMM_V2FP16_SPLAT
Definition SIDefines.h:427
@ OPERAND_REG_INLINE_C_INT64
Definition SIDefines.h:438
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
Definition SIDefines.h:436
@ OPERAND_REG_IMM_NOINLINE_V2FP16
Definition SIDefines.h:430
@ OPERAND_REG_IMM_FP64
Definition SIDefines.h:422
@ OPERAND_REG_INLINE_C_V2FP16
Definition SIDefines.h:445
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
Definition SIDefines.h:456
@ OPERAND_REG_INLINE_AC_FP32
Definition SIDefines.h:457
@ OPERAND_REG_IMM_V2INT32
Definition SIDefines.h:431
@ OPERAND_SDWA_VOPC_DST
Definition SIDefines.h:468
@ OPERAND_REG_IMM_FP32
Definition SIDefines.h:421
@ OPERAND_REG_INLINE_C_FP32
Definition SIDefines.h:441
@ OPERAND_REG_INLINE_C_INT32
Definition SIDefines.h:437
@ OPERAND_REG_INLINE_C_V2INT16
Definition SIDefines.h:443
@ OPERAND_INLINE_C_AV64_PSEUDO
Definition SIDefines.h:462
@ OPERAND_REG_IMM_V2FP32
Definition SIDefines.h:432
@ OPERAND_REG_INLINE_AC_FP64
Definition SIDefines.h:458
@ OPERAND_REG_INLINE_C_FP16
Definition SIDefines.h:440
@ OPERAND_REG_IMM_INT16
Definition SIDefines.h:420
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
Definition SIDefines.h:448
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)
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:333
constexpr bool isSDWA(const T &...O)
Definition SIDefines.h:243
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:573
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:207
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:165
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:546
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:284
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:45
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:331
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:150
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:189
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:155
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:53
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:394
@ 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:41
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:248
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
Definition SIInstrInfo.h:49
constexpr T reverseBits(T Val)
Reverse the bits in Val.
Definition MathExtras.h:118
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:572
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:77
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
MachineCycleInfo::CycleT MachineCycle
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
Definition SIInstrInfo.h:64
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:862
#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:68
MachineInstr * top() const
Definition SIInstrInfo.h:73
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.