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