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