LLVM 24.0.0git
AMDGPURegBankLegalizeHelper.cpp
Go to the documentation of this file.
1//===-- AMDGPURegBankLegalizeHelper.cpp -----------------------------------===//
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//
9/// Implements actual lowering algorithms for each ID that can be used in
10/// Rule.OperandMapping. Similar to legalizer helper but with register banks.
11//
12//===----------------------------------------------------------------------===//
13
16#include "AMDGPUInstrInfo.h"
17#include "AMDGPULaneMaskUtils.h"
20#include "GCNSubtarget.h"
28#include "llvm/IR/IntrinsicsAMDGPU.h"
29
30#define DEBUG_TYPE "amdgpu-reg-bank-legalize"
31
32using namespace llvm;
33using namespace AMDGPU;
34
38 const RegBankLegalizeRules &RBLRules)
39 : MF(B.getMF()), MFI(MF.getInfo<SIMachineFunctionInfo>()),
40 ST(MF.getSubtarget<GCNSubtarget>()), TII(*ST.getInstrInfo()), B(B),
41 MRI(*B.getMRI()), MUI(MUI), VT(VT), RBI(RBI), MORE(MF, nullptr),
42 RBLRules(RBLRules), IsWave32(ST.isWave32()),
43 SgprRB(&RBI.getRegBank(AMDGPU::SGPRRegBankID)),
44 VgprRB(&RBI.getRegBank(AMDGPU::VGPRRegBankID)),
45 AgprRB(&RBI.getRegBank(AMDGPU::AGPRRegBankID)),
46 VccRB(&RBI.getRegBank(AMDGPU::VCCRegBankID)) {}
47
49 const SetOfRulesForOpcode *RuleSet = RBLRules.getRulesForOpc(MI);
50 if (!RuleSet) {
52 "No AMDGPU RegBankLegalize rules defined for opcode",
53 MI);
54 return false;
55 }
56
57 const RegBankLLTMapping *Mapping = RuleSet->findMappingForMI(MI, MRI, MUI);
58 if (!Mapping) {
60 "AMDGPU RegBankLegalize: none of the rules defined with "
61 "'Any' for MI's opcode matched MI",
62 MI);
63 return false;
64 }
65
66 WaterfallInfo WFI;
67 unsigned OpIdx = 0;
68 if (!Mapping->DstOpMapping.empty()) {
69 B.setInsertPt(*MI.getParent(), std::next(MI.getIterator()));
70 if (!applyMappingDst(MI, OpIdx, Mapping->DstOpMapping))
71 return false;
72 }
73 if (!Mapping->SrcOpMapping.empty()) {
74 B.setInstr(MI);
75 if (!applyMappingSrc(MI, OpIdx, Mapping->SrcOpMapping, WFI))
76 return false;
77 }
78
79 if (!lower(MI, *Mapping, WFI))
80 return false;
81
82 if (!WFI.SgprWaterfallOperandRegs.empty()) {
83 if (!executeInWaterfallLoop(B, WFI))
84 return false;
85 }
86
87 return true;
88}
89
90bool RegBankLegalizeHelper::executeInWaterfallLoop(MachineIRBuilder &B,
91 const WaterfallInfo &WFI) {
92 assert(WFI.Start.isValid() && WFI.End.isValid() &&
93 "Waterfall range not initialized");
94
95 // Track use registers which have already been expanded with a readfirstlane
96 // sequence. This may have multiple uses if moving a sequence.
97 DenseMap<Register, Register> WaterfalledRegMap;
98
99 MachineBasicBlock &MBB = B.getMBB();
100 MachineFunction &MF = B.getMF();
101
104
105 const SIRegisterInfo *TRI = ST.getRegisterInfo();
106 const TargetRegisterClass *WaveRC = TRI->getWaveMaskRegClass();
108
109#ifndef NDEBUG
110 const int OrigRangeSize = std::distance(BeginIt, EndIt);
111#endif
112
113 MachineRegisterInfo &MRI = *B.getMRI();
114 Register SaveExecReg = MRI.createVirtualRegister(WaveRC);
115 Register InitSaveExecReg = MRI.createVirtualRegister(WaveRC);
116
117 // Don't bother using generic instructions/registers for the exec mask.
118 B.setInstr(*WFI.Start);
119 B.buildInstr(TargetOpcode::IMPLICIT_DEF).addDef(InitSaveExecReg);
120
121 Register SavedExec = MRI.createVirtualRegister(WaveRC);
122
123 // To insert the loop we need to split the block. Move everything before
124 // this point to a new block, and insert a new empty block before this
125 // instruction.
128 MachineBasicBlock *RestoreExecBB = MF.CreateMachineBasicBlock();
129 MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
131 ++MBBI;
132 MF.insert(MBBI, LoopBB);
133 MF.insert(MBBI, BodyBB);
134 MF.insert(MBBI, RestoreExecBB);
135 MF.insert(MBBI, RemainderBB);
136
137 LoopBB->addSuccessor(BodyBB);
138 BodyBB->addSuccessor(RestoreExecBB);
139 BodyBB->addSuccessor(LoopBB);
140
141 // Move the rest of the block into a new block.
143 RemainderBB->splice(RemainderBB->begin(), &MBB, EndIt, MBB.end());
144
145 MBB.addSuccessor(LoopBB);
146 RestoreExecBB->addSuccessor(RemainderBB);
147
148 B.setInsertPt(*LoopBB, LoopBB->end());
149
150 // +-MBB:------------+
151 // | ... |
152 // | %0 = G_INST_1 |
153 // | %Dst = MI %Vgpr |
154 // | %1 = G_INST_2 |
155 // | ... |
156 // +-----------------+
157 // ->
158 // +-MBB-------------------------------+
159 // | ... |
160 // | %0 = G_INST_1 |
161 // | %SaveExecReg = S_MOV_B32 $exec_lo |
162 // +----------------|------------------+
163 // | /------------------------------|
164 // V V |
165 // +-LoopBB---------------------------------------------------------------+ |
166 // | %CurrentLaneReg:sgpr(s32) = READFIRSTLANE %Vgpr | |
167 // | instead of executing for each lane, see if other lanes had | |
168 // | same value for %Vgpr and execute for them also. | |
169 // | %CondReg:vcc(s1) = G_ICMP eq %CurrentLaneReg, %Vgpr | |
170 // | %CondRegLM:sreg_32 = ballot %CondReg // copy vcc to sreg32 lane mask | |
171 // | %SavedExec = S_AND_SAVEEXEC_B32 %CondRegLM | |
172 // | exec is active for lanes with the same "CurrentLane value" in Vgpr | |
173 // +----------------|-----------------------------------------------------+ |
174 // V |
175 // +-BodyBB------------------------------------------------------------+ |
176 // | %Dst = MI %CurrentLaneReg:sgpr(s32) | |
177 // | executed only for active lanes and written to Dst | |
178 // | $exec = S_XOR_B32 $exec, %SavedExec | |
179 // | set active lanes to 0 in SavedExec, lanes that did not write to | |
180 // | Dst yet, and set this as new exec (for READFIRSTLANE and ICMP) | |
181 // | SI_WATERFALL_LOOP LoopBB |-----|
182 // +----------------|--------------------------------------------------+
183 // V
184 // +-RestoreExecBB--------------------------+
185 // | $exec_lo = S_MOV_B32_term %SaveExecReg |
186 // +----------------|-----------------------+
187 // V
188 // +-RemainderBB:----------------------+
189 // | %1 = G_INST_2 |
190 // | ... |
191 // +---------------------------------- +
192
193 // Move the instruction into the loop body. Note we moved everything after
194 // Range.end() already into a new block, so Range.end() is no longer valid.
195 BodyBB->splice(BodyBB->end(), &MBB, BeginIt, MBB.end());
196
197 // Figure out the iterator range after splicing the instructions.
198 MachineBasicBlock::iterator NewBegin = BeginIt;
199 auto NewEnd = BodyBB->end();
200 assert(std::distance(NewBegin, NewEnd) == OrigRangeSize);
201
202 B.setMBB(*LoopBB);
203 Register CondReg;
204
205 for (MachineInstr &MI : make_range(NewBegin, NewEnd)) {
206 for (MachineOperand &Op : MI.all_uses()) {
207 Register OldReg = Op.getReg();
208 if (!WFI.SgprWaterfallOperandRegs.count(OldReg))
209 continue;
210
211 // See if we already processed this register in another instruction in
212 // the sequence.
213 auto OldVal = WaterfalledRegMap.find(OldReg);
214 if (OldVal != WaterfalledRegMap.end()) {
215 Op.setReg(OldVal->second);
216 continue;
217 }
218
219 Register OpReg = Op.getReg();
220 LLT OpTy = MRI.getType(OpReg);
221
222 // TODO: support for agpr
223 assert(MRI.getRegBank(OpReg) == VgprRB);
224 Register CurrentLaneReg = MRI.createVirtualRegister({SgprRB, OpTy});
225 buildReadFirstLane(B, CurrentLaneReg, OpReg, RBI);
226
227 // Build the comparison(s), CurrentLaneReg == OpReg.
228 unsigned OpSize = OpTy.getSizeInBits();
229 unsigned PartSize = (OpSize % 64 == 0) ? 64 : 32;
230 LLT PartTy = LLT::integer(PartSize);
231 unsigned NumParts = OpSize / PartSize;
233 SmallVector<Register, 8> CurrentLaneParts;
234
235 if (NumParts == 1) {
236 OpParts.push_back(OpReg);
237 CurrentLaneParts.push_back(CurrentLaneReg);
238 } else {
239 auto UnmergeOp = B.buildUnmerge({VgprRB, PartTy}, OpReg);
240 auto UnmergeCurrLane = B.buildUnmerge({SgprRB, PartTy}, CurrentLaneReg);
241 for (unsigned i = 0; i < NumParts; ++i) {
242 OpParts.push_back(UnmergeOp.getReg(i));
243 CurrentLaneParts.push_back(UnmergeCurrLane.getReg(i));
244 }
245 }
246
247 for (unsigned i = 0; i < NumParts; ++i) {
248 Register CmpReg = MRI.createVirtualRegister(VccRB_S1);
249 B.buildICmp(CmpInst::ICMP_EQ, CmpReg, CurrentLaneParts[i], OpParts[i]);
250
251 if (!CondReg)
252 CondReg = CmpReg;
253 else
254 CondReg = B.buildAnd(VccRB_S1, CondReg, CmpReg).getReg(0);
255 }
256
257 Op.setReg(CurrentLaneReg);
258
259 // Make sure we don't re-process this register again.
260 WaterfalledRegMap.insert(std::pair(OldReg, Op.getReg()));
261 }
262 }
263
264 // Copy vcc to sgpr32/64, ballot becomes a no-op during instruction selection.
265 Register CondRegLM =
266 MRI.createVirtualRegister({WaveRC, LLT::integer(IsWave32 ? 32 : 64)});
267 B.buildIntrinsic(Intrinsic::amdgcn_ballot, CondRegLM).addReg(CondReg);
268
269 // Update EXEC, save the original EXEC value to SavedExec.
270 B.buildInstr(LMC.AndSaveExecOpc)
271 .addDef(SavedExec)
272 .addReg(CondRegLM, RegState::Kill)
273 .setOperandDead(3);
274 MRI.setSimpleHint(SavedExec, CondRegLM);
275
276 B.setInsertPt(*BodyBB, BodyBB->end());
277
278 // Update EXEC, switch all done bits to 0 and all todo bits to 1.
279 B.buildInstr(LMC.XorTermOpc)
280 .addDef(LMC.ExecReg)
281 .addReg(LMC.ExecReg)
282 .addReg(SavedExec)
283 .setOperandDead(3);
284
285 // XXX - s_xor_b64 sets scc to 1 if the result is nonzero, so can we use
286 // s_cbranch_scc0?
287
288 // Loop back to V_READFIRSTLANE_B32 if there are still variants to cover.
289 B.buildInstr(AMDGPU::SI_WATERFALL_LOOP).addMBB(LoopBB);
290
291 // Save the EXEC mask before the loop.
292 B.setInsertPt(MBB, MBB.end());
293 B.buildInstr(LMC.MovOpc).addDef(SaveExecReg).addReg(LMC.ExecReg);
294
295 // Restore the EXEC mask after the loop.
296 B.setInsertPt(*RestoreExecBB, RestoreExecBB->begin());
297 B.buildInstr(LMC.MovTermOpc).addDef(LMC.ExecReg).addReg(SaveExecReg);
298
299 // Set the insert point after the original instruction, so any new
300 // instructions will be in the remainder.
301 B.setInsertPt(*RemainderBB, RemainderBB->begin());
302
303 return true;
304}
305
306// Analyze a combined offset from an llvm.amdgcn.s.buffer intrinsic and store
307// the three offsets (voffset, soffset and instoffset)
308unsigned RegBankLegalizeHelper::setBufferOffsets(
309 MachineIRBuilder &B, Register CombinedOffset, Register &VOffsetReg,
310 Register &SOffsetReg, int64_t &InstOffsetVal, Align Alignment) {
311 if (std::optional<int64_t> Imm =
312 getIConstantVRegSExtVal(CombinedOffset, MRI)) {
313 uint32_t SOffset, ImmOffset;
314 if (TII.splitMUBUFOffset(*Imm, SOffset, ImmOffset, Alignment)) {
315 VOffsetReg = B.buildConstant(VgprRB_I32, 0).getReg(0);
316 SOffsetReg = B.buildConstant(SgprRB_I32, SOffset).getReg(0);
317 InstOffsetVal = ImmOffset;
318 return SOffset + ImmOffset;
319 }
320 }
321 const bool CheckNUW = ST.hasGFX1250Insts();
323 MRI, CombinedOffset, /*KnownBits=*/nullptr,
324 /*CheckNUW=*/CheckNUW);
325 uint32_t SOffset, ImmOffset;
326 if (static_cast<int32_t>(Offset) > 0 &&
327 TII.splitMUBUFOffset(Offset, SOffset, ImmOffset, Alignment)) {
328 if (Base.isValid() && MRI.getRegBank(Base) == VgprRB) {
329 VOffsetReg = Base;
330 SOffsetReg = B.buildConstant(SgprRB_I32, SOffset).getReg(0);
331 InstOffsetVal = ImmOffset;
332 return 0;
333 }
334 // If we have SGPR base, we can use it for soffset.
335 if (SOffset == 0) {
336 VOffsetReg = B.buildConstant(VgprRB_I32, 0).getReg(0);
337 SOffsetReg = Base;
338 InstOffsetVal = ImmOffset;
339 return 0;
340 }
341 }
342 // Handle the variable sgpr + vgpr case.
343 MachineInstr *Add = getOpcodeDef(AMDGPU::G_ADD, CombinedOffset, MRI);
344 if (Add && static_cast<int32_t>(Offset) >= 0 &&
345 (!CheckNUW || Add->getFlag(MachineInstr::NoUWrap))) {
346 Register Src0 = getSrcRegIgnoringCopies(Add->getOperand(1).getReg(), MRI);
347 Register Src1 = getSrcRegIgnoringCopies(Add->getOperand(2).getReg(), MRI);
348 const RegisterBank *Src0Bank = MRI.getRegBank(Src0);
349 const RegisterBank *Src1Bank = MRI.getRegBank(Src1);
350 if (Src0Bank == VgprRB && Src1Bank == SgprRB) {
351 VOffsetReg = Src0;
352 SOffsetReg = Src1;
353 return 0;
354 }
355 if (Src0Bank == SgprRB && Src1Bank == VgprRB) {
356 VOffsetReg = Src1;
357 SOffsetReg = Src0;
358 return 0;
359 }
360 }
361 // Ensure we have a VGPR for the combined offset. This could be an issue if we
362 // have an SGPR offset and a VGPR resource.
363 if (MRI.getRegBank(CombinedOffset) == VgprRB) {
364 VOffsetReg = CombinedOffset;
365 } else {
366 VOffsetReg = B.buildCopy(VgprRB_I32, CombinedOffset).getReg(0);
367 }
368 SOffsetReg = B.buildConstant(SgprRB_I32, 0).getReg(0);
369 return 0;
370}
371
372bool RegBankLegalizeHelper::splitLoad(MachineInstr &MI,
373 ArrayRef<LLT> LLTBreakdown, LLT MergeTy) {
374 MachineFunction &MF = B.getMF();
375 assert(MI.getNumMemOperands() == 1);
376 MachineMemOperand &BaseMMO = **MI.memoperands_begin();
377 Register Dst = MI.getOperand(0).getReg();
378 const RegisterBank *DstRB = MRI.getRegBankOrNull(Dst);
379 Register Base = MI.getOperand(1).getReg();
380 LLT PtrTy = MRI.getType(Base);
381 const RegisterBank *PtrRB = MRI.getRegBankOrNull(Base);
382 LLT OffsetTy = LLT::integer(PtrTy.getSizeInBits());
383 SmallVector<Register, 4> LoadPartRegs;
384
385 unsigned ByteOffset = 0;
386 for (LLT PartTy : LLTBreakdown) {
387 Register BasePlusOffset;
388 if (ByteOffset == 0) {
389 BasePlusOffset = Base;
390 } else {
391 auto Offset = B.buildConstant({PtrRB, OffsetTy}, ByteOffset);
392 BasePlusOffset =
393 B.buildObjectPtrOffset({PtrRB, PtrTy}, Base, Offset).getReg(0);
394 }
395 auto *OffsetMMO = MF.getMachineMemOperand(&BaseMMO, ByteOffset, PartTy);
396 auto LoadPart = B.buildLoad({DstRB, PartTy}, BasePlusOffset, *OffsetMMO);
397 LoadPartRegs.push_back(LoadPart.getReg(0));
398 ByteOffset += PartTy.getSizeInBytes();
399 }
400
401 if (!MergeTy.isValid()) {
402 // Loads are of same size, concat or merge them together.
403 B.buildMergeLikeInstr(Dst, LoadPartRegs);
404 } else {
405 // Loads are not all of same size, need to unmerge them to smaller pieces
406 // of MergeTy type, then merge pieces to Dst.
407 SmallVector<Register, 4> MergeTyParts;
408 for (Register Reg : LoadPartRegs) {
409 if (MRI.getType(Reg) == MergeTy) {
410 MergeTyParts.push_back(Reg);
411 } else {
412 auto Unmerge = B.buildUnmerge({DstRB, MergeTy}, Reg);
413 for (unsigned i = 0; i < Unmerge->getNumOperands() - 1; ++i)
414 MergeTyParts.push_back(Unmerge.getReg(i));
415 }
416 }
417 B.buildMergeLikeInstr(Dst, MergeTyParts);
418 }
419 MI.eraseFromParent();
420 return true;
421}
422
423bool RegBankLegalizeHelper::widenLoad(MachineInstr &MI, LLT WideTy,
424 LLT MergeTy) {
425 MachineFunction &MF = B.getMF();
426 assert(MI.getNumMemOperands() == 1);
427 MachineMemOperand &BaseMMO = **MI.memoperands_begin();
428 Register Dst = MI.getOperand(0).getReg();
429 const RegisterBank *DstRB = MRI.getRegBankOrNull(Dst);
430 Register Base = MI.getOperand(1).getReg();
431
432 MachineMemOperand *WideMMO = MF.getMachineMemOperand(&BaseMMO, 0, WideTy);
433 auto WideLoad = B.buildLoad({DstRB, WideTy}, Base, *WideMMO);
434
435 if (WideTy.isScalar()) {
436 B.buildTrunc(Dst, WideLoad);
437 } else {
438 SmallVector<Register, 4> MergeTyParts;
439 auto Unmerge = B.buildUnmerge({DstRB, MergeTy}, WideLoad);
440
441 LLT DstTy = MRI.getType(Dst);
442 unsigned NumElts = DstTy.getSizeInBits() / MergeTy.getSizeInBits();
443 for (unsigned i = 0; i < NumElts; ++i) {
444 MergeTyParts.push_back(Unmerge.getReg(i));
445 }
446 B.buildMergeLikeInstr(Dst, MergeTyParts);
447 }
448 MI.eraseFromParent();
449 return true;
450}
451
452bool RegBankLegalizeHelper::widenMMOToS32(GAnyLoad &MI) const {
453 Register Dst = MI.getDstReg();
454 Register Ptr = MI.getPointerReg();
455 MachineMemOperand &MMO = MI.getMMO();
456 unsigned MemSize = 8 * MMO.getSize().getValue();
457
458 MachineMemOperand *WideMMO = B.getMF().getMachineMemOperand(&MMO, 0, S32);
459
460 if (MI.getOpcode() == G_LOAD) {
461 B.buildLoad(Dst, Ptr, *WideMMO);
462 } else {
463 auto Load = B.buildLoad(SgprRB_I32, Ptr, *WideMMO);
464
465 if (MI.getOpcode() == G_ZEXTLOAD) {
466 APInt Mask = APInt::getLowBitsSet(S32.getSizeInBits(), MemSize);
467 auto MaskCst = B.buildConstant(SgprRB_I32, Mask);
468 B.buildAnd(Dst, Load, MaskCst);
469 } else {
470 assert(MI.getOpcode() == G_SEXTLOAD);
471 B.buildSExtInReg(Dst, Load, MemSize);
472 }
473 }
474
475 MI.eraseFromParent();
476 return true;
477}
478
479bool RegBankLegalizeHelper::lowerVccExtToSel(MachineInstr &MI) {
480 Register Dst = MI.getOperand(0).getReg();
481 LLT Ty = MRI.getType(Dst);
482 Register Src = MI.getOperand(1).getReg();
483 unsigned Opc = MI.getOpcode();
484 int TrueExtCst = Opc == G_SEXT ? -1 : 1;
485 if (Ty == S32 || Ty == S16) {
486 auto True = B.buildConstant({VgprRB, Ty}, TrueExtCst);
487 auto False = B.buildConstant({VgprRB, Ty}, 0);
488 B.buildSelect(Dst, Src, True, False);
489 } else if (Ty == S64) {
490 auto True = B.buildConstant({VgprRB_I32}, TrueExtCst);
491 auto False = B.buildConstant({VgprRB_I32}, 0);
492 auto Lo = B.buildSelect({VgprRB_I32}, Src, True, False);
493 MachineInstrBuilder Hi;
494 switch (Opc) {
495 case G_SEXT:
496 Hi = Lo;
497 break;
498 case G_ZEXT:
499 Hi = False;
500 break;
501 case G_ANYEXT:
502 Hi = B.buildUndef({VgprRB_I32});
503 break;
504 default:
506 MF, MORE, DEBUG_TYPE,
507 "AMDGPU RegBankLegalize: lowerVccExtToSel, Opcode not supported", MI);
508 return false;
509 }
510
511 B.buildMergeValues(Dst, {Lo.getReg(0), Hi.getReg(0)});
512 } else {
514 MF, MORE, DEBUG_TYPE,
515 "AMDGPU RegBankLegalize: lowerVccExtToSel, Type not supported", MI);
516 return false;
517 }
518
519 MI.eraseFromParent();
520 return true;
521}
522
523std::pair<Register, Register> RegBankLegalizeHelper::unpackZExt(Register Reg) {
524 auto PackedI32 = B.buildBitcast(SgprRB_I32, Reg);
525 auto Mask = B.buildConstant(SgprRB_I32, 0x0000ffff);
526 auto Lo = B.buildAnd(SgprRB_I32, PackedI32, Mask);
527 auto Hi = B.buildLShr(SgprRB_I32, PackedI32, B.buildConstant(SgprRB_I32, 16));
528 return {Lo.getReg(0), Hi.getReg(0)};
529}
530
531std::pair<Register, Register> RegBankLegalizeHelper::unpackSExt(Register Reg) {
532 auto PackedI32 = B.buildBitcast(SgprRB_I32, Reg);
533 auto Lo = B.buildSExtInReg(SgprRB_I32, PackedI32, 16);
534 auto Hi = B.buildAShr(SgprRB_I32, PackedI32, B.buildConstant(SgprRB_I32, 16));
535 return {Lo.getReg(0), Hi.getReg(0)};
536}
537
538std::pair<Register, Register> RegBankLegalizeHelper::unpackAExt(Register Reg) {
539 Register RegI32 = Reg;
540 if (MRI.getType(Reg) != I32)
541 RegI32 = B.buildBitcast(SgprRB_I32, Reg).getReg(0);
542
543 auto Hi = B.buildLShr(SgprRB_I32, RegI32, B.buildConstant(SgprRB_I32, 16));
544 return {RegI32, Hi.getReg(0)};
545}
546
547std::pair<Register, Register>
548RegBankLegalizeHelper::unpackAExtTruncS16(Register Reg) {
549 auto [Lo32, Hi32] = unpackAExt(Reg);
550 LLT EltTy = MRI.getType(Reg).getElementType();
551 return {B.buildTrunc({SgprRB, EltTy}, Lo32).getReg(0),
552 B.buildTrunc({SgprRB, EltTy}, Hi32).getReg(0)};
553}
554
555bool RegBankLegalizeHelper::lowerUnpackBitShift(MachineInstr &MI) {
556 Register Lo, Hi;
557 switch (MI.getOpcode()) {
558 case AMDGPU::G_SHL: {
559 auto [Val0, Val1] = unpackAExt(MI.getOperand(1).getReg());
560 auto [Amt0, Amt1] = unpackAExt(MI.getOperand(2).getReg());
561 Lo = B.buildInstr(MI.getOpcode(), {SgprRB_I32}, {Val0, Amt0}).getReg(0);
562 Hi = B.buildInstr(MI.getOpcode(), {SgprRB_I32}, {Val1, Amt1}).getReg(0);
563 break;
564 }
565 case AMDGPU::G_LSHR: {
566 auto [Val0, Val1] = unpackZExt(MI.getOperand(1).getReg());
567 auto [Amt0, Amt1] = unpackZExt(MI.getOperand(2).getReg());
568 Lo = B.buildInstr(MI.getOpcode(), {SgprRB_I32}, {Val0, Amt0}).getReg(0);
569 Hi = B.buildInstr(MI.getOpcode(), {SgprRB_I32}, {Val1, Amt1}).getReg(0);
570 break;
571 }
572 case AMDGPU::G_ASHR: {
573 auto [Val0, Val1] = unpackSExt(MI.getOperand(1).getReg());
574 auto [Amt0, Amt1] = unpackSExt(MI.getOperand(2).getReg());
575 Lo = B.buildAShr(SgprRB_I32, Val0, Amt0).getReg(0);
576 Hi = B.buildAShr(SgprRB_I32, Val1, Amt1).getReg(0);
577 break;
578 }
579 default:
581 MF, MORE, DEBUG_TYPE,
582 "AMDGPU RegBankLegalize: lowerUnpackBitShift, case not implemented",
583 MI);
584 return false;
585 }
586 B.buildBuildVectorTrunc(MI.getOperand(0).getReg(), {Lo, Hi});
587 MI.eraseFromParent();
588 return true;
589}
590
591bool RegBankLegalizeHelper::lowerUnpackMinMax(MachineInstr &MI) {
592 Register Lo, Hi;
593 switch (MI.getOpcode()) {
594 case AMDGPU::G_SMIN:
595 case AMDGPU::G_SMAX: {
596 // For signed operations, use sign extension
597 auto [Val0_Lo, Val0_Hi] = unpackSExt(MI.getOperand(1).getReg());
598 auto [Val1_Lo, Val1_Hi] = unpackSExt(MI.getOperand(2).getReg());
599 Lo = B.buildInstr(MI.getOpcode(), {SgprRB_I32}, {Val0_Lo, Val1_Lo})
600 .getReg(0);
601 Hi = B.buildInstr(MI.getOpcode(), {SgprRB_I32}, {Val0_Hi, Val1_Hi})
602 .getReg(0);
603 break;
604 }
605 case AMDGPU::G_UMIN:
606 case AMDGPU::G_UMAX: {
607 // For unsigned operations, use zero extension
608 auto [Val0_Lo, Val0_Hi] = unpackZExt(MI.getOperand(1).getReg());
609 auto [Val1_Lo, Val1_Hi] = unpackZExt(MI.getOperand(2).getReg());
610 Lo = B.buildInstr(MI.getOpcode(), {SgprRB_I32}, {Val0_Lo, Val1_Lo})
611 .getReg(0);
612 Hi = B.buildInstr(MI.getOpcode(), {SgprRB_I32}, {Val0_Hi, Val1_Hi})
613 .getReg(0);
614 break;
615 }
616 default:
618 MF, MORE, DEBUG_TYPE,
619 "AMDGPU RegBankLegalize: lowerUnpackMinMax, case not implemented", MI);
620 return false;
621 }
622 B.buildBuildVectorTrunc(MI.getOperand(0).getReg(), {Lo, Hi});
623 MI.eraseFromParent();
624 return true;
625}
626
627bool RegBankLegalizeHelper::lowerUnpackAExt(MachineInstr &MI) {
628 auto [Op1Lo, Op1Hi] = unpackAExt(MI.getOperand(1).getReg());
629 auto [Op2Lo, Op2Hi] = unpackAExt(MI.getOperand(2).getReg());
630 auto ResLo = B.buildInstr(MI.getOpcode(), {SgprRB_I32}, {Op1Lo, Op2Lo});
631 auto ResHi = B.buildInstr(MI.getOpcode(), {SgprRB_I32}, {Op1Hi, Op2Hi});
632 B.buildBuildVectorTrunc(MI.getOperand(0).getReg(),
633 {ResLo.getReg(0), ResHi.getReg(0)});
634 MI.eraseFromParent();
635 return true;
636}
637
638bool RegBankLegalizeHelper::lowerSBufToBuf(MachineInstr &MI,
639 WaterfallInfo &WFI) {
640 Register Dst = MI.getOperand(0).getReg();
641 LLT Ty = MRI.getType(Dst);
642 const RegisterBank *RSrcBank = MRI.getRegBank(MI.getOperand(1).getReg());
643 unsigned LoadSize = Ty.getSizeInBits();
644 int NumLoads = 1;
645 SmallVector<Register, 4> LoadParts;
646 if (LoadSize == 256 || LoadSize == 512) {
647 NumLoads = LoadSize / 128;
648 Ty = Ty.divide(NumLoads);
649 }
650 for (int I = 0; I < NumLoads; ++I)
651 LoadParts.emplace_back(MRI.createVirtualRegister({VgprRB, Ty}));
652 MachineMemOperand *OrigMMO = *MI.memoperands_begin();
653 const Align Alignment = OrigMMO->getAlign();
654 MachineFunction &MF = B.getMF();
655 Register SOffset;
656 Register VOffset;
657 int64_t ImmOffset = 0;
658 unsigned MMOOffset = setBufferOffsets(B, MI.getOperand(2).getReg(), VOffset,
659 SOffset, ImmOffset, Alignment);
660 const unsigned MemSize = divideCeil(OrigMMO->getSize().getValue(), NumLoads);
661 MachineMemOperand *BaseMMO = MF.getMachineMemOperand(OrigMMO, 0, MemSize);
662 if (MMOOffset != 0)
663 BaseMMO = MF.getMachineMemOperand(BaseMMO, MMOOffset, MemSize);
664 // If only the offset is divergent, emit a MUBUF buffer load
665 // instead. We can assume that the buffer is unswizzled.
666 Register RSrc = MI.getOperand(1).getReg();
667 Register VIndex = B.buildConstant(VgprRB_I32, 0).getReg(0);
668 unsigned CachePolicy = MI.getOperand(3).getImm();
669 unsigned Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD;
670 switch (MI.getOpcode()) {
671 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE:
672 Opc = G_AMDGPU_BUFFER_LOAD_SBYTE;
673 break;
674 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
675 Opc = G_AMDGPU_BUFFER_LOAD_UBYTE;
676 break;
677 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT:
678 Opc = G_AMDGPU_BUFFER_LOAD_SSHORT;
679 break;
680 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
681 Opc = G_AMDGPU_BUFFER_LOAD_USHORT;
682 break;
683 default:
684 break;
685 }
686 for (int I = 0; I < NumLoads; ++I) {
687 B.buildInstr(Opc)
688 .addDef(LoadParts[I]) // vdata
689 .addUse(RSrc) // rsrc
690 .addUse(VIndex) // vindex
691 .addUse(VOffset) // voffset
692 .addUse(SOffset) // soffset
693 .addImm(ImmOffset + 16 * I) // offset(imm)
694 .addImm(CachePolicy) // cachepolicy, swizzled buffer(imm)
695 .addImm(0) // idxen(imm)
696 .addMemOperand(MF.getMachineMemOperand(BaseMMO, 16 * I, MemSize));
697 }
698 if (NumLoads == 1)
699 B.buildCopy(Dst, LoadParts[0]);
700 else
701 B.buildMergeLikeInstr(Dst, LoadParts);
702 B.setInstr(*MRI.getVRegDef(LoadParts[0]));
703 if (RSrcBank != SgprRB) {
704 WFI.SgprWaterfallOperandRegs.insert(RSrc);
705 WFI.Start = MRI.getVRegDef(LoadParts.front());
706 WFI.End = std::next(MRI.getVRegDef(LoadParts.back())->getIterator());
707 }
708 MI.eraseFromParent();
709 return true;
710}
711
714 return (GI->is(Intrinsic::amdgcn_sbfe));
715
716 return MI.getOpcode() == AMDGPU::G_SBFX;
717}
718
719bool RegBankLegalizeHelper::lowerV_BFE(MachineInstr &MI) {
720 Register Dst = MI.getOperand(0).getReg();
721 assert(MRI.getType(Dst) == LLT::scalar(64));
722 bool Signed = isSignedBFE(MI);
723 unsigned FirstOpnd = isa<GIntrinsic>(MI) ? 2 : 1;
724 // Extract bitfield from Src, LSBit is the least-significant bit for the
725 // extraction (field offset) and Width is size of bitfield.
726 Register Src = MI.getOperand(FirstOpnd).getReg();
727 Register LSBit = MI.getOperand(FirstOpnd + 1).getReg();
728 Register Width = MI.getOperand(FirstOpnd + 2).getReg();
729 // Comments are for signed bitfield extract, similar for unsigned. x is sign
730 // bit. s is sign, l is LSB and y are remaining bits of bitfield to extract.
731
732 // Src >> LSBit Hi|Lo: x?????syyyyyyl??? -> xxxx?????syyyyyyl
733 unsigned SHROpc = Signed ? AMDGPU::G_ASHR : AMDGPU::G_LSHR;
734 auto SHRSrc = B.buildInstr(SHROpc, {VgprRB_I64}, {Src, LSBit});
735
736 auto ConstWidth = getIConstantVRegValWithLookThrough(Width, MRI);
737
738 // Expand to Src >> LSBit << (64 - Width) >> (64 - Width)
739 // << (64 - Width): Hi|Lo: xxxx?????syyyyyyl -> syyyyyyl000000000
740 // >> (64 - Width): Hi|Lo: syyyyyyl000000000 -> ssssssssssyyyyyyl
741 if (!ConstWidth) {
742 auto Amt = B.buildSub(VgprRB_I32, B.buildConstant(SgprRB_I32, 64), Width);
743 auto SignBit = B.buildShl(VgprRB_I64, SHRSrc, Amt);
744 B.buildInstr(SHROpc, {Dst}, {SignBit, Amt});
745 MI.eraseFromParent();
746 return true;
747 }
748
749 uint64_t WidthImm = ConstWidth->Value.getZExtValue();
750 auto UnmergeSHRSrc = B.buildUnmerge(VgprRB_I32, SHRSrc);
751 Register SHRSrcLo = UnmergeSHRSrc.getReg(0);
752 Register SHRSrcHi = UnmergeSHRSrc.getReg(1);
753 auto Zero = B.buildConstant(VgprRB_I32, 0);
754 unsigned BFXOpc = Signed ? AMDGPU::G_SBFX : AMDGPU::G_UBFX;
755
756 if (WidthImm <= 32) {
757 // SHRSrc Hi|Lo: ????????|???syyyl -> ????????|ssssyyyl
758 Register Lo = SHRSrcLo;
759 // V_BFE masks its width to 5 bits, so 32 would extract zero bits.
760 if (WidthImm < 32) {
761 Lo =
762 B.buildInstr(BFXOpc, {VgprRB_I32}, {SHRSrcLo, Zero, Width}).getReg(0);
763 }
764 MachineInstrBuilder Hi;
765 if (Signed) {
766 // SHRSrc Hi|Lo: ????????|ssssyyyl -> ssssssss|ssssyyyl
767 Hi = B.buildAShr(VgprRB_I32, Lo, B.buildConstant(VgprRB_I32, 31));
768 } else {
769 // SHRSrc Hi|Lo: ????????|000syyyl -> 00000000|000syyyl
770 Hi = Zero;
771 }
772 B.buildMergeLikeInstr(Dst, {Lo, Hi});
773 } else {
774 auto Amt = B.buildConstant(VgprRB_I32, WidthImm - 32);
775 // SHRSrc Hi|Lo: ??????sy|yyyyyyyl -> sssssssy|yyyyyyyl
776 auto Hi = B.buildInstr(BFXOpc, {VgprRB_I32}, {SHRSrcHi, Zero, Amt});
777 B.buildMergeLikeInstr(Dst, {SHRSrcLo, Hi});
778 }
779
780 MI.eraseFromParent();
781 return true;
782}
783
784bool RegBankLegalizeHelper::lowerS_BFE(MachineInstr &MI) {
785 Register DstReg = MI.getOperand(0).getReg();
786 LLT Ty = MRI.getType(DstReg);
787 bool Signed = isSignedBFE(MI);
788 unsigned FirstOpnd = isa<GIntrinsic>(MI) ? 2 : 1;
789 Register Src = MI.getOperand(FirstOpnd).getReg();
790 Register LSBit = MI.getOperand(FirstOpnd + 1).getReg();
791 Register Width = MI.getOperand(FirstOpnd + 2).getReg();
792 // For uniform bit field extract there are 4 available instructions, but
793 // LSBit(field offset) and Width(size of bitfield) need to be packed in S32,
794 // field offset in low and size in high 16 bits.
795
796 // Src1 Hi16|Lo16 = Size|FieldOffset
797 auto Mask = B.buildConstant(SgprRB_I32, maskTrailingOnes<unsigned>(6));
798 auto FieldOffset = B.buildAnd(SgprRB_I32, LSBit, Mask);
799 auto Size = B.buildShl(SgprRB_I32, Width, B.buildConstant(SgprRB_I32, 16));
800 auto Src1 = B.buildOr(SgprRB_I32, FieldOffset, Size);
801 unsigned Opc32 = Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
802 unsigned Opc64 = Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64;
803 unsigned Opc = Ty == S32 ? Opc32 : Opc64;
804
805 // Select machine instruction, because of reg class constraining, insert
806 // copies from reg class to reg bank.
807 auto S_BFE = B.buildInstr(Opc, {{SgprRB, Ty}},
808 {B.buildCopy(Ty, Src), B.buildCopy(I32, Src1)});
809 constrainSelectedInstRegOperands(*S_BFE, *ST.getInstrInfo(),
810 *ST.getRegisterInfo(), RBI);
811
812 B.buildCopy(DstReg, S_BFE->getOperand(0).getReg());
813 MI.eraseFromParent();
814 return true;
815}
816
817bool RegBankLegalizeHelper::lowerSplitTo32(MachineInstr &MI) {
818 Register Dst = MI.getOperand(0).getReg();
819 LLT DstTy = MRI.getType(Dst);
820 assert(DstTy == V4S16 || DstTy == V2S32 || DstTy == S64);
821 LLT Ty = DstTy.divide(2);
822 auto Op1 = B.buildUnmerge({VgprRB, Ty}, MI.getOperand(1).getReg());
823 auto Op2 = B.buildUnmerge({VgprRB, Ty}, MI.getOperand(2).getReg());
824 unsigned Opc = MI.getOpcode();
825 auto Flags = MI.getFlags();
826 auto Lo =
827 B.buildInstr(Opc, {{VgprRB, Ty}}, {Op1.getReg(0), Op2.getReg(0)}, Flags);
828 auto Hi =
829 B.buildInstr(Opc, {{VgprRB, Ty}}, {Op1.getReg(1), Op2.getReg(1)}, Flags);
830 B.buildMergeLikeInstr(Dst, {Lo, Hi});
831 MI.eraseFromParent();
832 return true;
833}
834
835bool RegBankLegalizeHelper::lowerSplitTo32Mul(MachineInstr &MI) {
836 Register Dst = MI.getOperand(0).getReg();
837 assert(MRI.getType(Dst) == S64);
838 auto Op1 = B.buildUnmerge({VgprRB_I32}, MI.getOperand(1).getReg());
839 auto Op2 = B.buildUnmerge({VgprRB_I32}, MI.getOperand(2).getReg());
840
841 // TODO: G_AMDGPU_MAD_* optimizations for G_MUL divergent S64 operation to
842 // match GlobalISel with old regbankselect.
843 auto Lo = B.buildMul(VgprRB_I32, Op1.getReg(0), Op2.getReg(0));
844 auto Carry = B.buildUMulH(VgprRB_I32, Op1.getReg(0), Op2.getReg(0));
845 auto MulLo0Hi1 = B.buildMul(VgprRB_I32, Op1.getReg(0), Op2.getReg(1));
846 auto MulHi0Lo1 = B.buildMul(VgprRB_I32, Op1.getReg(1), Op2.getReg(0));
847 auto Sum = B.buildAdd(VgprRB_I32, MulLo0Hi1, MulHi0Lo1);
848 auto Hi = B.buildAdd(VgprRB_I32, Sum, Carry);
849
850 B.buildMergeLikeInstr(Dst, {Lo, Hi});
851 MI.eraseFromParent();
852 return true;
853}
854
855bool RegBankLegalizeHelper::lowerSplitTo16(MachineInstr &MI) {
856 Register Dst = MI.getOperand(0).getReg();
857 assert(MRI.getType(Dst) == V2S16);
858 unsigned Opc = MI.getOpcode();
859 unsigned NumOps = MI.getNumOperands();
860 auto Flags = MI.getFlags();
861
862 auto [Op1Lo, Op1Hi] = unpackAExtTruncS16(MI.getOperand(1).getReg());
863 LLT EltTy = MRI.getType(Dst).getElementType();
864
865 if (NumOps == 2) {
866 auto Lo = B.buildInstr(Opc, {{SgprRB, EltTy}}, {Op1Lo}, Flags);
867 auto Hi = B.buildInstr(Opc, {{SgprRB, EltTy}}, {Op1Hi}, Flags);
868 B.buildMergeLikeInstr(Dst, {Lo, Hi});
869 MI.eraseFromParent();
870 return true;
871 }
872
873 auto [Op2Lo, Op2Hi] = unpackAExtTruncS16(MI.getOperand(2).getReg());
874
875 if (NumOps == 3) {
876 auto Lo = B.buildInstr(Opc, {{SgprRB, EltTy}}, {Op1Lo, Op2Lo}, Flags);
877 auto Hi = B.buildInstr(Opc, {{SgprRB, EltTy}}, {Op1Hi, Op2Hi}, Flags);
878 B.buildMergeLikeInstr(Dst, {Lo, Hi});
879 MI.eraseFromParent();
880 return true;
881 }
882
883 assert(NumOps == 4);
884 auto [Op3Lo, Op3Hi] = unpackAExtTruncS16(MI.getOperand(3).getReg());
885 auto Lo = B.buildInstr(Opc, {{SgprRB, EltTy}}, {Op1Lo, Op2Lo, Op3Lo}, Flags);
886 auto Hi = B.buildInstr(Opc, {{SgprRB, EltTy}}, {Op1Hi, Op2Hi, Op3Hi}, Flags);
887 B.buildMergeLikeInstr(Dst, {Lo, Hi});
888 MI.eraseFromParent();
889 return true;
890}
891
892bool RegBankLegalizeHelper::lowerUniMAD64(MachineInstr &MI) {
893 Register Dst0 = MI.getOperand(0).getReg();
894 Register Dst1 = MI.getOperand(1).getReg();
895 Register Src0 = MI.getOperand(2).getReg();
896 Register Src1 = MI.getOperand(3).getReg();
897 Register Src2 = MI.getOperand(4).getReg();
898
899 const GCNSubtarget &ST = B.getMF().getSubtarget<GCNSubtarget>();
900
901 // Keep the multiplication on the SALU.
902 Register DstLo = B.buildMul(SgprRB_I32, Src0, Src1).getReg(0);
903 Register DstHi = MRI.createVirtualRegister(SgprRB_I32);
904 if (ST.hasScalarMulHiInsts()) {
905 B.buildInstr(AMDGPU::G_UMULH, {{DstHi}}, {Src0, Src1});
906 } else {
907 auto VSrc0 = B.buildCopy(VgprRB_I32, Src0);
908 auto VSrc1 = B.buildCopy(VgprRB_I32, Src1);
909 auto MulHi = B.buildInstr(AMDGPU::G_UMULH, {VgprRB_I32}, {VSrc0, VSrc1});
910 buildReadAnyLane(B, DstHi, MulHi.getReg(0), RBI);
911 }
912
913 // Accumulate and produce the "carry-out" bit.
914
915 // The "carry-out" is defined as bit 64 of the result when computed as a
916 // big integer. For unsigned multiply-add, this matches the usual
917 // definition of carry-out.
918 if (mi_match(Src2, MRI, MIPatternMatch::m_ZeroInt())) {
919 // No accumulate: result is just the multiplication, carry is 0.
920 B.buildMergeLikeInstr(Dst0, {DstLo, DstHi});
921 B.buildConstant(Dst1, 0);
922 } else {
923 // Accumulate: add Src2 to the multiplication result with carry chain.
924 Register Src2Lo = MRI.createVirtualRegister(SgprRB_I32);
925 Register Src2Hi = MRI.createVirtualRegister(SgprRB_I32);
926 B.buildUnmerge({Src2Lo, Src2Hi}, Src2);
927
928 auto AddLo = B.buildUAddo(SgprRB_I32, SgprRB_I32, DstLo, Src2Lo);
929 auto AddHi =
930 B.buildUAdde(SgprRB_I32, SgprRB_I32, DstHi, Src2Hi, AddLo.getReg(1));
931 B.buildMergeLikeInstr(Dst0, {AddLo.getReg(0), AddHi.getReg(0)});
932 B.buildCopy(Dst1, AddHi.getReg(1));
933 }
934
935 MI.eraseFromParent();
936 return true;
937}
938
939bool RegBankLegalizeHelper::lowerSplitTo32Select(MachineInstr &MI) {
940 Register Dst = MI.getOperand(0).getReg();
941 LLT DstTy = MRI.getType(Dst);
942 assert(DstTy == V4S16 || DstTy == V2S32 || DstTy == S64 ||
943 (DstTy.isPointer() && DstTy.getSizeInBits() == 64));
944 LLT Ty = DstTy.isFloat() ? LLT::float32() : DstTy.divide(2);
945 auto Op2 = B.buildUnmerge({VgprRB, Ty}, MI.getOperand(2).getReg());
946 auto Op3 = B.buildUnmerge({VgprRB, Ty}, MI.getOperand(3).getReg());
947 Register Cond = MI.getOperand(1).getReg();
948 Cond = B.buildFreeze(VccRB_S1, Cond).getReg(0);
949 auto Flags = MI.getFlags();
950 auto Lo =
951 B.buildSelect({VgprRB, Ty}, Cond, Op2.getReg(0), Op3.getReg(0), Flags);
952 auto Hi =
953 B.buildSelect({VgprRB, Ty}, Cond, Op2.getReg(1), Op3.getReg(1), Flags);
954
955 B.buildMergeLikeInstr(Dst, {Lo, Hi});
956 MI.eraseFromParent();
957 return true;
958}
959
960bool RegBankLegalizeHelper::lowerSplitTo32SExtInReg(MachineInstr &MI) {
961 auto Op1 = B.buildUnmerge(VgprRB_I32, MI.getOperand(1).getReg());
962 int Amt = MI.getOperand(2).getImm();
963 Register Lo, Hi;
964 // Hi|Lo: s sign bit, ?/x bits changed/not changed by sign-extend
965 if (Amt <= 32) {
966 auto Freeze = B.buildFreeze(VgprRB_I32, Op1.getReg(0));
967 if (Amt == 32) {
968 // Hi|Lo: ????????|sxxxxxxx -> ssssssss|sxxxxxxx
969 Lo = Freeze.getReg(0);
970 } else {
971 // Hi|Lo: ????????|???sxxxx -> ssssssss|ssssxxxx
972 Lo = B.buildSExtInReg(VgprRB_I32, Freeze, Amt).getReg(0);
973 }
974
975 auto SignExtCst = B.buildConstant(SgprRB_I32, 31);
976 Hi = B.buildAShr(VgprRB_I32, Lo, SignExtCst).getReg(0);
977 } else {
978 // Hi|Lo: ?????sxx|xxxxxxxx -> ssssssxx|xxxxxxxx
979 Lo = Op1.getReg(0);
980 Hi = B.buildSExtInReg(VgprRB_I32, Op1.getReg(1), Amt - 32).getReg(0);
981 }
982
983 B.buildMergeLikeInstr(MI.getOperand(0).getReg(), {Lo, Hi});
984 MI.eraseFromParent();
985 return true;
986}
987
988bool RegBankLegalizeHelper::lowerSplitBitCount64To32(MachineInstr &MI) {
989 // Split 64-bit find-first-bit operations into 32-bit halves:
990 // (ffbh hi:lo) -> umin(ffbh(hi), uaddsat(ffbh(lo), 32))
991 // (ffbl hi:lo) -> umin(ffbl(lo), uaddsat(ffbl(hi), 32))
992 // (ctlz_zero_poison hi:lo) -> umin(ffbh(hi), add(ffbh(lo), 32))
993 // (cttz_zero_poison hi:lo) -> umin(ffbl(lo), add(ffbl(hi), 32))
994 unsigned Opc = MI.getOpcode();
995
996 // FFBH/FFBL return 0xFFFFFFFF on zero input, using uaddsat to avoid
997 // wrapping. CTLZ/CTTZ guarantee non-zero input (zero_poison), so plain add
998 // is fine.
999 unsigned FFBOpc;
1000 unsigned AddOpc;
1001 bool SearchFromMSB;
1002 switch (Opc) {
1003 case AMDGPU::G_AMDGPU_FFBH_U32:
1004 FFBOpc = Opc;
1005 AddOpc = AMDGPU::G_UADDSAT;
1006 SearchFromMSB = true;
1007 break;
1008 case AMDGPU::G_AMDGPU_FFBL_B32:
1009 FFBOpc = Opc;
1010 AddOpc = AMDGPU::G_UADDSAT;
1011 SearchFromMSB = false;
1012 break;
1013 case AMDGPU::G_CTLZ_ZERO_POISON:
1014 FFBOpc = AMDGPU::G_AMDGPU_FFBH_U32;
1015 AddOpc = AMDGPU::G_ADD;
1016 SearchFromMSB = true;
1017 break;
1018 case AMDGPU::G_CTTZ_ZERO_POISON:
1019 FFBOpc = AMDGPU::G_AMDGPU_FFBL_B32;
1020 AddOpc = AMDGPU::G_ADD;
1021 SearchFromMSB = false;
1022 break;
1023 default:
1024 llvm_unreachable("unexpected opcode in lowerSplitBitCount64To32");
1025 }
1026
1027 auto Unmerge = B.buildUnmerge(VgprRB_I32, MI.getOperand(1).getReg());
1028 Register Lo = Unmerge.getReg(0);
1029 Register Hi = Unmerge.getReg(1);
1030
1031 // MSB-first (FFBH/CTLZ) searches hi first; LSB-first (FFBL/CTTZ) searches
1032 // lo first. The secondary half adds 32 to account for the primary half's
1033 // width.
1034 auto Primary = B.buildInstr(FFBOpc, {VgprRB_I32}, {SearchFromMSB ? Hi : Lo});
1035 auto Secondary =
1036 B.buildInstr(FFBOpc, {VgprRB_I32}, {SearchFromMSB ? Lo : Hi});
1037
1038 auto Adjusted = B.buildInstr(AddOpc, {VgprRB_I32},
1039 {Secondary, B.buildConstant(VgprRB_I32, 32)});
1040 B.buildUMin(MI.getOperand(0).getReg(), Primary, Adjusted);
1041
1042 MI.eraseFromParent();
1043 return true;
1044}
1045
1046bool RegBankLegalizeHelper::lowerExtrVecEltToSel(MachineInstr &MI) {
1047 // Lower extract vector element to a compare-select chain:
1048 // result = elt[0]
1049 // for i in 1..N-1:
1050 // result = (idx == i) ? elt[i] : result
1051 //
1052 // When the index is divergent, each lane may want a different element, so
1053 // we must check every element per lane.
1054 Register Dst = MI.getOperand(0).getReg();
1055 Register Src = MI.getOperand(1).getReg();
1056 Register Idx = MI.getOperand(2).getReg();
1057
1058 LLT VecTy = MRI.getType(Src);
1059 LLT ScalarTy = VecTy.getScalarType();
1060 unsigned NumElts = VecTy.getNumElements();
1061 MachineRegisterInfo::VRegAttrs VgprRB_EltTy = {VgprRB, ScalarTy};
1062
1063 auto Unmerge = B.buildUnmerge(VgprRB_EltTy, Src);
1064
1065 if (ScalarTy.getSizeInBits() == 32) {
1066 Register PrevSelect = Unmerge.getReg(0);
1067 for (unsigned I = 1; I < NumElts; ++I) {
1068 auto IdxConst = B.buildConstant({SgprRB, MRI.getType(Idx)}, I);
1069 auto Cmp = B.buildICmp(CmpInst::ICMP_EQ, VccRB_S1, Idx, IdxConst);
1070 PrevSelect =
1071 B.buildSelect(VgprRB_EltTy, Cmp, Unmerge.getReg(I), PrevSelect)
1072 .getReg(0);
1073 }
1074 B.buildCopy(Dst, PrevSelect);
1075 } else if (ScalarTy.getSizeInBits() == 64) {
1076 auto InitUnmerge = B.buildUnmerge(VgprRB_I32, Unmerge.getReg(0));
1077 Register PrevLo = InitUnmerge.getReg(0);
1078 Register PrevHi = InitUnmerge.getReg(1);
1079 for (unsigned I = 1; I < NumElts; ++I) {
1080 auto IdxConst = B.buildConstant({SgprRB, MRI.getType(Idx)}, I);
1081 auto Cmp = B.buildICmp(CmpInst::ICMP_EQ, VccRB_S1, Idx, IdxConst);
1082 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Unmerge.getReg(I));
1083 PrevLo = B.buildSelect(VgprRB_I32, Cmp, EltUnmerge.getReg(0), PrevLo)
1084 .getReg(0);
1085 PrevHi = B.buildSelect(VgprRB_I32, Cmp, EltUnmerge.getReg(1), PrevHi)
1086 .getReg(0);
1087 }
1088 B.buildMergeLikeInstr(Dst, {PrevLo, PrevHi});
1089 } else {
1091 MF, MORE, DEBUG_TYPE,
1092 "AMDGPU RegBankLegalize: ExtrVecEltToSel unsupported element type", MI);
1093 return false;
1094 }
1095
1096 MI.eraseFromParent();
1097 return true;
1098}
1099
1100bool RegBankLegalizeHelper::lowerExtrVecEltTo32(MachineInstr &MI) {
1101 // Reduce a 64-bit element extract to two 32-bit extracts:
1102 // vec32 = bitcast <N x s64> to <2N x s32>
1103 // lo = vec32[idx * 2]
1104 // hi = vec32[idx * 2 + 1]
1105 // result = merge(lo, hi)
1106 //
1107 // When the index is uniform, all lanes extract the same element, so we can
1108 // just split the s64 extract into two s32 extracts which lower to MOVREL.
1109 Register Dst = MI.getOperand(0).getReg();
1110 Register Src = MI.getOperand(1).getReg();
1111 Register Idx = MI.getOperand(2).getReg();
1112
1113 LLT SrcTy = MRI.getType(Src);
1114 LLT Vec32Ty = LLT::fixed_vector(2 * SrcTy.getNumElements(), 32);
1115
1116 assert(MRI.getRegBank(Src) == VgprRB && MRI.getRegBank(Idx) == SgprRB &&
1117 "expected VGPR src and SGPR idx");
1118
1119 auto CastSrc = B.buildBitcast({VgprRB, Vec32Ty}, Src);
1120
1121 // Calculate new Lo and Hi indices
1122 auto One = B.buildConstant(SgprRB_I32, 1);
1123 auto IdxLo = B.buildShl(SgprRB_I32, Idx, One);
1124 auto IdxHi = B.buildAdd(SgprRB_I32, IdxLo, One);
1125
1126 auto ExtLo = B.buildExtractVectorElement(VgprRB_I32, CastSrc, IdxLo);
1127 auto ExtHi = B.buildExtractVectorElement(VgprRB_I32, CastSrc, IdxHi);
1128
1129 B.buildMergeLikeInstr(Dst, {ExtLo.getReg(0), ExtHi.getReg(0)});
1130
1131 MI.eraseFromParent();
1132 return true;
1133}
1134
1135bool RegBankLegalizeHelper::lowerInsVecEltToSel(MachineInstr &MI) {
1136 // Lower insert vector element to a compare-select chain:
1137 // for i in 0..N-1:
1138 // result[i] = (idx == i) ? elt : srcVec[i]
1139 // dst = merge(result[0..N-1])
1140 //
1141 // VGPR B64 requires splitting to lo/hi s32 pairs since there is no
1142 // v_cndmask_b64. SGPR B64/B32 and VGPR B32 can be handled natively.
1143 Register Dst = MI.getOperand(0).getReg();
1144 Register Src = MI.getOperand(1).getReg();
1145 Register Elt = MI.getOperand(2).getReg();
1146 Register Idx = MI.getOperand(3).getReg();
1147
1148 LLT VecTy = MRI.getType(Src);
1149 LLT ScalarTy = VecTy.getScalarType();
1150 unsigned NumElts = VecTy.getNumElements();
1151 const RegisterBank *SrcRB = MRI.getRegBank(Src);
1152 bool IsSGPR = (SrcRB == SgprRB);
1153 SmallVector<Register, 16> Selects;
1154
1155 if (!IsSGPR && ScalarTy.getSizeInBits() == 64) {
1156 // VGPR B64: split to 32-bit lo/hi since there is no v_cndmask_b64.
1157 auto Unmerge = B.buildUnmerge(VgprRB_I32, Src);
1158 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Elt);
1159 Register EltLo = EltUnmerge.getReg(0);
1160 Register EltHi = EltUnmerge.getReg(1);
1161 for (unsigned I = 0; I < NumElts; ++I) {
1162 auto IdxConst = B.buildConstant(VgprRB_I32, I);
1163 auto Cmp = B.buildICmp(CmpInst::ICMP_EQ, VccRB_S1, Idx, IdxConst);
1164 Selects.push_back(
1165 B.buildSelect(VgprRB_I32, Cmp, EltLo, Unmerge.getReg(2 * I))
1166 .getReg(0));
1167 Selects.push_back(
1168 B.buildSelect(VgprRB_I32, Cmp, EltHi, Unmerge.getReg(2 * I + 1))
1169 .getReg(0));
1170 }
1171 LLT Vec32Ty = LLT::fixed_vector(2 * NumElts, 32);
1172 auto Vec32 = B.buildBuildVector({VgprRB, Vec32Ty}, Selects);
1173 B.buildBitcast(Dst, Vec32);
1174 } else if (ScalarTy.getSizeInBits() == 32 || ScalarTy.getSizeInBits() == 64) {
1175 // B32 (any bank) and SGPR B64: element-wise select at native width.
1176 MachineRegisterInfo::VRegAttrs SrcRB_EltTy = {SrcRB, ScalarTy};
1177 MachineRegisterInfo::VRegAttrs CmpTy = IsSGPR ? SgprRB_I32 : VccRB_S1;
1178 auto Unmerge = B.buildUnmerge(SrcRB_EltTy, Src);
1179 for (unsigned I = 0; I < NumElts; ++I) {
1180 auto IdxConst = B.buildConstant(SgprRB_I32, I);
1181 auto Cmp = B.buildICmp(CmpInst::ICMP_EQ, CmpTy, Idx, IdxConst);
1182 Selects.push_back(
1183 B.buildSelect(SrcRB_EltTy, Cmp, Elt, Unmerge.getReg(I)).getReg(0));
1184 }
1185 B.buildMergeLikeInstr(Dst, Selects);
1186 } else {
1188 MF, MORE, DEBUG_TYPE,
1189 "AMDGPU RegBankLegalize: InsVecEltToSel unsupported element type", MI);
1190 return false;
1191 }
1192
1193 MI.eraseFromParent();
1194 return true;
1195}
1196
1197bool RegBankLegalizeHelper::lowerInsVecEltTo32(MachineInstr &MI) {
1198 // Reduce a 64-bit element insert to two 32-bit inserts:
1199 // vec32 = bitcast <N x s64> to <2N x s32>
1200 // lo, hi = unmerge elt
1201 // vec32[idx * 2] = lo
1202 // vec32[idx * 2 + 1] = hi
1203 // dst = bitcast <2N x s32> to <N x s64>
1204 //
1205 // When the index is uniform, all lanes insert at the same position, so we
1206 // can split the s64 insert into two s32 inserts which lower to MOVREL/GPRIDX.
1207 Register Dst = MI.getOperand(0).getReg();
1208 Register Src = MI.getOperand(1).getReg();
1209 Register Elt = MI.getOperand(2).getReg();
1210 Register Idx = MI.getOperand(3).getReg();
1211
1212 LLT SrcTy = MRI.getType(Src);
1213 LLT Vec32Ty = LLT::fixed_vector(2 * SrcTy.getNumElements(), 32);
1214
1215 assert(MRI.getRegBank(Src) == VgprRB && MRI.getRegBank(Idx) == SgprRB &&
1216 "expected VGPR src and SGPR idx");
1217
1218 MachineRegisterInfo::VRegAttrs VgprRB_Vec32Ty = {VgprRB, Vec32Ty};
1219
1220 auto CastSrc = B.buildBitcast(VgprRB_Vec32Ty, Src);
1221 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Elt);
1222
1223 // Calculate new Lo and Hi indices
1224 auto One = B.buildConstant(SgprRB_I32, 1);
1225 auto IdxLo = B.buildShl(SgprRB_I32, Idx, One);
1226 auto IdxHi = B.buildAdd(SgprRB_I32, IdxLo, One);
1227
1228 auto InsLo = B.buildInsertVectorElement(VgprRB_Vec32Ty, CastSrc,
1229 EltUnmerge.getReg(0), IdxLo);
1230 auto InsHi = B.buildInsertVectorElement(VgprRB_Vec32Ty, InsLo,
1231 EltUnmerge.getReg(1), IdxHi);
1232
1233 B.buildBitcast(Dst, InsHi);
1234
1235 MI.eraseFromParent();
1236 return true;
1237}
1238
1239bool RegBankLegalizeHelper::lowerAbsToNegMax(MachineInstr &MI) {
1240 // Lower divergent G_ABS to smax(x, 0 - x) in the VGPR bank:
1241 // zero = 0
1242 // neg = G_SUB zero, x
1243 // dst = G_SMAX x, neg
1244 //
1245 // There is no integer v_abs instruction on AMDGPU, so divergent G_ABS is
1246 // expanded to this sub/smax pair.
1247 Register DstReg = MI.getOperand(0).getReg();
1248 Register SrcReg = MI.getOperand(1).getReg();
1249 LLT Ty = MRI.getType(DstReg);
1250
1251 Register Zero;
1252 if (Ty == V2S16) {
1253 // buildConstant cannot produce a V2S16 directly; pack two S16 zeros.
1254 Register Zero16 = B.buildConstant({VgprRB, I16}, 0).getReg(0);
1255 Zero = B.buildBuildVector({VgprRB, Ty}, {Zero16, Zero16}).getReg(0);
1256 } else {
1257 assert((Ty == S32 || Ty == S16) && "unexpected type for AbsToNegMax");
1258 Zero = B.buildConstant({VgprRB, Ty}, 0).getReg(0);
1259 }
1260
1261 auto Neg = B.buildSub({VgprRB, Ty}, Zero, SrcReg);
1262 B.buildSMax(DstReg, SrcReg, Neg);
1263 MI.eraseFromParent();
1264 return true;
1265}
1266
1267bool RegBankLegalizeHelper::lowerAbsToS32(MachineInstr &MI) {
1268 // Lower uniform V2S16 abs by unpacking the values to two separate SGPR
1269 // registers and re-emitting G_ABS on each:
1270 // packed = bitcast <2 x s16> src to s32
1271 // lo = sext_inreg packed, 16
1272 // hi = ashr packed, 16
1273 // dst = build_vector_trunc G_ABS(lo), G_ABS(hi)
1274 //
1275 // SALU only has s_abs_i32, with no direct uniform V2S16 abs. The
1276 // re-emitted G_ABS(SgprRB, S32) selects to s_abs_i32 on each value.
1277 auto Bitcast = B.buildBitcast({SgprRB_I32}, MI.getOperand(1).getReg());
1278 auto SextInReg = B.buildSExtInReg({SgprRB_I32}, Bitcast, 16);
1279 auto ShiftHi =
1280 B.buildAShr({SgprRB_I32}, Bitcast, B.buildConstant({SgprRB_I32}, 16));
1281
1282 auto AbsLo = B.buildInstr(AMDGPU::G_ABS, {{SgprRB_I32}}, {SextInReg});
1283 auto AbsHi = B.buildInstr(AMDGPU::G_ABS, {{SgprRB_I32}}, {ShiftHi});
1284 B.buildBuildVectorTrunc(MI.getOperand(0).getReg(),
1285 {AbsLo.getReg(0), AbsHi.getReg(0)});
1286
1287 MI.eraseFromParent();
1288 return true;
1289}
1290
1291// Ported from SITargetLowering::lowerSET_ROUNDING in SIISelLowering.cpp.
1292// Keep the mapping logic and conversion tables aligned with the SDAG lowering.
1293bool RegBankLegalizeHelper::lowerSetRounding(MachineInstr &MI) {
1294 Register NewMode = MI.getOperand(0).getReg();
1295
1296 // Index a table of 4-bit entries mapping from the C FLT_ROUNDS values to the
1297 // hardware MODE.fp_round values.
1298 if (auto ConstMode = getIConstantVRegValWithLookThrough(NewMode, MRI)) {
1299 uint32_t ClampedVal = std::min(
1300 static_cast<uint32_t>(ConstMode->Value.getZExtValue()),
1301 static_cast<uint32_t>(AMDGPU::TowardZeroF32_TowardNegativeF64));
1302 uint32_t DecodedVal = AMDGPU::decodeFltRoundToHWConversionTable(ClampedVal);
1303 NewMode = B.buildConstant(SgprRB_I32, DecodedVal).getReg(0);
1304 } else {
1305 // If we know the input can only be one of the supported standard modes in
1306 // the range 0-3, we can use a simplified mapping to hardware values.
1307 KnownBits Known = VT->getKnownBits(NewMode);
1308 const bool UseReducedTable = Known.countMinLeadingZeros() >= 30;
1309 // The supported standard values are 0-3. The extended values start at 8. We
1310 // need to offset by 4 if the value is in the extended range.
1311
1312 if (UseReducedTable) {
1313 // Truncate to the low 32-bits.
1314 auto BitTable = B.buildConstant(
1315 SgprRB_I32, AMDGPU::FltRoundToHWConversionTable & 0xffff);
1316
1317 auto Two = B.buildConstant(SgprRB_I32, 2);
1318 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, NewMode, Two);
1319
1320 NewMode =
1321 B.buildLShr(SgprRB_I32, BitTable, RoundModeTimesNumBits).getReg(0);
1322
1323 // TODO: A demanded-bits simplification on the setreg source here could
1324 // likely reduce the table extracted bits into inline immediates.
1325 } else {
1326 // table_index = umin(value, value - 4)
1327 // MODE.fp_round = (bit_table >> (table_index << 2)) & 0xf
1328 auto NegFour = B.buildConstant(SgprRB_I32, -4);
1329 auto OffsetEnum = B.buildAdd(SgprRB_I32, NewMode, NegFour);
1330 auto IndexVal = B.buildUMin(SgprRB_I32, NewMode, OffsetEnum);
1331
1332 auto Two = B.buildConstant(SgprRB_I32, 2);
1333 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, IndexVal, Two);
1334
1335 auto BitTable =
1336 B.buildConstant(SgprRB_I64, AMDGPU::FltRoundToHWConversionTable);
1337 auto TableValue =
1338 B.buildLShr(SgprRB_I64, BitTable, RoundModeTimesNumBits);
1339 // No need to mask out the high bits since the setreg will ignore them
1340 // anyway.
1341 NewMode = B.buildTrunc(SgprRB_I32, TableValue).getReg(0);
1342 }
1343 }
1344
1345 // N.B. The setreg will be later folded into s_round_mode on supported
1346 // targets.
1347 uint32_t BothRoundHwReg =
1349 B.buildIntrinsic(Intrinsic::amdgcn_s_setreg, ArrayRef<DstOp>(),
1350 /*HasSideEffects=*/true, /*isConvergent=*/false)
1351 .addImm(static_cast<int16_t>(BothRoundHwReg))
1352 .addReg(NewMode);
1353
1354 MI.eraseFromParent();
1355 return true;
1356}
1357
1358// Ported from SITargetLowering::lowerGET_ROUNDING in SIISelLowering.cpp.
1359// Keep the mapping logic and conversion tables aligned with the SDAG lowering.
1360bool RegBankLegalizeHelper::lowerGetRounding(MachineInstr &MI) {
1361 Register Dst = MI.getOperand(0).getReg();
1362
1363 uint32_t BothRoundHwReg =
1365 auto GetReg =
1366 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {SgprRB_I32},
1367 /*HasSideEffects=*/true, /*isConvergent=*/false)
1368 .addImm(BothRoundHwReg);
1369
1370 // There are two rounding modes, one for f32 and one for f64/f16. We only
1371 // report in the standard value range if both are the same.
1372 //
1373 // The raw values also differ from the expected FLT_ROUNDS values. Nearest
1374 // ties away from zero is not supported, and the other values are rotated by
1375 // 1.
1376 //
1377 // If the two rounding modes are not the same, report a target defined value.
1378
1379 // Mode register rounding mode fields:
1380 //
1381 // [1:0] Single-precision round mode.
1382 // [3:2] Double/Half-precision round mode.
1383 //
1384 // 0=nearest even; 1= +infinity; 2= -infinity, 3= toward zero.
1385 //
1386 // Hardware Spec
1387 // Toward-0 3 0
1388 // Nearest Even 0 1
1389 // +Inf 1 2
1390 // -Inf 2 3
1391 // NearestAway0 N/A 4
1392 //
1393 // We have to handle 16 permutations of a 4-bit value, so we create a 64-bit
1394 // table we can index by the raw hardware mode.
1395 //
1396 // (trunc (FltRoundConversionTable >> MODE.fp_round)) & 0xf
1397 auto BitTable = B.buildConstant(SgprRB_I64, AMDGPU::FltRoundConversionTable);
1398
1399 auto Two = B.buildConstant(SgprRB_I32, 2);
1400 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, GetReg, Two);
1401
1402 // TODO: We could possibly avoid a 64-bit shift and use a simpler table if we
1403 // knew only one mode was demanded.
1404 auto TableValue = B.buildLShr(SgprRB_I64, BitTable, RoundModeTimesNumBits);
1405 auto TruncTable = B.buildTrunc(SgprRB_I32, TableValue);
1406
1407 auto EntryMask = B.buildConstant(SgprRB_I32, 0xf);
1408 auto TableEntry = B.buildAnd(SgprRB_I32, TruncTable, EntryMask);
1409
1410 // There's a gap in the 4-bit encoded table and actual enum values, so offset
1411 // if it's an extended value.
1412 auto Four = B.buildConstant(SgprRB_I32, 4);
1413 auto EnumOffset = B.buildAdd(SgprRB_I32, TableEntry, Four);
1414 auto IsStandardMode =
1415 B.buildICmp(CmpInst::ICMP_ULT, SgprRB_I32, TableEntry, Four);
1416 B.buildSelect(Dst, IsStandardMode, TableEntry, EnumOffset);
1417
1418 MI.eraseFromParent();
1419 return true;
1420}
1421
1422bool RegBankLegalizeHelper::lower(MachineInstr &MI,
1423 const RegBankLLTMapping &Mapping,
1424 WaterfallInfo &WFI) {
1425
1426 switch (Mapping.LoweringMethod) {
1427 case DoNotLower:
1428 break;
1429 case VccExtToSel:
1430 return lowerVccExtToSel(MI);
1431 case UniExtToSel: {
1432 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
1433 auto True = B.buildConstant({SgprRB, Ty},
1434 MI.getOpcode() == AMDGPU::G_SEXT ? -1 : 1);
1435 auto False = B.buildConstant({SgprRB, Ty}, 0);
1436 // Input to G_{Z|S}EXT is 'Legalizer legal' S1. Most common case is compare.
1437 // We are making select here. S1 cond was already 'any-extended to S32' +
1438 // 'AND with 1 to clean high bits' by Sgpr32AExtBoolInReg.
1439 B.buildSelect(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), True,
1440 False);
1441 MI.eraseFromParent();
1442 return true;
1443 }
1444 case UnpackBitShift:
1445 return lowerUnpackBitShift(MI);
1446 case UnpackMinMax:
1447 return lowerUnpackMinMax(MI);
1448 case ScalarizeToS16:
1449 return lowerSplitTo16(MI);
1450 case Ext32To64: {
1451 const RegisterBank *RB = MRI.getRegBank(MI.getOperand(0).getReg());
1452 MachineInstrBuilder Hi;
1453 switch (MI.getOpcode()) {
1454 case AMDGPU::G_ZEXT: {
1455 Hi = B.buildConstant({RB, I32}, 0);
1456 break;
1457 }
1458 case AMDGPU::G_SEXT: {
1459 // Replicate sign bit from 32-bit extended part.
1460 auto ShiftAmt = B.buildConstant({RB, I32}, 31);
1461 Hi = B.buildAShr({RB, MRI.getType(MI.getOperand(1).getReg())},
1462 MI.getOperand(1).getReg(), ShiftAmt);
1463 break;
1464 }
1465 case AMDGPU::G_ANYEXT: {
1466 Hi = B.buildUndef({RB, I32});
1467 break;
1468 }
1469 default:
1471 "AMDGPU RegBankLegalize: Ext32To64, unsuported opcode",
1472 MI);
1473 return false;
1474 }
1475
1476 B.buildMergeLikeInstr(MI.getOperand(0).getReg(),
1477 {MI.getOperand(1).getReg(), Hi});
1478 MI.eraseFromParent();
1479 return true;
1480 }
1481 case UniCstExt: {
1482 uint64_t ConstVal = MI.getOperand(1).getCImm()->getZExtValue();
1483 B.buildConstant(MI.getOperand(0).getReg(), ConstVal);
1484
1485 MI.eraseFromParent();
1486 return true;
1487 }
1488 case VgprToVccCopy: {
1489 Register Src = MI.getOperand(1).getReg();
1490 LLT Ty = MRI.getType(Src);
1491 // Take lowest bit from each lane and put it in lane mask.
1492 // Lowering via compare, but we need to clean high bits first as compare
1493 // compares all bits in register.
1494 Register BoolSrc = MRI.createVirtualRegister({VgprRB, Ty});
1495 if (Ty == S64) {
1496 auto Src64 = B.buildUnmerge(VgprRB_I32, Src);
1497 auto One = B.buildConstant(VgprRB_I32, 1);
1498 auto AndLo = B.buildAnd(VgprRB_I32, Src64.getReg(0), One);
1499 auto Zero = B.buildConstant(VgprRB_I32, 0);
1500 auto AndHi = B.buildAnd(VgprRB_I32, Src64.getReg(1), Zero);
1501 B.buildMergeLikeInstr(BoolSrc, {AndLo, AndHi});
1502 } else {
1503 assert(Ty == S32 || Ty == S16);
1504 auto One = B.buildConstant({VgprRB, Ty}, 1);
1505 B.buildAnd(BoolSrc, Src, One);
1506 }
1507 auto Zero = B.buildConstant({VgprRB, Ty}, 0);
1508 B.buildICmp(CmpInst::ICMP_NE, MI.getOperand(0).getReg(), BoolSrc, Zero);
1509 MI.eraseFromParent();
1510 return true;
1511 }
1512 case V_BFE:
1513 return lowerV_BFE(MI);
1514 case S_BFE:
1515 return lowerS_BFE(MI);
1516 case UniMAD64:
1517 return lowerUniMAD64(MI);
1518 case UniMul64: {
1519 B.buildMul(MI.getOperand(0), MI.getOperand(1), MI.getOperand(2));
1520 MI.eraseFromParent();
1521 return true;
1522 }
1523 case DivSMulToMAD: {
1524 auto Op1 = B.buildTrunc(VgprRB_I32, MI.getOperand(1));
1525 auto Op2 = B.buildTrunc(VgprRB_I32, MI.getOperand(2));
1526 auto Zero = B.buildConstant(VgprRB_I64, 0);
1527
1528 unsigned NewOpc = MI.getOpcode() == AMDGPU::G_AMDGPU_S_MUL_U64_U32
1529 ? AMDGPU::G_AMDGPU_MAD_U64_U32
1530 : AMDGPU::G_AMDGPU_MAD_I64_I32;
1531
1532 B.buildInstr(NewOpc, {MI.getOperand(0).getReg(), SgprRB_I32},
1533 {Op1, Op2, Zero});
1534 MI.eraseFromParent();
1535 return true;
1536 }
1537 case SplitTo32:
1538 return lowerSplitTo32(MI);
1539 case SplitTo32Mul:
1540 return lowerSplitTo32Mul(MI);
1541 case SplitTo32Select:
1542 return lowerSplitTo32Select(MI);
1543 case SplitTo32SExtInReg:
1544 return lowerSplitTo32SExtInReg(MI);
1545 case CtPop64To32: {
1546 auto Unmerge = B.buildUnmerge(VgprRB_I32, MI.getOperand(1).getReg());
1547 auto LoPopCnt = B.buildCTPOP(VgprRB_I32, Unmerge.getReg(0));
1548 auto HiPopCnt = B.buildCTPOP(VgprRB_I32, Unmerge.getReg(1));
1549 // Max popcount of two 32-bit values is 64, so this add cannot overflow.
1550 B.buildAdd(MI.getOperand(0).getReg(), LoPopCnt, HiPopCnt,
1552
1553 MI.eraseFromParent();
1554 break;
1555 }
1556 case S_BUF_to_BUF:
1557 return lowerSBufToBuf(MI, WFI);
1558 case SplitLoad: {
1559 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
1560 unsigned Size = DstTy.getSizeInBits();
1561 // Even split to 128-bit loads
1562 if (Size > 128) {
1563 LLT B128;
1564 if (DstTy.isVector()) {
1565 LLT EltTy = DstTy.getElementType();
1566 B128 = LLT::fixed_vector(128 / EltTy.getSizeInBits(), EltTy);
1567 } else {
1568 B128 = LLT::integer(128);
1569 }
1570 if (Size / 128 == 2)
1571 splitLoad(MI, {B128, B128});
1572 else if (Size / 128 == 4)
1573 splitLoad(MI, {B128, B128, B128, B128});
1574 else {
1576 "AMDGPU RegBankLegalize: SplitLoad, unsuported type",
1577 MI);
1578 return false;
1579 }
1580 }
1581 // 64 and 32 bit load
1582 else if (DstTy == S96)
1583 splitLoad(MI, {S64, S32}, S32);
1584 else if (DstTy == V3S32)
1585 splitLoad(MI, {V2S32, S32}, S32);
1586 else if (DstTy == V6S16)
1587 splitLoad(MI, {V4S16, V2S16}, V2S16);
1588 else {
1590 "AMDGPU RegBankLegalize: SplitLoad, unsuported type",
1591 MI);
1592 return false;
1593 }
1594 return true;
1595 }
1596 case DynStackAlloc: {
1597 const auto &TFI = *ST.getFrameLowering();
1598 // Guard in case the stack growth direction ever changes with scratch
1599 // instructions.
1600 assert(TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp &&
1601 "Stack grows upwards for AMDGPU");
1602
1603 Register Dst = MI.getOperand(0).getReg();
1604 Register AllocSize = MI.getOperand(1).getReg();
1605 Align Alignment = assumeAligned(MI.getOperand(2).getImm());
1606
1607 // Erase before building new instrs to avoid hitting multiple Dst assert
1608 // with CSE.
1609 B.setInsertPt(*MI.getParent(), std::next(MI.getIterator()));
1610 MI.eraseFromParent();
1611
1612 if (MRI.getRegBank(AllocSize) != SgprRB) {
1613 auto WaveReduction =
1614 B.buildIntrinsic(Intrinsic::amdgcn_wave_reduce_umax, {SgprRB_I32})
1615 .addUse(AllocSize)
1616 .addImm(0);
1617 AllocSize = WaveReduction.getReg(0);
1618 }
1619
1620 LLT PtrTy = MRI.getType(Dst);
1621 assert(PtrTy.getSizeInBits() == 32 &&
1622 "Expected 32-bit pointer for stack allocation");
1623 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
1624 Register SPReg = Info->getStackPtrOffsetReg();
1625
1626 // When using flat-scratch, the stack offset is unscaled.
1627 const bool HasFlatScratch = ST.hasFlatScratchEnabled();
1628 const unsigned WavefrontSizeLog2 = ST.getWavefrontSizeLog2();
1629
1630 Register AdjustedSize = AllocSize;
1631 if (!HasFlatScratch) {
1632 auto WaveSize = B.buildConstant(SgprRB_I32, WavefrontSizeLog2);
1633 AdjustedSize = B.buildShl(SgprRB_I32, AllocSize, WaveSize).getReg(0);
1634 }
1635 if (Alignment > TFI.getStackAlign()) {
1636 const uint64_t EffectiveAlignment =
1637 Alignment.value() << (HasFlatScratch ? 0 : WavefrontSizeLog2);
1638 auto OldSP = B.buildCopy({SgprRB, PtrTy}, SPReg);
1639 auto Tmp1 =
1640 B.buildPtrAdd({SgprRB, PtrTy}, OldSP,
1641 B.buildConstant(SgprRB_I32, EffectiveAlignment - 1));
1642 uint64_t Mask = maskTrailingZeros<uint64_t>(Log2_64(EffectiveAlignment));
1643 B.buildPtrMask(Dst, Tmp1, B.buildConstant(SgprRB_I32, Mask));
1644 } else {
1645 B.buildCopy(Dst, SPReg);
1646 }
1647 auto PtrAdd = B.buildPtrAdd({SgprRB, PtrTy}, Dst, AdjustedSize);
1648 B.buildCopy(SPReg, PtrAdd);
1649 return true;
1650 }
1651 case WidenLoad: {
1652 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
1653 if (DstTy == S96)
1654 widenLoad(MI, S128);
1655 else if (DstTy == V3S32)
1656 widenLoad(MI, V4S32, S32);
1657 else if (DstTy == V6S16)
1658 widenLoad(MI, V8S16, V2S16);
1659 else {
1661 "AMDGPU RegBankLegalize: WidenLoad, unsuported type",
1662 MI);
1663 return false;
1664 }
1665 return true;
1666 }
1667 case UnpackAExt:
1668 return lowerUnpackAExt(MI);
1669 case WidenMMOToS32:
1670 return widenMMOToS32(cast<GAnyLoad>(MI));
1671 case VerifyAllSgpr: {
1672 assert(llvm::all_of(MI.operands(), [&](const MachineOperand &Op) {
1673 return MRI.getRegBankOrNull(Op.getReg()) == SgprRB;
1674 }));
1675 return true;
1676 }
1677 case ApplyAllVgpr: {
1678 assert(llvm::all_of(MI.defs(), [&](const MachineOperand &Op) {
1679 return MRI.getRegBankOrNull(Op.getReg()) == VgprRB;
1680 }));
1681 B.setInstrAndDebugLoc(MI);
1682 for (unsigned i = MI.getNumDefs(); i < MI.getNumOperands(); ++i) {
1683 MachineOperand &Op = MI.getOperand(i);
1684 if (!Op.isReg())
1685 continue;
1686 Register Reg = Op.getReg();
1687 if (MRI.getRegBank(Reg) != VgprRB) {
1688 auto Copy = B.buildCopy({VgprRB, MRI.getType(Reg)}, Reg);
1689 Op.setReg(Copy.getReg(0));
1690 }
1691 }
1692 return true;
1693 }
1694 case UnmergeToShiftTrunc: {
1695 GUnmerge *Unmerge = dyn_cast<GUnmerge>(&MI);
1696 LLT Ty = MRI.getType(Unmerge->getSourceReg());
1697 if (Ty.getSizeInBits() % 32 != 0) {
1699 "AMDGPU RegBankLegalize: unmerge not multiple of 32",
1700 MI);
1701 return false;
1702 }
1703
1704 B.setInstrAndDebugLoc(MI);
1705 if (Ty.getSizeInBits() > 32) {
1706 auto UnmergeV2S16 =
1707 B.buildUnmerge({SgprRB, V2S16}, Unmerge->getSourceReg());
1708 for (unsigned i = 0; i < UnmergeV2S16->getNumDefs(); ++i) {
1709 auto [Dst0I32, Dst1I32] =
1710 unpackAExt(UnmergeV2S16->getOperand(i).getReg());
1711 B.buildTrunc(MI.getOperand(i * 2).getReg(), Dst0I32);
1712 B.buildTrunc(MI.getOperand(i * 2 + 1).getReg(), Dst1I32);
1713 }
1714 } else {
1715 auto [Dst0I32, Dst1I32] = unpackAExt(MI.getOperand(2).getReg());
1716 B.buildTrunc(MI.getOperand(0).getReg(), Dst0I32);
1717 B.buildTrunc(MI.getOperand(1).getReg(), Dst1I32);
1718 }
1719
1720 MI.eraseFromParent();
1721 return true;
1722 }
1724 Register Dst = MI.getOperand(0).getReg();
1725 Register NewDst = MRI.createVirtualRegister(SgprRB_I32);
1726 B.setInsertPt(*MI.getParent(), MI.getParent()->getFirstNonPHI());
1727 MI.getOperand(0).setReg(NewDst);
1728 B.buildTrunc(Dst, NewDst);
1729
1730 for (unsigned i = 1; i < MI.getNumOperands(); i += 2) {
1731 Register UseReg = MI.getOperand(i).getReg();
1732
1733 auto DefMI = MRI.getVRegDef(UseReg)->getIterator();
1734 MachineBasicBlock *DefMBB = DefMI->getParent();
1735
1736 B.setInsertPt(*DefMBB, DefMBB->SkipPHIsAndLabels(std::next(DefMI)));
1737
1738 auto NewUse = B.buildAnyExt(SgprRB_I32, UseReg);
1739 MI.getOperand(i).setReg(NewUse.getReg(0));
1740 }
1741 break;
1742 }
1743 case VerifyAllSgprGPHI: {
1744 assert(llvm::all_of(MI.operands(), [&](const MachineOperand &Op) {
1745 if (Op.isMBB())
1746 return true;
1747 return MRI.getRegBankOrNull(Op.getReg()) == SgprRB;
1748 }));
1749 return true;
1750 }
1752 assert(MRI.getRegBankOrNull(MI.getOperand(0).getReg()) == VgprRB);
1753 assert(llvm::all_of(MI.operands(), [&](const MachineOperand &Op) {
1754 if (Op.isMBB())
1755 return true;
1756 const RegisterBank *RB = MRI.getRegBankOrNull(Op.getReg());
1757 return RB == VgprRB || RB == SgprRB;
1758 }));
1759 return true;
1760 }
1761 case ApplyINTRIN_IMAGE: {
1762 const AMDGPU::RsrcIntrinsic *RSrcIntrin =
1764 assert(RSrcIntrin && RSrcIntrin->IsImage);
1765 // The reported argument index is relative to the IR intrinsic call
1766 // arguments, so shift by the number of defs and the intrinsic ID.
1767 unsigned RsrcIdx = RSrcIntrin->RsrcArg + MI.getNumExplicitDefs() + 1;
1768 return applyRegisterBanksVgprWithSgprRsrc(MI, RsrcIdx);
1769 }
1771 // Rsrc is the last register operand. Base BVH trails an A16 immediate
1772 // after rsrc; dual/BVH8 do not. Scan backwards for the last virtual
1773 // register.
1774 unsigned RsrcIdx = MI.getNumOperands();
1775 while (RsrcIdx-- > MI.getNumExplicitDefs()) {
1776 const MachineOperand &Op = MI.getOperand(RsrcIdx);
1777 if (Op.isReg() && Op.getReg().isVirtual())
1778 break;
1779 }
1780 return applyRegisterBanksVgprWithSgprRsrc(MI, RsrcIdx);
1781 }
1783 return lowerSplitBitCount64To32(MI);
1784 case ExtrVecEltToSel:
1785 return lowerExtrVecEltToSel(MI);
1786 case ExtrVecEltTo32:
1787 return lowerExtrVecEltTo32(MI);
1788 case InsVecEltToSel:
1789 return lowerInsVecEltToSel(MI);
1790 case InsVecEltTo32:
1791 return lowerInsVecEltTo32(MI);
1792 case AbsToNegMax:
1793 return lowerAbsToNegMax(MI);
1794 case AbsToS32:
1795 return lowerAbsToS32(MI);
1796 case DeletePrefetch:
1797 MI.eraseFromParent();
1798 return true;
1799 case LowerSetRounding:
1800 return lowerSetRounding(MI);
1801 case LowerGetRounding:
1802 return lowerGetRounding(MI);
1803 }
1804
1805 return true;
1806}
1807
1808LLT RegBankLegalizeHelper::getTyFromID(RegBankLLTMappingApplyID ID) {
1809 switch (ID) {
1810 case Vcc:
1811 case UniInVcc:
1812 return LLT::scalar(1);
1813 case Sgpr16:
1814 case Vgpr16:
1815 case UniInVgprS16:
1816 return LLT::scalar(16);
1817 case Sgpr32:
1818 case Sgpr32_WF:
1819 case Sgpr32Trunc:
1820 case Sgpr32AExt:
1822 case Sgpr32SExt:
1823 case Sgpr32ZExt:
1824 case UniInVgprS32:
1825 case Sgpr32ToVgprDst:
1826 case Vgpr32:
1827 case Vgpr32AExt:
1828 case Vgpr32SExt:
1829 case Vgpr32ZExt:
1830 return LLT::scalar(32);
1831 case Sgpr64:
1832 case Vgpr64:
1833 case UniInVgprS64:
1834 case Sgpr64ToVgprDst:
1835 return LLT::scalar(64);
1836 case Sgpr128:
1837 case Vgpr128:
1838 return LLT::scalar(128);
1839 case SgprP0:
1840 case SgprP0Call_WF:
1841 case VgprP0:
1842 return LLT::pointer(0, 64);
1843 case SgprP1:
1844 case VgprP1:
1845 return LLT::pointer(1, 64);
1846 case SgprP2:
1847 case VgprP2:
1848 return LLT::pointer(2, 32);
1849 case SgprP3:
1850 case VgprP3:
1851 return LLT::pointer(3, 32);
1852 case SgprP4:
1853 case SgprP4Call_WF:
1854 case VgprP4:
1855 return LLT::pointer(4, 64);
1856 case SgprP5:
1857 case VgprP5:
1858 return LLT::pointer(5, 32);
1859 case SgprP6:
1860 return LLT::pointer(6, 32);
1861 case SgprP8:
1862 return LLT::pointer(8, 128);
1863 case SgprV2S16:
1864 case VgprV2S16:
1865 case UniInVgprV2S16:
1866 return LLT::fixed_vector(2, 16);
1867 case SgprV2S32:
1868 case VgprV2S32:
1869 case UniInVgprV2S32:
1870 return LLT::fixed_vector(2, 32);
1871 case VgprV3S32:
1872 case UniInVgprV3S32:
1873 return LLT::fixed_vector(3, 32);
1874 case VgprV4S16:
1875 return LLT::fixed_vector(4, 16);
1876 case VgprV8S16:
1877 case UniInVgprV8S16:
1878 return LLT::fixed_vector(8, 16);
1879 case VgprV16S16:
1880 case UniInVgprV16S16:
1881 return LLT::fixed_vector(16, 16);
1882 case SgprV4S32:
1883 case SgprV4S32_WF:
1885 case VgprV4S32:
1886 case UniInVgprV4S32:
1887 return LLT::fixed_vector(4, 32);
1888 case VgprV8S32:
1889 case UniInVgprV8S32:
1891 return LLT::fixed_vector(8, 32);
1892 case VgprV2S64:
1893 case UniInVgprV2S64:
1894 return LLT::fixed_vector(2, 64);
1895 case VgprV6S32:
1896 case UniInVgprV6S32:
1897 return LLT::fixed_vector(6, 32);
1898 case VgprV16S32:
1899 case UniInVgprV16S32:
1900 return LLT::fixed_vector(16, 32);
1901 case VgprV32S16:
1902 case UniInVgprV32S16:
1903 return LLT::fixed_vector(32, 16);
1904 case VgprV32S32:
1905 case UniInVgprV32S32:
1906 return LLT::fixed_vector(32, 32);
1907 default:
1908 return LLT();
1909 }
1910}
1911
1912LLT RegBankLegalizeHelper::getBTyFromID(RegBankLLTMappingApplyID ID, LLT Ty) {
1913 switch (ID) {
1914 case SgprB32:
1915 case VgprB32:
1916 case SgprB32_M0:
1918 case UniInVgprB32:
1919 if (Ty == LLT::scalar(32) || Ty == LLT::fixed_vector(2, 16) ||
1920 isAnyPtr(Ty, 32))
1921 return Ty;
1922 return LLT();
1923 case SgprPtr32:
1924 case VgprPtr32:
1925 return isAnyPtr(Ty, 32) ? Ty : LLT();
1926 case SgprPtr64:
1927 case VgprPtr64:
1928 return isAnyPtr(Ty, 64) ? Ty : LLT();
1929 case SgprPtr128:
1930 case VgprPtr128:
1931 return isAnyPtr(Ty, 128) ? Ty : LLT();
1932 case SgprB64:
1933 case VgprB64:
1935 case UniInVgprB64:
1936 if (Ty == LLT::scalar(64) || Ty == LLT::fixed_vector(2, 32) ||
1937 Ty == LLT::fixed_vector(4, 16) || isAnyPtr(Ty, 64))
1938 return Ty;
1939 return LLT();
1940 case SgprB96:
1941 case VgprB96:
1942 case UniInVgprB96:
1943 if (Ty == LLT::scalar(96) || Ty == LLT::fixed_vector(3, 32) ||
1944 Ty == LLT::fixed_vector(6, 16))
1945 return Ty;
1946 return LLT();
1947 case SgprB128:
1948 case VgprB128:
1949 case UniInVgprB128:
1950 if (Ty.getSizeInBits() == 128)
1951 return Ty;
1952 return LLT();
1953 case VgprB160:
1954 case UniInVgprB160:
1955 if (Ty.getSizeInBits() == 160)
1956 return Ty;
1957 return LLT();
1958 case SgprB256:
1959 case VgprB256:
1960 case UniInVgprB256:
1961 if (Ty.getSizeInBits() == 256)
1962 return Ty;
1963 return LLT();
1964 case SgprB512:
1965 case VgprB512:
1966 case UniInVgprB512:
1967 if (Ty.getSizeInBits() == 512)
1968 return Ty;
1969 return LLT();
1970 case SgprBRC: {
1971 const SIRegisterInfo *TRI =
1972 static_cast<const SIRegisterInfo *>(MRI.getTargetRegisterInfo());
1973 unsigned LLTSize = Ty.getSizeInBits();
1974 if (LLTSize >= 32 && TRI->getSGPRClassForBitWidth(LLTSize))
1975 return Ty;
1976 return LLT();
1977 }
1978 case VgprBRC: {
1979 const SIRegisterInfo *TRI =
1980 static_cast<const SIRegisterInfo *>(MRI.getTargetRegisterInfo());
1981 if (TRI->getSGPRClassForBitWidth(Ty.getSizeInBits()))
1982 return Ty;
1983 return LLT();
1984 }
1985 default:
1986 return LLT();
1987 }
1988}
1989
1990const RegisterBank *
1991RegBankLegalizeHelper::getRegBankFromID(RegBankLLTMappingApplyID ID) {
1992 switch (ID) {
1993 case Vcc:
1994 return VccRB;
1995 case Sgpr16:
1996 case Sgpr32:
1997 case Sgpr32_WF:
1998 case Sgpr64:
1999 case Sgpr128:
2000 case SgprP0:
2001 case SgprP0Call_WF:
2002 case SgprP1:
2003 case SgprP2:
2004 case SgprP3:
2005 case SgprP4:
2006 case SgprP4Call_WF:
2007 case SgprP5:
2008 case SgprP6:
2009 case SgprP8:
2010 case SgprPtr32:
2011 case SgprPtr64:
2012 case SgprPtr128:
2013 case SgprV2S16:
2014 case SgprV2S32:
2015 case SgprV4S32:
2016 case SgprV4S32_WF:
2019 case SgprB32:
2020 case SgprB64:
2021 case SgprB96:
2022 case SgprB128:
2023 case SgprB256:
2024 case SgprB512:
2025 case SgprBRC:
2026 case UniInVcc:
2027 case UniInVgprS16:
2028 case UniInVgprS32:
2029 case UniInVgprS64:
2030 case UniInVgprV2S16:
2031 case UniInVgprV2S32:
2032 case UniInVgprV3S32:
2033 case UniInVgprV4S32:
2034 case UniInVgprV2S64:
2035 case UniInVgprV6S32:
2036 case UniInVgprV8S16:
2037 case UniInVgprV8S32:
2038 case UniInVgprV16S16:
2039 case UniInVgprV16S32:
2040 case UniInVgprV32S16:
2041 case UniInVgprV32S32:
2042 case UniInVgprB32:
2043 case UniInVgprB64:
2044 case UniInVgprB96:
2045 case UniInVgprB128:
2046 case UniInVgprB160:
2047 case UniInVgprB256:
2048 case UniInVgprB512:
2049 case Sgpr32Trunc:
2050 case Sgpr32AExt:
2052 case Sgpr32SExt:
2053 case Sgpr32ZExt:
2054 return SgprRB;
2055 case AgprAnyTy:
2056 return AgprRB;
2057 case Vgpr16:
2058 case Vgpr32:
2059 case Vgpr64:
2060 case Vgpr128:
2061 case VgprP0:
2062 case VgprP1:
2063 case VgprP2:
2064 case VgprP3:
2065 case VgprP4:
2066 case VgprP5:
2067 case VgprPtr32:
2068 case VgprPtr64:
2069 case VgprPtr128:
2070 case VgprV2S16:
2071 case VgprV2S32:
2072 case VgprV2S64:
2073 case VgprV3S32:
2074 case VgprV4S16:
2075 case VgprV8S16:
2076 case VgprV16S16:
2077 case VgprV4S32:
2078 case VgprV6S32:
2079 case VgprV8S32:
2080 case VgprV16S32:
2081 case VgprV32S16:
2082 case VgprV32S32:
2083 case VgprB32:
2084 case VgprB64:
2085 case VgprB96:
2086 case VgprB128:
2087 case VgprB160:
2088 case VgprB256:
2089 case VgprB512:
2090 case VgprBRC:
2091 case VgprAnyTy:
2092 case Vgpr32AExt:
2093 case Vgpr32SExt:
2094 case Vgpr32ZExt:
2095 case Sgpr32ToVgprDst:
2096 case Sgpr64ToVgprDst:
2097 return VgprRB;
2098 default:
2099 return nullptr;
2100 }
2101}
2102
2103bool RegBankLegalizeHelper::applyMappingDst(
2104 MachineInstr &MI, unsigned &OpIdx,
2105 const SmallVectorImpl<RegBankLLTMappingApplyID> &MethodIDs) {
2106 // Defs start from operand 0
2107 for (; OpIdx < MethodIDs.size(); ++OpIdx) {
2108 if (MethodIDs[OpIdx] == None)
2109 continue;
2110 MachineOperand &Op = MI.getOperand(OpIdx);
2111 Register Reg = Op.getReg();
2112 LLT Ty = MRI.getType(Reg);
2113 [[maybe_unused]] const RegisterBank *RB = MRI.getRegBank(Reg);
2114
2115 switch (MethodIDs[OpIdx]) {
2116 // vcc, sgpr and vgpr scalars, pointers and vectors
2117 case Vcc:
2118 case Sgpr16:
2119 case Sgpr32:
2120 case Sgpr64:
2121 case Sgpr128:
2122 case SgprP0:
2123 case SgprP1:
2124 case SgprP3:
2125 case SgprP4:
2126 case SgprP5:
2127 case SgprP6:
2128 case SgprP8:
2129 case SgprV2S16:
2130 case SgprV2S32:
2131 case SgprV4S32:
2132 case Vgpr16:
2133 case Vgpr32:
2134 case Vgpr64:
2135 case Vgpr128:
2136 case VgprP0:
2137 case VgprP1:
2138 case VgprP2:
2139 case VgprP3:
2140 case VgprP4:
2141 case VgprP5:
2142 case VgprV2S16:
2143 case VgprV2S32:
2144 case VgprV2S64:
2145 case VgprV3S32:
2146 case VgprV4S16:
2147 case VgprV8S16:
2148 case VgprV16S16:
2149 case VgprV4S32:
2150 case VgprV6S32:
2151 case VgprV8S32:
2152 case VgprV16S32:
2153 case VgprV32S16:
2154 case VgprV32S32: {
2155 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2156 assert(RB == getRegBankFromID(MethodIDs[OpIdx]));
2157 break;
2158 }
2159 // sgpr and vgpr B-types
2160 case SgprB32:
2161 case SgprB64:
2162 case SgprB96:
2163 case SgprB128:
2164 case SgprB256:
2165 case SgprB512:
2166 case SgprBRC:
2167 case SgprPtr32:
2168 case SgprPtr64:
2169 case SgprPtr128:
2170 case VgprB32:
2171 case VgprB64:
2172 case VgprB96:
2173 case VgprB128:
2174 case VgprB160:
2175 case VgprB256:
2176 case VgprB512:
2177 case VgprBRC:
2178 case VgprPtr32:
2179 case VgprPtr64:
2180 case VgprPtr128: {
2181 assert(Ty == getBTyFromID(MethodIDs[OpIdx], Ty));
2182 assert(RB == getRegBankFromID(MethodIDs[OpIdx]));
2183 break;
2184 }
2185 case VgprAnyTy: {
2186 assert(RB == VgprRB);
2187 break;
2188 }
2189 case AgprAnyTy: {
2190 if (RB == AgprRB)
2191 break;
2192 Register NewAgprDst = MRI.createVirtualRegister({AgprRB, Ty});
2193 Op.setReg(NewAgprDst);
2194 if (!MRI.use_nodbg_empty(Reg))
2195 B.buildCopy(Reg, NewAgprDst);
2196 break;
2197 }
2198 case VgprOrAgprAnyTy: {
2199 const unsigned NumRegs = Ty.getSizeInBits() / 32;
2200 const RegisterBank *DstRB =
2201 MFI->selectAGPRFormMFMA(NumRegs) ? AgprRB : VgprRB;
2202 if (RB == DstRB)
2203 break;
2204 Register NewDst = MRI.createVirtualRegister({DstRB, Ty});
2205 Op.setReg(NewDst);
2206 if (!MRI.use_nodbg_empty(Reg))
2207 B.buildCopy(Reg, NewDst);
2208 break;
2209 }
2210 // uniform in vcc/vgpr: scalars, vectors and B-types
2211 case UniInVcc: {
2212 assert(Ty == S1);
2213 assert(RB == SgprRB);
2214 Register NewDst = MRI.createVirtualRegister(VccRB_S1);
2215 Op.setReg(NewDst);
2216 if (!MRI.use_empty(Reg)) {
2217 auto CopyS32_Vcc =
2218 B.buildInstr(AMDGPU::G_AMDGPU_COPY_SCC_VCC, {SgprRB_I32}, {NewDst});
2219 B.buildTrunc(Reg, CopyS32_Vcc);
2220 }
2221 break;
2222 }
2223 case UniInVgprS16: {
2224 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2225 assert(RB == SgprRB);
2226 Register NewVgprDst16 = MRI.createVirtualRegister({VgprRB, Ty});
2227 Register NewVgprDstI32 = MRI.createVirtualRegister(VgprRB_I32);
2228 Register NewSgprDstI32 = MRI.createVirtualRegister(SgprRB_I32);
2229 Op.setReg(NewVgprDst16);
2230 B.buildAnyExt(NewVgprDstI32, NewVgprDst16);
2231 buildReadAnyLane(B, NewSgprDstI32, NewVgprDstI32, RBI);
2232 B.buildTrunc(Reg, NewSgprDstI32);
2233 break;
2234 }
2235 case UniInVgprS32:
2236 case UniInVgprS64:
2237 case UniInVgprV2S16:
2238 case UniInVgprV2S32:
2239 case UniInVgprV3S32:
2240 case UniInVgprV4S32:
2241 case UniInVgprV2S64:
2242 case UniInVgprV6S32:
2243 case UniInVgprV8S16:
2244 case UniInVgprV8S32:
2245 case UniInVgprV16S16:
2246 case UniInVgprV16S32:
2247 case UniInVgprV32S16:
2248 case UniInVgprV32S32: {
2249 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2250 assert(RB == SgprRB);
2251 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, Ty});
2252 Op.setReg(NewVgprDst);
2253 buildReadAnyLane(B, Reg, NewVgprDst, RBI);
2254 break;
2255 }
2256 case UniInVgprB32:
2257 case UniInVgprB64:
2258 case UniInVgprB96:
2259 case UniInVgprB128:
2260 case UniInVgprB160:
2261 case UniInVgprB256:
2262 case UniInVgprB512: {
2263 assert(Ty == getBTyFromID(MethodIDs[OpIdx], Ty));
2264 assert(RB == SgprRB);
2265 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, Ty});
2266 Op.setReg(NewVgprDst);
2267 AMDGPU::buildReadAnyLane(B, Reg, NewVgprDst, RBI);
2268 break;
2269 }
2270 // sgpr trunc
2271 case Sgpr32Trunc: {
2272 assert(Ty.getSizeInBits() < 32);
2273 assert(RB == SgprRB);
2274 Register NewDst = MRI.createVirtualRegister(SgprRB_I32);
2275 Op.setReg(NewDst);
2276 if (!MRI.use_empty(Reg))
2277 B.buildTrunc(Reg, NewDst);
2278 break;
2279 }
2280 case Sgpr32ToVgprDst:
2281 case Sgpr64ToVgprDst: {
2282 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2283 assert(RB == VgprRB);
2284 Op.setReg(MRI.createVirtualRegister({SgprRB, Ty}));
2285 B.buildCopy(Reg, Op.getReg());
2286 break;
2287 }
2288 case InvalidMapping: {
2290 MF, MORE, DEBUG_TYPE,
2291 "AMDGPU RegBankLegalize: missing fast rule ('Div' or 'Uni') for", MI);
2292 return false;
2293 }
2294 default:
2296 MF, MORE, DEBUG_TYPE,
2297 "AMDGPU RegBankLegalize: applyMappingDst, ID not supported", MI);
2298 return false;
2299 }
2300 }
2301
2302 return true;
2303}
2304
2305bool RegBankLegalizeHelper::applyMappingSrc(
2306 MachineInstr &MI, unsigned &OpIdx,
2307 const SmallVectorImpl<RegBankLLTMappingApplyID> &MethodIDs,
2308 WaterfallInfo &WFI) {
2309 for (unsigned i = 0; i < MethodIDs.size(); ++OpIdx, ++i) {
2310 if (MethodIDs[i] == None || MethodIDs[i] == IntrId || MethodIDs[i] == Imm)
2311 continue;
2312
2313 MachineOperand &Op = MI.getOperand(OpIdx);
2314 Register Reg = Op.getReg();
2315 LLT Ty = MRI.getType(Reg);
2316 const RegisterBank *RB = MRI.getRegBank(Reg);
2317
2318 switch (MethodIDs[i]) {
2319 case Vcc: {
2320 assert(Ty == S1);
2321 assert(RB == VccRB || RB == SgprRB);
2322 if (RB == SgprRB) {
2323 auto Aext = B.buildAnyExt(SgprRB_I32, Reg);
2324 auto Cst1 = B.buildConstant(SgprRB_I32, 1);
2325 auto BoolInReg = B.buildAnd(SgprRB_I32, Aext, Cst1);
2326 auto CopyVcc_Scc = B.buildInstr(AMDGPU::G_AMDGPU_COPY_VCC_SCC,
2327 {VccRB_S1}, {BoolInReg});
2328 Op.setReg(CopyVcc_Scc.getReg(0));
2329 }
2330 break;
2331 }
2332 // sgpr scalars, pointers and vectors
2333 case Sgpr16:
2334 case Sgpr32:
2335 case Sgpr64:
2336 case Sgpr128:
2337 case SgprP0:
2338 case SgprP1:
2339 case SgprP3:
2340 case SgprP4:
2341 case SgprP5:
2342 case SgprP6:
2343 case SgprP8:
2344 case SgprV2S16:
2345 case SgprV2S32:
2346 case SgprV4S32: {
2347 assert(Ty == getTyFromID(MethodIDs[i]));
2348 assert(RB == getRegBankFromID(MethodIDs[i]));
2349 break;
2350 }
2351 // sgpr B-types
2352 case SgprB32:
2353 case SgprB64:
2354 case SgprB96:
2355 case SgprB128:
2356 case SgprB256:
2357 case SgprB512:
2358 case SgprBRC:
2359 case SgprPtr32:
2360 case SgprPtr64:
2361 case SgprPtr128: {
2362 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2363 assert(RB == getRegBankFromID(MethodIDs[i]));
2364 break;
2365 }
2366 // vgpr scalars, pointers and vectors
2367 case Vgpr16:
2368 case Vgpr32:
2369 case Vgpr64:
2370 case Vgpr128:
2371 case VgprP0:
2372 case VgprP1:
2373 case VgprP2:
2374 case VgprP3:
2375 case VgprP4:
2376 case VgprP5:
2377 case VgprV2S16:
2378 case VgprV2S32:
2379 case VgprV2S64:
2380 case VgprV3S32:
2381 case VgprV4S16:
2382 case VgprV8S16:
2383 case VgprV16S16:
2384 case VgprV4S32:
2385 case VgprV6S32:
2386 case VgprV8S32:
2387 case VgprV16S32:
2388 case VgprV32S16:
2389 case VgprV32S32: {
2390 assert(Ty == getTyFromID(MethodIDs[i]));
2391 if (RB != VgprRB) {
2392 auto CopyToVgpr = B.buildCopy({VgprRB, Ty}, Reg);
2393 Op.setReg(CopyToVgpr.getReg(0));
2394 }
2395 break;
2396 }
2397 // vgpr B-types
2398 case VgprB32:
2399 case VgprB64:
2400 case VgprB96:
2401 case VgprB128:
2402 case VgprB160:
2403 case VgprB256:
2404 case VgprB512:
2405 case VgprBRC:
2406 case VgprPtr32:
2407 case VgprPtr64:
2408 case VgprPtr128: {
2409 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2410 if (RB != VgprRB) {
2411 auto CopyToVgpr = B.buildCopy({VgprRB, Ty}, Reg);
2412 Op.setReg(CopyToVgpr.getReg(0));
2413 }
2414 break;
2415 }
2416 case VgprAnyTy: {
2417 if (RB != VgprRB) {
2418 auto CopyToVgpr = B.buildCopy({VgprRB, Ty}, Reg);
2419 Op.setReg(CopyToVgpr.getReg(0));
2420 }
2421 break;
2422 }
2423 case AgprAnyTy: {
2424 if (RB != AgprRB) {
2425 auto CopyToAgpr = B.buildCopy({AgprRB, Ty}, Reg);
2426 Op.setReg(CopyToAgpr.getReg(0));
2427 }
2428 break;
2429 }
2430 case VgprOrAgprAnyTy: {
2431 const unsigned NumRegs = Ty.getSizeInBits() / 32;
2432 const RegisterBank *SrcRB =
2433 MFI->selectAGPRFormMFMA(NumRegs) ? AgprRB : VgprRB;
2434 if (RB != SrcRB)
2435 Op.setReg(B.buildCopy({SrcRB, Ty}, Reg).getReg(0));
2436 break;
2437 }
2438 // sgpr waterfall, scalars, and vectors
2439 case Sgpr32_WF:
2440 case SgprV4S32_WF: {
2441 assert(Ty == getTyFromID(MethodIDs[i]));
2442 if (RB != SgprRB) {
2443 WFI.SgprWaterfallOperandRegs.insert(Reg);
2444 if (!WFI.Start.isValid()) {
2445 WFI.Start = MI.getIterator();
2446 WFI.End = std::next(MI.getIterator());
2447 }
2448 }
2449 break;
2450 }
2451 case SgprP0Call_WF:
2452 case SgprP4Call_WF: {
2453 assert(Ty == getTyFromID(MethodIDs[i]));
2454 if (RB != SgprRB) {
2455 WFI.SgprWaterfallOperandRegs.insert(Reg);
2456
2457 // Find the ADJCALLSTACKUP before the call.
2458 MachineBasicBlock::iterator Start = MI.getIterator();
2459 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
2460 --Start;
2461
2462 // Find the ADJCALLSTACKDOWN after the call (include it in range).
2463 MachineBasicBlock::iterator End = MI.getIterator();
2464 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
2465 ++End;
2466 ++End;
2467
2468 WFI.Start = Start;
2469 WFI.End = End;
2470 }
2471 break;
2472 }
2473 case SgprB32_M0:
2475 case SgprB64_ReadFirstLane: {
2476 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2477 if (RB == SgprRB)
2478 break;
2479 assert(RB == VgprRB);
2480 Register NewSGPR = MRI.createVirtualRegister({SgprRB, Ty});
2481 buildReadFirstLane(B, NewSGPR, Op.getReg(), RBI);
2482 Op.setReg(NewSGPR);
2483 break;
2484 }
2487 assert(Ty == getTyFromID(MethodIDs[i]));
2488 if (RB == SgprRB)
2489 break;
2490 assert(RB == VgprRB);
2491 Register NewSGPR = MRI.createVirtualRegister({SgprRB, Ty});
2492 buildReadFirstLane(B, NewSGPR, Op.getReg(), RBI);
2493 Op.setReg(NewSGPR);
2494 break;
2495 }
2496 // sgpr and vgpr scalars with extend
2497 case Sgpr32AExt: {
2498 // Note: this ext allows S1, and it is meant to be combined away.
2499 assert(Ty.getSizeInBits() < 32);
2500 assert(RB == SgprRB);
2501 auto Aext = B.buildAnyExt(SgprRB_I32, Reg);
2502 Op.setReg(Aext.getReg(0));
2503 break;
2504 }
2505 case Sgpr32AExtBoolInReg: {
2506 // Note: this ext allows S1, and it is meant to be combined away.
2507 assert(Ty.getSizeInBits() == 1);
2508 assert(RB == SgprRB);
2509 auto Aext = B.buildAnyExt(SgprRB_I32, Reg);
2510 // Zext SgprS1 is not legal, make AND with 1 instead. This instruction is
2511 // most of times meant to be combined away in AMDGPURegBankCombiner.
2512 auto Cst1 = B.buildConstant(SgprRB_I32, 1);
2513 auto BoolInReg = B.buildAnd(SgprRB_I32, Aext, Cst1);
2514 Op.setReg(BoolInReg.getReg(0));
2515 break;
2516 }
2517 case Sgpr32SExt: {
2518 assert(1 < Ty.getSizeInBits() && Ty.getSizeInBits() < 32);
2519 assert(RB == SgprRB);
2520 auto Sext = B.buildSExt(SgprRB_I32, Reg);
2521 Op.setReg(Sext.getReg(0));
2522 break;
2523 }
2524 case Sgpr32ZExt: {
2525 assert(1 < Ty.getSizeInBits() && Ty.getSizeInBits() < 32);
2526 assert(RB == SgprRB);
2527 auto Zext = B.buildZExt(SgprRB_I32, Reg);
2528 Op.setReg(Zext.getReg(0));
2529 break;
2530 }
2531 case Vgpr32AExt: {
2532 assert(Ty.getSizeInBits() < 32);
2533 assert(RB == VgprRB);
2534 auto Aext = B.buildAnyExt(VgprRB_I32, Reg);
2535 Op.setReg(Aext.getReg(0));
2536 break;
2537 }
2538 case Vgpr32SExt: {
2539 // Note this ext allows S1, and it is meant to be combined away.
2540 assert(Ty.getSizeInBits() < 32);
2541 assert(RB == VgprRB);
2542 auto Sext = B.buildSExt(VgprRB_I32, Reg);
2543 Op.setReg(Sext.getReg(0));
2544 break;
2545 }
2546 case Vgpr32ZExt: {
2547 // Note this ext allows S1, and it is meant to be combined away.
2548 assert(Ty.getSizeInBits() < 32);
2549 assert(RB == VgprRB);
2550 auto Zext = B.buildZExt(VgprRB_I32, Reg);
2551 Op.setReg(Zext.getReg(0));
2552 break;
2553 }
2554 default:
2556 MF, MORE, DEBUG_TYPE,
2557 "AMDGPU RegBankLegalize: applyMappingSrc, ID not supported", MI);
2558 return false;
2559 }
2560 }
2561 return true;
2562}
2563
2564[[maybe_unused]] static bool verifyRegBankOnOperands(MachineInstr &MI,
2565 const RegisterBank *RB,
2567 unsigned StartOpIdx,
2568 unsigned EndOpIdx) {
2569 for (unsigned i = StartOpIdx; i <= EndOpIdx; ++i) {
2570 if (MRI.getRegBankOrNull(MI.getOperand(i).getReg()) != RB)
2571 return false;
2572 }
2573 return true;
2574}
2575
2576bool RegBankLegalizeHelper::applyRegisterBanksVgprWithSgprRsrc(
2577 MachineInstr &MI, unsigned RsrcIdx) {
2578 const unsigned NumDefs = MI.getNumExplicitDefs();
2579
2580 MachineBasicBlock *MBB = MI.getParent();
2581 B.setInsertPt(*MBB, MBB->SkipPHIsAndLabels(std::next(MI.getIterator())));
2582
2583 // Defs are vgpr.
2584 for (unsigned i = 0; i < NumDefs; ++i) {
2585 Register Reg = MI.getOperand(i).getReg();
2586 if (MRI.getRegBank(Reg) == VgprRB)
2587 continue;
2588
2589 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, MRI.getType(Reg)});
2590 MI.getOperand(i).setReg(NewVgprDst);
2591 buildReadAnyLane(B, Reg, NewVgprDst, RBI);
2592 }
2593
2594 B.setInstrAndDebugLoc(MI);
2595
2596 // Register uses before RsrcIdx are vgpr.
2597 for (unsigned i = NumDefs; i < RsrcIdx; ++i) {
2598 MachineOperand &Op = MI.getOperand(i);
2599 if (!Op.isReg())
2600 continue;
2601
2602 Register Reg = Op.getReg();
2603 if (!Reg.isVirtual())
2604 continue;
2605
2606 if (MRI.getRegBank(Reg) == VgprRB)
2607 continue;
2608
2609 auto Copy = B.buildCopy({VgprRB, MRI.getType(Reg)}, Reg);
2610 Op.setReg(Copy.getReg(0));
2611 }
2612
2613 SmallSet<Register, 4> OpsToWaterfall;
2614
2615 // Register use RsrcIdx (and later register operands) is sgpr.
2616 for (unsigned i = RsrcIdx; i < MI.getNumOperands(); ++i) {
2617 MachineOperand &Op = MI.getOperand(i);
2618 if (!Op.isReg())
2619 continue;
2620
2621 Register Reg = Op.getReg();
2622 if (MRI.getRegBank(Reg) != SgprRB)
2623 OpsToWaterfall.insert(Reg);
2624 }
2625
2626 if (!OpsToWaterfall.empty()) {
2627 MachineBasicBlock::iterator MII = MI.getIterator();
2628 executeInWaterfallLoop(B, {OpsToWaterfall, MII, std::next(MII)});
2629 }
2630
2631 return true;
2632}
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isSignedBFE(MachineInstr &MI)
static bool verifyRegBankOnOperands(MachineInstr &MI, const RegisterBank *RB, MachineRegisterInfo &MRI, unsigned StartOpIdx, unsigned EndOpIdx)
This file declares the targeting of the RegisterBankInfo class for AMDGPU.
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
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...
static Register UseReg(const MachineOperand &MO)
IRTranslator LLVM IR MI
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register Reg
Register const TargetRegisterInfo * TRI
Machine IR instance of the generic uniformity analysis.
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static const LaneMaskConstants & get(const GCNSubtarget &ST)
RegBankLegalizeHelper(MachineIRBuilder &B, const MachineUniformityInfo &MUI, GISelValueTracking *VT, const RegisterBankInfo &RBI, const RegBankLegalizeRules &RBLRules)
const RegBankLLTMapping * findMappingForMI(const MachineInstr &MI, const MachineRegisterInfo &MRI, const MachineUniformityInfo &MUI) const
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:302
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ ICMP_NE
not equal
Definition InstrTypes.h:762
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:782
iterator end()
Definition DenseMap.h:702
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:843
const SIRegisterInfo * getRegisterInfo() const override
Represents a call to an intrinsic.
Register getSourceReg() const
Get the unmerge source register.
constexpr bool isScalar() const
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
LLT divide(int Factor) const
Return a type that is Factor times smaller.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT float32()
Get a 32-bit IEEE float value.
TypeSize getValue() const
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI iterator SkipPHIsAndLabels(iterator I)
Return the first instruction in MBB after I that is not a PHI or a label.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
BasicBlockListType::iterator iterator
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
Helper class to build MachineInstr.
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
LocationSize getSize() const
Return the size in bytes of the memory reference.
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const RegisterBank * getRegBank(Register Reg) const
Return the register bank of Reg.
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...
Holds all the information related to register banks.
This class implements the register bank concept.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
bool empty() const
Definition SmallSet.h:169
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
self_iterator getIterator()
Definition ilist_node.h:123
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
const uint64_t FltRoundToHWConversionTable
bool isAnyPtr(LLT Ty, unsigned Width)
uint32_t decodeFltRoundToHWConversionTable(uint32_t FltRounds)
Read the hardware rounding mode equivalent of a AMDGPUFltRounds value.
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.
void buildReadAnyLane(MachineIRBuilder &B, Register SgprDst, Register VgprSrc, const RegisterBankInfo &RBI)
const RsrcIntrinsic * lookupRsrcIntrinsic(unsigned Intr)
void buildReadFirstLane(MachineIRBuilder &B, Register SgprDst, Register VgprSrc, const RegisterBankInfo &RBI)
const uint64_t FltRoundConversionTable
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.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< MachineSSAContext > MachineUniformityInfo
@ Offset
Definition DWP.cpp:577
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
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
@ Known
Known to have no common set bits.
@ Kill
The last use of a register.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI void constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition Utils.cpp:159
@ Load
The value being inserted comes from a load (InsertElement only).
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
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
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
LLVM_ABI void reportGISelFailure(MachineFunction &MF, MachineOptimizationRemarkEmitter &MORE, MachineOptimizationRemarkMissed &R)
Report an ISel error as a missed optimization remark to the LLVMContext's diagnostic stream.
Definition Utils.cpp:261
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
constexpr T maskTrailingZeros(unsigned N)
Create a bitmask with the N right-most bits set to 0, and all other bits set to 1.
Definition MathExtras.h:95
@ Add
Sum of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
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
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
Definition Alignment.h:100
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
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
static constexpr uint64_t encode(Fields... Values)
SmallVector< RegBankLLTMappingApplyID, 2 > DstOpMapping
SmallVector< RegBankLLTMappingApplyID, 4 > SrcOpMapping
Holds waterfall loop information: the set of SGPR operand registers that need waterfalling,...
MachineBasicBlock::iterator Start
SmallSet< Register, 4 > SgprWaterfallOperandRegs