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