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