LLVM 24.0.0git
AMDGPUISelDAGToDAG.cpp
Go to the documentation of this file.
1//===-- AMDGPUISelDAGToDAG.cpp - A dag to dag inst selector for AMDGPU ----===//
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/// \file
10/// Defines an instruction selector for the AMDGPU target.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AMDGPUISelDAGToDAG.h"
15#include "AMDGPU.h"
16#include "AMDGPUInstrInfo.h"
17#include "AMDGPUSubtarget.h"
18#include "AMDGPUTargetMachine.h"
21#include "R600RegisterInfo.h"
22#include "SIISelLowering.h"
29#include "llvm/IR/IntrinsicsAMDGPU.h"
32
33#ifdef EXPENSIVE_CHECKS
35#include "llvm/IR/Dominators.h"
36#endif
37
38#define DEBUG_TYPE "amdgpu-isel"
39
40using namespace llvm;
41
42//===----------------------------------------------------------------------===//
43// Instruction Selector Implementation
44//===----------------------------------------------------------------------===//
45
46namespace {
47static SDValue stripBitcast(SDValue Val) {
48 return Val.getOpcode() == ISD::BITCAST ? Val.getOperand(0) : Val;
49}
50
51// Figure out if this is really an extract of the high 16-bits of a dword.
52static bool isExtractHiElt(SDValue In, SDValue &Out) {
53 In = stripBitcast(In);
54
55 if (In.getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
56 if (ConstantSDNode *Idx = dyn_cast<ConstantSDNode>(In.getOperand(1))) {
57 if (!Idx->isOne())
58 return false;
59 Out = In.getOperand(0);
60 return true;
61 }
62 }
63
64 if (In.getOpcode() != ISD::TRUNCATE)
65 return false;
66
67 SDValue Srl = In.getOperand(0);
68 if (Srl.getOpcode() == ISD::SRL) {
69 if (ConstantSDNode *ShiftAmt = dyn_cast<ConstantSDNode>(Srl.getOperand(1))) {
70 if (ShiftAmt->getZExtValue() == 16) {
71 Out = stripBitcast(Srl.getOperand(0));
72 return true;
73 }
74 }
75 }
76
77 return false;
78}
79
80static SDValue createVOP3PSrc32FromLo16(SDValue Lo, SDValue Src,
81 llvm::SelectionDAG *CurDAG,
82 const GCNSubtarget *Subtarget) {
83 if (!Subtarget->useRealTrue16Insts()) {
84 return Lo;
85 }
86
87 SDValue NewSrc;
88 SDLoc SL(Lo);
89
90 if (Lo->isDivergent()) {
91 SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
92 SL, Lo.getValueType()),
93 0);
94 const SDValue Ops[] = {
95 CurDAG->getTargetConstant(AMDGPU::VGPR_32RegClassID, SL, MVT::i32), Lo,
96 CurDAG->getTargetConstant(AMDGPU::lo16, SL, MVT::i16), Undef,
97 CurDAG->getTargetConstant(AMDGPU::hi16, SL, MVT::i16)};
98
99 NewSrc = SDValue(CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, SL,
100 Src.getValueType(), Ops),
101 0);
102 } else {
103 // the S_MOV is needed since the Lo could still be a VGPR16.
104 // With S_MOV, isel insert a "sgpr32 = copy vgpr16" and we reply on
105 // the fixvgpr2sgprcopy pass to legalize it
106 NewSrc = SDValue(
107 CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, Src.getValueType(), Lo),
108 0);
109 }
110
111 return NewSrc;
112}
113
114// Look through operations that obscure just looking at the low 16-bits of the
115// same register.
116static SDValue stripExtractLoElt(SDValue In) {
117 if (In.getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
118 SDValue Idx = In.getOperand(1);
119 if (isNullConstant(Idx) && In.getValueSizeInBits() <= 32)
120 return In.getOperand(0);
121 }
122
123 if (In.getOpcode() == ISD::TRUNCATE) {
124 SDValue Src = In.getOperand(0);
125 if (Src.getValueType().getSizeInBits() == 32)
126 return stripBitcast(Src);
127 }
128
129 return In;
130}
131
132static SDValue emitRegSequence(llvm::SelectionDAG &CurDAG, unsigned DstRegClass,
133 EVT DstTy, ArrayRef<SDValue> Elts,
134 ArrayRef<unsigned> SubRegClass,
135 const SDLoc &DL) {
136 assert(Elts.size() == SubRegClass.size() && "array size mismatch");
137 unsigned NumElts = Elts.size();
138 SmallVector<SDValue, 17> Ops(2 * NumElts + 1);
139 Ops[0] = (CurDAG.getTargetConstant(DstRegClass, DL, MVT::i32));
140 for (unsigned i = 0; i < NumElts; ++i) {
141 Ops[2 * i + 1] = Elts[i];
142 Ops[2 * i + 2] = CurDAG.getTargetConstant(SubRegClass[i], DL, MVT::i32);
143 }
144 return SDValue(
145 CurDAG.getMachineNode(TargetOpcode::REG_SEQUENCE, DL, DstTy, Ops), 0);
146}
147
148} // end anonymous namespace
149
151 "AMDGPU DAG->DAG Pattern Instruction Selection", false,
152 false)
153INITIALIZE_PASS_DEPENDENCY(AMDGPUPerfHintAnalysisLegacy)
155#ifdef EXPENSIVE_CHECKS
158#endif
160 "AMDGPU DAG->DAG Pattern Instruction Selection", false,
161 false)
162
163/// This pass converts a legalized DAG into a AMDGPU-specific
164// DAG, ready for instruction scheduling.
166 CodeGenOptLevel OptLevel) {
167 return new AMDGPUDAGToDAGISelLegacy(TM, OptLevel);
168}
169
173
175 Subtarget = &MF.getSubtarget<GCNSubtarget>();
176 Subtarget->checkSubtargetFeatures(MF.getFunction());
177 Mode = SIModeRegisterDefaults(MF.getFunction(), *Subtarget);
179}
180
181bool AMDGPUDAGToDAGISel::fp16SrcZerosHighBits(unsigned Opc) const {
182 // XXX - only need to list legal operations.
183 switch (Opc) {
184 case ISD::POISON:
185 return true;
186 case ISD::FADD:
187 case ISD::FSUB:
188 case ISD::FMUL:
189 case ISD::FDIV:
190 case ISD::FREM:
192 case ISD::UINT_TO_FP:
193 case ISD::SINT_TO_FP:
194 case ISD::FABS:
195 // Fabs is lowered to a bit operation, but it's an and which will clear the
196 // high bits anyway.
197 case ISD::FSQRT:
198 case ISD::FSIN:
199 case ISD::FCOS:
200 case ISD::FPOWI:
201 case ISD::FPOW:
202 case ISD::FLOG:
203 case ISD::FLOG2:
204 case ISD::FLOG10:
205 case ISD::FEXP:
206 case ISD::FEXP2:
207 case ISD::FCEIL:
208 case ISD::FTRUNC:
209 case ISD::FRINT:
210 case ISD::FNEARBYINT:
211 case ISD::FROUNDEVEN:
212 case ISD::FROUND:
213 case ISD::FFLOOR:
214 case ISD::FMINNUM:
215 case ISD::FMAXNUM:
216 case ISD::FLDEXP:
217 case AMDGPUISD::FRACT:
218 case AMDGPUISD::CLAMP:
219 case AMDGPUISD::COS_HW:
220 case AMDGPUISD::SIN_HW:
221 case AMDGPUISD::FMIN3:
222 case AMDGPUISD::FMAX3:
223 case AMDGPUISD::FMED3:
224 case AMDGPUISD::FMAD_FTZ:
225 case AMDGPUISD::RCP:
226 case AMDGPUISD::RSQ:
227 case AMDGPUISD::RCP_IFLAG:
228 // On gfx10, all 16-bit instructions preserve the high bits.
229 return Subtarget->getGeneration() <= AMDGPUSubtarget::GFX9;
230 case ISD::FP_ROUND:
231 // We may select fptrunc (fma/mad) to mad_mixlo, which does not zero the
232 // high bits on gfx9.
233 // TODO: If we had the source node we could see if the source was fma/mad
235 case ISD::FMA:
236 case ISD::FMAD:
237 case AMDGPUISD::DIV_FIXUP:
239 default:
240 // fcopysign, select and others may be lowered to 32-bit bit operations
241 // which don't zero the high bits.
242 return false;
243 }
244}
245
247#ifdef EXPENSIVE_CHECKS
249 LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
250 for (auto &L : LI->getLoopsInPreorder()) {
251 assert(L->isLCSSAForm(DT));
252 }
253#endif
255}
256
265
267 assert(Subtarget->d16PreservesUnusedBits());
268 MVT VT = N->getValueType(0).getSimpleVT();
269 if (VT != MVT::v2i16 && VT != MVT::v2f16)
270 return false;
271
272 SDValue Lo = N->getOperand(0);
273 SDValue Hi = N->getOperand(1);
274
275 LoadSDNode *LdHi = dyn_cast<LoadSDNode>(stripBitcast(Hi));
276
277 // build_vector lo, (load ptr) -> load_d16_hi ptr, lo
278 // build_vector lo, (zextload ptr from i8) -> load_d16_hi_u8 ptr, lo
279 // build_vector lo, (sextload ptr from i8) -> load_d16_hi_i8 ptr, lo
280
281 // Need to check for possible indirect dependencies on the other half of the
282 // vector to avoid introducing a cycle.
283 if (LdHi && Hi.hasOneUse() && !LdHi->isPredecessorOf(Lo.getNode())) {
284 SDVTList VTList = CurDAG->getVTList(VT, MVT::Other);
285
286 SDValue TiedIn = CurDAG->getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), VT, Lo);
287 SDValue Ops[] = {
288 LdHi->getChain(), LdHi->getBasePtr(), TiedIn
289 };
290
291 unsigned LoadOp = AMDGPUISD::LOAD_D16_HI;
292 if (LdHi->getMemoryVT() == MVT::i8) {
293 LoadOp = LdHi->getExtensionType() == ISD::SEXTLOAD ?
294 AMDGPUISD::LOAD_D16_HI_I8 : AMDGPUISD::LOAD_D16_HI_U8;
295 } else {
296 assert(LdHi->getMemoryVT() == MVT::i16);
297 }
298
299 SDValue NewLoadHi =
300 CurDAG->getMemIntrinsicNode(LoadOp, SDLoc(LdHi), VTList,
301 Ops, LdHi->getMemoryVT(),
302 LdHi->getMemOperand());
303
304 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), NewLoadHi);
305 CurDAG->ReplaceAllUsesOfValueWith(SDValue(LdHi, 1), NewLoadHi.getValue(1));
306 return true;
307 }
308
309 // build_vector (load ptr), hi -> load_d16_lo ptr, hi
310 // build_vector (zextload ptr from i8), hi -> load_d16_lo_u8 ptr, hi
311 // build_vector (sextload ptr from i8), hi -> load_d16_lo_i8 ptr, hi
312 LoadSDNode *LdLo = dyn_cast<LoadSDNode>(stripBitcast(Lo));
313 if (LdLo && Lo.hasOneUse()) {
314 SDValue TiedIn = getHi16Elt(Hi);
315 if (!TiedIn || LdLo->isPredecessorOf(TiedIn.getNode()))
316 return false;
317
318 SDVTList VTList = CurDAG->getVTList(VT, MVT::Other);
319 unsigned LoadOp = AMDGPUISD::LOAD_D16_LO;
320 if (LdLo->getMemoryVT() == MVT::i8) {
321 LoadOp = LdLo->getExtensionType() == ISD::SEXTLOAD ?
322 AMDGPUISD::LOAD_D16_LO_I8 : AMDGPUISD::LOAD_D16_LO_U8;
323 } else {
324 assert(LdLo->getMemoryVT() == MVT::i16);
325 }
326
327 TiedIn = CurDAG->getNode(ISD::BITCAST, SDLoc(N), VT, TiedIn);
328
329 SDValue Ops[] = {
330 LdLo->getChain(), LdLo->getBasePtr(), TiedIn
331 };
332
333 SDValue NewLoadLo =
334 CurDAG->getMemIntrinsicNode(LoadOp, SDLoc(LdLo), VTList,
335 Ops, LdLo->getMemoryVT(),
336 LdLo->getMemOperand());
337
338 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), NewLoadLo);
339 CurDAG->ReplaceAllUsesOfValueWith(SDValue(LdLo, 1), NewLoadLo.getValue(1));
340 return true;
341 }
342
343 return false;
344}
345
347 if (!Subtarget->d16PreservesUnusedBits())
348 return;
349
350 SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end();
351
352 bool MadeChange = false;
353 while (Position != CurDAG->allnodes_begin()) {
354 SDNode *N = &*--Position;
355 if (N->use_empty())
356 continue;
357
358 switch (N->getOpcode()) {
360 // TODO: Match load d16 from shl (extload:i16), 16
361 MadeChange |= matchLoadD16FromBuildVector(N);
362 break;
363 default:
364 break;
365 }
366 }
367
368 if (MadeChange) {
369 CurDAG->RemoveDeadNodes();
370 LLVM_DEBUG(dbgs() << "After PreProcess:\n";
371 CurDAG->dump(););
372 }
373}
374
375bool AMDGPUDAGToDAGISel::isInlineImmediate(const SDNode *N) const {
376 if (N->isUndef())
377 return true;
378
379 const SIInstrInfo *TII = Subtarget->getInstrInfo();
381 return TII->isInlineConstant(C->getAPIntValue());
382
384 return TII->isInlineConstant(C->getValueAPF());
385
386 return false;
387}
388
389/// Determine the register class for \p OpNo
390/// \returns The register class of the virtual register that will be used for
391/// the given operand number \OpNo or NULL if the register class cannot be
392/// determined.
393const TargetRegisterClass *AMDGPUDAGToDAGISel::getOperandRegClass(SDNode *N,
394 unsigned OpNo) const {
395 if (!N->isMachineOpcode()) {
396 if (N->getOpcode() == ISD::CopyToReg) {
397 Register Reg = cast<RegisterSDNode>(N->getOperand(1))->getReg();
398 if (Reg.isVirtual()) {
400 return MRI.getRegClass(Reg);
401 }
402
403 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
404 return TRI->getPhysRegBaseClass(Reg);
405 }
406
407 return nullptr;
408 }
409
410 switch (N->getMachineOpcode()) {
411 default: {
412 const SIInstrInfo *TII = Subtarget->getInstrInfo();
413 const MCInstrDesc &Desc = TII->get(N->getMachineOpcode());
414 unsigned OpIdx = Desc.getNumDefs() + OpNo;
415 if (OpIdx >= Desc.getNumOperands())
416 return nullptr;
417
418 int16_t RegClass = TII->getOpRegClassID(Desc.operands()[OpIdx]);
419 if (RegClass == -1)
420 return nullptr;
421
422 return Subtarget->getRegisterInfo()->getRegClass(RegClass);
423 }
424 case AMDGPU::REG_SEQUENCE: {
425 unsigned RCID = N->getConstantOperandVal(0);
426 const TargetRegisterClass *SuperRC =
427 Subtarget->getRegisterInfo()->getRegClass(RCID);
428
429 SDValue SubRegOp = N->getOperand(OpNo + 1);
430 unsigned SubRegIdx = SubRegOp->getAsZExtVal();
431 return Subtarget->getRegisterInfo()->getSubClassWithSubReg(SuperRC,
432 SubRegIdx);
433 }
434 }
435}
436
437SDNode *AMDGPUDAGToDAGISel::glueCopyToOp(SDNode *N, SDValue NewChain,
438 SDValue Glue) const {
440 Ops.push_back(NewChain); // Replace the chain.
441 for (unsigned i = 1, e = N->getNumOperands(); i != e; ++i)
442 Ops.push_back(N->getOperand(i));
443
444 Ops.push_back(Glue);
445 return CurDAG->MorphNodeTo(N, N->getOpcode(), N->getVTList(), Ops);
446}
447
448SDNode *AMDGPUDAGToDAGISel::glueCopyToM0(SDNode *N, SDValue Val) const {
449 const SITargetLowering& Lowering =
450 *static_cast<const SITargetLowering*>(getTargetLowering());
451
452 assert(N->getOperand(0).getValueType() == MVT::Other && "Expected chain");
453
454 SDValue M0 = Lowering.copyToM0(*CurDAG, N->getOperand(0), SDLoc(N), Val);
455 return glueCopyToOp(N, M0, M0.getValue(1));
456}
457
458SDNode *AMDGPUDAGToDAGISel::glueCopyToM0LDSInit(SDNode *N) const {
459 unsigned AS = cast<MemSDNode>(N)->getAddressSpace();
460 if (AS == AMDGPUAS::LOCAL_ADDRESS) {
461 if (Subtarget->ldsRequiresM0Init())
462 return glueCopyToM0(
463 N, CurDAG->getSignedTargetConstant(-1, SDLoc(N), MVT::i32));
464 } else if (AS == AMDGPUAS::REGION_ADDRESS) {
465 MachineFunction &MF = CurDAG->getMachineFunction();
466 unsigned Value = MF.getInfo<SIMachineFunctionInfo>()->getGDSSize();
467 return
468 glueCopyToM0(N, CurDAG->getTargetConstant(Value, SDLoc(N), MVT::i32));
469 }
470 return N;
471}
472
473MachineSDNode *AMDGPUDAGToDAGISel::buildSMovImm64(SDLoc &DL, uint64_t Imm,
474 EVT VT) const {
475 SDNode *Lo = CurDAG->getMachineNode(
476 AMDGPU::S_MOV_B32, DL, MVT::i32,
477 CurDAG->getTargetConstant(Lo_32(Imm), DL, MVT::i32));
478 SDNode *Hi = CurDAG->getMachineNode(
479 AMDGPU::S_MOV_B32, DL, MVT::i32,
480 CurDAG->getTargetConstant(Hi_32(Imm), DL, MVT::i32));
481 const SDValue Ops[] = {
482 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32),
483 SDValue(Lo, 0), CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
484 SDValue(Hi, 0), CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32)};
485
486 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, VT, Ops);
487}
488
489SDNode *AMDGPUDAGToDAGISel::packConstantV2I16(const SDNode *N,
490 SelectionDAG &DAG) const {
491 // TODO: Handle undef as zero
492
493 assert(N->getOpcode() == ISD::BUILD_VECTOR && N->getNumOperands() == 2);
494 uint32_t LHSVal, RHSVal;
495 if (getConstantValue(N->getOperand(0), LHSVal) &&
496 getConstantValue(N->getOperand(1), RHSVal)) {
497 SDLoc SL(N);
498 uint32_t K = (LHSVal & 0xffff) | (RHSVal << 16);
499 return DAG.getMachineNode(
500 isVGPRImm(N) ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32, SL,
501 N->getValueType(0), DAG.getTargetConstant(K, SL, MVT::i32));
502 }
503
504 return nullptr;
505}
506
507void AMDGPUDAGToDAGISel::SelectBuildVector(SDNode *N, unsigned RegClassID) {
508 EVT VT = N->getValueType(0);
509 unsigned NumVectorElts = VT.getVectorNumElements();
510 EVT EltVT = VT.getVectorElementType();
511 SDLoc DL(N);
512 SDValue RegClass = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32);
513
514 if (NumVectorElts == 1) {
515 CurDAG->SelectNodeTo(N, AMDGPU::COPY_TO_REGCLASS, EltVT, N->getOperand(0),
516 RegClass);
517 return;
518 }
519
520 bool IsGCN = CurDAG->getSubtarget().getTargetTriple().isAMDGCN();
521 if (IsGCN && Subtarget->has64BitLiterals() && VT.getSizeInBits() == 64 &&
522 CurDAG->isConstantValueOfAnyType(SDValue(N, 0))) {
523 uint64_t C = 0;
524 bool AllConst = true;
525 unsigned EltSize = EltVT.getSizeInBits();
526 for (unsigned I = 0; I < NumVectorElts; ++I) {
527 SDValue Op = N->getOperand(I);
528 if (Op.isUndef()) {
529 AllConst = false;
530 break;
531 }
532 uint64_t Val;
534 Val = CF->getValueAPF().bitcastToAPInt().getZExtValue();
535 } else
536 Val = cast<ConstantSDNode>(Op)->getZExtValue();
537 C |= Val << (EltSize * I);
538 }
539 if (AllConst) {
540 SDValue CV = CurDAG->getTargetConstant(C, DL, MVT::i64);
541 MachineSDNode *Copy =
542 CurDAG->getMachineNode(AMDGPU::S_MOV_B64_IMM_PSEUDO, DL, VT, CV);
543 CurDAG->SelectNodeTo(N, AMDGPU::COPY_TO_REGCLASS, VT, SDValue(Copy, 0),
544 RegClass);
545 return;
546 }
547 }
548
549 assert(NumVectorElts <= 32 && "Vectors with more than 32 elements not "
550 "supported yet");
551 // 32 = Max Num Vector Elements
552 // 2 = 2 REG_SEQUENCE operands per element (value, subreg index)
553 // 1 = Vector Register Class
554 SmallVector<SDValue, 32 * 2 + 1> RegSeqArgs(NumVectorElts * 2 + 1);
555
556 RegSeqArgs[0] = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32);
557 bool IsRegSeq = true;
558 unsigned NOps = N->getNumOperands();
559 unsigned EltSizeInRegs = EltVT.getSizeInBits() / 32;
560 assert(IsGCN || EltSizeInRegs == 1);
561 for (unsigned i = 0; i < NOps; i++) {
562 // XXX: Why is this here?
563 if (isa<RegisterSDNode>(N->getOperand(i))) {
564 IsRegSeq = false;
565 break;
566 }
567 unsigned Sub = IsGCN ? SIRegisterInfo::getSubRegFromChannel(
568 i * EltSizeInRegs, EltSizeInRegs)
570 RegSeqArgs[1 + (2 * i)] = N->getOperand(i);
571 RegSeqArgs[1 + (2 * i) + 1] = CurDAG->getTargetConstant(Sub, DL, MVT::i32);
572 }
573 if (NOps != NumVectorElts) {
574 // Fill in the missing undef elements if this was a scalar_to_vector.
575 assert(N->getOpcode() == ISD::SCALAR_TO_VECTOR && NOps < NumVectorElts);
576 MachineSDNode *ImpDef = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
577 DL, EltVT);
578 for (unsigned i = NOps; i < NumVectorElts; ++i) {
579 unsigned Sub = IsGCN ? SIRegisterInfo::getSubRegFromChannel(
580 i * EltSizeInRegs, EltSizeInRegs)
582 RegSeqArgs[1 + (2 * i)] = SDValue(ImpDef, 0);
583 RegSeqArgs[1 + (2 * i) + 1] =
584 CurDAG->getTargetConstant(Sub, DL, MVT::i32);
585 }
586 }
587
588 if (!IsRegSeq)
589 SelectCode(N);
590 CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, N->getVTList(), RegSeqArgs);
591}
592
594 EVT VT = N->getValueType(0);
595 EVT EltVT = VT.getVectorElementType();
596
597 // TODO: Handle 16-bit element vectors with even aligned masks.
598 if (!Subtarget->hasPkMovB32() || !EltVT.bitsEq(MVT::i32) ||
599 VT.getVectorNumElements() != 2) {
600 SelectCode(N);
601 return;
602 }
603
604 auto *SVN = cast<ShuffleVectorSDNode>(N);
605
606 SDValue Src0 = SVN->getOperand(0);
607 SDValue Src1 = SVN->getOperand(1);
608 ArrayRef<int> Mask = SVN->getMask();
609 SDLoc DL(N);
610
611 assert(Src0.getValueType().getVectorNumElements() == 2 && Mask.size() == 2 &&
612 Mask[0] < 4 && Mask[1] < 4);
613
614 SDValue VSrc0 = Mask[0] < 2 ? Src0 : Src1;
615 SDValue VSrc1 = Mask[1] < 2 ? Src0 : Src1;
616 unsigned Src0SubReg = Mask[0] & 1 ? AMDGPU::sub1 : AMDGPU::sub0;
617 unsigned Src1SubReg = Mask[1] & 1 ? AMDGPU::sub1 : AMDGPU::sub0;
618
619 if (Mask[0] < 0) {
620 Src0SubReg = Src1SubReg;
621 MachineSDNode *ImpDef =
622 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, VT);
623 VSrc0 = SDValue(ImpDef, 0);
624 }
625
626 if (Mask[1] < 0) {
627 Src1SubReg = Src0SubReg;
628 MachineSDNode *ImpDef =
629 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, VT);
630 VSrc1 = SDValue(ImpDef, 0);
631 }
632
633 // SGPR case needs to lower to copies.
634 //
635 // Also use subregister extract when we can directly blend the registers with
636 // a simple subregister copy.
637 //
638 // TODO: Maybe we should fold this out earlier
639 if (N->isDivergent() && Src0SubReg == AMDGPU::sub1 &&
640 Src1SubReg == AMDGPU::sub0) {
641 // The low element of the result always comes from src0.
642 // The high element of the result always comes from src1.
643 // op_sel selects the high half of src0.
644 // op_sel_hi selects the high half of src1.
645
646 unsigned Src0OpSel =
647 Src0SubReg == AMDGPU::sub1 ? SISrcMods::OP_SEL_0 : SISrcMods::NONE;
648 unsigned Src1OpSel =
649 Src1SubReg == AMDGPU::sub1 ? SISrcMods::OP_SEL_0 : SISrcMods::NONE;
650
651 // Enable op_sel_hi to avoid printing it. This should have no effect on the
652 // result.
653 Src0OpSel |= SISrcMods::OP_SEL_1;
654 Src1OpSel |= SISrcMods::OP_SEL_1;
655
656 SDValue Src0OpSelVal = CurDAG->getTargetConstant(Src0OpSel, DL, MVT::i32);
657 SDValue Src1OpSelVal = CurDAG->getTargetConstant(Src1OpSel, DL, MVT::i32);
658 SDValue ZeroMods = CurDAG->getTargetConstant(0, DL, MVT::i32);
659
660 CurDAG->SelectNodeTo(N, AMDGPU::V_PK_MOV_B32, N->getVTList(),
661 {Src0OpSelVal, VSrc0, Src1OpSelVal, VSrc1,
662 ZeroMods, // clamp
663 ZeroMods, // op_sel
664 ZeroMods, // op_sel_hi
665 ZeroMods, // neg_lo
666 ZeroMods}); // neg_hi
667 return;
668 }
669
670 SDValue ResultElt0 =
671 CurDAG->getTargetExtractSubreg(Src0SubReg, DL, EltVT, VSrc0);
672 SDValue ResultElt1 =
673 CurDAG->getTargetExtractSubreg(Src1SubReg, DL, EltVT, VSrc1);
674
675 const SDValue Ops[] = {
676 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32),
677 ResultElt0, CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
678 ResultElt1, CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32)};
679 CurDAG->SelectNodeTo(N, TargetOpcode::REG_SEQUENCE, VT, Ops);
680}
681
683 unsigned int Opc = N->getOpcode();
684 if (N->isMachineOpcode()) {
685 N->setNodeId(-1);
686 return; // Already selected.
687 }
688
689 // isa<MemSDNode> almost works but is slightly too permissive for some DS
690 // intrinsics.
691 if (Opc == ISD::LOAD || Opc == ISD::STORE || isa<AtomicSDNode>(N)) {
692 N = glueCopyToM0LDSInit(N);
693 SelectCode(N);
694 return;
695 }
696
697 switch (Opc) {
698 default:
699 break;
700 case ISD::UADDO_CARRY:
701 case ISD::USUBO_CARRY:
702 if (N->getValueType(0) == MVT::i64) {
703 SelectAddcSubbI64(N);
704 return;
705 }
706
707 if (N->getValueType(0) != MVT::i32)
708 break;
709
710 SelectAddcSubb(N);
711 return;
712 case ISD::UADDO:
713 case ISD::USUBO: {
714 if (N->getValueType(0) == MVT::i64) {
715 SelectAddcSubbI64(N);
716 return;
717 }
718
719 SelectUADDO_USUBO(N);
720 return;
721 }
722 case AMDGPUISD::FMUL_W_CHAIN: {
723 SelectFMUL_W_CHAIN(N);
724 return;
725 }
726 case AMDGPUISD::FMA_W_CHAIN: {
727 SelectFMA_W_CHAIN(N);
728 return;
729 }
730
732 case ISD::BUILD_VECTOR: {
733 EVT VT = N->getValueType(0);
734 unsigned NumVectorElts = VT.getVectorNumElements();
735 if (VT.getScalarSizeInBits() == 16) {
736 if (Opc == ISD::BUILD_VECTOR && NumVectorElts == 2) {
737 if (SDNode *Packed = packConstantV2I16(N, *CurDAG)) {
738 ReplaceNode(N, Packed);
739 return;
740 }
741 }
742
743 break;
744 }
745
746 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
747 EVT EltTy = VT.getVectorElementType();
748 assert(EltTy.bitsEq(MVT::i32) || EltTy.bitsEq(MVT::i64));
749 unsigned VecInBits = NumVectorElts * EltTy.getScalarSizeInBits();
750 const TargetRegisterClass *RegClass =
751 N->isDivergent() ? TRI->getDefaultVectorSuperClassForBitWidth(VecInBits)
753
754 SelectBuildVector(N, RegClass->getID());
755 return;
756 }
759 return;
760 case ISD::BUILD_PAIR: {
761 SDValue RC, SubReg0, SubReg1;
762 SDLoc DL(N);
763 if (N->getValueType(0) == MVT::i128) {
764 RC = CurDAG->getTargetConstant(AMDGPU::SGPR_128RegClassID, DL, MVT::i32);
765 SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32);
766 SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32);
767 } else if (N->getValueType(0) == MVT::i64) {
768 RC = CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32);
769 SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32);
770 SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32);
771 } else {
772 llvm_unreachable("Unhandled value type for BUILD_PAIR");
773 }
774 const SDValue Ops[] = { RC, N->getOperand(0), SubReg0,
775 N->getOperand(1), SubReg1 };
776 ReplaceNode(N, CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
777 N->getValueType(0), Ops));
778 return;
779 }
780
781 case ISD::Constant:
782 case ISD::ConstantFP: {
783 if (N->getValueType(0).getSizeInBits() != 64 || isInlineImmediate(N) ||
784 Subtarget->has64BitLiterals())
785 break;
786
787 uint64_t Imm;
789 Imm = FP->getValueAPF().bitcastToAPInt().getZExtValue();
790 if (AMDGPU::isValid32BitLiteral(Imm, true))
791 break;
792 } else {
794 Imm = C->getZExtValue();
795 if (AMDGPU::isValid32BitLiteral(Imm, false))
796 break;
797 }
798
799 SDLoc DL(N);
800 ReplaceNode(N, buildSMovImm64(DL, Imm, N->getValueType(0)));
801 return;
802 }
803 case AMDGPUISD::BFE_I32:
804 case AMDGPUISD::BFE_U32: {
805 // There is a scalar version available, but unlike the vector version which
806 // has a separate operand for the offset and width, the scalar version packs
807 // the width and offset into a single operand. Try to move to the scalar
808 // version if the offsets are constant, so that we can try to keep extended
809 // loads of kernel arguments in SGPRs.
810
811 // TODO: Technically we could try to pattern match scalar bitshifts of
812 // dynamic values, but it's probably not useful.
814 if (!Offset)
815 break;
816
817 ConstantSDNode *Width = dyn_cast<ConstantSDNode>(N->getOperand(2));
818 if (!Width)
819 break;
820
821 bool Signed = Opc == AMDGPUISD::BFE_I32;
822
823 uint32_t OffsetVal = Offset->getZExtValue();
824 uint32_t WidthVal = Width->getZExtValue();
825
826 ReplaceNode(N, getBFE32(Signed, SDLoc(N), N->getOperand(0), OffsetVal,
827 WidthVal));
828 return;
829 }
830 case AMDGPUISD::DIV_SCALE: {
831 SelectDIV_SCALE(N);
832 return;
833 }
836 SelectMAD_64_32(N);
837 return;
838 }
839 case ISD::SMUL_LOHI:
840 case ISD::UMUL_LOHI:
841 return SelectMUL_LOHI(N);
842 case ISD::CopyToReg: {
844 *static_cast<const SITargetLowering*>(getTargetLowering());
845 N = Lowering.legalizeTargetIndependentNode(N, *CurDAG);
846 break;
847 }
848 case ISD::AND:
849 case ISD::SRL:
850 case ISD::SRA:
852 if (N->getValueType(0) != MVT::i32)
853 break;
854
855 SelectS_BFE(N);
856 return;
857 case ISD::BRCOND:
858 SelectBRCOND(N);
859 return;
860 case ISD::FP_EXTEND:
861 SelectFP_EXTEND(N);
862 return;
863 case AMDGPUISD::CVT_PKRTZ_F16_F32:
864 case AMDGPUISD::CVT_PKNORM_I16_F32:
865 case AMDGPUISD::CVT_PKNORM_U16_F32:
866 case AMDGPUISD::CVT_PK_U16_U32:
867 case AMDGPUISD::CVT_PK_I16_I32: {
868 // Hack around using a legal type if f16 is illegal.
869 if (N->getValueType(0) == MVT::i32) {
870 MVT NewVT = Opc == AMDGPUISD::CVT_PKRTZ_F16_F32 ? MVT::v2f16 : MVT::v2i16;
871 N = CurDAG->MorphNodeTo(N, N->getOpcode(), CurDAG->getVTList(NewVT),
872 { N->getOperand(0), N->getOperand(1) });
873 SelectCode(N);
874 return;
875 }
876
877 break;
878 }
880 SelectINTRINSIC_W_CHAIN(N);
881 return;
882 }
884 SelectINTRINSIC_WO_CHAIN(N);
885 return;
886 }
887 case ISD::INTRINSIC_VOID: {
888 SelectINTRINSIC_VOID(N);
889 return;
890 }
892 SelectWAVE_ADDRESS(N);
893 return;
894 }
895 case ISD::STACKRESTORE: {
896 SelectSTACKRESTORE(N);
897 return;
898 }
899 }
900
901 SelectCode(N);
902}
903
905 if (!Subtarget->hasSDWA())
906 return false;
907
908 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) {
909 EVT VT = cast<VTSDNode>(N->getOperand(1))->getVT();
910 return VT.getScalarSizeInBits() == 8 || VT.getScalarSizeInBits() == 16;
911 }
912
913 if (N->getOpcode() == ISD::AND)
914 if (auto *RHS = dyn_cast<ConstantSDNode>(N->getOperand(1)))
915 return RHS->getZExtValue() == 0xFF || RHS->getZExtValue() == 0xFFFF;
916
917 if (N->getOpcode() == ISD::SRA || N->getOpcode() == ISD::SRL)
918 if (auto *RHS = dyn_cast<ConstantSDNode>(N->getOperand(1)))
919 return (RHS->getZExtValue() % 8) == 0;
920
921 return false;
922}
923
924bool AMDGPUDAGToDAGISel::isUniformBr(const SDNode *N) const {
925 const BasicBlock *BB = FuncInfo->MBB->getBasicBlock();
926 const Instruction *Term = BB->getTerminator();
927 return Term->getMetadata("amdgpu.uniform") ||
928 Term->getMetadata("structurizecfg.uniform");
929}
930
931bool AMDGPUDAGToDAGISel::isUnneededShiftMask(const SDNode *N,
932 unsigned ShAmtBits) const {
933 assert(N->getOpcode() == ISD::AND);
934
935 const APInt &RHS = N->getConstantOperandAPInt(1);
936 if (RHS.countr_one() >= ShAmtBits)
937 return true;
938
939 const APInt &LHSKnownZeros = CurDAG->computeKnownBits(N->getOperand(0)).Zero;
940 return (LHSKnownZeros | RHS).countr_one() >= ShAmtBits;
941}
942
944 SDValue &N0, SDValue &N1) {
945 if (Addr.getValueType() == MVT::i64 && Addr.getOpcode() == ISD::BITCAST &&
947 // As we split 64-bit `or` earlier, it's complicated pattern to match, i.e.
948 // (i64 (bitcast (v2i32 (build_vector
949 // (or (extract_vector_elt V, 0), OFFSET),
950 // (extract_vector_elt V, 1)))))
951 SDValue Lo = Addr.getOperand(0).getOperand(0);
952 if (Lo.getOpcode() == ISD::OR && DAG.isBaseWithConstantOffset(Lo)) {
953 SDValue BaseLo = Lo.getOperand(0);
954 SDValue BaseHi = Addr.getOperand(0).getOperand(1);
955 // Check that split base (Lo and Hi) are extracted from the same one.
956 if (BaseLo.getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
958 BaseLo.getOperand(0) == BaseHi.getOperand(0) &&
959 // Lo is statically extracted from index 0.
960 isa<ConstantSDNode>(BaseLo.getOperand(1)) &&
961 BaseLo.getConstantOperandVal(1) == 0 &&
962 // Hi is statically extracted from index 0.
963 isa<ConstantSDNode>(BaseHi.getOperand(1)) &&
964 BaseHi.getConstantOperandVal(1) == 1) {
965 N0 = BaseLo.getOperand(0).getOperand(0);
966 N1 = Lo.getOperand(1);
967 return true;
968 }
969 }
970 }
971 return false;
972}
973
974bool AMDGPUDAGToDAGISel::isBaseWithConstantOffset64(SDValue Addr, SDValue &LHS,
975 SDValue &RHS) const {
976 if (CurDAG->isBaseWithConstantOffset(Addr)) {
977 LHS = Addr.getOperand(0);
978 RHS = Addr.getOperand(1);
979 return true;
980 }
981
984 return true;
985 }
986
987 return false;
988}
989
991 return "AMDGPU DAG->DAG Pattern Instruction Selection";
992}
993
997
1002 .getManager();
1003 auto &F = MF.getFunction();
1004 // UniformityInfoAnalysis is optional in generic dag isel,
1005 // AMDGPUISelDAGToDAGPass requires it, calculate it explicitly.
1006 FAM.getResult<UniformityInfoAnalysis>(F);
1007#ifdef EXPENSIVE_CHECKS
1008 DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
1009 LoopInfo &LI = FAM.getResult<LoopAnalysis>(F);
1010 for (auto &L : LI.getLoopsInPreorder())
1011 assert(L->isLCSSAForm(DT) && "Loop is not in LCSSA form!");
1012#endif
1013 return SelectionDAGISelPass::run(MF, MFAM);
1014}
1015
1016//===----------------------------------------------------------------------===//
1017// Complex Patterns
1018//===----------------------------------------------------------------------===//
1019
1020bool AMDGPUDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base,
1021 SDValue &Offset) {
1022 return false;
1023}
1024
1025bool AMDGPUDAGToDAGISel::SelectADDRIndirect(SDValue Addr, SDValue &Base,
1026 SDValue &Offset) {
1028 SDLoc DL(Addr);
1029
1030 if ((C = dyn_cast<ConstantSDNode>(Addr))) {
1031 Base = CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32);
1032 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);
1033 } else if ((Addr.getOpcode() == AMDGPUISD::DWORDADDR) &&
1034 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(0)))) {
1035 Base = CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32);
1036 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);
1037 } else if ((Addr.getOpcode() == ISD::ADD || Addr.getOpcode() == ISD::OR) &&
1038 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) {
1039 Base = Addr.getOperand(0);
1040 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);
1041 } else {
1042 Base = Addr;
1043 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
1044 }
1045
1046 return true;
1047}
1048
1049SDValue AMDGPUDAGToDAGISel::getMaterializedScalarImm32(int64_t Val,
1050 const SDLoc &DL) const {
1051 SDNode *Mov = CurDAG->getMachineNode(
1052 AMDGPU::S_MOV_B32, DL, MVT::i32,
1053 CurDAG->getTargetConstant(Val, DL, MVT::i32));
1054 return SDValue(Mov, 0);
1055}
1056
1057void AMDGPUDAGToDAGISel::SelectAddcSubb(SDNode *N) {
1058 SDValue LHS = N->getOperand(0);
1059 SDValue RHS = N->getOperand(1);
1060 SDValue CI = N->getOperand(2);
1061
1062 if (N->isDivergent()) {
1063 unsigned Opc = N->getOpcode() == ISD::UADDO_CARRY ? AMDGPU::V_ADDC_U32_e64
1064 : AMDGPU::V_SUBB_U32_e64;
1065 CurDAG->SelectNodeTo(
1066 N, Opc, N->getVTList(),
1067 {LHS, RHS, CI,
1068 CurDAG->getTargetConstant(0, {}, MVT::i1) /*clamp bit*/});
1069 } else {
1070 unsigned Opc = N->getOpcode() == ISD::UADDO_CARRY ? AMDGPU::S_ADD_CO_PSEUDO
1071 : AMDGPU::S_SUB_CO_PSEUDO;
1072 CurDAG->SelectNodeTo(N, Opc, N->getVTList(), {LHS, RHS, CI});
1073 }
1074}
1075
1076void AMDGPUDAGToDAGISel::SelectAddcSubbI64(SDNode *N) {
1077 SDLoc DL(N);
1078 SDValue LHS = N->getOperand(0);
1079 SDValue RHS = N->getOperand(1);
1080
1081 unsigned Opcode = N->getOpcode();
1082 bool ConsumeCarry = Opcode == ISD::UADDO_CARRY || Opcode == ISD::USUBO_CARRY;
1083 bool IsAdd = Opcode == ISD::UADDO || Opcode == ISD::UADDO_CARRY;
1084
1085 SDValue Sub0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32);
1086 SDValue Sub1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32);
1087
1088 SDNode *Lo0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL,
1089 MVT::i32, LHS, Sub0);
1090 SDNode *Hi0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL,
1091 MVT::i32, LHS, Sub1);
1092
1093 SDNode *Lo1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL,
1094 MVT::i32, RHS, Sub0);
1095 SDNode *Hi1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL,
1096 MVT::i32, RHS, Sub1);
1097
1098 SDVTList VTList = CurDAG->getVTList(MVT::i32, N->getValueType(1));
1099
1100 static const unsigned NoCarryOpcMap[2][2] = {
1101 {AMDGPU::S_USUBO_PSEUDO, AMDGPU::S_UADDO_PSEUDO},
1102 {AMDGPU::V_SUB_CO_U32_e64, AMDGPU::V_ADD_CO_U32_e64}};
1103 static const unsigned CarryOpcMap[2][2] = {
1104 {AMDGPU::S_SUB_CO_PSEUDO, AMDGPU::S_ADD_CO_PSEUDO},
1105 {AMDGPU::V_SUBB_U32_e64, AMDGPU::V_ADDC_U32_e64}};
1106
1107 bool IsVALU = N->isDivergent();
1108
1109 unsigned NoCarryOpc = NoCarryOpcMap[IsVALU][IsAdd];
1110 unsigned CarryOpc = CarryOpcMap[IsVALU][IsAdd];
1111 SDValue Clamp = CurDAG->getTargetConstant(0, DL, MVT::i1);
1112
1113 SDNode *AddLo;
1114 if (!ConsumeCarry) {
1115 if (IsVALU) {
1116 SDValue Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0), Clamp};
1117 AddLo = CurDAG->getMachineNode(NoCarryOpc, DL, VTList, Args);
1118 } else {
1119 SDValue Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0)};
1120 AddLo = CurDAG->getMachineNode(NoCarryOpc, DL, VTList, Args);
1121 }
1122 } else {
1123 if (IsVALU) {
1124 SDValue Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0), N->getOperand(2),
1125 Clamp};
1126 AddLo = CurDAG->getMachineNode(CarryOpc, DL, VTList, Args);
1127 } else {
1128 SDValue Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0), N->getOperand(2)};
1129 AddLo = CurDAG->getMachineNode(CarryOpc, DL, VTList, Args);
1130 }
1131 }
1132
1133 SDNode *AddHi;
1134 if (IsVALU) {
1135 SDValue Args[] = {SDValue(Hi0, 0), SDValue(Hi1, 0), SDValue(AddLo, 1),
1136 Clamp};
1137 AddHi = CurDAG->getMachineNode(CarryOpc, DL, VTList, Args);
1138 } else {
1139 SDValue Args[] = {SDValue(Hi0, 0), SDValue(Hi1, 0), SDValue(AddLo, 1)};
1140 AddHi = CurDAG->getMachineNode(CarryOpc, DL, VTList, Args);
1141 }
1142
1143 unsigned RC = IsVALU ? AMDGPU::VReg_64RegClassID : AMDGPU::SReg_64RegClassID;
1144 SDValue RegSequenceArgs[] = {CurDAG->getTargetConstant(RC, DL, MVT::i32),
1145 SDValue(AddLo, 0), Sub0, SDValue(AddHi, 0),
1146 Sub1};
1147 SDNode *RegSequence = CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, DL,
1148 MVT::i64, RegSequenceArgs);
1149
1150 ReplaceUses(SDValue(N, 1), SDValue(AddHi, 1));
1151 ReplaceNode(N, RegSequence);
1152}
1153
1154void AMDGPUDAGToDAGISel::SelectUADDO_USUBO(SDNode *N) {
1155 // The name of the opcodes are misleading. v_add_i32/v_sub_i32 have unsigned
1156 // carry out despite the _i32 name. These were renamed in VI to _U32.
1157 // FIXME: We should probably rename the opcodes here.
1158 bool IsAdd = N->getOpcode() == ISD::UADDO;
1159 bool IsVALU = N->isDivergent();
1160
1161 for (SDNode::user_iterator UI = N->user_begin(), E = N->user_end(); UI != E;
1162 ++UI)
1163 if (UI.getUse().getResNo() == 1) {
1164 if (UI->isMachineOpcode()) {
1165 if (UI->getMachineOpcode() !=
1166 (IsAdd ? AMDGPU::S_ADD_CO_PSEUDO : AMDGPU::S_SUB_CO_PSEUDO)) {
1167 IsVALU = true;
1168 break;
1169 }
1170 } else {
1171 if (UI->getOpcode() != (IsAdd ? ISD::UADDO_CARRY : ISD::USUBO_CARRY)) {
1172 IsVALU = true;
1173 break;
1174 }
1175 }
1176 }
1177
1178 if (IsVALU) {
1179 unsigned Opc = IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
1180
1181 CurDAG->SelectNodeTo(
1182 N, Opc, N->getVTList(),
1183 {N->getOperand(0), N->getOperand(1),
1184 CurDAG->getTargetConstant(0, {}, MVT::i1) /*clamp bit*/});
1185 } else {
1186 unsigned Opc = IsAdd ? AMDGPU::S_UADDO_PSEUDO : AMDGPU::S_USUBO_PSEUDO;
1187
1188 CurDAG->SelectNodeTo(N, Opc, N->getVTList(),
1189 {N->getOperand(0), N->getOperand(1)});
1190 }
1191}
1192
1193void AMDGPUDAGToDAGISel::SelectFMA_W_CHAIN(SDNode *N) {
1194 // src0_modifiers, src0, src1_modifiers, src1, src2_modifiers, src2, clamp, omod
1195 SDValue Ops[10];
1196
1197 SelectVOP3Mods0(N->getOperand(1), Ops[1], Ops[0], Ops[6], Ops[7]);
1198 SelectVOP3Mods(N->getOperand(2), Ops[3], Ops[2]);
1199 SelectVOP3Mods(N->getOperand(3), Ops[5], Ops[4]);
1200 Ops[8] = N->getOperand(0);
1201 Ops[9] = N->getOperand(4);
1202
1203 // If there are no source modifiers, prefer fmac over fma because it can use
1204 // the smaller VOP2 encoding.
1205 bool UseFMAC = Subtarget->hasDLInsts() &&
1206 cast<ConstantSDNode>(Ops[0])->isZero() &&
1207 cast<ConstantSDNode>(Ops[2])->isZero() &&
1208 cast<ConstantSDNode>(Ops[4])->isZero();
1209 unsigned Opcode = UseFMAC ? AMDGPU::V_FMAC_F32_e64 : AMDGPU::V_FMA_F32_e64;
1210 CurDAG->SelectNodeTo(N, Opcode, N->getVTList(), Ops);
1211}
1212
1213void AMDGPUDAGToDAGISel::SelectFMUL_W_CHAIN(SDNode *N) {
1214 // src0_modifiers, src0, src1_modifiers, src1, clamp, omod
1215 SDValue Ops[8];
1216
1217 SelectVOP3Mods0(N->getOperand(1), Ops[1], Ops[0], Ops[4], Ops[5]);
1218 SelectVOP3Mods(N->getOperand(2), Ops[3], Ops[2]);
1219 Ops[6] = N->getOperand(0);
1220 Ops[7] = N->getOperand(3);
1221
1222 CurDAG->SelectNodeTo(N, AMDGPU::V_MUL_F32_e64, N->getVTList(), Ops);
1223}
1224
1225// We need to handle this here because tablegen doesn't support matching
1226// instructions with multiple outputs.
1227void AMDGPUDAGToDAGISel::SelectDIV_SCALE(SDNode *N) {
1228 EVT VT = N->getValueType(0);
1229
1230 assert(VT == MVT::f32 || VT == MVT::f64);
1231
1232 unsigned Opc
1233 = (VT == MVT::f64) ? AMDGPU::V_DIV_SCALE_F64_e64 : AMDGPU::V_DIV_SCALE_F32_e64;
1234
1235 // src0_modifiers, src0, src1_modifiers, src1, src2_modifiers, src2, clamp,
1236 // omod
1237 SDValue Ops[8];
1238 SelectVOP3BMods0(N->getOperand(0), Ops[1], Ops[0], Ops[6], Ops[7]);
1239 SelectVOP3BMods(N->getOperand(1), Ops[3], Ops[2]);
1240 SelectVOP3BMods(N->getOperand(2), Ops[5], Ops[4]);
1241 CurDAG->SelectNodeTo(N, Opc, N->getVTList(), Ops);
1242}
1243
1244// We need to handle this here because tablegen doesn't support matching
1245// instructions with multiple outputs.
1246void AMDGPUDAGToDAGISel::SelectMAD_64_32(SDNode *N) {
1247 SDLoc SL(N);
1248 bool Signed = N->getOpcode() == AMDGPUISD::MAD_I64_I32;
1249 unsigned Opc;
1250 bool UseNoCarry = Subtarget->hasMadNC64_32Insts() && !N->hasAnyUseOfValue(1);
1251 if (Subtarget->hasMADIntraFwdBug())
1252 Opc = Signed ? AMDGPU::V_MAD_I64_I32_gfx11_e64
1253 : AMDGPU::V_MAD_U64_U32_gfx11_e64;
1254 else if (UseNoCarry)
1255 Opc = Signed ? AMDGPU::V_MAD_NC_I64_I32_e64 : AMDGPU::V_MAD_NC_U64_U32_e64;
1256 else
1257 Opc = Signed ? AMDGPU::V_MAD_I64_I32_e64 : AMDGPU::V_MAD_U64_U32_e64;
1258
1259 SDValue Clamp = CurDAG->getTargetConstant(0, SL, MVT::i1);
1260 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2),
1261 Clamp };
1262
1263 if (UseNoCarry) {
1264 MachineSDNode *Mad = CurDAG->getMachineNode(Opc, SL, MVT::i64, Ops);
1265 ReplaceUses(SDValue(N, 0), SDValue(Mad, 0));
1266 CurDAG->RemoveDeadNode(N);
1267 return;
1268 }
1269
1270 CurDAG->SelectNodeTo(N, Opc, N->getVTList(), Ops);
1271}
1272
1273// We need to handle this here because tablegen doesn't support matching
1274// instructions with multiple outputs.
1275void AMDGPUDAGToDAGISel::SelectMUL_LOHI(SDNode *N) {
1276 SDLoc SL(N);
1277 bool Signed = N->getOpcode() == ISD::SMUL_LOHI;
1278 SDVTList VTList;
1279 unsigned Opc;
1280 if (Subtarget->hasMadNC64_32Insts()) {
1281 VTList = CurDAG->getVTList(MVT::i64);
1282 Opc = Signed ? AMDGPU::V_MAD_NC_I64_I32_e64 : AMDGPU::V_MAD_NC_U64_U32_e64;
1283 } else {
1284 VTList = CurDAG->getVTList(MVT::i64, MVT::i1);
1285 if (Subtarget->hasMADIntraFwdBug()) {
1286 Opc = Signed ? AMDGPU::V_MAD_I64_I32_gfx11_e64
1287 : AMDGPU::V_MAD_U64_U32_gfx11_e64;
1288 } else {
1289 Opc = Signed ? AMDGPU::V_MAD_I64_I32_e64 : AMDGPU::V_MAD_U64_U32_e64;
1290 }
1291 }
1292
1293 SDValue Zero = CurDAG->getTargetConstant(0, SL, MVT::i64);
1294 SDValue Clamp = CurDAG->getTargetConstant(0, SL, MVT::i1);
1295 SDValue Ops[] = {N->getOperand(0), N->getOperand(1), Zero, Clamp};
1296 SDNode *Mad = CurDAG->getMachineNode(Opc, SL, VTList, Ops);
1297 if (!SDValue(N, 0).use_empty()) {
1298 SDValue Sub0 = CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32);
1299 SDNode *Lo = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, SL,
1300 MVT::i32, SDValue(Mad, 0), Sub0);
1301 ReplaceUses(SDValue(N, 0), SDValue(Lo, 0));
1302 }
1303 if (!SDValue(N, 1).use_empty()) {
1304 SDValue Sub1 = CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32);
1305 SDNode *Hi = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, SL,
1306 MVT::i32, SDValue(Mad, 0), Sub1);
1307 ReplaceUses(SDValue(N, 1), SDValue(Hi, 0));
1308 }
1309 CurDAG->RemoveDeadNode(N);
1310}
1311
1312bool AMDGPUDAGToDAGISel::isDSOffsetLegal(SDValue Base, unsigned Offset) const {
1313 if (!isUInt<16>(Offset))
1314 return false;
1315
1316 if (!Base || Subtarget->hasUsableDSOffset() ||
1317 Subtarget->unsafeDSOffsetFoldingEnabled())
1318 return true;
1319
1320 // On Southern Islands instruction with a negative base value and an offset
1321 // don't seem to work.
1322 return CurDAG->SignBitIsZero(Base);
1323}
1324
1325bool AMDGPUDAGToDAGISel::SelectDS1Addr1Offset(SDValue Addr, SDValue &Base,
1326 SDValue &Offset) const {
1327 SDLoc DL(Addr);
1328 if (CurDAG->isBaseWithConstantOffset(Addr)) {
1329 SDValue N0 = Addr.getOperand(0);
1330 SDValue N1 = Addr.getOperand(1);
1331 ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
1332 if (isDSOffsetLegal(N0, C1->getSExtValue())) {
1333 // (add n0, c0)
1334 Base = N0;
1335 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16);
1336 return true;
1337 }
1338 } else if (Addr.getOpcode() == ISD::SUB) {
1339 // sub C, x -> add (sub 0, x), C
1340 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Addr.getOperand(0))) {
1341 int64_t ByteOffset = C->getSExtValue();
1342 if (isDSOffsetLegal(SDValue(), ByteOffset)) {
1343 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
1344
1345 // XXX - This is kind of hacky. Create a dummy sub node so we can check
1346 // the known bits in isDSOffsetLegal. We need to emit the selected node
1347 // here, so this is thrown away.
1348 SDValue Sub = CurDAG->getNode(ISD::SUB, DL, MVT::i32,
1349 Zero, Addr.getOperand(1));
1350
1351 if (isDSOffsetLegal(Sub, ByteOffset)) {
1353 Opnds.push_back(Zero);
1354 Opnds.push_back(Addr.getOperand(1));
1355
1356 // FIXME: Select to VOP3 version for with-carry.
1357 unsigned SubOp = AMDGPU::V_SUB_CO_U32_e32;
1358 if (Subtarget->hasAddNoCarryInsts()) {
1359 SubOp = AMDGPU::V_SUB_U32_e64;
1360 Opnds.push_back(
1361 CurDAG->getTargetConstant(0, {}, MVT::i1)); // clamp bit
1362 }
1363
1364 MachineSDNode *MachineSub =
1365 CurDAG->getMachineNode(SubOp, DL, MVT::i32, Opnds);
1366
1367 Base = SDValue(MachineSub, 0);
1368 Offset = CurDAG->getTargetConstant(ByteOffset, DL, MVT::i16);
1369 return true;
1370 }
1371 }
1372 }
1373 } else if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) {
1374 // If we have a constant address, prefer to put the constant into the
1375 // offset. This can save moves to load the constant address since multiple
1376 // operations can share the zero base address register, and enables merging
1377 // into read2 / write2 instructions.
1378
1379 SDLoc DL(Addr);
1380
1381 if (isDSOffsetLegal(SDValue(), CAddr->getZExtValue())) {
1382 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
1383 MachineSDNode *MovZero = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
1384 DL, MVT::i32, Zero);
1385 Base = SDValue(MovZero, 0);
1386 Offset = CurDAG->getTargetConstant(CAddr->getZExtValue(), DL, MVT::i16);
1387 return true;
1388 }
1389 }
1390
1391 // default case
1392 Base = Addr;
1393 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i16);
1394 return true;
1395}
1396
1397bool AMDGPUDAGToDAGISel::isDSOffset2Legal(SDValue Base, unsigned Offset0,
1398 unsigned Offset1,
1399 unsigned Size) const {
1400 if (Offset0 % Size != 0 || Offset1 % Size != 0)
1401 return false;
1402 if (!isUInt<8>(Offset0 / Size) || !isUInt<8>(Offset1 / Size))
1403 return false;
1404
1405 if (!Base || Subtarget->hasUsableDSOffset() ||
1406 Subtarget->unsafeDSOffsetFoldingEnabled())
1407 return true;
1408
1409 // On Southern Islands instruction with a negative base value and an offset
1410 // don't seem to work.
1411 return CurDAG->SignBitIsZero(Base);
1412}
1413
1414// Return whether the operation has NoUnsignedWrap property.
1415static bool isNoUnsignedWrap(SDValue Addr) {
1416 return (Addr.getOpcode() == ISD::ADD &&
1417 Addr->getFlags().hasNoUnsignedWrap()) ||
1418 Addr->getOpcode() == ISD::OR;
1419}
1420
1421// Check that the base address of flat scratch load/store in the form of `base +
1422// offset` is legal to be put in SGPR/VGPR (i.e. unsigned per hardware
1423// requirement). We always treat the first operand as the base address here.
1424bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegal(SDValue Addr) const {
1425 if (isNoUnsignedWrap(Addr))
1426 return true;
1427
1428 // Starting with GFX12, VADDR and SADDR fields in VSCRATCH can use negative
1429 // values.
1430 if (Subtarget->hasSignedScratchOffsets())
1431 return true;
1432
1433 auto LHS = Addr.getOperand(0);
1434 auto RHS = Addr.getOperand(1);
1435
1436 // If the immediate offset is negative and within certain range, the base
1437 // address cannot also be negative. If the base is also negative, the sum
1438 // would be either negative or much larger than the valid range of scratch
1439 // memory a thread can access.
1440 ConstantSDNode *ImmOp = nullptr;
1441 if (Addr.getOpcode() == ISD::ADD && (ImmOp = dyn_cast<ConstantSDNode>(RHS))) {
1442 if (ImmOp->getSExtValue() < 0 && ImmOp->getSExtValue() > -0x40000000)
1443 return true;
1444 }
1445
1446 return CurDAG->SignBitIsZero(LHS);
1447}
1448
1449// Check address value in SGPR/VGPR are legal for flat scratch in the form
1450// of: SGPR + VGPR.
1451bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegalSV(SDValue Addr) const {
1452 if (isNoUnsignedWrap(Addr))
1453 return true;
1454
1455 // Starting with GFX12, VADDR and SADDR fields in VSCRATCH can use negative
1456 // values.
1457 if (Subtarget->hasSignedScratchOffsets())
1458 return true;
1459
1460 auto LHS = Addr.getOperand(0);
1461 auto RHS = Addr.getOperand(1);
1462 return CurDAG->SignBitIsZero(RHS) && CurDAG->SignBitIsZero(LHS);
1463}
1464
1465// Check address value in SGPR/VGPR are legal for flat scratch in the form
1466// of: SGPR + VGPR + Imm.
1467bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegalSVImm(SDValue Addr) const {
1468 // Starting with GFX12, VADDR and SADDR fields in VSCRATCH can use negative
1469 // values.
1470 if (AMDGPU::isGFX12Plus(*Subtarget))
1471 return true;
1472
1473 auto Base = Addr.getOperand(0);
1474 auto *RHSImm = cast<ConstantSDNode>(Addr.getOperand(1));
1475 // If the immediate offset is negative and within certain range, the base
1476 // address cannot also be negative. If the base is also negative, the sum
1477 // would be either negative or much larger than the valid range of scratch
1478 // memory a thread can access.
1479 if (isNoUnsignedWrap(Base) &&
1480 (isNoUnsignedWrap(Addr) ||
1481 (RHSImm->getSExtValue() < 0 && RHSImm->getSExtValue() > -0x40000000)))
1482 return true;
1483
1484 auto LHS = Base.getOperand(0);
1485 auto RHS = Base.getOperand(1);
1486 return CurDAG->SignBitIsZero(RHS) && CurDAG->SignBitIsZero(LHS);
1487}
1488
1489// TODO: If offset is too big, put low 16-bit into offset.
1490bool AMDGPUDAGToDAGISel::SelectDS64Bit4ByteAligned(SDValue Addr, SDValue &Base,
1491 SDValue &Offset0,
1492 SDValue &Offset1) const {
1493 return SelectDSReadWrite2(Addr, Base, Offset0, Offset1, 4);
1494}
1495
1496bool AMDGPUDAGToDAGISel::SelectDS128Bit8ByteAligned(SDValue Addr, SDValue &Base,
1497 SDValue &Offset0,
1498 SDValue &Offset1) const {
1499 return SelectDSReadWrite2(Addr, Base, Offset0, Offset1, 8);
1500}
1501
1502bool AMDGPUDAGToDAGISel::SelectDSReadWrite2(SDValue Addr, SDValue &Base,
1503 SDValue &Offset0, SDValue &Offset1,
1504 unsigned Size) const {
1505 SDLoc DL(Addr);
1506
1507 if (CurDAG->isBaseWithConstantOffset(Addr)) {
1508 SDValue N0 = Addr.getOperand(0);
1509 SDValue N1 = Addr.getOperand(1);
1510 ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
1511 unsigned OffsetValue0 = C1->getZExtValue();
1512 unsigned OffsetValue1 = OffsetValue0 + Size;
1513
1514 // (add n0, c0)
1515 if (isDSOffset2Legal(N0, OffsetValue0, OffsetValue1, Size)) {
1516 Base = N0;
1517 Offset0 = CurDAG->getTargetConstant(OffsetValue0 / Size, DL, MVT::i32);
1518 Offset1 = CurDAG->getTargetConstant(OffsetValue1 / Size, DL, MVT::i32);
1519 return true;
1520 }
1521 } else if (Addr.getOpcode() == ISD::SUB) {
1522 // sub C, x -> add (sub 0, x), C
1523 if (const ConstantSDNode *C =
1525 unsigned OffsetValue0 = C->getZExtValue();
1526 unsigned OffsetValue1 = OffsetValue0 + Size;
1527
1528 if (isDSOffset2Legal(SDValue(), OffsetValue0, OffsetValue1, Size)) {
1529 SDLoc DL(Addr);
1530 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
1531
1532 // XXX - This is kind of hacky. Create a dummy sub node so we can check
1533 // the known bits in isDSOffsetLegal. We need to emit the selected node
1534 // here, so this is thrown away.
1535 SDValue Sub =
1536 CurDAG->getNode(ISD::SUB, DL, MVT::i32, Zero, Addr.getOperand(1));
1537
1538 if (isDSOffset2Legal(Sub, OffsetValue0, OffsetValue1, Size)) {
1540 Opnds.push_back(Zero);
1541 Opnds.push_back(Addr.getOperand(1));
1542 unsigned SubOp = AMDGPU::V_SUB_CO_U32_e32;
1543 if (Subtarget->hasAddNoCarryInsts()) {
1544 SubOp = AMDGPU::V_SUB_U32_e64;
1545 Opnds.push_back(
1546 CurDAG->getTargetConstant(0, {}, MVT::i1)); // clamp bit
1547 }
1548
1549 MachineSDNode *MachineSub = CurDAG->getMachineNode(
1550 SubOp, DL, MVT::getIntegerVT(Size * 8), Opnds);
1551
1552 Base = SDValue(MachineSub, 0);
1553 Offset0 =
1554 CurDAG->getTargetConstant(OffsetValue0 / Size, DL, MVT::i32);
1555 Offset1 =
1556 CurDAG->getTargetConstant(OffsetValue1 / Size, DL, MVT::i32);
1557 return true;
1558 }
1559 }
1560 }
1561 } else if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) {
1562 unsigned OffsetValue0 = CAddr->getZExtValue();
1563 unsigned OffsetValue1 = OffsetValue0 + Size;
1564
1565 if (isDSOffset2Legal(SDValue(), OffsetValue0, OffsetValue1, Size)) {
1566 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
1567 MachineSDNode *MovZero =
1568 CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, DL, MVT::i32, Zero);
1569 Base = SDValue(MovZero, 0);
1570 Offset0 = CurDAG->getTargetConstant(OffsetValue0 / Size, DL, MVT::i32);
1571 Offset1 = CurDAG->getTargetConstant(OffsetValue1 / Size, DL, MVT::i32);
1572 return true;
1573 }
1574 }
1575
1576 // default case
1577
1578 Base = Addr;
1579 Offset0 = CurDAG->getTargetConstant(0, DL, MVT::i32);
1580 Offset1 = CurDAG->getTargetConstant(1, DL, MVT::i32);
1581 return true;
1582}
1583
1584bool AMDGPUDAGToDAGISel::SelectMUBUF(SDValue Addr, SDValue &Ptr, SDValue &VAddr,
1585 SDValue &SOffset, SDValue &Offset,
1586 SDValue &Offen, SDValue &Idxen,
1587 SDValue &Addr64) const {
1588 // Subtarget prefers to use flat instruction
1589 // FIXME: This should be a pattern predicate and not reach here
1590 if (Subtarget->useFlatForGlobal())
1591 return false;
1592
1593 SDLoc DL(Addr);
1594
1595 Idxen = CurDAG->getTargetConstant(0, DL, MVT::i1);
1596 Offen = CurDAG->getTargetConstant(0, DL, MVT::i1);
1597 Addr64 = CurDAG->getTargetConstant(0, DL, MVT::i1);
1598 SOffset = Subtarget->hasRestrictedSOffset()
1599 ? CurDAG->getRegister(AMDGPU::SGPR_NULL, MVT::i32)
1600 : CurDAG->getTargetConstant(0, DL, MVT::i32);
1601
1602 ConstantSDNode *C1 = nullptr;
1603 SDValue N0 = Addr;
1604 if (CurDAG->isBaseWithConstantOffset(Addr)) {
1605 C1 = cast<ConstantSDNode>(Addr.getOperand(1));
1606 if (isUInt<32>(C1->getZExtValue()))
1607 N0 = Addr.getOperand(0);
1608 else
1609 C1 = nullptr;
1610 }
1611
1612 if (N0->isAnyAdd()) {
1613 // (add N2, N3) -> addr64, or
1614 // (add (add N2, N3), C1) -> addr64
1615 SDValue N2 = N0.getOperand(0);
1616 SDValue N3 = N0.getOperand(1);
1617 Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1);
1618
1619 if (N2->isDivergent()) {
1620 if (N3->isDivergent()) {
1621 // Both N2 and N3 are divergent. Use N0 (the result of the add) as the
1622 // addr64, and construct the resource from a 0 address.
1623 Ptr = SDValue(buildSMovImm64(DL, 0, MVT::v2i32), 0);
1624 VAddr = N0;
1625 } else {
1626 // N2 is divergent, N3 is not.
1627 Ptr = N3;
1628 VAddr = N2;
1629 }
1630 } else {
1631 // N2 is not divergent.
1632 Ptr = N2;
1633 VAddr = N3;
1634 }
1635 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
1636 } else if (N0->isDivergent()) {
1637 // N0 is divergent. Use it as the addr64, and construct the resource from a
1638 // 0 address.
1639 Ptr = SDValue(buildSMovImm64(DL, 0, MVT::v2i32), 0);
1640 VAddr = N0;
1641 Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1);
1642 } else {
1643 // N0 -> offset, or
1644 // (N0 + C1) -> offset
1645 VAddr = CurDAG->getTargetConstant(0, DL, MVT::i32);
1646 Ptr = N0;
1647 }
1648
1649 if (!C1) {
1650 // No offset.
1651 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
1652 return true;
1653 }
1654
1655 const SIInstrInfo *TII = Subtarget->getInstrInfo();
1656 if (TII->isLegalMUBUFImmOffset(C1->getZExtValue())) {
1657 // Legal offset for instruction.
1658 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i32);
1659 return true;
1660 }
1661
1662 // Illegal offset, store it in soffset.
1663 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
1664 SOffset =
1665 SDValue(CurDAG->getMachineNode(
1666 AMDGPU::S_MOV_B32, DL, MVT::i32,
1667 CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i32)),
1668 0);
1669 return true;
1670}
1671
1672bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc,
1673 SDValue &VAddr, SDValue &SOffset,
1674 SDValue &Offset) const {
1675 SDValue Ptr, Offen, Idxen, Addr64;
1676
1677 // addr64 bit was removed for volcanic islands.
1678 // FIXME: This should be a pattern predicate and not reach here
1679 if (!Subtarget->hasAddr64())
1680 return false;
1681
1682 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64))
1683 return false;
1684
1685 ConstantSDNode *C = cast<ConstantSDNode>(Addr64);
1686 if (C->getSExtValue()) {
1687 SDLoc DL(Addr);
1688
1689 const SITargetLowering& Lowering =
1690 *static_cast<const SITargetLowering*>(getTargetLowering());
1691
1692 SRsrc = SDValue(Lowering.wrapAddr64Rsrc(*CurDAG, DL, Ptr), 0);
1693 return true;
1694 }
1695
1696 return false;
1697}
1698
1699std::pair<SDValue, SDValue> AMDGPUDAGToDAGISel::foldFrameIndex(SDValue N) const {
1700 SDLoc DL(N);
1701
1702 auto *FI = dyn_cast<FrameIndexSDNode>(N);
1703 SDValue TFI =
1704 FI ? CurDAG->getTargetFrameIndex(FI->getIndex(), FI->getValueType(0)) : N;
1705
1706 // We rebase the base address into an absolute stack address and hence
1707 // use constant 0 for soffset. This value must be retained until
1708 // frame elimination and eliminateFrameIndex will choose the appropriate
1709 // frame register if need be.
1710 return std::pair(TFI, CurDAG->getTargetConstant(0, DL, MVT::i32));
1711}
1712
1713bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(SDNode *Parent,
1714 SDValue Addr, SDValue &Rsrc,
1715 SDValue &VAddr, SDValue &SOffset,
1716 SDValue &ImmOffset) const {
1717
1718 SDLoc DL(Addr);
1719 MachineFunction &MF = CurDAG->getMachineFunction();
1720 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
1721
1722 Rsrc = CurDAG->getRegister(Info->getScratchRSrcReg(), MVT::v4i32);
1723
1724 if (ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) {
1725 int64_t Imm = CAddr->getSExtValue();
1726 const int64_t NullPtr =
1728 // Don't fold null pointer.
1729 if (Imm != NullPtr) {
1730 const int64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(*Subtarget);
1731 SDValue HighBits =
1732 CurDAG->getTargetConstant(Imm & ~MaxOffset, DL, MVT::i32);
1733 MachineSDNode *MovHighBits = CurDAG->getMachineNode(
1734 AMDGPU::V_MOV_B32_e32, DL, MVT::i32, HighBits);
1735 VAddr = SDValue(MovHighBits, 0);
1736
1737 SOffset = CurDAG->getTargetConstant(0, DL, MVT::i32);
1738 ImmOffset = CurDAG->getTargetConstant(Imm & MaxOffset, DL, MVT::i32);
1739 return true;
1740 }
1741 }
1742
1743 if (CurDAG->isBaseWithConstantOffset(Addr)) {
1744 // (add n0, c1)
1745
1746 SDValue N0 = Addr.getOperand(0);
1747 uint64_t C1 = Addr.getConstantOperandVal(1);
1748
1749 // Offsets in vaddr must be positive if range checking is enabled.
1750 //
1751 // The total computation of vaddr + soffset + offset must not overflow. If
1752 // vaddr is negative, even if offset is 0 the sgpr offset add will end up
1753 // overflowing.
1754 //
1755 // Prior to gfx9, MUBUF instructions with the vaddr offset enabled would
1756 // always perform a range check. If a negative vaddr base index was used,
1757 // this would fail the range check. The overall address computation would
1758 // compute a valid address, but this doesn't happen due to the range
1759 // check. For out-of-bounds MUBUF loads, a 0 is returned.
1760 //
1761 // Therefore it should be safe to fold any VGPR offset on gfx9 into the
1762 // MUBUF vaddr, but not on older subtargets which can only do this if the
1763 // sign bit is known 0.
1764 const SIInstrInfo *TII = Subtarget->getInstrInfo();
1765 if (TII->isLegalMUBUFImmOffset(C1) &&
1766 (!Subtarget->privateMemoryResourceIsRangeChecked() ||
1767 CurDAG->SignBitIsZero(N0))) {
1768 std::tie(VAddr, SOffset) = foldFrameIndex(N0);
1769 ImmOffset = CurDAG->getTargetConstant(C1, DL, MVT::i32);
1770 return true;
1771 }
1772 }
1773
1774 // (node)
1775 std::tie(VAddr, SOffset) = foldFrameIndex(Addr);
1776 ImmOffset = CurDAG->getTargetConstant(0, DL, MVT::i32);
1777 return true;
1778}
1779
1780static bool IsCopyFromSGPR(const SIRegisterInfo &TRI, SDValue Val) {
1781 if (Val.getOpcode() != ISD::CopyFromReg)
1782 return false;
1783 auto Reg = cast<RegisterSDNode>(Val.getOperand(1))->getReg();
1784 if (!Reg.isPhysical())
1785 return false;
1786 const auto *RC = TRI.getPhysRegBaseClass(Reg);
1787 return RC && TRI.isSGPRClass(RC);
1788}
1789
1790bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffset(SDNode *Parent,
1791 SDValue Addr,
1792 SDValue &SRsrc,
1793 SDValue &SOffset,
1794 SDValue &Offset) const {
1795 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
1796 const SIInstrInfo *TII = Subtarget->getInstrInfo();
1797 MachineFunction &MF = CurDAG->getMachineFunction();
1798 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
1799 SDLoc DL(Addr);
1800
1801 // CopyFromReg <sgpr>
1802 if (IsCopyFromSGPR(*TRI, Addr)) {
1803 SRsrc = CurDAG->getRegister(Info->getScratchRSrcReg(), MVT::v4i32);
1804 SOffset = Addr;
1805 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
1806 return true;
1807 }
1808
1809 ConstantSDNode *CAddr;
1810 if (Addr.getOpcode() == ISD::ADD) {
1811 // Add (CopyFromReg <sgpr>) <constant>
1812 CAddr = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
1813 if (!CAddr || !TII->isLegalMUBUFImmOffset(CAddr->getZExtValue()))
1814 return false;
1815 if (!IsCopyFromSGPR(*TRI, Addr.getOperand(0)))
1816 return false;
1817
1818 SOffset = Addr.getOperand(0);
1819 } else if ((CAddr = dyn_cast<ConstantSDNode>(Addr)) &&
1820 TII->isLegalMUBUFImmOffset(CAddr->getZExtValue())) {
1821 // <constant>
1822 SOffset = CurDAG->getTargetConstant(0, DL, MVT::i32);
1823 } else {
1824 return false;
1825 }
1826
1827 SRsrc = CurDAG->getRegister(Info->getScratchRSrcReg(), MVT::v4i32);
1828
1829 Offset = CurDAG->getTargetConstant(CAddr->getZExtValue(), DL, MVT::i32);
1830 return true;
1831}
1832
1833bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc,
1834 SDValue &SOffset, SDValue &Offset
1835 ) const {
1836 SDValue Ptr, VAddr, Offen, Idxen, Addr64;
1837 const SIInstrInfo *TII = Subtarget->getInstrInfo();
1838
1839 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64))
1840 return false;
1841
1842 if (!cast<ConstantSDNode>(Offen)->getSExtValue() &&
1843 !cast<ConstantSDNode>(Idxen)->getSExtValue() &&
1844 !cast<ConstantSDNode>(Addr64)->getSExtValue()) {
1845 uint64_t Rsrc = TII->getDefaultRsrcDataFormat() |
1846 maskTrailingOnes<uint64_t>(32); // Size
1847 SDLoc DL(Addr);
1848
1849 const SITargetLowering& Lowering =
1850 *static_cast<const SITargetLowering*>(getTargetLowering());
1851
1852 SRsrc = SDValue(Lowering.buildRSRC(*CurDAG, DL, Ptr, 0, Rsrc), 0);
1853 return true;
1854 }
1855 return false;
1856}
1857
1858bool AMDGPUDAGToDAGISel::SelectBUFSOffset(SDValue ByteOffsetNode,
1859 SDValue &SOffset) const {
1860 if (Subtarget->hasRestrictedSOffset() && isNullConstant(ByteOffsetNode)) {
1861 SOffset = CurDAG->getRegister(AMDGPU::SGPR_NULL, MVT::i32);
1862 return true;
1863 }
1864
1865 SOffset = ByteOffsetNode;
1866 return true;
1867}
1868
1869// Find a load or store from corresponding pattern root.
1870// Roots may be build_vector, bitconvert or their combinations.
1873 if (MemSDNode *MN = dyn_cast<MemSDNode>(N))
1874 return MN;
1876 for (SDValue V : N->op_values())
1877 if (MemSDNode *MN =
1879 return MN;
1880 llvm_unreachable("cannot find MemSDNode in the pattern!");
1881}
1882
1883bool AMDGPUDAGToDAGISel::SelectFlatOffsetImpl(
1884 SDNode *N, SDValue Addr, SDValue &VAddr, SDValue &Offset,
1885 AMDGPU::FlatAddrSpace FlatVariant) const {
1887 int64_t OffsetVal = 0;
1888
1889 unsigned AS = findMemSDNode(N)->getAddressSpace();
1890
1891 bool CanHaveFlatSegmentOffsetBug =
1892 Subtarget->hasFlatSegmentOffsetBug() &&
1893 FlatVariant == FlatAddrSpace::FLAT &&
1895
1896 if (Subtarget->hasFlatInstOffsets() && !CanHaveFlatSegmentOffsetBug) {
1897 SDValue N0, N1;
1898 if (isBaseWithConstantOffset64(Addr, N0, N1) &&
1899 (FlatVariant != FlatAddrSpace::FlatScratch ||
1900 isFlatScratchBaseLegal(Addr))) {
1901 int64_t COffsetVal = cast<ConstantSDNode>(N1)->getSExtValue();
1902
1903 // Adding the offset to the base address in a FLAT instruction must not
1904 // change the memory aperture in which the address falls. Therefore we can
1905 // only fold offsets from inbounds GEPs into FLAT instructions.
1906 bool IsInBounds =
1907 Addr.getOpcode() == ISD::PTRADD && Addr->getFlags().hasInBounds();
1908 if (COffsetVal == 0 || FlatVariant != FlatAddrSpace::FLAT || IsInBounds) {
1909 const SIInstrInfo *TII = Subtarget->getInstrInfo();
1910 if (TII->isLegalFLATOffset(COffsetVal, AS, FlatVariant)) {
1911 Addr = N0;
1912 OffsetVal = COffsetVal;
1913 } else {
1914 // If the offset doesn't fit, put the low bits into the offset field
1915 // and add the rest.
1916 //
1917 // For a FLAT instruction the hardware decides whether to access
1918 // global/scratch/shared memory based on the high bits of vaddr,
1919 // ignoring the offset field, so we have to ensure that when we add
1920 // remainder to vaddr it still points into the same underlying object.
1921 // The easiest way to do that is to make sure that we split the offset
1922 // into two pieces that are both >= 0 or both <= 0.
1923
1924 SDLoc DL(N);
1925 uint64_t RemainderOffset;
1926
1927 std::tie(OffsetVal, RemainderOffset) =
1928 TII->splitFlatOffset(COffsetVal, AS, FlatVariant);
1929
1930 SDValue AddOffsetLo =
1931 getMaterializedScalarImm32(Lo_32(RemainderOffset), DL);
1932 SDValue Clamp = CurDAG->getTargetConstant(0, DL, MVT::i1);
1933
1934 if (Addr.getValueType().getSizeInBits() == 32) {
1936 Opnds.push_back(N0);
1937 Opnds.push_back(AddOffsetLo);
1938 unsigned AddOp = AMDGPU::V_ADD_CO_U32_e32;
1939 if (Subtarget->hasAddNoCarryInsts()) {
1940 AddOp = AMDGPU::V_ADD_U32_e64;
1941 Opnds.push_back(Clamp);
1942 }
1943 Addr =
1944 SDValue(CurDAG->getMachineNode(AddOp, DL, MVT::i32, Opnds), 0);
1945 } else {
1946 // TODO: Should this try to use a scalar add pseudo if the base
1947 // address is uniform and saddr is usable?
1948 SDValue Sub0 =
1949 CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32);
1950 SDValue Sub1 =
1951 CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32);
1952
1953 SDNode *N0Lo = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
1954 DL, MVT::i32, N0, Sub0);
1955 SDNode *N0Hi = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
1956 DL, MVT::i32, N0, Sub1);
1957
1958 SDValue AddOffsetHi =
1959 getMaterializedScalarImm32(Hi_32(RemainderOffset), DL);
1960
1961 SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i1);
1962
1963 SDNode *Add =
1964 CurDAG->getMachineNode(AMDGPU::V_ADD_CO_U32_e64, DL, VTs,
1965 {AddOffsetLo, SDValue(N0Lo, 0), Clamp});
1966
1967 SDNode *Addc = CurDAG->getMachineNode(
1968 AMDGPU::V_ADDC_U32_e64, DL, VTs,
1969 {AddOffsetHi, SDValue(N0Hi, 0), SDValue(Add, 1), Clamp});
1970
1971 SDValue RegSequenceArgs[] = {
1972 CurDAG->getTargetConstant(AMDGPU::VReg_64RegClassID, DL,
1973 MVT::i32),
1974 SDValue(Add, 0), Sub0, SDValue(Addc, 0), Sub1};
1975
1976 Addr = SDValue(CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, DL,
1977 MVT::i64, RegSequenceArgs),
1978 0);
1979 }
1980 }
1981 }
1982 }
1983 }
1984
1985 VAddr = Addr;
1986 Offset = CurDAG->getSignedTargetConstant(OffsetVal, SDLoc(), MVT::i32);
1987 return true;
1988}
1989
1990bool AMDGPUDAGToDAGISel::SelectFlatOffset(SDNode *N, SDValue Addr,
1991 SDValue &VAddr,
1992 SDValue &Offset) const {
1993 return SelectFlatOffsetImpl(N, Addr, VAddr, Offset,
1995}
1996
1997bool AMDGPUDAGToDAGISel::SelectGlobalOffset(SDNode *N, SDValue Addr,
1998 SDValue &VAddr,
1999 SDValue &Offset) const {
2000 return SelectFlatOffsetImpl(N, Addr, VAddr, Offset,
2002}
2003
2004bool AMDGPUDAGToDAGISel::SelectScratchOffset(SDNode *N, SDValue Addr,
2005 SDValue &VAddr,
2006 SDValue &Offset) const {
2007 return SelectFlatOffsetImpl(N, Addr, VAddr, Offset,
2009}
2010
2011// If this matches *_extend i32:x, return x
2012// Otherwise if the value is I32 returns x.
2014 const SelectionDAG *DAG) {
2015 if (Op.getValueType() == MVT::i32)
2016 return Op;
2017
2018 if (Op.getOpcode() != (IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND) &&
2019 Op.getOpcode() != ISD::ANY_EXTEND &&
2020 !(DAG->SignBitIsZero(Op) &&
2021 Op.getOpcode() == (IsSigned ? ISD::ZERO_EXTEND : ISD::SIGN_EXTEND)))
2022 return SDValue();
2023
2024 SDValue ExtSrc = Op.getOperand(0);
2025 return (ExtSrc.getValueType() == MVT::i32) ? ExtSrc : SDValue();
2026}
2027
2028// Match (64-bit SGPR base) + (zext vgpr offset) + sext(imm offset)
2029// or (64-bit SGPR base) + (sext vgpr offset) + sext(imm offset)
2030bool AMDGPUDAGToDAGISel::SelectGlobalSAddr(SDNode *N, SDValue Addr,
2031 SDValue &SAddr, SDValue &VOffset,
2032 SDValue &Offset, bool &ScaleOffset,
2033 bool NeedIOffset) const {
2035 int64_t ImmOffset = 0;
2036 ScaleOffset = false;
2037
2038 // Match the immediate offset first, which canonically is moved as low as
2039 // possible.
2040
2041 SDValue LHS, RHS;
2042 if (isBaseWithConstantOffset64(Addr, LHS, RHS)) {
2043 int64_t COffsetVal = cast<ConstantSDNode>(RHS)->getSExtValue();
2044 const SIInstrInfo *TII = Subtarget->getInstrInfo();
2045
2046 if (NeedIOffset &&
2047 TII->isLegalFLATOffset(COffsetVal, AMDGPUAS::GLOBAL_ADDRESS,
2048 FlatAddrSpace::FlatGlobal)) {
2049 Addr = LHS;
2050 ImmOffset = COffsetVal;
2051 } else if (!LHS->isDivergent()) {
2052 if (COffsetVal > 0) {
2053 SDLoc SL(N);
2054 // saddr + large_offset -> saddr +
2055 // (voffset = large_offset & ~MaxOffset) +
2056 // (large_offset & MaxOffset);
2057 int64_t SplitImmOffset = 0, RemainderOffset = COffsetVal;
2058 if (NeedIOffset) {
2059 std::tie(SplitImmOffset, RemainderOffset) = TII->splitFlatOffset(
2060 COffsetVal, AMDGPUAS::GLOBAL_ADDRESS, FlatAddrSpace::FlatGlobal);
2061 }
2062
2063 if (Subtarget->hasSignedGVSOffset() ? isInt<32>(RemainderOffset)
2064 : isUInt<32>(RemainderOffset)) {
2065 SDNode *VMov = CurDAG->getMachineNode(
2066 AMDGPU::V_MOV_B32_e32, SL, MVT::i32,
2067 CurDAG->getTargetConstant(RemainderOffset, SDLoc(), MVT::i32));
2068 VOffset = SDValue(VMov, 0);
2069 SAddr = LHS;
2070 Offset = CurDAG->getTargetConstant(SplitImmOffset, SDLoc(), MVT::i32);
2071 return true;
2072 }
2073 }
2074
2075 // We are adding a 64 bit SGPR and a constant. If constant bus limit
2076 // is 1 we would need to perform 1 or 2 extra moves for each half of
2077 // the constant and it is better to do a scalar add and then issue a
2078 // single VALU instruction to materialize zero. Otherwise it is less
2079 // instructions to perform VALU adds with immediates or inline literals.
2080 unsigned NumLiterals =
2081 !TII->isInlineConstant(APInt(32, Lo_32(COffsetVal))) +
2082 !TII->isInlineConstant(APInt(32, Hi_32(COffsetVal)));
2083 if (Subtarget->getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
2084 return false;
2085 }
2086 }
2087
2088 // Match the variable offset.
2089 if (Addr->isAnyAdd()) {
2090 LHS = Addr.getOperand(0);
2091
2092 if (!LHS->isDivergent()) {
2093 // add (i64 sgpr), (*_extend (i32 vgpr))
2094 RHS = Addr.getOperand(1);
2095 ScaleOffset = SelectScaleOffset(N, RHS, Subtarget->hasSignedGVSOffset());
2096 if (SDValue ExtRHS = matchExtFromI32orI32(
2097 RHS, Subtarget->hasSignedGVSOffset(), CurDAG)) {
2098 SAddr = LHS;
2099 VOffset = ExtRHS;
2100 }
2101 }
2102
2103 RHS = Addr.getOperand(1);
2104 if (!SAddr && !RHS->isDivergent()) {
2105 // add (*_extend (i32 vgpr)), (i64 sgpr)
2106 ScaleOffset = SelectScaleOffset(N, LHS, Subtarget->hasSignedGVSOffset());
2107 if (SDValue ExtLHS = matchExtFromI32orI32(
2108 LHS, Subtarget->hasSignedGVSOffset(), CurDAG)) {
2109 SAddr = RHS;
2110 VOffset = ExtLHS;
2111 }
2112 }
2113
2114 if (SAddr) {
2115 Offset = CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2116 return true;
2117 }
2118 }
2119
2120 if (Subtarget->hasScaleOffset() &&
2121 (Addr.getOpcode() == (Subtarget->hasSignedGVSOffset()
2124 (Addr.getOpcode() == AMDGPUISD::MAD_U64_U32 &&
2125 CurDAG->SignBitIsZero(Addr.getOperand(0)))) &&
2126 Addr.getOperand(0)->isDivergent() &&
2128 !Addr.getOperand(2)->isDivergent()) {
2129 // mad_u64_u32 (i32 vgpr), (i32 c), (i64 sgpr)
2130 unsigned Size =
2131 (unsigned)cast<MemSDNode>(N)->getMemoryVT().getFixedSizeInBits() / 8;
2132 ScaleOffset = Addr.getConstantOperandVal(1) == Size;
2133 if (ScaleOffset) {
2134 SAddr = Addr.getOperand(2);
2135 VOffset = Addr.getOperand(0);
2136 Offset = CurDAG->getTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2137 return true;
2138 }
2139 }
2140
2141 if (Addr->isDivergent() || Addr.isUndef() || isa<ConstantSDNode>(Addr))
2142 return false;
2143
2144 // It's cheaper to materialize a single 32-bit zero for vaddr than the two
2145 // moves required to copy a 64-bit SGPR to VGPR.
2146 SAddr = Addr;
2147 SDNode *VMov =
2148 CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, SDLoc(Addr), MVT::i32,
2149 CurDAG->getTargetConstant(0, SDLoc(), MVT::i32));
2150 VOffset = SDValue(VMov, 0);
2151 Offset = CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2152 return true;
2153}
2154
2155bool AMDGPUDAGToDAGISel::SelectGlobalSAddr(SDNode *N, SDValue Addr,
2156 SDValue &SAddr, SDValue &VOffset,
2157 SDValue &Offset,
2158 SDValue &CPol) const {
2159 bool ScaleOffset;
2160 if (!SelectGlobalSAddr(N, Addr, SAddr, VOffset, Offset, ScaleOffset))
2161 return false;
2162
2163 CPol = CurDAG->getTargetConstant(ScaleOffset ? AMDGPU::CPol::SCAL : 0,
2164 SDLoc(), MVT::i32);
2165 return true;
2166}
2167
2168bool AMDGPUDAGToDAGISel::SelectGlobalSAddrCPol(SDNode *N, SDValue Addr,
2169 SDValue &SAddr, SDValue &VOffset,
2170 SDValue &Offset,
2171 SDValue &CPol) const {
2172 bool ScaleOffset;
2173 if (!SelectGlobalSAddr(N, Addr, SAddr, VOffset, Offset, ScaleOffset))
2174 return false;
2175
2176 // We are assuming CPol is always the last operand of the intrinsic.
2177 auto PassedCPol =
2178 N->getConstantOperandVal(N->getNumOperands() - 1) & ~AMDGPU::CPol::SCAL;
2179 CPol = CurDAG->getTargetConstant(
2180 (ScaleOffset ? AMDGPU::CPol::SCAL : 0) | PassedCPol, SDLoc(), MVT::i32);
2181 return true;
2182}
2183
2184bool AMDGPUDAGToDAGISel::SelectGlobalSAddrCPolM0(SDNode *N, SDValue Addr,
2185 SDValue &SAddr,
2186 SDValue &VOffset,
2187 SDValue &Offset,
2188 SDValue &CPol) const {
2189 bool ScaleOffset;
2190 if (!SelectGlobalSAddr(N, Addr, SAddr, VOffset, Offset, ScaleOffset))
2191 return false;
2192
2193 // We are assuming CPol is second from last operand of the intrinsic.
2194 auto PassedCPol =
2195 N->getConstantOperandVal(N->getNumOperands() - 2) & ~AMDGPU::CPol::SCAL;
2196 CPol = CurDAG->getTargetConstant(
2197 (ScaleOffset ? AMDGPU::CPol::SCAL : 0) | PassedCPol, SDLoc(), MVT::i32);
2198 return true;
2199}
2200
2201bool AMDGPUDAGToDAGISel::SelectGlobalSAddrGLC(SDNode *N, SDValue Addr,
2202 SDValue &SAddr, SDValue &VOffset,
2203 SDValue &Offset,
2204 SDValue &CPol) const {
2205 bool ScaleOffset;
2206 if (!SelectGlobalSAddr(N, Addr, SAddr, VOffset, Offset, ScaleOffset))
2207 return false;
2208
2209 unsigned CPolVal = (ScaleOffset ? AMDGPU::CPol::SCAL : 0) | AMDGPU::CPol::GLC;
2210 CPol = CurDAG->getTargetConstant(CPolVal, SDLoc(), MVT::i32);
2211 return true;
2212}
2213
2214bool AMDGPUDAGToDAGISel::SelectGlobalSAddrNoIOffset(SDNode *N, SDValue Addr,
2215 SDValue &SAddr,
2216 SDValue &VOffset,
2217 SDValue &CPol) const {
2218 bool ScaleOffset;
2219 SDValue DummyOffset;
2220 if (!SelectGlobalSAddr(N, Addr, SAddr, VOffset, DummyOffset, ScaleOffset,
2221 false))
2222 return false;
2223
2224 // We are assuming CPol is always the last operand of the intrinsic.
2225 auto PassedCPol =
2226 N->getConstantOperandVal(N->getNumOperands() - 1) & ~AMDGPU::CPol::SCAL;
2227 CPol = CurDAG->getTargetConstant(
2228 (ScaleOffset ? AMDGPU::CPol::SCAL : 0) | PassedCPol, SDLoc(), MVT::i32);
2229 return true;
2230}
2231
2232bool AMDGPUDAGToDAGISel::SelectGlobalSAddrNoIOffsetM0(SDNode *N, SDValue Addr,
2233 SDValue &SAddr,
2234 SDValue &VOffset,
2235 SDValue &CPol) const {
2236 bool ScaleOffset;
2237 SDValue DummyOffset;
2238 if (!SelectGlobalSAddr(N, Addr, SAddr, VOffset, DummyOffset, ScaleOffset,
2239 false))
2240 return false;
2241
2242 // We are assuming CPol is second from last operand of the intrinsic.
2243 auto PassedCPol =
2244 N->getConstantOperandVal(N->getNumOperands() - 2) & ~AMDGPU::CPol::SCAL;
2245 CPol = CurDAG->getTargetConstant(
2246 (ScaleOffset ? AMDGPU::CPol::SCAL : 0) | PassedCPol, SDLoc(), MVT::i32);
2247 return true;
2248}
2249
2251 if (auto *FI = dyn_cast<FrameIndexSDNode>(SAddr)) {
2252 SAddr = CurDAG->getTargetFrameIndex(FI->getIndex(), FI->getValueType(0));
2253 } else if (SAddr.getOpcode() == ISD::ADD &&
2255 // Materialize this into a scalar move for scalar address to avoid
2256 // readfirstlane.
2257 auto *FI = cast<FrameIndexSDNode>(SAddr.getOperand(0));
2258 SDValue TFI = CurDAG->getTargetFrameIndex(FI->getIndex(),
2259 FI->getValueType(0));
2260 SAddr = SDValue(CurDAG->getMachineNode(AMDGPU::S_ADD_I32, SDLoc(SAddr),
2261 MVT::i32, TFI, SAddr.getOperand(1)),
2262 0);
2263 }
2264
2265 return SAddr;
2266}
2267
2268// Match (32-bit SGPR base) + sext(imm offset)
2269bool AMDGPUDAGToDAGISel::SelectScratchSAddr(SDNode *Parent, SDValue Addr,
2270 SDValue &SAddr,
2271 SDValue &Offset) const {
2273 if (Addr->isDivergent())
2274 return false;
2275
2276 SDLoc DL(Addr);
2277
2278 int64_t COffsetVal = 0;
2279
2280 if (CurDAG->isBaseWithConstantOffset(Addr) && isFlatScratchBaseLegal(Addr)) {
2281 COffsetVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
2282 SAddr = Addr.getOperand(0);
2283 } else {
2284 SAddr = Addr;
2285 }
2286
2287 SAddr = SelectSAddrFI(CurDAG, SAddr);
2288
2289 const SIInstrInfo *TII = Subtarget->getInstrInfo();
2290
2291 if (!TII->isLegalFLATOffset(COffsetVal, AMDGPUAS::PRIVATE_ADDRESS,
2292 FlatAddrSpace::FlatScratch)) {
2293 int64_t SplitImmOffset, RemainderOffset;
2294 std::tie(SplitImmOffset, RemainderOffset) = TII->splitFlatOffset(
2295 COffsetVal, AMDGPUAS::PRIVATE_ADDRESS, FlatAddrSpace::FlatScratch);
2296
2297 COffsetVal = SplitImmOffset;
2298
2299 SDValue AddOffset =
2301 ? getMaterializedScalarImm32(Lo_32(RemainderOffset), DL)
2302 : CurDAG->getSignedTargetConstant(RemainderOffset, DL, MVT::i32);
2303 SAddr = SDValue(CurDAG->getMachineNode(AMDGPU::S_ADD_I32, DL, MVT::i32,
2304 SAddr, AddOffset),
2305 0);
2306 }
2307
2308 Offset = CurDAG->getSignedTargetConstant(COffsetVal, DL, MVT::i32);
2309
2310 return true;
2311}
2312
2313// Check whether the flat scratch SVS swizzle bug affects this access.
2314bool AMDGPUDAGToDAGISel::checkFlatScratchSVSSwizzleBug(
2315 SDValue VAddr, SDValue SAddr, uint64_t ImmOffset) const {
2316 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
2317 return false;
2318
2319 // The bug affects the swizzling of SVS accesses if there is any carry out
2320 // from the two low order bits (i.e. from bit 1 into bit 2) when adding
2321 // voffset to (soffset + inst_offset).
2322 KnownBits VKnown = CurDAG->computeKnownBits(VAddr);
2323 KnownBits SKnown =
2324 KnownBits::add(CurDAG->computeKnownBits(SAddr),
2325 KnownBits::makeConstant(APInt(32, ImmOffset,
2326 /*isSigned=*/true)));
2327 uint64_t VMax = VKnown.getMaxValue().getZExtValue();
2328 uint64_t SMax = SKnown.getMaxValue().getZExtValue();
2329 return (VMax & 3) + (SMax & 3) >= 4;
2330}
2331
2332bool AMDGPUDAGToDAGISel::SelectScratchSVAddr(SDNode *N, SDValue Addr,
2333 SDValue &VAddr, SDValue &SAddr,
2334 SDValue &Offset,
2335 SDValue &CPol) const {
2336 int64_t ImmOffset = 0;
2337
2338 SDValue LHS, RHS;
2339 SDValue OrigAddr = Addr;
2340 if (isBaseWithConstantOffset64(Addr, LHS, RHS)) {
2341 int64_t COffsetVal = cast<ConstantSDNode>(RHS)->getSExtValue();
2342 const SIInstrInfo *TII = Subtarget->getInstrInfo();
2343
2344 if (TII->isLegalFLATOffset(COffsetVal, AMDGPUAS::PRIVATE_ADDRESS,
2346 Addr = LHS;
2347 ImmOffset = COffsetVal;
2348 } else if (!LHS->isDivergent() && COffsetVal > 0) {
2349 SDLoc SL(N);
2350 // saddr + large_offset -> saddr + (vaddr = large_offset & ~MaxOffset) +
2351 // (large_offset & MaxOffset);
2352 int64_t SplitImmOffset, RemainderOffset;
2353 std::tie(SplitImmOffset, RemainderOffset) =
2354 TII->splitFlatOffset(COffsetVal, AMDGPUAS::PRIVATE_ADDRESS,
2356
2357 if (isUInt<32>(RemainderOffset)) {
2358 SDNode *VMov = CurDAG->getMachineNode(
2359 AMDGPU::V_MOV_B32_e32, SL, MVT::i32,
2360 CurDAG->getTargetConstant(RemainderOffset, SDLoc(), MVT::i32));
2361 VAddr = SDValue(VMov, 0);
2362 SAddr = LHS;
2363 if (!isFlatScratchBaseLegal(Addr))
2364 return false;
2365 if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, SplitImmOffset))
2366 return false;
2367 Offset = CurDAG->getTargetConstant(SplitImmOffset, SDLoc(), MVT::i32);
2368 CPol = CurDAG->getTargetConstant(0, SDLoc(), MVT::i32);
2369 return true;
2370 }
2371 }
2372 }
2373
2374 if (Addr.getOpcode() != ISD::ADD)
2375 return false;
2376
2377 LHS = Addr.getOperand(0);
2378 RHS = Addr.getOperand(1);
2379
2380 if (!LHS->isDivergent() && RHS->isDivergent()) {
2381 SAddr = LHS;
2382 VAddr = RHS;
2383 } else if (!RHS->isDivergent() && LHS->isDivergent()) {
2384 SAddr = RHS;
2385 VAddr = LHS;
2386 } else {
2387 return false;
2388 }
2389
2390 if (OrigAddr != Addr) {
2391 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
2392 return false;
2393 } else {
2394 if (!isFlatScratchBaseLegalSV(OrigAddr))
2395 return false;
2396 }
2397
2398 if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, ImmOffset))
2399 return false;
2400 SAddr = SelectSAddrFI(CurDAG, SAddr);
2401 Offset = CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2402
2403 bool ScaleOffset = SelectScaleOffset(N, VAddr, true /* IsSigned */);
2404 CPol = CurDAG->getTargetConstant(ScaleOffset ? AMDGPU::CPol::SCAL : 0,
2405 SDLoc(), MVT::i32);
2406 return true;
2407}
2408
2409// For unbuffered smem loads, it is illegal for the Immediate Offset to be
2410// negative if the resulting (Offset + (M0 or SOffset or zero) is negative.
2411// Handle the case where the Immediate Offset + SOffset is negative.
2412bool AMDGPUDAGToDAGISel::isSOffsetLegalWithImmOffset(SDValue *SOffset,
2413 bool Imm32Only,
2414 bool IsBuffer,
2415 int64_t ImmOffset) const {
2416 if (!IsBuffer && !Imm32Only && ImmOffset < 0 &&
2417 AMDGPU::hasSMRDSignedImmOffset(*Subtarget)) {
2418 KnownBits SKnown = CurDAG->computeKnownBits(*SOffset);
2419 if (ImmOffset + SKnown.getMinValue().getSExtValue() < 0)
2420 return false;
2421 }
2422
2423 return true;
2424}
2425
2426// Given \p Offset and load node \p N check if an \p Offset is a multiple of
2427// the load byte size. If it is update \p Offset to a pre-scaled value and
2428// return true.
2429bool AMDGPUDAGToDAGISel::SelectScaleOffset(SDNode *N, SDValue &Offset,
2430 bool IsSigned) const {
2431 bool ScaleOffset = false;
2432 if (!Subtarget->hasScaleOffset() || !Offset)
2433 return false;
2434
2435 unsigned Size =
2436 (unsigned)cast<MemSDNode>(N)->getMemoryVT().getFixedSizeInBits() / 8;
2437
2438 SDValue Off = Offset;
2439 if (SDValue Ext = matchExtFromI32orI32(Offset, IsSigned, CurDAG))
2440 Off = Ext;
2441
2442 if (isPowerOf2_32(Size) && Off.getOpcode() == ISD::SHL) {
2443 if (auto *C = dyn_cast<ConstantSDNode>(Off.getOperand(1)))
2444 ScaleOffset = C->getZExtValue() == Log2_32(Size);
2445 } else if (Offset.getOpcode() == ISD::MUL ||
2446 (IsSigned && Offset.getOpcode() == AMDGPUISD::MUL_I24) ||
2447 Offset.getOpcode() == AMDGPUISD::MUL_U24 ||
2448 (Offset.isMachineOpcode() &&
2449 Offset.getMachineOpcode() ==
2450 (IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO
2451 : AMDGPU::S_MUL_U64_U32_PSEUDO))) {
2452 if (auto *C = dyn_cast<ConstantSDNode>(Offset.getOperand(1)))
2453 ScaleOffset = C->getZExtValue() == Size;
2454 }
2455
2456 if (ScaleOffset)
2457 Offset = Off.getOperand(0);
2458
2459 return ScaleOffset;
2460}
2461
2462// Match an immediate (if Offset is not null) or an SGPR (if SOffset is
2463// not null) offset. If Imm32Only is true, match only 32-bit immediate
2464// offsets available on CI.
2465bool AMDGPUDAGToDAGISel::SelectSMRDOffset(SDNode *N, SDValue ByteOffsetNode,
2466 SDValue *SOffset, SDValue *Offset,
2467 bool Imm32Only, bool IsBuffer,
2468 bool HasSOffset, int64_t ImmOffset,
2469 bool *ScaleOffset) const {
2470 assert((!SOffset || !Offset) &&
2471 "Cannot match both soffset and offset at the same time!");
2472
2473 if (ScaleOffset) {
2474 assert(N && SOffset);
2475
2476 *ScaleOffset = SelectScaleOffset(N, ByteOffsetNode, false /* IsSigned */);
2477 }
2478
2479 ConstantSDNode *C = dyn_cast<ConstantSDNode>(ByteOffsetNode);
2480 if (!C) {
2481 if (!SOffset)
2482 return false;
2483
2484 if (ByteOffsetNode.getValueType().isScalarInteger() &&
2485 ByteOffsetNode.getValueType().getSizeInBits() == 32) {
2486 *SOffset = ByteOffsetNode;
2487 return isSOffsetLegalWithImmOffset(SOffset, Imm32Only, IsBuffer,
2488 ImmOffset);
2489 }
2490 if (ByteOffsetNode.getOpcode() == ISD::ZERO_EXTEND) {
2491 if (ByteOffsetNode.getOperand(0).getValueType().getSizeInBits() == 32) {
2492 *SOffset = ByteOffsetNode.getOperand(0);
2493 return isSOffsetLegalWithImmOffset(SOffset, Imm32Only, IsBuffer,
2494 ImmOffset);
2495 }
2496 }
2497 return false;
2498 }
2499
2500 SDLoc SL(ByteOffsetNode);
2501
2502 // GFX9 and GFX10 have signed byte immediate offsets. The immediate
2503 // offset for S_BUFFER instructions is unsigned.
2504 int64_t ByteOffset = IsBuffer ? C->getZExtValue() : C->getSExtValue();
2505 std::optional<int64_t> EncodedOffset = AMDGPU::getSMRDEncodedOffset(
2506 *Subtarget, ByteOffset, IsBuffer, HasSOffset);
2507 if (EncodedOffset && Offset && !Imm32Only) {
2508 *Offset = CurDAG->getSignedTargetConstant(*EncodedOffset, SL, MVT::i32);
2509 return true;
2510 }
2511
2512 // SGPR and literal offsets are unsigned.
2513 if (ByteOffset < 0)
2514 return false;
2515
2516 EncodedOffset = AMDGPU::getSMRDEncodedLiteralOffset32(*Subtarget, ByteOffset);
2517 if (EncodedOffset && Offset && Imm32Only) {
2518 *Offset = CurDAG->getTargetConstant(*EncodedOffset, SL, MVT::i32);
2519 return true;
2520 }
2521
2522 if (!isUInt<32>(ByteOffset) && !isInt<32>(ByteOffset))
2523 return false;
2524
2525 if (SOffset) {
2526 SDValue C32Bit = CurDAG->getTargetConstant(ByteOffset, SL, MVT::i32);
2527 *SOffset = SDValue(
2528 CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, C32Bit), 0);
2529 return true;
2530 }
2531
2532 return false;
2533}
2534
2535SDValue AMDGPUDAGToDAGISel::Expand32BitAddress(SDValue Addr) const {
2536 if (Addr.getValueType() != MVT::i32)
2537 return Addr;
2538
2539 // Zero-extend a 32-bit address.
2540 SDLoc SL(Addr);
2541
2542 const MachineFunction &MF = CurDAG->getMachineFunction();
2543 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
2544 unsigned AddrHiVal = Info->get32BitAddressHighBits();
2545 SDValue AddrHi = CurDAG->getTargetConstant(AddrHiVal, SL, MVT::i32);
2546
2547 const SDValue Ops[] = {
2548 CurDAG->getTargetConstant(AMDGPU::SReg_64_XEXECRegClassID, SL, MVT::i32),
2549 Addr,
2550 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32),
2551 SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, AddrHi),
2552 0),
2553 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32),
2554 };
2555
2556 return SDValue(CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, SL, MVT::i64,
2557 Ops), 0);
2558}
2559
2560// Match a base and an immediate (if Offset is not null) or an SGPR (if
2561// SOffset is not null) or an immediate+SGPR offset. If Imm32Only is
2562// true, match only 32-bit immediate offsets available on CI.
2563bool AMDGPUDAGToDAGISel::SelectSMRDBaseOffset(SDNode *N, SDValue Addr,
2564 SDValue &SBase, SDValue *SOffset,
2565 SDValue *Offset, bool Imm32Only,
2566 bool IsBuffer, bool HasSOffset,
2567 int64_t ImmOffset,
2568 bool *ScaleOffset) const {
2569 if (SOffset && Offset) {
2570 assert(!Imm32Only && !IsBuffer);
2571 SDValue B;
2572
2573 if (!SelectSMRDBaseOffset(N, Addr, B, nullptr, Offset, false, false, true))
2574 return false;
2575
2576 int64_t ImmOff = 0;
2577 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(*Offset))
2578 ImmOff = C->getSExtValue();
2579
2580 return SelectSMRDBaseOffset(N, B, SBase, SOffset, nullptr, false, false,
2581 true, ImmOff, ScaleOffset);
2582 }
2583
2584 // A 32-bit (address + offset) should not cause unsigned 32-bit integer
2585 // wraparound, because s_load instructions perform the addition in 64 bits.
2586 if (Addr.getValueType() == MVT::i32 && Addr.getOpcode() == ISD::ADD &&
2587 !Addr->getFlags().hasNoUnsignedWrap())
2588 return false;
2589
2590 SDValue N0, N1;
2591 // Extract the base and offset if possible.
2592 if (Addr->isAnyAdd() || CurDAG->isADDLike(Addr)) {
2593 N0 = Addr.getOperand(0);
2594 N1 = Addr.getOperand(1);
2595 } else if (getBaseWithOffsetUsingSplitOR(*CurDAG, Addr, N0, N1)) {
2596 assert(N0 && N1 && isa<ConstantSDNode>(N1));
2597 }
2598 if (!N0 || !N1)
2599 return false;
2600
2601 if (SelectSMRDOffset(N, N1, SOffset, Offset, Imm32Only, IsBuffer, HasSOffset,
2602 ImmOffset, ScaleOffset)) {
2603 SBase = N0;
2604 return true;
2605 }
2606 if (SelectSMRDOffset(N, N0, SOffset, Offset, Imm32Only, IsBuffer, HasSOffset,
2607 ImmOffset, ScaleOffset)) {
2608 SBase = N1;
2609 return true;
2610 }
2611 return false;
2612}
2613
2614bool AMDGPUDAGToDAGISel::SelectSMRD(SDNode *N, SDValue Addr, SDValue &SBase,
2615 SDValue *SOffset, SDValue *Offset,
2616 bool Imm32Only, bool *ScaleOffset) const {
2617 if (SelectSMRDBaseOffset(N, Addr, SBase, SOffset, Offset, Imm32Only,
2618 /* IsBuffer */ false, /* HasSOffset */ false,
2619 /* ImmOffset */ 0, ScaleOffset)) {
2620 SBase = Expand32BitAddress(SBase);
2621 return true;
2622 }
2623
2624 if (Addr.getValueType() == MVT::i32 && Offset && !SOffset) {
2625 SBase = Expand32BitAddress(Addr);
2626 *Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
2627 return true;
2628 }
2629
2630 return false;
2631}
2632
2633bool AMDGPUDAGToDAGISel::SelectSMRDImm(SDValue Addr, SDValue &SBase,
2634 SDValue &Offset) const {
2635 return SelectSMRD(/* N */ nullptr, Addr, SBase, /* SOffset */ nullptr,
2636 &Offset);
2637}
2638
2639bool AMDGPUDAGToDAGISel::SelectSMRDImm32(SDValue Addr, SDValue &SBase,
2640 SDValue &Offset) const {
2641 assert(Subtarget->getGeneration() == AMDGPUSubtarget::SEA_ISLANDS);
2642 return SelectSMRD(/* N */ nullptr, Addr, SBase, /* SOffset */ nullptr,
2643 &Offset, /* Imm32Only */ true);
2644}
2645
2646bool AMDGPUDAGToDAGISel::SelectSMRDSgpr(SDNode *N, SDValue Addr, SDValue &SBase,
2647 SDValue &SOffset, SDValue &CPol) const {
2648 bool ScaleOffset;
2649 if (!SelectSMRD(N, Addr, SBase, &SOffset, /* Offset */ nullptr,
2650 /* Imm32Only */ false, &ScaleOffset))
2651 return false;
2652
2653 CPol = CurDAG->getTargetConstant(ScaleOffset ? AMDGPU::CPol::SCAL : 0,
2654 SDLoc(N), MVT::i32);
2655 return true;
2656}
2657
2658bool AMDGPUDAGToDAGISel::SelectSMRDSgprImm(SDNode *N, SDValue Addr,
2659 SDValue &SBase, SDValue &SOffset,
2660 SDValue &Offset,
2661 SDValue &CPol) const {
2662 bool ScaleOffset;
2663 if (!SelectSMRD(N, Addr, SBase, &SOffset, &Offset, false, &ScaleOffset))
2664 return false;
2665
2666 CPol = CurDAG->getTargetConstant(ScaleOffset ? AMDGPU::CPol::SCAL : 0,
2667 SDLoc(N), MVT::i32);
2668 return true;
2669}
2670
2671bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm(SDValue N, SDValue &Offset) const {
2672 return SelectSMRDOffset(/* N */ nullptr, N, /* SOffset */ nullptr, &Offset,
2673 /* Imm32Only */ false, /* IsBuffer */ true);
2674}
2675
2676bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm32(SDValue N,
2677 SDValue &Offset) const {
2678 assert(Subtarget->getGeneration() == AMDGPUSubtarget::SEA_ISLANDS);
2679 return SelectSMRDOffset(/* N */ nullptr, N, /* SOffset */ nullptr, &Offset,
2680 /* Imm32Only */ true, /* IsBuffer */ true);
2681}
2682
2683bool AMDGPUDAGToDAGISel::SelectSMRDBufferSgprImm(SDValue N, SDValue &SOffset,
2684 SDValue &Offset) const {
2685 // Match the (soffset + offset) pair as a 32-bit register base and
2686 // an immediate offset.
2687 return N.getValueType() == MVT::i32 &&
2688 SelectSMRDBaseOffset(/* N */ nullptr, N, /* SBase */ SOffset,
2689 /* SOffset*/ nullptr, &Offset,
2690 /* Imm32Only */ false, /* IsBuffer */ true);
2691}
2692
2693bool AMDGPUDAGToDAGISel::SelectMOVRELOffset(SDValue Index,
2694 SDValue &Base,
2695 SDValue &Offset) const {
2696 SDLoc DL(Index);
2697
2698 if (CurDAG->isBaseWithConstantOffset(Index)) {
2699 SDValue N0 = Index.getOperand(0);
2700 SDValue N1 = Index.getOperand(1);
2701 ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
2702
2703 // (add n0, c0)
2704 // Don't peel off the offset (c0) if doing so could possibly lead
2705 // the base (n0) to be negative.
2706 // (or n0, |c0|) can never change a sign given isBaseWithConstantOffset.
2707 if (C1->getSExtValue() <= 0 || CurDAG->SignBitIsZero(N0) ||
2708 (Index->getOpcode() == ISD::OR && C1->getSExtValue() >= 0)) {
2709 Base = N0;
2710 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i32);
2711 return true;
2712 }
2713 }
2714
2715 if (isa<ConstantSDNode>(Index))
2716 return false;
2717
2718 Base = Index;
2719 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
2720 return true;
2721}
2722
2723SDNode *AMDGPUDAGToDAGISel::getBFE32(bool IsSigned, const SDLoc &DL,
2724 SDValue Val, uint32_t Offset,
2725 uint32_t Width) {
2726 if (Val->isDivergent()) {
2727 unsigned Opcode = IsSigned ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
2728 SDValue Off = CurDAG->getTargetConstant(Offset, DL, MVT::i32);
2729 SDValue W = CurDAG->getTargetConstant(Width, DL, MVT::i32);
2730
2731 return CurDAG->getMachineNode(Opcode, DL, MVT::i32, Val, Off, W);
2732 }
2733 unsigned Opcode = IsSigned ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
2734 // Transformation function, pack the offset and width of a BFE into
2735 // the format expected by the S_BFE_I32 / S_BFE_U32. In the second
2736 // source, bits [5:0] contain the offset and bits [22:16] the width.
2737 uint32_t PackedVal = Offset | (Width << 16);
2738 SDValue PackedConst = CurDAG->getTargetConstant(PackedVal, DL, MVT::i32);
2739
2740 return CurDAG->getMachineNode(Opcode, DL, MVT::i32, Val, PackedConst);
2741}
2742
2743void AMDGPUDAGToDAGISel::SelectS_BFEFromShifts(SDNode *N) {
2744 // "(a << b) srl c)" ---> "BFE_U32 a, (c-b), (32-c)
2745 // "(a << b) sra c)" ---> "BFE_I32 a, (c-b), (32-c)
2746 // Predicate: 0 < b <= c < 32
2747
2748 const SDValue &Shl = N->getOperand(0);
2749 ConstantSDNode *B = dyn_cast<ConstantSDNode>(Shl->getOperand(1));
2750 ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1));
2751
2752 if (B && C) {
2753 uint32_t BVal = B->getZExtValue();
2754 uint32_t CVal = C->getZExtValue();
2755
2756 if (0 < BVal && BVal <= CVal && CVal < 32) {
2757 bool Signed = N->getOpcode() == ISD::SRA;
2758 ReplaceNode(N, getBFE32(Signed, SDLoc(N), Shl.getOperand(0), CVal - BVal,
2759 32 - CVal));
2760 return;
2761 }
2762 }
2763 SelectCode(N);
2764}
2765
2766void AMDGPUDAGToDAGISel::SelectS_BFE(SDNode *N) {
2767 switch (N->getOpcode()) {
2768 case ISD::AND:
2769 if (N->getOperand(0).getOpcode() == ISD::SRL) {
2770 // "(a srl b) & mask" ---> "BFE_U32 a, b, popcount(mask)"
2771 // Predicate: isMask(mask)
2772 const SDValue &Srl = N->getOperand(0);
2773 ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(Srl.getOperand(1));
2774 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(N->getOperand(1));
2775
2776 if (Shift && Mask) {
2777 uint32_t ShiftVal = Shift->getZExtValue();
2778 uint32_t MaskVal = Mask->getZExtValue();
2779
2780 if (isMask_32(MaskVal)) {
2781 uint32_t WidthVal = llvm::popcount(MaskVal);
2782 ReplaceNode(N, getBFE32(false, SDLoc(N), Srl.getOperand(0), ShiftVal,
2783 WidthVal));
2784 return;
2785 }
2786 }
2787 }
2788 break;
2789 case ISD::SRL:
2790 if (N->getOperand(0).getOpcode() == ISD::AND) {
2791 // "(a & mask) srl b)" ---> "BFE_U32 a, b, popcount(mask >> b)"
2792 // Predicate: isMask(mask >> b)
2793 const SDValue &And = N->getOperand(0);
2794 ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(N->getOperand(1));
2795 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(And->getOperand(1));
2796
2797 if (Shift && Mask) {
2798 uint32_t ShiftVal = Shift->getZExtValue();
2799 uint32_t MaskVal = Mask->getZExtValue() >> ShiftVal;
2800
2801 if (isMask_32(MaskVal)) {
2802 uint32_t WidthVal = llvm::popcount(MaskVal);
2803 ReplaceNode(N, getBFE32(false, SDLoc(N), And.getOperand(0), ShiftVal,
2804 WidthVal));
2805 return;
2806 }
2807 }
2808 } else if (N->getOperand(0).getOpcode() == ISD::SHL) {
2809 SelectS_BFEFromShifts(N);
2810 return;
2811 }
2812 break;
2813 case ISD::SRA:
2814 if (N->getOperand(0).getOpcode() == ISD::SHL) {
2815 SelectS_BFEFromShifts(N);
2816 return;
2817 }
2818 break;
2819
2821 // sext_inreg (srl x, 16), i8 -> bfe_i32 x, 16, 8
2822 SDValue Src = N->getOperand(0);
2823 if (Src.getOpcode() != ISD::SRL)
2824 break;
2825
2826 const ConstantSDNode *Amt = dyn_cast<ConstantSDNode>(Src.getOperand(1));
2827 if (!Amt)
2828 break;
2829
2830 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
2831 ReplaceNode(N, getBFE32(true, SDLoc(N), Src.getOperand(0),
2832 Amt->getZExtValue(), Width));
2833 return;
2834 }
2835 }
2836
2837 SelectCode(N);
2838}
2839
2840bool AMDGPUDAGToDAGISel::isCBranchSCC(const SDNode *N) const {
2841 assert(N->getOpcode() == ISD::BRCOND);
2842 if (!N->hasOneUse())
2843 return false;
2844
2845 SDValue Cond = N->getOperand(1);
2846 if (Cond.getOpcode() == ISD::CopyToReg)
2847 Cond = Cond.getOperand(2);
2848
2849 if (Cond.getOpcode() != ISD::SETCC || !Cond.hasOneUse())
2850 return false;
2851
2852 MVT VT = Cond.getOperand(0).getSimpleValueType();
2853 if (VT == MVT::i32)
2854 return true;
2855
2856 if (VT == MVT::i64) {
2857 ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
2858 return (CC == ISD::SETEQ || CC == ISD::SETNE) &&
2859 Subtarget->hasScalarCompareEq64();
2860 }
2861
2862 if ((VT == MVT::f16 || VT == MVT::f32) && Subtarget->hasSALUFloatInsts())
2863 return true;
2864
2865 return false;
2866}
2867
2868static SDValue combineBallotPattern(SDValue VCMP, bool &Negate) {
2869 assert(VCMP->getOpcode() == AMDGPUISD::SETCC);
2870 // Special case for amdgcn.ballot:
2871 // %Cond = i1 (and/or combination of i1 ISD::SETCCs)
2872 // %VCMP = i(WaveSize) AMDGPUISD::SETCC (ext %Cond), 0, setne/seteq
2873 // =>
2874 // Use i1 %Cond value instead of i(WaveSize) %VCMP.
2875 // This is possible because divergent ISD::SETCC is selected as V_CMP and
2876 // Cond becomes a i(WaveSize) full mask value.
2877 // Note that ballot doesn't use SETEQ condition but its easy to support it
2878 // here for completeness, so in this case Negate is set true on return.
2879 auto VCMP_CC = cast<CondCodeSDNode>(VCMP.getOperand(2))->get();
2880 if ((VCMP_CC == ISD::SETEQ || VCMP_CC == ISD::SETNE) &&
2881 isNullConstant(VCMP.getOperand(1))) {
2882
2883 auto Cond = VCMP.getOperand(0);
2884 if (ISD::isExtOpcode(Cond->getOpcode())) // Skip extension.
2885 Cond = Cond.getOperand(0);
2886
2887 if (isBoolSGPR(Cond)) {
2888 Negate = VCMP_CC == ISD::SETEQ;
2889 return Cond;
2890 }
2891 }
2892 return SDValue();
2893}
2894
2895void AMDGPUDAGToDAGISel::SelectBRCOND(SDNode *N) {
2896 SDValue Cond = N->getOperand(1);
2897
2898 if (Cond.isUndef()) {
2899 CurDAG->SelectNodeTo(N, AMDGPU::SI_BR_UNDEF, MVT::Other,
2900 N->getOperand(2), N->getOperand(0));
2901 return;
2902 }
2903
2904 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
2905
2906 bool UseSCCBr = isCBranchSCC(N) && isUniformBr(N);
2907 bool AndExec = !UseSCCBr;
2908 bool Negate = false;
2909
2910 if (Cond.getOpcode() == ISD::SETCC &&
2911 Cond->getOperand(0)->getOpcode() == AMDGPUISD::SETCC) {
2912 SDValue VCMP = Cond->getOperand(0);
2913 auto CC = cast<CondCodeSDNode>(Cond->getOperand(2))->get();
2914 if ((CC == ISD::SETEQ || CC == ISD::SETNE) &&
2915 isNullConstant(Cond->getOperand(1)) &&
2916 // We may encounter ballot.i64 in wave32 mode on -O0.
2917 VCMP.getValueType().getSizeInBits() == Subtarget->getWavefrontSize()) {
2918 // %VCMP = i(WaveSize) AMDGPUISD::SETCC ...
2919 // %C = i1 ISD::SETCC %VCMP, 0, setne/seteq
2920 // BRCOND i1 %C, %BB
2921 // =>
2922 // %VCMP = i(WaveSize) AMDGPUISD::SETCC ...
2923 // VCC = COPY i(WaveSize) %VCMP
2924 // S_CBRANCH_VCCNZ/VCCZ %BB
2925 Negate = CC == ISD::SETEQ;
2926 bool NegatedBallot = false;
2927 if (auto BallotCond = combineBallotPattern(VCMP, NegatedBallot)) {
2928 Cond = BallotCond;
2929 UseSCCBr = !BallotCond->isDivergent();
2930 Negate = Negate ^ NegatedBallot;
2931 } else {
2932 // TODO: don't use SCC here assuming that AMDGPUISD::SETCC is always
2933 // selected as V_CMP, but this may change for uniform condition.
2934 Cond = VCMP;
2935 UseSCCBr = false;
2936 }
2937 }
2938 // Cond is either V_CMP resulted from AMDGPUISD::SETCC or a combination of
2939 // V_CMPs resulted from ballot or ballot has uniform condition and SCC is
2940 // used.
2941 AndExec = false;
2942 }
2943
2944 unsigned BrOp =
2945 UseSCCBr ? (Negate ? AMDGPU::S_CBRANCH_SCC0 : AMDGPU::S_CBRANCH_SCC1)
2946 : (Negate ? AMDGPU::S_CBRANCH_VCCZ : AMDGPU::S_CBRANCH_VCCNZ);
2947 Register CondReg = UseSCCBr ? AMDGPU::SCC : TRI->getVCC();
2948 SDLoc SL(N);
2949
2950 if (AndExec) {
2951 // This is the case that we are selecting to S_CBRANCH_VCCNZ. We have not
2952 // analyzed what generates the vcc value, so we do not know whether vcc
2953 // bits for disabled lanes are 0. Thus we need to mask out bits for
2954 // disabled lanes.
2955 //
2956 // For the case that we select S_CBRANCH_SCC1 and it gets
2957 // changed to S_CBRANCH_VCCNZ in SIFixSGPRCopies, SIFixSGPRCopies calls
2958 // SIInstrInfo::moveToVALU which inserts the S_AND).
2959 //
2960 // We could add an analysis of what generates the vcc value here and omit
2961 // the S_AND when is unnecessary. But it would be better to add a separate
2962 // pass after SIFixSGPRCopies to do the unnecessary S_AND removal, so it
2963 // catches both cases.
2964 Cond = SDValue(
2965 CurDAG->getMachineNode(
2966 Subtarget->isWave32() ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64, SL,
2967 MVT::i1,
2968 CurDAG->getRegister(Subtarget->isWave32() ? AMDGPU::EXEC_LO
2969 : AMDGPU::EXEC,
2970 MVT::i1),
2971 Cond),
2972 0);
2973 }
2974
2975 SDValue VCC = CurDAG->getCopyToReg(N->getOperand(0), SL, CondReg, Cond);
2976 CurDAG->SelectNodeTo(N, BrOp, MVT::Other,
2977 N->getOperand(2), // Basic Block
2978 VCC.getValue(0));
2979}
2980
2981void AMDGPUDAGToDAGISel::SelectFP_EXTEND(SDNode *N) {
2982 if (Subtarget->hasSALUFloatInsts() && N->getValueType(0) == MVT::f32 &&
2983 !N->isDivergent()) {
2984 SDValue Src = N->getOperand(0);
2985 if (Src.getValueType() == MVT::f16) {
2986 if (isExtractHiElt(Src, Src)) {
2987 CurDAG->SelectNodeTo(N, AMDGPU::S_CVT_HI_F32_F16, N->getVTList(),
2988 {Src});
2989 return;
2990 }
2991 }
2992 }
2993
2994 SelectCode(N);
2995}
2996
2997void AMDGPUDAGToDAGISel::SelectDSAppendConsume(SDNode *N, unsigned IntrID) {
2998 // The address is assumed to be uniform, so if it ends up in a VGPR, it will
2999 // be copied to an SGPR with readfirstlane.
3000 unsigned Opc = IntrID == Intrinsic::amdgcn_ds_append ?
3001 AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME;
3002
3003 SDValue Chain = N->getOperand(0);
3004 SDValue Ptr = N->getOperand(2);
3005 MemIntrinsicSDNode *M = cast<MemIntrinsicSDNode>(N);
3006 MachineMemOperand *MMO = M->getMemOperand();
3007 bool IsGDS = M->getAddressSpace() == AMDGPUAS::REGION_ADDRESS;
3008
3010 if (CurDAG->isBaseWithConstantOffset(Ptr)) {
3011 SDValue PtrBase = Ptr.getOperand(0);
3012 SDValue PtrOffset = Ptr.getOperand(1);
3013
3014 const APInt &OffsetVal = PtrOffset->getAsAPIntVal();
3015 if (isDSOffsetLegal(PtrBase, OffsetVal.getZExtValue())) {
3016 N = glueCopyToM0(N, PtrBase);
3017 Offset = CurDAG->getTargetConstant(OffsetVal, SDLoc(), MVT::i32);
3018 }
3019 }
3020
3021 if (!Offset) {
3022 N = glueCopyToM0(N, Ptr);
3023 Offset = CurDAG->getTargetConstant(0, SDLoc(), MVT::i32);
3024 }
3025
3026 SDValue Ops[] = {
3027 Offset,
3028 CurDAG->getTargetConstant(IsGDS, SDLoc(), MVT::i32),
3029 Chain,
3030 N->getOperand(N->getNumOperands() - 1) // New glue
3031 };
3032
3033 SDNode *Selected = CurDAG->SelectNodeTo(N, Opc, N->getVTList(), Ops);
3034 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Selected), {MMO});
3035}
3036
3037// We need to handle this here because tablegen doesn't support matching
3038// instructions with multiple outputs.
3039void AMDGPUDAGToDAGISel::SelectDSBvhStackIntrinsic(SDNode *N, unsigned IntrID) {
3040 unsigned Opc;
3041 switch (IntrID) {
3042 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
3043 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
3044 Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
3045 break;
3046 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
3047 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
3048 break;
3049 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
3050 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
3051 break;
3052 }
3053 SDValue Ops[] = {N->getOperand(2), N->getOperand(3), N->getOperand(4),
3054 N->getOperand(5), N->getOperand(0)};
3055
3056 MemIntrinsicSDNode *M = cast<MemIntrinsicSDNode>(N);
3057 MachineMemOperand *MMO = M->getMemOperand();
3058 SDNode *Selected = CurDAG->SelectNodeTo(N, Opc, N->getVTList(), Ops);
3059 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Selected), {MMO});
3060}
3061
3062void AMDGPUDAGToDAGISel::SelectTensorLoadStore(SDNode *N, unsigned IntrID) {
3063 bool IsLoad = IntrID == Intrinsic::amdgcn_tensor_load_to_lds;
3064 unsigned Opc =
3065 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3066
3067 SmallVector<SDValue, 7> TensorOps;
3068 // First two groups
3069 TensorOps.push_back(N->getOperand(2)); // D# group 0
3070 TensorOps.push_back(N->getOperand(3)); // D# group 1
3071
3072 // Use _D2 version if both group 2 and 3 are zero-initialized.
3073 SDValue Group2 = N->getOperand(4);
3074 SDValue Group3 = N->getOperand(5);
3075 if (ISD::isBuildVectorAllZeros(Group2.getNode()) &&
3077 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3078 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3079 } else { // Has at least 4 groups
3080 TensorOps.push_back(Group2); // D# group 2
3081 TensorOps.push_back(Group3); // D# group 3
3082 }
3083
3084 // TODO: Handle the fifth group: N->getOperand(6), which is silently ignored
3085 // for now because all existing targets only support up to 4 groups.
3086 TensorOps.push_back(CurDAG->getTargetConstant(0, SDLoc(N), MVT::i1)); // r128
3087 TensorOps.push_back(N->getOperand(7)); // cache policy
3088 TensorOps.push_back(N->getOperand(0)); // chain
3089
3090 (void)CurDAG->SelectNodeTo(N, Opc, MVT::Other, TensorOps);
3091}
3092
3093static unsigned gwsIntrinToOpcode(unsigned IntrID) {
3094 switch (IntrID) {
3095 case Intrinsic::amdgcn_ds_gws_init:
3096 return AMDGPU::DS_GWS_INIT;
3097 case Intrinsic::amdgcn_ds_gws_barrier:
3098 return AMDGPU::DS_GWS_BARRIER;
3099 case Intrinsic::amdgcn_ds_gws_sema_v:
3100 return AMDGPU::DS_GWS_SEMA_V;
3101 case Intrinsic::amdgcn_ds_gws_sema_br:
3102 return AMDGPU::DS_GWS_SEMA_BR;
3103 case Intrinsic::amdgcn_ds_gws_sema_p:
3104 return AMDGPU::DS_GWS_SEMA_P;
3105 case Intrinsic::amdgcn_ds_gws_sema_release_all:
3106 return AMDGPU::DS_GWS_SEMA_RELEASE_ALL;
3107 default:
3108 llvm_unreachable("not a gws intrinsic");
3109 }
3110}
3111
3112void AMDGPUDAGToDAGISel::SelectDS_GWS(SDNode *N, unsigned IntrID) {
3113 if (!Subtarget->hasGWS() ||
3114 (IntrID == Intrinsic::amdgcn_ds_gws_sema_release_all &&
3115 !Subtarget->hasGWSSemaReleaseAll())) {
3116 // Let this error.
3117 SelectCode(N);
3118 return;
3119 }
3120
3121 // Chain, intrinsic ID, vsrc, offset
3122 const bool HasVSrc = N->getNumOperands() == 4;
3123 assert(HasVSrc || N->getNumOperands() == 3);
3124
3125 SDLoc SL(N);
3126 SDValue BaseOffset = N->getOperand(HasVSrc ? 3 : 2);
3127 int ImmOffset = 0;
3128 MemIntrinsicSDNode *M = cast<MemIntrinsicSDNode>(N);
3129 MachineMemOperand *MMO = M->getMemOperand();
3130
3131 // Don't worry if the offset ends up in a VGPR. Only one lane will have
3132 // effect, so SIFixSGPRCopies will validly insert readfirstlane.
3133
3134 // The resource id offset is computed as (<isa opaque base> + M0[21:16] +
3135 // offset field) % 64. Some versions of the programming guide omit the m0
3136 // part, or claim it's from offset 0.
3137 if (ConstantSDNode *ConstOffset = dyn_cast<ConstantSDNode>(BaseOffset)) {
3138 // If we have a constant offset, try to use the 0 in m0 as the base.
3139 // TODO: Look into changing the default m0 initialization value. If the
3140 // default -1 only set the low 16-bits, we could leave it as-is and add 1 to
3141 // the immediate offset.
3142 glueCopyToM0(N, CurDAG->getTargetConstant(0, SL, MVT::i32));
3143 ImmOffset = ConstOffset->getZExtValue();
3144 } else {
3145 if (CurDAG->isBaseWithConstantOffset(BaseOffset)) {
3146 ImmOffset = BaseOffset.getConstantOperandVal(1);
3147 BaseOffset = BaseOffset.getOperand(0);
3148 }
3149
3150 // Prefer to do the shift in an SGPR since it should be possible to use m0
3151 // as the result directly. If it's already an SGPR, it will be eliminated
3152 // later.
3153 SDNode *SGPROffset
3154 = CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32,
3155 BaseOffset);
3156 // Shift to offset in m0
3157 SDNode *M0Base
3158 = CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32,
3159 SDValue(SGPROffset, 0),
3160 CurDAG->getTargetConstant(16, SL, MVT::i32));
3161 glueCopyToM0(N, SDValue(M0Base, 0));
3162 }
3163
3164 SDValue Chain = N->getOperand(0);
3165 SDValue OffsetField = CurDAG->getTargetConstant(ImmOffset, SL, MVT::i32);
3166
3167 const unsigned Opc = gwsIntrinToOpcode(IntrID);
3168
3169 const MCInstrDesc &InstrDesc = TII->get(Opc);
3170 int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
3171
3172 const TargetRegisterClass *DataRC = TII->getRegClass(InstrDesc, Data0Idx);
3173
3175 if (HasVSrc) {
3176 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
3177
3178 SDValue Data = N->getOperand(2);
3179 MVT DataVT = Data.getValueType().getSimpleVT();
3180 if (TRI->isTypeLegalForClass(*DataRC, DataVT)) {
3181 // Normal 32-bit case.
3182 Ops.push_back(N->getOperand(2));
3183 } else {
3184 // Operand is really 32-bits, but requires 64-bit alignment, so use the
3185 // even aligned 64-bit register class.
3186 const SDValue RegSeqOps[] = {
3187 CurDAG->getTargetConstant(DataRC->getID(), SL, MVT::i32), Data,
3188 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32),
3189 SDValue(
3190 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, SL, MVT::i32),
3191 0),
3192 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32)};
3193
3194 Ops.push_back(SDValue(CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
3195 SL, MVT::v2i32, RegSeqOps),
3196 0));
3197 }
3198 }
3199
3200 Ops.push_back(OffsetField);
3201 Ops.push_back(Chain);
3202
3203 SDNode *Selected = CurDAG->SelectNodeTo(N, Opc, N->getVTList(), Ops);
3204 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Selected), {MMO});
3205}
3206
3207void AMDGPUDAGToDAGISel::SelectInterpP1F16(SDNode *N) {
3208 if (Subtarget->getLDSBankCount() != 16) {
3209 // This is a single instruction with a pattern.
3210 SelectCode(N);
3211 return;
3212 }
3213
3214 SDLoc DL(N);
3215
3216 // This requires 2 instructions. It is possible to write a pattern to support
3217 // this, but the generated isel emitter doesn't correctly deal with multiple
3218 // output instructions using the same physical register input. The copy to m0
3219 // is incorrectly placed before the second instruction.
3220 //
3221 // TODO: Match source modifiers.
3222 //
3223 // def : Pat <
3224 // (int_amdgcn_interp_p1_f16
3225 // (VOP3Mods f32:$src0, i32:$src0_modifiers),
3226 // (i32 timm:$attrchan), (i32 timm:$attr),
3227 // (i1 timm:$high), M0),
3228 // (V_INTERP_P1LV_F16 $src0_modifiers, VGPR_32:$src0, timm:$attr,
3229 // timm:$attrchan, 0,
3230 // (V_INTERP_MOV_F32 2, timm:$attr, timm:$attrchan), timm:$high)> {
3231 // let Predicates = [has16BankLDS];
3232 // }
3233
3234 // 16 bank LDS
3235 SDValue ToM0 = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, AMDGPU::M0,
3236 N->getOperand(5), SDValue());
3237
3238 SDVTList VTs = CurDAG->getVTList(MVT::f32, MVT::Other);
3239
3240 SDNode *InterpMov =
3241 CurDAG->getMachineNode(AMDGPU::V_INTERP_MOV_F32, DL, VTs, {
3242 CurDAG->getTargetConstant(2, DL, MVT::i32), // P0
3243 N->getOperand(3), // Attr
3244 N->getOperand(2), // Attrchan
3245 ToM0.getValue(1) // In glue
3246 });
3247
3248 SDNode *InterpP1LV =
3249 CurDAG->getMachineNode(AMDGPU::V_INTERP_P1LV_F16, DL, MVT::f32, {
3250 CurDAG->getTargetConstant(0, DL, MVT::i32), // $src0_modifiers
3251 N->getOperand(1), // Src0
3252 N->getOperand(3), // Attr
3253 N->getOperand(2), // Attrchan
3254 CurDAG->getTargetConstant(0, DL, MVT::i32), // $src2_modifiers
3255 SDValue(InterpMov, 0), // Src2 - holds two f16 values selected by high
3256 N->getOperand(4), // high
3257 CurDAG->getTargetConstant(0, DL, MVT::i1), // $clamp
3258 CurDAG->getTargetConstant(0, DL, MVT::i32), // $omod
3259 SDValue(InterpMov, 1)
3260 });
3261
3262 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), SDValue(InterpP1LV, 0));
3263}
3264
3265void AMDGPUDAGToDAGISel::SelectINTRINSIC_W_CHAIN(SDNode *N) {
3266 unsigned IntrID = N->getConstantOperandVal(1);
3267 switch (IntrID) {
3268 case Intrinsic::amdgcn_ds_append:
3269 case Intrinsic::amdgcn_ds_consume: {
3270 if (N->getValueType(0) != MVT::i32)
3271 break;
3272 SelectDSAppendConsume(N, IntrID);
3273 return;
3274 }
3275 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
3276 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
3277 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
3278 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
3279 SelectDSBvhStackIntrinsic(N, IntrID);
3280 return;
3281 case Intrinsic::amdgcn_init_whole_wave:
3282 CurDAG->getMachineFunction()
3283 .getInfo<SIMachineFunctionInfo>()
3284 ->setInitWholeWave();
3285 break;
3286 }
3287
3288 SelectCode(N);
3289}
3290
3291void AMDGPUDAGToDAGISel::SelectINTRINSIC_WO_CHAIN(SDNode *N) {
3292 unsigned IntrID = N->getConstantOperandVal(0);
3293 unsigned Opcode = AMDGPU::INSTRUCTION_LIST_END;
3294 SDNode *ConvGlueNode = N->getGluedNode();
3295 if (ConvGlueNode) {
3296 // FIXME: Possibly iterate over multiple glue nodes?
3297 assert(ConvGlueNode->getOpcode() == ISD::CONVERGENCECTRL_GLUE);
3298 ConvGlueNode = ConvGlueNode->getOperand(0).getNode();
3299 ConvGlueNode =
3300 CurDAG->getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, {},
3301 MVT::Glue, SDValue(ConvGlueNode, 0));
3302 } else {
3303 ConvGlueNode = nullptr;
3304 }
3305 switch (IntrID) {
3306 case Intrinsic::amdgcn_wqm:
3307 Opcode = AMDGPU::WQM;
3308 break;
3309 case Intrinsic::amdgcn_softwqm:
3310 Opcode = AMDGPU::SOFT_WQM;
3311 break;
3312 case Intrinsic::amdgcn_wwm:
3313 case Intrinsic::amdgcn_strict_wwm:
3314 Opcode = AMDGPU::STRICT_WWM;
3315 break;
3316 case Intrinsic::amdgcn_strict_wqm:
3317 Opcode = AMDGPU::STRICT_WQM;
3318 break;
3319 case Intrinsic::amdgcn_interp_p1_f16:
3320 SelectInterpP1F16(N);
3321 return;
3322 case Intrinsic::amdgcn_permlane16_swap:
3323 case Intrinsic::amdgcn_permlane32_swap: {
3324 if ((IntrID == Intrinsic::amdgcn_permlane16_swap &&
3325 !Subtarget->hasPermlane16Swap()) ||
3326 (IntrID == Intrinsic::amdgcn_permlane32_swap &&
3327 !Subtarget->hasPermlane32Swap())) {
3328 SelectCode(N); // Hit the default error
3329 return;
3330 }
3331
3332 Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
3333 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
3334 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
3335
3336 SmallVector<SDValue, 4> NewOps(N->op_begin() + 1, N->op_end());
3337 if (ConvGlueNode)
3338 NewOps.push_back(SDValue(ConvGlueNode, 0));
3339
3340 bool FI = N->getConstantOperandVal(3);
3341 NewOps[2] = CurDAG->getTargetConstant(
3342 FI ? AMDGPU::DPP::DPP_FI_1 : AMDGPU::DPP::DPP_FI_0, SDLoc(), MVT::i32);
3343
3344 CurDAG->SelectNodeTo(N, Opcode, N->getVTList(), NewOps);
3345 return;
3346 }
3347 default:
3348 SelectCode(N);
3349 break;
3350 }
3351
3352 if (Opcode != AMDGPU::INSTRUCTION_LIST_END) {
3353 SDValue Src = N->getOperand(1);
3354 CurDAG->SelectNodeTo(N, Opcode, N->getVTList(), {Src});
3355 }
3356
3357 if (ConvGlueNode) {
3358 SmallVector<SDValue, 4> NewOps(N->ops());
3359 NewOps.push_back(SDValue(ConvGlueNode, 0));
3360 CurDAG->MorphNodeTo(N, N->getOpcode(), N->getVTList(), NewOps);
3361 }
3362}
3363
3364void AMDGPUDAGToDAGISel::SelectINTRINSIC_VOID(SDNode *N) {
3365 unsigned IntrID = N->getConstantOperandVal(1);
3366 switch (IntrID) {
3367 case Intrinsic::amdgcn_ds_gws_init:
3368 case Intrinsic::amdgcn_ds_gws_barrier:
3369 case Intrinsic::amdgcn_ds_gws_sema_v:
3370 case Intrinsic::amdgcn_ds_gws_sema_br:
3371 case Intrinsic::amdgcn_ds_gws_sema_p:
3372 case Intrinsic::amdgcn_ds_gws_sema_release_all:
3373 SelectDS_GWS(N, IntrID);
3374 return;
3375 case Intrinsic::amdgcn_tensor_load_to_lds:
3376 case Intrinsic::amdgcn_tensor_store_from_lds:
3377 SelectTensorLoadStore(N, IntrID);
3378 return;
3379 default:
3380 break;
3381 }
3382
3383 SelectCode(N);
3384}
3385
3386void AMDGPUDAGToDAGISel::SelectWAVE_ADDRESS(SDNode *N) {
3387 SDValue Log2WaveSize =
3388 CurDAG->getTargetConstant(Subtarget->getWavefrontSizeLog2(), SDLoc(N), MVT::i32);
3389 CurDAG->SelectNodeTo(N, AMDGPU::S_LSHR_B32, N->getVTList(),
3390 {N->getOperand(0), Log2WaveSize});
3391}
3392
3393void AMDGPUDAGToDAGISel::SelectSTACKRESTORE(SDNode *N) {
3394 SDValue SrcVal = N->getOperand(1);
3395 if (SrcVal.getValueType() != MVT::i32) {
3396 SelectCode(N); // Emit default error
3397 return;
3398 }
3399
3400 SDValue CopyVal;
3401 Register SP = TLI->getStackPointerRegisterToSaveRestore();
3402 SDLoc SL(N);
3403
3404 if (SrcVal.getOpcode() == AMDGPUISD::WAVE_ADDRESS) {
3405 CopyVal = SrcVal.getOperand(0);
3406 } else {
3407 SDValue Log2WaveSize = CurDAG->getTargetConstant(
3408 Subtarget->getWavefrontSizeLog2(), SL, MVT::i32);
3409
3410 if (N->isDivergent()) {
3411 SrcVal = SDValue(CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL,
3412 MVT::i32, SrcVal),
3413 0);
3414 }
3415
3416 CopyVal = SDValue(CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32,
3417 {SrcVal, Log2WaveSize}),
3418 0);
3419 }
3420
3421 SDValue CopyToSP = CurDAG->getCopyToReg(N->getOperand(0), SL, SP, CopyVal);
3422 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), CopyToSP);
3423}
3424
3425bool AMDGPUDAGToDAGISel::SelectVOP3ModsImpl(SDValue In, SDValue &Src,
3426 unsigned &Mods,
3427 bool IsCanonicalizing,
3428 bool AllowAbs) const {
3429 Mods = SISrcMods::NONE;
3430 Src = In;
3431
3432 if (Src.getOpcode() == ISD::FNEG) {
3433 Mods |= SISrcMods::NEG;
3434 Src = Src.getOperand(0);
3435 } else if (Src.getOpcode() == ISD::FSUB && IsCanonicalizing) {
3436 // Fold fsub [+-]0 into fneg. This may not have folded depending on the
3437 // denormal mode, but we're implicitly canonicalizing in a source operand.
3438 auto *LHS = dyn_cast<ConstantFPSDNode>(Src.getOperand(0));
3439 if (LHS && LHS->isZero()) {
3440 Mods |= SISrcMods::NEG;
3441 Src = Src.getOperand(1);
3442 }
3443 }
3444
3445 if (AllowAbs && Src.getOpcode() == ISD::FABS) {
3446 Mods |= SISrcMods::ABS;
3447 Src = Src.getOperand(0);
3448 }
3449
3450 if (Mods != SISrcMods::NONE)
3451 return true;
3452
3453 // Convert various sign-bit masks on integers to src mods. Currently disabled
3454 // for 16-bit types as the codegen replaces the operand without adding a
3455 // srcmod. This is intentionally finding the cases where we are performing
3456 // float neg and abs on int types, the goal is not to obtain two's complement
3457 // neg or abs. Limit converison to select operands via the nonCanonalizing
3458 // pattern.
3459 // TODO: Add 16-bit support.
3460 if (IsCanonicalizing)
3461 return true;
3462
3463 // v2i32 xor/or/and are legal. A vselect using these instructions as operands
3464 // is scalarised into two selects with EXTRACT_VECTOR_ELT operands. Peek
3465 // through the extract to the bitwise op.
3466 SDValue PeekSrc =
3467 Src->getOpcode() == ISD::EXTRACT_VECTOR_ELT ? Src->getOperand(0) : Src;
3468 // Convert various sign-bit masks to src mods. Currently disabled for 16-bit
3469 // types as the codegen replaces the operand without adding a srcmod.
3470 // This is intentionally finding the cases where we are performing float neg
3471 // and abs on int types, the goal is not to obtain two's complement neg or
3472 // abs.
3473 // TODO: Add 16-bit support.
3474 unsigned Opc = PeekSrc.getOpcode();
3475 EVT VT = Src.getValueType();
3476 if ((Opc != ISD::AND && Opc != ISD::OR && Opc != ISD::XOR) ||
3477 (VT != MVT::i32 && VT != MVT::v2i32 && VT != MVT::i64))
3478 return true;
3479
3480 ConstantSDNode *CRHS = isConstOrConstSplat(PeekSrc->getOperand(1));
3481 if (!CRHS)
3482 return true;
3483
3484 auto ReplaceSrc = [&]() -> SDValue {
3485 if (Src->getOpcode() != ISD::EXTRACT_VECTOR_ELT)
3486 return Src.getOperand(0);
3487
3488 SDValue LHS = PeekSrc->getOperand(0);
3489 SDValue Index = Src->getOperand(1);
3490 return CurDAG->getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(Src),
3491 Src.getValueType(), LHS, Index);
3492 };
3493
3494 // Recognise Srcmods:
3495 // (xor a, 0x80000000) or v2i32 (xor a, {0x80000000,0x80000000}) as NEG.
3496 // (and a, 0x7fffffff) or v2i32 (and a, {0x7fffffff,0x7fffffff}) as ABS.
3497 // (or a, 0x80000000) or v2i32 (or a, {0x80000000,0x80000000}) as NEG+ABS
3498 // SrcModifiers.
3499 if (Opc == ISD::XOR && CRHS->getAPIntValue().isSignMask()) {
3500 Mods |= SISrcMods::NEG;
3501 Src = ReplaceSrc();
3502 } else if (Opc == ISD::AND && AllowAbs &&
3503 CRHS->getAPIntValue().isMaxSignedValue()) {
3504 Mods |= SISrcMods::ABS;
3505 Src = ReplaceSrc();
3506 } else if (Opc == ISD::OR && AllowAbs && CRHS->getAPIntValue().isSignMask()) {
3508 Src = ReplaceSrc();
3509 }
3510
3511 return true;
3512}
3513
3514bool AMDGPUDAGToDAGISel::SelectVOP3Mods(SDValue In, SDValue &Src,
3515 SDValue &SrcMods) const {
3516 unsigned Mods;
3517 if (SelectVOP3ModsImpl(In, Src, Mods, /*IsCanonicalizing=*/true,
3518 /*AllowAbs=*/true)) {
3519 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3520 return true;
3521 }
3522
3523 return false;
3524}
3525
3526bool AMDGPUDAGToDAGISel::SelectVOP3ModsNonCanonicalizing(
3527 SDValue In, SDValue &Src, SDValue &SrcMods) const {
3528 unsigned Mods;
3529 if (SelectVOP3ModsImpl(In, Src, Mods, /*IsCanonicalizing=*/false,
3530 /*AllowAbs=*/true)) {
3531 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3532 return true;
3533 }
3534
3535 return false;
3536}
3537
3538bool AMDGPUDAGToDAGISel::SelectVOP3BMods(SDValue In, SDValue &Src,
3539 SDValue &SrcMods) const {
3540 unsigned Mods;
3541 if (SelectVOP3ModsImpl(In, Src, Mods,
3542 /*IsCanonicalizing=*/true,
3543 /*AllowAbs=*/false)) {
3544 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3545 return true;
3546 }
3547
3548 return false;
3549}
3550
3551bool AMDGPUDAGToDAGISel::SelectVOP3NoMods(SDValue In, SDValue &Src) const {
3552 if (In.getOpcode() == ISD::FABS || In.getOpcode() == ISD::FNEG)
3553 return false;
3554
3555 Src = In;
3556 return true;
3557}
3558
3559bool AMDGPUDAGToDAGISel::SelectVINTERPModsImpl(SDValue In, SDValue &Src,
3560 SDValue &SrcMods,
3561 bool OpSel) const {
3562 unsigned Mods;
3563 if (SelectVOP3ModsImpl(In, Src, Mods,
3564 /*IsCanonicalizing=*/true,
3565 /*AllowAbs=*/false)) {
3566 if (OpSel)
3567 Mods |= SISrcMods::OP_SEL_0;
3568 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3569 return true;
3570 }
3571
3572 return false;
3573}
3574
3575bool AMDGPUDAGToDAGISel::SelectVINTERPMods(SDValue In, SDValue &Src,
3576 SDValue &SrcMods) const {
3577 return SelectVINTERPModsImpl(In, Src, SrcMods, /* OpSel */ false);
3578}
3579
3580bool AMDGPUDAGToDAGISel::SelectVINTERPModsHi(SDValue In, SDValue &Src,
3581 SDValue &SrcMods) const {
3582 return SelectVINTERPModsImpl(In, Src, SrcMods, /* OpSel */ true);
3583}
3584
3585bool AMDGPUDAGToDAGISel::SelectVOP3Mods0(SDValue In, SDValue &Src,
3586 SDValue &SrcMods, SDValue &Clamp,
3587 SDValue &Omod) const {
3588 SDLoc DL(In);
3589 Clamp = CurDAG->getTargetConstant(0, DL, MVT::i1);
3590 Omod = CurDAG->getTargetConstant(0, DL, MVT::i1);
3591
3592 return SelectVOP3Mods(In, Src, SrcMods);
3593}
3594
3595bool AMDGPUDAGToDAGISel::SelectVOP3BMods0(SDValue In, SDValue &Src,
3596 SDValue &SrcMods, SDValue &Clamp,
3597 SDValue &Omod) const {
3598 SDLoc DL(In);
3599 Clamp = CurDAG->getTargetConstant(0, DL, MVT::i1);
3600 Omod = CurDAG->getTargetConstant(0, DL, MVT::i1);
3601
3602 return SelectVOP3BMods(In, Src, SrcMods);
3603}
3604
3605bool AMDGPUDAGToDAGISel::SelectVOP3OMods(SDValue In, SDValue &Src,
3606 SDValue &Clamp, SDValue &Omod) const {
3607 Src = In;
3608
3609 SDLoc DL(In);
3610 Clamp = CurDAG->getTargetConstant(0, DL, MVT::i1);
3611 Omod = CurDAG->getTargetConstant(0, DL, MVT::i1);
3612
3613 return true;
3614}
3615
3616bool AMDGPUDAGToDAGISel::SelectVOP3PMods(SDValue In, SDValue &Src,
3617 SDValue &SrcMods, bool IsDOT) const {
3618 unsigned Mods = SISrcMods::NONE;
3619 Src = In;
3620
3621 // TODO: Handle G_FSUB 0 as fneg
3622 if (Src.getOpcode() == ISD::FNEG) {
3624 Src = Src.getOperand(0);
3625 }
3626
3627 // 64-bit VOP3P instructions do not have OPSEL or ABS.
3628 bool HasOpSel = Src.getValueSizeInBits() != 128;
3629
3630 if (Src.getOpcode() == ISD::BUILD_VECTOR && Src.getNumOperands() == 2 &&
3631 (!IsDOT || !Subtarget->hasDOTOpSelHazard())) {
3632 unsigned VecMods = Mods;
3633
3634 SDValue Lo = stripBitcast(Src.getOperand(0));
3635 SDValue Hi = stripBitcast(Src.getOperand(1));
3636
3637 if (Lo.getOpcode() == ISD::FNEG) {
3638 Lo = stripBitcast(Lo.getOperand(0));
3639 Mods ^= SISrcMods::NEG;
3640 }
3641
3642 if (Hi.getOpcode() == ISD::FNEG) {
3643 Hi = stripBitcast(Hi.getOperand(0));
3644 Mods ^= SISrcMods::NEG_HI;
3645 }
3646
3647 if (HasOpSel) {
3648 if (isExtractHiElt(Lo, Lo))
3649 Mods |= SISrcMods::OP_SEL_0;
3650
3651 if (isExtractHiElt(Hi, Hi))
3652 Mods |= SISrcMods::OP_SEL_1;
3653 }
3654
3655 unsigned VecSize = Src.getValueSizeInBits();
3656 Lo = stripExtractLoElt(Lo);
3657 Hi = stripExtractLoElt(Hi);
3658
3659 if (Lo.getValueSizeInBits() > VecSize) {
3660 Lo = CurDAG->getTargetExtractSubreg(
3661 (VecSize > 32) ? AMDGPU::sub0_sub1 : AMDGPU::sub0, SDLoc(In),
3662 MVT::getIntegerVT(VecSize), Lo);
3663 }
3664
3665 if (Hi.getValueSizeInBits() > VecSize) {
3666 Hi = CurDAG->getTargetExtractSubreg(
3667 (VecSize > 32) ? AMDGPU::sub0_sub1 : AMDGPU::sub0, SDLoc(In),
3668 MVT::getIntegerVT(VecSize), Hi);
3669 }
3670
3671 assert(Lo.getValueSizeInBits() <= VecSize &&
3672 Hi.getValueSizeInBits() <= VecSize);
3673
3674 if (Lo == Hi && !isInlineImmediate(Lo.getNode())) {
3675 // Really a scalar input. Just select from the low half of the register to
3676 // avoid packing.
3677
3678 if (VecSize == Lo.getValueSizeInBits()) {
3679 Src = Lo;
3680 } else if (VecSize == 32) {
3681 Src = createVOP3PSrc32FromLo16(Lo, Src, CurDAG, Subtarget);
3682 } else {
3683 assert((Lo.getValueSizeInBits() == 32 && VecSize == 64) ||
3684 (Lo.getValueSizeInBits() == 64 && VecSize == 128));
3685
3686 SDLoc SL(In);
3688 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, SL,
3689 Lo.getValueType()), 0);
3690 const SIRegisterInfo *TRI = Subtarget->getRegisterInfo();
3691 // <2 x 64> instructions do not have OPSEL and also replicate low 64
3692 // bits of a scalar input into high 64 bits. Use VGPRs in this case.
3693 // TODO: This fact can be exploited but we need to set proper OPSEL for
3694 // codegen folding purposes. It will not affect a final instruction.
3695 auto RC = Lo->isDivergent() ? TRI->getVGPRClassForBitWidth(VecSize)
3696 : TRI->getSGPRClassForBitWidth(VecSize);
3697 unsigned NumRegs = Lo.getValueSizeInBits() == 32 ? 1 : 2;
3698 const SDValue Ops[] = {
3699 CurDAG->getTargetConstant(RC->getID(), SL, MVT::i32), Lo,
3700 CurDAG->getTargetConstant(TRI->getSubRegFromChannel(0, NumRegs), SL,
3701 MVT::i32),
3702 (!HasOpSel && Lo->isDivergent()) ? Lo : Undef,
3703 CurDAG->getTargetConstant(
3704 TRI->getSubRegFromChannel(NumRegs, NumRegs), SL, MVT::i32)};
3705
3706 Src = SDValue(CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, SL,
3707 Src.getValueType(), Ops), 0);
3708 }
3709 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3710 return true;
3711 }
3712
3713 if (VecSize == 64 && Lo == Hi && isa<ConstantFPSDNode>(Lo)) {
3714 uint64_t Lit = cast<ConstantFPSDNode>(Lo)->getValueAPF()
3715 .bitcastToAPInt().getZExtValue();
3716 if (AMDGPU::isInlinableLiteral32(Lit, Subtarget->hasInv2PiInlineImm())) {
3717 Src = CurDAG->getTargetConstant(Lit, SDLoc(In), MVT::i64);
3718 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3719 return true;
3720 }
3721 }
3722
3723 Mods = VecMods;
3724 } else if (Src.getOpcode() == ISD::VECTOR_SHUFFLE &&
3725 Src.getNumOperands() == 2) {
3726
3727 // TODO: We should repeat the build_vector source check above for the
3728 // vector_shuffle for negates and casts of individual elements.
3729
3730 assert(Src.getValueSizeInBits() != 128 &&
3731 "<2 x 64> VECTOR_SHUFFLE should not be legal.");
3732
3733 auto *SVN = cast<ShuffleVectorSDNode>(Src);
3734 ArrayRef<int> Mask = SVN->getMask();
3735
3736 if (Mask[0] < 2 && Mask[1] < 2) {
3737 // src1 should be undef.
3738 SDValue ShuffleSrc = SVN->getOperand(0);
3739
3740 if (ShuffleSrc.getOpcode() == ISD::FNEG) {
3741 ShuffleSrc = ShuffleSrc.getOperand(0);
3743 }
3744
3745 if (Mask[0] == 1)
3746 Mods |= SISrcMods::OP_SEL_0;
3747 if (Mask[1] == 1)
3748 Mods |= SISrcMods::OP_SEL_1;
3749
3750 Src = ShuffleSrc;
3751 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3752 return true;
3753 }
3754 }
3755
3756 // Packed instructions do not have abs modifiers.
3757 Mods |= SISrcMods::OP_SEL_1;
3758
3759 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3760 return true;
3761}
3762
3763bool AMDGPUDAGToDAGISel::SelectVOP3PModsDOT(SDValue In, SDValue &Src,
3764 SDValue &SrcMods) const {
3765 return SelectVOP3PMods(In, Src, SrcMods, true);
3766}
3767
3768bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsDOT(SDValue In, SDValue &Src) const {
3769 SDValue SrcTmp, SrcModsTmp;
3770 SelectVOP3PMods(In, SrcTmp, SrcModsTmp, true);
3771 if (cast<ConstantSDNode>(SrcModsTmp)->getZExtValue() == SISrcMods::OP_SEL_1) {
3772 Src = SrcTmp;
3773 return true;
3774 }
3775
3776 return false;
3777}
3778
3779bool AMDGPUDAGToDAGISel::SelectVOP3PModsF32(SDValue In, SDValue &Src,
3780 SDValue &SrcMods) const {
3781 SelectVOP3Mods(In, Src, SrcMods);
3782 unsigned Mods = SISrcMods::OP_SEL_1;
3783 Mods |= cast<ConstantSDNode>(SrcMods)->getZExtValue();
3784 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3785 return true;
3786}
3787
3788bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsF32(SDValue In, SDValue &Src) const {
3789 SDValue SrcTmp, SrcModsTmp;
3790 SelectVOP3PModsF32(In, SrcTmp, SrcModsTmp);
3791 if (cast<ConstantSDNode>(SrcModsTmp)->getZExtValue() == SISrcMods::OP_SEL_1) {
3792 Src = SrcTmp;
3793 return true;
3794 }
3795
3796 return false;
3797}
3798
3799bool AMDGPUDAGToDAGISel::SelectWMMAOpSelVOP3PMods(SDValue In,
3800 SDValue &Src) const {
3801 const ConstantSDNode *C = cast<ConstantSDNode>(In);
3802 assert(C->getAPIntValue().getBitWidth() == 1 && "expected i1 value");
3803
3804 unsigned Mods = SISrcMods::OP_SEL_1;
3805 unsigned SrcVal = C->getZExtValue();
3806 if (SrcVal == 1)
3807 Mods |= SISrcMods::OP_SEL_0;
3808
3809 Src = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3810 return true;
3811}
3812
3814AMDGPUDAGToDAGISel::buildRegSequence32(SmallVectorImpl<SDValue> &Elts,
3815 const SDLoc &DL) const {
3816 unsigned DstRegClass;
3817 EVT DstTy;
3818 switch (Elts.size()) {
3819 case 8:
3820 DstRegClass = AMDGPU::VReg_256RegClassID;
3821 DstTy = MVT::v8i32;
3822 break;
3823 case 4:
3824 DstRegClass = AMDGPU::VReg_128RegClassID;
3825 DstTy = MVT::v4i32;
3826 break;
3827 case 2:
3828 DstRegClass = AMDGPU::VReg_64RegClassID;
3829 DstTy = MVT::v2i32;
3830 break;
3831 default:
3832 llvm_unreachable("unhandled Reg sequence size");
3833 }
3834
3836 Ops.push_back(CurDAG->getTargetConstant(DstRegClass, DL, MVT::i32));
3837 for (unsigned i = 0; i < Elts.size(); ++i) {
3838 Ops.push_back(Elts[i]);
3839 Ops.push_back(CurDAG->getTargetConstant(
3841 }
3842 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, DstTy, Ops);
3843}
3844
3846AMDGPUDAGToDAGISel::buildRegSequence16(SmallVectorImpl<SDValue> &Elts,
3847 const SDLoc &DL) const {
3848 SmallVector<SDValue, 8> PackedElts;
3849 assert("unhandled Reg sequence size" &&
3850 (Elts.size() == 8 || Elts.size() == 16));
3851
3852 // Pack 16-bit elements in pairs into 32-bit register. If both elements are
3853 // unpacked from 32-bit source use it, otherwise pack them using v_perm.
3854 for (unsigned i = 0; i < Elts.size(); i += 2) {
3855 SDValue LoSrc = stripExtractLoElt(stripBitcast(Elts[i]));
3856 SDValue HiSrc;
3857 if (isExtractHiElt(Elts[i + 1], HiSrc) && LoSrc == HiSrc) {
3858 PackedElts.push_back(HiSrc);
3859 } else {
3860 if (Subtarget->useRealTrue16Insts()) {
3861 // FIXME-TRUE16. For now pack VGPR_32 for 16-bit source before
3862 // passing to v_perm_b32. Eventually we should use replace v_perm_b32
3863 // by reg_sequence.
3865 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::i16),
3866 0);
3867 Elts[i] =
3868 emitRegSequence(*CurDAG, AMDGPU::VGPR_32RegClassID, MVT::i32,
3869 {Elts[i], Undef}, {AMDGPU::lo16, AMDGPU::hi16}, DL);
3870 Elts[i + 1] = emitRegSequence(*CurDAG, AMDGPU::VGPR_32RegClassID,
3871 MVT::i32, {Elts[i + 1], Undef},
3872 {AMDGPU::lo16, AMDGPU::hi16}, DL);
3873 }
3874 SDValue PackLoLo = CurDAG->getTargetConstant(0x05040100, DL, MVT::i32);
3875 MachineSDNode *Packed =
3876 CurDAG->getMachineNode(AMDGPU::V_PERM_B32_e64, DL, MVT::i32,
3877 {Elts[i + 1], Elts[i], PackLoLo});
3878 PackedElts.push_back(SDValue(Packed, 0));
3879 }
3880 }
3881 return buildRegSequence32(PackedElts, DL);
3882}
3883
3885AMDGPUDAGToDAGISel::buildRegSequence(SmallVectorImpl<SDValue> &Elts,
3886 const SDLoc &DL,
3887 unsigned ElementSize) const {
3888 if (ElementSize == 16)
3889 return buildRegSequence16(Elts, DL);
3890 if (ElementSize == 32)
3891 return buildRegSequence32(Elts, DL);
3892 llvm_unreachable("Unhandled element size");
3893}
3894
3895void AMDGPUDAGToDAGISel::selectWMMAModsNegAbs(unsigned ModOpcode,
3896 unsigned &Mods,
3898 SDValue &Src, const SDLoc &DL,
3899 unsigned ElementSize) const {
3900 if (ModOpcode == ISD::FNEG) {
3901 Mods |= SISrcMods::NEG;
3902 // Check if all elements also have abs modifier
3903 SmallVector<SDValue, 8> NegAbsElts;
3904 for (auto El : Elts) {
3905 if (El.getOpcode() != ISD::FABS)
3906 break;
3907 NegAbsElts.push_back(El->getOperand(0));
3908 }
3909 if (Elts.size() != NegAbsElts.size()) {
3910 // Neg
3911 Src = SDValue(buildRegSequence(Elts, DL, ElementSize), 0);
3912 } else {
3913 // Neg and Abs
3914 Mods |= SISrcMods::NEG_HI;
3915 Src = SDValue(buildRegSequence(NegAbsElts, DL, ElementSize), 0);
3916 }
3917 } else {
3918 assert(ModOpcode == ISD::FABS);
3919 // Abs
3920 Mods |= SISrcMods::NEG_HI;
3921 Src = SDValue(buildRegSequence(Elts, DL, ElementSize), 0);
3922 }
3923}
3924
3925// Check all f16 elements for modifiers while looking through b32 and v2b16
3926// build vector, stop if element does not satisfy ModifierCheck.
3927static void
3929 std::function<bool(SDValue)> ModifierCheck) {
3930 for (unsigned i = 0; i < BV->getNumOperands(); ++i) {
3931 if (auto *F16Pair =
3932 dyn_cast<BuildVectorSDNode>(stripBitcast(BV->getOperand(i)))) {
3933 for (unsigned i = 0; i < F16Pair->getNumOperands(); ++i) {
3934 SDValue ElF16 = stripBitcast(F16Pair->getOperand(i));
3935 if (!ModifierCheck(ElF16))
3936 break;
3937 }
3938 }
3939 }
3940}
3941
3942bool AMDGPUDAGToDAGISel::SelectWMMAModsF16Neg(SDValue In, SDValue &Src,
3943 SDValue &SrcMods) const {
3944 Src = In;
3945 unsigned Mods = SISrcMods::OP_SEL_1;
3946
3947 // mods are on f16 elements
3948 if (auto *BV = dyn_cast<BuildVectorSDNode>(stripBitcast(In))) {
3950
3951 checkWMMAElementsModifiersF16(BV, [&](SDValue Element) -> bool {
3952 if (Element.getOpcode() != ISD::FNEG)
3953 return false;
3954 EltsF16.push_back(Element.getOperand(0));
3955 return true;
3956 });
3957
3958 // All elements have neg modifier
3959 if (BV->getNumOperands() * 2 == EltsF16.size()) {
3960 Src = SDValue(buildRegSequence16(EltsF16, SDLoc(In)), 0);
3961 Mods |= SISrcMods::NEG;
3962 Mods |= SISrcMods::NEG_HI;
3963 }
3964 }
3965
3966 // mods are on v2f16 elements
3967 if (auto *BV = dyn_cast<BuildVectorSDNode>(stripBitcast(In))) {
3968 SmallVector<SDValue, 8> EltsV2F16;
3969 for (unsigned i = 0; i < BV->getNumOperands(); ++i) {
3970 SDValue ElV2f16 = stripBitcast(BV->getOperand(i));
3971 // Based on first element decide which mod we match, neg or abs
3972 if (ElV2f16.getOpcode() != ISD::FNEG)
3973 break;
3974 EltsV2F16.push_back(ElV2f16.getOperand(0));
3975 }
3976
3977 // All pairs of elements have neg modifier
3978 if (BV->getNumOperands() == EltsV2F16.size()) {
3979 Src = SDValue(buildRegSequence32(EltsV2F16, SDLoc(In)), 0);
3980 Mods |= SISrcMods::NEG;
3981 Mods |= SISrcMods::NEG_HI;
3982 }
3983 }
3984
3985 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3986 return true;
3987}
3988
3989bool AMDGPUDAGToDAGISel::SelectWMMAModsF16NegAbs(SDValue In, SDValue &Src,
3990 SDValue &SrcMods) const {
3991 Src = In;
3992 unsigned Mods = SISrcMods::OP_SEL_1;
3993 unsigned ModOpcode;
3994
3995 // mods are on f16 elements
3996 if (auto *BV = dyn_cast<BuildVectorSDNode>(stripBitcast(In))) {
3998 checkWMMAElementsModifiersF16(BV, [&](SDValue ElF16) -> bool {
3999 // Based on first element decide which mod we match, neg or abs
4000 if (EltsF16.empty())
4001 ModOpcode = (ElF16.getOpcode() == ISD::FNEG) ? ISD::FNEG : ISD::FABS;
4002 if (ElF16.getOpcode() != ModOpcode)
4003 return false;
4004 EltsF16.push_back(ElF16.getOperand(0));
4005 return true;
4006 });
4007
4008 // All elements have ModOpcode modifier
4009 if (BV->getNumOperands() * 2 == EltsF16.size())
4010 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF16, Src, SDLoc(In), 16);
4011 }
4012
4013 // mods are on v2f16 elements
4014 if (auto *BV = dyn_cast<BuildVectorSDNode>(stripBitcast(In))) {
4015 SmallVector<SDValue, 8> EltsV2F16;
4016
4017 for (unsigned i = 0; i < BV->getNumOperands(); ++i) {
4018 SDValue ElV2f16 = stripBitcast(BV->getOperand(i));
4019 // Based on first element decide which mod we match, neg or abs
4020 if (EltsV2F16.empty())
4021 ModOpcode = (ElV2f16.getOpcode() == ISD::FNEG) ? ISD::FNEG : ISD::FABS;
4022 if (ElV2f16->getOpcode() != ModOpcode)
4023 break;
4024 EltsV2F16.push_back(ElV2f16->getOperand(0));
4025 }
4026
4027 // All elements have ModOpcode modifier
4028 if (BV->getNumOperands() == EltsV2F16.size())
4029 selectWMMAModsNegAbs(ModOpcode, Mods, EltsV2F16, Src, SDLoc(In), 32);
4030 }
4031
4032 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4033 return true;
4034}
4035
4036bool AMDGPUDAGToDAGISel::SelectWMMAModsF32NegAbs(SDValue In, SDValue &Src,
4037 SDValue &SrcMods) const {
4038 Src = In;
4039 unsigned Mods = SISrcMods::OP_SEL_1;
4041
4042 if (auto *BV = dyn_cast<BuildVectorSDNode>(stripBitcast(In))) {
4043 assert(BV->getNumOperands() > 0);
4044 // Based on first element decide which mod we match, neg or abs
4045 SDValue ElF32 = stripBitcast(BV->getOperand(0));
4046 unsigned ModOpcode =
4047 (ElF32.getOpcode() == ISD::FNEG) ? ISD::FNEG : ISD::FABS;
4048 for (unsigned i = 0; i < BV->getNumOperands(); ++i) {
4049 SDValue ElF32 = stripBitcast(BV->getOperand(i));
4050 if (ElF32.getOpcode() != ModOpcode)
4051 break;
4052 EltsF32.push_back(ElF32.getOperand(0));
4053 }
4054
4055 // All elements had ModOpcode modifier
4056 if (BV->getNumOperands() == EltsF32.size())
4057 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF32, Src, SDLoc(In), 32);
4058 }
4059
4060 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4061 return true;
4062}
4063
4064bool AMDGPUDAGToDAGISel::SelectWMMAVISrc(SDValue In, SDValue &Src) const {
4065 if (auto *BV = dyn_cast<BuildVectorSDNode>(In)) {
4066 BitVector UndefElements;
4067 if (SDValue Splat = BV->getSplatValue(&UndefElements))
4068 if (isInlineImmediate(Splat.getNode())) {
4069 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Splat)) {
4070 unsigned Imm = C->getAPIntValue().getSExtValue();
4071 Src = CurDAG->getTargetConstant(Imm, SDLoc(In), MVT::i32);
4072 return true;
4073 }
4074 if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Splat)) {
4075 unsigned Imm = C->getValueAPF().bitcastToAPInt().getSExtValue();
4076 Src = CurDAG->getTargetConstant(Imm, SDLoc(In), MVT::i32);
4077 return true;
4078 }
4079 llvm_unreachable("unhandled Constant node");
4080 }
4081 }
4082
4083 // 16 bit splat
4084 SDValue SplatSrc32 = stripBitcast(In);
4085 if (auto *SplatSrc32BV = dyn_cast<BuildVectorSDNode>(SplatSrc32))
4086 if (SDValue Splat32 = SplatSrc32BV->getSplatValue()) {
4087 SDValue SplatSrc16 = stripBitcast(Splat32);
4088 if (auto *SplatSrc16BV = dyn_cast<BuildVectorSDNode>(SplatSrc16))
4089 if (SDValue Splat = SplatSrc16BV->getSplatValue()) {
4090 const SIInstrInfo *TII = Subtarget->getInstrInfo();
4091 std::optional<APInt> RawValue;
4092 if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Splat))
4093 RawValue = C->getValueAPF().bitcastToAPInt();
4094 else if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Splat))
4095 RawValue = C->getAPIntValue();
4096
4097 if (RawValue.has_value()) {
4098 EVT VT = In.getValueType().getScalarType();
4099 if (VT.getSimpleVT() == MVT::f16 || VT.getSimpleVT() == MVT::bf16) {
4100 APFloat FloatVal(VT.getSimpleVT() == MVT::f16
4103 RawValue.value());
4104 if (TII->isInlineConstant(FloatVal)) {
4105 Src = CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4106 MVT::i16);
4107 return true;
4108 }
4109 } else if (VT.getSimpleVT() == MVT::i16) {
4110 if (TII->isInlineConstant(RawValue.value())) {
4111 Src = CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4112 MVT::i16);
4113 return true;
4114 }
4115 } else
4116 llvm_unreachable("unknown 16-bit type");
4117 }
4118 }
4119 }
4120
4121 // Currently f64 immediate vectors are represented as vectors of v2i32, with
4122 // different lo and hi 32-bit values even though double values are splated.
4123 // So we have to manually compare to determine whether it is splated.
4124 if (CurDAG->isConstantIntBuildVectorOrConstantInt(SplatSrc32)) {
4125 int64_t Imm64 = 0;
4126 for (unsigned i = 0; i < SplatSrc32->getNumOperands(); i += 2) {
4127 auto Lo32 = cast<ConstantSDNode>(SplatSrc32->getOperand(i));
4128 auto Hi32 = cast<ConstantSDNode>(SplatSrc32->getOperand(i + 1));
4129 int64_t LoImm = Lo32->getAPIntValue().getSExtValue();
4130 int64_t HiImm = Hi32->getAPIntValue().getSExtValue();
4131 int64_t Imm64I = (HiImm << 32) + LoImm;
4132 if (i == 0) {
4133 if (!isInlineImmediate(APInt(64, Imm64I)))
4134 return false;
4135 Imm64 = Imm64I;
4136 } else if (Imm64I != Imm64)
4137 return false;
4138 } // end for
4139
4140 Src = CurDAG->getTargetConstant(Imm64, SDLoc(In), MVT::i64);
4141 return true;
4142 }
4143
4144 return false;
4145}
4146
4147bool AMDGPUDAGToDAGISel::SelectSWMMACIndex8(SDValue In, SDValue &Src,
4148 SDValue &IndexKey) const {
4149 unsigned Key = 0;
4150 Src = In;
4151
4152 if (In.getOpcode() == ISD::SRL) {
4153 const llvm::SDValue &ShiftSrc = In.getOperand(0);
4154 ConstantSDNode *ShiftAmt = dyn_cast<ConstantSDNode>(In.getOperand(1));
4155 if (ShiftSrc.getValueType().getSizeInBits() == 32 && ShiftAmt &&
4156 ShiftAmt->getZExtValue() % 8 == 0) {
4157 Key = ShiftAmt->getZExtValue() / 8;
4158 Src = ShiftSrc;
4159 }
4160 }
4161
4162 IndexKey = CurDAG->getTargetConstant(Key, SDLoc(In), MVT::i32);
4163 return true;
4164}
4165
4166bool AMDGPUDAGToDAGISel::SelectSWMMACIndex16(SDValue In, SDValue &Src,
4167 SDValue &IndexKey) const {
4168 unsigned Key = 0;
4169 Src = In;
4170
4171 if (In.getOpcode() == ISD::SRL) {
4172 const llvm::SDValue &ShiftSrc = In.getOperand(0);
4173 ConstantSDNode *ShiftAmt = dyn_cast<ConstantSDNode>(In.getOperand(1));
4174 if (ShiftSrc.getValueType().getSizeInBits() == 32 && ShiftAmt &&
4175 ShiftAmt->getZExtValue() == 16) {
4176 Key = 1;
4177 Src = ShiftSrc;
4178 }
4179 }
4180
4181 IndexKey = CurDAG->getTargetConstant(Key, SDLoc(In), MVT::i32);
4182 return true;
4183}
4184
4185bool AMDGPUDAGToDAGISel::SelectSWMMACIndex32(SDValue In, SDValue &Src,
4186 SDValue &IndexKey) const {
4187 unsigned Key = 0;
4188 Src = In;
4189
4190 SDValue InI32;
4191
4192 if (In.getOpcode() == ISD::ANY_EXTEND || In.getOpcode() == ISD::ZERO_EXTEND) {
4193 const SDValue &ExtendSrc = In.getOperand(0);
4194 if (ExtendSrc.getValueSizeInBits() == 32)
4195 InI32 = ExtendSrc;
4196 } else if (In->getOpcode() == ISD::BITCAST) {
4197 const SDValue &CastSrc = In.getOperand(0);
4198 if (CastSrc.getOpcode() == ISD::BUILD_VECTOR &&
4199 CastSrc.getOperand(0).getValueSizeInBits() == 32) {
4200 ConstantSDNode *Zero = dyn_cast<ConstantSDNode>(CastSrc.getOperand(1));
4201 if (Zero && Zero->getZExtValue() == 0)
4202 InI32 = CastSrc.getOperand(0);
4203 }
4204 }
4205
4206 if (InI32 && InI32.getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
4207 const SDValue &ExtractVecEltSrc = InI32.getOperand(0);
4208 ConstantSDNode *EltIdx = dyn_cast<ConstantSDNode>(InI32.getOperand(1));
4209 if (ExtractVecEltSrc.getValueSizeInBits() == 64 && EltIdx &&
4210 EltIdx->getZExtValue() == 1) {
4211 Key = 1;
4212 Src = ExtractVecEltSrc;
4213 }
4214 }
4215
4216 IndexKey = CurDAG->getTargetConstant(Key, SDLoc(In), MVT::i32);
4217 return true;
4218}
4219
4220bool AMDGPUDAGToDAGISel::SelectVOP3OpSel(SDValue In, SDValue &Src,
4221 SDValue &SrcMods) const {
4222 Src = In;
4223 // FIXME: Handle op_sel
4224 SrcMods = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32);
4225 return true;
4226}
4227
4228bool AMDGPUDAGToDAGISel::SelectVOP3OpSelMods(SDValue In, SDValue &Src,
4229 SDValue &SrcMods) const {
4230 // FIXME: Handle op_sel
4231 return SelectVOP3Mods(In, Src, SrcMods);
4232}
4233
4234// Match lowered fpext from bf16 to f32. This is a bit operation extending
4235// a 16-bit value with 16-bit of zeroes at LSB:
4236//
4237// 1. (f32 (bitcast (build_vector (i16 0), (i16 (bitcast bf16:val)))))
4238// 2. (f32 (bitcast (and i32:val, 0xffff0000))) -> IsExtractHigh = true
4239// 3. (f32 (bitcast (shl i32:va, 16) -> IsExtractHigh = false
4240static SDValue matchBF16FPExtendLike(SDValue Op, bool &IsExtractHigh) {
4241 if (Op.getValueType() != MVT::f32 || Op.getOpcode() != ISD::BITCAST)
4242 return SDValue();
4243 Op = Op.getOperand(0);
4244
4245 IsExtractHigh = false;
4246 if (Op.getValueType() == MVT::v2i16 && Op.getOpcode() == ISD::BUILD_VECTOR) {
4247 auto Low16 = dyn_cast<ConstantSDNode>(Op.getOperand(0));
4248 if (!Low16 || !Low16->isZero())
4249 return SDValue();
4250 Op = stripBitcast(Op.getOperand(1));
4251 if (Op.getValueType() != MVT::bf16)
4252 return SDValue();
4253 return Op;
4254 }
4255
4256 if (Op.getValueType() != MVT::i32)
4257 return SDValue();
4258
4259 if (Op.getOpcode() == ISD::AND) {
4260 if (auto Mask = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
4261 if (Mask->getZExtValue() == 0xffff0000) {
4262 IsExtractHigh = true;
4263 return Op.getOperand(0);
4264 }
4265 }
4266 return SDValue();
4267 }
4268
4269 if (Op.getOpcode() == ISD::SHL) {
4270 if (auto Amt = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
4271 if (Amt->getZExtValue() == 16)
4272 return Op.getOperand(0);
4273 }
4274 }
4275
4276 return SDValue();
4277}
4278
4279// The return value is not whether the match is possible (which it always is),
4280// but whether or not it a conversion is really used.
4281bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsImpl(SDValue In, SDValue &Src,
4282 unsigned &Mods,
4283 MVT VT) const {
4284 Mods = 0;
4285 SelectVOP3ModsImpl(In, Src, Mods);
4286
4287 bool IsExtractHigh = false;
4288 if (Src.getOpcode() == ISD::FP_EXTEND) {
4289 Src = Src.getOperand(0);
4290 } else if (VT == MVT::bf16) {
4291 SDValue B16 = matchBF16FPExtendLike(Src, IsExtractHigh);
4292 if (!B16)
4293 return false;
4294 Src = B16;
4295 } else
4296 return false;
4297
4298 if (Src.getValueType() != VT &&
4299 (VT != MVT::bf16 || Src.getValueType() != MVT::i32))
4300 return false;
4301
4302 Src = stripBitcast(Src);
4303
4304 // Be careful about folding modifiers if we already have an abs. fneg is
4305 // applied last, so we don't want to apply an earlier fneg.
4306 if ((Mods & SISrcMods::ABS) == 0) {
4307 unsigned ModsTmp;
4308 SelectVOP3ModsImpl(Src, Src, ModsTmp);
4309
4310 if ((ModsTmp & SISrcMods::NEG) != 0)
4311 Mods ^= SISrcMods::NEG;
4312
4313 if ((ModsTmp & SISrcMods::ABS) != 0)
4314 Mods |= SISrcMods::ABS;
4315 }
4316
4317 // op_sel/op_sel_hi decide the source type and source.
4318 // If the source's op_sel_hi is set, it indicates to do a conversion from
4319 // fp16. If the sources's op_sel is set, it picks the high half of the source
4320 // register.
4321
4322 Mods |= SISrcMods::OP_SEL_1;
4323 if (Src.getValueSizeInBits() == 16) {
4324 if (isExtractHiElt(Src, Src)) {
4325 Mods |= SISrcMods::OP_SEL_0;
4326
4327 // TODO: Should we try to look for neg/abs here?
4328 return true;
4329 }
4330
4331 if (Src.getOpcode() == ISD::TRUNCATE &&
4332 Src.getOperand(0).getValueType() == MVT::i32) {
4333 Src = Src.getOperand(0);
4334 return true;
4335 }
4336
4337 if (Subtarget->useRealTrue16Insts())
4338 // In true16 mode, pack src to a 32bit
4339 Src = createVOP3PSrc32FromLo16(Src, In, CurDAG, Subtarget);
4340 } else if (IsExtractHigh)
4341 Mods |= SISrcMods::OP_SEL_0;
4342
4343 return true;
4344}
4345
4346bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsExt(SDValue In, SDValue &Src,
4347 SDValue &SrcMods) const {
4348 unsigned Mods = 0;
4349 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16))
4350 return false;
4351 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4352 return true;
4353}
4354
4355bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixMods(SDValue In, SDValue &Src,
4356 SDValue &SrcMods) const {
4357 unsigned Mods = 0;
4358 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16);
4359 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4360 return true;
4361}
4362
4363bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsExt(SDValue In, SDValue &Src,
4364 SDValue &SrcMods) const {
4365 unsigned Mods = 0;
4366 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16))
4367 return false;
4368 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4369 return true;
4370}
4371
4372bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16Mods(SDValue In, SDValue &Src,
4373 SDValue &SrcMods) const {
4374 unsigned Mods = 0;
4375 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16);
4376 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4377 return true;
4378}
4379
4380// Match BITOP3 operation and return a number of matched instructions plus
4381// truth table.
4382static std::pair<unsigned, uint8_t> BitOp3_Op(SDValue In,
4384 unsigned NumOpcodes = 0;
4385 uint8_t LHSBits, RHSBits;
4386
4387 auto getOperandBits = [&Src, In](SDValue Op, uint8_t &Bits) -> bool {
4388 // Define truth table given Src0, Src1, Src2 bits permutations:
4389 // 0 0 0
4390 // 0 0 1
4391 // 0 1 0
4392 // 0 1 1
4393 // 1 0 0
4394 // 1 0 1
4395 // 1 1 0
4396 // 1 1 1
4397 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4398
4399 if (auto *C = dyn_cast<ConstantSDNode>(Op)) {
4400 if (C->isAllOnes()) {
4401 Bits = 0xff;
4402 return true;
4403 }
4404 if (C->isZero()) {
4405 Bits = 0;
4406 return true;
4407 }
4408 }
4409
4410 for (unsigned I = 0; I < Src.size(); ++I) {
4411 // Try to find existing reused operand
4412 if (Src[I] == Op) {
4413 Bits = SrcBits[I];
4414 return true;
4415 }
4416 // Try to replace parent operator
4417 if (Src[I] == In) {
4418 Bits = SrcBits[I];
4419 Src[I] = Op;
4420 return true;
4421 }
4422 }
4423
4424 if (Src.size() == 3) {
4425 // No room left for operands. Try one last time, there can be a 'not' of
4426 // one of our source operands. In this case we can compute the bits
4427 // without growing Src vector.
4428 if (Op.getOpcode() == ISD::XOR) {
4429 if (auto *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
4430 if (C->isAllOnes()) {
4431 SDValue LHS = Op.getOperand(0);
4432 for (unsigned I = 0; I < Src.size(); ++I) {
4433 if (Src[I] == LHS) {
4434 Bits = ~SrcBits[I];
4435 return true;
4436 }
4437 }
4438 }
4439 }
4440 }
4441
4442 return false;
4443 }
4444
4445 Bits = SrcBits[Src.size()];
4446 Src.push_back(Op);
4447 return true;
4448 };
4449
4450 switch (In.getOpcode()) {
4451 case ISD::AND:
4452 case ISD::OR:
4453 case ISD::XOR: {
4454 SDValue LHS = In.getOperand(0);
4455 SDValue RHS = In.getOperand(1);
4456
4457 SmallVector<SDValue, 3> Backup(Src.begin(), Src.end());
4458 if (!getOperandBits(LHS, LHSBits) ||
4459 !getOperandBits(RHS, RHSBits)) {
4460 Src = std::move(Backup);
4461 return std::make_pair(0, 0);
4462 }
4463
4464 // Recursion is naturally limited by the size of the operand vector.
4465 //
4466 // When LHS and RHS share a common sub-expression, one side's recursion
4467 // may decompose that sub-expression and replace the Src slot the other
4468 // side occupies with sub-operands via the "replace parent" path in
4469 // getOperandBits. The other side's cached bit-pattern then refers to a
4470 // slot whose contents changed, producing a wrong truth table.
4471 //
4472 // We detect this in three ways:
4473 // (A) If LHS recursed, its truth table is valid against the Src state
4474 // when LHS recursion completed (SrcAfterLHS). If RHS recursion
4475 // then mutates a Src slot that LHSBits depends on, LHSBits is
4476 // stale.
4477 // (B) If RHS did not recurse, RHSBits came from getOperandBits and
4478 // refers to a specific Src slot. If that slot's contents changed
4479 // (by either recursion), RHSBits is stale.
4480 // (C) Symmetrically for LHS if it did not recurse.
4481 SmallVector<SDValue, 3> SrcBeforeRecurse(Src.begin(), Src.end());
4482 uint8_t LHSBitsOrig = LHSBits;
4483 uint8_t RHSBitsOrig = RHSBits;
4484
4485 auto LHSOp = BitOp3_Op(LHS, Src);
4486 if (LHSOp.first) {
4487 NumOpcodes += LHSOp.first;
4488 LHSBits = LHSOp.second;
4489 }
4490
4491 SmallVector<SDValue, 3> SrcAfterLHS(Src.begin(), Src.end());
4492
4493 auto RHSOp = BitOp3_Op(RHS, Src);
4494 if (RHSOp.first) {
4495 NumOpcodes += RHSOp.first;
4496 RHSBits = RHSOp.second;
4497 }
4498
4499 // dependsOnSlot: true iff the truth table TT varies with slot Slot.
4500 auto dependsOnSlot = [](uint8_t TT, int Slot) -> bool {
4501 if (Slot < 0 || Slot > 2)
4502 return false;
4503 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4504 const int Shifts[3] = {4, 2, 1};
4505 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4506 };
4507
4508 // findSlot: locate the Src slot a getOperandBits result depends on,
4509 // including negated (XOR with -1) patterns that getOperandBits
4510 // resolves via the NOT shortcut (~SrcBits[I]).
4511 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4512 auto findSlot = [&](uint8_t Bits, SDValue Op,
4513 const SmallVectorImpl<SDValue> &S) -> int {
4514 SDValue NegatedInner;
4515 bool IsNegationOp =
4516 Op.getOpcode() == ISD::XOR && isAllOnesConstant(Op.getOperand(1));
4517 if (IsNegationOp)
4518 NegatedInner = Op.getOperand(0);
4519 for (int I = 0; I < (int)S.size(); I++) {
4520 if (Bits == SrcBitsConst[I] && S[I] == Op)
4521 return I;
4522 if (IsNegationOp && Bits == (uint8_t)~SrcBitsConst[I] &&
4523 S[I] == NegatedInner)
4524 return I;
4525 }
4526 return -1;
4527 };
4528
4529 bool Stale = false;
4530
4531 // (A) LHS recursed: its truth table is against SrcAfterLHS.
4532 // Check if RHS recursion mutated a slot that LHSBits uses.
4533 if (LHSOp.first) {
4534 for (int I = 0; I < (int)SrcAfterLHS.size() && I < 3; I++) {
4535 if (I < (int)Src.size() && Src[I] != SrcAfterLHS[I] &&
4536 dependsOnSlot(LHSBits, I)) {
4537 Stale = true;
4538 break;
4539 }
4540 }
4541 }
4542
4543 // (B) RHS did not recurse: RHSBits from getOperandBits is against
4544 // SrcBeforeRecurse. Check if that slot was mutated since then.
4545 if (!Stale && !RHSOp.first) {
4546 int Slot = findSlot(RHSBitsOrig, RHS, SrcBeforeRecurse);
4547 if (Slot >= 0 &&
4548 (Slot >= (int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4549 Stale = true;
4550 }
4551
4552 // (C) LHS did not recurse: LHSBits from getOperandBits is against
4553 // SrcBeforeRecurse. Check if that slot was mutated since then.
4554 if (!Stale && !LHSOp.first) {
4555 int Slot = findSlot(LHSBitsOrig, LHS, SrcBeforeRecurse);
4556 if (Slot >= 0 &&
4557 (Slot >= (int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4558 Stale = true;
4559 }
4560
4561 if (Stale) {
4562 Src = std::move(SrcBeforeRecurse);
4563 LHSBits = LHSBitsOrig;
4564 RHSBits = RHSBitsOrig;
4565 NumOpcodes = 0;
4566 }
4567 break;
4568 }
4569 default:
4570 return std::make_pair(0, 0);
4571 }
4572
4573 uint8_t TTbl;
4574 switch (In.getOpcode()) {
4575 case ISD::AND:
4576 TTbl = LHSBits & RHSBits;
4577 break;
4578 case ISD::OR:
4579 TTbl = LHSBits | RHSBits;
4580 break;
4581 case ISD::XOR:
4582 TTbl = LHSBits ^ RHSBits;
4583 break;
4584 default:
4585 break;
4586 }
4587
4588 return std::make_pair(NumOpcodes + 1, TTbl);
4589}
4590
4591bool AMDGPUDAGToDAGISel::SelectBITOP3(SDValue In, SDValue &Src0, SDValue &Src1,
4592 SDValue &Src2, SDValue &Tbl) const {
4594 uint8_t TTbl;
4595 unsigned NumOpcodes;
4596
4597 std::tie(NumOpcodes, TTbl) = BitOp3_Op(In, Src);
4598
4599 // Src.empty() case can happen if all operands are all zero or all ones.
4600 // Normally it shall be optimized out before reaching this.
4601 if (NumOpcodes < 2 || Src.empty())
4602 return false;
4603
4604 // For a uniform case threshold should be higher to account for moves between
4605 // VGPRs and SGPRs. It needs one operand in a VGPR, rest two can be in SGPRs
4606 // and a readtfirstlane after.
4607 if (NumOpcodes < 4 && !In->isDivergent())
4608 return false;
4609
4610 if (NumOpcodes == 2 && In.getValueType() == MVT::i32) {
4611 // Avoid using BITOP3 for OR3, XOR3, AND_OR. This is not faster but makes
4612 // asm more readable. This cannot be modeled with AddedComplexity because
4613 // selector does not know how many operations did we match.
4614 if ((In.getOpcode() == ISD::XOR || In.getOpcode() == ISD::OR) &&
4615 (In.getOperand(0).getOpcode() == In.getOpcode() ||
4616 In.getOperand(1).getOpcode() == In.getOpcode()))
4617 return false;
4618
4619 if (In.getOpcode() == ISD::OR &&
4620 (In.getOperand(0).getOpcode() == ISD::AND ||
4621 In.getOperand(1).getOpcode() == ISD::AND))
4622 return false;
4623 }
4624
4625 // Last operand can be ignored, turning a ternary operation into a binary.
4626 // For example: (~a & b & c) | (~a & b & ~c) -> (~a & b). We can replace
4627 // 'c' with 'a' here without changing the answer. In some pathological
4628 // cases it should be possible to get an operation with a single operand
4629 // too if optimizer would not catch it.
4630 while (Src.size() < 3)
4631 Src.push_back(Src[0]);
4632
4633 Src0 = Src[0];
4634 Src1 = Src[1];
4635 Src2 = Src[2];
4636
4637 Tbl = CurDAG->getTargetConstant(TTbl, SDLoc(In), MVT::i32);
4638 return true;
4639}
4640
4641SDValue AMDGPUDAGToDAGISel::getHi16Elt(SDValue In) const {
4642 if (In.getOpcode() == ISD::POISON)
4643 return CurDAG->getPOISON(MVT::i32);
4644
4645 if (In.getOpcode() == ISD::UNDEF)
4646 return CurDAG->getUNDEF(MVT::i32);
4647
4648 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(In)) {
4649 SDLoc SL(In);
4650 return CurDAG->getConstant(C->getZExtValue() << 16, SL, MVT::i32);
4651 }
4652
4653 if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(In)) {
4654 SDLoc SL(In);
4655 return CurDAG->getConstant(
4656 C->getValueAPF().bitcastToAPInt().getZExtValue() << 16, SL, MVT::i32);
4657 }
4658
4659 SDValue Src;
4660 if (isExtractHiElt(In, Src))
4661 return Src;
4662
4663 return SDValue();
4664}
4665
4666bool AMDGPUDAGToDAGISel::isVGPRImm(const SDNode * N) const {
4667 assert(CurDAG->getTarget().getTargetTriple().isAMDGCN());
4668
4669 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
4670 const SIInstrInfo *SII = Subtarget->getInstrInfo();
4671
4672 unsigned Limit = 0;
4673 bool AllUsesAcceptSReg = true;
4674 for (SDNode::use_iterator U = N->use_begin(), E = SDNode::use_end();
4675 Limit < 10 && U != E; ++U, ++Limit) {
4676 const TargetRegisterClass *RC =
4677 getOperandRegClass(U->getUser(), U->getOperandNo());
4678
4679 // If the register class is unknown, it could be an unknown
4680 // register class that needs to be an SGPR, e.g. an inline asm
4681 // constraint
4682 if (!RC || SIRI->isSGPRClass(RC))
4683 return false;
4684
4685 if (RC != &AMDGPU::VS_32RegClass && RC != &AMDGPU::VS_64RegClass &&
4686 RC != &AMDGPU::VS_64_Align2RegClass) {
4687 AllUsesAcceptSReg = false;
4688 SDNode *User = U->getUser();
4689 if (User->isMachineOpcode()) {
4690 unsigned Opc = User->getMachineOpcode();
4691 const MCInstrDesc &Desc = SII->get(Opc);
4692 if (Desc.isCommutable()) {
4693 unsigned OpIdx = Desc.getNumDefs() + U->getOperandNo();
4694 unsigned CommuteIdx1 = TargetInstrInfo::CommuteAnyOperandIndex;
4695 if (SII->findCommutedOpIndices(Desc, OpIdx, CommuteIdx1)) {
4696 unsigned CommutedOpNo = CommuteIdx1 - Desc.getNumDefs();
4697 const TargetRegisterClass *CommutedRC =
4698 getOperandRegClass(U->getUser(), CommutedOpNo);
4699 if (CommutedRC == &AMDGPU::VS_32RegClass ||
4700 CommutedRC == &AMDGPU::VS_64RegClass ||
4701 CommutedRC == &AMDGPU::VS_64_Align2RegClass)
4702 AllUsesAcceptSReg = true;
4703 }
4704 }
4705 }
4706 // If "AllUsesAcceptSReg == false" so far we haven't succeeded
4707 // commuting current user. This means have at least one use
4708 // that strictly require VGPR. Thus, we will not attempt to commute
4709 // other user instructions.
4710 if (!AllUsesAcceptSReg)
4711 break;
4712 }
4713 }
4714 return !AllUsesAcceptSReg && (Limit < 10);
4715}
4716
4717bool AMDGPUDAGToDAGISel::isUniformLoad(const SDNode *N) const {
4718 const auto *Ld = cast<LoadSDNode>(N);
4719 const MachineMemOperand *MMO = Ld->getMemOperand();
4720
4721 // FIXME: We ought to able able to take the direct isDivergent result. We
4722 // cannot rely on the MMO for a uniformity check, and should stop using
4723 // it. This is a hack for 2 ways that the IR divergence analysis is superior
4724 // to the DAG divergence: Recognizing shift-of-workitem-id as always
4725 // uniform, and isSingleLaneExecution. These should be handled in the DAG
4726 // version, and then this can be dropped.
4727 if (Ld->isDivergent() && !AMDGPU::isUniformMMO(MMO))
4728 return false;
4729
4730 return MMO->getSize().hasValue() &&
4731 Ld->getAlign() >=
4732 Align(std::min(MMO->getSize().getValue().getKnownMinValue(),
4733 uint64_t(4))) &&
4734 (MMO->isInvariant() ||
4735 (Ld->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS ||
4736 Ld->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT) ||
4737 (Subtarget->getScalarizeGlobalBehavior() &&
4738 Ld->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS &&
4739 Ld->isSimple() &&
4740 static_cast<const SITargetLowering *>(getTargetLowering())
4741 ->isMemOpHasNoClobberedMemOperand(N)));
4742}
4743
4746 *static_cast<const AMDGPUTargetLowering*>(getTargetLowering());
4747 bool IsModified = false;
4748 do {
4749 IsModified = false;
4750
4751 // Go over all selected nodes and try to fold them a bit more
4752 SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_begin();
4753 while (Position != CurDAG->allnodes_end()) {
4754 SDNode *Node = &*Position++;
4756 if (!MachineNode)
4757 continue;
4758
4759 SDNode *ResNode = Lowering.PostISelFolding(MachineNode, *CurDAG);
4760 if (ResNode != Node) {
4761 if (ResNode)
4762 ReplaceUses(Node, ResNode);
4763 IsModified = true;
4764 }
4765 }
4766 CurDAG->RemoveDeadNodes();
4767 } while (IsModified);
4768}
4769
4774
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool getBaseWithOffsetUsingSplitOR(SelectionDAG &DAG, SDValue Addr, SDValue &N0, SDValue &N1)
static SDValue SelectSAddrFI(SelectionDAG *CurDAG, SDValue SAddr)
static SDValue matchExtFromI32orI32(SDValue Op, bool IsSigned, const SelectionDAG *DAG)
static MemSDNode * findMemSDNode(SDNode *N)
static bool IsCopyFromSGPR(const SIRegisterInfo &TRI, SDValue Val)
static SDValue combineBallotPattern(SDValue VCMP, bool &Negate)
static SDValue matchBF16FPExtendLike(SDValue Op, bool &IsExtractHigh)
static void checkWMMAElementsModifiersF16(BuildVectorSDNode *BV, std::function< bool(SDValue)> ModifierCheck)
Defines an instruction selector for the AMDGPU target.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isNoUnsignedWrap(MachineInstr *Addr)
static bool isExtractHiElt(MachineRegisterInfo &MRI, Register In, Register &Out)
static std::pair< unsigned, uint8_t > BitOp3_Op(Register R, SmallVectorImpl< Register > &Src, const MachineRegisterInfo &MRI)
static unsigned gwsIntrinToOpcode(unsigned IntrID)
Provides AMDGPU specific target descriptions.
Base class for AMDGPU specific classes of TargetSubtarget.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
MachineInstr unsigned OpIdx
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
Provides R600 specific target descriptions.
Interface definition for R600RegisterInfo.
const SmallVectorImpl< MachineOperand > & Cond
SI DAG Lowering interface definition.
#define LLVM_DEBUG(...)
Definition Debug.h:119
LLVM IR instance of the generic uniformity analysis.
Value * RHS
Value * LHS
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
AMDGPUDAGToDAGISelLegacy(TargetMachine &TM, CodeGenOptLevel OptLevel)
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
AMDGPU specific code to select AMDGPU machine instructions for SelectionDAG operations.
bool isSDWAOperand(const SDNode *N) const
void SelectBuildVector(SDNode *N, unsigned RegClassID)
void Select(SDNode *N) override
Main hook for targets to transform nodes into machine nodes.
bool runOnMachineFunction(MachineFunction &MF) override
void PreprocessISelDAG() override
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
void PostprocessISelDAG() override
PostprocessISelDAG() - This hook allows the target to hack on the graph right after selection.
bool matchLoadD16FromBuildVector(SDNode *N) const
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
AMDGPUISelDAGToDAGPass(TargetMachine &TM)
static SDValue stripBitcast(SDValue Val)
static const fltSemantics & BFloat()
Definition APFloat.h:296
static const fltSemantics & IEEEhalf()
Definition APFloat.h:295
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1565
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
Definition APInt.h:467
bool isMaxSignedValue() const
Determine if this is the largest signed value.
Definition APInt.h:406
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1587
unsigned countr_one() const
Count the number of trailing one bits.
Definition APInt.h:1681
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
LLVM Basic Block Representation.
Definition BasicBlock.h:62
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI SDValue getSplatValue(const APInt &DemandedElts, BitVector *UndefElements=nullptr) const
Returns the demanded splatted value or a null value if this is not a splat.
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
Analysis pass which computes a DominatorTree.
Definition Dominators.h:270
Legacy analysis pass which computes a DominatorTree.
Definition Dominators.h:306
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:151
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
const SIInstrInfo * getInstrInfo() const override
bool useRealTrue16Insts() const
Return true if real (non-fake) variants of True16 instructions using 16-bit registers should be code-...
Generation getGeneration() const
void checkSubtargetFeatures(const Function &F) const
Diagnose inconsistent subtarget features before attempting to codegen function F.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
bool hasValue() const
TypeSize getValue() const
Analysis pass that exposes the LoopInfo for a function.
Definition LoopInfo.h:587
SmallVector< LoopT *, 4 > getLoopsInPreorder() const
Return all of the loops in the function in preorder across the loop nests, with siblings in forward p...
The legacy pass manager's analysis pass to compute loop information.
Definition LoopInfo.h:612
unsigned getID() const
getID() - Return the register class ID number.
Machine Value Type.
static MVT getIntegerVT(unsigned BitWidth)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
LocationSize getSize() const
Return the size in bytes of the memory reference.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
Wrapper class representing virtual and physical registers.
Definition Register.h:20
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool isDivergent() const
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
bool isAnyAdd() const
Returns true if the node type is ADD or PTRADD.
static use_iterator use_end()
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isUndef() const
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
static bool isSGPRClass(const TargetRegisterClass *RC)
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
std::unique_ptr< FunctionLoweringInfo > FuncInfo
const TargetLowering * TLI
const TargetInstrInfo * TII
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
SelectionDAGISel(TargetMachine &tm, CodeGenOptLevel OL=CodeGenOptLevel::Default)
virtual bool runOnMachineFunction(MachineFunction &mf)
const TargetLowering * getTargetLowering() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
SDValue getTargetFrameIndex(int FI, EVT VT)
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
MachineFunction & getMachineFunction() const
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
ilist< SDNode >::iterator allnodes_iterator
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
static const unsigned CommuteAnyOperandIndex
Primary interface to the complete machine description for the target machine.
Analysis pass which computes UniformityInfo.
Legacy analysis pass which computes a CycleInfo.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
std::optional< int64_t > getSMRDEncodedLiteralOffset32(const MCSubtargetInfo &ST, int64_t ByteOffset)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
bool hasSMRDSignedImmOffset(const MCSubtargetInfo &ST)
std::optional< int64_t > getSMRDEncodedOffset(const MCSubtargetInfo &ST, int64_t ByteOffset, bool IsBuffer, bool HasSOffset)
bool isUniformMMO(const MachineMemOperand *MMO)
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.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:829
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ PTRADD
PTRADD represents pointer arithmetic semantics, for targets that opt in using shouldPreservePtrArith(...
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:236
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:275
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
Definition ISDOpcodes.h:524
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:863
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:520
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition ISDOpcodes.h:220
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:890
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:417
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition ISDOpcodes.h:254
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ CONVERGENCECTRL_GLUE
This does not correspond to any convergence control intrinsic.
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:667
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:543
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
Definition ISDOpcodes.h:230
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:651
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:578
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition ISDOpcodes.h:224
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ TargetFrameIndex
Definition ISDOpcodes.h:187
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:898
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:988
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
Definition ISDOpcodes.h:328
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:969
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:866
@ BRCOND
BRCOND - Conditional branch.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:213
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:558
bool isExtOpcode(unsigned Opcode)
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
@ User
could "use" a pointer
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
Definition MathExtras.h:256
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
Op::Description Desc
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
bool isBoolSGPR(SDValue V)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
static bool getConstantValue(SDValue N, uint32_t &Out)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:82
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
FunctionPass * createAMDGPUISelDag(TargetMachine &TM, CodeGenOptLevel OptLevel)
This pass converts a legalized DAG into a AMDGPU-specific.
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
Definition VE.h:376
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
Extended Value Type.
Definition ValueTypes.h:35
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
Definition ValueTypes.h:279
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
Definition ValueTypes.h:165
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
Definition KnownBits.h:315
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
Definition KnownBits.h:361
APInt getMaxValue() const
Return the maximal unsigned value possible given these KnownBits.
Definition KnownBits.h:146
APInt getMinValue() const
Return the minimal unsigned value possible given these KnownBits.
Definition KnownBits.h:130
static unsigned getSubRegFromChannel(unsigned Channel)
bool hasNoUnsignedWrap() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.