LLVM 24.0.0git
AMDGPUInstructionSelector.cpp
Go to the documentation of this file.
1//===- AMDGPUInstructionSelector.cpp ----------------------------*- C++ -*-==//
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/// \file
9/// This file implements the targeting of the InstructionSelector class for
10/// AMDGPU.
11/// \todo This should be generated by TableGen.
12//===----------------------------------------------------------------------===//
13
15#include "AMDGPU.h"
17#include "AMDGPUInstrInfo.h"
19#include "AMDGPUTargetMachine.h"
29#include "llvm/IR/IntrinsicsAMDGPU.h"
30#include <optional>
31
32#define DEBUG_TYPE "amdgpu-isel"
33
34using namespace llvm;
35using namespace MIPatternMatch;
36
37#define GET_GLOBALISEL_IMPL
38#define AMDGPUSubtarget GCNSubtarget
39#include "AMDGPUGenGlobalISel.inc"
40#undef GET_GLOBALISEL_IMPL
41#undef AMDGPUSubtarget
42
44 const GCNSubtarget &STI, const AMDGPURegisterBankInfo &RBI)
45 : TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI), STI(STI),
47#include "AMDGPUGenGlobalISel.inc"
50#include "AMDGPUGenGlobalISel.inc"
52{
53}
54
55const char *AMDGPUInstructionSelector::getName() { return DEBUG_TYPE; }
56
67
68// Return the wave level SGPR base address if this is a wave address.
70 return Def->getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS
71 ? Def->getOperand(1).getReg()
72 : Register();
73}
74
75bool AMDGPUInstructionSelector::isVCC(Register Reg,
76 const MachineRegisterInfo &MRI) const {
77 // The verifier is oblivious to s1 being a valid value for wavesize registers.
78 if (Reg.isPhysical())
79 return false;
80
81 auto &RegClassOrBank = MRI.getRegClassOrRegBank(Reg);
82 const TargetRegisterClass *RC =
84 if (RC) {
85 const LLT Ty = MRI.getType(Reg);
86 if (!Ty.isValid() || Ty.getSizeInBits() != 1)
87 return false;
88 // G_TRUNC s1 result is never vcc.
89 return !mi_match(Reg, MRI, m_GTrunc(m_Reg())) &&
90 RC->hasSuperClassEq(TRI.getBoolRC());
91 }
92
93 const RegisterBank *RB = cast<const RegisterBank *>(RegClassOrBank);
94 return RB->getID() == AMDGPU::VCCRegBankID;
95}
96
97bool AMDGPUInstructionSelector::constrainCopyLikeIntrin(MachineInstr &MI,
98 unsigned NewOpc) const {
99 MI.setDesc(TII.get(NewOpc));
100 MI.removeOperand(1); // Remove intrinsic ID.
101 MI.addOperand(*MF, MachineOperand::CreateReg(AMDGPU::EXEC, false, true));
102
103 MachineOperand &Dst = MI.getOperand(0);
104 MachineOperand &Src = MI.getOperand(1);
105
106 // TODO: This should be legalized to s32 if needed
107 if (MRI->getType(Dst.getReg()) == LLT::scalar(1))
108 return false;
109
110 const TargetRegisterClass *DstRC
111 = TRI.getConstrainedRegClassForOperand(Dst, *MRI);
112 const TargetRegisterClass *SrcRC
113 = TRI.getConstrainedRegClassForOperand(Src, *MRI);
114 if (!DstRC || DstRC != SrcRC)
115 return false;
116
117 if (!RBI.constrainGenericRegister(Dst.getReg(), *DstRC, *MRI) ||
118 !RBI.constrainGenericRegister(Src.getReg(), *SrcRC, *MRI))
119 return false;
120 const MCInstrDesc &MCID = MI.getDesc();
121 if (MCID.getOperandConstraint(0, MCOI::EARLY_CLOBBER) != -1) {
122 MI.getOperand(0).setIsEarlyClobber(true);
123 }
124 return true;
125}
126
127bool AMDGPUInstructionSelector::selectCOPY(MachineInstr &I) const {
128 const DebugLoc &DL = I.getDebugLoc();
129 MachineBasicBlock *BB = I.getParent();
130 I.setDesc(TII.get(TargetOpcode::COPY));
131
132 const MachineOperand &Src = I.getOperand(1);
133 MachineOperand &Dst = I.getOperand(0);
134 Register DstReg = Dst.getReg();
135 Register SrcReg = Src.getReg();
136
137 if (isVCC(DstReg, *MRI)) {
138 if (SrcReg == AMDGPU::SCC) {
139 const TargetRegisterClass *RC
140 = TRI.getConstrainedRegClassForOperand(Dst, *MRI);
141 if (!RC)
142 return true;
143 return RBI.constrainGenericRegister(DstReg, *RC, *MRI);
144 }
145
146 if (!isVCC(SrcReg, *MRI)) {
147 // TODO: Should probably leave the copy and let copyPhysReg expand it.
148 if (!RBI.constrainGenericRegister(DstReg, *TRI.getBoolRC(), *MRI))
149 return false;
150
151 const TargetRegisterClass *SrcRC
152 = TRI.getConstrainedRegClassForOperand(Src, *MRI);
153
154 std::optional<ValueAndVReg> ConstVal =
155 getIConstantVRegValWithLookThrough(SrcReg, *MRI, true);
156 if (ConstVal) {
157 unsigned MovOpc =
158 STI.isWave64() ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
159 BuildMI(*BB, &I, DL, TII.get(MovOpc), DstReg)
160 .addImm(ConstVal->Value.getBoolValue() ? -1 : 0);
161 } else {
162 Register MaskedReg = MRI->createVirtualRegister(SrcRC);
163
164 // We can't trust the high bits at this point, so clear them.
165
166 // TODO: Skip masking high bits if def is known boolean.
167
168 if (AMDGPU::getRegBitWidth(SrcRC->getID()) == 16) {
169 assert(Subtarget->useRealTrue16Insts());
170 const int64_t NoMods = 0;
171 BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_AND_B16_t16_e64), MaskedReg)
172 .addImm(NoMods)
173 .addImm(1)
174 .addImm(NoMods)
175 .addReg(SrcReg)
176 .addImm(NoMods);
177 BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_CMP_NE_U16_t16_e64), DstReg)
178 .addImm(NoMods)
179 .addImm(0)
180 .addImm(NoMods)
181 .addReg(MaskedReg)
182 .addImm(NoMods);
183 } else {
184 bool IsSGPR = TRI.isSGPRClass(SrcRC);
185 unsigned AndOpc = IsSGPR ? AMDGPU::S_AND_B32 : AMDGPU::V_AND_B32_e32;
186 auto And = BuildMI(*BB, &I, DL, TII.get(AndOpc), MaskedReg)
187 .addImm(1)
188 .addReg(SrcReg);
189 if (IsSGPR)
190 And.setOperandDead(3); // Dead scc
191
192 BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_CMP_NE_U32_e64), DstReg)
193 .addImm(0)
194 .addReg(MaskedReg);
195 }
196 }
197
198 if (!MRI->getRegClassOrNull(SrcReg))
199 MRI->setRegClass(SrcReg, SrcRC);
200 I.eraseFromParent();
201 return true;
202 }
203
204 const TargetRegisterClass *RC =
205 TRI.getConstrainedRegClassForOperand(Dst, *MRI);
206 if (RC && !RBI.constrainGenericRegister(DstReg, *RC, *MRI))
207 return false;
208
209 return true;
210 }
211
212 for (const MachineOperand &MO : I.operands()) {
213 if (MO.getReg().isPhysical())
214 continue;
215
216 const TargetRegisterClass *RC =
217 TRI.getConstrainedRegClassForOperand(MO, *MRI);
218 if (!RC)
219 continue;
220 RBI.constrainGenericRegister(MO.getReg(), *RC, *MRI);
221 }
222 return true;
223}
224
225bool AMDGPUInstructionSelector::selectCOPY_SCC_VCC(MachineInstr &I) const {
226 const DebugLoc &DL = I.getDebugLoc();
227 MachineBasicBlock *BB = I.getParent();
228 Register VCCReg = I.getOperand(1).getReg();
229 MachineInstr *Cmp;
230
231 // Set SCC as a side effect with S_CMP or S_OR.
232 if (STI.hasScalarCompareEq64()) {
233 unsigned CmpOpc =
234 STI.isWave64() ? AMDGPU::S_CMP_LG_U64 : AMDGPU::S_CMP_LG_U32;
235 Cmp = BuildMI(*BB, &I, DL, TII.get(CmpOpc)).addReg(VCCReg).addImm(0);
236 } else {
237 Register DeadDst = MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
238 Cmp = BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_OR_B64), DeadDst)
239 .addReg(VCCReg)
240 .addReg(VCCReg);
241 }
242
243 constrainSelectedInstRegOperands(*Cmp, TII, TRI, RBI);
244
245 Register DstReg = I.getOperand(0).getReg();
246 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), DstReg).addReg(AMDGPU::SCC);
247
248 I.eraseFromParent();
249 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
250}
251
252bool AMDGPUInstructionSelector::selectCOPY_VCC_SCC(MachineInstr &I) const {
253 const DebugLoc &DL = I.getDebugLoc();
254 MachineBasicBlock *BB = I.getParent();
255
256 Register DstReg = I.getOperand(0).getReg();
257 Register SrcReg = I.getOperand(1).getReg();
258 std::optional<ValueAndVReg> Arg =
259 getIConstantVRegValWithLookThrough(I.getOperand(1).getReg(), *MRI);
260
261 if (Arg) {
262 const int64_t Value = Arg->Value.getZExtValue();
263 if (Value == 0) {
264 unsigned Opcode = STI.isWave64() ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
265 BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg).addImm(0);
266 } else {
267 assert(Value == 1);
268 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), DstReg).addReg(TRI.getExec());
269 }
270 I.eraseFromParent();
271 return RBI.constrainGenericRegister(DstReg, *TRI.getBoolRC(), *MRI);
272 }
273
274 // RegBankLegalize ensures that SrcReg is bool in reg (high bits are 0).
275 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::SCC).addReg(SrcReg);
276
277 unsigned SelectOpcode =
278 STI.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
279 MachineInstr *Select = BuildMI(*BB, &I, DL, TII.get(SelectOpcode), DstReg)
280 .addReg(TRI.getExec())
281 .addImm(0);
282
283 I.eraseFromParent();
285 return true;
286}
287
288bool AMDGPUInstructionSelector::selectReadAnyLane(MachineInstr &I) const {
289 Register DstReg = I.getOperand(0).getReg();
290 Register SrcReg = I.getOperand(1).getReg();
291
292 const DebugLoc &DL = I.getDebugLoc();
293 MachineBasicBlock *BB = I.getParent();
294
295 auto RFL = BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
296 .addReg(SrcReg);
297
298 I.eraseFromParent();
299 constrainSelectedInstRegOperands(*RFL, TII, TRI, RBI);
300 return true;
301}
302
303bool AMDGPUInstructionSelector::selectPHI(MachineInstr &I) const {
304 const Register DefReg = I.getOperand(0).getReg();
305 const LLT DefTy = MRI->getType(DefReg);
306
307 // S1 G_PHIs should not be selected in instruction-select, instead:
308 // - divergent S1 G_PHI should go through lane mask merging algorithm
309 // and be fully inst-selected in AMDGPUGlobalISelDivergenceLowering
310 // - uniform S1 G_PHI should be lowered into S32 G_PHI in AMDGPURegBankSelect
311 if (DefTy == LLT::scalar(1))
312 return false;
313
314 // TODO: Verify this doesn't have insane operands (i.e. VGPR to SGPR copy)
315
316 const RegClassOrRegBank &RegClassOrBank =
317 MRI->getRegClassOrRegBank(DefReg);
318
319 const TargetRegisterClass *DefRC =
321 if (!DefRC) {
322 if (!DefTy.isValid()) {
323 LLVM_DEBUG(dbgs() << "PHI operand has no type, not a gvreg?\n");
324 return false;
325 }
326
327 const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
328 DefRC = TRI.getRegClassForTypeOnBank(DefTy, RB);
329 if (!DefRC) {
330 LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
331 return false;
332 }
333 }
334
335 // If inputs have register bank, assign corresponding reg class.
336 // Note: registers don't need to have the same reg bank.
337 for (unsigned i = 1; i != I.getNumOperands(); i += 2) {
338 const Register SrcReg = I.getOperand(i).getReg();
339
340 const RegisterBank *RB = MRI->getRegBankOrNull(SrcReg);
341 if (RB) {
342 const LLT SrcTy = MRI->getType(SrcReg);
343 const TargetRegisterClass *SrcRC =
344 TRI.getRegClassForTypeOnBank(SrcTy, *RB);
345 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
346 return false;
347 }
348 }
349
350 I.setDesc(TII.get(TargetOpcode::PHI));
351 return RBI.constrainGenericRegister(DefReg, *DefRC, *MRI);
352}
353
355AMDGPUInstructionSelector::getSubOperand64(MachineOperand &MO,
356 const TargetRegisterClass &SubRC,
357 unsigned SubIdx) const {
358
359 MachineInstr *MI = MO.getParent();
360 MachineBasicBlock *BB = MO.getParent()->getParent();
361 Register DstReg = MRI->createVirtualRegister(&SubRC);
362
363 if (MO.isReg()) {
364 unsigned ComposedSubIdx = TRI.composeSubRegIndices(MO.getSubReg(), SubIdx);
365 Register Reg = MO.getReg();
366 BuildMI(*BB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), DstReg)
367 .addReg(Reg, {}, ComposedSubIdx);
368
369 return MachineOperand::CreateReg(DstReg, MO.isDef(), MO.isImplicit(),
370 MO.isKill(), MO.isDead(), MO.isUndef(),
371 MO.isEarlyClobber(), 0, MO.isDebug(),
372 MO.isInternalRead());
373 }
374
375 assert(MO.isImm());
376
377 APInt Imm(64, MO.getImm());
378
379 switch (SubIdx) {
380 default:
381 llvm_unreachable("do not know to split immediate with this sub index.");
382 case AMDGPU::sub0:
383 return MachineOperand::CreateImm(Imm.getLoBits(32).getSExtValue());
384 case AMDGPU::sub1:
385 return MachineOperand::CreateImm(Imm.getHiBits(32).getSExtValue());
386 }
387}
388
389static unsigned getLogicalBitOpcode(unsigned Opc, bool Is64) {
390 switch (Opc) {
391 case AMDGPU::G_AND:
392 return Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
393 case AMDGPU::G_OR:
394 return Is64 ? AMDGPU::S_OR_B64 : AMDGPU::S_OR_B32;
395 case AMDGPU::G_XOR:
396 return Is64 ? AMDGPU::S_XOR_B64 : AMDGPU::S_XOR_B32;
397 default:
398 llvm_unreachable("not a bit op");
399 }
400}
401
402bool AMDGPUInstructionSelector::selectG_AND_OR_XOR(MachineInstr &I) const {
403 Register DstReg = I.getOperand(0).getReg();
404 unsigned Size = RBI.getSizeInBits(DstReg, *MRI, TRI);
405
406 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
407 if (DstRB->getID() != AMDGPU::SGPRRegBankID &&
408 DstRB->getID() != AMDGPU::VCCRegBankID)
409 return false;
410
411 bool Is64 = Size > 32 || (DstRB->getID() == AMDGPU::VCCRegBankID &&
412 STI.isWave64());
413 I.setDesc(TII.get(getLogicalBitOpcode(I.getOpcode(), Is64)));
414
415 // Dead implicit-def of scc
416 I.addOperand(MachineOperand::CreateReg(AMDGPU::SCC, true, // isDef
417 true, // isImp
418 false, // isKill
419 true)); // isDead
420 constrainSelectedInstRegOperands(I, TII, TRI, RBI);
421 return true;
422}
423
424bool AMDGPUInstructionSelector::selectG_ADD_SUB(MachineInstr &I) const {
425 MachineBasicBlock *BB = I.getParent();
427 Register DstReg = I.getOperand(0).getReg();
428 const DebugLoc &DL = I.getDebugLoc();
429 LLT Ty = MRI->getType(DstReg);
430 if (Ty.isVector())
431 return false;
432
433 unsigned Size = Ty.getSizeInBits();
434 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
435 const bool IsSALU = DstRB->getID() == AMDGPU::SGPRRegBankID;
436 const bool Sub = I.getOpcode() == TargetOpcode::G_SUB;
437
438 if (Size == 32) {
439 if (IsSALU) {
440 const unsigned Opc = Sub ? AMDGPU::S_SUB_U32 : AMDGPU::S_ADD_U32;
441 MachineInstr *Add =
442 BuildMI(*BB, &I, DL, TII.get(Opc), DstReg)
443 .add(I.getOperand(1))
444 .add(I.getOperand(2))
445 .setOperandDead(3); // Dead scc
446 I.eraseFromParent();
447 constrainSelectedInstRegOperands(*Add, TII, TRI, RBI);
448 return true;
449 }
450
451 if (STI.hasAddNoCarryInsts()) {
452 const unsigned Opc = Sub ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_ADD_U32_e64;
453 I.setDesc(TII.get(Opc));
454 I.addOperand(*MF, MachineOperand::CreateImm(0));
455 I.addOperand(*MF, MachineOperand::CreateReg(AMDGPU::EXEC, false, true));
456 constrainSelectedInstRegOperands(I, TII, TRI, RBI);
457 return true;
458 }
459
460 const unsigned Opc = Sub ? AMDGPU::V_SUB_CO_U32_e64 : AMDGPU::V_ADD_CO_U32_e64;
461
462 Register UnusedCarry = MRI->createVirtualRegister(TRI.getWaveMaskRegClass());
463 MachineInstr *Add
464 = BuildMI(*BB, &I, DL, TII.get(Opc), DstReg)
465 .addDef(UnusedCarry, RegState::Dead)
466 .add(I.getOperand(1))
467 .add(I.getOperand(2))
468 .addImm(0);
469 I.eraseFromParent();
470 constrainSelectedInstRegOperands(*Add, TII, TRI, RBI);
471 return true;
472 }
473
474 assert(!Sub && "illegal sub should not reach here");
475
476 const TargetRegisterClass &RC
477 = IsSALU ? AMDGPU::SReg_64_XEXECRegClass : AMDGPU::VReg_64RegClass;
478 const TargetRegisterClass &HalfRC
479 = IsSALU ? AMDGPU::SReg_32RegClass : AMDGPU::VGPR_32RegClass;
480
481 MachineOperand Lo1(getSubOperand64(I.getOperand(1), HalfRC, AMDGPU::sub0));
482 MachineOperand Lo2(getSubOperand64(I.getOperand(2), HalfRC, AMDGPU::sub0));
483 MachineOperand Hi1(getSubOperand64(I.getOperand(1), HalfRC, AMDGPU::sub1));
484 MachineOperand Hi2(getSubOperand64(I.getOperand(2), HalfRC, AMDGPU::sub1));
485
486 Register DstLo = MRI->createVirtualRegister(&HalfRC);
487 Register DstHi = MRI->createVirtualRegister(&HalfRC);
488
489 if (IsSALU) {
490 BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADD_U32), DstLo)
491 .add(Lo1)
492 .add(Lo2);
493 BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADDC_U32), DstHi)
494 .add(Hi1)
495 .add(Hi2)
496 .setOperandDead(3); // Dead scc
497 } else {
498 const TargetRegisterClass *CarryRC = TRI.getWaveMaskRegClass();
499 Register CarryReg = MRI->createVirtualRegister(CarryRC);
500 BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_ADD_CO_U32_e64), DstLo)
501 .addDef(CarryReg)
502 .add(Lo1)
503 .add(Lo2)
504 .addImm(0);
505 MachineInstr *Addc = BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_ADDC_U32_e64), DstHi)
506 .addDef(MRI->createVirtualRegister(CarryRC), RegState::Dead)
507 .add(Hi1)
508 .add(Hi2)
509 .addReg(CarryReg, RegState::Kill)
510 .addImm(0);
511
512 constrainSelectedInstRegOperands(*Addc, TII, TRI, RBI);
513 }
514
515 BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
516 .addReg(DstLo)
517 .addImm(AMDGPU::sub0)
518 .addReg(DstHi)
519 .addImm(AMDGPU::sub1);
520
521
522 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
523 return false;
524
525 I.eraseFromParent();
526 return true;
527}
528
529bool AMDGPUInstructionSelector::selectG_UADDO_USUBO_UADDE_USUBE(
530 MachineInstr &I) const {
531 MachineBasicBlock *BB = I.getParent();
533 const DebugLoc &DL = I.getDebugLoc();
534 Register Dst0Reg = I.getOperand(0).getReg();
535 Register Dst1Reg = I.getOperand(1).getReg();
536 const bool IsAdd = I.getOpcode() == AMDGPU::G_UADDO ||
537 I.getOpcode() == AMDGPU::G_UADDE;
538 const bool HasCarryIn = I.getOpcode() == AMDGPU::G_UADDE ||
539 I.getOpcode() == AMDGPU::G_USUBE;
540
541 if (isVCC(Dst1Reg, *MRI)) {
542 unsigned NoCarryOpc =
543 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
544 unsigned CarryOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
545 I.setDesc(TII.get(HasCarryIn ? CarryOpc : NoCarryOpc));
546 I.addOperand(*MF, MachineOperand::CreateReg(AMDGPU::EXEC, false, true));
547 I.addOperand(*MF, MachineOperand::CreateImm(0));
548 constrainSelectedInstRegOperands(I, TII, TRI, RBI);
549 return true;
550 }
551
552 Register Src0Reg = I.getOperand(2).getReg();
553 Register Src1Reg = I.getOperand(3).getReg();
554
555 if (HasCarryIn) {
556 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
557 .addReg(I.getOperand(4).getReg());
558 }
559
560 unsigned NoCarryOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
561 unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
562
563 auto CarryInst = BuildMI(*BB, &I, DL, TII.get(HasCarryIn ? CarryOpc : NoCarryOpc), Dst0Reg)
564 .add(I.getOperand(2))
565 .add(I.getOperand(3));
566
567 if (MRI->use_nodbg_empty(Dst1Reg)) {
568 CarryInst.setOperandDead(3); // Dead scc
569 } else {
570 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), Dst1Reg)
571 .addReg(AMDGPU::SCC);
572 if (!MRI->getRegClassOrNull(Dst1Reg))
573 MRI->setRegClass(Dst1Reg, &AMDGPU::SReg_32RegClass);
574 }
575
576 if (!RBI.constrainGenericRegister(Dst0Reg, AMDGPU::SReg_32RegClass, *MRI) ||
577 !RBI.constrainGenericRegister(Src0Reg, AMDGPU::SReg_32RegClass, *MRI) ||
578 !RBI.constrainGenericRegister(Src1Reg, AMDGPU::SReg_32RegClass, *MRI))
579 return false;
580
581 if (HasCarryIn &&
582 !RBI.constrainGenericRegister(I.getOperand(4).getReg(),
583 AMDGPU::SReg_32RegClass, *MRI))
584 return false;
585
586 I.eraseFromParent();
587 return true;
588}
589
590bool AMDGPUInstructionSelector::selectG_AMDGPU_MAD_64_32(
591 MachineInstr &I) const {
592 MachineBasicBlock *BB = I.getParent();
594 const bool IsUnsigned = I.getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32;
595 bool UseNoCarry = Subtarget->hasMadNC64_32Insts() &&
596 MRI->use_nodbg_empty(I.getOperand(1).getReg());
597
598 unsigned Opc;
599 if (Subtarget->hasMADIntraFwdBug())
600 Opc = IsUnsigned ? AMDGPU::V_MAD_U64_U32_gfx11_e64
601 : AMDGPU::V_MAD_I64_I32_gfx11_e64;
602 else if (UseNoCarry)
603 Opc = IsUnsigned ? AMDGPU::V_MAD_NC_U64_U32_e64
604 : AMDGPU::V_MAD_NC_I64_I32_e64;
605 else
606 Opc = IsUnsigned ? AMDGPU::V_MAD_U64_U32_e64 : AMDGPU::V_MAD_I64_I32_e64;
607
608 if (UseNoCarry)
609 I.removeOperand(1);
610
611 I.setDesc(TII.get(Opc));
612 I.addOperand(*MF, MachineOperand::CreateImm(0));
613 I.addImplicitDefUseOperands(*MF);
614 I.getOperand(0).setIsEarlyClobber(true);
615 constrainSelectedInstRegOperands(I, TII, TRI, RBI);
616 return true;
617}
618
619// TODO: We should probably legalize these to only using 32-bit results.
620bool AMDGPUInstructionSelector::selectG_EXTRACT(MachineInstr &I) const {
621 MachineBasicBlock *BB = I.getParent();
622 Register DstReg = I.getOperand(0).getReg();
623 Register SrcReg = I.getOperand(1).getReg();
624 LLT DstTy = MRI->getType(DstReg);
625 LLT SrcTy = MRI->getType(SrcReg);
626 const unsigned SrcSize = SrcTy.getSizeInBits();
627 unsigned DstSize = DstTy.getSizeInBits();
628
629 // TODO: Should handle any multiple of 32 offset.
630 unsigned Offset = I.getOperand(2).getImm();
631 if (Offset % 32 != 0 || DstSize > 128)
632 return false;
633
634 // 16-bit operations really use 32-bit registers.
635 // FIXME: Probably should not allow 16-bit G_EXTRACT results.
636 if (DstSize == 16)
637 DstSize = 32;
638
639 const TargetRegisterClass *DstRC =
640 TRI.getConstrainedRegClassForOperand(I.getOperand(0), *MRI);
641 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
642 return false;
643
644 const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, *MRI, TRI);
645 const TargetRegisterClass *SrcRC =
646 TRI.getRegClassForSizeOnBank(SrcSize, *SrcBank);
647 if (!SrcRC)
648 return false;
649 unsigned SubReg = SIRegisterInfo::getSubRegFromChannel(Offset / 32,
650 DstSize / 32);
651 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubReg);
652 if (!SrcRC)
653 return false;
654
655 SrcReg = constrainOperandRegClass(*MF, TRI, *MRI, TII, RBI, I,
656 *SrcRC, I.getOperand(1));
657 const DebugLoc &DL = I.getDebugLoc();
658 BuildMI(*BB, &I, DL, TII.get(TargetOpcode::COPY), DstReg)
659 .addReg(SrcReg, {}, SubReg);
660
661 I.eraseFromParent();
662 return true;
663}
664
665bool AMDGPUInstructionSelector::selectS16MergeToS32(MachineInstr &MI) const {
666 Register Dst = MI.getOperand(0).getReg();
667 Register Src0 = MI.getOperand(1).getReg();
668 Register Src1 = MI.getOperand(2).getReg();
669
670 LLT Src0Ty = MRI->getType(Src0);
671 LLT Src1Ty = MRI->getType(Src1);
672
673 const RegisterBank *DstBank = RBI.getRegBank(Dst, *MRI, TRI);
674 const RegisterBank *Src0Bank = RBI.getRegBank(Src0, *MRI, TRI);
675 const RegisterBank *Src1Bank = RBI.getRegBank(Src1, *MRI, TRI);
676 const bool IsVector = DstBank->getID() == AMDGPU::VGPRRegBankID;
677
678 Register ShiftSrc0;
679 Register ShiftSrc1;
680
681 const DebugLoc &DL = MI.getDebugLoc();
682 MachineBasicBlock *BB = MI.getParent();
683
684 // VGPR case
685 if (IsVector) {
686 // If source are both VGPR16, use REG_SEQUENCE with lo16/hi16 subregisters
687 if (Src0Bank->getID() == AMDGPU::VGPRRegBankID &&
688 Src1Bank->getID() == AMDGPU::VGPRRegBankID &&
689 Src0Ty == LLT::scalar(16) && Src1Ty == LLT::scalar(16)) {
690 BuildMI(*BB, MI, DL, TII.get(TargetOpcode::REG_SEQUENCE), Dst)
691 .addReg(Src0)
692 .addImm(AMDGPU::lo16)
693 .addReg(Src1)
694 .addImm(AMDGPU::hi16);
695
696 if (!RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI))
697 return false;
698
699 MI.eraseFromParent();
700 return true;
701 }
702
703 // Otherwise, use V_LSHL_OR_B32_e64
704 Register TmpReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
705 auto MIB = BuildMI(*BB, MI, DL, TII.get(AMDGPU::V_AND_B32_e32), TmpReg)
706 .addImm(0xFFFF)
707 .addReg(Src0);
708 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
709
710 MIB = BuildMI(*BB, MI, DL, TII.get(AMDGPU::V_LSHL_OR_B32_e64), Dst)
711 .addReg(Src1)
712 .addImm(16)
713 .addReg(TmpReg);
714 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
715
716 MI.eraseFromParent();
717 return true;
718 }
719
720 // SGPR case -> S_PACK_*_B32_B16
721 // With multiple uses of the shift, this will duplicate the shift and
722 // increase register pressure.
723 //
724 // (merge (lshr_oneuse $src0, 16), (lshr_oneuse $src1, 16)
725 // => (S_PACK_HH_B32_B16 $src0, $src1)
726 // (merge (lshr_oneuse SReg_32:$src0, 16), $src1)
727 // => (S_PACK_HL_B32_B16 $src0, $src1)
728 // (merge $src0, (lshr_oneuse SReg_32:$src1, 16))
729 // => (S_PACK_LH_B32_B16 $src0, $src1)
730 // (merge $src0, $src1)
731 // => (S_PACK_LL_B32_B16 $src0, $src1)
732
733 bool Shift0 = mi_match(
734 Src0, *MRI, m_OneUse(m_GLShr(m_Reg(ShiftSrc0), m_SpecificICst(16))));
735
736 bool Shift1 = mi_match(
737 Src1, *MRI, m_OneUse(m_GLShr(m_Reg(ShiftSrc1), m_SpecificICst(16))));
738
739 unsigned Opc = AMDGPU::S_PACK_LL_B32_B16;
740 if (Shift0 && Shift1) {
741 Opc = AMDGPU::S_PACK_HH_B32_B16;
742 MI.getOperand(1).setReg(ShiftSrc0);
743 MI.getOperand(2).setReg(ShiftSrc1);
744 } else if (Shift1) {
745 Opc = AMDGPU::S_PACK_LH_B32_B16;
746 MI.getOperand(2).setReg(ShiftSrc1);
747 } else if (Shift0) {
748 auto ConstSrc1 =
749 getAnyConstantVRegValWithLookThrough(Src1, *MRI, true, true);
750 if (ConstSrc1 && ConstSrc1->Value == 0) {
751 // build_vector_trunc (lshr $src0, 16), 0 -> s_lshr_b32 $src0, 16
752 auto MIB = BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_LSHR_B32), Dst)
753 .addReg(ShiftSrc0)
754 .addImm(16)
755 .setOperandDead(3); // Dead scc
756
757 MI.eraseFromParent();
758 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
759 return true;
760 }
761 if (STI.hasSPackHL()) {
762 Opc = AMDGPU::S_PACK_HL_B32_B16;
763 MI.getOperand(1).setReg(ShiftSrc0);
764 }
765 }
766
767 MI.setDesc(TII.get(Opc));
768 constrainSelectedInstRegOperands(MI, TII, TRI, RBI);
769 return true;
770}
771
772// Pack each pair of s16 into an s32 with S_PACK_LL_B32_B16, then combine the
773// s32 pieces into the destination with a REG_SEQUENCE.
774bool AMDGPUInstructionSelector::selectS16MergeToWide(MachineInstr &MI) const {
775 MachineBasicBlock *BB = MI.getParent();
776 const DebugLoc &DL = MI.getDebugLoc();
777 Register DstReg = MI.getOperand(0).getReg();
778 const unsigned DstSize = MRI->getType(DstReg).getSizeInBits();
779 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
780 const unsigned NumSrc = MI.getNumOperands() - 1;
781
782 // Pack each pair of s16 sources into an s32.
784 for (unsigned I = 0; I != NumSrc; I += 2) {
785 Register S32 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
786 auto Pack = BuildMI(*BB, MI, DL, TII.get(AMDGPU::S_PACK_LL_B32_B16), S32)
787 .addReg(MI.getOperand(I + 1).getReg())
788 .addReg(MI.getOperand(I + 2).getReg());
789 constrainSelectedInstRegOperands(*Pack, TII, TRI, RBI);
790 S32Regs.push_back(S32);
791 }
792
793 // Combine the s32 pieces into the destination with a REG_SEQUENCE.
794 const TargetRegisterClass *DstRC =
795 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
796 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
797 return false;
798 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(DstRC, /*EltSize=*/4);
799 auto MIB = BuildMI(*BB, MI, DL, TII.get(TargetOpcode::REG_SEQUENCE), DstReg);
800 for (unsigned I = 0, E = S32Regs.size(); I != E; ++I)
801 MIB.addReg(S32Regs[I]).addImm(SubRegs[I]);
802
803 MI.eraseFromParent();
804 return true;
805}
806
807bool AMDGPUInstructionSelector::selectG_MERGE_VALUES(MachineInstr &MI) const {
808 MachineBasicBlock *BB = MI.getParent();
809 Register DstReg = MI.getOperand(0).getReg();
810 LLT DstTy = MRI->getType(DstReg);
811 LLT SrcTy = MRI->getType(MI.getOperand(1).getReg());
812
813 const unsigned SrcSize = SrcTy.getSizeInBits();
814 if (SrcSize < 32) {
815 // Handle s32 <- G_MERGE_VALUES s16, s16
816 if (SrcSize == 16 && DstTy.getSizeInBits() == 32 &&
817 MI.getNumOperands() == 3) {
818 return selectS16MergeToS32(MI);
819 }
820 // With true16 a scalar s16 is a register type, so a scalar wider than 32
821 // bits can be built from s16 pieces.
822 bool IsWideS16Merge = SrcSize == 16 && DstTy.getSizeInBits() > 32 &&
823 DstTy.getSizeInBits() % 32 == 0;
824
825 // SGPRs have no 16-bit subregisters, so pack pairs of s16 with S_PACK.
826 if (IsWideS16Merge &&
827 RBI.getRegBank(DstReg, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
828 return selectS16MergeToWide(MI);
829
830 // A VGPR wide s16 merge falls through to the generic path below.
831 if (!IsWideS16Merge)
832 return selectImpl(MI, *CoverageInfo);
833 }
834
835 const DebugLoc &DL = MI.getDebugLoc();
836 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
837 const unsigned DstSize = DstTy.getSizeInBits();
838 const TargetRegisterClass *DstRC =
839 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
840 if (!DstRC)
841 return false;
842
843 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(DstRC, SrcSize / 8);
844 MachineInstrBuilder MIB =
845 BuildMI(*BB, &MI, DL, TII.get(TargetOpcode::REG_SEQUENCE), DstReg);
846 for (int I = 0, E = MI.getNumOperands() - 1; I != E; ++I) {
847 MachineOperand &Src = MI.getOperand(I + 1);
848 MIB.addReg(Src.getReg(), getUndefRegState(Src.isUndef()));
849 MIB.addImm(SubRegs[I]);
850
851 const TargetRegisterClass *SrcRC
852 = TRI.getConstrainedRegClassForOperand(Src, *MRI);
853 if (SrcRC && !RBI.constrainGenericRegister(Src.getReg(), *SrcRC, *MRI))
854 return false;
855 }
856
857 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
858 return false;
859
860 MI.eraseFromParent();
861 return true;
862}
863
864bool AMDGPUInstructionSelector::selectG_UNMERGE_VALUES(MachineInstr &MI) const {
865 MachineBasicBlock *BB = MI.getParent();
866 const int NumDst = MI.getNumOperands() - 1;
867
868 MachineOperand &Src = MI.getOperand(NumDst);
869
870 Register SrcReg = Src.getReg();
871 Register DstReg0 = MI.getOperand(0).getReg();
872 LLT DstTy = MRI->getType(DstReg0);
873 LLT SrcTy = MRI->getType(SrcReg);
874
875 const unsigned DstSize = DstTy.getSizeInBits();
876 const unsigned SrcSize = SrcTy.getSizeInBits();
877 const DebugLoc &DL = MI.getDebugLoc();
878 const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, *MRI, TRI);
879
880 const TargetRegisterClass *SrcRC =
881 TRI.getRegClassForSizeOnBank(SrcSize, *SrcBank);
882 if (!SrcRC || !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
883 return false;
884
885 // Note we could have mixed SGPR and VGPR destination banks for an SGPR
886 // source, and this relies on the fact that the same subregister indices are
887 // used for both.
888 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(SrcRC, DstSize / 8);
889 for (int I = 0, E = NumDst; I != E; ++I) {
890 MachineOperand &Dst = MI.getOperand(I);
891 // hi16:sreg_32 is not allowed so explicitly shift upper 16-bits.
892 if (SrcBank->getID() == AMDGPU::SGPRRegBankID &&
893 SubRegs[I] == AMDGPU::hi16) {
894 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_LSHR_B32), Dst.getReg())
895 .addReg(SrcReg)
896 .addImm(16);
897 } else {
898 BuildMI(*BB, &MI, DL, TII.get(TargetOpcode::COPY), Dst.getReg())
899 .addReg(SrcReg, {}, SubRegs[I]);
900 }
901
902 // Make sure the subregister index is valid for the source register.
903 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubRegs[I]);
904 if (!SrcRC || !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
905 return false;
906
907 const TargetRegisterClass *DstRC =
908 TRI.getConstrainedRegClassForOperand(Dst, *MRI);
909 if (DstRC && !RBI.constrainGenericRegister(Dst.getReg(), *DstRC, *MRI))
910 return false;
911 }
912
913 MI.eraseFromParent();
914 return true;
915}
916
917bool AMDGPUInstructionSelector::selectG_BUILD_VECTOR(MachineInstr &MI) const {
918 assert(MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC ||
919 MI.getOpcode() == AMDGPU::G_BUILD_VECTOR);
920
921 Register Src0 = MI.getOperand(1).getReg();
922 Register Src1 = MI.getOperand(2).getReg();
923 LLT SrcTy = MRI->getType(Src0);
924 const unsigned SrcSize = SrcTy.getSizeInBits();
925
926 // BUILD_VECTOR with >=32 bits source is handled by MERGE_VALUE.
927 if (MI.getOpcode() == AMDGPU::G_BUILD_VECTOR && SrcSize >= 32) {
928 return selectG_MERGE_VALUES(MI);
929 }
930
931 // Selection logic below is for V2S16 only.
932 // For G_BUILD_VECTOR_TRUNC, additionally check that the operands are s32.
933 Register Dst = MI.getOperand(0).getReg();
934 if (MRI->getType(Dst) != LLT::fixed_vector(2, 16) ||
935 (MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC &&
936 SrcTy != LLT::scalar(32)))
937 return selectImpl(MI, *CoverageInfo);
938
939 const RegisterBank *DstBank = RBI.getRegBank(Dst, *MRI, TRI);
940 if (DstBank->getID() == AMDGPU::AGPRRegBankID)
941 return false;
942
943 assert(DstBank->getID() == AMDGPU::SGPRRegBankID ||
944 DstBank->getID() == AMDGPU::VGPRRegBankID);
945 const bool IsVector = DstBank->getID() == AMDGPU::VGPRRegBankID;
946
947 const DebugLoc &DL = MI.getDebugLoc();
948 MachineBasicBlock *BB = MI.getParent();
949
950 // First, before trying TableGen patterns, check if both sources are
951 // constants. In those cases, we can trivially compute the final constant
952 // and emit a simple move.
953 auto ConstSrc1 = getAnyConstantVRegValWithLookThrough(Src1, *MRI, true, true);
954 if (ConstSrc1) {
955 auto ConstSrc0 =
956 getAnyConstantVRegValWithLookThrough(Src0, *MRI, true, true);
957 if (ConstSrc0) {
958 const int64_t K0 = ConstSrc0->Value.getSExtValue();
959 const int64_t K1 = ConstSrc1->Value.getSExtValue();
960 uint32_t Lo16 = static_cast<uint32_t>(K0) & 0xffff;
961 uint32_t Hi16 = static_cast<uint32_t>(K1) & 0xffff;
962 uint32_t Imm = Lo16 | (Hi16 << 16);
963
964 // VALU
965 if (IsVector) {
966 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::V_MOV_B32_e32), Dst).addImm(Imm);
967 MI.eraseFromParent();
968 return RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI);
969 }
970
971 // SALU
972 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_MOV_B32), Dst).addImm(Imm);
973 MI.eraseFromParent();
974 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
975 }
976 }
977
978 // Now try TableGen patterns.
979 if (selectImpl(MI, *CoverageInfo))
980 return true;
981
982 // TODO: This should probably be a combine somewhere
983 // (build_vector $src0, undef) -> copy $src0
984 MachineInstr *Src1Def = getDefIgnoringCopies(Src1, *MRI);
985 if (Src1Def->getOpcode() == AMDGPU::G_IMPLICIT_DEF) {
986 MI.setDesc(TII.get(AMDGPU::COPY));
987 MI.removeOperand(2);
988 const auto &RC =
989 IsVector ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
990 return RBI.constrainGenericRegister(Dst, RC, *MRI) &&
991 RBI.constrainGenericRegister(Src0, RC, *MRI);
992 }
993
994 return selectS16MergeToS32(MI);
995}
996
997bool AMDGPUInstructionSelector::selectG_IMPLICIT_DEF(MachineInstr &I) const {
998 const MachineOperand &MO = I.getOperand(0);
999
1000 // FIXME: Interface for getConstrainedRegClassForOperand needs work. The
1001 // regbank check here is to know why getConstrainedRegClassForOperand failed.
1002 const TargetRegisterClass *RC = TRI.getConstrainedRegClassForOperand(MO, *MRI);
1003 if ((!RC && !MRI->getRegBankOrNull(MO.getReg())) ||
1004 (RC && RBI.constrainGenericRegister(MO.getReg(), *RC, *MRI))) {
1005 I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
1006 return true;
1007 }
1008
1009 return false;
1010}
1011
1012bool AMDGPUInstructionSelector::selectG_INSERT(MachineInstr &I) const {
1013 MachineBasicBlock *BB = I.getParent();
1014
1015 Register DstReg = I.getOperand(0).getReg();
1016 Register Src0Reg = I.getOperand(1).getReg();
1017 Register Src1Reg = I.getOperand(2).getReg();
1018 LLT Src1Ty = MRI->getType(Src1Reg);
1019
1020 unsigned DstSize = MRI->getType(DstReg).getSizeInBits();
1021 unsigned InsSize = Src1Ty.getSizeInBits();
1022
1023 int64_t Offset = I.getOperand(3).getImm();
1024
1025 // FIXME: These cases should have been illegal and unnecessary to check here.
1026 if (Offset % 32 != 0 || InsSize % 32 != 0)
1027 return false;
1028
1029 // Currently not handled by getSubRegFromChannel.
1030 if (InsSize > 128)
1031 return false;
1032
1033 unsigned SubReg = TRI.getSubRegFromChannel(Offset / 32, InsSize / 32);
1034 if (SubReg == AMDGPU::NoSubRegister)
1035 return false;
1036
1037 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
1038 const TargetRegisterClass *DstRC =
1039 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
1040 if (!DstRC)
1041 return false;
1042
1043 const RegisterBank *Src0Bank = RBI.getRegBank(Src0Reg, *MRI, TRI);
1044 const RegisterBank *Src1Bank = RBI.getRegBank(Src1Reg, *MRI, TRI);
1045 const TargetRegisterClass *Src0RC =
1046 TRI.getRegClassForSizeOnBank(DstSize, *Src0Bank);
1047 const TargetRegisterClass *Src1RC =
1048 TRI.getRegClassForSizeOnBank(InsSize, *Src1Bank);
1049
1050 // Deal with weird cases where the class only partially supports the subreg
1051 // index.
1052 Src0RC = TRI.getSubClassWithSubReg(Src0RC, SubReg);
1053 if (!Src0RC || !Src1RC)
1054 return false;
1055
1056 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
1057 !RBI.constrainGenericRegister(Src0Reg, *Src0RC, *MRI) ||
1058 !RBI.constrainGenericRegister(Src1Reg, *Src1RC, *MRI))
1059 return false;
1060
1061 const DebugLoc &DL = I.getDebugLoc();
1062 BuildMI(*BB, &I, DL, TII.get(TargetOpcode::INSERT_SUBREG), DstReg)
1063 .addReg(Src0Reg)
1064 .addReg(Src1Reg)
1065 .addImm(SubReg);
1066
1067 I.eraseFromParent();
1068 return true;
1069}
1070
1071bool AMDGPUInstructionSelector::selectG_SBFX_UBFX(MachineInstr &MI) const {
1072 Register DstReg = MI.getOperand(0).getReg();
1073 Register SrcReg = MI.getOperand(1).getReg();
1074 Register OffsetReg = MI.getOperand(2).getReg();
1075 Register WidthReg = MI.getOperand(3).getReg();
1076
1077 assert(RBI.getRegBank(DstReg, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID &&
1078 "scalar BFX instructions are expanded in regbankselect");
1079 assert(MRI->getType(MI.getOperand(0).getReg()).getSizeInBits() == 32 &&
1080 "64-bit vector BFX instructions are expanded in regbankselect");
1081
1082 const DebugLoc &DL = MI.getDebugLoc();
1083 MachineBasicBlock *MBB = MI.getParent();
1084
1085 bool IsSigned = MI.getOpcode() == TargetOpcode::G_SBFX;
1086 unsigned Opc = IsSigned ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
1087 auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc), DstReg)
1088 .addReg(SrcReg)
1089 .addReg(OffsetReg)
1090 .addReg(WidthReg);
1091 MI.eraseFromParent();
1092 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
1093 return true;
1094}
1095
1096bool AMDGPUInstructionSelector::selectInterpP1F16(MachineInstr &MI) const {
1097 if (STI.getLDSBankCount() != 16)
1098 return selectImpl(MI, *CoverageInfo);
1099
1100 Register Dst = MI.getOperand(0).getReg();
1101 Register Src0 = MI.getOperand(2).getReg();
1102 Register M0Val = MI.getOperand(6).getReg();
1103 if (!RBI.constrainGenericRegister(M0Val, AMDGPU::SReg_32RegClass, *MRI) ||
1104 !RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI) ||
1105 !RBI.constrainGenericRegister(Src0, AMDGPU::VGPR_32RegClass, *MRI))
1106 return false;
1107
1108 // This requires 2 instructions. It is possible to write a pattern to support
1109 // this, but the generated isel emitter doesn't correctly deal with multiple
1110 // output instructions using the same physical register input. The copy to m0
1111 // is incorrectly placed before the second instruction.
1112 //
1113 // TODO: Match source modifiers.
1114
1115 Register InterpMov = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
1116 const DebugLoc &DL = MI.getDebugLoc();
1117 MachineBasicBlock *MBB = MI.getParent();
1118
1119 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
1120 .addReg(M0Val);
1121 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::V_INTERP_MOV_F32), InterpMov)
1122 .addImm(2)
1123 .addImm(MI.getOperand(4).getImm()) // $attr
1124 .addImm(MI.getOperand(3).getImm()); // $attrchan
1125
1126 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::V_INTERP_P1LV_F16), Dst)
1127 .addImm(0) // $src0_modifiers
1128 .addReg(Src0) // $src0
1129 .addImm(MI.getOperand(4).getImm()) // $attr
1130 .addImm(MI.getOperand(3).getImm()) // $attrchan
1131 .addImm(0) // $src2_modifiers
1132 .addReg(InterpMov) // $src2 - 2 f16 values selected by high
1133 .addImm(MI.getOperand(5).getImm()) // $high
1134 .addImm(0) // $clamp
1135 .addImm(0); // $omod
1136
1137 MI.eraseFromParent();
1138 return true;
1139}
1140
1141// Writelane is special in that it can use SGPR and M0 (which would normally
1142// count as using the constant bus twice - but in this case it is allowed since
1143// the lane selector doesn't count as a use of the constant bus). However, it is
1144// still required to abide by the 1 SGPR rule. Fix this up if we might have
1145// multiple SGPRs.
1146bool AMDGPUInstructionSelector::selectWritelane(MachineInstr &MI) const {
1147 // With a constant bus limit of at least 2, there's no issue.
1148 if (STI.getConstantBusLimit(AMDGPU::V_WRITELANE_B32) > 1)
1149 return selectImpl(MI, *CoverageInfo);
1150
1151 MachineBasicBlock *MBB = MI.getParent();
1152 const DebugLoc &DL = MI.getDebugLoc();
1153 Register VDst = MI.getOperand(0).getReg();
1154 Register Val = MI.getOperand(2).getReg();
1155 Register LaneSelect = MI.getOperand(3).getReg();
1156 Register VDstIn = MI.getOperand(4).getReg();
1157
1158 auto MIB = BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::V_WRITELANE_B32), VDst);
1159
1160 std::optional<ValueAndVReg> ConstSelect =
1161 getIConstantVRegValWithLookThrough(LaneSelect, *MRI);
1162 if (ConstSelect) {
1163 // The selector has to be an inline immediate, so we can use whatever for
1164 // the other operands.
1165 MIB.addReg(Val);
1166 MIB.addImm(ConstSelect->Value.getSExtValue() &
1167 maskTrailingOnes<uint64_t>(STI.getWavefrontSizeLog2()));
1168 } else {
1169 std::optional<ValueAndVReg> ConstVal =
1171
1172 // If the value written is an inline immediate, we can get away without a
1173 // copy to m0.
1174 if (ConstVal && AMDGPU::isInlinableLiteral32(ConstVal->Value.getSExtValue(),
1175 STI.hasInv2PiInlineImm())) {
1176 MIB.addImm(ConstVal->Value.getSExtValue());
1177 MIB.addReg(LaneSelect);
1178 } else {
1179 MIB.addReg(Val);
1180
1181 // If the lane selector was originally in a VGPR and copied with
1182 // readfirstlane, there's a hazard to read the same SGPR from the
1183 // VALU. Constrain to a different SGPR to help avoid needing a nop later.
1184 RBI.constrainGenericRegister(LaneSelect, AMDGPU::SReg_32_XM0RegClass, *MRI);
1185
1186 BuildMI(*MBB, *MIB, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
1187 .addReg(LaneSelect);
1188 MIB.addReg(AMDGPU::M0);
1189 }
1190 }
1191
1192 MIB.addReg(VDstIn);
1193
1194 MI.eraseFromParent();
1195 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
1196 return true;
1197}
1198
1199// We need to handle this here because tablegen doesn't support matching
1200// instructions with multiple outputs.
1201bool AMDGPUInstructionSelector::selectDivScale(MachineInstr &MI) const {
1202 Register Dst0 = MI.getOperand(0).getReg();
1203 Register Dst1 = MI.getOperand(1).getReg();
1204
1205 LLT Ty = MRI->getType(Dst0);
1206 unsigned Opc;
1207 if (Ty == LLT::scalar(32))
1208 Opc = AMDGPU::V_DIV_SCALE_F32_e64;
1209 else if (Ty == LLT::scalar(64))
1210 Opc = AMDGPU::V_DIV_SCALE_F64_e64;
1211 else
1212 return false;
1213
1214 // TODO: Match source modifiers.
1215
1216 const DebugLoc &DL = MI.getDebugLoc();
1217 MachineBasicBlock *MBB = MI.getParent();
1218
1219 Register Numer = MI.getOperand(3).getReg();
1220 Register Denom = MI.getOperand(4).getReg();
1221 unsigned ChooseDenom = MI.getOperand(5).getImm();
1222
1223 Register Src0 = ChooseDenom != 0 ? Numer : Denom;
1224
1225 auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc), Dst0)
1226 .addDef(Dst1)
1227 .addImm(0) // $src0_modifiers
1228 .addUse(Src0) // $src0
1229 .addImm(0) // $src1_modifiers
1230 .addUse(Denom) // $src1
1231 .addImm(0) // $src2_modifiers
1232 .addUse(Numer) // $src2
1233 .addImm(0) // $clamp
1234 .addImm(0); // $omod
1235
1236 MI.eraseFromParent();
1237 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
1238 return true;
1239}
1240
1241bool AMDGPUInstructionSelector::selectG_INTRINSIC(MachineInstr &I) const {
1242 Intrinsic::ID IntrinsicID = cast<GIntrinsic>(I).getIntrinsicID();
1243 switch (IntrinsicID) {
1244 case Intrinsic::amdgcn_if_break: {
1245 MachineBasicBlock *BB = I.getParent();
1246
1247 // FIXME: Manually selecting to avoid dealing with the SReg_1 trick
1248 // SelectionDAG uses for wave32 vs wave64.
1249 BuildMI(*BB, &I, I.getDebugLoc(), TII.get(AMDGPU::SI_IF_BREAK))
1250 .add(I.getOperand(0))
1251 .add(I.getOperand(2))
1252 .add(I.getOperand(3));
1253
1254 Register DstReg = I.getOperand(0).getReg();
1255 Register Src0Reg = I.getOperand(2).getReg();
1256 Register Src1Reg = I.getOperand(3).getReg();
1257
1258 I.eraseFromParent();
1259
1260 for (Register Reg : { DstReg, Src0Reg, Src1Reg })
1261 MRI->setRegClass(Reg, TRI.getWaveMaskRegClass());
1262
1263 return true;
1264 }
1265 case Intrinsic::amdgcn_interp_p1_f16:
1266 return selectInterpP1F16(I);
1267 case Intrinsic::amdgcn_wqm:
1268 return constrainCopyLikeIntrin(I, AMDGPU::WQM);
1269 case Intrinsic::amdgcn_softwqm:
1270 return constrainCopyLikeIntrin(I, AMDGPU::SOFT_WQM);
1271 case Intrinsic::amdgcn_strict_wwm:
1272 case Intrinsic::amdgcn_wwm:
1273 return constrainCopyLikeIntrin(I, AMDGPU::STRICT_WWM);
1274 case Intrinsic::amdgcn_strict_wqm:
1275 return constrainCopyLikeIntrin(I, AMDGPU::STRICT_WQM);
1276 case Intrinsic::amdgcn_writelane:
1277 return selectWritelane(I);
1278 case Intrinsic::amdgcn_div_scale:
1279 return selectDivScale(I);
1280 case Intrinsic::amdgcn_icmp:
1281 case Intrinsic::amdgcn_fcmp:
1282 if (selectImpl(I, *CoverageInfo))
1283 return true;
1284 return selectIntrinsicCmp(I);
1285 case Intrinsic::amdgcn_ballot:
1286 return selectBallot(I);
1287 case Intrinsic::amdgcn_reloc_constant:
1288 return selectRelocConstant(I);
1289 case Intrinsic::amdgcn_groupstaticsize:
1290 return selectGroupStaticSize(I);
1291 case Intrinsic::returnaddress:
1292 return selectReturnAddress(I);
1293 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
1294 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
1295 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
1296 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
1297 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
1298 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
1299 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
1300 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
1301 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
1302 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
1303 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
1304 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
1305 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
1306 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
1307 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
1308 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
1309 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
1310 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
1311 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
1312 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
1313 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
1314 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
1315 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
1316 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
1317 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
1318 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
1319 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
1320 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
1321 return selectSMFMACIntrin(I);
1322 case Intrinsic::amdgcn_permlane16_swap:
1323 case Intrinsic::amdgcn_permlane32_swap:
1324 return selectPermlaneSwapIntrin(I, IntrinsicID);
1325 case Intrinsic::amdgcn_wave_shuffle:
1326 return selectWaveShuffleIntrin(I);
1327 default:
1328 return selectImpl(I, *CoverageInfo);
1329 }
1330}
1331
1333 const GCNSubtarget &ST) {
1334 if (Size != 16 && Size != 32 && Size != 64)
1335 return -1;
1336
1337 if (Size == 16 && !ST.has16BitInsts())
1338 return -1;
1339
1340 const auto Select = [&](unsigned S16Opc, unsigned TrueS16Opc,
1341 unsigned FakeS16Opc, unsigned S32Opc,
1342 unsigned S64Opc) {
1343 if (Size == 16)
1344 return ST.hasTrue16BitInsts()
1345 ? ST.useRealTrue16Insts() ? TrueS16Opc : FakeS16Opc
1346 : S16Opc;
1347 if (Size == 32)
1348 return S32Opc;
1349 return S64Opc;
1350 };
1351
1352 switch (P) {
1353 default:
1354 llvm_unreachable("Unknown condition code!");
1355 case CmpInst::ICMP_NE:
1356 return Select(AMDGPU::V_CMP_NE_U16_e64, AMDGPU::V_CMP_NE_U16_t16_e64,
1357 AMDGPU::V_CMP_NE_U16_fake16_e64, AMDGPU::V_CMP_NE_U32_e64,
1358 AMDGPU::V_CMP_NE_U64_e64);
1359 case CmpInst::ICMP_EQ:
1360 return Select(AMDGPU::V_CMP_EQ_U16_e64, AMDGPU::V_CMP_EQ_U16_t16_e64,
1361 AMDGPU::V_CMP_EQ_U16_fake16_e64, AMDGPU::V_CMP_EQ_U32_e64,
1362 AMDGPU::V_CMP_EQ_U64_e64);
1363 case CmpInst::ICMP_SGT:
1364 return Select(AMDGPU::V_CMP_GT_I16_e64, AMDGPU::V_CMP_GT_I16_t16_e64,
1365 AMDGPU::V_CMP_GT_I16_fake16_e64, AMDGPU::V_CMP_GT_I32_e64,
1366 AMDGPU::V_CMP_GT_I64_e64);
1367 case CmpInst::ICMP_SGE:
1368 return Select(AMDGPU::V_CMP_GE_I16_e64, AMDGPU::V_CMP_GE_I16_t16_e64,
1369 AMDGPU::V_CMP_GE_I16_fake16_e64, AMDGPU::V_CMP_GE_I32_e64,
1370 AMDGPU::V_CMP_GE_I64_e64);
1371 case CmpInst::ICMP_SLT:
1372 return Select(AMDGPU::V_CMP_LT_I16_e64, AMDGPU::V_CMP_LT_I16_t16_e64,
1373 AMDGPU::V_CMP_LT_I16_fake16_e64, AMDGPU::V_CMP_LT_I32_e64,
1374 AMDGPU::V_CMP_LT_I64_e64);
1375 case CmpInst::ICMP_SLE:
1376 return Select(AMDGPU::V_CMP_LE_I16_e64, AMDGPU::V_CMP_LE_I16_t16_e64,
1377 AMDGPU::V_CMP_LE_I16_fake16_e64, AMDGPU::V_CMP_LE_I32_e64,
1378 AMDGPU::V_CMP_LE_I64_e64);
1379 case CmpInst::ICMP_UGT:
1380 return Select(AMDGPU::V_CMP_GT_U16_e64, AMDGPU::V_CMP_GT_U16_t16_e64,
1381 AMDGPU::V_CMP_GT_U16_fake16_e64, AMDGPU::V_CMP_GT_U32_e64,
1382 AMDGPU::V_CMP_GT_U64_e64);
1383 case CmpInst::ICMP_UGE:
1384 return Select(AMDGPU::V_CMP_GE_U16_e64, AMDGPU::V_CMP_GE_U16_t16_e64,
1385 AMDGPU::V_CMP_GE_U16_fake16_e64, AMDGPU::V_CMP_GE_U32_e64,
1386 AMDGPU::V_CMP_GE_U64_e64);
1387 case CmpInst::ICMP_ULT:
1388 return Select(AMDGPU::V_CMP_LT_U16_e64, AMDGPU::V_CMP_LT_U16_t16_e64,
1389 AMDGPU::V_CMP_LT_U16_fake16_e64, AMDGPU::V_CMP_LT_U32_e64,
1390 AMDGPU::V_CMP_LT_U64_e64);
1391 case CmpInst::ICMP_ULE:
1392 return Select(AMDGPU::V_CMP_LE_U16_e64, AMDGPU::V_CMP_LE_U16_t16_e64,
1393 AMDGPU::V_CMP_LE_U16_fake16_e64, AMDGPU::V_CMP_LE_U32_e64,
1394 AMDGPU::V_CMP_LE_U64_e64);
1395
1396 case CmpInst::FCMP_OEQ:
1397 return Select(AMDGPU::V_CMP_EQ_F16_e64, AMDGPU::V_CMP_EQ_F16_t16_e64,
1398 AMDGPU::V_CMP_EQ_F16_fake16_e64, AMDGPU::V_CMP_EQ_F32_e64,
1399 AMDGPU::V_CMP_EQ_F64_e64);
1400 case CmpInst::FCMP_OGT:
1401 return Select(AMDGPU::V_CMP_GT_F16_e64, AMDGPU::V_CMP_GT_F16_t16_e64,
1402 AMDGPU::V_CMP_GT_F16_fake16_e64, AMDGPU::V_CMP_GT_F32_e64,
1403 AMDGPU::V_CMP_GT_F64_e64);
1404 case CmpInst::FCMP_OGE:
1405 return Select(AMDGPU::V_CMP_GE_F16_e64, AMDGPU::V_CMP_GE_F16_t16_e64,
1406 AMDGPU::V_CMP_GE_F16_fake16_e64, AMDGPU::V_CMP_GE_F32_e64,
1407 AMDGPU::V_CMP_GE_F64_e64);
1408 case CmpInst::FCMP_OLT:
1409 return Select(AMDGPU::V_CMP_LT_F16_e64, AMDGPU::V_CMP_LT_F16_t16_e64,
1410 AMDGPU::V_CMP_LT_F16_fake16_e64, AMDGPU::V_CMP_LT_F32_e64,
1411 AMDGPU::V_CMP_LT_F64_e64);
1412 case CmpInst::FCMP_OLE:
1413 return Select(AMDGPU::V_CMP_LE_F16_e64, AMDGPU::V_CMP_LE_F16_t16_e64,
1414 AMDGPU::V_CMP_LE_F16_fake16_e64, AMDGPU::V_CMP_LE_F32_e64,
1415 AMDGPU::V_CMP_LE_F64_e64);
1416 case CmpInst::FCMP_ONE:
1417 return Select(AMDGPU::V_CMP_NEQ_F16_e64, AMDGPU::V_CMP_NEQ_F16_t16_e64,
1418 AMDGPU::V_CMP_NEQ_F16_fake16_e64, AMDGPU::V_CMP_NEQ_F32_e64,
1419 AMDGPU::V_CMP_NEQ_F64_e64);
1420 case CmpInst::FCMP_ORD:
1421 return Select(AMDGPU::V_CMP_O_F16_e64, AMDGPU::V_CMP_O_F16_t16_e64,
1422 AMDGPU::V_CMP_O_F16_fake16_e64, AMDGPU::V_CMP_O_F32_e64,
1423 AMDGPU::V_CMP_O_F64_e64);
1424 case CmpInst::FCMP_UNO:
1425 return Select(AMDGPU::V_CMP_U_F16_e64, AMDGPU::V_CMP_U_F16_t16_e64,
1426 AMDGPU::V_CMP_U_F16_fake16_e64, AMDGPU::V_CMP_U_F32_e64,
1427 AMDGPU::V_CMP_U_F64_e64);
1428 case CmpInst::FCMP_UEQ:
1429 return Select(AMDGPU::V_CMP_NLG_F16_e64, AMDGPU::V_CMP_NLG_F16_t16_e64,
1430 AMDGPU::V_CMP_NLG_F16_fake16_e64, AMDGPU::V_CMP_NLG_F32_e64,
1431 AMDGPU::V_CMP_NLG_F64_e64);
1432 case CmpInst::FCMP_UGT:
1433 return Select(AMDGPU::V_CMP_NLE_F16_e64, AMDGPU::V_CMP_NLE_F16_t16_e64,
1434 AMDGPU::V_CMP_NLE_F16_fake16_e64, AMDGPU::V_CMP_NLE_F32_e64,
1435 AMDGPU::V_CMP_NLE_F64_e64);
1436 case CmpInst::FCMP_UGE:
1437 return Select(AMDGPU::V_CMP_NLT_F16_e64, AMDGPU::V_CMP_NLT_F16_t16_e64,
1438 AMDGPU::V_CMP_NLT_F16_fake16_e64, AMDGPU::V_CMP_NLT_F32_e64,
1439 AMDGPU::V_CMP_NLT_F64_e64);
1440 case CmpInst::FCMP_ULT:
1441 return Select(AMDGPU::V_CMP_NGE_F16_e64, AMDGPU::V_CMP_NGE_F16_t16_e64,
1442 AMDGPU::V_CMP_NGE_F16_fake16_e64, AMDGPU::V_CMP_NGE_F32_e64,
1443 AMDGPU::V_CMP_NGE_F64_e64);
1444 case CmpInst::FCMP_ULE:
1445 return Select(AMDGPU::V_CMP_NGT_F16_e64, AMDGPU::V_CMP_NGT_F16_t16_e64,
1446 AMDGPU::V_CMP_NGT_F16_fake16_e64, AMDGPU::V_CMP_NGT_F32_e64,
1447 AMDGPU::V_CMP_NGT_F64_e64);
1448 case CmpInst::FCMP_UNE:
1449 return Select(AMDGPU::V_CMP_NEQ_F16_e64, AMDGPU::V_CMP_NEQ_F16_t16_e64,
1450 AMDGPU::V_CMP_NEQ_F16_fake16_e64, AMDGPU::V_CMP_NEQ_F32_e64,
1451 AMDGPU::V_CMP_NEQ_F64_e64);
1452 case CmpInst::FCMP_TRUE:
1453 return Select(AMDGPU::V_CMP_TRU_F16_e64, AMDGPU::V_CMP_TRU_F16_t16_e64,
1454 AMDGPU::V_CMP_TRU_F16_fake16_e64, AMDGPU::V_CMP_TRU_F32_e64,
1455 AMDGPU::V_CMP_TRU_F64_e64);
1457 return Select(AMDGPU::V_CMP_F_F16_e64, AMDGPU::V_CMP_F_F16_t16_e64,
1458 AMDGPU::V_CMP_F_F16_fake16_e64, AMDGPU::V_CMP_F_F32_e64,
1459 AMDGPU::V_CMP_F_F64_e64);
1460 }
1461}
1462
1463int AMDGPUInstructionSelector::getS_CMPOpcode(CmpInst::Predicate P,
1464 unsigned Size) const {
1465 if (Size == 64) {
1466 if (!STI.hasScalarCompareEq64())
1467 return -1;
1468
1469 switch (P) {
1470 case CmpInst::ICMP_NE:
1471 return AMDGPU::S_CMP_LG_U64;
1472 case CmpInst::ICMP_EQ:
1473 return AMDGPU::S_CMP_EQ_U64;
1474 default:
1475 return -1;
1476 }
1477 }
1478
1479 if (Size == 32) {
1480 switch (P) {
1481 case CmpInst::ICMP_NE:
1482 return AMDGPU::S_CMP_LG_U32;
1483 case CmpInst::ICMP_EQ:
1484 return AMDGPU::S_CMP_EQ_U32;
1485 case CmpInst::ICMP_SGT:
1486 return AMDGPU::S_CMP_GT_I32;
1487 case CmpInst::ICMP_SGE:
1488 return AMDGPU::S_CMP_GE_I32;
1489 case CmpInst::ICMP_SLT:
1490 return AMDGPU::S_CMP_LT_I32;
1491 case CmpInst::ICMP_SLE:
1492 return AMDGPU::S_CMP_LE_I32;
1493 case CmpInst::ICMP_UGT:
1494 return AMDGPU::S_CMP_GT_U32;
1495 case CmpInst::ICMP_UGE:
1496 return AMDGPU::S_CMP_GE_U32;
1497 case CmpInst::ICMP_ULT:
1498 return AMDGPU::S_CMP_LT_U32;
1499 case CmpInst::ICMP_ULE:
1500 return AMDGPU::S_CMP_LE_U32;
1501 case CmpInst::FCMP_OEQ:
1502 return AMDGPU::S_CMP_EQ_F32;
1503 case CmpInst::FCMP_OGT:
1504 return AMDGPU::S_CMP_GT_F32;
1505 case CmpInst::FCMP_OGE:
1506 return AMDGPU::S_CMP_GE_F32;
1507 case CmpInst::FCMP_OLT:
1508 return AMDGPU::S_CMP_LT_F32;
1509 case CmpInst::FCMP_OLE:
1510 return AMDGPU::S_CMP_LE_F32;
1511 case CmpInst::FCMP_ONE:
1512 return AMDGPU::S_CMP_LG_F32;
1513 case CmpInst::FCMP_ORD:
1514 return AMDGPU::S_CMP_O_F32;
1515 case CmpInst::FCMP_UNO:
1516 return AMDGPU::S_CMP_U_F32;
1517 case CmpInst::FCMP_UEQ:
1518 return AMDGPU::S_CMP_NLG_F32;
1519 case CmpInst::FCMP_UGT:
1520 return AMDGPU::S_CMP_NLE_F32;
1521 case CmpInst::FCMP_UGE:
1522 return AMDGPU::S_CMP_NLT_F32;
1523 case CmpInst::FCMP_ULT:
1524 return AMDGPU::S_CMP_NGE_F32;
1525 case CmpInst::FCMP_ULE:
1526 return AMDGPU::S_CMP_NGT_F32;
1527 case CmpInst::FCMP_UNE:
1528 return AMDGPU::S_CMP_NEQ_F32;
1529 default:
1530 llvm_unreachable("Unknown condition code!");
1531 }
1532 }
1533
1534 if (Size == 16) {
1535 if (!STI.hasSALUFloatInsts())
1536 return -1;
1537
1538 switch (P) {
1539 case CmpInst::FCMP_OEQ:
1540 return AMDGPU::S_CMP_EQ_F16;
1541 case CmpInst::FCMP_OGT:
1542 return AMDGPU::S_CMP_GT_F16;
1543 case CmpInst::FCMP_OGE:
1544 return AMDGPU::S_CMP_GE_F16;
1545 case CmpInst::FCMP_OLT:
1546 return AMDGPU::S_CMP_LT_F16;
1547 case CmpInst::FCMP_OLE:
1548 return AMDGPU::S_CMP_LE_F16;
1549 case CmpInst::FCMP_ONE:
1550 return AMDGPU::S_CMP_LG_F16;
1551 case CmpInst::FCMP_ORD:
1552 return AMDGPU::S_CMP_O_F16;
1553 case CmpInst::FCMP_UNO:
1554 return AMDGPU::S_CMP_U_F16;
1555 case CmpInst::FCMP_UEQ:
1556 return AMDGPU::S_CMP_NLG_F16;
1557 case CmpInst::FCMP_UGT:
1558 return AMDGPU::S_CMP_NLE_F16;
1559 case CmpInst::FCMP_UGE:
1560 return AMDGPU::S_CMP_NLT_F16;
1561 case CmpInst::FCMP_ULT:
1562 return AMDGPU::S_CMP_NGE_F16;
1563 case CmpInst::FCMP_ULE:
1564 return AMDGPU::S_CMP_NGT_F16;
1565 case CmpInst::FCMP_UNE:
1566 return AMDGPU::S_CMP_NEQ_F16;
1567 default:
1568 llvm_unreachable("Unknown condition code!");
1569 }
1570 }
1571
1572 return -1;
1573}
1574
1575bool AMDGPUInstructionSelector::selectG_ICMP_or_FCMP(MachineInstr &I) const {
1576
1577 MachineBasicBlock *BB = I.getParent();
1578 const DebugLoc &DL = I.getDebugLoc();
1579
1580 Register SrcReg = I.getOperand(2).getReg();
1581 unsigned Size = RBI.getSizeInBits(SrcReg, *MRI, TRI);
1582
1583 auto Pred = (CmpInst::Predicate)I.getOperand(1).getPredicate();
1584
1585 Register CCReg = I.getOperand(0).getReg();
1586 if (!isVCC(CCReg, *MRI)) {
1587 int Opcode = getS_CMPOpcode(Pred, Size);
1588 if (Opcode == -1)
1589 return false;
1590 MachineInstr *ICmp = BuildMI(*BB, &I, DL, TII.get(Opcode))
1591 .add(I.getOperand(2))
1592 .add(I.getOperand(3));
1593 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), CCReg)
1594 .addReg(AMDGPU::SCC);
1595 constrainSelectedInstRegOperands(*ICmp, TII, TRI, RBI);
1596 bool Ret =
1597 RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32RegClass, *MRI);
1598 I.eraseFromParent();
1599 return Ret;
1600 }
1601
1602 if (I.getOpcode() == AMDGPU::G_FCMP)
1603 return false;
1604
1605 int Opcode = getV_CMPOpcode(Pred, Size, *Subtarget);
1606 if (Opcode == -1)
1607 return false;
1608
1609 MachineInstrBuilder ICmp;
1610 // t16 instructions
1611 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers)) {
1612 ICmp = BuildMI(*BB, &I, DL, TII.get(Opcode), I.getOperand(0).getReg())
1613 .addImm(0)
1614 .add(I.getOperand(2))
1615 .addImm(0)
1616 .add(I.getOperand(3))
1617 .addImm(0); // op_sel
1618 } else {
1619 ICmp = BuildMI(*BB, &I, DL, TII.get(Opcode), I.getOperand(0).getReg())
1620 .add(I.getOperand(2))
1621 .add(I.getOperand(3));
1622 }
1623
1624 RBI.constrainGenericRegister(ICmp->getOperand(0).getReg(),
1625 *TRI.getBoolRC(), *MRI);
1626 constrainSelectedInstRegOperands(*ICmp, TII, TRI, RBI);
1627 I.eraseFromParent();
1628 return true;
1629}
1630
1631bool AMDGPUInstructionSelector::selectIntrinsicCmp(MachineInstr &I) const {
1632 Register Dst = I.getOperand(0).getReg();
1633 if (isVCC(Dst, *MRI))
1634 return false;
1635
1636 LLT DstTy = MRI->getType(Dst);
1637 if (DstTy.getSizeInBits() != STI.getWavefrontSize())
1638 return false;
1639
1640 MachineBasicBlock *BB = I.getParent();
1641 const DebugLoc &DL = I.getDebugLoc();
1642 Register SrcReg = I.getOperand(2).getReg();
1643 unsigned Size = RBI.getSizeInBits(SrcReg, *MRI, TRI);
1644
1645 // i1 inputs are not supported in GlobalISel.
1646 if (Size == 1)
1647 return false;
1648
1649 auto Pred = static_cast<CmpInst::Predicate>(I.getOperand(4).getImm());
1650 if (!CmpInst::isIntPredicate(Pred) && !CmpInst::isFPPredicate(Pred)) {
1651 BuildMI(*BB, &I, DL, TII.get(AMDGPU::IMPLICIT_DEF), Dst);
1652 I.eraseFromParent();
1653 return RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI);
1654 }
1655
1656 const int Opcode = getV_CMPOpcode(Pred, Size, *Subtarget);
1657 if (Opcode == -1)
1658 return false;
1659
1660 MachineInstrBuilder SelectedMI;
1661 MachineOperand &LHS = I.getOperand(2);
1662 MachineOperand &RHS = I.getOperand(3);
1663 auto [Src0, Src0Mods] = selectVOP3ModsImpl(LHS.getReg());
1664 auto [Src1, Src1Mods] = selectVOP3ModsImpl(RHS.getReg());
1665 Register Src0Reg =
1666 copyToVGPRIfSrcFolded(Src0, Src0Mods, LHS, &I, /*ForceVGPR*/ true);
1667 Register Src1Reg =
1668 copyToVGPRIfSrcFolded(Src1, Src1Mods, RHS, &I, /*ForceVGPR*/ true);
1669 SelectedMI = BuildMI(*BB, &I, DL, TII.get(Opcode), Dst);
1670 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers))
1671 SelectedMI.addImm(Src0Mods);
1672 SelectedMI.addReg(Src0Reg);
1673 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src1_modifiers))
1674 SelectedMI.addImm(Src1Mods);
1675 SelectedMI.addReg(Src1Reg);
1676 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::clamp))
1677 SelectedMI.addImm(0); // clamp
1678 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::op_sel))
1679 SelectedMI.addImm(0); // op_sel
1680
1681 RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI);
1682 constrainSelectedInstRegOperands(*SelectedMI, TII, TRI, RBI);
1683
1684 I.eraseFromParent();
1685 return true;
1686}
1687
1688// Ballot has to zero bits in input lane-mask that are zero in current exec,
1689// Done as AND with exec. For inputs that are results of instruction that
1690// implicitly use same exec, for example compares in same basic block or SCC to
1691// VCC copy, use copy.
1694 MachineInstr *MI = MRI.getVRegDef(Reg);
1695 if (MI->getParent() != MBB)
1696 return false;
1697
1698 // Lane mask generated by SCC to VCC copy.
1699 if (MI->getOpcode() == AMDGPU::COPY) {
1700 auto DstRB = MRI.getRegBankOrNull(MI->getOperand(0).getReg());
1701 auto SrcRB = MRI.getRegBankOrNull(MI->getOperand(1).getReg());
1702 if (DstRB && SrcRB && DstRB->getID() == AMDGPU::VCCRegBankID &&
1703 SrcRB->getID() == AMDGPU::SGPRRegBankID)
1704 return true;
1705 }
1706
1707 // Lane mask generated by SCC to VCC copy
1708 if (MI->getOpcode() == AMDGPU::G_AMDGPU_COPY_VCC_SCC)
1709 return true;
1710
1711 // Lane mask generated using compare with same exec.
1712 if (isa<GAnyCmp>(MI))
1713 return true;
1714
1715 Register LHS, RHS;
1716 // Look through AND.
1717 if (mi_match(Reg, MRI, m_GAnd(m_Reg(LHS), m_Reg(RHS))))
1718 return isLaneMaskFromSameBlock(LHS, MRI, MBB) ||
1720
1721 return false;
1722}
1723
1724bool AMDGPUInstructionSelector::selectBallot(MachineInstr &I) const {
1725 MachineBasicBlock *BB = I.getParent();
1726 const DebugLoc &DL = I.getDebugLoc();
1727 Register DstReg = I.getOperand(0).getReg();
1728 Register SrcReg = I.getOperand(2).getReg();
1729 const unsigned BallotSize = MRI->getType(DstReg).getSizeInBits();
1730 const unsigned WaveSize = STI.getWavefrontSize();
1731
1732 // In the common case, the return type matches the wave size.
1733 // However we also support emitting i64 ballots in wave32 mode.
1734 if (BallotSize != WaveSize && (BallotSize != 64 || WaveSize != 32))
1735 return false;
1736
1737 std::optional<ValueAndVReg> Arg =
1739
1740 Register Dst = DstReg;
1741 // i64 ballot on Wave32: new Dst(i32) for WaveSize ballot.
1742 if (BallotSize != WaveSize) {
1743 Dst = MRI->createVirtualRegister(TRI.getBoolRC());
1744 }
1745
1746 if (Arg) {
1747 const int64_t Value = Arg->Value.getZExtValue();
1748 if (Value == 0) {
1749 // Dst = S_MOV 0
1750 unsigned Opcode = WaveSize == 64 ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
1751 BuildMI(*BB, &I, DL, TII.get(Opcode), Dst).addImm(0);
1752 } else {
1753 // Dst = COPY EXEC
1754 assert(Value == 1);
1755 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), Dst).addReg(TRI.getExec());
1756 }
1757 if (!RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI))
1758 return false;
1759 } else {
1760 if (isLaneMaskFromSameBlock(SrcReg, *MRI, BB)) {
1761 // Dst = COPY SrcReg
1762 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), Dst).addReg(SrcReg);
1763 if (!RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI))
1764 return false;
1765 } else {
1766 // Dst = S_AND SrcReg, EXEC
1767 unsigned AndOpc = WaveSize == 64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
1768 auto And = BuildMI(*BB, &I, DL, TII.get(AndOpc), Dst)
1769 .addReg(SrcReg)
1770 .addReg(TRI.getExec())
1771 .setOperandDead(3); // Dead scc
1772 constrainSelectedInstRegOperands(*And, TII, TRI, RBI);
1773 }
1774 }
1775
1776 // i64 ballot on Wave32: zero-extend i32 ballot to i64.
1777 if (BallotSize != WaveSize) {
1778 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
1779 BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_MOV_B32), HiReg).addImm(0);
1780 BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
1781 .addReg(Dst)
1782 .addImm(AMDGPU::sub0)
1783 .addReg(HiReg)
1784 .addImm(AMDGPU::sub1);
1785 }
1786
1787 I.eraseFromParent();
1788 return true;
1789}
1790
1791bool AMDGPUInstructionSelector::selectRelocConstant(MachineInstr &I) const {
1792 Register DstReg = I.getOperand(0).getReg();
1793 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
1794 const TargetRegisterClass *DstRC = TRI.getRegClassForSizeOnBank(32, *DstBank);
1795 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
1796 return false;
1797
1798 const bool IsVALU = DstBank->getID() == AMDGPU::VGPRRegBankID;
1799
1800 Module *M = MF->getFunction().getParent();
1801 const MDNode *Metadata = I.getOperand(2).getMetadata();
1802 auto SymbolName = cast<MDString>(Metadata->getOperand(0))->getString();
1803 auto *RelocSymbol = cast<GlobalVariable>(
1804 M->getOrInsertGlobal(SymbolName, Type::getInt32Ty(M->getContext())));
1805
1806 MachineBasicBlock *BB = I.getParent();
1807 BuildMI(*BB, &I, I.getDebugLoc(),
1808 TII.get(IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32), DstReg)
1810
1811 I.eraseFromParent();
1812 return true;
1813}
1814
1815bool AMDGPUInstructionSelector::selectGroupStaticSize(MachineInstr &I) const {
1816 Triple::OSType OS = MF->getTarget().getTargetTriple().getOS();
1817
1818 Register DstReg = I.getOperand(0).getReg();
1819 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
1820 unsigned Mov = DstRB->getID() == AMDGPU::SGPRRegBankID ?
1821 AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1822
1823 MachineBasicBlock *MBB = I.getParent();
1824 const DebugLoc &DL = I.getDebugLoc();
1825
1826 auto MIB = BuildMI(*MBB, &I, DL, TII.get(Mov), DstReg);
1827
1828 if (OS == Triple::AMDHSA || OS == Triple::AMDPAL) {
1829 const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
1830 MIB.addImm(MFI->getLDSSize());
1831 } else {
1832 Module *M = MF->getFunction().getParent();
1833 const GlobalValue *GV =
1834 Intrinsic::getOrInsertDeclaration(M, Intrinsic::amdgcn_groupstaticsize);
1836 }
1837
1838 I.eraseFromParent();
1839 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
1840 return true;
1841}
1842
1843bool AMDGPUInstructionSelector::selectReturnAddress(MachineInstr &I) const {
1844 MachineBasicBlock *MBB = I.getParent();
1846 const DebugLoc &DL = I.getDebugLoc();
1847
1848 MachineOperand &Dst = I.getOperand(0);
1849 Register DstReg = Dst.getReg();
1850 unsigned Depth = I.getOperand(2).getImm();
1851
1852 const TargetRegisterClass *RC
1853 = TRI.getConstrainedRegClassForOperand(Dst, *MRI);
1854 if (!RC->hasSubClassEq(&AMDGPU::SGPR_64RegClass) ||
1855 !RBI.constrainGenericRegister(DstReg, *RC, *MRI))
1856 return false;
1857
1858 // Check for kernel and shader functions
1859 if (Depth != 0 ||
1860 MF.getInfo<SIMachineFunctionInfo>()->isEntryFunction()) {
1861 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_MOV_B64), DstReg)
1862 .addImm(0);
1863 I.eraseFromParent();
1864 return true;
1865 }
1866
1867 MachineFrameInfo &MFI = MF.getFrameInfo();
1868 // There is a call to @llvm.returnaddress in this function
1869 MFI.setReturnAddressIsTaken(true);
1870
1871 // Get the return address reg and mark it as an implicit live-in
1872 Register ReturnAddrReg = TRI.getReturnAddressReg(MF);
1873 Register LiveIn = getFunctionLiveInPhysReg(MF, TII, ReturnAddrReg,
1874 AMDGPU::SReg_64RegClass, DL);
1875 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::COPY), DstReg)
1876 .addReg(LiveIn);
1877 I.eraseFromParent();
1878 return true;
1879}
1880
1881bool AMDGPUInstructionSelector::selectEndCfIntrinsic(MachineInstr &MI) const {
1882 // FIXME: Manually selecting to avoid dealing with the SReg_1 trick
1883 // SelectionDAG uses for wave32 vs wave64.
1884 MachineBasicBlock *BB = MI.getParent();
1885 BuildMI(*BB, &MI, MI.getDebugLoc(), TII.get(AMDGPU::SI_END_CF))
1886 .add(MI.getOperand(1));
1887
1888 Register Reg = MI.getOperand(1).getReg();
1889 MI.eraseFromParent();
1890
1891 if (!MRI->getRegClassOrNull(Reg))
1892 MRI->setRegClass(Reg, TRI.getWaveMaskRegClass());
1893 return true;
1894}
1895
1896bool AMDGPUInstructionSelector::selectDSOrderedIntrinsic(
1897 MachineInstr &MI, Intrinsic::ID IntrID) const {
1898 MachineBasicBlock *MBB = MI.getParent();
1900 const DebugLoc &DL = MI.getDebugLoc();
1901
1902 unsigned IndexOperand = MI.getOperand(7).getImm();
1903 bool WaveRelease = MI.getOperand(8).getImm() != 0;
1904 bool WaveDone = MI.getOperand(9).getImm() != 0;
1905
1906 if (WaveDone && !WaveRelease) {
1907 // TODO: Move this to IR verifier
1908 const Function &Fn = MF->getFunction();
1909 Fn.getContext().diagnose(DiagnosticInfoUnsupported(
1910 Fn, "ds_ordered_count: wave_done requires wave_release", DL));
1911 }
1912
1913 unsigned OrderedCountIndex = IndexOperand & 0x3f;
1914 IndexOperand &= ~0x3f;
1915 unsigned CountDw = 0;
1916
1917 if (STI.getGeneration() >= AMDGPUSubtarget::GFX10) {
1918 CountDw = (IndexOperand >> 24) & 0xf;
1919 IndexOperand &= ~(0xf << 24);
1920
1921 if (CountDw < 1 || CountDw > 4) {
1922 const Function &Fn = MF->getFunction();
1923 Fn.getContext().diagnose(DiagnosticInfoUnsupported(
1924 Fn, "ds_ordered_count: dword count must be between 1 and 4", DL));
1925 CountDw = 1;
1926 }
1927 }
1928
1929 if (IndexOperand) {
1930 const Function &Fn = MF->getFunction();
1931 Fn.getContext().diagnose(DiagnosticInfoUnsupported(
1932 Fn, "ds_ordered_count: bad index operand", DL));
1933 }
1934
1935 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
1936 unsigned ShaderType = SIInstrInfo::getDSShaderTypeValue(*MF);
1937
1938 unsigned Offset0 = OrderedCountIndex << 2;
1939 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
1940
1941 if (STI.getGeneration() >= AMDGPUSubtarget::GFX10)
1942 Offset1 |= (CountDw - 1) << 6;
1943
1944 if (STI.getGeneration() < AMDGPUSubtarget::GFX11)
1945 Offset1 |= ShaderType << 2;
1946
1947 unsigned Offset = Offset0 | (Offset1 << 8);
1948
1949 Register M0Val = MI.getOperand(2).getReg();
1950 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
1951 .addReg(M0Val);
1952
1953 Register DstReg = MI.getOperand(0).getReg();
1954 Register ValReg = MI.getOperand(3).getReg();
1955 MachineInstrBuilder DS =
1956 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::DS_ORDERED_COUNT), DstReg)
1957 .addReg(ValReg)
1958 .addImm(Offset)
1959 .cloneMemRefs(MI);
1960
1961 if (!RBI.constrainGenericRegister(M0Val, AMDGPU::SReg_32RegClass, *MRI))
1962 return false;
1963
1964 constrainSelectedInstRegOperands(*DS, TII, TRI, RBI);
1965 MI.eraseFromParent();
1966 return true;
1967}
1968
1969static unsigned gwsIntrinToOpcode(unsigned IntrID) {
1970 switch (IntrID) {
1971 case Intrinsic::amdgcn_ds_gws_init:
1972 return AMDGPU::DS_GWS_INIT;
1973 case Intrinsic::amdgcn_ds_gws_barrier:
1974 return AMDGPU::DS_GWS_BARRIER;
1975 case Intrinsic::amdgcn_ds_gws_sema_v:
1976 return AMDGPU::DS_GWS_SEMA_V;
1977 case Intrinsic::amdgcn_ds_gws_sema_br:
1978 return AMDGPU::DS_GWS_SEMA_BR;
1979 case Intrinsic::amdgcn_ds_gws_sema_p:
1980 return AMDGPU::DS_GWS_SEMA_P;
1981 case Intrinsic::amdgcn_ds_gws_sema_release_all:
1982 return AMDGPU::DS_GWS_SEMA_RELEASE_ALL;
1983 default:
1984 llvm_unreachable("not a gws intrinsic");
1985 }
1986}
1987
1988bool AMDGPUInstructionSelector::selectDSGWSIntrinsic(MachineInstr &MI,
1989 Intrinsic::ID IID) const {
1990 if (!STI.hasGWS() || (IID == Intrinsic::amdgcn_ds_gws_sema_release_all &&
1991 !STI.hasGWSSemaReleaseAll()))
1992 return false;
1993
1994 // intrinsic ID, vsrc, offset
1995 const bool HasVSrc = MI.getNumOperands() == 3;
1996 assert(HasVSrc || MI.getNumOperands() == 2);
1997
1998 Register BaseOffset = MI.getOperand(HasVSrc ? 2 : 1).getReg();
1999 const RegisterBank *OffsetRB = RBI.getRegBank(BaseOffset, *MRI, TRI);
2000 if (OffsetRB->getID() != AMDGPU::SGPRRegBankID)
2001 return false;
2002
2003 MachineInstr *OffsetDef = getDefIgnoringCopies(BaseOffset, *MRI);
2004 unsigned ImmOffset;
2005
2006 MachineBasicBlock *MBB = MI.getParent();
2007 const DebugLoc &DL = MI.getDebugLoc();
2008
2009 MachineInstr *Readfirstlane = nullptr;
2010
2011 // If we legalized the VGPR input, strip out the readfirstlane to analyze the
2012 // incoming offset, in case there's an add of a constant. We'll have to put it
2013 // back later.
2014 if (OffsetDef->getOpcode() == AMDGPU::V_READFIRSTLANE_B32) {
2015 Readfirstlane = OffsetDef;
2016 BaseOffset = OffsetDef->getOperand(1).getReg();
2017 OffsetDef = getDefIgnoringCopies(BaseOffset, *MRI);
2018 }
2019
2020 if (OffsetDef->getOpcode() == AMDGPU::G_CONSTANT) {
2021 // If we have a constant offset, try to use the 0 in m0 as the base.
2022 // TODO: Look into changing the default m0 initialization value. If the
2023 // default -1 only set the low 16-bits, we could leave it as-is and add 1 to
2024 // the immediate offset.
2025
2026 ImmOffset = OffsetDef->getOperand(1).getCImm()->getZExtValue();
2027 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2028 .addImm(0);
2029 } else {
2030 std::tie(BaseOffset, ImmOffset) =
2031 AMDGPU::getBaseWithConstantOffset(*MRI, BaseOffset, VT);
2032
2033 if (Readfirstlane) {
2034 // We have the constant offset now, so put the readfirstlane back on the
2035 // variable component.
2036 if (!RBI.constrainGenericRegister(BaseOffset, AMDGPU::VGPR_32RegClass, *MRI))
2037 return false;
2038
2039 Readfirstlane->getOperand(1).setReg(BaseOffset);
2040 BaseOffset = Readfirstlane->getOperand(0).getReg();
2041 } else {
2042 if (!RBI.constrainGenericRegister(BaseOffset,
2043 AMDGPU::SReg_32RegClass, *MRI))
2044 return false;
2045 }
2046
2047 Register M0Base = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2048 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::S_LSHL_B32), M0Base)
2049 .addReg(BaseOffset)
2050 .addImm(16)
2051 .setOperandDead(3); // Dead scc
2052
2053 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
2054 .addReg(M0Base);
2055 }
2056
2057 // The resource id offset is computed as (<isa opaque base> + M0[21:16] +
2058 // offset field) % 64. Some versions of the programming guide omit the m0
2059 // part, or claim it's from offset 0.
2060
2061 unsigned Opc = gwsIntrinToOpcode(IID);
2062 const MCInstrDesc &InstrDesc = TII.get(Opc);
2063
2064 if (HasVSrc) {
2065 Register VSrc = MI.getOperand(1).getReg();
2066
2067 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
2068 const TargetRegisterClass *DataRC = TII.getRegClass(InstrDesc, Data0Idx);
2069 const TargetRegisterClass *SubRC =
2070 TRI.getSubRegisterClass(DataRC, AMDGPU::sub0);
2071
2072 if (!SubRC) {
2073 // 32-bit normal case.
2074 if (!RBI.constrainGenericRegister(VSrc, *DataRC, *MRI))
2075 return false;
2076
2077 BuildMI(*MBB, &MI, DL, InstrDesc)
2078 .addReg(VSrc)
2079 .addImm(ImmOffset)
2080 .cloneMemRefs(MI);
2081 } else {
2082 // Requires even register alignment, so create 64-bit value and pad the
2083 // top half with undef.
2084 Register DataReg = MRI->createVirtualRegister(DataRC);
2085 if (!RBI.constrainGenericRegister(VSrc, *SubRC, *MRI))
2086 return false;
2087
2088 Register UndefReg = MRI->createVirtualRegister(SubRC);
2089 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2090 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::REG_SEQUENCE), DataReg)
2091 .addReg(VSrc)
2092 .addImm(AMDGPU::sub0)
2093 .addReg(UndefReg)
2094 .addImm(AMDGPU::sub1);
2095
2096 BuildMI(*MBB, &MI, DL, InstrDesc)
2097 .addReg(DataReg)
2098 .addImm(ImmOffset)
2099 .cloneMemRefs(MI);
2100 }
2101 } else {
2102 BuildMI(*MBB, &MI, DL, InstrDesc)
2103 .addImm(ImmOffset)
2104 .cloneMemRefs(MI);
2105 }
2106
2107 MI.eraseFromParent();
2108 return true;
2109}
2110
2111bool AMDGPUInstructionSelector::selectDSAppendConsume(MachineInstr &MI,
2112 bool IsAppend) const {
2113 Register PtrBase = MI.getOperand(2).getReg();
2114 LLT PtrTy = MRI->getType(PtrBase);
2115 bool IsGDS = PtrTy.getAddressSpace() == AMDGPUAS::REGION_ADDRESS;
2116
2117 unsigned Offset;
2118 std::tie(PtrBase, Offset) = selectDS1Addr1OffsetImpl(MI.getOperand(2));
2119
2120 // TODO: Should this try to look through readfirstlane like GWS?
2121 if (!isDSOffsetLegal(PtrBase, Offset)) {
2122 PtrBase = MI.getOperand(2).getReg();
2123 Offset = 0;
2124 }
2125
2126 MachineBasicBlock *MBB = MI.getParent();
2127 const DebugLoc &DL = MI.getDebugLoc();
2128 const unsigned Opc = IsAppend ? AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME;
2129
2130 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
2131 .addReg(PtrBase);
2132 if (!RBI.constrainGenericRegister(PtrBase, AMDGPU::SReg_32RegClass, *MRI))
2133 return false;
2134
2135 auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc), MI.getOperand(0).getReg())
2136 .addImm(Offset)
2137 .addImm(IsGDS ? -1 : 0)
2138 .cloneMemRefs(MI);
2139 MI.eraseFromParent();
2140 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
2141 return true;
2142}
2143
2144bool AMDGPUInstructionSelector::selectInitWholeWave(MachineInstr &MI) const {
2145 MachineFunction *MF = MI.getMF();
2146 SIMachineFunctionInfo *MFInfo = MF->getInfo<SIMachineFunctionInfo>();
2147
2148 MFInfo->setInitWholeWave();
2149 return selectImpl(MI, *CoverageInfo);
2150}
2151
2152static bool parseTexFail(uint64_t TexFailCtrl, bool &TFE, bool &LWE,
2153 bool &IsTexFail) {
2154 if (TexFailCtrl)
2155 IsTexFail = true;
2156
2157 TFE = TexFailCtrl & 0x1;
2158 TexFailCtrl &= ~(uint64_t)0x1;
2159 LWE = TexFailCtrl & 0x2;
2160 TexFailCtrl &= ~(uint64_t)0x2;
2161
2162 return TexFailCtrl == 0;
2163}
2164
2165bool AMDGPUInstructionSelector::selectImageIntrinsic(
2166 MachineInstr &MI, const AMDGPU::ImageDimIntrinsicInfo *Intr) const {
2167 MachineBasicBlock *MBB = MI.getParent();
2168 const DebugLoc &DL = MI.getDebugLoc();
2169 unsigned IntrOpcode = Intr->BaseOpcode;
2170
2171 // For image atomic: use no-return opcode if result is unused.
2172 if (Intr->AtomicNoRetBaseOpcode != Intr->BaseOpcode) {
2173 Register ResultDef = MI.getOperand(0).getReg();
2174 if (MRI->use_nodbg_empty(ResultDef))
2175 IntrOpcode = Intr->AtomicNoRetBaseOpcode;
2176 }
2177
2178 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
2180
2181 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfo(Intr->Dim);
2182 const bool IsGFX10Plus = AMDGPU::isGFX10Plus(STI);
2183 const bool IsGFX11Plus = AMDGPU::isGFX11Plus(STI);
2184 const bool IsGFX12Plus = AMDGPU::isGFX12Plus(STI);
2185 const bool IsGFX13Plus = AMDGPU::isGFX13Plus(STI);
2186
2187 const unsigned ArgOffset = MI.getNumExplicitDefs() + 1;
2188
2189 Register VDataIn = AMDGPU::NoRegister;
2190 Register VDataOut = AMDGPU::NoRegister;
2191 LLT VDataTy;
2192 int NumVDataDwords = -1;
2193 bool IsD16 = MI.getOpcode() == AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16 ||
2194 MI.getOpcode() == AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16;
2195
2196 bool Unorm;
2197 if (!BaseOpcode->Sampler)
2198 Unorm = true;
2199 else
2200 Unorm = MI.getOperand(ArgOffset + Intr->UnormIndex).getImm() != 0;
2201
2202 bool TFE;
2203 bool LWE;
2204 bool IsTexFail = false;
2205 if (!parseTexFail(MI.getOperand(ArgOffset + Intr->TexFailCtrlIndex).getImm(),
2206 TFE, LWE, IsTexFail))
2207 return false;
2208
2209 const int Flags = MI.getOperand(ArgOffset + Intr->NumArgs).getImm();
2210 const bool IsA16 = (Flags & 1) != 0;
2211 const bool IsG16 = (Flags & 2) != 0;
2212
2213 // A16 implies 16 bit gradients if subtarget doesn't support G16
2214 if (IsA16 && !STI.hasG16() && !IsG16)
2215 return false;
2216
2217 unsigned DMask = 0;
2218 unsigned DMaskLanes = 0;
2219
2220 if (BaseOpcode->Atomic) {
2221 if (!BaseOpcode->NoReturn)
2222 VDataOut = MI.getOperand(0).getReg();
2223 VDataIn = MI.getOperand(2).getReg();
2224 LLT Ty = MRI->getType(VDataIn);
2225
2226 // Be careful to allow atomic swap on 16-bit element vectors.
2227 const bool Is64Bit = BaseOpcode->AtomicX2 ?
2228 Ty.getSizeInBits() == 128 :
2229 Ty.getSizeInBits() == 64;
2230
2231 if (BaseOpcode->AtomicX2) {
2232 assert(MI.getOperand(3).getReg() == AMDGPU::NoRegister);
2233
2234 DMask = Is64Bit ? 0xf : 0x3;
2235 NumVDataDwords = Is64Bit ? 4 : 2;
2236 } else {
2237 DMask = Is64Bit ? 0x3 : 0x1;
2238 NumVDataDwords = Is64Bit ? 2 : 1;
2239 }
2240 } else {
2241 DMask = MI.getOperand(ArgOffset + Intr->DMaskIndex).getImm();
2242 DMaskLanes = BaseOpcode->Gather4 ? 4 : llvm::popcount(DMask);
2243
2244 if (BaseOpcode->Store) {
2245 VDataIn = MI.getOperand(1).getReg();
2246 VDataTy = MRI->getType(VDataIn);
2247 NumVDataDwords = (VDataTy.getSizeInBits() + 31) / 32;
2248 } else if (BaseOpcode->NoReturn) {
2249 NumVDataDwords = 0;
2250 } else {
2251 VDataOut = MI.getOperand(0).getReg();
2252 VDataTy = MRI->getType(VDataOut);
2253 NumVDataDwords = DMaskLanes;
2254
2255 if (IsD16 && !STI.hasUnpackedD16VMem())
2256 NumVDataDwords = (DMaskLanes + 1) / 2;
2257 }
2258 }
2259
2260 // Set G16 opcode
2261 if (Subtarget->hasG16() && IsG16) {
2262 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
2264 assert(G16MappingInfo);
2265 IntrOpcode = G16MappingInfo->G16; // set opcode to variant with _g16
2266 }
2267
2268 // TODO: Check this in verifier.
2269 assert((!IsTexFail || DMaskLanes >= 1) && "should have legalized this");
2270
2271 unsigned CPol = MI.getOperand(ArgOffset + Intr->CachePolicyIndex).getImm();
2272 // Keep GLC only when the atomic's result is actually used.
2273 if (BaseOpcode->Atomic && !BaseOpcode->NoReturn)
2275 if (CPol & ~((IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12) |
2277 return false;
2278
2279 int NumVAddrRegs = 0;
2280 int NumVAddrDwords = 0;
2281 for (unsigned I = Intr->VAddrStart; I < Intr->VAddrEnd; I++) {
2282 // Skip the $noregs and 0s inserted during legalization.
2283 MachineOperand &AddrOp = MI.getOperand(ArgOffset + I);
2284 if (!AddrOp.isReg())
2285 continue; // XXX - Break?
2286
2287 Register Addr = AddrOp.getReg();
2288 if (!Addr)
2289 break;
2290
2291 ++NumVAddrRegs;
2292 NumVAddrDwords += (MRI->getType(Addr).getSizeInBits() + 31) / 32;
2293 }
2294
2295 // The legalizer preprocessed the intrinsic arguments. If we aren't using
2296 // NSA, these should have been packed into a single value in the first
2297 // address register
2298 const bool UseNSA =
2299 NumVAddrRegs != 1 &&
2300 (STI.hasPartialNSAEncoding() ? NumVAddrDwords >= NumVAddrRegs
2301 : NumVAddrDwords == NumVAddrRegs);
2302 if (UseNSA && !STI.hasFeature(AMDGPU::FeatureNSAEncoding)) {
2303 LLVM_DEBUG(dbgs() << "Trying to use NSA on non-NSA target\n");
2304 return false;
2305 }
2306
2307 if (IsTexFail)
2308 ++NumVDataDwords;
2309
2310 int Opcode = -1;
2311 if (IsGFX13Plus) {
2312 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx13,
2313 NumVDataDwords, NumVAddrDwords);
2314 } else if (IsGFX12Plus) {
2315 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx12,
2316 NumVDataDwords, NumVAddrDwords);
2317 } else if (IsGFX11Plus) {
2318 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
2319 UseNSA ? AMDGPU::MIMGEncGfx11NSA
2320 : AMDGPU::MIMGEncGfx11Default,
2321 NumVDataDwords, NumVAddrDwords);
2322 } else if (IsGFX10Plus) {
2323 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
2324 UseNSA ? AMDGPU::MIMGEncGfx10NSA
2325 : AMDGPU::MIMGEncGfx10Default,
2326 NumVDataDwords, NumVAddrDwords);
2327 } else {
2328 if (Subtarget->hasGFX90AInsts()) {
2329 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx90a,
2330 NumVDataDwords, NumVAddrDwords);
2331 if (Opcode == -1) {
2332 LLVM_DEBUG(
2333 dbgs()
2334 << "requested image instruction is not supported on this GPU\n");
2335 return false;
2336 }
2337 }
2338 if (Opcode == -1 &&
2339 STI.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
2340 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx8,
2341 NumVDataDwords, NumVAddrDwords);
2342 if (Opcode == -1)
2343 Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx6,
2344 NumVDataDwords, NumVAddrDwords);
2345 }
2346 if (Opcode == -1)
2347 return false;
2348
2349 auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opcode))
2350 .cloneMemRefs(MI);
2351
2352 if (VDataOut) {
2353 if (BaseOpcode->AtomicX2) {
2354 const bool Is64 = MRI->getType(VDataOut).getSizeInBits() == 64;
2355
2356 Register TmpReg = MRI->createVirtualRegister(
2357 Is64 ? &AMDGPU::VReg_128RegClass : &AMDGPU::VReg_64RegClass);
2358 unsigned SubReg = Is64 ? AMDGPU::sub0_sub1 : AMDGPU::sub0;
2359
2360 MIB.addDef(TmpReg);
2361 if (!MRI->use_empty(VDataOut)) {
2362 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), VDataOut)
2363 .addReg(TmpReg, RegState::Kill, SubReg);
2364 }
2365
2366 } else {
2367 MIB.addDef(VDataOut); // vdata output
2368 }
2369 }
2370
2371 if (VDataIn)
2372 MIB.addReg(VDataIn); // vdata input
2373
2374 for (int I = 0; I != NumVAddrRegs; ++I) {
2375 MachineOperand &SrcOp = MI.getOperand(ArgOffset + Intr->VAddrStart + I);
2376 if (SrcOp.isReg()) {
2377 assert(SrcOp.getReg() != 0);
2378 MIB.addReg(SrcOp.getReg());
2379 }
2380 }
2381
2382 MIB.addReg(MI.getOperand(ArgOffset + Intr->RsrcIndex).getReg());
2383 if (BaseOpcode->Sampler)
2384 MIB.addReg(MI.getOperand(ArgOffset + Intr->SampIndex).getReg());
2385
2386 MIB.addImm(DMask); // dmask
2387
2388 if (IsGFX10Plus)
2389 MIB.addImm(DimInfo->Encoding);
2390 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::unorm))
2391 MIB.addImm(Unorm);
2392
2393 MIB.addImm(CPol);
2394 MIB.addImm(IsA16 && // a16 or r128
2395 STI.hasFeature(AMDGPU::FeatureR128A16) ? -1 : 0);
2396 if (IsGFX10Plus)
2397 MIB.addImm(IsA16 ? -1 : 0);
2398
2399 if (!Subtarget->hasGFX90AInsts()) {
2400 MIB.addImm(TFE); // tfe
2401 } else if (TFE) {
2402 LLVM_DEBUG(dbgs() << "TFE is not supported on this GPU\n");
2403 return false;
2404 }
2405
2406 if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::lwe))
2407 MIB.addImm(LWE); // lwe
2408 if (!IsGFX10Plus)
2409 MIB.addImm(DimInfo->DA ? -1 : 0);
2410 if (BaseOpcode->HasD16)
2411 MIB.addImm(IsD16 ? -1 : 0);
2412
2413 MI.eraseFromParent();
2414 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
2415 TII.enforceOperandRCAlignment(*MIB, AMDGPU::OpName::vaddr);
2416 return true;
2417}
2418
2419// We need to handle this here because tablegen doesn't support matching
2420// instructions with multiple outputs.
2421bool AMDGPUInstructionSelector::selectDSBvhStackIntrinsic(
2422 MachineInstr &MI) const {
2423 Register Dst0 = MI.getOperand(0).getReg();
2424 Register Dst1 = MI.getOperand(1).getReg();
2425
2426 const DebugLoc &DL = MI.getDebugLoc();
2427 MachineBasicBlock *MBB = MI.getParent();
2428
2429 Register Addr = MI.getOperand(3).getReg();
2430 Register Data0 = MI.getOperand(4).getReg();
2431 Register Data1 = MI.getOperand(5).getReg();
2432 unsigned Offset = MI.getOperand(6).getImm();
2433
2434 unsigned Opc;
2435 switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
2436 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
2437 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
2438 Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
2439 break;
2440 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
2441 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
2442 break;
2443 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
2444 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
2445 break;
2446 }
2447
2448 auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc), Dst0)
2449 .addDef(Dst1)
2450 .addUse(Addr)
2451 .addUse(Data0)
2452 .addUse(Data1)
2453 .addImm(Offset)
2454 .cloneMemRefs(MI);
2455
2456 MI.eraseFromParent();
2457 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
2458 return true;
2459}
2460
2461bool AMDGPUInstructionSelector::selectG_INTRINSIC_W_SIDE_EFFECTS(
2462 MachineInstr &I) const {
2463 Intrinsic::ID IntrinsicID = cast<GIntrinsic>(I).getIntrinsicID();
2464 switch (IntrinsicID) {
2465 case Intrinsic::amdgcn_end_cf:
2466 return selectEndCfIntrinsic(I);
2467 case Intrinsic::amdgcn_ds_ordered_add:
2468 case Intrinsic::amdgcn_ds_ordered_swap:
2469 return selectDSOrderedIntrinsic(I, IntrinsicID);
2470 case Intrinsic::amdgcn_ds_gws_init:
2471 case Intrinsic::amdgcn_ds_gws_barrier:
2472 case Intrinsic::amdgcn_ds_gws_sema_v:
2473 case Intrinsic::amdgcn_ds_gws_sema_br:
2474 case Intrinsic::amdgcn_ds_gws_sema_p:
2475 case Intrinsic::amdgcn_ds_gws_sema_release_all:
2476 return selectDSGWSIntrinsic(I, IntrinsicID);
2477 case Intrinsic::amdgcn_ds_append:
2478 return selectDSAppendConsume(I, true);
2479 case Intrinsic::amdgcn_ds_consume:
2480 return selectDSAppendConsume(I, false);
2481 case Intrinsic::amdgcn_init_whole_wave:
2482 return selectInitWholeWave(I);
2483 case Intrinsic::amdgcn_raw_buffer_load_lds:
2484 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
2485 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
2486 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
2487 case Intrinsic::amdgcn_struct_buffer_load_lds:
2488 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
2489 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
2490 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
2491 return selectBufferLoadLds(I);
2492 // Until we can store both the address space of the global and the LDS
2493 // arguments by having tto MachineMemOperands on an intrinsic, we just trust
2494 // that the argument is a global pointer (buffer pointers have been handled by
2495 // a LLVM IR-level lowering).
2496 case Intrinsic::amdgcn_load_to_lds:
2497 case Intrinsic::amdgcn_load_async_to_lds:
2498 case Intrinsic::amdgcn_global_load_lds:
2499 case Intrinsic::amdgcn_global_load_async_lds:
2500 return selectGlobalLoadLds(I);
2501 case Intrinsic::amdgcn_tensor_load_to_lds:
2502 case Intrinsic::amdgcn_tensor_store_from_lds:
2503 return selectTensorLoadStore(I, IntrinsicID);
2504 case Intrinsic::amdgcn_asyncmark:
2505 case Intrinsic::amdgcn_wait_asyncmark:
2506 if (!Subtarget->hasAsyncMark())
2507 return false;
2508 break;
2509 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
2510 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
2511 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
2512 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
2513 return selectDSBvhStackIntrinsic(I);
2514 case Intrinsic::amdgcn_s_alloc_vgpr: {
2515 // S_ALLOC_VGPR doesn't have a destination register, it just implicitly sets
2516 // SCC. We then need to COPY it into the result vreg.
2517 MachineBasicBlock *MBB = I.getParent();
2518 const DebugLoc &DL = I.getDebugLoc();
2519
2520 Register ResReg = I.getOperand(0).getReg();
2521
2522 MachineInstr *AllocMI = BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_ALLOC_VGPR))
2523 .add(I.getOperand(2));
2524 (void)BuildMI(*MBB, &I, DL, TII.get(AMDGPU::COPY), ResReg)
2525 .addReg(AMDGPU::SCC);
2526 I.eraseFromParent();
2527 constrainSelectedInstRegOperands(*AllocMI, TII, TRI, RBI);
2528 return RBI.constrainGenericRegister(ResReg, AMDGPU::SReg_32RegClass, *MRI);
2529 }
2530 case Intrinsic::amdgcn_s_barrier_init:
2531 case Intrinsic::amdgcn_s_barrier_signal_var:
2532 return selectNamedBarrierInit(I, IntrinsicID);
2533 case Intrinsic::amdgcn_s_wakeup_barrier:
2534 case Intrinsic::amdgcn_s_barrier_join:
2535 case Intrinsic::amdgcn_s_get_named_barrier_state:
2536 return selectNamedBarrierInst(I, IntrinsicID);
2537 case Intrinsic::amdgcn_s_get_barrier_state:
2538 return selectSGetBarrierState(I, IntrinsicID);
2539 case Intrinsic::amdgcn_s_barrier_signal_isfirst:
2540 return selectSBarrierSignalIsfirst(I, IntrinsicID);
2541 }
2542 return selectImpl(I, *CoverageInfo);
2543}
2544
2545bool AMDGPUInstructionSelector::selectG_SELECT(MachineInstr &I) const {
2546 if (selectImpl(I, *CoverageInfo))
2547 return true;
2548
2549 MachineBasicBlock *BB = I.getParent();
2550 const DebugLoc &DL = I.getDebugLoc();
2551
2552 Register DstReg = I.getOperand(0).getReg();
2553 unsigned Size = RBI.getSizeInBits(DstReg, *MRI, TRI);
2554 assert(Size <= 32 || Size == 64);
2555 const MachineOperand &CCOp = I.getOperand(1);
2556 Register CCReg = CCOp.getReg();
2557 if (!isVCC(CCReg, *MRI)) {
2558 unsigned SelectOpcode = Size == 64 ? AMDGPU::S_CSELECT_B64 :
2559 AMDGPU::S_CSELECT_B32;
2560 MachineInstr *CopySCC = BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
2561 .addReg(CCReg);
2562
2563 // The generic constrainSelectedInstRegOperands doesn't work for the scc register
2564 // bank, because it does not cover the register class that we used to represent
2565 // for it. So we need to manually set the register class here.
2566 if (!MRI->getRegClassOrNull(CCReg))
2567 MRI->setRegClass(CCReg, TRI.getConstrainedRegClassForOperand(CCOp, *MRI));
2568 MachineInstr *Select = BuildMI(*BB, &I, DL, TII.get(SelectOpcode), DstReg)
2569 .add(I.getOperand(2))
2570 .add(I.getOperand(3));
2571
2573 constrainSelectedInstRegOperands(*CopySCC, TII, TRI, RBI);
2574 I.eraseFromParent();
2575 return true;
2576 }
2577
2578 // Wide VGPR select should have been split in RegBankSelect.
2579 if (Size > 32)
2580 return false;
2581
2582 MachineInstr *Select =
2583 BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2584 .addImm(0)
2585 .add(I.getOperand(3))
2586 .addImm(0)
2587 .add(I.getOperand(2))
2588 .add(I.getOperand(1));
2589
2591 I.eraseFromParent();
2592 return true;
2593}
2594
2595bool AMDGPUInstructionSelector::selectG_TRUNC(MachineInstr &I) const {
2596 Register DstReg = I.getOperand(0).getReg();
2597 Register SrcReg = I.getOperand(1).getReg();
2598 const LLT DstTy = MRI->getType(DstReg);
2599 const LLT SrcTy = MRI->getType(SrcReg);
2600 const LLT S1 = LLT::scalar(1);
2601
2602 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
2603 const RegisterBank *DstRB;
2604 if (DstTy == S1) {
2605 // This is a special case. We don't treat s1 for legalization artifacts as
2606 // vcc booleans.
2607 DstRB = SrcRB;
2608 } else {
2609 DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
2610 if (SrcRB != DstRB)
2611 return false;
2612 }
2613
2614 const bool IsVALU = DstRB->getID() == AMDGPU::VGPRRegBankID;
2615
2616 unsigned DstSize = DstTy.getSizeInBits();
2617 unsigned SrcSize = SrcTy.getSizeInBits();
2618
2619 const TargetRegisterClass *SrcRC =
2620 TRI.getRegClassForSizeOnBank(SrcSize, *SrcRB);
2621 const TargetRegisterClass *DstRC =
2622 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
2623 if (!SrcRC || !DstRC)
2624 return false;
2625
2626 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
2627 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
2628 LLVM_DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
2629 return false;
2630 }
2631
2632 if (DstRC == &AMDGPU::VGPR_16RegClass && SrcSize == 32) {
2633 assert(STI.useRealTrue16Insts());
2634 const DebugLoc &DL = I.getDebugLoc();
2635 MachineBasicBlock *MBB = I.getParent();
2636 BuildMI(*MBB, I, DL, TII.get(AMDGPU::COPY), DstReg)
2637 .addReg(SrcReg, {}, AMDGPU::lo16);
2638 I.eraseFromParent();
2639 return true;
2640 }
2641
2642 if (DstTy == LLT::fixed_vector(2, 16) && SrcTy == LLT::fixed_vector(2, 32)) {
2643 MachineBasicBlock *MBB = I.getParent();
2644 const DebugLoc &DL = I.getDebugLoc();
2645
2646 Register LoReg = MRI->createVirtualRegister(DstRC);
2647 Register HiReg = MRI->createVirtualRegister(DstRC);
2648 BuildMI(*MBB, I, DL, TII.get(AMDGPU::COPY), LoReg)
2649 .addReg(SrcReg, {}, AMDGPU::sub0);
2650 BuildMI(*MBB, I, DL, TII.get(AMDGPU::COPY), HiReg)
2651 .addReg(SrcReg, {}, AMDGPU::sub1);
2652
2653 if (IsVALU && STI.hasSDWA()) {
2654 // Write the low 16-bits of the high element into the high 16-bits of the
2655 // low element.
2656 MachineInstr *MovSDWA =
2657 BuildMI(*MBB, I, DL, TII.get(AMDGPU::V_MOV_B32_sdwa), DstReg)
2658 .addImm(0) // $src0_modifiers
2659 .addReg(HiReg) // $src0
2660 .addImm(0) // $clamp
2661 .addImm(AMDGPU::SDWA::WORD_1) // $dst_sel
2662 .addImm(AMDGPU::SDWA::UNUSED_PRESERVE) // $dst_unused
2663 .addImm(AMDGPU::SDWA::WORD_0) // $src0_sel
2664 .addReg(LoReg, RegState::Implicit);
2665 MovSDWA->tieOperands(0, MovSDWA->getNumOperands() - 1);
2666 } else {
2667 Register TmpReg0 = MRI->createVirtualRegister(DstRC);
2668 Register TmpReg1 = MRI->createVirtualRegister(DstRC);
2669 Register ImmReg = MRI->createVirtualRegister(DstRC);
2670 if (IsVALU) {
2671 BuildMI(*MBB, I, DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), TmpReg0)
2672 .addImm(16)
2673 .addReg(HiReg);
2674 } else {
2675 BuildMI(*MBB, I, DL, TII.get(AMDGPU::S_LSHL_B32), TmpReg0)
2676 .addReg(HiReg)
2677 .addImm(16)
2678 .setOperandDead(3); // Dead scc
2679 }
2680
2681 unsigned MovOpc = IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32;
2682 unsigned AndOpc = IsVALU ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
2683 unsigned OrOpc = IsVALU ? AMDGPU::V_OR_B32_e64 : AMDGPU::S_OR_B32;
2684
2685 BuildMI(*MBB, I, DL, TII.get(MovOpc), ImmReg)
2686 .addImm(0xffff);
2687 auto And = BuildMI(*MBB, I, DL, TII.get(AndOpc), TmpReg1)
2688 .addReg(LoReg)
2689 .addReg(ImmReg);
2690 auto Or = BuildMI(*MBB, I, DL, TII.get(OrOpc), DstReg)
2691 .addReg(TmpReg0)
2692 .addReg(TmpReg1);
2693
2694 if (!IsVALU) {
2695 And.setOperandDead(3); // Dead scc
2696 Or.setOperandDead(3); // Dead scc
2697 }
2698 }
2699
2700 I.eraseFromParent();
2701 return true;
2702 }
2703
2704 if (!DstTy.isScalar())
2705 return false;
2706
2707 if (SrcSize > 32) {
2708 unsigned SubRegIdx = DstSize < 32
2709 ? static_cast<unsigned>(AMDGPU::sub0)
2710 : TRI.getSubRegFromChannel(0, DstSize / 32);
2711 if (SubRegIdx == AMDGPU::NoSubRegister)
2712 return false;
2713
2714 // Deal with weird cases where the class only partially supports the subreg
2715 // index.
2716 const TargetRegisterClass *SrcWithSubRC
2717 = TRI.getSubClassWithSubReg(SrcRC, SubRegIdx);
2718 if (!SrcWithSubRC)
2719 return false;
2720
2721 if (SrcWithSubRC != SrcRC) {
2722 if (!RBI.constrainGenericRegister(SrcReg, *SrcWithSubRC, *MRI))
2723 return false;
2724 }
2725
2726 I.getOperand(1).setSubReg(SubRegIdx);
2727 }
2728
2729 I.setDesc(TII.get(TargetOpcode::COPY));
2730 return true;
2731}
2732
2733/// \returns true if a bitmask for \p Size bits will be an inline immediate.
2734static bool shouldUseAndMask(unsigned Size, unsigned &Mask) {
2736 int SignedMask = static_cast<int>(Mask);
2737 return SignedMask >= -16 && SignedMask <= 64;
2738}
2739
2740// Like RegisterBankInfo::getRegBank, but don't assume vcc for s1.
2741const RegisterBank *AMDGPUInstructionSelector::getArtifactRegBank(
2742 Register Reg, const MachineRegisterInfo &MRI,
2743 const TargetRegisterInfo &TRI) const {
2744 const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Reg);
2745 if (auto *RB = dyn_cast<const RegisterBank *>(RegClassOrBank))
2746 return RB;
2747
2748 // Ignore the type, since we don't use vcc in artifacts.
2749 if (auto *RC = dyn_cast<const TargetRegisterClass *>(RegClassOrBank))
2750 return &RBI.getRegBankFromRegClass(*RC, LLT());
2751 return nullptr;
2752}
2753
2754bool AMDGPUInstructionSelector::selectG_SZA_EXT(MachineInstr &I) const {
2755 bool InReg = I.getOpcode() == AMDGPU::G_SEXT_INREG;
2756 bool Signed = I.getOpcode() == AMDGPU::G_SEXT || InReg;
2757 const DebugLoc &DL = I.getDebugLoc();
2758 MachineBasicBlock &MBB = *I.getParent();
2759 const Register DstReg = I.getOperand(0).getReg();
2760 const Register SrcReg = I.getOperand(1).getReg();
2761
2762 const LLT DstTy = MRI->getType(DstReg);
2763 const LLT SrcTy = MRI->getType(SrcReg);
2764 const unsigned SrcSize = I.getOpcode() == AMDGPU::G_SEXT_INREG ?
2765 I.getOperand(2).getImm() : SrcTy.getSizeInBits();
2766 const unsigned DstSize = DstTy.getSizeInBits();
2767 if (!DstTy.isScalar())
2768 return false;
2769
2770 // Artifact casts should never use vcc.
2771 const RegisterBank *SrcBank = getArtifactRegBank(SrcReg, *MRI, TRI);
2772
2773 // FIXME: This should probably be illegal and split earlier.
2774 if (I.getOpcode() == AMDGPU::G_ANYEXT) {
2775 if (DstSize <= 32)
2776 return selectCOPY(I);
2777
2778 const TargetRegisterClass *SrcRC =
2779 TRI.getRegClassForTypeOnBank(SrcTy, *SrcBank);
2780 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
2781 const TargetRegisterClass *DstRC =
2782 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
2783
2784 Register UndefReg = MRI->createVirtualRegister(SrcRC);
2785 BuildMI(MBB, I, DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2786 BuildMI(MBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
2787 .addReg(SrcReg)
2788 .addImm(AMDGPU::sub0)
2789 .addReg(UndefReg)
2790 .addImm(AMDGPU::sub1);
2791 I.eraseFromParent();
2792
2793 return RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) &&
2794 RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI);
2795 }
2796
2797 if (SrcBank->getID() == AMDGPU::VGPRRegBankID && DstSize <= 32) {
2798 // 64-bit should have been split up in RegBankSelect
2799
2800 // Try to use an and with a mask if it will save code size.
2801 unsigned Mask;
2802 if (!Signed && shouldUseAndMask(SrcSize, Mask)) {
2803 MachineInstr *ExtI =
2804 BuildMI(MBB, I, DL, TII.get(AMDGPU::V_AND_B32_e32), DstReg)
2805 .addImm(Mask)
2806 .addReg(SrcReg);
2807 I.eraseFromParent();
2808 constrainSelectedInstRegOperands(*ExtI, TII, TRI, RBI);
2809 return true;
2810 }
2811
2812 const unsigned BFE = Signed ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
2813 MachineInstr *ExtI =
2814 BuildMI(MBB, I, DL, TII.get(BFE), DstReg)
2815 .addReg(SrcReg)
2816 .addImm(0) // Offset
2817 .addImm(SrcSize); // Width
2818 I.eraseFromParent();
2819 constrainSelectedInstRegOperands(*ExtI, TII, TRI, RBI);
2820 return true;
2821 }
2822
2823 if (SrcBank->getID() == AMDGPU::SGPRRegBankID && DstSize <= 64) {
2824 const TargetRegisterClass &SrcRC = InReg && DstSize > 32 ?
2825 AMDGPU::SReg_64RegClass : AMDGPU::SReg_32RegClass;
2826 if (!RBI.constrainGenericRegister(SrcReg, SrcRC, *MRI))
2827 return false;
2828
2829 if (Signed && DstSize == 32 && (SrcSize == 8 || SrcSize == 16)) {
2830 const unsigned SextOpc = SrcSize == 8 ?
2831 AMDGPU::S_SEXT_I32_I8 : AMDGPU::S_SEXT_I32_I16;
2832 BuildMI(MBB, I, DL, TII.get(SextOpc), DstReg)
2833 .addReg(SrcReg);
2834 I.eraseFromParent();
2835 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
2836 }
2837
2838 // Using a single 32-bit SALU to calculate the high half is smaller than
2839 // S_BFE with a literal constant operand.
2840 if (DstSize > 32 && SrcSize == 32) {
2841 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2842 unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
2843 if (Signed) {
2844 BuildMI(MBB, I, DL, TII.get(AMDGPU::S_ASHR_I32), HiReg)
2845 .addReg(SrcReg, {}, SubReg)
2846 .addImm(31)
2847 .setOperandDead(3); // Dead scc
2848 } else {
2849 BuildMI(MBB, I, DL, TII.get(AMDGPU::S_MOV_B32), HiReg)
2850 .addImm(0);
2851 }
2852 BuildMI(MBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
2853 .addReg(SrcReg, {}, SubReg)
2854 .addImm(AMDGPU::sub0)
2855 .addReg(HiReg)
2856 .addImm(AMDGPU::sub1);
2857 I.eraseFromParent();
2858 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass,
2859 *MRI);
2860 }
2861
2862 const unsigned BFE64 = Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64;
2863 const unsigned BFE32 = Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
2864
2865 // Scalar BFE is encoded as S1[5:0] = offset, S1[22:16]= width.
2866 if (DstSize > 32 && (SrcSize <= 32 || InReg)) {
2867 // We need a 64-bit register source, but the high bits don't matter.
2868 Register ExtReg = MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
2869 Register UndefReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2870 unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
2871
2872 BuildMI(MBB, I, DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2873 BuildMI(MBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), ExtReg)
2874 .addReg(SrcReg, {}, SubReg)
2875 .addImm(AMDGPU::sub0)
2876 .addReg(UndefReg)
2877 .addImm(AMDGPU::sub1);
2878
2879 BuildMI(MBB, I, DL, TII.get(BFE64), DstReg)
2880 .addReg(ExtReg)
2881 .addImm(SrcSize << 16);
2882
2883 I.eraseFromParent();
2884 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass, *MRI);
2885 }
2886
2887 unsigned Mask;
2888 if (!Signed && shouldUseAndMask(SrcSize, Mask)) {
2889 BuildMI(MBB, I, DL, TII.get(AMDGPU::S_AND_B32), DstReg)
2890 .addReg(SrcReg)
2891 .addImm(Mask)
2892 .setOperandDead(3); // Dead scc
2893 } else {
2894 BuildMI(MBB, I, DL, TII.get(BFE32), DstReg)
2895 .addReg(SrcReg)
2896 .addImm(SrcSize << 16);
2897 }
2898
2899 I.eraseFromParent();
2900 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
2901 }
2902
2903 return false;
2904}
2905
2909
2911 Register BitcastSrc;
2912 if (mi_match(Reg, MRI, m_GBitcast(m_Reg(BitcastSrc))))
2913 Reg = BitcastSrc;
2914 return Reg;
2915}
2916
2918 Register &Out) {
2919 // When unmerging a register that is composed of 2 x 16-bit values allow to
2920 // use an extract hi instruction for the upper 16 bits. We only need to check
2921 // the size of `In` as all defs are guaranteed to be the same type for
2922 // GUnmerge.
2923 GUnmerge *Unmerge;
2924 if (mi_match(In, MRI, m_GUnmerge(Unmerge))) {
2925 if (Unmerge->getNumDefs() == 2 && Unmerge->getOperand(1).getReg() == In &&
2926 MRI.getType(In).getSizeInBits() == 16) {
2927 Out = Unmerge->getSourceReg();
2928 return true;
2929 }
2930 }
2931
2932 Register Trunc;
2933 if (!mi_match(In, MRI, m_GTrunc(m_Reg(Trunc))))
2934 return false;
2935
2936 Register LShlSrc;
2937 Register Cst;
2938 if (mi_match(Trunc, MRI, m_GLShr(m_Reg(LShlSrc), m_Reg(Cst)))) {
2939 Cst = stripCopy(Cst, MRI);
2940 if (mi_match(Cst, MRI, m_SpecificICst(16))) {
2941 Out = stripBitCast(LShlSrc, MRI);
2942 return true;
2943 }
2944 }
2945
2946 ArrayRef<int> Mask;
2947 Register Src1;
2948 if (!mi_match(Trunc, MRI, m_GShuffleVector(m_Reg(Src1), m_Reg(), Mask)))
2949 return false;
2950
2951 assert(MRI.getType(Src1) == LLT::fixed_vector(2, 16));
2952 assert(Mask.size() == 2);
2953
2954 if (Mask[0] == 1 && Mask[1] <= 1) {
2955 Out = Trunc;
2956 return true;
2957 }
2958
2959 return false;
2960}
2961
2962bool AMDGPUInstructionSelector::selectG_FPEXT(MachineInstr &I) const {
2963 if (!Subtarget->hasSALUFloatInsts())
2964 return false;
2965
2966 Register Dst = I.getOperand(0).getReg();
2967 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2968 if (DstRB->getID() != AMDGPU::SGPRRegBankID)
2969 return false;
2970
2971 Register Src = I.getOperand(1).getReg();
2972
2973 if (MRI->getType(Dst) == LLT::scalar(32) &&
2974 MRI->getType(Src) == LLT::scalar(16)) {
2975 if (isExtractHiElt(*MRI, Src, Src)) {
2976 MachineBasicBlock *BB = I.getParent();
2977 BuildMI(*BB, &I, I.getDebugLoc(), TII.get(AMDGPU::S_CVT_HI_F32_F16), Dst)
2978 .addUse(Src);
2979 I.eraseFromParent();
2980 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
2981 }
2982 }
2983
2984 return false;
2985}
2986
2987bool AMDGPUInstructionSelector::selectG_FNEG(MachineInstr &MI) const {
2988 // Only manually handle the f64 SGPR case.
2989 //
2990 // FIXME: This is a workaround for 2.5 different tablegen problems. Because
2991 // the bit ops theoretically have a second result due to the implicit def of
2992 // SCC, the GlobalISelEmitter is overly conservative and rejects it. Fixing
2993 // that is easy by disabling the check. The result works, but uses a
2994 // nonsensical sreg32orlds_and_sreg_1 regclass.
2995 //
2996 // The DAG emitter is more problematic, and incorrectly adds both S_XOR_B32 to
2997 // the variadic REG_SEQUENCE operands.
2998
2999 Register Dst = MI.getOperand(0).getReg();
3000 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
3001 if (DstRB->getID() != AMDGPU::SGPRRegBankID ||
3002 MRI->getType(Dst) != LLT::scalar(64))
3003 return false;
3004
3005 Register Src = MI.getOperand(1).getReg();
3006 MachineInstr *Fabs = getOpcodeDef(TargetOpcode::G_FABS, Src, *MRI);
3007 if (Fabs)
3008 Src = Fabs->getOperand(1).getReg();
3009
3010 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
3011 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
3012 return false;
3013
3014 MachineBasicBlock *BB = MI.getParent();
3015 const DebugLoc &DL = MI.getDebugLoc();
3016 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3017 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3018 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3019 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3020
3021 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), LoReg)
3022 .addReg(Src, {}, AMDGPU::sub0);
3023 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), HiReg)
3024 .addReg(Src, {}, AMDGPU::sub1);
3025 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3026 .addImm(0x80000000);
3027
3028 // Set or toggle sign bit.
3029 unsigned Opc = Fabs ? AMDGPU::S_OR_B32 : AMDGPU::S_XOR_B32;
3030 BuildMI(*BB, &MI, DL, TII.get(Opc), OpReg)
3031 .addReg(HiReg)
3032 .addReg(ConstReg)
3033 .setOperandDead(3); // Dead scc
3034 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3035 .addReg(LoReg)
3036 .addImm(AMDGPU::sub0)
3037 .addReg(OpReg)
3038 .addImm(AMDGPU::sub1);
3039 MI.eraseFromParent();
3040 return true;
3041}
3042
3043// FIXME: This is a workaround for the same tablegen problems as G_FNEG
3044bool AMDGPUInstructionSelector::selectG_FABS(MachineInstr &MI) const {
3045 Register Dst = MI.getOperand(0).getReg();
3046 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
3047 if (DstRB->getID() != AMDGPU::SGPRRegBankID ||
3048 MRI->getType(Dst) != LLT::scalar(64))
3049 return false;
3050
3051 Register Src = MI.getOperand(1).getReg();
3052 MachineBasicBlock *BB = MI.getParent();
3053 const DebugLoc &DL = MI.getDebugLoc();
3054 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3055 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3056 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3057 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3058
3059 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
3060 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
3061 return false;
3062
3063 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), LoReg)
3064 .addReg(Src, {}, AMDGPU::sub0);
3065 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), HiReg)
3066 .addReg(Src, {}, AMDGPU::sub1);
3067 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3068 .addImm(0x7fffffff);
3069
3070 // Clear sign bit.
3071 // TODO: Should this used S_BITSET0_*?
3072 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_AND_B32), OpReg)
3073 .addReg(HiReg)
3074 .addReg(ConstReg)
3075 .setOperandDead(3); // Dead scc
3076 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3077 .addReg(LoReg)
3078 .addImm(AMDGPU::sub0)
3079 .addReg(OpReg)
3080 .addImm(AMDGPU::sub1);
3081
3082 MI.eraseFromParent();
3083 return true;
3084}
3085
3086static bool isConstant(const MachineInstr &MI) {
3087 return MI.getOpcode() == TargetOpcode::G_CONSTANT;
3088}
3089
3090void AMDGPUInstructionSelector::getAddrModeInfo(const MachineInstr &Load,
3091 const MachineRegisterInfo &MRI, SmallVectorImpl<GEPInfo> &AddrInfo) const {
3092
3093 unsigned OpNo = Load.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3094 const MachineInstr *PtrMI =
3095 MRI.getUniqueVRegDef(Load.getOperand(OpNo).getReg());
3096
3097 assert(PtrMI);
3098
3099 if (PtrMI->getOpcode() != TargetOpcode::G_PTR_ADD)
3100 return;
3101
3102 GEPInfo GEPInfo;
3103
3104 for (unsigned i = 1; i != 3; ++i) {
3105 const MachineOperand &GEPOp = PtrMI->getOperand(i);
3106 const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.getReg());
3107 assert(OpDef);
3108 if (i == 2 && isConstant(*OpDef)) {
3109 // TODO: Could handle constant base + variable offset, but a combine
3110 // probably should have commuted it.
3111 assert(GEPInfo.Imm == 0);
3112 GEPInfo.Imm = OpDef->getOperand(1).getCImm()->getSExtValue();
3113 continue;
3114 }
3115 const RegisterBank *OpBank = RBI.getRegBank(GEPOp.getReg(), MRI, TRI);
3116 if (OpBank->getID() == AMDGPU::SGPRRegBankID)
3117 GEPInfo.SgprParts.push_back(GEPOp.getReg());
3118 else
3119 GEPInfo.VgprParts.push_back(GEPOp.getReg());
3120 }
3121
3122 AddrInfo.push_back(GEPInfo);
3123 getAddrModeInfo(*PtrMI, MRI, AddrInfo);
3124}
3125
3126bool AMDGPUInstructionSelector::isSGPR(Register Reg) const {
3127 return RBI.getRegBank(Reg, *MRI, TRI)->getID() == AMDGPU::SGPRRegBankID;
3128}
3129
3130bool AMDGPUInstructionSelector::isInstrUniform(const MachineInstr &MI) const {
3131 if (!MI.hasOneMemOperand())
3132 return false;
3133
3134 const MachineMemOperand *MMO = *MI.memoperands_begin();
3135 const Value *Ptr = MMO->getValue();
3136
3137 // UndefValue means this is a load of a kernel input. These are uniform.
3138 // Sometimes LDS instructions have constant pointers.
3139 // If Ptr is null, then that means this mem operand contains a
3140 // PseudoSourceValue like GOT.
3142 return true;
3143
3145 return true;
3146
3147 if (MI.getOpcode() == AMDGPU::G_PREFETCH)
3148 return RBI.getRegBank(MI.getOperand(0).getReg(), *MRI, TRI)->getID() ==
3149 AMDGPU::SGPRRegBankID;
3150
3151 const Instruction *I = dyn_cast<Instruction>(Ptr);
3152 return I && I->getMetadata("amdgpu.uniform");
3153}
3154
3155bool AMDGPUInstructionSelector::hasVgprParts(ArrayRef<GEPInfo> AddrInfo) const {
3156 for (const GEPInfo &GEPInfo : AddrInfo) {
3157 if (!GEPInfo.VgprParts.empty())
3158 return true;
3159 }
3160 return false;
3161}
3162
3163void AMDGPUInstructionSelector::initM0(MachineInstr &I) const {
3164 const LLT PtrTy = MRI->getType(I.getOperand(1).getReg());
3165 unsigned AS = PtrTy.getAddressSpace();
3167 STI.ldsRequiresM0Init()) {
3168 MachineBasicBlock *BB = I.getParent();
3169
3170 // If DS instructions require M0 initialization, insert it before selecting.
3171 BuildMI(*BB, &I, I.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
3172 .addImm(-1);
3173 }
3174}
3175
3176bool AMDGPUInstructionSelector::selectG_LOAD_STORE_ATOMICRMW(
3177 MachineInstr &I) const {
3178 initM0(I);
3179 return selectImpl(I, *CoverageInfo);
3180}
3181
3183 if (Reg.isPhysical())
3184 return false;
3185
3187 const unsigned Opcode = MI.getOpcode();
3188
3189 if (Opcode == AMDGPU::COPY)
3190 return isVCmpResult(MI.getOperand(1).getReg(), MRI);
3191
3192 if (Opcode == AMDGPU::G_AND || Opcode == AMDGPU::G_OR ||
3193 Opcode == AMDGPU::G_XOR)
3194 return isVCmpResult(MI.getOperand(1).getReg(), MRI) &&
3195 isVCmpResult(MI.getOperand(2).getReg(), MRI);
3196
3197 if (auto *GI = dyn_cast<GIntrinsic>(&MI))
3198 return GI->is(Intrinsic::amdgcn_class);
3199
3200 return Opcode == AMDGPU::G_ICMP || Opcode == AMDGPU::G_FCMP;
3201}
3202
3203bool AMDGPUInstructionSelector::selectG_BRCOND(MachineInstr &I) const {
3204 MachineBasicBlock *BB = I.getParent();
3205 MachineOperand &CondOp = I.getOperand(0);
3206 Register CondReg = CondOp.getReg();
3207 const DebugLoc &DL = I.getDebugLoc();
3208
3209 unsigned BrOpcode;
3210 Register CondPhysReg;
3211 const TargetRegisterClass *ConstrainRC;
3212
3213 // In SelectionDAG, we inspect the IR block for uniformity metadata to decide
3214 // whether the branch is uniform when selecting the instruction. In
3215 // GlobalISel, we should push that decision into RegBankSelect. Assume for now
3216 // RegBankSelect knows what it's doing if the branch condition is scc, even
3217 // though it currently does not.
3218 if (!isVCC(CondReg, *MRI)) {
3219 if (MRI->getType(CondReg) != LLT::scalar(32))
3220 return false;
3221
3222 CondPhysReg = AMDGPU::SCC;
3223 BrOpcode = AMDGPU::S_CBRANCH_SCC1;
3224 ConstrainRC = &AMDGPU::SReg_32RegClass;
3225 } else {
3226 // FIXME: Should scc->vcc copies and with exec?
3227
3228 // Unless the value of CondReg is a result of a V_CMP* instruction then we
3229 // need to insert an and with exec.
3230 if (!isVCmpResult(CondReg, *MRI)) {
3231 const bool Is64 = STI.isWave64();
3232 const unsigned Opcode = Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
3233 const Register Exec = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;
3234
3235 Register TmpReg = MRI->createVirtualRegister(TRI.getBoolRC());
3236 BuildMI(*BB, &I, DL, TII.get(Opcode), TmpReg)
3237 .addReg(CondReg)
3238 .addReg(Exec)
3239 .setOperandDead(3); // Dead scc
3240 CondReg = TmpReg;
3241 }
3242
3243 CondPhysReg = TRI.getVCC();
3244 BrOpcode = AMDGPU::S_CBRANCH_VCCNZ;
3245 ConstrainRC = TRI.getBoolRC();
3246 }
3247
3248 if (!MRI->getRegClassOrNull(CondReg))
3249 MRI->setRegClass(CondReg, ConstrainRC);
3250
3251 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), CondPhysReg)
3252 .addReg(CondReg);
3253 BuildMI(*BB, &I, DL, TII.get(BrOpcode))
3254 .addMBB(I.getOperand(1).getMBB());
3255
3256 I.eraseFromParent();
3257 return true;
3258}
3259
3260bool AMDGPUInstructionSelector::selectG_GLOBAL_VALUE(
3261 MachineInstr &I) const {
3262 Register DstReg = I.getOperand(0).getReg();
3263 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3264 const bool IsVGPR = DstRB->getID() == AMDGPU::VGPRRegBankID;
3265 I.setDesc(TII.get(IsVGPR ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32));
3266 if (IsVGPR)
3267 I.addOperand(*MF, MachineOperand::CreateReg(AMDGPU::EXEC, false, true));
3268
3269 return RBI.constrainGenericRegister(
3270 DstReg, IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass, *MRI);
3271}
3272
3273bool AMDGPUInstructionSelector::selectG_PTRMASK(MachineInstr &I) const {
3274 Register DstReg = I.getOperand(0).getReg();
3275 Register SrcReg = I.getOperand(1).getReg();
3276 Register MaskReg = I.getOperand(2).getReg();
3277 LLT Ty = MRI->getType(DstReg);
3278 LLT MaskTy = MRI->getType(MaskReg);
3279 MachineBasicBlock *BB = I.getParent();
3280 const DebugLoc &DL = I.getDebugLoc();
3281
3282 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3283 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3284 const RegisterBank *MaskRB = RBI.getRegBank(MaskReg, *MRI, TRI);
3285 const bool IsVGPR = DstRB->getID() == AMDGPU::VGPRRegBankID;
3286 if (DstRB != SrcRB) // Should only happen for hand written MIR.
3287 return false;
3288
3289 // Try to avoid emitting a bit operation when we only need to touch half of
3290 // the 64-bit pointer.
3291 APInt MaskOnes = VT->getKnownOnes(MaskReg).zext(64);
3292 const APInt MaskHi32 = APInt::getHighBitsSet(64, 32);
3293 const APInt MaskLo32 = APInt::getLowBitsSet(64, 32);
3294
3295 const bool CanCopyLow32 = (MaskOnes & MaskLo32) == MaskLo32;
3296 const bool CanCopyHi32 = (MaskOnes & MaskHi32) == MaskHi32;
3297
3298 if (!IsVGPR && Ty.getSizeInBits() == 64 &&
3299 !CanCopyLow32 && !CanCopyHi32) {
3300 auto MIB = BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_AND_B64), DstReg)
3301 .addReg(SrcReg)
3302 .addReg(MaskReg)
3303 .setOperandDead(3); // Dead scc
3304 I.eraseFromParent();
3305 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
3306 return true;
3307 }
3308
3309 unsigned NewOpc = IsVGPR ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
3310 const TargetRegisterClass &RegRC
3311 = IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
3312
3313 const TargetRegisterClass *DstRC = TRI.getRegClassForTypeOnBank(Ty, *DstRB);
3314 const TargetRegisterClass *SrcRC = TRI.getRegClassForTypeOnBank(Ty, *SrcRB);
3315 const TargetRegisterClass *MaskRC =
3316 TRI.getRegClassForTypeOnBank(MaskTy, *MaskRB);
3317
3318 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3319 !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3320 !RBI.constrainGenericRegister(MaskReg, *MaskRC, *MRI))
3321 return false;
3322
3323 if (Ty.getSizeInBits() == 32) {
3324 assert(MaskTy.getSizeInBits() == 32 &&
3325 "ptrmask should have been narrowed during legalize");
3326
3327 auto NewOp = BuildMI(*BB, &I, DL, TII.get(NewOpc), DstReg)
3328 .addReg(SrcReg)
3329 .addReg(MaskReg);
3330
3331 if (!IsVGPR)
3332 NewOp.setOperandDead(3); // Dead scc
3333 I.eraseFromParent();
3334 return true;
3335 }
3336
3337 Register HiReg = MRI->createVirtualRegister(&RegRC);
3338 Register LoReg = MRI->createVirtualRegister(&RegRC);
3339
3340 // Extract the subregisters from the source pointer.
3341 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), LoReg)
3342 .addReg(SrcReg, {}, AMDGPU::sub0);
3343 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), HiReg)
3344 .addReg(SrcReg, {}, AMDGPU::sub1);
3345
3346 Register MaskedLo, MaskedHi;
3347
3348 if (CanCopyLow32) {
3349 // If all the bits in the low half are 1, we only need a copy for it.
3350 MaskedLo = LoReg;
3351 } else {
3352 // Extract the mask subregister and apply the and.
3353 Register MaskLo = MRI->createVirtualRegister(&RegRC);
3354 MaskedLo = MRI->createVirtualRegister(&RegRC);
3355
3356 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), MaskLo)
3357 .addReg(MaskReg, {}, AMDGPU::sub0);
3358 BuildMI(*BB, &I, DL, TII.get(NewOpc), MaskedLo)
3359 .addReg(LoReg)
3360 .addReg(MaskLo);
3361 }
3362
3363 if (CanCopyHi32) {
3364 // If all the bits in the high half are 1, we only need a copy for it.
3365 MaskedHi = HiReg;
3366 } else {
3367 Register MaskHi = MRI->createVirtualRegister(&RegRC);
3368 MaskedHi = MRI->createVirtualRegister(&RegRC);
3369
3370 BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), MaskHi)
3371 .addReg(MaskReg, {}, AMDGPU::sub1);
3372 BuildMI(*BB, &I, DL, TII.get(NewOpc), MaskedHi)
3373 .addReg(HiReg)
3374 .addReg(MaskHi);
3375 }
3376
3377 BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
3378 .addReg(MaskedLo)
3379 .addImm(AMDGPU::sub0)
3380 .addReg(MaskedHi)
3381 .addImm(AMDGPU::sub1);
3382 I.eraseFromParent();
3383 return true;
3384}
3385
3386/// Return the register to use for the index value, and the subregister to use
3387/// for the indirectly accessed register.
3388static std::pair<Register, unsigned>
3390 const TargetRegisterClass *SuperRC, Register IdxReg,
3391 unsigned EltSize, GISelValueTracking &ValueTracking) {
3392 Register IdxBaseReg;
3393 int Offset;
3394
3395 std::tie(IdxBaseReg, Offset) =
3396 AMDGPU::getBaseWithConstantOffset(MRI, IdxReg, &ValueTracking);
3397 if (IdxBaseReg == AMDGPU::NoRegister) {
3398 // This will happen if the index is a known constant. This should ordinarily
3399 // be legalized out, but handle it as a register just in case.
3400 assert(Offset == 0);
3401 IdxBaseReg = IdxReg;
3402 }
3403
3404 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(SuperRC, EltSize);
3405
3406 // Skip out of bounds offsets, or else we would end up using an undefined
3407 // register.
3408 if (static_cast<unsigned>(Offset) >= SubRegs.size())
3409 return std::pair(IdxReg, SubRegs[0]);
3410 return std::pair(IdxBaseReg, SubRegs[Offset]);
3411}
3412
3413bool AMDGPUInstructionSelector::selectG_EXTRACT_VECTOR_ELT(
3414 MachineInstr &MI) const {
3415 Register DstReg = MI.getOperand(0).getReg();
3416 Register SrcReg = MI.getOperand(1).getReg();
3417 Register IdxReg = MI.getOperand(2).getReg();
3418
3419 LLT DstTy = MRI->getType(DstReg);
3420 LLT SrcTy = MRI->getType(SrcReg);
3421
3422 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3423 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3424 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3425
3426 // The index must be scalar. If it wasn't RegBankSelect should have moved this
3427 // into a waterfall loop.
3428 if (IdxRB->getID() != AMDGPU::SGPRRegBankID)
3429 return false;
3430
3431 const TargetRegisterClass *SrcRC =
3432 TRI.getRegClassForTypeOnBank(SrcTy, *SrcRB);
3433 const TargetRegisterClass *DstRC =
3434 TRI.getRegClassForTypeOnBank(DstTy, *DstRB);
3435 if (!SrcRC || !DstRC)
3436 return false;
3437 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3438 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3439 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3440 return false;
3441
3442 MachineBasicBlock *BB = MI.getParent();
3443 const DebugLoc &DL = MI.getDebugLoc();
3444 const bool Is64 = DstTy.getSizeInBits() == 64;
3445
3446 unsigned SubReg;
3447 std::tie(IdxReg, SubReg) = computeIndirectRegIndex(
3448 *MRI, TRI, SrcRC, IdxReg, DstTy.getSizeInBits() / 8, *VT);
3449
3450 if (SrcRB->getID() == AMDGPU::SGPRRegBankID) {
3451 if (DstTy.getSizeInBits() != 32 && !Is64)
3452 return false;
3453
3454 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3455 .addReg(IdxReg);
3456
3457 unsigned Opc = Is64 ? AMDGPU::S_MOVRELS_B64 : AMDGPU::S_MOVRELS_B32;
3458 BuildMI(*BB, &MI, DL, TII.get(Opc), DstReg)
3459 .addReg(SrcReg, {}, SubReg)
3460 .addReg(SrcReg, RegState::Implicit);
3461 MI.eraseFromParent();
3462 return true;
3463 }
3464
3465 if (SrcRB->getID() != AMDGPU::VGPRRegBankID || DstTy.getSizeInBits() != 32)
3466 return false;
3467
3468 if (!STI.useVGPRIndexMode()) {
3469 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3470 .addReg(IdxReg);
3471 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::V_MOVRELS_B32_e32), DstReg)
3472 .addReg(SrcReg, {}, SubReg)
3473 .addReg(SrcReg, RegState::Implicit);
3474 MI.eraseFromParent();
3475 return true;
3476 }
3477
3478 const MCInstrDesc &GPRIDXDesc =
3479 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*SrcRC), true);
3480 BuildMI(*BB, MI, DL, GPRIDXDesc, DstReg)
3481 .addReg(SrcReg)
3482 .addReg(IdxReg)
3483 .addImm(SubReg);
3484
3485 MI.eraseFromParent();
3486 return true;
3487}
3488
3489// TODO: Fold insert_vector_elt (extract_vector_elt) into movrelsd
3490bool AMDGPUInstructionSelector::selectG_INSERT_VECTOR_ELT(
3491 MachineInstr &MI) const {
3492 Register DstReg = MI.getOperand(0).getReg();
3493 Register VecReg = MI.getOperand(1).getReg();
3494 Register ValReg = MI.getOperand(2).getReg();
3495 Register IdxReg = MI.getOperand(3).getReg();
3496
3497 LLT VecTy = MRI->getType(DstReg);
3498 LLT ValTy = MRI->getType(ValReg);
3499 unsigned VecSize = VecTy.getSizeInBits();
3500 unsigned ValSize = ValTy.getSizeInBits();
3501
3502 const RegisterBank *VecRB = RBI.getRegBank(VecReg, *MRI, TRI);
3503 const RegisterBank *ValRB = RBI.getRegBank(ValReg, *MRI, TRI);
3504 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3505
3506 assert(VecTy.getElementType() == ValTy);
3507
3508 // The index must be scalar. If it wasn't RegBankSelect should have moved this
3509 // into a waterfall loop.
3510 if (IdxRB->getID() != AMDGPU::SGPRRegBankID)
3511 return false;
3512
3513 const TargetRegisterClass *VecRC =
3514 TRI.getRegClassForTypeOnBank(VecTy, *VecRB);
3515 const TargetRegisterClass *ValRC =
3516 TRI.getRegClassForTypeOnBank(ValTy, *ValRB);
3517
3518 if (!RBI.constrainGenericRegister(VecReg, *VecRC, *MRI) ||
3519 !RBI.constrainGenericRegister(DstReg, *VecRC, *MRI) ||
3520 !RBI.constrainGenericRegister(ValReg, *ValRC, *MRI) ||
3521 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3522 return false;
3523
3524 if (VecRB->getID() == AMDGPU::VGPRRegBankID && ValSize != 32)
3525 return false;
3526
3527 unsigned SubReg;
3528 std::tie(IdxReg, SubReg) =
3529 computeIndirectRegIndex(*MRI, TRI, VecRC, IdxReg, ValSize / 8, *VT);
3530
3531 const bool IndexMode = VecRB->getID() == AMDGPU::VGPRRegBankID &&
3532 STI.useVGPRIndexMode();
3533
3534 MachineBasicBlock *BB = MI.getParent();
3535 const DebugLoc &DL = MI.getDebugLoc();
3536
3537 if (!IndexMode) {
3538 BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3539 .addReg(IdxReg);
3540
3541 const MCInstrDesc &RegWriteOp = TII.getIndirectRegWriteMovRelPseudo(
3542 VecSize, ValSize, VecRB->getID() == AMDGPU::SGPRRegBankID);
3543 BuildMI(*BB, MI, DL, RegWriteOp, DstReg)
3544 .addReg(VecReg)
3545 .addReg(ValReg)
3546 .addImm(SubReg);
3547 MI.eraseFromParent();
3548 return true;
3549 }
3550
3551 const MCInstrDesc &GPRIDXDesc =
3552 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
3553 BuildMI(*BB, MI, DL, GPRIDXDesc, DstReg)
3554 .addReg(VecReg)
3555 .addReg(ValReg)
3556 .addReg(IdxReg)
3557 .addImm(SubReg);
3558
3559 MI.eraseFromParent();
3560 return true;
3561}
3562
3563static bool isAsyncLDSDMA(Intrinsic::ID Intr) {
3564 switch (Intr) {
3565 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
3566 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
3567 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
3568 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
3569 case Intrinsic::amdgcn_load_async_to_lds:
3570 case Intrinsic::amdgcn_global_load_async_lds:
3571 return true;
3572 }
3573 return false;
3574}
3575
3576bool AMDGPUInstructionSelector::selectBufferLoadLds(MachineInstr &MI) const {
3577 if (!Subtarget->hasVMemToLDSLoad())
3578 return false;
3579 unsigned Opc;
3580 unsigned Size = MI.getOperand(3).getImm();
3581 Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID();
3582
3583 // The struct intrinsic variants add one additional operand over raw.
3584 const bool HasVIndex = MI.getNumOperands() == 9;
3585 Register VIndex;
3586 int OpOffset = 0;
3587 if (HasVIndex) {
3588 VIndex = MI.getOperand(4).getReg();
3589 OpOffset = 1;
3590 }
3591
3592 Register VOffset = MI.getOperand(4 + OpOffset).getReg();
3593 std::optional<ValueAndVReg> MaybeVOffset =
3595 const bool HasVOffset = !MaybeVOffset || MaybeVOffset->Value.getZExtValue();
3596
3597 switch (Size) {
3598 default:
3599 return false;
3600 case 1:
3601 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
3602 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
3603 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
3604 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
3605 break;
3606 case 2:
3607 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
3608 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
3609 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
3610 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
3611 break;
3612 case 4:
3613 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
3614 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
3615 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
3616 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
3617 break;
3618 case 12:
3619 if (!Subtarget->hasLDSLoadB96_B128())
3620 return false;
3621
3622 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
3623 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
3624 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
3625 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
3626 break;
3627 case 16:
3628 if (!Subtarget->hasLDSLoadB96_B128())
3629 return false;
3630
3631 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
3632 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
3633 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
3634 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
3635 break;
3636 }
3637
3638 MachineBasicBlock *MBB = MI.getParent();
3639 const DebugLoc &DL = MI.getDebugLoc();
3640 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3641 .add(MI.getOperand(2));
3642
3643 auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc));
3644
3645 if (HasVIndex && HasVOffset) {
3646 Register IdxReg = MRI->createVirtualRegister(TRI.getVGPR64Class());
3647 BuildMI(*MBB, &*MIB, DL, TII.get(AMDGPU::REG_SEQUENCE), IdxReg)
3648 .addReg(VIndex)
3649 .addImm(AMDGPU::sub0)
3650 .addReg(VOffset)
3651 .addImm(AMDGPU::sub1);
3652
3653 MIB.addReg(IdxReg);
3654 } else if (HasVIndex) {
3655 MIB.addReg(VIndex);
3656 } else if (HasVOffset) {
3657 MIB.addReg(VOffset);
3658 }
3659
3660 MIB.add(MI.getOperand(1)); // rsrc
3661 MIB.add(MI.getOperand(5 + OpOffset)); // soffset
3662 MIB.add(MI.getOperand(6 + OpOffset)); // imm offset
3663 bool IsGFX12Plus = AMDGPU::isGFX12Plus(STI);
3664 unsigned Aux = MI.getOperand(7 + OpOffset).getImm();
3665 MIB.addImm(Aux & (IsGFX12Plus ? AMDGPU::CPol::ALL
3666 : AMDGPU::CPol::ALL_pregfx12)); // cpol
3667 MIB.addImm(
3668 Aux & (IsGFX12Plus ? AMDGPU::CPol::SWZ : AMDGPU::CPol::SWZ_pregfx12)
3669 ? 1
3670 : 0); // swz
3671 MIB.addImm(isAsyncLDSDMA(IntrinsicID));
3672
3673 MachineMemOperand *LoadMMO = *MI.memoperands_begin();
3674 // Don't set the offset value here because the pointer points to the base of
3675 // the buffer.
3676 MachinePointerInfo LoadPtrI = LoadMMO->getPointerInfo();
3677
3678 MachinePointerInfo StorePtrI = LoadPtrI;
3679 LoadPtrI.V = PoisonValue::get(PointerType::get(MF->getFunction().getContext(),
3683
3684 auto F = LoadMMO->getFlags() &
3686 LoadMMO = MF->getMachineMemOperand(LoadPtrI, F | MachineMemOperand::MOLoad,
3687 Size, LoadMMO->getBaseAlign());
3688
3689 MachineMemOperand *StoreMMO =
3690 MF->getMachineMemOperand(StorePtrI, F | MachineMemOperand::MOStore,
3691 sizeof(int32_t), LoadMMO->getBaseAlign());
3692
3693 MIB.setMemRefs({LoadMMO, StoreMMO});
3694
3695 MI.eraseFromParent();
3696 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
3697 return true;
3698}
3699
3700/// Match a zero extend from a 32-bit value to 64-bits.
3701Register AMDGPUInstructionSelector::matchZeroExtendFromS32(Register Reg) const {
3702 Register ZExtSrc;
3703 if (mi_match(Reg, *MRI, m_GZExt(m_Reg(ZExtSrc))))
3704 return MRI->getType(ZExtSrc) == LLT::scalar(32) ? ZExtSrc : Register();
3705
3706 // Match legalized form %zext = G_MERGE_VALUES (s32 %x), (s32 0)
3707 const MachineInstr *Def = getDefIgnoringCopies(Reg, *MRI);
3708 if (Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3709 return Register();
3710
3711 assert(Def->getNumOperands() == 3 &&
3712 MRI->getType(Def->getOperand(0).getReg()) == LLT::scalar(64));
3713 if (mi_match(Def->getOperand(2).getReg(), *MRI, m_ZeroInt())) {
3714 return Def->getOperand(1).getReg();
3715 }
3716
3717 return Register();
3718}
3719
3720/// Match a sign extend from a 32-bit value to 64-bits.
3721Register AMDGPUInstructionSelector::matchSignExtendFromS32(Register Reg) const {
3722 Register SExtSrc;
3723 if (mi_match(Reg, *MRI, m_GSExt(m_Reg(SExtSrc))))
3724 return MRI->getType(SExtSrc) == LLT::scalar(32) ? SExtSrc : Register();
3725
3726 // Match legalized form %sext = G_MERGE_VALUES (s32 %x), G_ASHR((S32 %x, 31))
3727 const MachineInstr *Def = getDefIgnoringCopies(Reg, *MRI);
3728 if (Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3729 return Register();
3730
3731 assert(Def->getNumOperands() == 3 &&
3732 MRI->getType(Def->getOperand(0).getReg()) == LLT::scalar(64));
3733 if (mi_match(Def->getOperand(2).getReg(), *MRI,
3734 m_GAShr(m_SpecificReg(Def->getOperand(1).getReg()),
3735 m_SpecificICst(31))))
3736 return Def->getOperand(1).getReg();
3737
3738 if (VT->signBitIsZero(Reg))
3739 return matchZeroExtendFromS32(Reg);
3740
3741 return Register();
3742}
3743
3744/// Match a zero extend from a 32-bit value to 64-bits, or \p Reg itself if it
3745/// is 32-bit.
3747AMDGPUInstructionSelector::matchZeroExtendFromS32OrS32(Register Reg) const {
3748 return MRI->getType(Reg) == LLT::scalar(32) ? Reg
3749 : matchZeroExtendFromS32(Reg);
3750}
3751
3752/// Match a sign extend from a 32-bit value to 64-bits, or \p Reg itself if it
3753/// is 32-bit.
3755AMDGPUInstructionSelector::matchSignExtendFromS32OrS32(Register Reg) const {
3756 return MRI->getType(Reg) == LLT::scalar(32) ? Reg
3757 : matchSignExtendFromS32(Reg);
3758}
3759
3761AMDGPUInstructionSelector::matchExtendFromS32OrS32(Register Reg,
3762 bool IsSigned) const {
3763 if (IsSigned)
3764 return matchSignExtendFromS32OrS32(Reg);
3765
3766 return matchZeroExtendFromS32OrS32(Reg);
3767}
3768
3769Register AMDGPUInstructionSelector::matchAnyExtendFromS32(Register Reg) const {
3770 Register AnyExtSrc;
3771 if (mi_match(Reg, *MRI, m_GAnyExt(m_Reg(AnyExtSrc))))
3772 return MRI->getType(AnyExtSrc) == LLT::scalar(32) ? AnyExtSrc : Register();
3773
3774 // Match legalized form %zext = G_MERGE_VALUES (s32 %x), (s32 G_IMPLICIT_DEF)
3775 const MachineInstr *Def = getDefIgnoringCopies(Reg, *MRI);
3776 if (Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3777 return Register();
3778
3779 assert(Def->getNumOperands() == 3 &&
3780 MRI->getType(Def->getOperand(0).getReg()) == LLT::scalar(64));
3781
3782 if (mi_match(Def->getOperand(2).getReg(), *MRI, m_GImplicitDef()))
3783 return Def->getOperand(1).getReg();
3784
3785 return Register();
3786}
3787
3788bool AMDGPUInstructionSelector::selectGlobalLoadLds(MachineInstr &MI) const{
3789 if (!Subtarget->hasVMemToLDSLoad())
3790 return false;
3791
3792 unsigned Opc;
3793 unsigned Size = MI.getOperand(3).getImm();
3794 Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID();
3795
3796 switch (Size) {
3797 default:
3798 return false;
3799 case 1:
3800 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
3801 break;
3802 case 2:
3803 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
3804 break;
3805 case 4:
3806 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
3807 break;
3808 case 12:
3809 if (!Subtarget->hasLDSLoadB96_B128())
3810 return false;
3811 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
3812 break;
3813 case 16:
3814 if (!Subtarget->hasLDSLoadB96_B128())
3815 return false;
3816 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
3817 break;
3818 }
3819
3820 MachineBasicBlock *MBB = MI.getParent();
3821 const DebugLoc &DL = MI.getDebugLoc();
3822 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3823 .add(MI.getOperand(2));
3824
3825 Register Addr = MI.getOperand(1).getReg();
3826 Register VOffset;
3827 // Try to split SAddr and VOffset. Global and LDS pointers share the same
3828 // immediate offset, so we cannot use a regular SelectGlobalSAddr().
3829 if (!isSGPR(Addr)) {
3830 auto AddrDef = getDefSrcRegIgnoringCopies(Addr, *MRI);
3831 if (isSGPR(AddrDef->Reg)) {
3832 Addr = AddrDef->Reg;
3833 } else if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
3834 Register SAddr =
3835 getSrcRegIgnoringCopies(AddrDef->MI->getOperand(1).getReg(), *MRI);
3836 if (isSGPR(SAddr)) {
3837 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
3838 if (Register Off = matchZeroExtendFromS32(PtrBaseOffset)) {
3839 Addr = SAddr;
3840 VOffset = Off;
3841 }
3842 }
3843 }
3844 }
3845
3846 if (isSGPR(Addr)) {
3848 if (!VOffset) {
3849 VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
3850 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
3851 .addImm(0);
3852 }
3853 }
3854
3855 auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc))
3856 .addReg(Addr);
3857
3858 if (isSGPR(Addr))
3859 MIB.addReg(VOffset);
3860
3861 MIB.add(MI.getOperand(4)); // offset
3862
3863 unsigned Aux = MI.getOperand(5).getImm();
3864 MIB.addImm(Aux & ~AMDGPU::CPol::VIRTUAL_BITS); // cpol
3865 MIB.addImm(isAsyncLDSDMA(IntrinsicID));
3866
3867 MachineMemOperand *LoadMMO = *MI.memoperands_begin();
3868 MachinePointerInfo LoadPtrI = LoadMMO->getPointerInfo();
3869 LoadPtrI.Offset = MI.getOperand(4).getImm();
3870 MachinePointerInfo StorePtrI = LoadPtrI;
3871 LoadPtrI.V = PoisonValue::get(PointerType::get(MF->getFunction().getContext(),
3875 auto F = LoadMMO->getFlags() &
3877 LoadMMO = MF->getMachineMemOperand(LoadPtrI, F | MachineMemOperand::MOLoad,
3878 Size, LoadMMO->getBaseAlign());
3879 MachineMemOperand *StoreMMO =
3880 MF->getMachineMemOperand(StorePtrI, F | MachineMemOperand::MOStore,
3881 sizeof(int32_t), Align(4));
3882
3883 MIB.setMemRefs({LoadMMO, StoreMMO});
3884
3885 MI.eraseFromParent();
3886 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
3887 return true;
3888}
3889
3890bool AMDGPUInstructionSelector::selectTensorLoadStore(MachineInstr &MI,
3891 Intrinsic::ID IID) const {
3892 bool IsLoad = IID == Intrinsic::amdgcn_tensor_load_to_lds;
3893 unsigned Opc =
3894 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3895 int NumGroups = 4;
3896
3897 // A lamda function to check whether an operand is a vector of all 0s.
3898 const auto isAllZeros = [&](MachineOperand &Opnd) {
3899 const MachineInstr *DefMI = MRI->getVRegDef(Opnd.getReg());
3900 if (!DefMI)
3901 return false;
3902 return llvm::isBuildVectorAllZeros(*DefMI, *MRI, true);
3903 };
3904
3905 // Use _D2 version if both group 2 and 3 are zero-initialized.
3906 if (isAllZeros(MI.getOperand(3)) && isAllZeros(MI.getOperand(4))) {
3907 NumGroups = 2;
3908 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3909 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3910 }
3911
3912 // TODO: Handle the fifth group: MI.getOpetand(5), which is silently ignored
3913 // for now because all existing targets only support up to 4 groups.
3914 MachineBasicBlock *MBB = MI.getParent();
3915 auto MIB = BuildMI(*MBB, &MI, MI.getDebugLoc(), TII.get(Opc))
3916 .add(MI.getOperand(1)) // D# group 0
3917 .add(MI.getOperand(2)); // D# group 1
3918
3919 if (NumGroups >= 4) { // Has at least 4 groups
3920 MIB.add(MI.getOperand(3)) // D# group 2
3921 .add(MI.getOperand(4)); // D# group 3
3922 }
3923
3924 MIB.addImm(0) // r128
3925 .add(MI.getOperand(6)); // cpol
3926
3927 MI.eraseFromParent();
3928 return true;
3929}
3930
3931bool AMDGPUInstructionSelector::selectBVHIntersectRayIntrinsic(
3932 MachineInstr &MI) const {
3933 unsigned OpcodeOpIdx =
3934 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY ? 1 : 3;
3935 MI.setDesc(TII.get(MI.getOperand(OpcodeOpIdx).getImm()));
3936 MI.removeOperand(OpcodeOpIdx);
3937 MI.addImplicitDefUseOperands(*MI.getMF());
3938 constrainSelectedInstRegOperands(MI, TII, TRI, RBI);
3939 return true;
3940}
3941
3942// FIXME: This should be removed and let the patterns select. We just need the
3943// AGPR/VGPR combination versions.
3944bool AMDGPUInstructionSelector::selectSMFMACIntrin(MachineInstr &MI) const {
3945 unsigned Opc;
3946 switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
3947 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
3948 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_F16_e64;
3949 break;
3950 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
3951 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_F16_e64;
3952 break;
3953 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
3954 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_BF16_e64;
3955 break;
3956 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
3957 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_BF16_e64;
3958 break;
3959 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
3960 Opc = AMDGPU::V_SMFMAC_I32_16X16X64_I8_e64;
3961 break;
3962 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
3963 Opc = AMDGPU::V_SMFMAC_I32_32X32X32_I8_e64;
3964 break;
3965 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
3966 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_BF8_e64;
3967 break;
3968 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
3969 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_FP8_e64;
3970 break;
3971 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
3972 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_BF8_e64;
3973 break;
3974 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
3975 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_FP8_e64;
3976 break;
3977 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
3978 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_BF8_e64;
3979 break;
3980 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
3981 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_FP8_e64;
3982 break;
3983 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
3984 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_BF8_e64;
3985 break;
3986 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
3987 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_FP8_e64;
3988 break;
3989 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
3990 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_F16_e64;
3991 break;
3992 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
3993 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_F16_e64;
3994 break;
3995 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
3996 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF16_e64;
3997 break;
3998 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
3999 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF16_e64;
4000 break;
4001 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
4002 Opc = AMDGPU::V_SMFMAC_I32_16X16X128_I8_e64;
4003 break;
4004 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
4005 Opc = AMDGPU::V_SMFMAC_I32_32X32X64_I8_e64;
4006 break;
4007 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
4008 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_BF8_e64;
4009 break;
4010 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
4011 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_FP8_e64;
4012 break;
4013 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
4014 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_BF8_e64;
4015 break;
4016 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
4017 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_FP8_e64;
4018 break;
4019 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
4020 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_BF8_e64;
4021 break;
4022 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
4023 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_FP8_e64;
4024 break;
4025 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
4026 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_BF8_e64;
4027 break;
4028 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
4029 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_FP8_e64;
4030 break;
4031 default:
4032 llvm_unreachable("unhandled smfmac intrinsic");
4033 }
4034
4035 auto VDst_In = MI.getOperand(4);
4036
4037 MI.setDesc(TII.get(Opc));
4038 MI.removeOperand(4); // VDst_In
4039 MI.removeOperand(1); // Intrinsic ID
4040 MI.addOperand(VDst_In); // Readd VDst_In to the end
4041 MI.addImplicitDefUseOperands(*MI.getMF());
4042 const MCInstrDesc &MCID = MI.getDesc();
4043 if (MCID.getOperandConstraint(0, MCOI::EARLY_CLOBBER) != -1) {
4044 MI.getOperand(0).setIsEarlyClobber(true);
4045 }
4046 return true;
4047}
4048
4049bool AMDGPUInstructionSelector::selectPermlaneSwapIntrin(
4050 MachineInstr &MI, Intrinsic::ID IntrID) const {
4051 if (IntrID == Intrinsic::amdgcn_permlane16_swap &&
4052 !Subtarget->hasPermlane16Swap())
4053 return false;
4054 if (IntrID == Intrinsic::amdgcn_permlane32_swap &&
4055 !Subtarget->hasPermlane32Swap())
4056 return false;
4057
4058 unsigned Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
4059 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
4060 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
4061
4062 MI.removeOperand(2);
4063 MI.setDesc(TII.get(Opcode));
4064 MI.addOperand(*MF, MachineOperand::CreateReg(AMDGPU::EXEC, false, true));
4065
4066 MachineOperand &FI = MI.getOperand(4);
4068
4069 constrainSelectedInstRegOperands(MI, TII, TRI, RBI);
4070 return true;
4071}
4072
4073bool AMDGPUInstructionSelector::selectWaveAddress(MachineInstr &MI) const {
4074 Register DstReg = MI.getOperand(0).getReg();
4075 Register SrcReg = MI.getOperand(1).getReg();
4076 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4077 const bool IsVALU = DstRB->getID() == AMDGPU::VGPRRegBankID;
4078 MachineBasicBlock *MBB = MI.getParent();
4079 const DebugLoc &DL = MI.getDebugLoc();
4080
4081 if (IsVALU) {
4082 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_LSHRREV_B32_e64), DstReg)
4083 .addImm(Subtarget->getWavefrontSizeLog2())
4084 .addReg(SrcReg);
4085 } else {
4086 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::S_LSHR_B32), DstReg)
4087 .addReg(SrcReg)
4088 .addImm(Subtarget->getWavefrontSizeLog2())
4089 .setOperandDead(3); // Dead scc
4090 }
4091
4092 const TargetRegisterClass &RC =
4093 IsVALU ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
4094 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
4095 return false;
4096
4097 MI.eraseFromParent();
4098 return true;
4099}
4100
4101bool AMDGPUInstructionSelector::selectWaveShuffleIntrin(
4102 MachineInstr &MI) const {
4103 assert(MI.getNumOperands() == 4);
4104 MachineBasicBlock *MBB = MI.getParent();
4105 const DebugLoc &DL = MI.getDebugLoc();
4106
4107 Register DstReg = MI.getOperand(0).getReg();
4108 Register ValReg = MI.getOperand(2).getReg();
4109 Register IdxReg = MI.getOperand(3).getReg();
4110
4111 const LLT DstTy = MRI->getType(DstReg);
4112 unsigned DstSize = DstTy.getSizeInBits();
4113 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4114 const TargetRegisterClass *DstRC =
4115 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
4116
4117 if (DstTy != LLT::scalar(32))
4118 return false;
4119
4120 if (!Subtarget->supportsBPermute())
4121 return false;
4122
4123 // If we can bpermute across the whole wave, then just do that
4124 if (Subtarget->supportsWaveWideBPermute()) {
4125 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4126 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4127 .addImm(2)
4128 .addReg(IdxReg);
4129
4130 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::DS_BPERMUTE_B32), DstReg)
4131 .addReg(ShiftIdxReg)
4132 .addReg(ValReg)
4133 .addImm(0);
4134 } else {
4135 // Otherwise, we need to make use of whole wave mode
4136 assert(Subtarget->isWave64());
4137
4138 // Set inactive lanes to poison
4139 Register UndefValReg =
4140 MRI->createVirtualRegister(TRI.getRegClass(AMDGPU::SReg_32RegClassID));
4141 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefValReg);
4142
4143 Register UndefExecReg = MRI->createVirtualRegister(
4144 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4145 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefExecReg);
4146
4147 Register PoisonValReg = MRI->createVirtualRegister(DstRC);
4148 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonValReg)
4149 .addImm(0)
4150 .addReg(ValReg)
4151 .addImm(0)
4152 .addReg(UndefValReg)
4153 .addReg(UndefExecReg);
4154
4155 // ds_bpermute requires index to be multiplied by 4
4156 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4157 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4158 .addImm(2)
4159 .addReg(IdxReg);
4160
4161 Register PoisonIdxReg = MRI->createVirtualRegister(DstRC);
4162 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonIdxReg)
4163 .addImm(0)
4164 .addReg(ShiftIdxReg)
4165 .addImm(0)
4166 .addReg(UndefValReg)
4167 .addReg(UndefExecReg);
4168
4169 Register PoisonUnshiftedIdxReg = MRI->createVirtualRegister(DstRC);
4170 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_SET_INACTIVE_B32),
4171 PoisonUnshiftedIdxReg)
4172 .addImm(0)
4173 .addReg(IdxReg)
4174 .addImm(0)
4175 .addReg(UndefValReg)
4176 .addReg(UndefExecReg);
4177
4178 // Get permutation of each half, then we'll select which one to use
4179 Register SameSidePermReg = MRI->createVirtualRegister(DstRC);
4180 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::DS_BPERMUTE_B32), SameSidePermReg)
4181 .addReg(PoisonIdxReg)
4182 .addReg(PoisonValReg)
4183 .addImm(0);
4184
4185 Register SwappedValReg = MRI->createVirtualRegister(DstRC);
4186 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_PERMLANE64_B32), SwappedValReg)
4187 .addReg(PoisonValReg);
4188
4189 Register OppSidePermReg = MRI->createVirtualRegister(DstRC);
4190 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::DS_BPERMUTE_B32), OppSidePermReg)
4191 .addReg(PoisonIdxReg)
4192 .addReg(SwappedValReg)
4193 .addImm(0);
4194
4195 Register WWMSwapPermReg = MRI->createVirtualRegister(DstRC);
4196 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::STRICT_WWM), WWMSwapPermReg)
4197 .addReg(OppSidePermReg);
4198
4199 // Select which side to take the permute from
4200 // We can get away with only using mbcnt_lo here since we're only
4201 // trying to detect which side of 32 each lane is on, and mbcnt_lo
4202 // returns 32 for lanes 32-63.
4203 Register ThreadIDReg = MRI->createVirtualRegister(DstRC);
4204 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_MBCNT_LO_U32_B32_e64), ThreadIDReg)
4205 .addImm(-1)
4206 .addImm(0);
4207
4208 Register XORReg = MRI->createVirtualRegister(DstRC);
4209 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_XOR_B32_e64), XORReg)
4210 .addReg(ThreadIDReg)
4211 .addReg(PoisonUnshiftedIdxReg);
4212
4213 Register ANDReg = MRI->createVirtualRegister(DstRC);
4214 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_AND_B32_e64), ANDReg)
4215 .addReg(XORReg)
4216 .addImm(32);
4217
4218 Register CompareReg = MRI->createVirtualRegister(
4219 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4220 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), CompareReg)
4221 .addReg(ANDReg)
4222 .addImm(0);
4223
4224 // Finally do the selection
4225 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
4226 .addImm(0)
4227 .addReg(WWMSwapPermReg)
4228 .addImm(0)
4229 .addReg(SameSidePermReg)
4230 .addReg(CompareReg);
4231 }
4232
4233 MI.eraseFromParent();
4234 return true;
4235}
4236
4237// Match BITOP3 operation and return a number of matched instructions plus
4238// truth table.
4239static std::pair<unsigned, uint8_t> BitOp3_Op(Register R,
4241 const MachineRegisterInfo &MRI) {
4242 unsigned NumOpcodes = 0;
4243 uint8_t LHSBits, RHSBits;
4244
4245 auto getOperandBits = [&Src, R, &MRI](Register Op, uint8_t &Bits) -> bool {
4246 // Define truth table given Src0, Src1, Src2 bits permutations:
4247 // 0 0 0
4248 // 0 0 1
4249 // 0 1 0
4250 // 0 1 1
4251 // 1 0 0
4252 // 1 0 1
4253 // 1 1 0
4254 // 1 1 1
4255 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4256
4257 if (mi_match(Op, MRI, m_AllOnesInt())) {
4258 Bits = 0xff;
4259 return true;
4260 }
4261 if (mi_match(Op, MRI, m_ZeroInt())) {
4262 Bits = 0;
4263 return true;
4264 }
4265
4266 for (unsigned I = 0; I < Src.size(); ++I) {
4267 // Try to find existing reused operand
4268 if (Src[I] == Op) {
4269 Bits = SrcBits[I];
4270 return true;
4271 }
4272 // Try to replace parent operator
4273 if (Src[I] == R) {
4274 Bits = SrcBits[I];
4275 Src[I] = Op;
4276 return true;
4277 }
4278 }
4279
4280 if (Src.size() == 3) {
4281 // No room left for operands. Try one last time, there can be a 'not' of
4282 // one of our source operands. In this case we can compute the bits
4283 // without growing Src vector.
4284 Register LHS;
4285 if (mi_match(Op, MRI, m_Not(m_Reg(LHS)))) {
4287 for (unsigned I = 0; I < Src.size(); ++I) {
4288 if (Src[I] == LHS) {
4289 Bits = ~SrcBits[I];
4290 return true;
4291 }
4292 }
4293 }
4294
4295 return false;
4296 }
4297
4298 Bits = SrcBits[Src.size()];
4299 Src.push_back(Op);
4300 return true;
4301 };
4302
4303 MachineInstr *MI = MRI.getVRegDef(R);
4304 switch (MI->getOpcode()) {
4305 case TargetOpcode::G_AND:
4306 case TargetOpcode::G_OR:
4307 case TargetOpcode::G_XOR: {
4308 Register LHS = getSrcRegIgnoringCopies(MI->getOperand(1).getReg(), MRI);
4309 Register RHS = getSrcRegIgnoringCopies(MI->getOperand(2).getReg(), MRI);
4310
4311 SmallVector<Register, 3> Backup(Src.begin(), Src.end());
4312 if (!getOperandBits(LHS, LHSBits) ||
4313 !getOperandBits(RHS, RHSBits)) {
4314 Src = std::move(Backup);
4315 return std::make_pair(0, 0);
4316 }
4317
4318 // Recursion is naturally limited by the size of the operand vector.
4319 //
4320 // When LHS and RHS share a common sub-expression, one side's recursion
4321 // may decompose that sub-expression and replace the Src slot the other
4322 // side occupies with sub-operands via the "replace parent" path in
4323 // getOperandBits. The other side's cached bit-pattern then refers to a
4324 // slot whose contents changed, producing a wrong truth table.
4325 //
4326 // We detect this in three ways:
4327 // (A) If LHS recursed, its truth table is valid against the Src state
4328 // when LHS recursion completed (SrcAfterLHS). If RHS recursion
4329 // then mutates a Src slot that LHSBits depends on, LHSBits is
4330 // stale.
4331 // (B) If RHS did not recurse, RHSBits came from getOperandBits and
4332 // refers to a specific Src slot. If that slot's contents changed
4333 // (by either recursion), RHSBits is stale.
4334 // (C) Symmetrically for LHS if it did not recurse.
4335 SmallVector<Register, 3> SrcBeforeRecurse(Src.begin(), Src.end());
4336 uint8_t LHSBitsOrig = LHSBits;
4337 uint8_t RHSBitsOrig = RHSBits;
4338
4339 auto LHSOp = BitOp3_Op(LHS, Src, MRI);
4340 if (LHSOp.first) {
4341 NumOpcodes += LHSOp.first;
4342 LHSBits = LHSOp.second;
4343 }
4344
4345 SmallVector<Register, 3> SrcAfterLHS(Src.begin(), Src.end());
4346
4347 auto RHSOp = BitOp3_Op(RHS, Src, MRI);
4348 if (RHSOp.first) {
4349 NumOpcodes += RHSOp.first;
4350 RHSBits = RHSOp.second;
4351 }
4352
4353 // dependsOnSlot: true iff the truth table TT varies with slot Slot.
4354 auto dependsOnSlot = [](uint8_t TT, int Slot) -> bool {
4355 if (Slot < 0 || Slot > 2)
4356 return false;
4357 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4358 const int Shifts[3] = {4, 2, 1};
4359 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4360 };
4361
4362 // findSlot: locate the Src slot a getOperandBits result depends on,
4363 // including negated (NOT) patterns that getOperandBits resolves via
4364 // the ~SrcBits[I] shortcut.
4365 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4366 auto findSlot = [&](uint8_t Bits, Register Op,
4367 const SmallVectorImpl<Register> &S) -> int {
4368 Register NegatedInner;
4369 bool IsNegationOp = mi_match(Op, MRI, m_Not(m_Reg(NegatedInner)));
4370 if (IsNegationOp)
4371 NegatedInner = getSrcRegIgnoringCopies(NegatedInner, MRI);
4372 for (int I = 0; I < (int)S.size(); I++) {
4373 if (Bits == SrcBitsConst[I] && S[I] == Op)
4374 return I;
4375 if (IsNegationOp && Bits == (uint8_t)~SrcBitsConst[I] &&
4376 S[I] == NegatedInner)
4377 return I;
4378 }
4379 return -1;
4380 };
4381
4382 bool Stale = false;
4383
4384 // (A) LHS recursed: its truth table is against SrcAfterLHS.
4385 // Check if RHS recursion mutated a slot that LHSBits uses.
4386 if (LHSOp.first) {
4387 for (int I = 0; I < (int)SrcAfterLHS.size() && I < 3; I++) {
4388 if (I < (int)Src.size() && Src[I] != SrcAfterLHS[I] &&
4389 dependsOnSlot(LHSBits, I)) {
4390 Stale = true;
4391 break;
4392 }
4393 }
4394 }
4395
4396 // (B) RHS did not recurse: RHSBits from getOperandBits is against
4397 // SrcBeforeRecurse. Check if that slot was mutated since then.
4398 if (!Stale && !RHSOp.first) {
4399 int Slot = findSlot(RHSBitsOrig, RHS, SrcBeforeRecurse);
4400 if (Slot >= 0 &&
4401 (Slot >= (int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4402 Stale = true;
4403 }
4404
4405 // (C) LHS did not recurse: LHSBits from getOperandBits is against
4406 // SrcBeforeRecurse. Check if that slot was mutated since then.
4407 if (!Stale && !LHSOp.first) {
4408 int Slot = findSlot(LHSBitsOrig, LHS, SrcBeforeRecurse);
4409 if (Slot >= 0 &&
4410 (Slot >= (int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4411 Stale = true;
4412 }
4413
4414 if (Stale) {
4415 Src = std::move(SrcBeforeRecurse);
4416 LHSBits = LHSBitsOrig;
4417 RHSBits = RHSBitsOrig;
4418 NumOpcodes = 0;
4419 }
4420 break;
4421 }
4422 default:
4423 return std::make_pair(0, 0);
4424 }
4425
4426 uint8_t TTbl;
4427 switch (MI->getOpcode()) {
4428 case TargetOpcode::G_AND:
4429 TTbl = LHSBits & RHSBits;
4430 break;
4431 case TargetOpcode::G_OR:
4432 TTbl = LHSBits | RHSBits;
4433 break;
4434 case TargetOpcode::G_XOR:
4435 TTbl = LHSBits ^ RHSBits;
4436 break;
4437 default:
4438 break;
4439 }
4440
4441 return std::make_pair(NumOpcodes + 1, TTbl);
4442}
4443
4444bool AMDGPUInstructionSelector::selectBITOP3(MachineInstr &MI) const {
4445 if (!Subtarget->hasBitOp3Insts())
4446 return false;
4447
4448 Register DstReg = MI.getOperand(0).getReg();
4449 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4450 const bool IsVALU = DstRB->getID() == AMDGPU::VGPRRegBankID;
4451 if (!IsVALU)
4452 return false;
4453
4455 uint8_t TTbl;
4456 unsigned NumOpcodes;
4457
4458 std::tie(NumOpcodes, TTbl) = BitOp3_Op(DstReg, Src, *MRI);
4459
4460 // Src.empty() case can happen if all operands are all zero or all ones.
4461 // Normally it shall be optimized out before reaching this.
4462 if (NumOpcodes < 2 || Src.empty())
4463 return false;
4464
4465 // RegBankSelect splits wider VALU logic ops and widens 1-bit ones, so only
4466 // 16 and 32 bit types reach here. Note that <2 x i16> is 32 bits wide.
4467 unsigned Size = MRI->getType(DstReg).getSizeInBits();
4468 assert((Size == 16 || Size == 32) && "unexpected VALU logic op size");
4469 const bool IsB32 = Size == 32;
4470 if (NumOpcodes == 2 && IsB32) {
4471 // Avoid using BITOP3 for OR3, XOR3, AND_OR. This is not faster but makes
4472 // asm more readable. This cannot be modeled with AddedComplexity because
4473 // selector does not know how many operations did we match.
4474 if (mi_match(MI, *MRI, m_GXor(m_GXor(m_Reg(), m_Reg()), m_Reg())) ||
4475 mi_match(MI, *MRI, m_GOr(m_GOr(m_Reg(), m_Reg()), m_Reg())) ||
4476 mi_match(MI, *MRI, m_GOr(m_GAnd(m_Reg(), m_Reg()), m_Reg())))
4477 return false;
4478 } else if (NumOpcodes < 4) {
4479 // For a uniform case threshold should be higher to account for moves
4480 // between VGPRs and SGPRs. It needs one operand in a VGPR, rest two can be
4481 // in SGPRs and a readtfirstlane after.
4482 return false;
4483 }
4484
4485 unsigned Opc = IsB32 ? AMDGPU::V_BITOP3_B32_e64 : AMDGPU::V_BITOP3_B16_e64;
4486 if (!IsB32 && STI.hasTrue16BitInsts())
4487 Opc = STI.useRealTrue16Insts() ? AMDGPU::V_BITOP3_B16_gfx1250_t16_e64
4488 : AMDGPU::V_BITOP3_B16_gfx1250_fake16_e64;
4489 unsigned CBL = STI.getConstantBusLimit(Opc);
4490 MachineBasicBlock *MBB = MI.getParent();
4491 const DebugLoc &DL = MI.getDebugLoc();
4492
4493 for (unsigned I = 0; I < Src.size(); ++I) {
4494 const RegisterBank *RB = RBI.getRegBank(Src[I], *MRI, TRI);
4495 if (RB->getID() != AMDGPU::SGPRRegBankID)
4496 continue;
4497 if (CBL > 0) {
4498 --CBL;
4499 continue;
4500 }
4501 Register NewReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4502 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::COPY), NewReg)
4503 .addReg(Src[I]);
4504 Src[I] = NewReg;
4505 }
4506
4507 // Last operand can be ignored, turning a ternary operation into a binary.
4508 // For example: (~a & b & c) | (~a & b & ~c) -> (~a & b). We can replace
4509 // 'c' with 'a' here without changing the answer. In some pathological
4510 // cases it should be possible to get an operation with a single operand
4511 // too if optimizer would not catch it.
4512 while (Src.size() < 3)
4513 Src.push_back(Src[0]);
4514
4515 auto MIB = BuildMI(*MBB, MI, DL, TII.get(Opc), DstReg);
4516 if (!IsB32)
4517 MIB.addImm(0); // src_mod0
4518 MIB.addReg(Src[0]);
4519 if (!IsB32)
4520 MIB.addImm(0); // src_mod1
4521 MIB.addReg(Src[1]);
4522 if (!IsB32)
4523 MIB.addImm(0); // src_mod2
4524 MIB.addReg(Src[2])
4525 .addImm(TTbl);
4526 if (!IsB32)
4527 MIB.addImm(0); // op_sel
4528
4529 constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
4530 MI.eraseFromParent();
4531
4532 return true;
4533}
4534
4535bool AMDGPUInstructionSelector::selectStackRestore(MachineInstr &MI) const {
4536 Register SrcReg = MI.getOperand(0).getReg();
4537 if (!RBI.constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, *MRI))
4538 return false;
4539
4540 MachineInstr *DefMI = MRI->getVRegDef(SrcReg);
4541 Register SP =
4542 Subtarget->getTargetLowering()->getStackPointerRegisterToSaveRestore();
4543 Register WaveAddr = getWaveAddress(DefMI);
4544 MachineBasicBlock *MBB = MI.getParent();
4545 const DebugLoc &DL = MI.getDebugLoc();
4546
4547 if (!WaveAddr) {
4548 WaveAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
4549 BuildMI(*MBB, MI, DL, TII.get(AMDGPU::S_LSHR_B32), WaveAddr)
4550 .addReg(SrcReg)
4551 .addImm(Subtarget->getWavefrontSizeLog2())
4552 .setOperandDead(3); // Dead scc
4553 }
4554
4555 BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), SP)
4556 .addReg(WaveAddr);
4557
4558 MI.eraseFromParent();
4559 return true;
4560}
4561
4563
4564 if (!I.isPreISelOpcode()) {
4565 if (I.isCopy())
4566 return selectCOPY(I);
4567 return true;
4568 }
4569
4570 switch (I.getOpcode()) {
4571 case TargetOpcode::G_AND:
4572 case TargetOpcode::G_OR:
4573 case TargetOpcode::G_XOR:
4574 if (selectBITOP3(I))
4575 return true;
4576 if (selectImpl(I, *CoverageInfo))
4577 return true;
4578 return selectG_AND_OR_XOR(I);
4579 case TargetOpcode::G_ADD:
4580 case TargetOpcode::G_SUB:
4581 case TargetOpcode::G_PTR_ADD:
4582 if (selectImpl(I, *CoverageInfo))
4583 return true;
4584 return selectG_ADD_SUB(I);
4585 case TargetOpcode::G_UADDO:
4586 case TargetOpcode::G_USUBO:
4587 case TargetOpcode::G_UADDE:
4588 case TargetOpcode::G_USUBE:
4589 return selectG_UADDO_USUBO_UADDE_USUBE(I);
4590 case AMDGPU::G_AMDGPU_MAD_U64_U32:
4591 case AMDGPU::G_AMDGPU_MAD_I64_I32:
4592 return selectG_AMDGPU_MAD_64_32(I);
4593 case TargetOpcode::G_INTTOPTR:
4594 case TargetOpcode::G_BITCAST:
4595 case TargetOpcode::G_PTRTOINT:
4596 case TargetOpcode::G_FREEZE:
4597 return selectCOPY(I);
4598 case TargetOpcode::G_FNEG:
4599 if (selectImpl(I, *CoverageInfo))
4600 return true;
4601 return selectG_FNEG(I);
4602 case TargetOpcode::G_FABS:
4603 if (selectImpl(I, *CoverageInfo))
4604 return true;
4605 return selectG_FABS(I);
4606 case TargetOpcode::G_EXTRACT:
4607 return selectG_EXTRACT(I);
4608 case TargetOpcode::G_MERGE_VALUES:
4609 case TargetOpcode::G_CONCAT_VECTORS:
4610 return selectG_MERGE_VALUES(I);
4611 case TargetOpcode::G_UNMERGE_VALUES:
4612 return selectG_UNMERGE_VALUES(I);
4613 case TargetOpcode::G_BUILD_VECTOR:
4614 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
4615 return selectG_BUILD_VECTOR(I);
4616 case TargetOpcode::G_IMPLICIT_DEF:
4617 return selectG_IMPLICIT_DEF(I);
4618 case TargetOpcode::G_INSERT:
4619 return selectG_INSERT(I);
4620 case TargetOpcode::G_INTRINSIC:
4621 case TargetOpcode::G_INTRINSIC_CONVERGENT:
4622 return selectG_INTRINSIC(I);
4623 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
4624 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
4625 return selectG_INTRINSIC_W_SIDE_EFFECTS(I);
4626 case TargetOpcode::G_ICMP:
4627 case TargetOpcode::G_FCMP:
4628 if (selectG_ICMP_or_FCMP(I))
4629 return true;
4630 return selectImpl(I, *CoverageInfo);
4631 case TargetOpcode::G_LOAD:
4632 case TargetOpcode::G_ZEXTLOAD:
4633 case TargetOpcode::G_SEXTLOAD:
4634 case TargetOpcode::G_STORE:
4635 case TargetOpcode::G_ATOMIC_CMPXCHG:
4636 case TargetOpcode::G_ATOMICRMW_XCHG:
4637 case TargetOpcode::G_ATOMICRMW_ADD:
4638 case TargetOpcode::G_ATOMICRMW_SUB:
4639 case TargetOpcode::G_ATOMICRMW_AND:
4640 case TargetOpcode::G_ATOMICRMW_OR:
4641 case TargetOpcode::G_ATOMICRMW_XOR:
4642 case TargetOpcode::G_ATOMICRMW_MIN:
4643 case TargetOpcode::G_ATOMICRMW_MAX:
4644 case TargetOpcode::G_ATOMICRMW_UMIN:
4645 case TargetOpcode::G_ATOMICRMW_UMAX:
4646 case TargetOpcode::G_ATOMICRMW_UINC_WRAP:
4647 case TargetOpcode::G_ATOMICRMW_UDEC_WRAP:
4648 case TargetOpcode::G_ATOMICRMW_USUB_COND:
4649 case TargetOpcode::G_ATOMICRMW_USUB_SAT:
4650 case TargetOpcode::G_ATOMICRMW_FADD:
4651 case TargetOpcode::G_ATOMICRMW_FMIN:
4652 case TargetOpcode::G_ATOMICRMW_FMAX:
4653 return selectG_LOAD_STORE_ATOMICRMW(I);
4654 case TargetOpcode::G_SELECT:
4655 return selectG_SELECT(I);
4656 case TargetOpcode::G_TRUNC:
4657 return selectG_TRUNC(I);
4658 case TargetOpcode::G_SEXT:
4659 case TargetOpcode::G_ZEXT:
4660 case TargetOpcode::G_ANYEXT:
4661 case TargetOpcode::G_SEXT_INREG:
4662 // This is a workaround. For extension from type i1, `selectImpl()` uses
4663 // patterns from TD file and generates an illegal VGPR to SGPR COPY as type
4664 // i1 can only be hold in a SGPR class.
4665 if (MRI->getType(I.getOperand(1).getReg()) != LLT::scalar(1) &&
4666 selectImpl(I, *CoverageInfo))
4667 return true;
4668 return selectG_SZA_EXT(I);
4669 case TargetOpcode::G_FPEXT:
4670 if (selectG_FPEXT(I))
4671 return true;
4672 return selectImpl(I, *CoverageInfo);
4673 case TargetOpcode::G_BRCOND:
4674 return selectG_BRCOND(I);
4675 case TargetOpcode::G_GLOBAL_VALUE:
4676 return selectG_GLOBAL_VALUE(I);
4677 case TargetOpcode::G_PTRMASK:
4678 return selectG_PTRMASK(I);
4679 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4680 return selectG_EXTRACT_VECTOR_ELT(I);
4681 case TargetOpcode::G_INSERT_VECTOR_ELT:
4682 return selectG_INSERT_VECTOR_ELT(I);
4683 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
4684 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
4685 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
4686 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
4687 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
4688 const AMDGPU::ImageDimIntrinsicInfo *Intr =
4690 assert(Intr && "not an image intrinsic with image pseudo");
4691 return selectImageIntrinsic(I, Intr);
4692 }
4693 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY:
4694 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
4695 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
4696 return selectBVHIntersectRayIntrinsic(I);
4697 case AMDGPU::G_SBFX:
4698 case AMDGPU::G_UBFX:
4699 return selectG_SBFX_UBFX(I);
4700 case AMDGPU::G_SI_CALL:
4701 I.setDesc(TII.get(AMDGPU::SI_CALL));
4702 return true;
4703 case AMDGPU::G_AMDGPU_WAVE_ADDRESS:
4704 return selectWaveAddress(I);
4705 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN: {
4706 I.setDesc(TII.get(AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN));
4707 return true;
4708 }
4709 case AMDGPU::G_STACKRESTORE:
4710 return selectStackRestore(I);
4711 case AMDGPU::G_PHI:
4712 return selectPHI(I);
4713 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
4714 return selectCOPY_SCC_VCC(I);
4715 case AMDGPU::G_AMDGPU_COPY_VCC_SCC:
4716 return selectCOPY_VCC_SCC(I);
4717 case AMDGPU::G_AMDGPU_READANYLANE:
4718 return selectReadAnyLane(I);
4719 case TargetOpcode::G_CONSTANT:
4720 case TargetOpcode::G_FCONSTANT:
4721 default:
4722 return selectImpl(I, *CoverageInfo);
4723 }
4724 return false;
4725}
4726
4728AMDGPUInstructionSelector::selectVCSRC(MachineOperand &Root) const {
4729 return {{
4730 [=](MachineInstrBuilder &MIB) { MIB.add(Root); }
4731 }};
4732
4733}
4734
4735std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3ModsImpl(
4736 Register Src, bool IsCanonicalizing, bool AllowAbs, bool OpSel) const {
4737 unsigned Mods = 0;
4738 MachineInstr *MI = getDefIgnoringCopies(Src, *MRI);
4739
4740 if (MI->getOpcode() == AMDGPU::G_FNEG) {
4741 Src = MI->getOperand(1).getReg();
4742 Mods |= SISrcMods::NEG;
4743 MI = getDefIgnoringCopies(Src, *MRI);
4744 } else if (MI->getOpcode() == AMDGPU::G_FSUB && IsCanonicalizing) {
4745 // Fold fsub [+-]0 into fneg. This may not have folded depending on the
4746 // denormal mode, but we're implicitly canonicalizing in a source operand.
4747 const ConstantFP *LHS =
4748 getConstantFPVRegVal(MI->getOperand(1).getReg(), *MRI);
4749 if (LHS && LHS->isZero()) {
4750 Mods |= SISrcMods::NEG;
4751 Src = MI->getOperand(2).getReg();
4752 }
4753 }
4754
4755 if (AllowAbs && MI->getOpcode() == AMDGPU::G_FABS) {
4756 Src = MI->getOperand(1).getReg();
4757 Mods |= SISrcMods::ABS;
4758 }
4759
4760 if (OpSel)
4761 Mods |= SISrcMods::OP_SEL_0;
4762
4763 return std::pair(Src, Mods);
4764}
4765
4766std::pair<Register, unsigned>
4767AMDGPUInstructionSelector::selectVOP3PModsF32Impl(Register Src) const {
4768 unsigned Mods;
4769 std::tie(Src, Mods) = selectVOP3ModsImpl(Src);
4770 Mods |= SISrcMods::OP_SEL_1;
4771 return std::pair(Src, Mods);
4772}
4773
4774Register AMDGPUInstructionSelector::copyToVGPRIfSrcFolded(
4775 Register Src, unsigned Mods, MachineOperand Root, MachineInstr *InsertPt,
4776 bool ForceVGPR) const {
4777 if ((Mods != 0 || ForceVGPR) &&
4778 RBI.getRegBank(Src, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID) {
4779
4780 // If we looked through copies to find source modifiers on an SGPR operand,
4781 // we now have an SGPR register source. To avoid potentially violating the
4782 // constant bus restriction, we need to insert a copy to a VGPR.
4783 Register VGPRSrc = MRI->cloneVirtualRegister(Root.getReg());
4784 BuildMI(*InsertPt->getParent(), InsertPt, InsertPt->getDebugLoc(),
4785 TII.get(AMDGPU::COPY), VGPRSrc)
4786 .addReg(Src);
4787 Src = VGPRSrc;
4788 }
4789
4790 return Src;
4791}
4792
4793///
4794/// This will select either an SGPR or VGPR operand and will save us from
4795/// having to write an extra tablegen pattern.
4797AMDGPUInstructionSelector::selectVSRC0(MachineOperand &Root) const {
4798 return {{
4799 [=](MachineInstrBuilder &MIB) { MIB.add(Root); }
4800 }};
4801}
4802
4804AMDGPUInstructionSelector::selectVOP3Mods0(MachineOperand &Root) const {
4805 Register Src;
4806 unsigned Mods;
4807 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg());
4808
4809 return {{
4810 [=](MachineInstrBuilder &MIB) {
4811 MIB.addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4812 },
4813 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }, // src0_mods
4814 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }, // clamp
4815 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); } // omod
4816 }};
4817}
4818
4820AMDGPUInstructionSelector::selectVOP3BMods0(MachineOperand &Root) const {
4821 Register Src;
4822 unsigned Mods;
4823 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg(),
4824 /*IsCanonicalizing=*/true,
4825 /*AllowAbs=*/false);
4826
4827 return {{
4828 [=](MachineInstrBuilder &MIB) {
4829 MIB.addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4830 },
4831 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }, // src0_mods
4832 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }, // clamp
4833 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); } // omod
4834 }};
4835}
4836
4838AMDGPUInstructionSelector::selectVOP3OMods(MachineOperand &Root) const {
4839 return {{
4840 [=](MachineInstrBuilder &MIB) { MIB.add(Root); },
4841 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }, // clamp
4842 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); } // omod
4843 }};
4844}
4845
4847AMDGPUInstructionSelector::selectVOP3Mods(MachineOperand &Root) const {
4848 Register Src;
4849 unsigned Mods;
4850 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg());
4851
4852 return {{
4853 [=](MachineInstrBuilder &MIB) {
4854 MIB.addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4855 },
4856 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
4857 }};
4858}
4859
4861AMDGPUInstructionSelector::selectVOP3ModsNonCanonicalizing(
4862 MachineOperand &Root) const {
4863 Register Src;
4864 unsigned Mods;
4865 std::tie(Src, Mods) =
4866 selectVOP3ModsImpl(Root.getReg(), /*IsCanonicalizing=*/false);
4867
4868 return {{
4869 [=](MachineInstrBuilder &MIB) {
4870 MIB.addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4871 },
4872 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
4873 }};
4874}
4875
4877AMDGPUInstructionSelector::selectVOP3BMods(MachineOperand &Root) const {
4878 Register Src;
4879 unsigned Mods;
4880 std::tie(Src, Mods) =
4881 selectVOP3ModsImpl(Root.getReg(), /*IsCanonicalizing=*/true,
4882 /*AllowAbs=*/false);
4883
4884 return {{
4885 [=](MachineInstrBuilder &MIB) {
4886 MIB.addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4887 },
4888 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
4889 }};
4890}
4891
4893AMDGPUInstructionSelector::selectVOP3NoMods(MachineOperand &Root) const {
4894 Register Reg = Root.getReg();
4895 const MachineInstr *Def = getDefIgnoringCopies(Reg, *MRI);
4896 if (Def->getOpcode() == AMDGPU::G_FNEG || Def->getOpcode() == AMDGPU::G_FABS)
4897 return {};
4898 return {{
4899 [=](MachineInstrBuilder &MIB) { MIB.addReg(Reg); },
4900 }};
4901}
4902
4903enum class SrcStatus {
4908 // This means current op = [op_upper, op_lower] and src = -op_lower.
4911 // This means current op = [op_upper, op_lower] and src = [op_upper,
4912 // -op_lower].
4920};
4921/// Test if the MI is truncating to half, such as `%reg0:n = G_TRUNC %reg1:2n`
4922static bool isTruncHalf(const MachineInstr *MI,
4923 const MachineRegisterInfo &MRI) {
4924 if (MI->getOpcode() != AMDGPU::G_TRUNC)
4925 return false;
4926
4927 unsigned DstSize = MRI.getType(MI->getOperand(0).getReg()).getSizeInBits();
4928 unsigned SrcSize = MRI.getType(MI->getOperand(1).getReg()).getSizeInBits();
4929 return DstSize * 2 == SrcSize;
4930}
4931
4932/// Test if the MI is logic shift right with half bits,
4933/// such as `%reg0:2n =G_LSHR %reg1:2n, CONST(n)`
4934static bool isLshrHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI) {
4935 if (MI->getOpcode() != AMDGPU::G_LSHR)
4936 return false;
4937
4938 Register ShiftSrc;
4939 std::optional<ValueAndVReg> ShiftAmt;
4940 if (mi_match(MI->getOperand(0).getReg(), MRI,
4941 m_GLShr(m_Reg(ShiftSrc), m_GCst(ShiftAmt)))) {
4942 unsigned SrcSize = MRI.getType(MI->getOperand(1).getReg()).getSizeInBits();
4943 unsigned Shift = ShiftAmt->Value.getZExtValue();
4944 return Shift * 2 == SrcSize;
4945 }
4946 return false;
4947}
4948
4949/// Test if the MI is shift left with half bits,
4950/// such as `%reg0:2n =G_SHL %reg1:2n, CONST(n)`
4951static bool isShlHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI) {
4952 if (MI->getOpcode() != AMDGPU::G_SHL)
4953 return false;
4954
4955 Register ShiftSrc;
4956 std::optional<ValueAndVReg> ShiftAmt;
4957 if (mi_match(MI->getOperand(0).getReg(), MRI,
4958 m_GShl(m_Reg(ShiftSrc), m_GCst(ShiftAmt)))) {
4959 unsigned SrcSize = MRI.getType(MI->getOperand(1).getReg()).getSizeInBits();
4960 unsigned Shift = ShiftAmt->Value.getZExtValue();
4961 return Shift * 2 == SrcSize;
4962 }
4963 return false;
4964}
4965
4966/// Test function, if the MI is `%reg0:n, %reg1:n = G_UNMERGE_VALUES %reg2:2n`
4967static bool isUnmergeHalf(const MachineInstr *MI,
4968 const MachineRegisterInfo &MRI) {
4969 if (MI->getOpcode() != AMDGPU::G_UNMERGE_VALUES)
4970 return false;
4971 return MI->getNumOperands() == 3 && MI->getOperand(0).isDef() &&
4972 MI->getOperand(1).isDef() && !MI->getOperand(2).isDef();
4973}
4974
4976
4978 const MachineRegisterInfo &MRI) {
4979 LLT OpTy = MRI.getType(Reg);
4980 if (OpTy.isScalar())
4981 return TypeClass::SCALAR;
4982 if (OpTy.isVector() && OpTy.getNumElements() == 2)
4985}
4986
4988 const MachineRegisterInfo &MRI) {
4989 TypeClass NegType = isVectorOfTwoOrScalar(Reg, MRI);
4990 if (NegType != TypeClass::VECTOR_OF_TWO && NegType != TypeClass::SCALAR)
4991 return SrcStatus::INVALID;
4992
4993 switch (S) {
4994 case SrcStatus::IS_SAME:
4995 if (NegType == TypeClass::VECTOR_OF_TWO) {
4996 // Vector of 2:
4997 // [SrcHi, SrcLo] = [CurrHi, CurrLo]
4998 // [CurrHi, CurrLo] = neg [OpHi, OpLo](2 x Type)
4999 // [CurrHi, CurrLo] = [-OpHi, -OpLo](2 x Type)
5000 // [SrcHi, SrcLo] = [-OpHi, -OpLo]
5002 }
5003 if (NegType == TypeClass::SCALAR) {
5004 // Scalar:
5005 // [SrcHi, SrcLo] = [CurrHi, CurrLo]
5006 // [CurrHi, CurrLo] = neg [OpHi, OpLo](Type)
5007 // [CurrHi, CurrLo] = [-OpHi, OpLo](Type)
5008 // [SrcHi, SrcLo] = [-OpHi, OpLo]
5009 return SrcStatus::IS_HI_NEG;
5010 }
5011 break;
5013 if (NegType == TypeClass::VECTOR_OF_TWO) {
5014 // Vector of 2:
5015 // [SrcHi, SrcLo] = [-CurrHi, CurrLo]
5016 // [CurrHi, CurrLo] = neg [OpHi, OpLo](2 x Type)
5017 // [CurrHi, CurrLo] = [-OpHi, -OpLo](2 x Type)
5018 // [SrcHi, SrcLo] = [-(-OpHi), -OpLo] = [OpHi, -OpLo]
5019 return SrcStatus::IS_LO_NEG;
5020 }
5021 if (NegType == TypeClass::SCALAR) {
5022 // Scalar:
5023 // [SrcHi, SrcLo] = [-CurrHi, CurrLo]
5024 // [CurrHi, CurrLo] = neg [OpHi, OpLo](Type)
5025 // [CurrHi, CurrLo] = [-OpHi, OpLo](Type)
5026 // [SrcHi, SrcLo] = [-(-OpHi), OpLo] = [OpHi, OpLo]
5027 return SrcStatus::IS_SAME;
5028 }
5029 break;
5031 if (NegType == TypeClass::VECTOR_OF_TWO) {
5032 // Vector of 2:
5033 // [SrcHi, SrcLo] = [CurrHi, -CurrLo]
5034 // [CurrHi, CurrLo] = fneg [OpHi, OpLo](2 x Type)
5035 // [CurrHi, CurrLo] = [-OpHi, -OpLo](2 x Type)
5036 // [SrcHi, SrcLo] = [-OpHi, -(-OpLo)] = [-OpHi, OpLo]
5037 return SrcStatus::IS_HI_NEG;
5038 }
5039 if (NegType == TypeClass::SCALAR) {
5040 // Scalar:
5041 // [SrcHi, SrcLo] = [CurrHi, -CurrLo]
5042 // [CurrHi, CurrLo] = fneg [OpHi, OpLo](Type)
5043 // [CurrHi, CurrLo] = [-OpHi, OpLo](Type)
5044 // [SrcHi, SrcLo] = [-OpHi, -OpLo]
5046 }
5047 break;
5049 if (NegType == TypeClass::VECTOR_OF_TWO) {
5050 // Vector of 2:
5051 // [SrcHi, SrcLo] = [-CurrHi, -CurrLo]
5052 // [CurrHi, CurrLo] = fneg [OpHi, OpLo](2 x Type)
5053 // [CurrHi, CurrLo] = [-OpHi, -OpLo](2 x Type)
5054 // [SrcHi, SrcLo] = [OpHi, OpLo]
5055 return SrcStatus::IS_SAME;
5056 }
5057 if (NegType == TypeClass::SCALAR) {
5058 // Scalar:
5059 // [SrcHi, SrcLo] = [-CurrHi, -CurrLo]
5060 // [CurrHi, CurrLo] = fneg [OpHi, OpLo](Type)
5061 // [CurrHi, CurrLo] = [-OpHi, OpLo](Type)
5062 // [SrcHi, SrcLo] = [OpHi, -OpLo]
5063 return SrcStatus::IS_LO_NEG;
5064 }
5065 break;
5067 // Vector of 2:
5068 // Src = CurrUpper
5069 // Curr = [CurrUpper, CurrLower]
5070 // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](2 x Type)
5071 // [CurrUpper, CurrLower] = [-OpUpper, -OpLower](2 x Type)
5072 // Src = -OpUpper
5073 //
5074 // Scalar:
5075 // Src = CurrUpper
5076 // Curr = [CurrUpper, CurrLower]
5077 // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](Type)
5078 // [CurrUpper, CurrLower] = [-OpUpper, OpLower](Type)
5079 // Src = -OpUpper
5082 if (NegType == TypeClass::VECTOR_OF_TWO) {
5083 // Vector of 2:
5084 // Src = CurrLower
5085 // Curr = [CurrUpper, CurrLower]
5086 // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](2 x Type)
5087 // [CurrUpper, CurrLower] = [-OpUpper, -OpLower](2 x Type)
5088 // Src = -OpLower
5090 }
5091 if (NegType == TypeClass::SCALAR) {
5092 // Scalar:
5093 // Src = CurrLower
5094 // Curr = [CurrUpper, CurrLower]
5095 // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](Type)
5096 // [CurrUpper, CurrLower] = [-OpUpper, OpLower](Type)
5097 // Src = OpLower
5099 }
5100 break;
5102 // Vector of 2:
5103 // Src = -CurrUpper
5104 // Curr = [CurrUpper, CurrLower]
5105 // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](2 x Type)
5106 // [CurrUpper, CurrLower] = [-OpUpper, -OpLower](2 x Type)
5107 // Src = -(-OpUpper) = OpUpper
5108 //
5109 // Scalar:
5110 // Src = -CurrUpper
5111 // Curr = [CurrUpper, CurrLower]
5112 // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](Type)
5113 // [CurrUpper, CurrLower] = [-OpUpper, OpLower](Type)
5114 // Src = -(-OpUpper) = OpUpper
5117 if (NegType == TypeClass::VECTOR_OF_TWO) {
5118 // Vector of 2:
5119 // Src = -CurrLower
5120 // Curr = [CurrUpper, CurrLower]
5121 // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](2 x Type)
5122 // [CurrUpper, CurrLower] = [-OpUpper, -OpLower](2 x Type)
5123 // Src = -(-OpLower) = OpLower
5125 }
5126 if (NegType == TypeClass::SCALAR) {
5127 // Scalar:
5128 // Src = -CurrLower
5129 // Curr = [CurrUpper, CurrLower]
5130 // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](Type)
5131 // [CurrUpper, CurrLower] = [-OpUpper, OpLower](Type)
5132 // Src = -OpLower
5134 }
5135 break;
5136 default:
5137 break;
5138 }
5139 llvm_unreachable("unexpected SrcStatus & NegType combination");
5140}
5141
5142static std::optional<std::pair<Register, SrcStatus>>
5143calcNextStatus(std::pair<Register, SrcStatus> Curr,
5144 const MachineRegisterInfo &MRI) {
5145 const MachineInstr *MI = MRI.getVRegDef(Curr.first);
5146
5147 unsigned Opc = MI->getOpcode();
5148
5149 // Handle general Opc cases.
5150 switch (Opc) {
5151 case AMDGPU::G_BITCAST:
5152 return std::optional<std::pair<Register, SrcStatus>>(
5153 {MI->getOperand(1).getReg(), Curr.second});
5154 case AMDGPU::COPY:
5155 if (MI->getOperand(1).getReg().isPhysical())
5156 return std::nullopt;
5157 return std::optional<std::pair<Register, SrcStatus>>(
5158 {MI->getOperand(1).getReg(), Curr.second});
5159 case AMDGPU::G_FNEG: {
5160 SrcStatus Stat = getNegStatus(Curr.first, Curr.second, MRI);
5161 if (Stat == SrcStatus::INVALID)
5162 return std::nullopt;
5163 return std::optional<std::pair<Register, SrcStatus>>(
5164 {MI->getOperand(1).getReg(), Stat});
5165 }
5166 default:
5167 break;
5168 }
5169
5170 // Calc next Stat from current Stat.
5171 switch (Curr.second) {
5172 case SrcStatus::IS_SAME:
5173 if (isTruncHalf(MI, MRI))
5174 return std::optional<std::pair<Register, SrcStatus>>(
5175 {MI->getOperand(1).getReg(), SrcStatus::IS_LOWER_HALF});
5176 else if (isUnmergeHalf(MI, MRI)) {
5177 if (Curr.first == MI->getOperand(0).getReg())
5178 return std::optional<std::pair<Register, SrcStatus>>(
5179 {MI->getOperand(2).getReg(), SrcStatus::IS_LOWER_HALF});
5180 return std::optional<std::pair<Register, SrcStatus>>(
5181 {MI->getOperand(2).getReg(), SrcStatus::IS_UPPER_HALF});
5182 }
5183 break;
5185 if (isTruncHalf(MI, MRI)) {
5186 // [SrcHi, SrcLo] = [-CurrHi, CurrLo]
5187 // [CurrHi, CurrLo] = trunc [OpUpper, OpLower] = OpLower
5188 // = [OpLowerHi, OpLowerLo]
5189 // Src = [SrcHi, SrcLo] = [-CurrHi, CurrLo]
5190 // = [-OpLowerHi, OpLowerLo]
5191 // = -OpLower
5192 return std::optional<std::pair<Register, SrcStatus>>(
5193 {MI->getOperand(1).getReg(), SrcStatus::IS_LOWER_HALF_NEG});
5194 }
5195 if (isUnmergeHalf(MI, MRI)) {
5196 if (Curr.first == MI->getOperand(0).getReg())
5197 return std::optional<std::pair<Register, SrcStatus>>(
5198 {MI->getOperand(2).getReg(), SrcStatus::IS_LOWER_HALF_NEG});
5199 return std::optional<std::pair<Register, SrcStatus>>(
5200 {MI->getOperand(2).getReg(), SrcStatus::IS_UPPER_HALF_NEG});
5201 }
5202 break;
5204 if (isShlHalf(MI, MRI))
5205 return std::optional<std::pair<Register, SrcStatus>>(
5206 {MI->getOperand(1).getReg(), SrcStatus::IS_LOWER_HALF});
5207 break;
5209 if (isLshrHalf(MI, MRI))
5210 return std::optional<std::pair<Register, SrcStatus>>(
5211 {MI->getOperand(1).getReg(), SrcStatus::IS_UPPER_HALF});
5212 break;
5214 if (isShlHalf(MI, MRI))
5215 return std::optional<std::pair<Register, SrcStatus>>(
5216 {MI->getOperand(1).getReg(), SrcStatus::IS_LOWER_HALF_NEG});
5217 break;
5219 if (isLshrHalf(MI, MRI))
5220 return std::optional<std::pair<Register, SrcStatus>>(
5221 {MI->getOperand(1).getReg(), SrcStatus::IS_UPPER_HALF_NEG});
5222 break;
5223 default:
5224 break;
5225 }
5226 return std::nullopt;
5227}
5228
5229/// This is used to control valid status that current MI supports. For example,
5230/// non floating point intrinsic such as @llvm.amdgcn.sdot2 does not support NEG
5231/// bit on VOP3P.
5232/// The class can be further extended to recognize support on SEL, NEG, ABS bit
5233/// for different MI on different arch
5235private:
5236 bool HasNeg = false;
5237 // Assume all complex pattern of VOP3P have opsel.
5238 bool HasOpsel = true;
5239
5240public:
5242 const MachineInstr *MI = MRI.getVRegDef(Reg);
5243 unsigned Opc = MI->getOpcode();
5244
5245 if (Opc == TargetOpcode::G_INTRINSIC) {
5246 Intrinsic::ID IntrinsicID = cast<GIntrinsic>(*MI).getIntrinsicID();
5247 // Only float point intrinsic has neg & neg_hi bits.
5248 if (IntrinsicID == Intrinsic::amdgcn_fdot2)
5249 HasNeg = true;
5251 // Keep same for generic op.
5252 HasNeg = true;
5253 }
5254 }
5255 bool checkOptions(SrcStatus Stat) const {
5256 if (!HasNeg &&
5257 (Stat >= SrcStatus::NEG_START && Stat <= SrcStatus::NEG_END)) {
5258 return false;
5259 }
5260 if (!HasOpsel &&
5261 (Stat >= SrcStatus::HALF_START && Stat <= SrcStatus::HALF_END)) {
5262 return false;
5263 }
5264 return true;
5265 }
5266};
5267
5270 int MaxDepth = 3) {
5271 int Depth = 0;
5272 auto Curr = calcNextStatus({Reg, SrcStatus::IS_SAME}, MRI);
5274
5275 while (Depth <= MaxDepth && Curr.has_value()) {
5276 Depth++;
5277 if (SO.checkOptions(Curr.value().second))
5278 Statlist.push_back(Curr.value());
5279 Curr = calcNextStatus(Curr.value(), MRI);
5280 }
5281
5282 return Statlist;
5283}
5284
5285static std::pair<Register, SrcStatus>
5287 int MaxDepth = 3) {
5288 int Depth = 0;
5289 std::pair<Register, SrcStatus> LastSameOrNeg = {Reg, SrcStatus::IS_SAME};
5290 auto Curr = calcNextStatus(LastSameOrNeg, MRI);
5291
5292 while (Depth <= MaxDepth && Curr.has_value()) {
5293 Depth++;
5294 SrcStatus Stat = Curr.value().second;
5295 if (SO.checkOptions(Stat)) {
5296 if (Stat == SrcStatus::IS_SAME || Stat == SrcStatus::IS_HI_NEG ||
5298 LastSameOrNeg = Curr.value();
5299 }
5300 Curr = calcNextStatus(Curr.value(), MRI);
5301 }
5302
5303 return LastSameOrNeg;
5304}
5305
5306static bool isSameBitWidth(Register Reg1, Register Reg2,
5307 const MachineRegisterInfo &MRI) {
5308 unsigned Width1 = MRI.getType(Reg1).getSizeInBits();
5309 unsigned Width2 = MRI.getType(Reg2).getSizeInBits();
5310 return Width1 == Width2;
5311}
5312
5313static unsigned updateMods(SrcStatus HiStat, SrcStatus LoStat, unsigned Mods) {
5314 // SrcStatus::IS_LOWER_HALF remain 0.
5315 if (HiStat == SrcStatus::IS_UPPER_HALF_NEG) {
5316 Mods ^= SISrcMods::NEG_HI;
5317 Mods |= SISrcMods::OP_SEL_1;
5318 } else if (HiStat == SrcStatus::IS_UPPER_HALF)
5319 Mods |= SISrcMods::OP_SEL_1;
5320 else if (HiStat == SrcStatus::IS_LOWER_HALF_NEG)
5321 Mods ^= SISrcMods::NEG_HI;
5322 else if (HiStat == SrcStatus::IS_HI_NEG)
5323 Mods ^= SISrcMods::NEG_HI;
5324
5325 if (LoStat == SrcStatus::IS_UPPER_HALF_NEG) {
5326 Mods ^= SISrcMods::NEG;
5327 Mods |= SISrcMods::OP_SEL_0;
5328 } else if (LoStat == SrcStatus::IS_UPPER_HALF)
5329 Mods |= SISrcMods::OP_SEL_0;
5330 else if (LoStat == SrcStatus::IS_LOWER_HALF_NEG)
5331 Mods |= SISrcMods::NEG;
5332 else if (LoStat == SrcStatus::IS_HI_NEG)
5333 Mods ^= SISrcMods::NEG;
5334
5335 return Mods;
5336}
5337
5338static bool isValidToPack(SrcStatus HiStat, SrcStatus LoStat, Register NewReg,
5339 Register RootReg, const SIInstrInfo &TII,
5340 const MachineRegisterInfo &MRI) {
5341 auto IsHalfState = [](SrcStatus S) {
5344 };
5345 return isSameBitWidth(NewReg, RootReg, MRI) && IsHalfState(LoStat) &&
5346 IsHalfState(HiStat);
5347}
5348
5349std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3PModsImpl(
5350 Register RootReg, const MachineRegisterInfo &MRI, bool IsDOT) const {
5351 unsigned Mods = 0;
5352 // No modification if Root type is not form of <2 x Type>.
5353 if (isVectorOfTwoOrScalar(RootReg, MRI) != TypeClass::VECTOR_OF_TWO) {
5354 Mods |= SISrcMods::OP_SEL_1;
5355 return {RootReg, Mods};
5356 }
5357
5358 SearchOptions SO(RootReg, MRI);
5359
5360 std::pair<Register, SrcStatus> Stat = getLastSameOrNeg(RootReg, MRI, SO);
5361
5362 if (Stat.second == SrcStatus::IS_BOTH_NEG)
5364 else if (Stat.second == SrcStatus::IS_HI_NEG)
5365 Mods ^= SISrcMods::NEG_HI;
5366 else if (Stat.second == SrcStatus::IS_LO_NEG)
5367 Mods ^= SISrcMods::NEG;
5368
5369 // 64-bit VOP3P instructions do not have OPSEL or ABS. Bail on v2f64 or v2i64.
5370 // TODO: Select NEG_LO and NEG_HI modifiers from BUILD_VECTOR.
5371 if (MRI.getType(RootReg).getSizeInBits() == 128) {
5372 Mods |= SISrcMods::OP_SEL_1; // Just the default, OPSEL unsupported.
5373 return {Stat.first, Mods};
5374 }
5375
5376 GBuildVector *MI;
5377 if (!mi_match(Stat.first, MRI, m_GBuildVector(MI)) ||
5378 MI->getNumOperands() != 3 || (IsDOT && Subtarget->hasDOTOpSelHazard())) {
5379 Mods |= SISrcMods::OP_SEL_1;
5380 return {Stat.first, Mods};
5381 }
5382
5384 getSrcStats(MI->getOperand(2).getReg(), MRI, SO);
5385
5386 if (StatlistHi.empty()) {
5387 Mods |= SISrcMods::OP_SEL_1;
5388 return {Stat.first, Mods};
5389 }
5390
5392 getSrcStats(MI->getOperand(1).getReg(), MRI, SO);
5393
5394 if (StatlistLo.empty()) {
5395 Mods |= SISrcMods::OP_SEL_1;
5396 return {Stat.first, Mods};
5397 }
5398
5399 for (int I = StatlistHi.size() - 1; I >= 0; I--) {
5400 for (int J = StatlistLo.size() - 1; J >= 0; J--) {
5401 if (StatlistHi[I].first == StatlistLo[J].first &&
5402 isValidToPack(StatlistHi[I].second, StatlistLo[J].second,
5403 StatlistHi[I].first, RootReg, TII, MRI))
5404 return {StatlistHi[I].first,
5405 updateMods(StatlistHi[I].second, StatlistLo[J].second, Mods)};
5406 }
5407 }
5408 // Packed instructions do not have abs modifiers.
5409 Mods |= SISrcMods::OP_SEL_1;
5410
5411 return {Stat.first, Mods};
5412}
5413
5414// Removed unused function `getAllKindImm` to eliminate dead code.
5415
5416static bool checkRB(Register Reg, unsigned int RBNo,
5417 const AMDGPURegisterBankInfo &RBI,
5418 const MachineRegisterInfo &MRI,
5419 const TargetRegisterInfo &TRI) {
5420 const RegisterBank *RB = RBI.getRegBank(Reg, MRI, TRI);
5421 return RB->getID() == RBNo;
5422}
5423
5424// This function is used to get the correct register bank for returned reg.
5425// Assume:
5426// 1. VOP3P is always legal for VGPR.
5427// 2. RootOp's regbank is legal.
5428// Thus
5429// 1. If RootOp is SGPR, then NewOp can be SGPR or VGPR.
5430// 2. If RootOp is VGPR, then NewOp must be VGPR.
5431static Register
5434 const TargetRegisterInfo &TRI, const SIInstrInfo &TII) {
5435 // RootOp can only be VGPR or SGPR (some hand written cases such as.
5436 // inst-select-ashr.v2s16.mir::ashr_v2s16_vs).
5437 if (checkRB(RootReg, AMDGPU::SGPRRegBankID, RBI, MRI, TRI) ||
5438 checkRB(NewReg, AMDGPU::VGPRRegBankID, RBI, MRI, TRI))
5439 return NewReg;
5440
5441 if (mi_match(RootReg, MRI, m_Copy(m_SpecificReg(NewReg)))) {
5442 // RootOp is VGPR, NewOp is not VGPR, but RootOp = COPY NewOp.
5443 return RootReg;
5444 }
5445
5446 Register DstReg = MRI.cloneVirtualRegister(RootReg);
5447 MachineInstrBuilder MIB = BuildMI(*Use.getParent(), Use, Use.getDebugLoc(),
5448 TII.get(AMDGPU::COPY), DstReg)
5449 .addReg(NewReg);
5450
5451 // Only accept VGPR.
5452 return MIB->getOperand(0).getReg();
5453}
5454
5456AMDGPUInstructionSelector::selectVOP3PRetHelper(MachineOperand &Root,
5457 bool IsDOT) const {
5458 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
5459 Register Reg;
5460 unsigned Mods;
5461 std::tie(Reg, Mods) = selectVOP3PModsImpl(Root.getReg(), MRI, IsDOT);
5462
5463 Reg = getLegalRegBank(Reg, Root.getReg(), *Root.getParent(), RBI, MRI, TRI,
5464 TII);
5465 return {{
5466 [=](MachineInstrBuilder &MIB) { MIB.addReg(Reg); },
5467 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
5468 }};
5469}
5470
5472AMDGPUInstructionSelector::selectVOP3PMods(MachineOperand &Root) const {
5473
5474 return selectVOP3PRetHelper(Root);
5475}
5476
5478AMDGPUInstructionSelector::selectVOP3PModsDOT(MachineOperand &Root) const {
5479
5480 return selectVOP3PRetHelper(Root, true);
5481}
5482
5484AMDGPUInstructionSelector::selectVOP3PNoModsDOT(MachineOperand &Root) const {
5485 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
5486 Register Src;
5487 unsigned Mods;
5488 std::tie(Src, Mods) = selectVOP3PModsImpl(Root.getReg(), MRI, true /*IsDOT*/);
5489 if (Mods != SISrcMods::OP_SEL_1)
5490 return {};
5491
5492 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Src); }}};
5493}
5494
5496AMDGPUInstructionSelector::selectVOP3PModsF32(MachineOperand &Root) const {
5497 Register Src;
5498 unsigned Mods;
5499 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.getReg());
5500
5501 return {{
5502 [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
5503 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
5504 }};
5505}
5506
5508AMDGPUInstructionSelector::selectVOP3PNoModsF32(MachineOperand &Root) const {
5509 Register Src;
5510 unsigned Mods;
5511 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.getReg());
5512 if (Mods != SISrcMods::OP_SEL_1)
5513 return {};
5514
5515 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Src); }}};
5516}
5517
5519AMDGPUInstructionSelector::selectWMMAOpSelVOP3PMods(
5520 MachineOperand &Root) const {
5521 assert((Root.isImm() && (Root.getImm() == -1 || Root.getImm() == 0)) &&
5522 "expected i1 value");
5523 unsigned Mods = SISrcMods::OP_SEL_1;
5524 if (Root.getImm() != 0)
5525 Mods |= SISrcMods::OP_SEL_0;
5526
5527 return {{
5528 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
5529 }};
5530}
5531
5533 MachineInstr *InsertPt,
5534 MachineRegisterInfo &MRI) {
5535 const TargetRegisterClass *DstRegClass;
5536 switch (Elts.size()) {
5537 case 8:
5538 DstRegClass = &AMDGPU::VReg_256RegClass;
5539 break;
5540 case 4:
5541 DstRegClass = &AMDGPU::VReg_128RegClass;
5542 break;
5543 case 2:
5544 DstRegClass = &AMDGPU::VReg_64RegClass;
5545 break;
5546 default:
5547 llvm_unreachable("unhandled Reg sequence size");
5548 }
5549
5550 MachineIRBuilder B(*InsertPt);
5551 auto MIB = B.buildInstr(AMDGPU::REG_SEQUENCE)
5552 .addDef(MRI.createVirtualRegister(DstRegClass));
5553 for (unsigned i = 0; i < Elts.size(); ++i) {
5554 MIB.addReg(Elts[i]);
5556 }
5557 return MIB->getOperand(0).getReg();
5558}
5559
5560static void selectWMMAModsNegAbs(unsigned ModOpcode, unsigned &Mods,
5562 MachineInstr *InsertPt,
5563 MachineRegisterInfo &MRI) {
5564 if (ModOpcode == TargetOpcode::G_FNEG) {
5565 Mods |= SISrcMods::NEG;
5566 // Check if all elements also have abs modifier
5567 SmallVector<Register, 8> NegAbsElts;
5568 for (auto El : Elts) {
5569 Register FabsSrc;
5570 if (!mi_match(El, MRI, m_GFabs(m_Reg(FabsSrc))))
5571 break;
5572 NegAbsElts.push_back(FabsSrc);
5573 }
5574 if (Elts.size() != NegAbsElts.size()) {
5575 // Neg
5576 Src = buildRegSequence(Elts, InsertPt, MRI);
5577 } else {
5578 // Neg and Abs
5579 Mods |= SISrcMods::NEG_HI;
5580 Src = buildRegSequence(NegAbsElts, InsertPt, MRI);
5581 }
5582 } else {
5583 assert(ModOpcode == TargetOpcode::G_FABS);
5584 // Abs
5585 Mods |= SISrcMods::NEG_HI;
5586 Src = buildRegSequence(Elts, InsertPt, MRI);
5587 }
5588}
5589
5591AMDGPUInstructionSelector::selectWMMAModsF32NegAbs(MachineOperand &Root) const {
5592 Register Src = Root.getReg();
5593 unsigned Mods = SISrcMods::OP_SEL_1;
5595
5596 GBuildVector *BV;
5597 if (mi_match(Src, *MRI, m_GBuildVector(BV))) {
5598 assert(BV->getNumSources() > 0);
5599 // Based on first element decide which mod we match, neg or abs
5600 MachineInstr *ElF32 = MRI->getVRegDef(BV->getSourceReg(0));
5601 unsigned ModOpcode = (ElF32->getOpcode() == AMDGPU::G_FNEG)
5602 ? AMDGPU::G_FNEG
5603 : AMDGPU::G_FABS;
5604 for (unsigned i = 0; i < BV->getNumSources(); ++i) {
5605 ElF32 = MRI->getVRegDef(BV->getSourceReg(i));
5606 if (ElF32->getOpcode() != ModOpcode)
5607 break;
5608 EltsF32.push_back(ElF32->getOperand(1).getReg());
5609 }
5610
5611 // All elements had ModOpcode modifier
5612 if (BV->getNumSources() == EltsF32.size()) {
5613 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF32, Src, Root.getParent(),
5614 *MRI);
5615 }
5616 }
5617
5618 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
5619 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }}};
5620}
5621
5623AMDGPUInstructionSelector::selectWMMAModsF16Neg(MachineOperand &Root) const {
5624 Register Src = Root.getReg();
5625 unsigned Mods = SISrcMods::OP_SEL_1;
5626 SmallVector<Register, 8> EltsV2F16;
5627
5628 GConcatVectors *CV;
5629 if (mi_match(Src, *MRI, m_GConcatVectors(CV))) {
5630 for (unsigned i = 0; i < CV->getNumSources(); ++i) {
5631 Register FNegSrc;
5632 if (!mi_match(CV->getSourceReg(i), *MRI, m_GFNeg(m_Reg(FNegSrc))))
5633 break;
5634 EltsV2F16.push_back(FNegSrc);
5635 }
5636
5637 // All elements had ModOpcode modifier
5638 if (CV->getNumSources() == EltsV2F16.size()) {
5639 Mods |= SISrcMods::NEG;
5640 Mods |= SISrcMods::NEG_HI;
5641 Src = buildRegSequence(EltsV2F16, Root.getParent(), *MRI);
5642 }
5643 }
5644
5645 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
5646 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }}};
5647}
5648
5650AMDGPUInstructionSelector::selectWMMAModsF16NegAbs(MachineOperand &Root) const {
5651 Register Src = Root.getReg();
5652 unsigned Mods = SISrcMods::OP_SEL_1;
5653 SmallVector<Register, 8> EltsV2F16;
5654
5655 GConcatVectors *CV;
5656 if (mi_match(Src, *MRI, m_GConcatVectors(CV))) {
5657 assert(CV->getNumSources() > 0);
5658 MachineInstr *ElV2F16 = MRI->getVRegDef(CV->getSourceReg(0));
5659 // Based on first element decide which mod we match, neg or abs
5660 unsigned ModOpcode = (ElV2F16->getOpcode() == AMDGPU::G_FNEG)
5661 ? AMDGPU::G_FNEG
5662 : AMDGPU::G_FABS;
5663
5664 for (unsigned i = 0; i < CV->getNumSources(); ++i) {
5665 ElV2F16 = MRI->getVRegDef(CV->getSourceReg(i));
5666 if (ElV2F16->getOpcode() != ModOpcode)
5667 break;
5668 EltsV2F16.push_back(ElV2F16->getOperand(1).getReg());
5669 }
5670
5671 // All elements had ModOpcode modifier
5672 if (CV->getNumSources() == EltsV2F16.size()) {
5673 MachineIRBuilder B(*Root.getParent());
5674 selectWMMAModsNegAbs(ModOpcode, Mods, EltsV2F16, Src, Root.getParent(),
5675 *MRI);
5676 }
5677 }
5678
5679 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
5680 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }}};
5681}
5682
5684AMDGPUInstructionSelector::selectWMMAVISrc(MachineOperand &Root) const {
5685 std::optional<FPValueAndVReg> FPValReg;
5686 if (mi_match(Root.getReg(), *MRI, m_GFCstOrSplat(FPValReg))) {
5687 if (TII.isInlineConstant(FPValReg->Value)) {
5688 return {{[=](MachineInstrBuilder &MIB) {
5689 MIB.addImm(FPValReg->Value.bitcastToAPInt().getSExtValue());
5690 }}};
5691 }
5692 // Non-inlineable splat floats should not fall-through for integer immediate
5693 // checks.
5694 return {};
5695 }
5696
5697 APInt ICst;
5698 if (mi_match(Root.getReg(), *MRI, m_ICstOrSplat(ICst))) {
5699 if (TII.isInlineConstant(ICst)) {
5700 return {
5701 {[=](MachineInstrBuilder &MIB) { MIB.addImm(ICst.getSExtValue()); }}};
5702 }
5703 }
5704
5705 return {};
5706}
5707
5709AMDGPUInstructionSelector::selectSWMMACIndex8(MachineOperand &Root) const {
5710 Register Src =
5711 getDefIgnoringCopies(Root.getReg(), *MRI)->getOperand(0).getReg();
5712 unsigned Key = 0;
5713
5714 Register ShiftSrc;
5715 std::optional<ValueAndVReg> ShiftAmt;
5716 if (mi_match(Src, *MRI, m_GLShr(m_Reg(ShiftSrc), m_GCst(ShiftAmt))) &&
5717 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5718 ShiftAmt->Value.getZExtValue() % 8 == 0) {
5719 Key = ShiftAmt->Value.getZExtValue() / 8;
5720 Src = ShiftSrc;
5721 }
5722
5723 return {{
5724 [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
5725 [=](MachineInstrBuilder &MIB) { MIB.addImm(Key); } // index_key
5726 }};
5727}
5728
5730AMDGPUInstructionSelector::selectSWMMACIndex16(MachineOperand &Root) const {
5731
5732 Register Src =
5733 getDefIgnoringCopies(Root.getReg(), *MRI)->getOperand(0).getReg();
5734 unsigned Key = 0;
5735
5736 Register ShiftSrc;
5737 std::optional<ValueAndVReg> ShiftAmt;
5738 if (mi_match(Src, *MRI, m_GLShr(m_Reg(ShiftSrc), m_GCst(ShiftAmt))) &&
5739 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5740 ShiftAmt->Value.getZExtValue() == 16) {
5741 Src = ShiftSrc;
5742 Key = 1;
5743 }
5744
5745 return {{
5746 [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
5747 [=](MachineInstrBuilder &MIB) { MIB.addImm(Key); } // index_key
5748 }};
5749}
5750
5752AMDGPUInstructionSelector::selectSWMMACIndex32(MachineOperand &Root) const {
5753 Register Src =
5754 getDefIgnoringCopies(Root.getReg(), *MRI)->getOperand(0).getReg();
5755 unsigned Key = 0;
5756
5757 Register S32 = matchZeroExtendFromS32(Src);
5758 if (!S32)
5759 S32 = matchAnyExtendFromS32(Src);
5760
5761 if (S32) {
5762 const MachineInstr *Def = getDefIgnoringCopies(S32, *MRI);
5763 if (Def->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
5764 assert(Def->getNumOperands() == 3);
5765 Register DstReg1 = Def->getOperand(1).getReg();
5766 if (mi_match(S32, *MRI,
5767 m_any_of(m_SpecificReg(DstReg1), m_Copy(m_Reg(DstReg1))))) {
5768 Src = Def->getOperand(2).getReg();
5769 Key = 1;
5770 }
5771 }
5772 }
5773
5774 return {{
5775 [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
5776 [=](MachineInstrBuilder &MIB) { MIB.addImm(Key); } // index_key
5777 }};
5778}
5779
5781AMDGPUInstructionSelector::selectVOP3OpSelMods(MachineOperand &Root) const {
5782 Register Src;
5783 unsigned Mods;
5784 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg());
5785
5786 // FIXME: Handle op_sel
5787 return {{
5788 [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
5789 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
5790 }};
5791}
5792
5793// FIXME-TRUE16 remove when fake16 is removed
5795AMDGPUInstructionSelector::selectVINTERPMods(MachineOperand &Root) const {
5796 Register Src;
5797 unsigned Mods;
5798 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg(),
5799 /*IsCanonicalizing=*/true,
5800 /*AllowAbs=*/false,
5801 /*OpSel=*/false);
5802
5803 return {{
5804 [=](MachineInstrBuilder &MIB) {
5805 MIB.addReg(
5806 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB, /* ForceVGPR */ true));
5807 },
5808 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }, // src0_mods
5809 }};
5810}
5811
5813AMDGPUInstructionSelector::selectVINTERPModsHi(MachineOperand &Root) const {
5814 Register Src;
5815 unsigned Mods;
5816 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg(),
5817 /*IsCanonicalizing=*/true,
5818 /*AllowAbs=*/false,
5819 /*OpSel=*/true);
5820
5821 return {{
5822 [=](MachineInstrBuilder &MIB) {
5823 MIB.addReg(
5824 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB, /* ForceVGPR */ true));
5825 },
5826 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }, // src0_mods
5827 }};
5828}
5829
5830// Given \p Offset and load specified by the \p Root operand check if \p Offset
5831// is a multiple of the load byte size. If it is update \p Offset to a
5832// pre-scaled value and return true.
5833bool AMDGPUInstructionSelector::selectScaleOffset(MachineOperand &Root,
5835 bool IsSigned) const {
5836 if (!Subtarget->hasScaleOffset())
5837 return false;
5838
5839 const MachineInstr &MI = *Root.getParent();
5840 MachineMemOperand *MMO = *MI.memoperands_begin();
5841
5842 if (!MMO->getSize().hasValue())
5843 return false;
5844
5845 uint64_t Size = MMO->getSize().getValue();
5846
5847 Register OffsetReg = matchExtendFromS32OrS32(Offset, IsSigned);
5848 if (!OffsetReg)
5849 OffsetReg = Offset;
5850
5851 if (auto Def = getDefSrcRegIgnoringCopies(OffsetReg, *MRI))
5852 OffsetReg = Def->Reg;
5853
5854 Register Op0;
5855 MachineInstr *Mul;
5856 bool ScaleOffset =
5857 (isPowerOf2_64(Size) &&
5858 mi_match(OffsetReg, *MRI,
5859 m_GShl(m_Reg(Op0),
5862 mi_match(OffsetReg, *MRI,
5864 m_Copy(m_SpecificICst(Size))))) ||
5865 mi_match(
5866 OffsetReg, *MRI,
5867 m_BinOp(IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO : AMDGPU::S_MUL_U64,
5868 m_Reg(Op0), m_SpecificICst(Size))) ||
5869 // Match G_AMDGPU_MAD_U64_U32 offset, c, 0
5870 (mi_match(OffsetReg, *MRI, m_MInstr(Mul)) &&
5871 (Mul->getOpcode() == (IsSigned ? AMDGPU::G_AMDGPU_MAD_I64_I32
5872 : AMDGPU::G_AMDGPU_MAD_U64_U32) ||
5873 (IsSigned && Mul->getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32 &&
5874 VT->signBitIsZero(Mul->getOperand(2).getReg()))) &&
5875 mi_match(Mul->getOperand(4).getReg(), *MRI, m_ZeroInt()) &&
5876 mi_match(Mul->getOperand(3).getReg(), *MRI,
5878 m_Copy(m_SpecificICst(Size))))) &&
5879 mi_match(Mul->getOperand(2).getReg(), *MRI, m_Reg(Op0)));
5880
5881 if (ScaleOffset)
5882 Offset = Op0;
5883
5884 return ScaleOffset;
5885}
5886
5887bool AMDGPUInstructionSelector::selectSmrdOffset(MachineOperand &Root,
5888 Register &Base,
5889 Register *SOffset,
5890 int64_t *Offset,
5891 bool *ScaleOffset) const {
5892 MachineInstr *MI = Root.getParent();
5893 MachineBasicBlock *MBB = MI->getParent();
5894
5895 // FIXME: We should shrink the GEP if the offset is known to be <= 32-bits,
5896 // then we can select all ptr + 32-bit offsets.
5897 SmallVector<GEPInfo, 4> AddrInfo;
5898 getAddrModeInfo(*MI, *MRI, AddrInfo);
5899
5900 if (AddrInfo.empty())
5901 return false;
5902
5903 const GEPInfo &GEPI = AddrInfo[0];
5904 std::optional<int64_t> EncodedImm;
5905
5906 if (ScaleOffset)
5907 *ScaleOffset = false;
5908
5909 if (SOffset && Offset) {
5910 EncodedImm = AMDGPU::getSMRDEncodedOffset(STI, GEPI.Imm, /*IsBuffer=*/false,
5911 /*HasSOffset=*/true);
5912 if (GEPI.SgprParts.size() == 1 && GEPI.Imm != 0 && EncodedImm &&
5913 AddrInfo.size() > 1) {
5914 const GEPInfo &GEPI2 = AddrInfo[1];
5915 if (GEPI2.SgprParts.size() == 2 && GEPI2.Imm == 0) {
5916 Register OffsetReg = GEPI2.SgprParts[1];
5917 if (ScaleOffset)
5918 *ScaleOffset =
5919 selectScaleOffset(Root, OffsetReg, false /* IsSigned */);
5920 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5921 if (OffsetReg) {
5922 Base = GEPI2.SgprParts[0];
5923 *SOffset = OffsetReg;
5924 *Offset = *EncodedImm;
5925 if (*Offset >= 0 || !AMDGPU::hasSMRDSignedImmOffset(STI))
5926 return true;
5927
5928 // For unbuffered smem loads, it is illegal for the Immediate Offset
5929 // to be negative if the resulting (Offset + (M0 or SOffset or zero)
5930 // is negative. Handle the case where the Immediate Offset + SOffset
5931 // is negative.
5932 auto SKnown = VT->getKnownBits(*SOffset);
5933 if (*Offset + SKnown.getMinValue().getSExtValue() < 0)
5934 return false;
5935
5936 return true;
5937 }
5938 }
5939 }
5940 return false;
5941 }
5942
5943 EncodedImm = AMDGPU::getSMRDEncodedOffset(STI, GEPI.Imm, /*IsBuffer=*/false,
5944 /*HasSOffset=*/false);
5945 if (Offset && GEPI.SgprParts.size() == 1 && EncodedImm) {
5946 Base = GEPI.SgprParts[0];
5947 *Offset = *EncodedImm;
5948 return true;
5949 }
5950
5951 // SGPR offset is unsigned.
5952 if (SOffset && GEPI.SgprParts.size() == 1 && isUInt<32>(GEPI.Imm) &&
5953 GEPI.Imm != 0) {
5954 // If we make it this far we have a load with an 32-bit immediate offset.
5955 // It is OK to select this using a sgpr offset, because we have already
5956 // failed trying to select this load into one of the _IMM variants since
5957 // the _IMM Patterns are considered before the _SGPR patterns.
5958 Base = GEPI.SgprParts[0];
5959 *SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
5960 BuildMI(*MBB, MI, MI->getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), *SOffset)
5961 .addImm(GEPI.Imm);
5962 return true;
5963 }
5964
5965 if (SOffset && GEPI.SgprParts.size() && GEPI.Imm == 0) {
5966 Register OffsetReg = GEPI.SgprParts[1];
5967 if (ScaleOffset)
5968 *ScaleOffset = selectScaleOffset(Root, OffsetReg, false /* IsSigned */);
5969 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5970 if (OffsetReg) {
5971 Base = GEPI.SgprParts[0];
5972 *SOffset = OffsetReg;
5973 return true;
5974 }
5975 }
5976
5977 return false;
5978}
5979
5981AMDGPUInstructionSelector::selectSmrdImm(MachineOperand &Root) const {
5982 Register Base;
5983 int64_t Offset;
5984 if (!selectSmrdOffset(Root, Base, /* SOffset= */ nullptr, &Offset,
5985 /* ScaleOffset */ nullptr))
5986 return std::nullopt;
5987
5988 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Base); },
5989 [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); }}};
5990}
5991
5993AMDGPUInstructionSelector::selectSmrdImm32(MachineOperand &Root) const {
5994 SmallVector<GEPInfo, 4> AddrInfo;
5995 getAddrModeInfo(*Root.getParent(), *MRI, AddrInfo);
5996
5997 if (AddrInfo.empty() || AddrInfo[0].SgprParts.size() != 1)
5998 return std::nullopt;
5999
6000 const GEPInfo &GEPInfo = AddrInfo[0];
6001 Register PtrReg = GEPInfo.SgprParts[0];
6002 std::optional<int64_t> EncodedImm =
6003 AMDGPU::getSMRDEncodedLiteralOffset32(STI, GEPInfo.Imm);
6004 if (!EncodedImm)
6005 return std::nullopt;
6006
6007 return {{
6008 [=](MachineInstrBuilder &MIB) { MIB.addReg(PtrReg); },
6009 [=](MachineInstrBuilder &MIB) { MIB.addImm(*EncodedImm); }
6010 }};
6011}
6012
6014AMDGPUInstructionSelector::selectSmrdSgpr(MachineOperand &Root) const {
6015 Register Base, SOffset;
6016 bool ScaleOffset;
6017 if (!selectSmrdOffset(Root, Base, &SOffset, /* Offset= */ nullptr,
6018 &ScaleOffset))
6019 return std::nullopt;
6020
6021 unsigned CPol = ScaleOffset ? AMDGPU::CPol::SCAL : 0;
6022 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Base); },
6023 [=](MachineInstrBuilder &MIB) { MIB.addReg(SOffset); },
6024 [=](MachineInstrBuilder &MIB) { MIB.addImm(CPol); }}};
6025}
6026
6028AMDGPUInstructionSelector::selectSmrdSgprImm(MachineOperand &Root) const {
6029 Register Base, SOffset;
6030 int64_t Offset;
6031 bool ScaleOffset;
6032 if (!selectSmrdOffset(Root, Base, &SOffset, &Offset, &ScaleOffset))
6033 return std::nullopt;
6034
6035 unsigned CPol = ScaleOffset ? AMDGPU::CPol::SCAL : 0;
6036 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Base); },
6037 [=](MachineInstrBuilder &MIB) { MIB.addReg(SOffset); },
6038 [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); },
6039 [=](MachineInstrBuilder &MIB) { MIB.addImm(CPol); }}};
6040}
6041
6042std::pair<Register, int> AMDGPUInstructionSelector::selectFlatOffsetImpl(
6043 MachineOperand &Root, AMDGPU::FlatAddrSpace FlatVariant) const {
6044 MachineInstr *MI = Root.getParent();
6045
6046 auto Default = std::pair(Root.getReg(), 0);
6047
6048 if (!STI.hasFlatInstOffsets())
6049 return Default;
6050
6051 Register PtrBase;
6052 int64_t ConstOffset;
6053 bool IsInBounds;
6054 std::tie(PtrBase, ConstOffset, IsInBounds) =
6055 getPtrBaseWithConstantOffset(Root.getReg(), *MRI);
6056
6057 // Adding the offset to the base address with an immediate in a FLAT
6058 // instruction must not change the memory aperture in which the address falls.
6059 // Therefore we can only fold offsets from inbounds GEPs into FLAT
6060 // instructions.
6061 if (ConstOffset == 0 ||
6062 (FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch &&
6063 !isFlatScratchBaseLegal(Root.getReg())) ||
6064 (FlatVariant == AMDGPU::FlatAddrSpace::FLAT && !IsInBounds))
6065 return Default;
6066
6067 unsigned AddrSpace = (*MI->memoperands_begin())->getAddrSpace();
6068 if (!TII.isLegalFLATOffset(ConstOffset, AddrSpace, FlatVariant))
6069 return Default;
6070
6071 return std::pair(PtrBase, ConstOffset);
6072}
6073
6075AMDGPUInstructionSelector::selectFlatOffset(MachineOperand &Root) const {
6076 auto PtrWithOffset = selectFlatOffsetImpl(Root, AMDGPU::FlatAddrSpace::FLAT);
6077
6078 return {{
6079 [=](MachineInstrBuilder &MIB) { MIB.addReg(PtrWithOffset.first); },
6080 [=](MachineInstrBuilder &MIB) { MIB.addImm(PtrWithOffset.second); },
6081 }};
6082}
6083
6085AMDGPUInstructionSelector::selectGlobalOffset(MachineOperand &Root) const {
6086 auto PtrWithOffset =
6087 selectFlatOffsetImpl(Root, AMDGPU::FlatAddrSpace::FlatGlobal);
6088
6089 return {{
6090 [=](MachineInstrBuilder &MIB) { MIB.addReg(PtrWithOffset.first); },
6091 [=](MachineInstrBuilder &MIB) { MIB.addImm(PtrWithOffset.second); },
6092 }};
6093}
6094
6096AMDGPUInstructionSelector::selectScratchOffset(MachineOperand &Root) const {
6097 auto PtrWithOffset =
6098 selectFlatOffsetImpl(Root, AMDGPU::FlatAddrSpace::FlatScratch);
6099
6100 return {{
6101 [=](MachineInstrBuilder &MIB) { MIB.addReg(PtrWithOffset.first); },
6102 [=](MachineInstrBuilder &MIB) { MIB.addImm(PtrWithOffset.second); },
6103 }};
6104}
6105
6106// Match (64-bit SGPR base) + (zext vgpr offset) + sext(imm offset)
6108AMDGPUInstructionSelector::selectGlobalSAddr(MachineOperand &Root,
6109 unsigned CPolBits,
6110 bool NeedIOffset) const {
6111 Register Addr = Root.getReg();
6112 Register PtrBase;
6113 int64_t ConstOffset;
6114 int64_t ImmOffset = 0;
6115
6116 // Match the immediate offset first, which canonically is moved as low as
6117 // possible.
6118 std::tie(PtrBase, ConstOffset, std::ignore) =
6119 getPtrBaseWithConstantOffset(Addr, *MRI);
6120
6121 if (ConstOffset != 0) {
6122 if (NeedIOffset &&
6123 TII.isLegalFLATOffset(ConstOffset, AMDGPUAS::GLOBAL_ADDRESS,
6125 Addr = PtrBase;
6126 ImmOffset = ConstOffset;
6127 } else {
6128 auto PtrBaseDef = getDefSrcRegIgnoringCopies(PtrBase, *MRI);
6129 if (isSGPR(PtrBaseDef->Reg)) {
6130 if (ConstOffset > 0) {
6131 // Offset is too large.
6132 //
6133 // saddr + large_offset -> saddr +
6134 // (voffset = large_offset & ~MaxOffset) +
6135 // (large_offset & MaxOffset);
6136 int64_t SplitImmOffset = 0, RemainderOffset = ConstOffset;
6137 if (NeedIOffset) {
6138 std::tie(SplitImmOffset, RemainderOffset) =
6139 TII.splitFlatOffset(ConstOffset, AMDGPUAS::GLOBAL_ADDRESS,
6141 }
6142
6143 if (Subtarget->hasSignedGVSOffset() ? isInt<32>(RemainderOffset)
6144 : isUInt<32>(RemainderOffset)) {
6145 MachineInstr *MI = Root.getParent();
6146 MachineBasicBlock *MBB = MI->getParent();
6147 Register HighBits =
6148 MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6149
6150 BuildMI(*MBB, MI, MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6151 HighBits)
6152 .addImm(RemainderOffset);
6153
6154 if (NeedIOffset)
6155 return {{
6156 [=](MachineInstrBuilder &MIB) {
6157 MIB.addReg(PtrBase);
6158 }, // saddr
6159 [=](MachineInstrBuilder &MIB) {
6160 MIB.addReg(HighBits);
6161 }, // voffset
6162 [=](MachineInstrBuilder &MIB) { MIB.addImm(SplitImmOffset); },
6163 [=](MachineInstrBuilder &MIB) { MIB.addImm(CPolBits); },
6164 }};
6165 return {{
6166 [=](MachineInstrBuilder &MIB) { MIB.addReg(PtrBase); }, // saddr
6167 [=](MachineInstrBuilder &MIB) {
6168 MIB.addReg(HighBits);
6169 }, // voffset
6170 [=](MachineInstrBuilder &MIB) { MIB.addImm(CPolBits); },
6171 }};
6172 }
6173 }
6174
6175 // We are adding a 64 bit SGPR and a constant. If constant bus limit
6176 // is 1 we would need to perform 1 or 2 extra moves for each half of
6177 // the constant and it is better to do a scalar add and then issue a
6178 // single VALU instruction to materialize zero. Otherwise it is less
6179 // instructions to perform VALU adds with immediates or inline literals.
6180 unsigned NumLiterals =
6181 !TII.isInlineConstant(APInt(32, Lo_32(ConstOffset))) +
6182 !TII.isInlineConstant(APInt(32, Hi_32(ConstOffset)));
6183 if (STI.getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
6184 return std::nullopt;
6185 }
6186 }
6187 }
6188
6189 // Match the variable offset.
6190 auto AddrDef = getDefSrcRegIgnoringCopies(Addr, *MRI);
6191 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6192 // Look through the SGPR->VGPR copy.
6193 Register SAddr =
6194 getSrcRegIgnoringCopies(AddrDef->MI->getOperand(1).getReg(), *MRI);
6195
6196 if (isSGPR(SAddr)) {
6197 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
6198
6199 // It's possible voffset is an SGPR here, but the copy to VGPR will be
6200 // inserted later.
6201 bool ScaleOffset = selectScaleOffset(Root, PtrBaseOffset,
6202 Subtarget->hasSignedGVSOffset());
6203 if (Register VOffset = matchExtendFromS32OrS32(
6204 PtrBaseOffset, Subtarget->hasSignedGVSOffset())) {
6205 if (NeedIOffset)
6206 return {{[=](MachineInstrBuilder &MIB) { // saddr
6207 MIB.addReg(SAddr);
6208 },
6209 [=](MachineInstrBuilder &MIB) { // voffset
6210 MIB.addReg(VOffset);
6211 },
6212 [=](MachineInstrBuilder &MIB) { // offset
6213 MIB.addImm(ImmOffset);
6214 },
6215 [=](MachineInstrBuilder &MIB) { // cpol
6216 MIB.addImm(CPolBits |
6217 (ScaleOffset ? AMDGPU::CPol::SCAL : 0));
6218 }}};
6219 return {{[=](MachineInstrBuilder &MIB) { // saddr
6220 MIB.addReg(SAddr);
6221 },
6222 [=](MachineInstrBuilder &MIB) { // voffset
6223 MIB.addReg(VOffset);
6224 },
6225 [=](MachineInstrBuilder &MIB) { // cpol
6226 MIB.addImm(CPolBits |
6227 (ScaleOffset ? AMDGPU::CPol::SCAL : 0));
6228 }}};
6229 }
6230 }
6231 }
6232
6233 // FIXME: We should probably have folded COPY (G_IMPLICIT_DEF) earlier, and
6234 // drop this.
6235 if (AddrDef->MI->getOpcode() == AMDGPU::G_IMPLICIT_DEF ||
6236 AddrDef->MI->getOpcode() == AMDGPU::G_CONSTANT || !isSGPR(AddrDef->Reg))
6237 return std::nullopt;
6238
6239 // It's cheaper to materialize a single 32-bit zero for vaddr than the two
6240 // moves required to copy a 64-bit SGPR to VGPR.
6241 MachineInstr *MI = Root.getParent();
6242 MachineBasicBlock *MBB = MI->getParent();
6243 Register VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6244
6245 BuildMI(*MBB, MI, MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
6246 .addImm(0);
6247
6248 if (NeedIOffset)
6249 return {{
6250 [=](MachineInstrBuilder &MIB) { MIB.addReg(AddrDef->Reg); }, // saddr
6251 [=](MachineInstrBuilder &MIB) { MIB.addReg(VOffset); }, // voffset
6252 [=](MachineInstrBuilder &MIB) { MIB.addImm(ImmOffset); }, // offset
6253 [=](MachineInstrBuilder &MIB) { MIB.addImm(CPolBits); } // cpol
6254 }};
6255 return {{
6256 [=](MachineInstrBuilder &MIB) { MIB.addReg(AddrDef->Reg); }, // saddr
6257 [=](MachineInstrBuilder &MIB) { MIB.addReg(VOffset); }, // voffset
6258 [=](MachineInstrBuilder &MIB) { MIB.addImm(CPolBits); } // cpol
6259 }};
6260}
6261
6263AMDGPUInstructionSelector::selectGlobalSAddr(MachineOperand &Root) const {
6264 return selectGlobalSAddr(Root, 0);
6265}
6266
6268AMDGPUInstructionSelector::selectGlobalSAddrCPol(MachineOperand &Root) const {
6269 const MachineInstr &I = *Root.getParent();
6270
6271 // We are assuming CPol is always the last operand of the intrinsic.
6272 auto PassedCPol =
6273 I.getOperand(I.getNumOperands() - 1).getImm() & ~AMDGPU::CPol::SCAL;
6274 return selectGlobalSAddr(Root, PassedCPol);
6275}
6276
6278AMDGPUInstructionSelector::selectGlobalSAddrCPolM0(MachineOperand &Root) const {
6279 const MachineInstr &I = *Root.getParent();
6280
6281 // We are assuming CPol is second from last operand of the intrinsic.
6282 auto PassedCPol =
6283 I.getOperand(I.getNumOperands() - 2).getImm() & ~AMDGPU::CPol::SCAL;
6284 return selectGlobalSAddr(Root, PassedCPol);
6285}
6286
6288AMDGPUInstructionSelector::selectGlobalSAddrGLC(MachineOperand &Root) const {
6289 return selectGlobalSAddr(Root, AMDGPU::CPol::GLC);
6290}
6291
6293AMDGPUInstructionSelector::selectGlobalSAddrNoIOffset(
6294 MachineOperand &Root) const {
6295 const MachineInstr &I = *Root.getParent();
6296
6297 // We are assuming CPol is always the last operand of the intrinsic.
6298 auto PassedCPol =
6299 I.getOperand(I.getNumOperands() - 1).getImm() & ~AMDGPU::CPol::SCAL;
6300 return selectGlobalSAddr(Root, PassedCPol, false);
6301}
6302
6304AMDGPUInstructionSelector::selectGlobalSAddrNoIOffsetM0(
6305 MachineOperand &Root) const {
6306 const MachineInstr &I = *Root.getParent();
6307
6308 // We are assuming CPol is second from last operand of the intrinsic.
6309 auto PassedCPol =
6310 I.getOperand(I.getNumOperands() - 2).getImm() & ~AMDGPU::CPol::SCAL;
6311 return selectGlobalSAddr(Root, PassedCPol, false);
6312}
6313
6315AMDGPUInstructionSelector::selectScratchSAddr(MachineOperand &Root) const {
6316 Register Addr = Root.getReg();
6317 Register PtrBase;
6318 int64_t ConstOffset;
6319 int64_t ImmOffset = 0;
6320
6321 // Match the immediate offset first, which canonically is moved as low as
6322 // possible.
6323 std::tie(PtrBase, ConstOffset, std::ignore) =
6324 getPtrBaseWithConstantOffset(Addr, *MRI);
6325
6326 if (ConstOffset != 0 && isFlatScratchBaseLegal(Addr) &&
6327 TII.isLegalFLATOffset(ConstOffset, AMDGPUAS::PRIVATE_ADDRESS,
6329 Addr = PtrBase;
6330 ImmOffset = ConstOffset;
6331 }
6332
6333 auto AddrDef = getDefSrcRegIgnoringCopies(Addr, *MRI);
6334 if (AddrDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6335 int FI = AddrDef->MI->getOperand(1).getIndex();
6336 return {{
6337 [=](MachineInstrBuilder &MIB) { MIB.addFrameIndex(FI); }, // saddr
6338 [=](MachineInstrBuilder &MIB) { MIB.addImm(ImmOffset); } // offset
6339 }};
6340 }
6341
6342 Register SAddr = AddrDef->Reg;
6343
6344 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6345 Register LHS = AddrDef->MI->getOperand(1).getReg();
6346 Register RHS = AddrDef->MI->getOperand(2).getReg();
6347 auto LHSDef = getDefSrcRegIgnoringCopies(LHS, *MRI);
6348 auto RHSDef = getDefSrcRegIgnoringCopies(RHS, *MRI);
6349
6350 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX &&
6351 isSGPR(RHSDef->Reg)) {
6352 int FI = LHSDef->MI->getOperand(1).getIndex();
6353 MachineInstr &I = *Root.getParent();
6354 MachineBasicBlock *BB = I.getParent();
6355 const DebugLoc &DL = I.getDebugLoc();
6356 SAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6357
6358 BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADD_I32), SAddr)
6359 .addFrameIndex(FI)
6360 .addReg(RHSDef->Reg)
6361 .setOperandDead(3); // Dead scc
6362 }
6363 }
6364
6365 if (!isSGPR(SAddr))
6366 return std::nullopt;
6367
6368 return {{
6369 [=](MachineInstrBuilder &MIB) { MIB.addReg(SAddr); }, // saddr
6370 [=](MachineInstrBuilder &MIB) { MIB.addImm(ImmOffset); } // offset
6371 }};
6372}
6373
6374// Check whether the flat scratch SVS swizzle bug affects this access.
6375bool AMDGPUInstructionSelector::checkFlatScratchSVSSwizzleBug(
6376 Register VAddr, Register SAddr, uint64_t ImmOffset) const {
6377 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
6378 return false;
6379
6380 // The bug affects the swizzling of SVS accesses if there is any carry out
6381 // from the two low order bits (i.e. from bit 1 into bit 2) when adding
6382 // voffset to (soffset + inst_offset).
6383 auto VKnown = VT->getKnownBits(VAddr);
6384 auto SKnown = KnownBits::add(VT->getKnownBits(SAddr),
6385 KnownBits::makeConstant(APInt(32, ImmOffset)));
6386 uint64_t VMax = VKnown.getMaxValue().getZExtValue();
6387 uint64_t SMax = SKnown.getMaxValue().getZExtValue();
6388 return (VMax & 3) + (SMax & 3) >= 4;
6389}
6390
6392AMDGPUInstructionSelector::selectScratchSVAddr(MachineOperand &Root) const {
6393 Register Addr = Root.getReg();
6394 Register PtrBase;
6395 int64_t ConstOffset;
6396 int64_t ImmOffset = 0;
6397
6398 // Match the immediate offset first, which canonically is moved as low as
6399 // possible.
6400 std::tie(PtrBase, ConstOffset, std::ignore) =
6401 getPtrBaseWithConstantOffset(Addr, *MRI);
6402
6403 Register OrigAddr = Addr;
6404 if (ConstOffset != 0 &&
6405 TII.isLegalFLATOffset(ConstOffset, AMDGPUAS::PRIVATE_ADDRESS,
6407 Addr = PtrBase;
6408 ImmOffset = ConstOffset;
6409 }
6410
6411 auto AddrDef = getDefSrcRegIgnoringCopies(Addr, *MRI);
6412 if (AddrDef->MI->getOpcode() != AMDGPU::G_PTR_ADD)
6413 return std::nullopt;
6414
6415 Register RHS = AddrDef->MI->getOperand(2).getReg();
6416 if (RBI.getRegBank(RHS, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
6417 return std::nullopt;
6418
6419 Register LHS = AddrDef->MI->getOperand(1).getReg();
6420 auto LHSDef = getDefSrcRegIgnoringCopies(LHS, *MRI);
6421
6422 if (OrigAddr != Addr) {
6423 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
6424 return std::nullopt;
6425 } else {
6426 if (!isFlatScratchBaseLegalSV(OrigAddr))
6427 return std::nullopt;
6428 }
6429
6430 if (checkFlatScratchSVSSwizzleBug(RHS, LHS, ImmOffset))
6431 return std::nullopt;
6432
6433 unsigned CPol = selectScaleOffset(Root, RHS, true /* IsSigned */)
6435 : 0;
6436
6437 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6438 int FI = LHSDef->MI->getOperand(1).getIndex();
6439 return {{
6440 [=](MachineInstrBuilder &MIB) { MIB.addReg(RHS); }, // vaddr
6441 [=](MachineInstrBuilder &MIB) { MIB.addFrameIndex(FI); }, // saddr
6442 [=](MachineInstrBuilder &MIB) { MIB.addImm(ImmOffset); }, // offset
6443 [=](MachineInstrBuilder &MIB) { MIB.addImm(CPol); } // cpol
6444 }};
6445 }
6446
6447 if (!isSGPR(LHS))
6448 if (auto Def = getDefSrcRegIgnoringCopies(LHS, *MRI))
6449 LHS = Def->Reg;
6450
6451 if (!isSGPR(LHS))
6452 return std::nullopt;
6453
6454 return {{
6455 [=](MachineInstrBuilder &MIB) { MIB.addReg(RHS); }, // vaddr
6456 [=](MachineInstrBuilder &MIB) { MIB.addReg(LHS); }, // saddr
6457 [=](MachineInstrBuilder &MIB) { MIB.addImm(ImmOffset); }, // offset
6458 [=](MachineInstrBuilder &MIB) { MIB.addImm(CPol); } // cpol
6459 }};
6460}
6461
6463AMDGPUInstructionSelector::selectMUBUFScratchOffen(MachineOperand &Root) const {
6464 MachineInstr *MI = Root.getParent();
6465 MachineBasicBlock *MBB = MI->getParent();
6467 const SIMachineFunctionInfo *Info = MF->getInfo<SIMachineFunctionInfo>();
6468
6469 int64_t Offset = 0;
6470 if (mi_match(Root.getReg(), *MRI, m_ICst(Offset)) &&
6472 Register HighBits = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6473
6474 // TODO: Should this be inside the render function? The iterator seems to
6475 // move.
6476 const int64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(*Subtarget);
6477 BuildMI(*MBB, MI, MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6478 HighBits)
6479 .addImm(Offset & ~MaxOffset);
6480
6481 return {{[=](MachineInstrBuilder &MIB) { // rsrc
6482 MIB.addReg(Info->getScratchRSrcReg());
6483 },
6484 [=](MachineInstrBuilder &MIB) { // vaddr
6485 MIB.addReg(HighBits);
6486 },
6487 [=](MachineInstrBuilder &MIB) { // soffset
6488 // Use constant zero for soffset and rely on eliminateFrameIndex
6489 // to choose the appropriate frame register if need be.
6490 MIB.addImm(0);
6491 },
6492 [=](MachineInstrBuilder &MIB) { // offset
6493 MIB.addImm(Offset & MaxOffset);
6494 }}};
6495 }
6496
6497 assert(Offset == 0 || Offset == -1);
6498
6499 // Try to fold a frame index directly into the MUBUF vaddr field, and any
6500 // offsets.
6501 std::optional<int> FI;
6502 Register VAddr = Root.getReg();
6503
6504 Register PtrBase;
6505 int64_t ConstOffset;
6506 std::tie(PtrBase, ConstOffset, std::ignore) =
6507 getPtrBaseWithConstantOffset(VAddr, *MRI);
6508 int MatchedFI;
6509 if (ConstOffset != 0) {
6510 if (TII.isLegalMUBUFImmOffset(ConstOffset) &&
6511 (!STI.privateMemoryResourceIsRangeChecked() ||
6512 VT->signBitIsZero(PtrBase))) {
6513 if (mi_match(PtrBase, *MRI, m_GFrameIndex(MatchedFI)))
6514 FI = MatchedFI;
6515 else
6516 VAddr = PtrBase;
6517 Offset = ConstOffset;
6518 }
6519 } else if (mi_match(Root.getReg(), *MRI, m_GFrameIndex(MatchedFI))) {
6520 FI = MatchedFI;
6521 }
6522
6523 return {{[=](MachineInstrBuilder &MIB) { // rsrc
6524 MIB.addReg(Info->getScratchRSrcReg());
6525 },
6526 [=](MachineInstrBuilder &MIB) { // vaddr
6527 if (FI)
6528 MIB.addFrameIndex(*FI);
6529 else
6530 MIB.addReg(VAddr);
6531 },
6532 [=](MachineInstrBuilder &MIB) { // soffset
6533 // Use constant zero for soffset and rely on eliminateFrameIndex
6534 // to choose the appropriate frame register if need be.
6535 MIB.addImm(0);
6536 },
6537 [=](MachineInstrBuilder &MIB) { // offset
6538 MIB.addImm(Offset);
6539 }}};
6540}
6541
6542bool AMDGPUInstructionSelector::isDSOffsetLegal(Register Base,
6543 int64_t Offset) const {
6544 if (!isUInt<16>(Offset))
6545 return false;
6546
6547 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6548 return true;
6549
6550 // On Southern Islands instruction with a negative base value and an offset
6551 // don't seem to work.
6552 return VT->signBitIsZero(Base);
6553}
6554
6555bool AMDGPUInstructionSelector::isDSOffset2Legal(Register Base, int64_t Offset0,
6556 int64_t Offset1,
6557 unsigned Size) const {
6558 if (Offset0 % Size != 0 || Offset1 % Size != 0)
6559 return false;
6560 if (!isUInt<8>(Offset0 / Size) || !isUInt<8>(Offset1 / Size))
6561 return false;
6562
6563 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6564 return true;
6565
6566 // On Southern Islands instruction with a negative base value and an offset
6567 // don't seem to work.
6568 return VT->signBitIsZero(Base);
6569}
6570
6571// Return whether the operation has NoUnsignedWrap property.
6572static bool isNoUnsignedWrap(MachineInstr *Addr) {
6573 return Addr->getOpcode() == TargetOpcode::G_OR ||
6574 (Addr->getOpcode() == TargetOpcode::G_PTR_ADD &&
6576}
6577
6578// Check that the base address of flat scratch load/store in the form of `base +
6579// offset` is legal to be put in SGPR/VGPR (i.e. unsigned per hardware
6580// requirement). We always treat the first operand as the base address here.
6581bool AMDGPUInstructionSelector::isFlatScratchBaseLegal(Register Addr) const {
6582 MachineInstr *AddrMI = getDefIgnoringCopies(Addr, *MRI);
6583
6584 if (isNoUnsignedWrap(AddrMI))
6585 return true;
6586
6587 // Starting with GFX12, VADDR and SADDR fields in VSCRATCH can use negative
6588 // values.
6589 if (STI.hasSignedScratchOffsets())
6590 return true;
6591
6592 Register LHS = AddrMI->getOperand(1).getReg();
6593 Register RHS = AddrMI->getOperand(2).getReg();
6594
6595 if (AddrMI->getOpcode() == TargetOpcode::G_PTR_ADD) {
6596 std::optional<ValueAndVReg> RhsValReg =
6598 // If the immediate offset is negative and within certain range, the base
6599 // address cannot also be negative. If the base is also negative, the sum
6600 // would be either negative or much larger than the valid range of scratch
6601 // memory a thread can access.
6602 if (RhsValReg && RhsValReg->Value.getSExtValue() < 0 &&
6603 RhsValReg->Value.getSExtValue() > -0x40000000)
6604 return true;
6605 }
6606
6607 return VT->signBitIsZero(LHS);
6608}
6609
6610// Check address value in SGPR/VGPR are legal for flat scratch in the form
6611// of: SGPR + VGPR.
6612bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSV(Register Addr) const {
6613 MachineInstr *AddrMI = getDefIgnoringCopies(Addr, *MRI);
6614
6615 if (isNoUnsignedWrap(AddrMI))
6616 return true;
6617
6618 // Starting with GFX12, VADDR and SADDR fields in VSCRATCH can use negative
6619 // values.
6620 if (STI.hasSignedScratchOffsets())
6621 return true;
6622
6623 Register LHS = AddrMI->getOperand(1).getReg();
6624 Register RHS = AddrMI->getOperand(2).getReg();
6625 return VT->signBitIsZero(RHS) && VT->signBitIsZero(LHS);
6626}
6627
6628// Check address value in SGPR/VGPR are legal for flat scratch in the form
6629// of: SGPR + VGPR + Imm.
6630bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSVImm(
6631 Register Addr) const {
6632 // Starting with GFX12, VADDR and SADDR fields in VSCRATCH can use negative
6633 // values.
6634 if (STI.hasSignedScratchOffsets())
6635 return true;
6636
6637 MachineInstr *AddrMI = getDefIgnoringCopies(Addr, *MRI);
6638 Register Base = AddrMI->getOperand(1).getReg();
6639 std::optional<DefinitionAndSourceRegister> BaseDef =
6641 std::optional<ValueAndVReg> RHSOffset =
6643 assert(RHSOffset);
6644
6645 // If the immediate offset is negative and within certain range, the base
6646 // address cannot also be negative. If the base is also negative, the sum
6647 // would be either negative or much larger than the valid range of scratch
6648 // memory a thread can access.
6649 if (isNoUnsignedWrap(BaseDef->MI) &&
6650 (isNoUnsignedWrap(AddrMI) ||
6651 (RHSOffset->Value.getSExtValue() < 0 &&
6652 RHSOffset->Value.getSExtValue() > -0x40000000)))
6653 return true;
6654
6655 Register LHS = BaseDef->MI->getOperand(1).getReg();
6656 Register RHS = BaseDef->MI->getOperand(2).getReg();
6657 return VT->signBitIsZero(RHS) && VT->signBitIsZero(LHS);
6658}
6659
6660bool AMDGPUInstructionSelector::isUnneededShiftMask(const MachineInstr &MI,
6661 unsigned ShAmtBits) const {
6662 assert(MI.getOpcode() == TargetOpcode::G_AND);
6663
6664 std::optional<APInt> RHS =
6665 getIConstantVRegVal(MI.getOperand(2).getReg(), *MRI);
6666 if (!RHS)
6667 return false;
6668
6669 if (RHS->countr_one() >= ShAmtBits)
6670 return true;
6671
6672 const APInt &LHSKnownZeros = VT->getKnownZeroes(MI.getOperand(1).getReg());
6673 return (LHSKnownZeros | *RHS).countr_one() >= ShAmtBits;
6674}
6675
6677AMDGPUInstructionSelector::selectMUBUFScratchOffset(
6678 MachineOperand &Root) const {
6679 Register Reg = Root.getReg();
6680 const SIMachineFunctionInfo *Info = MF->getInfo<SIMachineFunctionInfo>();
6681
6682 std::optional<DefinitionAndSourceRegister> Def =
6684 assert(Def && "this shouldn't be an optional result");
6685 Reg = Def->Reg;
6686
6687 if (Register WaveBase = getWaveAddress(Def->MI)) {
6688 return {{
6689 [=](MachineInstrBuilder &MIB) { // rsrc
6690 MIB.addReg(Info->getScratchRSrcReg());
6691 },
6692 [=](MachineInstrBuilder &MIB) { // soffset
6693 MIB.addReg(WaveBase);
6694 },
6695 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); } // offset
6696 }};
6697 }
6698
6699 int64_t Offset = 0;
6700
6701 // FIXME: Copy check is a hack
6703 if (mi_match(Reg, *MRI,
6704 m_GPtrAdd(m_Reg(BasePtr),
6706 if (!TII.isLegalMUBUFImmOffset(Offset))
6707 return {};
6708 MachineInstr *BasePtrDef = getDefIgnoringCopies(BasePtr, *MRI);
6709 Register WaveBase = getWaveAddress(BasePtrDef);
6710 if (!WaveBase)
6711 return {};
6712
6713 return {{
6714 [=](MachineInstrBuilder &MIB) { // rsrc
6715 MIB.addReg(Info->getScratchRSrcReg());
6716 },
6717 [=](MachineInstrBuilder &MIB) { // soffset
6718 MIB.addReg(WaveBase);
6719 },
6720 [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); } // offset
6721 }};
6722 }
6723
6724 if (!mi_match(Root.getReg(), *MRI, m_ICst(Offset)) ||
6725 !TII.isLegalMUBUFImmOffset(Offset))
6726 return {};
6727
6728 return {{
6729 [=](MachineInstrBuilder &MIB) { // rsrc
6730 MIB.addReg(Info->getScratchRSrcReg());
6731 },
6732 [=](MachineInstrBuilder &MIB) { // soffset
6733 MIB.addImm(0);
6734 },
6735 [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); } // offset
6736 }};
6737}
6738
6739std::pair<Register, unsigned>
6740AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(
6741 MachineOperand &Root) const {
6742 int64_t ConstAddr = 0;
6743
6744 Register PtrBase;
6745 int64_t Offset;
6746 std::tie(PtrBase, Offset, std::ignore) =
6747 getPtrBaseWithConstantOffset(Root.getReg(), *MRI);
6748
6749 if (Offset) {
6750 if (isDSOffsetLegal(PtrBase, Offset)) {
6751 // (add n0, c0)
6752 return std::pair(PtrBase, Offset);
6753 }
6754 } else if (mi_match(Root.getReg(), *MRI, m_GSub(m_Reg(), m_Reg()))) {
6755 // TODO
6756
6757 } else if (mi_match(Root.getReg(), *MRI, m_ICst(ConstAddr))) {
6758 // TODO
6759 }
6760
6761 return std::pair(Root.getReg(), 0);
6762}
6763
6765AMDGPUInstructionSelector::selectDS1Addr1Offset(MachineOperand &Root) const {
6766 Register Reg;
6767 unsigned Offset;
6768 std::tie(Reg, Offset) = selectDS1Addr1OffsetImpl(Root);
6769 return {{
6770 [=](MachineInstrBuilder &MIB) { MIB.addReg(Reg); },
6771 [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); }
6772 }};
6773}
6774
6776AMDGPUInstructionSelector::selectDS64Bit4ByteAligned(MachineOperand &Root) const {
6777 return selectDSReadWrite2(Root, 4);
6778}
6779
6781AMDGPUInstructionSelector::selectDS128Bit8ByteAligned(MachineOperand &Root) const {
6782 return selectDSReadWrite2(Root, 8);
6783}
6784
6786AMDGPUInstructionSelector::selectDSReadWrite2(MachineOperand &Root,
6787 unsigned Size) const {
6788 Register Reg;
6789 unsigned Offset;
6790 std::tie(Reg, Offset) = selectDSReadWrite2Impl(Root, Size);
6791 return {{
6792 [=](MachineInstrBuilder &MIB) { MIB.addReg(Reg); },
6793 [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); },
6794 [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset+1); }
6795 }};
6796}
6797
6798std::pair<Register, unsigned>
6799AMDGPUInstructionSelector::selectDSReadWrite2Impl(MachineOperand &Root,
6800 unsigned Size) const {
6801 int64_t ConstAddr = 0;
6802
6803 Register PtrBase;
6804 int64_t Offset;
6805 std::tie(PtrBase, Offset, std::ignore) =
6806 getPtrBaseWithConstantOffset(Root.getReg(), *MRI);
6807
6808 if (Offset) {
6809 int64_t OffsetValue0 = Offset;
6810 int64_t OffsetValue1 = Offset + Size;
6811 if (isDSOffset2Legal(PtrBase, OffsetValue0, OffsetValue1, Size)) {
6812 // (add n0, c0)
6813 return std::pair(PtrBase, OffsetValue0 / Size);
6814 }
6815 } else if (mi_match(Root.getReg(), *MRI, m_GSub(m_Reg(), m_Reg()))) {
6816 // TODO
6817
6818 } else if (mi_match(Root.getReg(), *MRI, m_ICst(ConstAddr))) {
6819 // TODO
6820 }
6821
6822 return std::pair(Root.getReg(), 0);
6823}
6824
6825/// If \p Root is a G_PTR_ADD with a G_CONSTANT on the right hand side, return
6826/// the base value with the constant offset, and if the offset computation is
6827/// known to be inbounds. There may be intervening copies between \p Root and
6828/// the identified constant. Returns \p Root, 0, false if this does not match
6829/// the pattern.
6830std::tuple<Register, int64_t, bool>
6831AMDGPUInstructionSelector::getPtrBaseWithConstantOffset(
6832 Register Root, const MachineRegisterInfo &MRI) const {
6833 MachineInstr *RootI = getDefIgnoringCopies(Root, MRI);
6834 if (RootI->getOpcode() != TargetOpcode::G_PTR_ADD)
6835 return {Root, 0, false};
6836
6837 MachineOperand &RHS = RootI->getOperand(2);
6838 std::optional<ValueAndVReg> MaybeOffset =
6840 if (!MaybeOffset)
6841 return {Root, 0, false};
6842 bool IsInBounds = RootI->getFlag(MachineInstr::MIFlag::InBounds);
6843 return {RootI->getOperand(1).getReg(), MaybeOffset->Value.getSExtValue(),
6844 IsInBounds};
6845}
6846
6848 MIB.addImm(0);
6849}
6850
6851/// Return a resource descriptor for use with an arbitrary 64-bit pointer. If \p
6852/// BasePtr is not valid, a null base pointer will be used.
6854 uint32_t FormatLo, uint32_t FormatHi,
6855 Register BasePtr) {
6856 Register RSrc2 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6857 Register RSrc3 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
6858 Register RSrcHi = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
6859 Register RSrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
6860
6861 B.buildInstr(AMDGPU::S_MOV_B32)
6862 .addDef(RSrc2)
6863 .addImm(FormatLo);
6864 B.buildInstr(AMDGPU::S_MOV_B32)
6865 .addDef(RSrc3)
6866 .addImm(FormatHi);
6867
6868 // Build the half of the subregister with the constants before building the
6869 // full 128-bit register. If we are building multiple resource descriptors,
6870 // this will allow CSEing of the 2-component register.
6871 B.buildInstr(AMDGPU::REG_SEQUENCE)
6872 .addDef(RSrcHi)
6873 .addReg(RSrc2)
6874 .addImm(AMDGPU::sub0)
6875 .addReg(RSrc3)
6876 .addImm(AMDGPU::sub1);
6877
6878 Register RSrcLo = BasePtr;
6879 if (!BasePtr) {
6880 RSrcLo = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
6881 B.buildInstr(AMDGPU::S_MOV_B64)
6882 .addDef(RSrcLo)
6883 .addImm(0);
6884 }
6885
6886 B.buildInstr(AMDGPU::REG_SEQUENCE)
6887 .addDef(RSrc)
6888 .addReg(RSrcLo)
6889 .addImm(AMDGPU::sub0_sub1)
6890 .addReg(RSrcHi)
6891 .addImm(AMDGPU::sub2_sub3);
6892
6893 return RSrc;
6894}
6895
6897 const SIInstrInfo &TII, Register BasePtr) {
6898 uint64_t DefaultFormat = TII.getDefaultRsrcDataFormat();
6899
6900 // FIXME: Why are half the "default" bits ignored based on the addressing
6901 // mode?
6902 return buildRSRC(B, MRI, 0, Hi_32(DefaultFormat), BasePtr);
6903}
6904
6906 const SIInstrInfo &TII, Register BasePtr) {
6907 uint64_t DefaultFormat = TII.getDefaultRsrcDataFormat();
6908
6909 // FIXME: Why are half the "default" bits ignored based on the addressing
6910 // mode?
6911 return buildRSRC(B, MRI, -1, Hi_32(DefaultFormat), BasePtr);
6912}
6913
6914AMDGPUInstructionSelector::MUBUFAddressData
6915AMDGPUInstructionSelector::parseMUBUFAddress(Register Src) const {
6916 MUBUFAddressData Data;
6917 Data.N0 = Src;
6918
6919 Register PtrBase;
6920 int64_t Offset;
6921
6922 std::tie(PtrBase, Offset, std::ignore) =
6923 getPtrBaseWithConstantOffset(Src, *MRI);
6924 if (isUInt<32>(Offset)) {
6925 Data.N0 = PtrBase;
6926 Data.Offset = Offset;
6927 }
6928
6929 if (MachineInstr *InputAdd
6930 = getOpcodeDef(TargetOpcode::G_PTR_ADD, Data.N0, *MRI)) {
6931 Data.N2 = InputAdd->getOperand(1).getReg();
6932 Data.N3 = InputAdd->getOperand(2).getReg();
6933
6934 // FIXME: Need to fix extra SGPR->VGPRcopies inserted
6935 // FIXME: Don't know this was defined by operand 0
6936 //
6937 // TODO: Remove this when we have copy folding optimizations after
6938 // RegBankSelect.
6939 Data.N2 = getDefIgnoringCopies(Data.N2, *MRI)->getOperand(0).getReg();
6940 Data.N3 = getDefIgnoringCopies(Data.N3, *MRI)->getOperand(0).getReg();
6941 }
6942
6943 return Data;
6944}
6945
6946/// Return if the addr64 mubuf mode should be used for the given address.
6947bool AMDGPUInstructionSelector::shouldUseAddr64(MUBUFAddressData Addr) const {
6948 // (ptr_add N2, N3) -> addr64, or
6949 // (ptr_add (ptr_add N2, N3), C1) -> addr64
6950 if (Addr.N2)
6951 return true;
6952
6953 const RegisterBank *N0Bank = RBI.getRegBank(Addr.N0, *MRI, TRI);
6954 return N0Bank->getID() == AMDGPU::VGPRRegBankID;
6955}
6956
6957/// Split an immediate offset \p ImmOffset depending on whether it fits in the
6958/// immediate field. Modifies \p ImmOffset and sets \p SOffset to the variable
6959/// component.
6960void AMDGPUInstructionSelector::splitIllegalMUBUFOffset(
6961 MachineIRBuilder &B, Register &SOffset, int64_t &ImmOffset) const {
6962 if (TII.isLegalMUBUFImmOffset(ImmOffset))
6963 return;
6964
6965 // Illegal offset, store it in soffset.
6966 SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6967 B.buildInstr(AMDGPU::S_MOV_B32)
6968 .addDef(SOffset)
6969 .addImm(ImmOffset);
6970 ImmOffset = 0;
6971}
6972
6973bool AMDGPUInstructionSelector::selectMUBUFAddr64Impl(
6974 MachineOperand &Root, Register &VAddr, Register &RSrcReg,
6975 Register &SOffset, int64_t &Offset) const {
6976 // FIXME: Predicates should stop this from reaching here.
6977 // addr64 bit was removed for volcanic islands.
6978 if (!STI.hasAddr64() || STI.useFlatForGlobal())
6979 return false;
6980
6981 MUBUFAddressData AddrData = parseMUBUFAddress(Root.getReg());
6982 if (!shouldUseAddr64(AddrData))
6983 return false;
6984
6985 Register N0 = AddrData.N0;
6986 Register N2 = AddrData.N2;
6987 Register N3 = AddrData.N3;
6988 Offset = AddrData.Offset;
6989
6990 // Base pointer for the SRD.
6991 Register SRDPtr;
6992
6993 if (N2) {
6994 if (RBI.getRegBank(N2, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
6995 assert(N3);
6996 if (RBI.getRegBank(N3, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
6997 // Both N2 and N3 are divergent. Use N0 (the result of the add) as the
6998 // addr64, and construct the default resource from a 0 address.
6999 VAddr = N0;
7000 } else {
7001 SRDPtr = N3;
7002 VAddr = N2;
7003 }
7004 } else {
7005 // N2 is not divergent.
7006 SRDPtr = N2;
7007 VAddr = N3;
7008 }
7009 } else if (RBI.getRegBank(N0, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7010 // Use the default null pointer in the resource
7011 VAddr = N0;
7012 } else {
7013 // N0 -> offset, or
7014 // (N0 + C1) -> offset
7015 SRDPtr = N0;
7016 }
7017
7018 MachineIRBuilder B(*Root.getParent());
7019 RSrcReg = buildAddr64RSrc(B, *MRI, TII, SRDPtr);
7020 splitIllegalMUBUFOffset(B, SOffset, Offset);
7021 return true;
7022}
7023
7024bool AMDGPUInstructionSelector::selectMUBUFOffsetImpl(
7025 MachineOperand &Root, Register &RSrcReg, Register &SOffset,
7026 int64_t &Offset) const {
7027
7028 // FIXME: Pattern should not reach here.
7029 if (STI.useFlatForGlobal())
7030 return false;
7031
7032 MUBUFAddressData AddrData = parseMUBUFAddress(Root.getReg());
7033 if (shouldUseAddr64(AddrData))
7034 return false;
7035
7036 // N0 -> offset, or
7037 // (N0 + C1) -> offset
7038 Register SRDPtr = AddrData.N0;
7039 Offset = AddrData.Offset;
7040
7041 // TODO: Look through extensions for 32-bit soffset.
7042 MachineIRBuilder B(*Root.getParent());
7043
7044 RSrcReg = buildOffsetSrc(B, *MRI, TII, SRDPtr);
7045 splitIllegalMUBUFOffset(B, SOffset, Offset);
7046 return true;
7047}
7048
7050AMDGPUInstructionSelector::selectMUBUFAddr64(MachineOperand &Root) const {
7051 Register VAddr;
7052 Register RSrcReg;
7053 Register SOffset;
7054 int64_t Offset = 0;
7055
7056 if (!selectMUBUFAddr64Impl(Root, VAddr, RSrcReg, SOffset, Offset))
7057 return {};
7058
7059 // FIXME: Use defaulted operands for trailing 0s and remove from the complex
7060 // pattern.
7061 return {{
7062 [=](MachineInstrBuilder &MIB) { // rsrc
7063 MIB.addReg(RSrcReg);
7064 },
7065 [=](MachineInstrBuilder &MIB) { // vaddr
7066 MIB.addReg(VAddr);
7067 },
7068 [=](MachineInstrBuilder &MIB) { // soffset
7069 if (SOffset)
7070 MIB.addReg(SOffset);
7071 else if (STI.hasRestrictedSOffset())
7072 MIB.addReg(AMDGPU::SGPR_NULL);
7073 else
7074 MIB.addImm(0);
7075 },
7076 [=](MachineInstrBuilder &MIB) { // offset
7077 MIB.addImm(Offset);
7078 },
7079 addZeroImm, // cpol
7080 addZeroImm, // tfe
7081 addZeroImm // swz
7082 }};
7083}
7084
7086AMDGPUInstructionSelector::selectMUBUFOffset(MachineOperand &Root) const {
7087 Register RSrcReg;
7088 Register SOffset;
7089 int64_t Offset = 0;
7090
7091 if (!selectMUBUFOffsetImpl(Root, RSrcReg, SOffset, Offset))
7092 return {};
7093
7094 return {{
7095 [=](MachineInstrBuilder &MIB) { // rsrc
7096 MIB.addReg(RSrcReg);
7097 },
7098 [=](MachineInstrBuilder &MIB) { // soffset
7099 if (SOffset)
7100 MIB.addReg(SOffset);
7101 else if (STI.hasRestrictedSOffset())
7102 MIB.addReg(AMDGPU::SGPR_NULL);
7103 else
7104 MIB.addImm(0);
7105 },
7106 [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); }, // offset
7107 addZeroImm, // cpol
7108 addZeroImm, // tfe
7109 addZeroImm, // swz
7110 }};
7111}
7112
7114AMDGPUInstructionSelector::selectBUFSOffset(MachineOperand &Root) const {
7115
7116 Register SOffset = Root.getReg();
7117
7118 if (STI.hasRestrictedSOffset() && mi_match(SOffset, *MRI, m_ZeroInt()))
7119 SOffset = AMDGPU::SGPR_NULL;
7120
7121 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(SOffset); }}};
7122}
7123
7124/// Get an immediate that must be 32-bits, and treated as zero extended.
7125static std::optional<uint64_t>
7127 // getIConstantVRegVal sexts any values, so see if that matters.
7128 std::optional<int64_t> OffsetVal = getIConstantVRegSExtVal(Reg, MRI);
7129 if (!OffsetVal || !isInt<32>(*OffsetVal))
7130 return std::nullopt;
7131 return Lo_32(*OffsetVal);
7132}
7133
7135AMDGPUInstructionSelector::selectSMRDBufferImm(MachineOperand &Root) const {
7136 std::optional<uint64_t> OffsetVal =
7137 Root.isImm() ? Root.getImm() : getConstantZext32Val(Root.getReg(), *MRI);
7138 if (!OffsetVal)
7139 return {};
7140
7141 std::optional<int64_t> EncodedImm =
7142 AMDGPU::getSMRDEncodedOffset(STI, *OffsetVal, true);
7143 if (!EncodedImm)
7144 return {};
7145
7146 return {{ [=](MachineInstrBuilder &MIB) { MIB.addImm(*EncodedImm); } }};
7147}
7148
7150AMDGPUInstructionSelector::selectSMRDBufferImm32(MachineOperand &Root) const {
7151 assert(STI.getGeneration() == AMDGPUSubtarget::SEA_ISLANDS);
7152
7153 std::optional<uint64_t> OffsetVal = getConstantZext32Val(Root.getReg(), *MRI);
7154 if (!OffsetVal)
7155 return {};
7156
7157 std::optional<int64_t> EncodedImm =
7159 if (!EncodedImm)
7160 return {};
7161
7162 return {{ [=](MachineInstrBuilder &MIB) { MIB.addImm(*EncodedImm); } }};
7163}
7164
7166AMDGPUInstructionSelector::selectSMRDBufferSgprImm(MachineOperand &Root) const {
7167 // Match the (soffset + offset) pair as a 32-bit register base and
7168 // an immediate offset.
7169 Register SOffset;
7170 unsigned Offset;
7171 std::tie(SOffset, Offset) = AMDGPU::getBaseWithConstantOffset(
7172 *MRI, Root.getReg(), VT, /*CheckNUW*/ true);
7173 if (!SOffset)
7174 return std::nullopt;
7175
7176 std::optional<int64_t> EncodedOffset =
7177 AMDGPU::getSMRDEncodedOffset(STI, Offset, /* IsBuffer */ true);
7178 if (!EncodedOffset)
7179 return std::nullopt;
7180
7181 assert(MRI->getType(SOffset).getSizeInBits() == 32);
7182 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(SOffset); },
7183 [=](MachineInstrBuilder &MIB) { MIB.addImm(*EncodedOffset); }}};
7184}
7185
7186std::pair<Register, unsigned>
7187AMDGPUInstructionSelector::selectVOP3PMadMixModsImpl(MachineOperand &Root,
7188 bool &Matched) const {
7189 Matched = false;
7190
7191 Register Src;
7192 unsigned Mods;
7193 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg());
7194
7195 if (mi_match(Src, *MRI, m_GFPExt(m_Reg(Src)))) {
7196 assert(MRI->getType(Src) == LLT::scalar(16));
7197
7198 // Only change Src if src modifier could be gained. In such cases new Src
7199 // could be sgpr but this does not violate constant bus restriction for
7200 // instruction that is being selected.
7201 Src = stripBitCast(Src, *MRI);
7202
7203 const auto CheckAbsNeg = [&]() {
7204 // Be careful about folding modifiers if we already have an abs. fneg is
7205 // applied last, so we don't want to apply an earlier fneg.
7206 if ((Mods & SISrcMods::ABS) == 0) {
7207 unsigned ModsTmp;
7208 std::tie(Src, ModsTmp) = selectVOP3ModsImpl(Src);
7209
7210 if ((ModsTmp & SISrcMods::NEG) != 0)
7211 Mods ^= SISrcMods::NEG;
7212
7213 if ((ModsTmp & SISrcMods::ABS) != 0)
7214 Mods |= SISrcMods::ABS;
7215 }
7216 };
7217
7218 CheckAbsNeg();
7219
7220 // op_sel/op_sel_hi decide the source type and source.
7221 // If the source's op_sel_hi is set, it indicates to do a conversion from
7222 // fp16. If the sources's op_sel is set, it picks the high half of the
7223 // source register.
7224
7225 Mods |= SISrcMods::OP_SEL_1;
7226
7227 if (isExtractHiElt(*MRI, Src, Src)) {
7228 Mods |= SISrcMods::OP_SEL_0;
7229 CheckAbsNeg();
7230 }
7231
7232 Matched = true;
7233 }
7234
7235 return {Src, Mods};
7236}
7237
7239AMDGPUInstructionSelector::selectVOP3PMadMixModsExt(
7240 MachineOperand &Root) const {
7241 Register Src;
7242 unsigned Mods;
7243 bool Matched;
7244 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7245 if (!Matched)
7246 return {};
7247
7248 return {{
7249 [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
7250 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
7251 }};
7252}
7253
7255AMDGPUInstructionSelector::selectVOP3PMadMixMods(MachineOperand &Root) const {
7256 Register Src;
7257 unsigned Mods;
7258 bool Matched;
7259 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7260
7261 return {{
7262 [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
7263 [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
7264 }};
7265}
7266
7268AMDGPUInstructionSelector::selectVOP3PMadMixModsExtNeg(
7269 MachineOperand &Root) const {
7270 Register Src;
7271 unsigned Mods;
7272 bool Matched;
7273 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7274 if (!Matched)
7275 return {};
7276
7277 return {{
7278 [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
7279 [=](MachineInstrBuilder &MIB) {
7280 MIB.addImm(Mods ^ SISrcMods::NEG);
7281 } // src_mods
7282 }};
7283}
7284
7286AMDGPUInstructionSelector::selectVOP3PMadMixModsNeg(
7287 MachineOperand &Root) const {
7288 Register Src;
7289 unsigned Mods;
7290 bool Matched;
7291 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7292
7293 return {{
7294 [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
7295 [=](MachineInstrBuilder &MIB) {
7296 MIB.addImm(Mods ^ SISrcMods::NEG);
7297 } // src_mods
7298 }};
7299}
7300
7301bool AMDGPUInstructionSelector::selectSBarrierSignalIsfirst(
7302 MachineInstr &I, Intrinsic::ID IntrID) const {
7303 MachineBasicBlock *MBB = I.getParent();
7304 const DebugLoc &DL = I.getDebugLoc();
7305 Register CCReg = I.getOperand(0).getReg();
7306
7307 // Set SCC to true, in case the barrier instruction gets converted to a NOP.
7308 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_CMP_EQ_U32)).addImm(0).addImm(0);
7309
7310 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM))
7311 .addImm(I.getOperand(2).getImm());
7312
7313 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::COPY), CCReg).addReg(AMDGPU::SCC);
7314
7315 I.eraseFromParent();
7316 return RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32_XM0_XEXECRegClass,
7317 *MRI);
7318}
7319
7320bool AMDGPUInstructionSelector::selectSGetBarrierState(
7321 MachineInstr &I, Intrinsic::ID IntrID) const {
7322 MachineBasicBlock *MBB = I.getParent();
7323 const DebugLoc &DL = I.getDebugLoc();
7324 const MachineOperand &BarOp = I.getOperand(2);
7325 std::optional<int64_t> BarValImm =
7326 getIConstantVRegSExtVal(BarOp.getReg(), *MRI);
7327
7328 if (!BarValImm) {
7329 auto CopyMIB = BuildMI(*MBB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7330 .addReg(BarOp.getReg());
7331 constrainSelectedInstRegOperands(*CopyMIB, TII, TRI, RBI);
7332 }
7333 MachineInstrBuilder MIB;
7334 unsigned Opc = BarValImm ? AMDGPU::S_GET_BARRIER_STATE_IMM
7335 : AMDGPU::S_GET_BARRIER_STATE_M0;
7336 MIB = BuildMI(*MBB, &I, DL, TII.get(Opc));
7337
7338 auto DstReg = I.getOperand(0).getReg();
7339 const TargetRegisterClass *DstRC =
7340 TRI.getConstrainedRegClassForOperand(I.getOperand(0), *MRI);
7341 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7342 return false;
7343 MIB.addDef(DstReg);
7344 if (BarValImm) {
7345 MIB.addImm(*BarValImm);
7346 }
7347 I.eraseFromParent();
7348 return true;
7349}
7350
7351unsigned getNamedBarrierOp(bool HasInlineConst, Intrinsic::ID IntrID) {
7352 if (HasInlineConst) {
7353 switch (IntrID) {
7354 default:
7355 llvm_unreachable("not a named barrier op");
7356 case Intrinsic::amdgcn_s_barrier_join:
7357 return AMDGPU::S_BARRIER_JOIN_IMM;
7358 case Intrinsic::amdgcn_s_wakeup_barrier:
7359 return AMDGPU::S_WAKEUP_BARRIER_IMM;
7360 case Intrinsic::amdgcn_s_get_named_barrier_state:
7361 return AMDGPU::S_GET_BARRIER_STATE_IMM;
7362 };
7363 } else {
7364 switch (IntrID) {
7365 default:
7366 llvm_unreachable("not a named barrier op");
7367 case Intrinsic::amdgcn_s_barrier_join:
7368 return AMDGPU::S_BARRIER_JOIN_M0;
7369 case Intrinsic::amdgcn_s_wakeup_barrier:
7370 return AMDGPU::S_WAKEUP_BARRIER_M0;
7371 case Intrinsic::amdgcn_s_get_named_barrier_state:
7372 return AMDGPU::S_GET_BARRIER_STATE_M0;
7373 };
7374 }
7375}
7376
7377bool AMDGPUInstructionSelector::selectNamedBarrierInit(
7378 MachineInstr &I, Intrinsic::ID IntrID) const {
7379 MachineBasicBlock *MBB = I.getParent();
7380 const DebugLoc &DL = I.getDebugLoc();
7381 const MachineOperand &BarOp = I.getOperand(1);
7382 const MachineOperand &CntOp = I.getOperand(2);
7383
7384 // A member count of 0 means "keep existing member count". That plus a known
7385 // constant value for the barrier ID lets us use the immarg form.
7386 if (IntrID == Intrinsic::amdgcn_s_barrier_signal_var) {
7387 std::optional<int64_t> CntImm =
7388 getIConstantVRegSExtVal(CntOp.getReg(), *MRI);
7389 if (CntImm && *CntImm == 0) {
7390 std::optional<int64_t> BarValImm =
7391 getIConstantVRegSExtVal(BarOp.getReg(), *MRI);
7392 if (BarValImm) {
7393 auto BarID = ((*BarValImm) >> 4) & 0x3F;
7394 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_IMM))
7395 .addImm(BarID);
7396 I.eraseFromParent();
7397 return true;
7398 }
7399 }
7400 }
7401
7402 // BarID = (BarOp >> 4) & 0x3F
7403 Register TmpReg0 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7404 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_LSHR_B32), TmpReg0)
7405 .add(BarOp)
7406 .addImm(4u)
7407 .setOperandDead(3); // Dead scc
7408
7409 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7410 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_AND_B32), TmpReg1)
7411 .addReg(TmpReg0)
7412 .addImm(0x3F)
7413 .setOperandDead(3); // Dead scc
7414
7415 // MO = ((CntOp & 0x3F) << shAmt) | BarID
7416 Register TmpReg2 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7417 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_AND_B32), TmpReg2)
7418 .add(CntOp)
7419 .addImm(0x3F)
7420 .setOperandDead(3); // Dead scc
7421
7422 Register TmpReg3 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7423 constexpr unsigned ShAmt = 16;
7424 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_LSHL_B32), TmpReg3)
7425 .addReg(TmpReg2)
7426 .addImm(ShAmt)
7427 .setOperandDead(3); // Dead scc
7428
7429 Register TmpReg4 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7430 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_OR_B32), TmpReg4)
7431 .addReg(TmpReg1)
7432 .addReg(TmpReg3)
7433 .setOperandDead(3); // Dead scc;
7434
7435 auto CopyMIB =
7436 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::M0).addReg(TmpReg4);
7437 constrainSelectedInstRegOperands(*CopyMIB, TII, TRI, RBI);
7438
7439 unsigned Opc = IntrID == Intrinsic::amdgcn_s_barrier_init
7440 ? AMDGPU::S_BARRIER_INIT_M0
7441 : AMDGPU::S_BARRIER_SIGNAL_M0;
7442 MachineInstrBuilder MIB;
7443 MIB = BuildMI(*MBB, &I, DL, TII.get(Opc));
7444
7445 I.eraseFromParent();
7446 return true;
7447}
7448
7449bool AMDGPUInstructionSelector::selectNamedBarrierInst(
7450 MachineInstr &I, Intrinsic::ID IntrID) const {
7451 MachineBasicBlock *MBB = I.getParent();
7452 const DebugLoc &DL = I.getDebugLoc();
7453 MachineOperand BarOp = IntrID == Intrinsic::amdgcn_s_get_named_barrier_state
7454 ? I.getOperand(2)
7455 : I.getOperand(1);
7456 std::optional<int64_t> BarValImm =
7457 getIConstantVRegSExtVal(BarOp.getReg(), *MRI);
7458
7459 if (!BarValImm) {
7460 // BarID = (BarOp >> 4) & 0x3F
7461 Register TmpReg0 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7462 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_LSHR_B32), TmpReg0)
7463 .addReg(BarOp.getReg())
7464 .addImm(4u)
7465 .setOperandDead(3); // Dead scc;
7466
7467 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7468 BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_AND_B32), TmpReg1)
7469 .addReg(TmpReg0)
7470 .addImm(0x3F)
7471 .setOperandDead(3); // Dead scc;
7472
7473 auto CopyMIB = BuildMI(*MBB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7474 .addReg(TmpReg1);
7475 constrainSelectedInstRegOperands(*CopyMIB, TII, TRI, RBI);
7476 }
7477
7478 MachineInstrBuilder MIB;
7479 unsigned Opc = getNamedBarrierOp(BarValImm.has_value(), IntrID);
7480 MIB = BuildMI(*MBB, &I, DL, TII.get(Opc));
7481
7482 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
7483 auto DstReg = I.getOperand(0).getReg();
7484 const TargetRegisterClass *DstRC =
7485 TRI.getConstrainedRegClassForOperand(I.getOperand(0), *MRI);
7486 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7487 return false;
7488 MIB.addDef(DstReg);
7489 }
7490
7491 if (BarValImm) {
7492 auto BarId = ((*BarValImm) >> 4) & 0x3F;
7493 MIB.addImm(BarId);
7494 }
7495
7496 I.eraseFromParent();
7497 return true;
7498}
7499
7500void AMDGPUInstructionSelector::renderTruncImm32(MachineInstrBuilder &MIB,
7501 const MachineInstr &MI,
7502 int OpIdx) const {
7503 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7504 "Expected G_CONSTANT");
7505 MIB.addImm(MI.getOperand(1).getCImm()->getSExtValue());
7506}
7507
7508void AMDGPUInstructionSelector::renderNegateImm(MachineInstrBuilder &MIB,
7509 const MachineInstr &MI,
7510 int OpIdx) const {
7511 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7512 "Expected G_CONSTANT");
7513 MIB.addImm(-MI.getOperand(1).getCImm()->getSExtValue());
7514}
7515
7516void AMDGPUInstructionSelector::renderBitcastFPImm(MachineInstrBuilder &MIB,
7517 const MachineInstr &MI,
7518 int OpIdx) const {
7519 const MachineOperand &Op = MI.getOperand(1);
7520 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1);
7521 MIB.addImm(Op.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
7522}
7523
7524void AMDGPUInstructionSelector::renderCountTrailingOnesImm(
7525 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
7526 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7527 "Expected G_CONSTANT");
7528 MIB.addImm(MI.getOperand(1).getCImm()->getValue().countTrailingOnes());
7529}
7530
7531/// This only really exists to satisfy DAG type checking machinery, so is a
7532/// no-op here.
7533void AMDGPUInstructionSelector::renderTruncTImm(MachineInstrBuilder &MIB,
7534 const MachineInstr &MI,
7535 int OpIdx) const {
7536 const MachineOperand &Op = MI.getOperand(OpIdx);
7537 int64_t Imm;
7538 if (Op.isReg() && mi_match(Op.getReg(), *MRI, m_ICst(Imm)))
7539 MIB.addImm(Imm);
7540 else
7541 MIB.addImm(Op.getImm());
7542}
7543
7544void AMDGPUInstructionSelector::renderZextBoolTImm(MachineInstrBuilder &MIB,
7545 const MachineInstr &MI,
7546 int OpIdx) const {
7547 MIB.addImm(MI.getOperand(OpIdx).getImm() != 0);
7548}
7549
7550void AMDGPUInstructionSelector::renderOpSelTImm(MachineInstrBuilder &MIB,
7551 const MachineInstr &MI,
7552 int OpIdx) const {
7553 assert(OpIdx >= 0 && "expected to match an immediate operand");
7554 MIB.addImm(MI.getOperand(OpIdx).getImm() ? (int64_t)SISrcMods::OP_SEL_0 : 0);
7555}
7556
7557void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_0(
7558 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
7559 assert(OpIdx >= 0 && "expected to match an immediate operand");
7560 MIB.addImm(
7561 (MI.getOperand(OpIdx).getImm() & 0x1) ? (int64_t)SISrcMods::OP_SEL_0 : 0);
7562}
7563
7564void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_1(
7565 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
7566 assert(OpIdx >= 0 && "expected to match an immediate operand");
7567 MIB.addImm((MI.getOperand(OpIdx).getImm() & 0x1)
7569 : (int64_t)SISrcMods::DST_OP_SEL);
7570}
7571
7572void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_0(
7573 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
7574 assert(OpIdx >= 0 && "expected to match an immediate operand");
7575 MIB.addImm(
7576 (MI.getOperand(OpIdx).getImm() & 0x2) ? (int64_t)SISrcMods::OP_SEL_0 : 0);
7577}
7578
7579void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_1(
7580 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
7581 assert(OpIdx >= 0 && "expected to match an immediate operand");
7582 MIB.addImm((MI.getOperand(OpIdx).getImm() & 0x2)
7583 ? (int64_t)(SISrcMods::OP_SEL_0)
7584 : 0);
7585}
7586
7587void AMDGPUInstructionSelector::renderDstSelToOpSelXForm(
7588 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
7589 assert(OpIdx >= 0 && "expected to match an immediate operand");
7590 MIB.addImm(MI.getOperand(OpIdx).getImm() ? (int64_t)(SISrcMods::DST_OP_SEL)
7591 : 0);
7592}
7593
7594void AMDGPUInstructionSelector::renderSrcSelToOpSelXForm(
7595 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
7596 assert(OpIdx >= 0 && "expected to match an immediate operand");
7597 MIB.addImm(MI.getOperand(OpIdx).getImm() ? (int64_t)(SISrcMods::OP_SEL_0)
7598 : 0);
7599}
7600
7601void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_2_0(
7602 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
7603 assert(OpIdx >= 0 && "expected to match an immediate operand");
7604 MIB.addImm(
7605 (MI.getOperand(OpIdx).getImm() & 0x1) ? (int64_t)SISrcMods::OP_SEL_0 : 0);
7606}
7607
7608void AMDGPUInstructionSelector::renderDstSelToOpSel3XFormXForm(
7609 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
7610 assert(OpIdx >= 0 && "expected to match an immediate operand");
7611 MIB.addImm((MI.getOperand(OpIdx).getImm() & 0x2)
7612 ? (int64_t)SISrcMods::DST_OP_SEL
7613 : 0);
7614}
7615
7616void AMDGPUInstructionSelector::renderExtractCPol(MachineInstrBuilder &MIB,
7617 const MachineInstr &MI,
7618 int OpIdx) const {
7619 assert(OpIdx >= 0 && "expected to match an immediate operand");
7620 MIB.addImm(MI.getOperand(OpIdx).getImm() &
7623}
7624
7625void AMDGPUInstructionSelector::renderExtractSWZ(MachineInstrBuilder &MIB,
7626 const MachineInstr &MI,
7627 int OpIdx) const {
7628 assert(OpIdx >= 0 && "expected to match an immediate operand");
7629 const bool Swizzle = MI.getOperand(OpIdx).getImm() &
7632 MIB.addImm(Swizzle);
7633}
7634
7635void AMDGPUInstructionSelector::renderExtractCpolSetGLC(
7636 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
7637 assert(OpIdx >= 0 && "expected to match an immediate operand");
7638 const uint32_t Cpol = MI.getOperand(OpIdx).getImm() &
7641 MIB.addImm(Cpol | AMDGPU::CPol::GLC);
7642}
7643
7644void AMDGPUInstructionSelector::renderFPPow2ToExponent(MachineInstrBuilder &MIB,
7645 const MachineInstr &MI,
7646 int OpIdx) const {
7647 const APFloat &APF = MI.getOperand(1).getFPImm()->getValueAPF();
7648 int ExpVal = APF.getExactLog2Abs();
7649 assert(ExpVal != INT_MIN);
7650 MIB.addImm(ExpVal);
7651}
7652
7653void AMDGPUInstructionSelector::renderRoundMode(MachineInstrBuilder &MIB,
7654 const MachineInstr &MI,
7655 int OpIdx) const {
7656 // "round.towardzero" -> TowardZero 0 -> FP_ROUND_ROUND_TO_ZERO 3
7657 // "round.tonearest" -> NearestTiesToEven 1 -> FP_ROUND_ROUND_TO_NEAREST 0
7658 // "round.upward" -> TowardPositive 2 -> FP_ROUND_ROUND_TO_INF 1
7659 // "round.downward -> TowardNegative 3 -> FP_ROUND_ROUND_TO_NEGINF 2
7660 MIB.addImm((MI.getOperand(OpIdx).getImm() + 3) % 4);
7661}
7662
7663void AMDGPUInstructionSelector::renderVOP3PModsNeg(MachineInstrBuilder &MIB,
7664 const MachineInstr &MI,
7665 int OpIdx) const {
7666 unsigned Mods = SISrcMods::OP_SEL_1;
7667 if (MI.getOperand(OpIdx).getImm())
7668 Mods ^= SISrcMods::NEG;
7669 MIB.addImm((int64_t)Mods);
7670}
7671
7672void AMDGPUInstructionSelector::renderVOP3PModsNegs(MachineInstrBuilder &MIB,
7673 const MachineInstr &MI,
7674 int OpIdx) const {
7675 unsigned Mods = SISrcMods::OP_SEL_1;
7676 if (MI.getOperand(OpIdx).getImm())
7678 MIB.addImm((int64_t)Mods);
7679}
7680
7681void AMDGPUInstructionSelector::renderVOP3PModsNegAbs(MachineInstrBuilder &MIB,
7682 const MachineInstr &MI,
7683 int OpIdx) const {
7684 unsigned Val = MI.getOperand(OpIdx).getImm();
7685 unsigned Mods = SISrcMods::OP_SEL_1; // default: none
7686 if (Val == 1) // neg
7687 Mods ^= SISrcMods::NEG;
7688 if (Val == 2) // abs
7689 Mods ^= SISrcMods::ABS;
7690 if (Val == 3) // neg and abs
7691 Mods ^= (SISrcMods::NEG | SISrcMods::ABS);
7692 MIB.addImm((int64_t)Mods);
7693}
7694
7695void AMDGPUInstructionSelector::renderPrefetchLoc(MachineInstrBuilder &MIB,
7696 const MachineInstr &MI,
7697 int OpIdx) const {
7698 uint32_t V = MI.getOperand(2).getImm();
7701 if (!Subtarget->hasSafeCUPrefetch())
7702 V = std::max(V, (uint32_t)AMDGPU::CPol::SCOPE_SE); // CU scope is unsafe
7703 MIB.addImm(V);
7704}
7705
7706/// Convert from 2-bit value to enum values used for op_sel* source modifiers.
7707void AMDGPUInstructionSelector::renderScaledMAIIntrinsicOperand(
7708 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
7709 unsigned Val = MI.getOperand(OpIdx).getImm();
7710 unsigned New = 0;
7711 if (Val & 0x1)
7713 if (Val & 0x2)
7715 MIB.addImm(New);
7716}
7717
7718bool AMDGPUInstructionSelector::isInlineImmediate(const APInt &Imm) const {
7719 return TII.isInlineConstant(Imm);
7720}
7721
7722bool AMDGPUInstructionSelector::isInlineImmediate(const APFloat &Imm) const {
7723 return TII.isInlineConstant(Imm);
7724}
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
unsigned uint64_t
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isShlHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test if the MI is shift left with half bits, such as reg0:2n =G_SHL reg1:2n, CONST(n)
static bool isNoUnsignedWrap(MachineInstr *Addr)
static Register buildOffsetSrc(MachineIRBuilder &B, MachineRegisterInfo &MRI, const SIInstrInfo &TII, Register BasePtr)
unsigned getNamedBarrierOp(bool HasInlineConst, Intrinsic::ID IntrID)
static Register getLegalRegBank(Register NewReg, Register RootReg, MachineInstr &Use, const AMDGPURegisterBankInfo &RBI, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const SIInstrInfo &TII)
static bool checkRB(Register Reg, unsigned int RBNo, const AMDGPURegisterBankInfo &RBI, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI)
static unsigned updateMods(SrcStatus HiStat, SrcStatus LoStat, unsigned Mods)
static bool isTruncHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test if the MI is truncating to half, such as reg0:n = G_TRUNC reg1:2n
static Register getWaveAddress(const MachineInstr *Def)
static bool isExtractHiElt(MachineRegisterInfo &MRI, Register In, Register &Out)
static bool shouldUseAndMask(unsigned Size, unsigned &Mask)
static std::pair< unsigned, uint8_t > BitOp3_Op(Register R, SmallVectorImpl< Register > &Src, const MachineRegisterInfo &MRI)
static TypeClass isVectorOfTwoOrScalar(Register Reg, const MachineRegisterInfo &MRI)
static bool isLaneMaskFromSameBlock(Register Reg, MachineRegisterInfo &MRI, MachineBasicBlock *MBB)
static bool parseTexFail(uint64_t TexFailCtrl, bool &TFE, bool &LWE, bool &IsTexFail)
static void addZeroImm(MachineInstrBuilder &MIB)
static unsigned gwsIntrinToOpcode(unsigned IntrID)
static bool isConstant(const MachineInstr &MI)
static bool isSameBitWidth(Register Reg1, Register Reg2, const MachineRegisterInfo &MRI)
static Register buildRegSequence(SmallVectorImpl< Register > &Elts, MachineInstr *InsertPt, MachineRegisterInfo &MRI)
static Register buildRSRC(MachineIRBuilder &B, MachineRegisterInfo &MRI, uint32_t FormatLo, uint32_t FormatHi, Register BasePtr)
Return a resource descriptor for use with an arbitrary 64-bit pointer.
static bool isAsyncLDSDMA(Intrinsic::ID Intr)
static std::pair< Register, unsigned > computeIndirectRegIndex(MachineRegisterInfo &MRI, const SIRegisterInfo &TRI, const TargetRegisterClass *SuperRC, Register IdxReg, unsigned EltSize, GISelValueTracking &ValueTracking)
Return the register to use for the index value, and the subregister to use for the indirectly accesse...
static unsigned getLogicalBitOpcode(unsigned Opc, bool Is64)
static std::pair< Register, SrcStatus > getLastSameOrNeg(Register Reg, const MachineRegisterInfo &MRI, SearchOptions SO, int MaxDepth=3)
static Register stripCopy(Register Reg, MachineRegisterInfo &MRI)
static std::optional< std::pair< Register, SrcStatus > > calcNextStatus(std::pair< Register, SrcStatus > Curr, const MachineRegisterInfo &MRI)
static Register stripBitCast(Register Reg, MachineRegisterInfo &MRI)
static std::optional< uint64_t > getConstantZext32Val(Register Reg, const MachineRegisterInfo &MRI)
Get an immediate that must be 32-bits, and treated as zero extended.
static bool isValidToPack(SrcStatus HiStat, SrcStatus LoStat, Register NewReg, Register RootReg, const SIInstrInfo &TII, const MachineRegisterInfo &MRI)
static int getV_CMPOpcode(CmpInst::Predicate P, unsigned Size, const GCNSubtarget &ST)
static SmallVector< std::pair< Register, SrcStatus > > getSrcStats(Register Reg, const MachineRegisterInfo &MRI, SearchOptions SO, int MaxDepth=3)
static bool isUnmergeHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test function, if the MI is reg0:n, reg1:n = G_UNMERGE_VALUES reg2:2n
static SrcStatus getNegStatus(Register Reg, SrcStatus S, const MachineRegisterInfo &MRI)
static bool isVCmpResult(Register Reg, MachineRegisterInfo &MRI)
static Register buildAddr64RSrc(MachineIRBuilder &B, MachineRegisterInfo &MRI, const SIInstrInfo &TII, Register BasePtr)
static bool isLshrHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test if the MI is logic shift right with half bits, such as reg0:2n =G_LSHR reg1:2n,...
static void selectWMMAModsNegAbs(unsigned ModOpcode, unsigned &Mods, SmallVectorImpl< Register > &Elts, Register &Src, MachineInstr *InsertPt, MachineRegisterInfo &MRI)
This file declares the targeting of the InstructionSelector class for AMDGPU.
constexpr LLT S1
constexpr LLT S32
AMDGPU Register Bank Select
This file declares the targeting of the RegisterBankInfo class for AMDGPU.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isAllZeros(StringRef Arr)
Return true if the array is empty or all zeros.
dxil translate DXIL Translate Metadata
Provides analysis for querying information about KnownBits during GISel passes.
#define DEBUG_TYPE
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define P(N)
static std::vector< std::pair< int, unsigned > > Swizzle(std::vector< std::pair< int, unsigned > > Src, R600InstrInfo::BankSwizzle Swz)
#define LLVM_DEBUG(...)
Definition Debug.h:119
Value * RHS
Value * LHS
This is used to control valid status that current MI supports.
bool checkOptions(SrcStatus Stat) const
SearchOptions(Register Reg, const MachineRegisterInfo &MRI)
AMDGPUInstructionSelector(const GCNSubtarget &STI, const AMDGPURegisterBankInfo &RBI)
static const char * getName()
bool select(MachineInstr &I) override
Select the (possibly generic) instruction I to only use target-specific opcodes.
void setupMF(MachineFunction &MF, GISelValueTracking *VT, CodeGenCoverage *CoverageInfo, ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI) override
Setup per-MF executor state.
LLVM_READONLY int getExactLog2Abs() const
Definition APFloat.h:1631
Class for arbitrary precision integers.
Definition APInt.h:78
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:303
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition APInt.h:293
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1583
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition InstrTypes.h:743
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
Definition InstrTypes.h:757
@ ICMP_SLT
signed less than
Definition InstrTypes.h:769
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:770
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition InstrTypes.h:746
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
Definition InstrTypes.h:755
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
Definition InstrTypes.h:744
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
Definition InstrTypes.h:745
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:764
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:763
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:767
@ FCMP_ULT
1 1 0 0 True if unordered or less than
Definition InstrTypes.h:754
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition InstrTypes.h:748
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition InstrTypes.h:751
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
Definition InstrTypes.h:752
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition InstrTypes.h:747
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition InstrTypes.h:749
@ ICMP_NE
not equal
Definition InstrTypes.h:762
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:768
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
Definition InstrTypes.h:756
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:766
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
Definition InstrTypes.h:753
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
Definition InstrTypes.h:742
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:750
bool isFPPredicate() const
Definition InstrTypes.h:845
bool isIntPredicate() const
Definition InstrTypes.h:846
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Definition Constants.h:174
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
DILocation * get() const
Get the underlying DILocation.
Definition DebugLoc.h:220
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:353
void checkSubtargetFeatures(const Function &F) const
Diagnose inconsistent subtarget features before attempting to codegen function F.
std::optional< SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > > ComplexRendererFns
virtual void setupMF(MachineFunction &mf, GISelValueTracking *vt, CodeGenCoverage *covinfo=nullptr, ProfileSummaryInfo *psi=nullptr, BlockFrequencyInfo *bfi=nullptr)
Setup per-MF executor state.
Register getSourceReg(unsigned I) const
Returns the I'th source register.
unsigned getNumSources() const
Returns the number of source registers.
Represents a G_UNMERGE_VALUES.
unsigned getNumDefs() const
Returns the number of def registers.
Register getSourceReg() const
Get the unmerge source register.
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool hasValue() const
TypeSize getValue() const
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
unsigned getID() const
getID() - Return the register class ID number.
bool hasSubClassEq(const MCRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void setReturnAddressIsTaken(bool s)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Helper class to build MachineInstr.
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
LocationSize getSize() const
Return the size in bytes of the memory reference.
unsigned getAddrSpace() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
const Value * getValue() const
Return the base address of the memory access.
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const ConstantInt * getCImm() const
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
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.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static MachineOperand CreateImm(int64_t Val)
bool isEarlyClobber() const
Register getReg() const
getReg - Returns the register number.
bool isInternalRead() const
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)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
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.
const RegisterBank * getRegBankOrNull(Register Reg) const
Return the register bank of Reg, or null if Reg has not been assigned a register bank or has been ass...
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 LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
Definition Type.cpp:911
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Analysis providing profile information.
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
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
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.
static bool isGenericOpcode(unsigned Opc)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
LLVM_READONLY const MIMGG16MappingInfo * getMIMGG16MappingInfo(unsigned G)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords)
std::optional< int64_t > getSMRDEncodedLiteralOffset32(const MCSubtargetInfo &ST, int64_t ByteOffset)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
bool hasSMRDSignedImmOffset(const MCSubtargetInfo &ST)
LLVM_READONLY int32_t getGlobalSaddrOp(uint32_t Opcode)
bool isGFX13Plus(const MCSubtargetInfo &STI)
bool isGFX11Plus(const MCSubtargetInfo &STI)
bool isGFX10Plus(const MCSubtargetInfo &STI)
std::optional< int64_t > getSMRDEncodedOffset(const MCSubtargetInfo &ST, int64_t ByteOffset, bool IsBuffer, bool HasSOffset)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
Intrinsic::ID getIntrinsicID(const MachineInstr &I)
Return the intrinsic ID for opcodes with the G_AMDGPU_INTRIN_ prefix.
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
IndexMode
ARM Index Modes.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
GInstrBind< GBuildVector > m_GBuildVector(GBuildVector *&Inst)
GCstAndRegMatch m_GCst(std::optional< ValueAndVReg > &ValReg)
UnaryOp_match< SrcTy, TargetOpcode::COPY > m_Copy(SrcTy &&Src)
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_XOR, true > m_GXor(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_SEXT > m_GSExt(const SrcTy &Src)
UnaryOp_match< SrcTy, TargetOpcode::G_FPEXT > m_GFPExt(const SrcTy &Src)
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
ConstantMatch< APInt > m_ICst(APInt &Cst)
SpecificConstantMatch m_AllOnesInt()
BinaryOp_match< LHS, RHS, TargetOpcode::G_OR, true > m_GOr(const LHS &L, const RHS &R)
ICstOrSplatMatch< APInt > m_ICstOrSplat(APInt &Cst)
ImplicitDefMatch m_GImplicitDef()
GInstrBind< GConcatVectors > m_GConcatVectors(GConcatVectors *&Inst)
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
GInstrBind< GUnmerge > m_GUnmerge(GUnmerge *&Inst)
Instruction binders for ops with no operand-form matcher (constant-immediate or variadic-source ops).
BinaryOp_match< LHS, RHS, TargetOpcode::G_SUB > m_GSub(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ASHR, false > m_GAShr(const LHS &L, const RHS &R)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)
SpecificRegisterMatch m_SpecificReg(Register RequestedReg)
Matches a register only if it is equal to RequestedReg.
BinaryOp_match< LHS, RHS, TargetOpcode::G_SHL, false > m_GShl(const LHS &L, const RHS &R)
GFrameIndexMatch m_GFrameIndex(int &FI)
Or< Preds... > m_any_of(Preds &&... preds)
BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_BITCAST > m_GBitcast(const SrcTy &Src)
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
UnaryOp_match< SrcTy, TargetOpcode::G_FNEG > m_GFNeg(const SrcTy &Src)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
UnaryOp_match< SrcTy, TargetOpcode::G_FABS > m_GFabs(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_LSHR, false > m_GLShr(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_ANYEXT > m_GAnyExt(const SrcTy &Src)
ShuffleVectorMatch< Src1Ty, Src2Ty > m_GShuffleVector(const Src1Ty &Src1, const Src2Ty &Src2, ArrayRef< int > &Mask)
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, TargetOpcode::G_MUL, true > m_GMul(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, MCRegister PhysReg, const TargetRegisterClass &RC, const DebugLoc &DL, LLT RegTy=LLT())
Return a virtual register corresponding to the incoming argument register PhysReg.
Definition Utils.cpp:848
@ Offset
Definition DWP.cpp:578
LLVM_ABI bool isBuildVectorAllZeros(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndef=false)
Return true if the specified instruction is a G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all of the...
Definition Utils.cpp:1434
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
Definition Utils.cpp:60
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
Definition Utils.cpp:656
PointerUnion< const TargetRegisterClass *, const RegisterBank * > RegClassOrRegBank
Convenient type to represent either a register class or a register bank.
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
Definition Utils.cpp:464
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
Definition Utils.cpp:297
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Dead
Unused definition.
@ Kill
The last use of a register.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI void constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition Utils.cpp:159
@ Load
The value being inserted comes from a load (InsertElement only).
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition Utils.cpp:497
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:338
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
Definition Utils.cpp:317
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI std::optional< ValueAndVReg > getAnyConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true, bool LookThroughAnyExt=false)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT or G_FCONST...
Definition Utils.cpp:442
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition Utils.cpp:436
LLVM_ABI std::optional< DefinitionAndSourceRegister > getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, and underlying value Register folding away any copies.
Definition Utils.cpp:472
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
Definition Utils.cpp:504
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
constexpr RegState getUndefRegState(bool B)
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
Definition KnownBits.h:315
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
Definition KnownBits.h:361
int64_t Offset
Offset - This is an offset from the base Value*.
PointerUnion< const Value *, const PseudoSourceValue * > V
This is the IR pointer value for the access, or it is null if unknown.