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