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