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 "AMDGPU.h" 15 #include "AMDGPUArgumentUsageInfo.h" 16 #include "AMDGPUISelLowering.h" // For AMDGPUISD 17 #include "AMDGPUInstrInfo.h" 18 #include "AMDGPUPerfHintAnalysis.h" 19 #include "AMDGPURegisterInfo.h" 20 #include "AMDGPUSubtarget.h" 21 #include "AMDGPUTargetMachine.h" 22 #include "SIDefines.h" 23 #include "SIISelLowering.h" 24 #include "SIInstrInfo.h" 25 #include "SIMachineFunctionInfo.h" 26 #include "SIRegisterInfo.h" 27 #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 28 #include "llvm/ADT/APInt.h" 29 #include "llvm/ADT/SmallVector.h" 30 #include "llvm/ADT/StringRef.h" 31 #include "llvm/Analysis/LegacyDivergenceAnalysis.h" 32 #include "llvm/Analysis/ValueTracking.h" 33 #include "llvm/CodeGen/FunctionLoweringInfo.h" 34 #include "llvm/CodeGen/ISDOpcodes.h" 35 #include "llvm/CodeGen/MachineFunction.h" 36 #include "llvm/CodeGen/MachineRegisterInfo.h" 37 #include "llvm/CodeGen/SelectionDAG.h" 38 #include "llvm/CodeGen/SelectionDAGISel.h" 39 #include "llvm/CodeGen/SelectionDAGNodes.h" 40 #include "llvm/CodeGen/ValueTypes.h" 41 #include "llvm/IR/BasicBlock.h" 42 #ifdef EXPENSIVE_CHECKS 43 #include "llvm/IR/Dominators.h" 44 #endif 45 #include "llvm/IR/Instruction.h" 46 #include "llvm/MC/MCInstrDesc.h" 47 #include "llvm/Support/Casting.h" 48 #include "llvm/Support/CodeGen.h" 49 #include "llvm/Support/ErrorHandling.h" 50 #include "llvm/Support/MachineValueType.h" 51 #include "llvm/Support/MathExtras.h" 52 #include <cassert> 53 #include <cstdint> 54 #include <new> 55 #include <vector> 56 57 #define DEBUG_TYPE "isel" 58 59 using namespace llvm; 60 61 namespace llvm { 62 63 class R600InstrInfo; 64 65 } // end namespace llvm 66 67 //===----------------------------------------------------------------------===// 68 // Instruction Selector Implementation 69 //===----------------------------------------------------------------------===// 70 71 namespace { 72 73 static bool isNullConstantOrUndef(SDValue V) { 74 if (V.isUndef()) 75 return true; 76 77 ConstantSDNode *Const = dyn_cast<ConstantSDNode>(V); 78 return Const != nullptr && Const->isNullValue(); 79 } 80 81 static bool getConstantValue(SDValue N, uint32_t &Out) { 82 // This is only used for packed vectors, where ussing 0 for undef should 83 // always be good. 84 if (N.isUndef()) { 85 Out = 0; 86 return true; 87 } 88 89 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 90 Out = C->getAPIntValue().getSExtValue(); 91 return true; 92 } 93 94 if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N)) { 95 Out = C->getValueAPF().bitcastToAPInt().getSExtValue(); 96 return true; 97 } 98 99 return false; 100 } 101 102 // TODO: Handle undef as zero 103 static SDNode *packConstantV2I16(const SDNode *N, SelectionDAG &DAG, 104 bool Negate = false) { 105 assert(N->getOpcode() == ISD::BUILD_VECTOR && N->getNumOperands() == 2); 106 uint32_t LHSVal, RHSVal; 107 if (getConstantValue(N->getOperand(0), LHSVal) && 108 getConstantValue(N->getOperand(1), RHSVal)) { 109 SDLoc SL(N); 110 uint32_t K = Negate ? 111 (-LHSVal & 0xffff) | (-RHSVal << 16) : 112 (LHSVal & 0xffff) | (RHSVal << 16); 113 return DAG.getMachineNode(AMDGPU::S_MOV_B32, SL, N->getValueType(0), 114 DAG.getTargetConstant(K, SL, MVT::i32)); 115 } 116 117 return nullptr; 118 } 119 120 static SDNode *packNegConstantV2I16(const SDNode *N, SelectionDAG &DAG) { 121 return packConstantV2I16(N, DAG, true); 122 } 123 124 /// AMDGPU specific code to select AMDGPU machine instructions for 125 /// SelectionDAG operations. 126 class AMDGPUDAGToDAGISel : public SelectionDAGISel { 127 // Subtarget - Keep a pointer to the AMDGPU Subtarget around so that we can 128 // make the right decision when generating code for different targets. 129 const GCNSubtarget *Subtarget; 130 bool EnableLateStructurizeCFG; 131 132 public: 133 explicit AMDGPUDAGToDAGISel(TargetMachine *TM = nullptr, 134 CodeGenOpt::Level OptLevel = CodeGenOpt::Default) 135 : SelectionDAGISel(*TM, OptLevel) { 136 EnableLateStructurizeCFG = AMDGPUTargetMachine::EnableLateStructurizeCFG; 137 } 138 ~AMDGPUDAGToDAGISel() override = default; 139 140 void getAnalysisUsage(AnalysisUsage &AU) const override { 141 AU.addRequired<AMDGPUArgumentUsageInfo>(); 142 AU.addRequired<LegacyDivergenceAnalysis>(); 143 #ifdef EXPENSIVE_CHECKS 144 AU.addRequired<DominatorTreeWrapperPass>(); 145 AU.addRequired<LoopInfoWrapperPass>(); 146 #endif 147 SelectionDAGISel::getAnalysisUsage(AU); 148 } 149 150 bool matchLoadD16FromBuildVector(SDNode *N) const; 151 152 bool runOnMachineFunction(MachineFunction &MF) override; 153 void PreprocessISelDAG() override; 154 void Select(SDNode *N) override; 155 StringRef getPassName() const override; 156 void PostprocessISelDAG() override; 157 158 protected: 159 void SelectBuildVector(SDNode *N, unsigned RegClassID); 160 161 private: 162 std::pair<SDValue, SDValue> foldFrameIndex(SDValue N) const; 163 bool isNoNanSrc(SDValue N) const; 164 bool isInlineImmediate(const SDNode *N, bool Negated = false) const; 165 bool isNegInlineImmediate(const SDNode *N) const { 166 return isInlineImmediate(N, true); 167 } 168 169 bool isVGPRImm(const SDNode *N) const; 170 bool isUniformLoad(const SDNode *N) const; 171 bool isUniformBr(const SDNode *N) const; 172 173 MachineSDNode *buildSMovImm64(SDLoc &DL, uint64_t Val, EVT VT) const; 174 175 SDNode *glueCopyToM0LDSInit(SDNode *N) const; 176 SDNode *glueCopyToM0(SDNode *N, SDValue Val) const; 177 178 const TargetRegisterClass *getOperandRegClass(SDNode *N, unsigned OpNo) const; 179 virtual bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, SDValue &Offset); 180 virtual bool SelectADDRIndirect(SDValue Addr, SDValue &Base, SDValue &Offset); 181 bool isDSOffsetLegal(SDValue Base, unsigned Offset, 182 unsigned OffsetBits) const; 183 bool SelectDS1Addr1Offset(SDValue Ptr, SDValue &Base, SDValue &Offset) const; 184 bool SelectDS64Bit4ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0, 185 SDValue &Offset1) const; 186 bool SelectMUBUF(SDValue Addr, SDValue &SRsrc, SDValue &VAddr, 187 SDValue &SOffset, SDValue &Offset, SDValue &Offen, 188 SDValue &Idxen, SDValue &Addr64, SDValue &GLC, SDValue &SLC, 189 SDValue &TFE, SDValue &DLC) const; 190 bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, SDValue &VAddr, 191 SDValue &SOffset, SDValue &Offset, SDValue &GLC, 192 SDValue &SLC, SDValue &TFE, SDValue &DLC) const; 193 bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, 194 SDValue &VAddr, SDValue &SOffset, SDValue &Offset, 195 SDValue &SLC) const; 196 bool SelectMUBUFScratchOffen(SDNode *Parent, 197 SDValue Addr, SDValue &RSrc, SDValue &VAddr, 198 SDValue &SOffset, SDValue &ImmOffset) const; 199 bool SelectMUBUFScratchOffset(SDNode *Parent, 200 SDValue Addr, SDValue &SRsrc, SDValue &Soffset, 201 SDValue &Offset) const; 202 203 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &SOffset, 204 SDValue &Offset, SDValue &GLC, SDValue &SLC, 205 SDValue &TFE, SDValue &DLC) const; 206 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset, 207 SDValue &Offset, SDValue &SLC) const; 208 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset, 209 SDValue &Offset) const; 210 211 bool SelectFlatAtomic(SDNode *N, SDValue Addr, SDValue &VAddr, 212 SDValue &Offset, SDValue &SLC) const; 213 bool SelectFlatAtomicSigned(SDNode *N, SDValue Addr, SDValue &VAddr, 214 SDValue &Offset, SDValue &SLC) const; 215 216 template <bool IsSigned> 217 bool SelectFlatOffset(SDNode *N, SDValue Addr, SDValue &VAddr, 218 SDValue &Offset, SDValue &SLC) const; 219 220 bool SelectSMRDOffset(SDValue ByteOffsetNode, SDValue &Offset, 221 bool &Imm) const; 222 SDValue Expand32BitAddress(SDValue Addr) const; 223 bool SelectSMRD(SDValue Addr, SDValue &SBase, SDValue &Offset, 224 bool &Imm) const; 225 bool SelectSMRDImm(SDValue Addr, SDValue &SBase, SDValue &Offset) const; 226 bool SelectSMRDImm32(SDValue Addr, SDValue &SBase, SDValue &Offset) const; 227 bool SelectSMRDSgpr(SDValue Addr, SDValue &SBase, SDValue &Offset) const; 228 bool SelectSMRDBufferImm(SDValue Addr, SDValue &Offset) const; 229 bool SelectSMRDBufferImm32(SDValue Addr, SDValue &Offset) const; 230 bool SelectMOVRELOffset(SDValue Index, SDValue &Base, SDValue &Offset) const; 231 232 bool SelectVOP3Mods_NNaN(SDValue In, SDValue &Src, SDValue &SrcMods) const; 233 bool SelectVOP3ModsImpl(SDValue In, SDValue &Src, unsigned &SrcMods) const; 234 bool SelectVOP3Mods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 235 bool SelectVOP3NoMods(SDValue In, SDValue &Src) const; 236 bool SelectVOP3Mods0(SDValue In, SDValue &Src, SDValue &SrcMods, 237 SDValue &Clamp, SDValue &Omod) const; 238 bool SelectVOP3NoMods0(SDValue In, SDValue &Src, SDValue &SrcMods, 239 SDValue &Clamp, SDValue &Omod) const; 240 241 bool SelectVOP3Mods0Clamp0OMod(SDValue In, SDValue &Src, SDValue &SrcMods, 242 SDValue &Clamp, 243 SDValue &Omod) const; 244 245 bool SelectVOP3OMods(SDValue In, SDValue &Src, 246 SDValue &Clamp, SDValue &Omod) const; 247 248 bool SelectVOP3PMods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 249 bool SelectVOP3PMods0(SDValue In, SDValue &Src, SDValue &SrcMods, 250 SDValue &Clamp) const; 251 252 bool SelectVOP3OpSel(SDValue In, SDValue &Src, SDValue &SrcMods) const; 253 bool SelectVOP3OpSel0(SDValue In, SDValue &Src, SDValue &SrcMods, 254 SDValue &Clamp) const; 255 256 bool SelectVOP3OpSelMods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 257 bool SelectVOP3OpSelMods0(SDValue In, SDValue &Src, SDValue &SrcMods, 258 SDValue &Clamp) const; 259 bool SelectVOP3PMadMixModsImpl(SDValue In, SDValue &Src, unsigned &Mods) const; 260 bool SelectVOP3PMadMixMods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 261 262 SDValue getHi16Elt(SDValue In) const; 263 264 void SelectADD_SUB_I64(SDNode *N); 265 void SelectAddcSubb(SDNode *N); 266 void SelectUADDO_USUBO(SDNode *N); 267 void SelectDIV_SCALE(SDNode *N); 268 void SelectDIV_FMAS(SDNode *N); 269 void SelectMAD_64_32(SDNode *N); 270 void SelectFMA_W_CHAIN(SDNode *N); 271 void SelectFMUL_W_CHAIN(SDNode *N); 272 273 SDNode *getS_BFE(unsigned Opcode, const SDLoc &DL, SDValue Val, 274 uint32_t Offset, uint32_t Width); 275 void SelectS_BFEFromShifts(SDNode *N); 276 void SelectS_BFE(SDNode *N); 277 bool isCBranchSCC(const SDNode *N) const; 278 void SelectBRCOND(SDNode *N); 279 void SelectFMAD_FMA(SDNode *N); 280 void SelectATOMIC_CMP_SWAP(SDNode *N); 281 void SelectDSAppendConsume(SDNode *N, unsigned IntrID); 282 void SelectDS_GWS(SDNode *N, unsigned IntrID); 283 void SelectINTRINSIC_W_CHAIN(SDNode *N); 284 void SelectINTRINSIC_VOID(SDNode *N); 285 286 protected: 287 // Include the pieces autogenerated from the target description. 288 #include "AMDGPUGenDAGISel.inc" 289 }; 290 291 class R600DAGToDAGISel : public AMDGPUDAGToDAGISel { 292 const R600Subtarget *Subtarget; 293 294 bool isConstantLoad(const MemSDNode *N, int cbID) const; 295 bool SelectGlobalValueConstantOffset(SDValue Addr, SDValue& IntPtr); 296 bool SelectGlobalValueVariableOffset(SDValue Addr, SDValue &BaseReg, 297 SDValue& Offset); 298 public: 299 explicit R600DAGToDAGISel(TargetMachine *TM, CodeGenOpt::Level OptLevel) : 300 AMDGPUDAGToDAGISel(TM, OptLevel) {} 301 302 void Select(SDNode *N) override; 303 304 bool SelectADDRIndirect(SDValue Addr, SDValue &Base, 305 SDValue &Offset) override; 306 bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, 307 SDValue &Offset) override; 308 309 bool runOnMachineFunction(MachineFunction &MF) override; 310 311 void PreprocessISelDAG() override {} 312 313 protected: 314 // Include the pieces autogenerated from the target description. 315 #include "R600GenDAGISel.inc" 316 }; 317 318 static SDValue stripBitcast(SDValue Val) { 319 return Val.getOpcode() == ISD::BITCAST ? Val.getOperand(0) : Val; 320 } 321 322 // Figure out if this is really an extract of the high 16-bits of a dword. 323 static bool isExtractHiElt(SDValue In, SDValue &Out) { 324 In = stripBitcast(In); 325 if (In.getOpcode() != ISD::TRUNCATE) 326 return false; 327 328 SDValue Srl = In.getOperand(0); 329 if (Srl.getOpcode() == ISD::SRL) { 330 if (ConstantSDNode *ShiftAmt = dyn_cast<ConstantSDNode>(Srl.getOperand(1))) { 331 if (ShiftAmt->getZExtValue() == 16) { 332 Out = stripBitcast(Srl.getOperand(0)); 333 return true; 334 } 335 } 336 } 337 338 return false; 339 } 340 341 // Look through operations that obscure just looking at the low 16-bits of the 342 // same register. 343 static SDValue stripExtractLoElt(SDValue In) { 344 if (In.getOpcode() == ISD::TRUNCATE) { 345 SDValue Src = In.getOperand(0); 346 if (Src.getValueType().getSizeInBits() == 32) 347 return stripBitcast(Src); 348 } 349 350 return In; 351 } 352 353 } // end anonymous namespace 354 355 INITIALIZE_PASS_BEGIN(AMDGPUDAGToDAGISel, "amdgpu-isel", 356 "AMDGPU DAG->DAG Pattern Instruction Selection", false, false) 357 INITIALIZE_PASS_DEPENDENCY(AMDGPUArgumentUsageInfo) 358 INITIALIZE_PASS_DEPENDENCY(AMDGPUPerfHintAnalysis) 359 INITIALIZE_PASS_DEPENDENCY(LegacyDivergenceAnalysis) 360 #ifdef EXPENSIVE_CHECKS 361 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 362 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) 363 #endif 364 INITIALIZE_PASS_END(AMDGPUDAGToDAGISel, "amdgpu-isel", 365 "AMDGPU DAG->DAG Pattern Instruction Selection", false, false) 366 367 /// This pass converts a legalized DAG into a AMDGPU-specific 368 // DAG, ready for instruction scheduling. 369 FunctionPass *llvm::createAMDGPUISelDag(TargetMachine *TM, 370 CodeGenOpt::Level OptLevel) { 371 return new AMDGPUDAGToDAGISel(TM, OptLevel); 372 } 373 374 /// This pass converts a legalized DAG into a R600-specific 375 // DAG, ready for instruction scheduling. 376 FunctionPass *llvm::createR600ISelDag(TargetMachine *TM, 377 CodeGenOpt::Level OptLevel) { 378 return new R600DAGToDAGISel(TM, OptLevel); 379 } 380 381 bool AMDGPUDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 382 #ifdef EXPENSIVE_CHECKS 383 DominatorTree & DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 384 LoopInfo * LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 385 for (auto &L : LI->getLoopsInPreorder()) { 386 assert(L->isLCSSAForm(DT)); 387 } 388 #endif 389 Subtarget = &MF.getSubtarget<GCNSubtarget>(); 390 return SelectionDAGISel::runOnMachineFunction(MF); 391 } 392 393 bool AMDGPUDAGToDAGISel::matchLoadD16FromBuildVector(SDNode *N) const { 394 assert(Subtarget->d16PreservesUnusedBits()); 395 MVT VT = N->getValueType(0).getSimpleVT(); 396 if (VT != MVT::v2i16 && VT != MVT::v2f16) 397 return false; 398 399 SDValue Lo = N->getOperand(0); 400 SDValue Hi = N->getOperand(1); 401 402 LoadSDNode *LdHi = dyn_cast<LoadSDNode>(stripBitcast(Hi)); 403 404 // build_vector lo, (load ptr) -> load_d16_hi ptr, lo 405 // build_vector lo, (zextload ptr from i8) -> load_d16_hi_u8 ptr, lo 406 // build_vector lo, (sextload ptr from i8) -> load_d16_hi_i8 ptr, lo 407 408 // Need to check for possible indirect dependencies on the other half of the 409 // vector to avoid introducing a cycle. 410 if (LdHi && Hi.hasOneUse() && !LdHi->isPredecessorOf(Lo.getNode())) { 411 SDVTList VTList = CurDAG->getVTList(VT, MVT::Other); 412 413 SDValue TiedIn = CurDAG->getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), VT, Lo); 414 SDValue Ops[] = { 415 LdHi->getChain(), LdHi->getBasePtr(), TiedIn 416 }; 417 418 unsigned LoadOp = AMDGPUISD::LOAD_D16_HI; 419 if (LdHi->getMemoryVT() == MVT::i8) { 420 LoadOp = LdHi->getExtensionType() == ISD::SEXTLOAD ? 421 AMDGPUISD::LOAD_D16_HI_I8 : AMDGPUISD::LOAD_D16_HI_U8; 422 } else { 423 assert(LdHi->getMemoryVT() == MVT::i16); 424 } 425 426 SDValue NewLoadHi = 427 CurDAG->getMemIntrinsicNode(LoadOp, SDLoc(LdHi), VTList, 428 Ops, LdHi->getMemoryVT(), 429 LdHi->getMemOperand()); 430 431 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), NewLoadHi); 432 CurDAG->ReplaceAllUsesOfValueWith(SDValue(LdHi, 1), NewLoadHi.getValue(1)); 433 return true; 434 } 435 436 // build_vector (load ptr), hi -> load_d16_lo ptr, hi 437 // build_vector (zextload ptr from i8), hi -> load_d16_lo_u8 ptr, hi 438 // build_vector (sextload ptr from i8), hi -> load_d16_lo_i8 ptr, hi 439 LoadSDNode *LdLo = dyn_cast<LoadSDNode>(stripBitcast(Lo)); 440 if (LdLo && Lo.hasOneUse()) { 441 SDValue TiedIn = getHi16Elt(Hi); 442 if (!TiedIn || LdLo->isPredecessorOf(TiedIn.getNode())) 443 return false; 444 445 SDVTList VTList = CurDAG->getVTList(VT, MVT::Other); 446 unsigned LoadOp = AMDGPUISD::LOAD_D16_LO; 447 if (LdLo->getMemoryVT() == MVT::i8) { 448 LoadOp = LdLo->getExtensionType() == ISD::SEXTLOAD ? 449 AMDGPUISD::LOAD_D16_LO_I8 : AMDGPUISD::LOAD_D16_LO_U8; 450 } else { 451 assert(LdLo->getMemoryVT() == MVT::i16); 452 } 453 454 TiedIn = CurDAG->getNode(ISD::BITCAST, SDLoc(N), VT, TiedIn); 455 456 SDValue Ops[] = { 457 LdLo->getChain(), LdLo->getBasePtr(), TiedIn 458 }; 459 460 SDValue NewLoadLo = 461 CurDAG->getMemIntrinsicNode(LoadOp, SDLoc(LdLo), VTList, 462 Ops, LdLo->getMemoryVT(), 463 LdLo->getMemOperand()); 464 465 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), NewLoadLo); 466 CurDAG->ReplaceAllUsesOfValueWith(SDValue(LdLo, 1), NewLoadLo.getValue(1)); 467 return true; 468 } 469 470 return false; 471 } 472 473 void AMDGPUDAGToDAGISel::PreprocessISelDAG() { 474 if (!Subtarget->d16PreservesUnusedBits()) 475 return; 476 477 SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end(); 478 479 bool MadeChange = false; 480 while (Position != CurDAG->allnodes_begin()) { 481 SDNode *N = &*--Position; 482 if (N->use_empty()) 483 continue; 484 485 switch (N->getOpcode()) { 486 case ISD::BUILD_VECTOR: 487 MadeChange |= matchLoadD16FromBuildVector(N); 488 break; 489 default: 490 break; 491 } 492 } 493 494 if (MadeChange) { 495 CurDAG->RemoveDeadNodes(); 496 LLVM_DEBUG(dbgs() << "After PreProcess:\n"; 497 CurDAG->dump();); 498 } 499 } 500 501 bool AMDGPUDAGToDAGISel::isNoNanSrc(SDValue N) const { 502 if (TM.Options.NoNaNsFPMath) 503 return true; 504 505 // TODO: Move into isKnownNeverNaN 506 if (N->getFlags().isDefined()) 507 return N->getFlags().hasNoNaNs(); 508 509 return CurDAG->isKnownNeverNaN(N); 510 } 511 512 bool AMDGPUDAGToDAGISel::isInlineImmediate(const SDNode *N, 513 bool Negated) const { 514 if (N->isUndef()) 515 return true; 516 517 const SIInstrInfo *TII = Subtarget->getInstrInfo(); 518 if (Negated) { 519 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) 520 return TII->isInlineConstant(-C->getAPIntValue()); 521 522 if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N)) 523 return TII->isInlineConstant(-C->getValueAPF().bitcastToAPInt()); 524 525 } else { 526 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) 527 return TII->isInlineConstant(C->getAPIntValue()); 528 529 if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N)) 530 return TII->isInlineConstant(C->getValueAPF().bitcastToAPInt()); 531 } 532 533 return false; 534 } 535 536 /// Determine the register class for \p OpNo 537 /// \returns The register class of the virtual register that will be used for 538 /// the given operand number \OpNo or NULL if the register class cannot be 539 /// determined. 540 const TargetRegisterClass *AMDGPUDAGToDAGISel::getOperandRegClass(SDNode *N, 541 unsigned OpNo) const { 542 if (!N->isMachineOpcode()) { 543 if (N->getOpcode() == ISD::CopyToReg) { 544 unsigned Reg = cast<RegisterSDNode>(N->getOperand(1))->getReg(); 545 if (TargetRegisterInfo::isVirtualRegister(Reg)) { 546 MachineRegisterInfo &MRI = CurDAG->getMachineFunction().getRegInfo(); 547 return MRI.getRegClass(Reg); 548 } 549 550 const SIRegisterInfo *TRI 551 = static_cast<const GCNSubtarget *>(Subtarget)->getRegisterInfo(); 552 return TRI->getPhysRegClass(Reg); 553 } 554 555 return nullptr; 556 } 557 558 switch (N->getMachineOpcode()) { 559 default: { 560 const MCInstrDesc &Desc = 561 Subtarget->getInstrInfo()->get(N->getMachineOpcode()); 562 unsigned OpIdx = Desc.getNumDefs() + OpNo; 563 if (OpIdx >= Desc.getNumOperands()) 564 return nullptr; 565 int RegClass = Desc.OpInfo[OpIdx].RegClass; 566 if (RegClass == -1) 567 return nullptr; 568 569 return Subtarget->getRegisterInfo()->getRegClass(RegClass); 570 } 571 case AMDGPU::REG_SEQUENCE: { 572 unsigned RCID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); 573 const TargetRegisterClass *SuperRC = 574 Subtarget->getRegisterInfo()->getRegClass(RCID); 575 576 SDValue SubRegOp = N->getOperand(OpNo + 1); 577 unsigned SubRegIdx = cast<ConstantSDNode>(SubRegOp)->getZExtValue(); 578 return Subtarget->getRegisterInfo()->getSubClassWithSubReg(SuperRC, 579 SubRegIdx); 580 } 581 } 582 } 583 584 SDNode *AMDGPUDAGToDAGISel::glueCopyToM0(SDNode *N, SDValue Val) const { 585 const SITargetLowering& Lowering = 586 *static_cast<const SITargetLowering*>(getTargetLowering()); 587 588 assert(N->getOperand(0).getValueType() == MVT::Other && "Expected chain"); 589 590 SDValue M0 = Lowering.copyToM0(*CurDAG, N->getOperand(0), SDLoc(N), 591 Val); 592 593 SDValue Glue = M0.getValue(1); 594 595 SmallVector <SDValue, 8> Ops; 596 Ops.push_back(M0); // Replace the chain. 597 for (unsigned i = 1, e = N->getNumOperands(); i != e; ++i) 598 Ops.push_back(N->getOperand(i)); 599 600 Ops.push_back(Glue); 601 return CurDAG->MorphNodeTo(N, N->getOpcode(), N->getVTList(), Ops); 602 } 603 604 SDNode *AMDGPUDAGToDAGISel::glueCopyToM0LDSInit(SDNode *N) const { 605 unsigned AS = cast<MemSDNode>(N)->getAddressSpace(); 606 if (AS == AMDGPUAS::LOCAL_ADDRESS) { 607 if (Subtarget->ldsRequiresM0Init()) 608 return glueCopyToM0(N, CurDAG->getTargetConstant(-1, SDLoc(N), MVT::i32)); 609 } else if (AS == AMDGPUAS::REGION_ADDRESS) { 610 MachineFunction &MF = CurDAG->getMachineFunction(); 611 unsigned Value = MF.getInfo<SIMachineFunctionInfo>()->getGDSSize(); 612 return 613 glueCopyToM0(N, CurDAG->getTargetConstant(Value, SDLoc(N), MVT::i32)); 614 } 615 return N; 616 } 617 618 MachineSDNode *AMDGPUDAGToDAGISel::buildSMovImm64(SDLoc &DL, uint64_t Imm, 619 EVT VT) const { 620 SDNode *Lo = CurDAG->getMachineNode( 621 AMDGPU::S_MOV_B32, DL, MVT::i32, 622 CurDAG->getConstant(Imm & 0xFFFFFFFF, DL, MVT::i32)); 623 SDNode *Hi = 624 CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, 625 CurDAG->getConstant(Imm >> 32, DL, MVT::i32)); 626 const SDValue Ops[] = { 627 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32), 628 SDValue(Lo, 0), CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32), 629 SDValue(Hi, 0), CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32)}; 630 631 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, VT, Ops); 632 } 633 634 static unsigned selectSGPRVectorRegClassID(unsigned NumVectorElts) { 635 switch (NumVectorElts) { 636 case 1: 637 return AMDGPU::SReg_32_XM0RegClassID; 638 case 2: 639 return AMDGPU::SReg_64RegClassID; 640 case 3: 641 return AMDGPU::SGPR_96RegClassID; 642 case 4: 643 return AMDGPU::SReg_128RegClassID; 644 case 5: 645 return AMDGPU::SGPR_160RegClassID; 646 case 8: 647 return AMDGPU::SReg_256RegClassID; 648 case 16: 649 return AMDGPU::SReg_512RegClassID; 650 } 651 652 llvm_unreachable("invalid vector size"); 653 } 654 655 void AMDGPUDAGToDAGISel::SelectBuildVector(SDNode *N, unsigned RegClassID) { 656 EVT VT = N->getValueType(0); 657 unsigned NumVectorElts = VT.getVectorNumElements(); 658 EVT EltVT = VT.getVectorElementType(); 659 SDLoc DL(N); 660 SDValue RegClass = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32); 661 662 if (NumVectorElts == 1) { 663 CurDAG->SelectNodeTo(N, AMDGPU::COPY_TO_REGCLASS, EltVT, N->getOperand(0), 664 RegClass); 665 return; 666 } 667 668 assert(NumVectorElts <= 16 && "Vectors with more than 16 elements not " 669 "supported yet"); 670 // 16 = Max Num Vector Elements 671 // 2 = 2 REG_SEQUENCE operands per element (value, subreg index) 672 // 1 = Vector Register Class 673 SmallVector<SDValue, 16 * 2 + 1> RegSeqArgs(NumVectorElts * 2 + 1); 674 675 RegSeqArgs[0] = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32); 676 bool IsRegSeq = true; 677 unsigned NOps = N->getNumOperands(); 678 for (unsigned i = 0; i < NOps; i++) { 679 // XXX: Why is this here? 680 if (isa<RegisterSDNode>(N->getOperand(i))) { 681 IsRegSeq = false; 682 break; 683 } 684 unsigned Sub = AMDGPURegisterInfo::getSubRegFromChannel(i); 685 RegSeqArgs[1 + (2 * i)] = N->getOperand(i); 686 RegSeqArgs[1 + (2 * i) + 1] = CurDAG->getTargetConstant(Sub, DL, MVT::i32); 687 } 688 if (NOps != NumVectorElts) { 689 // Fill in the missing undef elements if this was a scalar_to_vector. 690 assert(N->getOpcode() == ISD::SCALAR_TO_VECTOR && NOps < NumVectorElts); 691 MachineSDNode *ImpDef = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, 692 DL, EltVT); 693 for (unsigned i = NOps; i < NumVectorElts; ++i) { 694 unsigned Sub = AMDGPURegisterInfo::getSubRegFromChannel(i); 695 RegSeqArgs[1 + (2 * i)] = SDValue(ImpDef, 0); 696 RegSeqArgs[1 + (2 * i) + 1] = 697 CurDAG->getTargetConstant(Sub, DL, MVT::i32); 698 } 699 } 700 701 if (!IsRegSeq) 702 SelectCode(N); 703 CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, N->getVTList(), RegSeqArgs); 704 } 705 706 void AMDGPUDAGToDAGISel::Select(SDNode *N) { 707 unsigned int Opc = N->getOpcode(); 708 if (N->isMachineOpcode()) { 709 N->setNodeId(-1); 710 return; // Already selected. 711 } 712 713 if (isa<AtomicSDNode>(N) || 714 (Opc == AMDGPUISD::ATOMIC_INC || Opc == AMDGPUISD::ATOMIC_DEC || 715 Opc == ISD::ATOMIC_LOAD_FADD || 716 Opc == AMDGPUISD::ATOMIC_LOAD_FMIN || 717 Opc == AMDGPUISD::ATOMIC_LOAD_FMAX)) 718 N = glueCopyToM0LDSInit(N); 719 720 switch (Opc) { 721 default: 722 break; 723 // We are selecting i64 ADD here instead of custom lower it during 724 // DAG legalization, so we can fold some i64 ADDs used for address 725 // calculation into the LOAD and STORE instructions. 726 case ISD::ADDC: 727 case ISD::ADDE: 728 case ISD::SUBC: 729 case ISD::SUBE: { 730 if (N->getValueType(0) != MVT::i64) 731 break; 732 733 SelectADD_SUB_I64(N); 734 return; 735 } 736 case ISD::ADDCARRY: 737 case ISD::SUBCARRY: 738 if (N->getValueType(0) != MVT::i32) 739 break; 740 741 SelectAddcSubb(N); 742 return; 743 case ISD::UADDO: 744 case ISD::USUBO: { 745 SelectUADDO_USUBO(N); 746 return; 747 } 748 case AMDGPUISD::FMUL_W_CHAIN: { 749 SelectFMUL_W_CHAIN(N); 750 return; 751 } 752 case AMDGPUISD::FMA_W_CHAIN: { 753 SelectFMA_W_CHAIN(N); 754 return; 755 } 756 757 case ISD::SCALAR_TO_VECTOR: 758 case ISD::BUILD_VECTOR: { 759 EVT VT = N->getValueType(0); 760 unsigned NumVectorElts = VT.getVectorNumElements(); 761 if (VT.getScalarSizeInBits() == 16) { 762 if (Opc == ISD::BUILD_VECTOR && NumVectorElts == 2) { 763 if (SDNode *Packed = packConstantV2I16(N, *CurDAG)) { 764 ReplaceNode(N, Packed); 765 return; 766 } 767 } 768 769 break; 770 } 771 772 assert(VT.getVectorElementType().bitsEq(MVT::i32)); 773 unsigned RegClassID = selectSGPRVectorRegClassID(NumVectorElts); 774 SelectBuildVector(N, RegClassID); 775 return; 776 } 777 case ISD::BUILD_PAIR: { 778 SDValue RC, SubReg0, SubReg1; 779 SDLoc DL(N); 780 if (N->getValueType(0) == MVT::i128) { 781 RC = CurDAG->getTargetConstant(AMDGPU::SReg_128RegClassID, DL, MVT::i32); 782 SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32); 783 SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32); 784 } else if (N->getValueType(0) == MVT::i64) { 785 RC = CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32); 786 SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32); 787 SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32); 788 } else { 789 llvm_unreachable("Unhandled value type for BUILD_PAIR"); 790 } 791 const SDValue Ops[] = { RC, N->getOperand(0), SubReg0, 792 N->getOperand(1), SubReg1 }; 793 ReplaceNode(N, CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, 794 N->getValueType(0), Ops)); 795 return; 796 } 797 798 case ISD::Constant: 799 case ISD::ConstantFP: { 800 if (N->getValueType(0).getSizeInBits() != 64 || isInlineImmediate(N)) 801 break; 802 803 uint64_t Imm; 804 if (ConstantFPSDNode *FP = dyn_cast<ConstantFPSDNode>(N)) 805 Imm = FP->getValueAPF().bitcastToAPInt().getZExtValue(); 806 else { 807 ConstantSDNode *C = cast<ConstantSDNode>(N); 808 Imm = C->getZExtValue(); 809 } 810 811 SDLoc DL(N); 812 ReplaceNode(N, buildSMovImm64(DL, Imm, N->getValueType(0))); 813 return; 814 } 815 case ISD::LOAD: 816 case ISD::STORE: 817 case ISD::ATOMIC_LOAD: 818 case ISD::ATOMIC_STORE: { 819 N = glueCopyToM0LDSInit(N); 820 break; 821 } 822 823 case AMDGPUISD::BFE_I32: 824 case AMDGPUISD::BFE_U32: { 825 // There is a scalar version available, but unlike the vector version which 826 // has a separate operand for the offset and width, the scalar version packs 827 // the width and offset into a single operand. Try to move to the scalar 828 // version if the offsets are constant, so that we can try to keep extended 829 // loads of kernel arguments in SGPRs. 830 831 // TODO: Technically we could try to pattern match scalar bitshifts of 832 // dynamic values, but it's probably not useful. 833 ConstantSDNode *Offset = dyn_cast<ConstantSDNode>(N->getOperand(1)); 834 if (!Offset) 835 break; 836 837 ConstantSDNode *Width = dyn_cast<ConstantSDNode>(N->getOperand(2)); 838 if (!Width) 839 break; 840 841 bool Signed = Opc == AMDGPUISD::BFE_I32; 842 843 uint32_t OffsetVal = Offset->getZExtValue(); 844 uint32_t WidthVal = Width->getZExtValue(); 845 846 ReplaceNode(N, getS_BFE(Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32, 847 SDLoc(N), N->getOperand(0), OffsetVal, WidthVal)); 848 return; 849 } 850 case AMDGPUISD::DIV_SCALE: { 851 SelectDIV_SCALE(N); 852 return; 853 } 854 case AMDGPUISD::DIV_FMAS: { 855 SelectDIV_FMAS(N); 856 return; 857 } 858 case AMDGPUISD::MAD_I64_I32: 859 case AMDGPUISD::MAD_U64_U32: { 860 SelectMAD_64_32(N); 861 return; 862 } 863 case ISD::CopyToReg: { 864 const SITargetLowering& Lowering = 865 *static_cast<const SITargetLowering*>(getTargetLowering()); 866 N = Lowering.legalizeTargetIndependentNode(N, *CurDAG); 867 break; 868 } 869 case ISD::AND: 870 case ISD::SRL: 871 case ISD::SRA: 872 case ISD::SIGN_EXTEND_INREG: 873 if (N->getValueType(0) != MVT::i32) 874 break; 875 876 SelectS_BFE(N); 877 return; 878 case ISD::BRCOND: 879 SelectBRCOND(N); 880 return; 881 case ISD::FMAD: 882 case ISD::FMA: 883 SelectFMAD_FMA(N); 884 return; 885 case AMDGPUISD::ATOMIC_CMP_SWAP: 886 SelectATOMIC_CMP_SWAP(N); 887 return; 888 case AMDGPUISD::CVT_PKRTZ_F16_F32: 889 case AMDGPUISD::CVT_PKNORM_I16_F32: 890 case AMDGPUISD::CVT_PKNORM_U16_F32: 891 case AMDGPUISD::CVT_PK_U16_U32: 892 case AMDGPUISD::CVT_PK_I16_I32: { 893 // Hack around using a legal type if f16 is illegal. 894 if (N->getValueType(0) == MVT::i32) { 895 MVT NewVT = Opc == AMDGPUISD::CVT_PKRTZ_F16_F32 ? MVT::v2f16 : MVT::v2i16; 896 N = CurDAG->MorphNodeTo(N, N->getOpcode(), CurDAG->getVTList(NewVT), 897 { N->getOperand(0), N->getOperand(1) }); 898 SelectCode(N); 899 return; 900 } 901 902 break; 903 } 904 case ISD::INTRINSIC_W_CHAIN: { 905 SelectINTRINSIC_W_CHAIN(N); 906 return; 907 } 908 case ISD::INTRINSIC_VOID: { 909 SelectINTRINSIC_VOID(N); 910 return; 911 } 912 } 913 914 SelectCode(N); 915 } 916 917 bool AMDGPUDAGToDAGISel::isUniformBr(const SDNode *N) const { 918 const BasicBlock *BB = FuncInfo->MBB->getBasicBlock(); 919 const Instruction *Term = BB->getTerminator(); 920 return Term->getMetadata("amdgpu.uniform") || 921 Term->getMetadata("structurizecfg.uniform"); 922 } 923 924 StringRef AMDGPUDAGToDAGISel::getPassName() const { 925 return "AMDGPU DAG->DAG Pattern Instruction Selection"; 926 } 927 928 //===----------------------------------------------------------------------===// 929 // Complex Patterns 930 //===----------------------------------------------------------------------===// 931 932 bool AMDGPUDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base, 933 SDValue &Offset) { 934 return false; 935 } 936 937 bool AMDGPUDAGToDAGISel::SelectADDRIndirect(SDValue Addr, SDValue &Base, 938 SDValue &Offset) { 939 ConstantSDNode *C; 940 SDLoc DL(Addr); 941 942 if ((C = dyn_cast<ConstantSDNode>(Addr))) { 943 Base = CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32); 944 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 945 } else if ((Addr.getOpcode() == AMDGPUISD::DWORDADDR) && 946 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(0)))) { 947 Base = CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32); 948 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 949 } else if ((Addr.getOpcode() == ISD::ADD || Addr.getOpcode() == ISD::OR) && 950 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) { 951 Base = Addr.getOperand(0); 952 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 953 } else { 954 Base = Addr; 955 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); 956 } 957 958 return true; 959 } 960 961 // FIXME: Should only handle addcarry/subcarry 962 void AMDGPUDAGToDAGISel::SelectADD_SUB_I64(SDNode *N) { 963 SDLoc DL(N); 964 SDValue LHS = N->getOperand(0); 965 SDValue RHS = N->getOperand(1); 966 967 unsigned Opcode = N->getOpcode(); 968 bool ConsumeCarry = (Opcode == ISD::ADDE || Opcode == ISD::SUBE); 969 bool ProduceCarry = 970 ConsumeCarry || Opcode == ISD::ADDC || Opcode == ISD::SUBC; 971 bool IsAdd = Opcode == ISD::ADD || Opcode == ISD::ADDC || Opcode == ISD::ADDE; 972 973 SDValue Sub0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32); 974 SDValue Sub1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32); 975 976 SDNode *Lo0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 977 DL, MVT::i32, LHS, Sub0); 978 SDNode *Hi0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 979 DL, MVT::i32, LHS, Sub1); 980 981 SDNode *Lo1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 982 DL, MVT::i32, RHS, Sub0); 983 SDNode *Hi1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 984 DL, MVT::i32, RHS, Sub1); 985 986 SDVTList VTList = CurDAG->getVTList(MVT::i32, MVT::Glue); 987 988 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32; 989 unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32; 990 991 SDNode *AddLo; 992 if (!ConsumeCarry) { 993 SDValue Args[] = { SDValue(Lo0, 0), SDValue(Lo1, 0) }; 994 AddLo = CurDAG->getMachineNode(Opc, DL, VTList, Args); 995 } else { 996 SDValue Args[] = { SDValue(Lo0, 0), SDValue(Lo1, 0), N->getOperand(2) }; 997 AddLo = CurDAG->getMachineNode(CarryOpc, DL, VTList, Args); 998 } 999 SDValue AddHiArgs[] = { 1000 SDValue(Hi0, 0), 1001 SDValue(Hi1, 0), 1002 SDValue(AddLo, 1) 1003 }; 1004 SDNode *AddHi = CurDAG->getMachineNode(CarryOpc, DL, VTList, AddHiArgs); 1005 1006 SDValue RegSequenceArgs[] = { 1007 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32), 1008 SDValue(AddLo,0), 1009 Sub0, 1010 SDValue(AddHi,0), 1011 Sub1, 1012 }; 1013 SDNode *RegSequence = CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, DL, 1014 MVT::i64, RegSequenceArgs); 1015 1016 if (ProduceCarry) { 1017 // Replace the carry-use 1018 ReplaceUses(SDValue(N, 1), SDValue(AddHi, 1)); 1019 } 1020 1021 // Replace the remaining uses. 1022 ReplaceNode(N, RegSequence); 1023 } 1024 1025 void AMDGPUDAGToDAGISel::SelectAddcSubb(SDNode *N) { 1026 SDLoc DL(N); 1027 SDValue LHS = N->getOperand(0); 1028 SDValue RHS = N->getOperand(1); 1029 SDValue CI = N->getOperand(2); 1030 1031 unsigned Opc = N->getOpcode() == ISD::ADDCARRY ? AMDGPU::V_ADDC_U32_e64 1032 : AMDGPU::V_SUBB_U32_e64; 1033 CurDAG->SelectNodeTo( 1034 N, Opc, N->getVTList(), 1035 {LHS, RHS, CI, CurDAG->getTargetConstant(0, {}, MVT::i1) /*clamp bit*/}); 1036 } 1037 1038 void AMDGPUDAGToDAGISel::SelectUADDO_USUBO(SDNode *N) { 1039 // The name of the opcodes are misleading. v_add_i32/v_sub_i32 have unsigned 1040 // carry out despite the _i32 name. These were renamed in VI to _U32. 1041 // FIXME: We should probably rename the opcodes here. 1042 unsigned Opc = N->getOpcode() == ISD::UADDO ? 1043 AMDGPU::V_ADD_I32_e64 : AMDGPU::V_SUB_I32_e64; 1044 1045 CurDAG->SelectNodeTo( 1046 N, Opc, N->getVTList(), 1047 {N->getOperand(0), N->getOperand(1), 1048 CurDAG->getTargetConstant(0, {}, MVT::i1) /*clamp bit*/}); 1049 } 1050 1051 void AMDGPUDAGToDAGISel::SelectFMA_W_CHAIN(SDNode *N) { 1052 SDLoc SL(N); 1053 // src0_modifiers, src0, src1_modifiers, src1, src2_modifiers, src2, clamp, omod 1054 SDValue Ops[10]; 1055 1056 SelectVOP3Mods0(N->getOperand(1), Ops[1], Ops[0], Ops[6], Ops[7]); 1057 SelectVOP3Mods(N->getOperand(2), Ops[3], Ops[2]); 1058 SelectVOP3Mods(N->getOperand(3), Ops[5], Ops[4]); 1059 Ops[8] = N->getOperand(0); 1060 Ops[9] = N->getOperand(4); 1061 1062 CurDAG->SelectNodeTo(N, AMDGPU::V_FMA_F32, N->getVTList(), Ops); 1063 } 1064 1065 void AMDGPUDAGToDAGISel::SelectFMUL_W_CHAIN(SDNode *N) { 1066 SDLoc SL(N); 1067 // src0_modifiers, src0, src1_modifiers, src1, clamp, omod 1068 SDValue Ops[8]; 1069 1070 SelectVOP3Mods0(N->getOperand(1), Ops[1], Ops[0], Ops[4], Ops[5]); 1071 SelectVOP3Mods(N->getOperand(2), Ops[3], Ops[2]); 1072 Ops[6] = N->getOperand(0); 1073 Ops[7] = N->getOperand(3); 1074 1075 CurDAG->SelectNodeTo(N, AMDGPU::V_MUL_F32_e64, N->getVTList(), Ops); 1076 } 1077 1078 // We need to handle this here because tablegen doesn't support matching 1079 // instructions with multiple outputs. 1080 void AMDGPUDAGToDAGISel::SelectDIV_SCALE(SDNode *N) { 1081 SDLoc SL(N); 1082 EVT VT = N->getValueType(0); 1083 1084 assert(VT == MVT::f32 || VT == MVT::f64); 1085 1086 unsigned Opc 1087 = (VT == MVT::f64) ? AMDGPU::V_DIV_SCALE_F64 : AMDGPU::V_DIV_SCALE_F32; 1088 1089 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2) }; 1090 CurDAG->SelectNodeTo(N, Opc, N->getVTList(), Ops); 1091 } 1092 1093 void AMDGPUDAGToDAGISel::SelectDIV_FMAS(SDNode *N) { 1094 const GCNSubtarget *ST = static_cast<const GCNSubtarget *>(Subtarget); 1095 const SIRegisterInfo *TRI = ST->getRegisterInfo(); 1096 1097 SDLoc SL(N); 1098 EVT VT = N->getValueType(0); 1099 1100 assert(VT == MVT::f32 || VT == MVT::f64); 1101 1102 unsigned Opc 1103 = (VT == MVT::f64) ? AMDGPU::V_DIV_FMAS_F64 : AMDGPU::V_DIV_FMAS_F32; 1104 1105 SDValue CarryIn = N->getOperand(3); 1106 // V_DIV_FMAS implicitly reads VCC. 1107 SDValue VCC = CurDAG->getCopyToReg(CurDAG->getEntryNode(), SL, 1108 TRI->getVCC(), CarryIn, SDValue()); 1109 1110 SDValue Ops[10]; 1111 1112 SelectVOP3Mods0(N->getOperand(0), Ops[1], Ops[0], Ops[6], Ops[7]); 1113 SelectVOP3Mods(N->getOperand(1), Ops[3], Ops[2]); 1114 SelectVOP3Mods(N->getOperand(2), Ops[5], Ops[4]); 1115 1116 Ops[8] = VCC; 1117 Ops[9] = VCC.getValue(1); 1118 1119 CurDAG->SelectNodeTo(N, Opc, N->getVTList(), Ops); 1120 } 1121 1122 // We need to handle this here because tablegen doesn't support matching 1123 // instructions with multiple outputs. 1124 void AMDGPUDAGToDAGISel::SelectMAD_64_32(SDNode *N) { 1125 SDLoc SL(N); 1126 bool Signed = N->getOpcode() == AMDGPUISD::MAD_I64_I32; 1127 unsigned Opc = Signed ? AMDGPU::V_MAD_I64_I32 : AMDGPU::V_MAD_U64_U32; 1128 1129 SDValue Clamp = CurDAG->getTargetConstant(0, SL, MVT::i1); 1130 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 1131 Clamp }; 1132 CurDAG->SelectNodeTo(N, Opc, N->getVTList(), Ops); 1133 } 1134 1135 bool AMDGPUDAGToDAGISel::isDSOffsetLegal(SDValue Base, unsigned Offset, 1136 unsigned OffsetBits) const { 1137 if ((OffsetBits == 16 && !isUInt<16>(Offset)) || 1138 (OffsetBits == 8 && !isUInt<8>(Offset))) 1139 return false; 1140 1141 if (Subtarget->hasUsableDSOffset() || 1142 Subtarget->unsafeDSOffsetFoldingEnabled()) 1143 return true; 1144 1145 // On Southern Islands instruction with a negative base value and an offset 1146 // don't seem to work. 1147 return CurDAG->SignBitIsZero(Base); 1148 } 1149 1150 bool AMDGPUDAGToDAGISel::SelectDS1Addr1Offset(SDValue Addr, SDValue &Base, 1151 SDValue &Offset) const { 1152 SDLoc DL(Addr); 1153 if (CurDAG->isBaseWithConstantOffset(Addr)) { 1154 SDValue N0 = Addr.getOperand(0); 1155 SDValue N1 = Addr.getOperand(1); 1156 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 1157 if (isDSOffsetLegal(N0, C1->getSExtValue(), 16)) { 1158 // (add n0, c0) 1159 Base = N0; 1160 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16); 1161 return true; 1162 } 1163 } else if (Addr.getOpcode() == ISD::SUB) { 1164 // sub C, x -> add (sub 0, x), C 1165 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Addr.getOperand(0))) { 1166 int64_t ByteOffset = C->getSExtValue(); 1167 if (isUInt<16>(ByteOffset)) { 1168 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32); 1169 1170 // XXX - This is kind of hacky. Create a dummy sub node so we can check 1171 // the known bits in isDSOffsetLegal. We need to emit the selected node 1172 // here, so this is thrown away. 1173 SDValue Sub = CurDAG->getNode(ISD::SUB, DL, MVT::i32, 1174 Zero, Addr.getOperand(1)); 1175 1176 if (isDSOffsetLegal(Sub, ByteOffset, 16)) { 1177 SmallVector<SDValue, 3> Opnds; 1178 Opnds.push_back(Zero); 1179 Opnds.push_back(Addr.getOperand(1)); 1180 1181 // FIXME: Select to VOP3 version for with-carry. 1182 unsigned SubOp = AMDGPU::V_SUB_I32_e32; 1183 if (Subtarget->hasAddNoCarry()) { 1184 SubOp = AMDGPU::V_SUB_U32_e64; 1185 Opnds.push_back( 1186 CurDAG->getTargetConstant(0, {}, MVT::i1)); // clamp bit 1187 } 1188 1189 MachineSDNode *MachineSub = 1190 CurDAG->getMachineNode(SubOp, DL, MVT::i32, Opnds); 1191 1192 Base = SDValue(MachineSub, 0); 1193 Offset = CurDAG->getTargetConstant(ByteOffset, DL, MVT::i16); 1194 return true; 1195 } 1196 } 1197 } 1198 } else if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) { 1199 // If we have a constant address, prefer to put the constant into the 1200 // offset. This can save moves to load the constant address since multiple 1201 // operations can share the zero base address register, and enables merging 1202 // into read2 / write2 instructions. 1203 1204 SDLoc DL(Addr); 1205 1206 if (isUInt<16>(CAddr->getZExtValue())) { 1207 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32); 1208 MachineSDNode *MovZero = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, 1209 DL, MVT::i32, Zero); 1210 Base = SDValue(MovZero, 0); 1211 Offset = CurDAG->getTargetConstant(CAddr->getZExtValue(), DL, MVT::i16); 1212 return true; 1213 } 1214 } 1215 1216 // default case 1217 Base = Addr; 1218 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i16); 1219 return true; 1220 } 1221 1222 // TODO: If offset is too big, put low 16-bit into offset. 1223 bool AMDGPUDAGToDAGISel::SelectDS64Bit4ByteAligned(SDValue Addr, SDValue &Base, 1224 SDValue &Offset0, 1225 SDValue &Offset1) const { 1226 SDLoc DL(Addr); 1227 1228 if (CurDAG->isBaseWithConstantOffset(Addr)) { 1229 SDValue N0 = Addr.getOperand(0); 1230 SDValue N1 = Addr.getOperand(1); 1231 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 1232 unsigned DWordOffset0 = C1->getZExtValue() / 4; 1233 unsigned DWordOffset1 = DWordOffset0 + 1; 1234 // (add n0, c0) 1235 if (isDSOffsetLegal(N0, DWordOffset1, 8)) { 1236 Base = N0; 1237 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8); 1238 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8); 1239 return true; 1240 } 1241 } else if (Addr.getOpcode() == ISD::SUB) { 1242 // sub C, x -> add (sub 0, x), C 1243 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Addr.getOperand(0))) { 1244 unsigned DWordOffset0 = C->getZExtValue() / 4; 1245 unsigned DWordOffset1 = DWordOffset0 + 1; 1246 1247 if (isUInt<8>(DWordOffset0)) { 1248 SDLoc DL(Addr); 1249 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32); 1250 1251 // XXX - This is kind of hacky. Create a dummy sub node so we can check 1252 // the known bits in isDSOffsetLegal. We need to emit the selected node 1253 // here, so this is thrown away. 1254 SDValue Sub = CurDAG->getNode(ISD::SUB, DL, MVT::i32, 1255 Zero, Addr.getOperand(1)); 1256 1257 if (isDSOffsetLegal(Sub, DWordOffset1, 8)) { 1258 SmallVector<SDValue, 3> Opnds; 1259 Opnds.push_back(Zero); 1260 Opnds.push_back(Addr.getOperand(1)); 1261 unsigned SubOp = AMDGPU::V_SUB_I32_e32; 1262 if (Subtarget->hasAddNoCarry()) { 1263 SubOp = AMDGPU::V_SUB_U32_e64; 1264 Opnds.push_back( 1265 CurDAG->getTargetConstant(0, {}, MVT::i1)); // clamp bit 1266 } 1267 1268 MachineSDNode *MachineSub 1269 = CurDAG->getMachineNode(SubOp, DL, MVT::i32, Opnds); 1270 1271 Base = SDValue(MachineSub, 0); 1272 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8); 1273 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8); 1274 return true; 1275 } 1276 } 1277 } 1278 } else if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) { 1279 unsigned DWordOffset0 = CAddr->getZExtValue() / 4; 1280 unsigned DWordOffset1 = DWordOffset0 + 1; 1281 assert(4 * DWordOffset0 == CAddr->getZExtValue()); 1282 1283 if (isUInt<8>(DWordOffset0) && isUInt<8>(DWordOffset1)) { 1284 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32); 1285 MachineSDNode *MovZero 1286 = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, 1287 DL, MVT::i32, Zero); 1288 Base = SDValue(MovZero, 0); 1289 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8); 1290 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8); 1291 return true; 1292 } 1293 } 1294 1295 // default case 1296 1297 Base = Addr; 1298 Offset0 = CurDAG->getTargetConstant(0, DL, MVT::i8); 1299 Offset1 = CurDAG->getTargetConstant(1, DL, MVT::i8); 1300 return true; 1301 } 1302 1303 bool AMDGPUDAGToDAGISel::SelectMUBUF(SDValue Addr, SDValue &Ptr, 1304 SDValue &VAddr, SDValue &SOffset, 1305 SDValue &Offset, SDValue &Offen, 1306 SDValue &Idxen, SDValue &Addr64, 1307 SDValue &GLC, SDValue &SLC, 1308 SDValue &TFE, SDValue &DLC) const { 1309 // Subtarget prefers to use flat instruction 1310 if (Subtarget->useFlatForGlobal()) 1311 return false; 1312 1313 SDLoc DL(Addr); 1314 1315 if (!GLC.getNode()) 1316 GLC = CurDAG->getTargetConstant(0, DL, MVT::i1); 1317 if (!SLC.getNode()) 1318 SLC = CurDAG->getTargetConstant(0, DL, MVT::i1); 1319 TFE = CurDAG->getTargetConstant(0, DL, MVT::i1); 1320 DLC = CurDAG->getTargetConstant(0, DL, MVT::i1); 1321 1322 Idxen = CurDAG->getTargetConstant(0, DL, MVT::i1); 1323 Offen = CurDAG->getTargetConstant(0, DL, MVT::i1); 1324 Addr64 = CurDAG->getTargetConstant(0, DL, MVT::i1); 1325 SOffset = CurDAG->getTargetConstant(0, DL, MVT::i32); 1326 1327 ConstantSDNode *C1 = nullptr; 1328 SDValue N0 = Addr; 1329 if (CurDAG->isBaseWithConstantOffset(Addr)) { 1330 C1 = cast<ConstantSDNode>(Addr.getOperand(1)); 1331 if (isUInt<32>(C1->getZExtValue())) 1332 N0 = Addr.getOperand(0); 1333 else 1334 C1 = nullptr; 1335 } 1336 1337 if (N0.getOpcode() == ISD::ADD) { 1338 // (add N2, N3) -> addr64, or 1339 // (add (add N2, N3), C1) -> addr64 1340 SDValue N2 = N0.getOperand(0); 1341 SDValue N3 = N0.getOperand(1); 1342 Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1); 1343 1344 if (N2->isDivergent()) { 1345 if (N3->isDivergent()) { 1346 // Both N2 and N3 are divergent. Use N0 (the result of the add) as the 1347 // addr64, and construct the resource from a 0 address. 1348 Ptr = SDValue(buildSMovImm64(DL, 0, MVT::v2i32), 0); 1349 VAddr = N0; 1350 } else { 1351 // N2 is divergent, N3 is not. 1352 Ptr = N3; 1353 VAddr = N2; 1354 } 1355 } else { 1356 // N2 is not divergent. 1357 Ptr = N2; 1358 VAddr = N3; 1359 } 1360 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16); 1361 } else if (N0->isDivergent()) { 1362 // N0 is divergent. Use it as the addr64, and construct the resource from a 1363 // 0 address. 1364 Ptr = SDValue(buildSMovImm64(DL, 0, MVT::v2i32), 0); 1365 VAddr = N0; 1366 Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1); 1367 } else { 1368 // N0 -> offset, or 1369 // (N0 + C1) -> offset 1370 VAddr = CurDAG->getTargetConstant(0, DL, MVT::i32); 1371 Ptr = N0; 1372 } 1373 1374 if (!C1) { 1375 // No offset. 1376 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16); 1377 return true; 1378 } 1379 1380 if (SIInstrInfo::isLegalMUBUFImmOffset(C1->getZExtValue())) { 1381 // Legal offset for instruction. 1382 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16); 1383 return true; 1384 } 1385 1386 // Illegal offset, store it in soffset. 1387 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16); 1388 SOffset = 1389 SDValue(CurDAG->getMachineNode( 1390 AMDGPU::S_MOV_B32, DL, MVT::i32, 1391 CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i32)), 1392 0); 1393 return true; 1394 } 1395 1396 bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, 1397 SDValue &VAddr, SDValue &SOffset, 1398 SDValue &Offset, SDValue &GLC, 1399 SDValue &SLC, SDValue &TFE, 1400 SDValue &DLC) const { 1401 SDValue Ptr, Offen, Idxen, Addr64; 1402 1403 // addr64 bit was removed for volcanic islands. 1404 if (!Subtarget->hasAddr64()) 1405 return false; 1406 1407 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64, 1408 GLC, SLC, TFE, DLC)) 1409 return false; 1410 1411 ConstantSDNode *C = cast<ConstantSDNode>(Addr64); 1412 if (C->getSExtValue()) { 1413 SDLoc DL(Addr); 1414 1415 const SITargetLowering& Lowering = 1416 *static_cast<const SITargetLowering*>(getTargetLowering()); 1417 1418 SRsrc = SDValue(Lowering.wrapAddr64Rsrc(*CurDAG, DL, Ptr), 0); 1419 return true; 1420 } 1421 1422 return false; 1423 } 1424 1425 bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, 1426 SDValue &VAddr, SDValue &SOffset, 1427 SDValue &Offset, 1428 SDValue &SLC) const { 1429 SLC = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i1); 1430 SDValue GLC, TFE, DLC; 1431 1432 return SelectMUBUFAddr64(Addr, SRsrc, VAddr, SOffset, Offset, GLC, SLC, TFE, DLC); 1433 } 1434 1435 static bool isStackPtrRelative(const MachinePointerInfo &PtrInfo) { 1436 auto PSV = PtrInfo.V.dyn_cast<const PseudoSourceValue *>(); 1437 return PSV && PSV->isStack(); 1438 } 1439 1440 std::pair<SDValue, SDValue> AMDGPUDAGToDAGISel::foldFrameIndex(SDValue N) const { 1441 const MachineFunction &MF = CurDAG->getMachineFunction(); 1442 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>(); 1443 1444 if (auto FI = dyn_cast<FrameIndexSDNode>(N)) { 1445 SDValue TFI = CurDAG->getTargetFrameIndex(FI->getIndex(), 1446 FI->getValueType(0)); 1447 1448 // If we can resolve this to a frame index access, this will be relative to 1449 // either the stack or frame pointer SGPR. 1450 return std::make_pair( 1451 TFI, CurDAG->getRegister(Info->getStackPtrOffsetReg(), MVT::i32)); 1452 } 1453 1454 // If we don't know this private access is a local stack object, it needs to 1455 // be relative to the entry point's scratch wave offset register. 1456 return std::make_pair(N, CurDAG->getRegister(Info->getScratchWaveOffsetReg(), 1457 MVT::i32)); 1458 } 1459 1460 bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(SDNode *Parent, 1461 SDValue Addr, SDValue &Rsrc, 1462 SDValue &VAddr, SDValue &SOffset, 1463 SDValue &ImmOffset) const { 1464 1465 SDLoc DL(Addr); 1466 MachineFunction &MF = CurDAG->getMachineFunction(); 1467 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>(); 1468 1469 Rsrc = CurDAG->getRegister(Info->getScratchRSrcReg(), MVT::v4i32); 1470 1471 if (ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) { 1472 unsigned Imm = CAddr->getZExtValue(); 1473 1474 SDValue HighBits = CurDAG->getTargetConstant(Imm & ~4095, DL, MVT::i32); 1475 MachineSDNode *MovHighBits = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, 1476 DL, MVT::i32, HighBits); 1477 VAddr = SDValue(MovHighBits, 0); 1478 1479 // In a call sequence, stores to the argument stack area are relative to the 1480 // stack pointer. 1481 const MachinePointerInfo &PtrInfo = cast<MemSDNode>(Parent)->getPointerInfo(); 1482 unsigned SOffsetReg = isStackPtrRelative(PtrInfo) ? 1483 Info->getStackPtrOffsetReg() : Info->getScratchWaveOffsetReg(); 1484 1485 SOffset = CurDAG->getRegister(SOffsetReg, MVT::i32); 1486 ImmOffset = CurDAG->getTargetConstant(Imm & 4095, DL, MVT::i16); 1487 return true; 1488 } 1489 1490 if (CurDAG->isBaseWithConstantOffset(Addr)) { 1491 // (add n0, c1) 1492 1493 SDValue N0 = Addr.getOperand(0); 1494 SDValue N1 = Addr.getOperand(1); 1495 1496 // Offsets in vaddr must be positive if range checking is enabled. 1497 // 1498 // The total computation of vaddr + soffset + offset must not overflow. If 1499 // vaddr is negative, even if offset is 0 the sgpr offset add will end up 1500 // overflowing. 1501 // 1502 // Prior to gfx9, MUBUF instructions with the vaddr offset enabled would 1503 // always perform a range check. If a negative vaddr base index was used, 1504 // this would fail the range check. The overall address computation would 1505 // compute a valid address, but this doesn't happen due to the range 1506 // check. For out-of-bounds MUBUF loads, a 0 is returned. 1507 // 1508 // Therefore it should be safe to fold any VGPR offset on gfx9 into the 1509 // MUBUF vaddr, but not on older subtargets which can only do this if the 1510 // sign bit is known 0. 1511 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 1512 if (SIInstrInfo::isLegalMUBUFImmOffset(C1->getZExtValue()) && 1513 (!Subtarget->privateMemoryResourceIsRangeChecked() || 1514 CurDAG->SignBitIsZero(N0))) { 1515 std::tie(VAddr, SOffset) = foldFrameIndex(N0); 1516 ImmOffset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16); 1517 return true; 1518 } 1519 } 1520 1521 // (node) 1522 std::tie(VAddr, SOffset) = foldFrameIndex(Addr); 1523 ImmOffset = CurDAG->getTargetConstant(0, DL, MVT::i16); 1524 return true; 1525 } 1526 1527 bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffset(SDNode *Parent, 1528 SDValue Addr, 1529 SDValue &SRsrc, 1530 SDValue &SOffset, 1531 SDValue &Offset) const { 1532 ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr); 1533 if (!CAddr || !SIInstrInfo::isLegalMUBUFImmOffset(CAddr->getZExtValue())) 1534 return false; 1535 1536 SDLoc DL(Addr); 1537 MachineFunction &MF = CurDAG->getMachineFunction(); 1538 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>(); 1539 1540 SRsrc = CurDAG->getRegister(Info->getScratchRSrcReg(), MVT::v4i32); 1541 1542 const MachinePointerInfo &PtrInfo = cast<MemSDNode>(Parent)->getPointerInfo(); 1543 unsigned SOffsetReg = isStackPtrRelative(PtrInfo) ? 1544 Info->getStackPtrOffsetReg() : Info->getScratchWaveOffsetReg(); 1545 1546 // FIXME: Get from MachinePointerInfo? We should only be using the frame 1547 // offset if we know this is in a call sequence. 1548 SOffset = CurDAG->getRegister(SOffsetReg, MVT::i32); 1549 1550 Offset = CurDAG->getTargetConstant(CAddr->getZExtValue(), DL, MVT::i16); 1551 return true; 1552 } 1553 1554 bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, 1555 SDValue &SOffset, SDValue &Offset, 1556 SDValue &GLC, SDValue &SLC, 1557 SDValue &TFE, SDValue &DLC) const { 1558 SDValue Ptr, VAddr, Offen, Idxen, Addr64; 1559 const SIInstrInfo *TII = 1560 static_cast<const SIInstrInfo *>(Subtarget->getInstrInfo()); 1561 1562 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64, 1563 GLC, SLC, TFE, DLC)) 1564 return false; 1565 1566 if (!cast<ConstantSDNode>(Offen)->getSExtValue() && 1567 !cast<ConstantSDNode>(Idxen)->getSExtValue() && 1568 !cast<ConstantSDNode>(Addr64)->getSExtValue()) { 1569 uint64_t Rsrc = TII->getDefaultRsrcDataFormat() | 1570 APInt::getAllOnesValue(32).getZExtValue(); // Size 1571 SDLoc DL(Addr); 1572 1573 const SITargetLowering& Lowering = 1574 *static_cast<const SITargetLowering*>(getTargetLowering()); 1575 1576 SRsrc = SDValue(Lowering.buildRSRC(*CurDAG, DL, Ptr, 0, Rsrc), 0); 1577 return true; 1578 } 1579 return false; 1580 } 1581 1582 bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, 1583 SDValue &Soffset, SDValue &Offset 1584 ) const { 1585 SDValue GLC, SLC, TFE, DLC; 1586 1587 return SelectMUBUFOffset(Addr, SRsrc, Soffset, Offset, GLC, SLC, TFE, DLC); 1588 } 1589 bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, 1590 SDValue &Soffset, SDValue &Offset, 1591 SDValue &SLC) const { 1592 SDValue GLC, TFE, DLC; 1593 1594 return SelectMUBUFOffset(Addr, SRsrc, Soffset, Offset, GLC, SLC, TFE, DLC); 1595 } 1596 1597 template <bool IsSigned> 1598 bool AMDGPUDAGToDAGISel::SelectFlatOffset(SDNode *N, 1599 SDValue Addr, 1600 SDValue &VAddr, 1601 SDValue &Offset, 1602 SDValue &SLC) const { 1603 return static_cast<const SITargetLowering*>(getTargetLowering())-> 1604 SelectFlatOffset(IsSigned, *CurDAG, N, Addr, VAddr, Offset, SLC); 1605 } 1606 1607 bool AMDGPUDAGToDAGISel::SelectFlatAtomic(SDNode *N, 1608 SDValue Addr, 1609 SDValue &VAddr, 1610 SDValue &Offset, 1611 SDValue &SLC) const { 1612 return SelectFlatOffset<false>(N, Addr, VAddr, Offset, SLC); 1613 } 1614 1615 bool AMDGPUDAGToDAGISel::SelectFlatAtomicSigned(SDNode *N, 1616 SDValue Addr, 1617 SDValue &VAddr, 1618 SDValue &Offset, 1619 SDValue &SLC) const { 1620 return SelectFlatOffset<true>(N, Addr, VAddr, Offset, SLC); 1621 } 1622 1623 bool AMDGPUDAGToDAGISel::SelectSMRDOffset(SDValue ByteOffsetNode, 1624 SDValue &Offset, bool &Imm) const { 1625 1626 // FIXME: Handle non-constant offsets. 1627 ConstantSDNode *C = dyn_cast<ConstantSDNode>(ByteOffsetNode); 1628 if (!C) 1629 return false; 1630 1631 SDLoc SL(ByteOffsetNode); 1632 GCNSubtarget::Generation Gen = Subtarget->getGeneration(); 1633 int64_t ByteOffset = C->getSExtValue(); 1634 int64_t EncodedOffset = AMDGPU::getSMRDEncodedOffset(*Subtarget, ByteOffset); 1635 1636 if (AMDGPU::isLegalSMRDImmOffset(*Subtarget, ByteOffset)) { 1637 Offset = CurDAG->getTargetConstant(EncodedOffset, SL, MVT::i32); 1638 Imm = true; 1639 return true; 1640 } 1641 1642 if (!isUInt<32>(EncodedOffset) || !isUInt<32>(ByteOffset)) 1643 return false; 1644 1645 if (Gen == AMDGPUSubtarget::SEA_ISLANDS && isUInt<32>(EncodedOffset)) { 1646 // 32-bit Immediates are supported on Sea Islands. 1647 Offset = CurDAG->getTargetConstant(EncodedOffset, SL, MVT::i32); 1648 } else { 1649 SDValue C32Bit = CurDAG->getTargetConstant(ByteOffset, SL, MVT::i32); 1650 Offset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, 1651 C32Bit), 0); 1652 } 1653 Imm = false; 1654 return true; 1655 } 1656 1657 SDValue AMDGPUDAGToDAGISel::Expand32BitAddress(SDValue Addr) const { 1658 if (Addr.getValueType() != MVT::i32) 1659 return Addr; 1660 1661 // Zero-extend a 32-bit address. 1662 SDLoc SL(Addr); 1663 1664 const MachineFunction &MF = CurDAG->getMachineFunction(); 1665 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>(); 1666 unsigned AddrHiVal = Info->get32BitAddressHighBits(); 1667 SDValue AddrHi = CurDAG->getTargetConstant(AddrHiVal, SL, MVT::i32); 1668 1669 const SDValue Ops[] = { 1670 CurDAG->getTargetConstant(AMDGPU::SReg_64_XEXECRegClassID, SL, MVT::i32), 1671 Addr, 1672 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32), 1673 SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, AddrHi), 1674 0), 1675 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32), 1676 }; 1677 1678 return SDValue(CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, SL, MVT::i64, 1679 Ops), 0); 1680 } 1681 1682 bool AMDGPUDAGToDAGISel::SelectSMRD(SDValue Addr, SDValue &SBase, 1683 SDValue &Offset, bool &Imm) const { 1684 SDLoc SL(Addr); 1685 1686 // A 32-bit (address + offset) should not cause unsigned 32-bit integer 1687 // wraparound, because s_load instructions perform the addition in 64 bits. 1688 if ((Addr.getValueType() != MVT::i32 || 1689 Addr->getFlags().hasNoUnsignedWrap()) && 1690 CurDAG->isBaseWithConstantOffset(Addr)) { 1691 SDValue N0 = Addr.getOperand(0); 1692 SDValue N1 = Addr.getOperand(1); 1693 1694 if (SelectSMRDOffset(N1, Offset, Imm)) { 1695 SBase = Expand32BitAddress(N0); 1696 return true; 1697 } 1698 } 1699 SBase = Expand32BitAddress(Addr); 1700 Offset = CurDAG->getTargetConstant(0, SL, MVT::i32); 1701 Imm = true; 1702 return true; 1703 } 1704 1705 bool AMDGPUDAGToDAGISel::SelectSMRDImm(SDValue Addr, SDValue &SBase, 1706 SDValue &Offset) const { 1707 bool Imm; 1708 return SelectSMRD(Addr, SBase, Offset, Imm) && Imm; 1709 } 1710 1711 bool AMDGPUDAGToDAGISel::SelectSMRDImm32(SDValue Addr, SDValue &SBase, 1712 SDValue &Offset) const { 1713 1714 if (Subtarget->getGeneration() != AMDGPUSubtarget::SEA_ISLANDS) 1715 return false; 1716 1717 bool Imm; 1718 if (!SelectSMRD(Addr, SBase, Offset, Imm)) 1719 return false; 1720 1721 return !Imm && isa<ConstantSDNode>(Offset); 1722 } 1723 1724 bool AMDGPUDAGToDAGISel::SelectSMRDSgpr(SDValue Addr, SDValue &SBase, 1725 SDValue &Offset) const { 1726 bool Imm; 1727 return SelectSMRD(Addr, SBase, Offset, Imm) && !Imm && 1728 !isa<ConstantSDNode>(Offset); 1729 } 1730 1731 bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm(SDValue Addr, 1732 SDValue &Offset) const { 1733 bool Imm; 1734 return SelectSMRDOffset(Addr, Offset, Imm) && Imm; 1735 } 1736 1737 bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm32(SDValue Addr, 1738 SDValue &Offset) const { 1739 if (Subtarget->getGeneration() != AMDGPUSubtarget::SEA_ISLANDS) 1740 return false; 1741 1742 bool Imm; 1743 if (!SelectSMRDOffset(Addr, Offset, Imm)) 1744 return false; 1745 1746 return !Imm && isa<ConstantSDNode>(Offset); 1747 } 1748 1749 bool AMDGPUDAGToDAGISel::SelectMOVRELOffset(SDValue Index, 1750 SDValue &Base, 1751 SDValue &Offset) const { 1752 SDLoc DL(Index); 1753 1754 if (CurDAG->isBaseWithConstantOffset(Index)) { 1755 SDValue N0 = Index.getOperand(0); 1756 SDValue N1 = Index.getOperand(1); 1757 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 1758 1759 // (add n0, c0) 1760 // Don't peel off the offset (c0) if doing so could possibly lead 1761 // the base (n0) to be negative. 1762 if (C1->getSExtValue() <= 0 || CurDAG->SignBitIsZero(N0)) { 1763 Base = N0; 1764 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i32); 1765 return true; 1766 } 1767 } 1768 1769 if (isa<ConstantSDNode>(Index)) 1770 return false; 1771 1772 Base = Index; 1773 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); 1774 return true; 1775 } 1776 1777 SDNode *AMDGPUDAGToDAGISel::getS_BFE(unsigned Opcode, const SDLoc &DL, 1778 SDValue Val, uint32_t Offset, 1779 uint32_t Width) { 1780 // Transformation function, pack the offset and width of a BFE into 1781 // the format expected by the S_BFE_I32 / S_BFE_U32. In the second 1782 // source, bits [5:0] contain the offset and bits [22:16] the width. 1783 uint32_t PackedVal = Offset | (Width << 16); 1784 SDValue PackedConst = CurDAG->getTargetConstant(PackedVal, DL, MVT::i32); 1785 1786 return CurDAG->getMachineNode(Opcode, DL, MVT::i32, Val, PackedConst); 1787 } 1788 1789 void AMDGPUDAGToDAGISel::SelectS_BFEFromShifts(SDNode *N) { 1790 // "(a << b) srl c)" ---> "BFE_U32 a, (c-b), (32-c) 1791 // "(a << b) sra c)" ---> "BFE_I32 a, (c-b), (32-c) 1792 // Predicate: 0 < b <= c < 32 1793 1794 const SDValue &Shl = N->getOperand(0); 1795 ConstantSDNode *B = dyn_cast<ConstantSDNode>(Shl->getOperand(1)); 1796 ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1)); 1797 1798 if (B && C) { 1799 uint32_t BVal = B->getZExtValue(); 1800 uint32_t CVal = C->getZExtValue(); 1801 1802 if (0 < BVal && BVal <= CVal && CVal < 32) { 1803 bool Signed = N->getOpcode() == ISD::SRA; 1804 unsigned Opcode = Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32; 1805 1806 ReplaceNode(N, getS_BFE(Opcode, SDLoc(N), Shl.getOperand(0), CVal - BVal, 1807 32 - CVal)); 1808 return; 1809 } 1810 } 1811 SelectCode(N); 1812 } 1813 1814 void AMDGPUDAGToDAGISel::SelectS_BFE(SDNode *N) { 1815 switch (N->getOpcode()) { 1816 case ISD::AND: 1817 if (N->getOperand(0).getOpcode() == ISD::SRL) { 1818 // "(a srl b) & mask" ---> "BFE_U32 a, b, popcount(mask)" 1819 // Predicate: isMask(mask) 1820 const SDValue &Srl = N->getOperand(0); 1821 ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(Srl.getOperand(1)); 1822 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(N->getOperand(1)); 1823 1824 if (Shift && Mask) { 1825 uint32_t ShiftVal = Shift->getZExtValue(); 1826 uint32_t MaskVal = Mask->getZExtValue(); 1827 1828 if (isMask_32(MaskVal)) { 1829 uint32_t WidthVal = countPopulation(MaskVal); 1830 1831 ReplaceNode(N, getS_BFE(AMDGPU::S_BFE_U32, SDLoc(N), 1832 Srl.getOperand(0), ShiftVal, WidthVal)); 1833 return; 1834 } 1835 } 1836 } 1837 break; 1838 case ISD::SRL: 1839 if (N->getOperand(0).getOpcode() == ISD::AND) { 1840 // "(a & mask) srl b)" ---> "BFE_U32 a, b, popcount(mask >> b)" 1841 // Predicate: isMask(mask >> b) 1842 const SDValue &And = N->getOperand(0); 1843 ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(N->getOperand(1)); 1844 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(And->getOperand(1)); 1845 1846 if (Shift && Mask) { 1847 uint32_t ShiftVal = Shift->getZExtValue(); 1848 uint32_t MaskVal = Mask->getZExtValue() >> ShiftVal; 1849 1850 if (isMask_32(MaskVal)) { 1851 uint32_t WidthVal = countPopulation(MaskVal); 1852 1853 ReplaceNode(N, getS_BFE(AMDGPU::S_BFE_U32, SDLoc(N), 1854 And.getOperand(0), ShiftVal, WidthVal)); 1855 return; 1856 } 1857 } 1858 } else if (N->getOperand(0).getOpcode() == ISD::SHL) { 1859 SelectS_BFEFromShifts(N); 1860 return; 1861 } 1862 break; 1863 case ISD::SRA: 1864 if (N->getOperand(0).getOpcode() == ISD::SHL) { 1865 SelectS_BFEFromShifts(N); 1866 return; 1867 } 1868 break; 1869 1870 case ISD::SIGN_EXTEND_INREG: { 1871 // sext_inreg (srl x, 16), i8 -> bfe_i32 x, 16, 8 1872 SDValue Src = N->getOperand(0); 1873 if (Src.getOpcode() != ISD::SRL) 1874 break; 1875 1876 const ConstantSDNode *Amt = dyn_cast<ConstantSDNode>(Src.getOperand(1)); 1877 if (!Amt) 1878 break; 1879 1880 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits(); 1881 ReplaceNode(N, getS_BFE(AMDGPU::S_BFE_I32, SDLoc(N), Src.getOperand(0), 1882 Amt->getZExtValue(), Width)); 1883 return; 1884 } 1885 } 1886 1887 SelectCode(N); 1888 } 1889 1890 bool AMDGPUDAGToDAGISel::isCBranchSCC(const SDNode *N) const { 1891 assert(N->getOpcode() == ISD::BRCOND); 1892 if (!N->hasOneUse()) 1893 return false; 1894 1895 SDValue Cond = N->getOperand(1); 1896 if (Cond.getOpcode() == ISD::CopyToReg) 1897 Cond = Cond.getOperand(2); 1898 1899 if (Cond.getOpcode() != ISD::SETCC || !Cond.hasOneUse()) 1900 return false; 1901 1902 MVT VT = Cond.getOperand(0).getSimpleValueType(); 1903 if (VT == MVT::i32) 1904 return true; 1905 1906 if (VT == MVT::i64) { 1907 auto ST = static_cast<const GCNSubtarget *>(Subtarget); 1908 1909 ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get(); 1910 return (CC == ISD::SETEQ || CC == ISD::SETNE) && ST->hasScalarCompareEq64(); 1911 } 1912 1913 return false; 1914 } 1915 1916 void AMDGPUDAGToDAGISel::SelectBRCOND(SDNode *N) { 1917 SDValue Cond = N->getOperand(1); 1918 1919 if (Cond.isUndef()) { 1920 CurDAG->SelectNodeTo(N, AMDGPU::SI_BR_UNDEF, MVT::Other, 1921 N->getOperand(2), N->getOperand(0)); 1922 return; 1923 } 1924 1925 const GCNSubtarget *ST = static_cast<const GCNSubtarget *>(Subtarget); 1926 const SIRegisterInfo *TRI = ST->getRegisterInfo(); 1927 1928 bool UseSCCBr = isCBranchSCC(N) && isUniformBr(N); 1929 unsigned BrOp = UseSCCBr ? AMDGPU::S_CBRANCH_SCC1 : AMDGPU::S_CBRANCH_VCCNZ; 1930 unsigned CondReg = UseSCCBr ? (unsigned)AMDGPU::SCC : TRI->getVCC(); 1931 SDLoc SL(N); 1932 1933 if (!UseSCCBr) { 1934 // This is the case that we are selecting to S_CBRANCH_VCCNZ. We have not 1935 // analyzed what generates the vcc value, so we do not know whether vcc 1936 // bits for disabled lanes are 0. Thus we need to mask out bits for 1937 // disabled lanes. 1938 // 1939 // For the case that we select S_CBRANCH_SCC1 and it gets 1940 // changed to S_CBRANCH_VCCNZ in SIFixSGPRCopies, SIFixSGPRCopies calls 1941 // SIInstrInfo::moveToVALU which inserts the S_AND). 1942 // 1943 // We could add an analysis of what generates the vcc value here and omit 1944 // the S_AND when is unnecessary. But it would be better to add a separate 1945 // pass after SIFixSGPRCopies to do the unnecessary S_AND removal, so it 1946 // catches both cases. 1947 Cond = SDValue(CurDAG->getMachineNode(ST->isWave32() ? AMDGPU::S_AND_B32 1948 : AMDGPU::S_AND_B64, 1949 SL, MVT::i1, 1950 CurDAG->getRegister(ST->isWave32() ? AMDGPU::EXEC_LO 1951 : AMDGPU::EXEC, 1952 MVT::i1), 1953 Cond), 1954 0); 1955 } 1956 1957 SDValue VCC = CurDAG->getCopyToReg(N->getOperand(0), SL, CondReg, Cond); 1958 CurDAG->SelectNodeTo(N, BrOp, MVT::Other, 1959 N->getOperand(2), // Basic Block 1960 VCC.getValue(0)); 1961 } 1962 1963 void AMDGPUDAGToDAGISel::SelectFMAD_FMA(SDNode *N) { 1964 MVT VT = N->getSimpleValueType(0); 1965 bool IsFMA = N->getOpcode() == ISD::FMA; 1966 if (VT != MVT::f32 || (!Subtarget->hasMadMixInsts() && 1967 !Subtarget->hasFmaMixInsts()) || 1968 ((IsFMA && Subtarget->hasMadMixInsts()) || 1969 (!IsFMA && Subtarget->hasFmaMixInsts()))) { 1970 SelectCode(N); 1971 return; 1972 } 1973 1974 SDValue Src0 = N->getOperand(0); 1975 SDValue Src1 = N->getOperand(1); 1976 SDValue Src2 = N->getOperand(2); 1977 unsigned Src0Mods, Src1Mods, Src2Mods; 1978 1979 // Avoid using v_mad_mix_f32/v_fma_mix_f32 unless there is actually an operand 1980 // using the conversion from f16. 1981 bool Sel0 = SelectVOP3PMadMixModsImpl(Src0, Src0, Src0Mods); 1982 bool Sel1 = SelectVOP3PMadMixModsImpl(Src1, Src1, Src1Mods); 1983 bool Sel2 = SelectVOP3PMadMixModsImpl(Src2, Src2, Src2Mods); 1984 1985 assert((IsFMA || !Subtarget->hasFP32Denormals()) && 1986 "fmad selected with denormals enabled"); 1987 // TODO: We can select this with f32 denormals enabled if all the sources are 1988 // converted from f16 (in which case fmad isn't legal). 1989 1990 if (Sel0 || Sel1 || Sel2) { 1991 // For dummy operands. 1992 SDValue Zero = CurDAG->getTargetConstant(0, SDLoc(), MVT::i32); 1993 SDValue Ops[] = { 1994 CurDAG->getTargetConstant(Src0Mods, SDLoc(), MVT::i32), Src0, 1995 CurDAG->getTargetConstant(Src1Mods, SDLoc(), MVT::i32), Src1, 1996 CurDAG->getTargetConstant(Src2Mods, SDLoc(), MVT::i32), Src2, 1997 CurDAG->getTargetConstant(0, SDLoc(), MVT::i1), 1998 Zero, Zero 1999 }; 2000 2001 CurDAG->SelectNodeTo(N, 2002 IsFMA ? AMDGPU::V_FMA_MIX_F32 : AMDGPU::V_MAD_MIX_F32, 2003 MVT::f32, Ops); 2004 } else { 2005 SelectCode(N); 2006 } 2007 } 2008 2009 // This is here because there isn't a way to use the generated sub0_sub1 as the 2010 // subreg index to EXTRACT_SUBREG in tablegen. 2011 void AMDGPUDAGToDAGISel::SelectATOMIC_CMP_SWAP(SDNode *N) { 2012 MemSDNode *Mem = cast<MemSDNode>(N); 2013 unsigned AS = Mem->getAddressSpace(); 2014 if (AS == AMDGPUAS::FLAT_ADDRESS) { 2015 SelectCode(N); 2016 return; 2017 } 2018 2019 MVT VT = N->getSimpleValueType(0); 2020 bool Is32 = (VT == MVT::i32); 2021 SDLoc SL(N); 2022 2023 MachineSDNode *CmpSwap = nullptr; 2024 if (Subtarget->hasAddr64()) { 2025 SDValue SRsrc, VAddr, SOffset, Offset, SLC; 2026 2027 if (SelectMUBUFAddr64(Mem->getBasePtr(), SRsrc, VAddr, SOffset, Offset, SLC)) { 2028 unsigned Opcode = Is32 ? AMDGPU::BUFFER_ATOMIC_CMPSWAP_ADDR64_RTN : 2029 AMDGPU::BUFFER_ATOMIC_CMPSWAP_X2_ADDR64_RTN; 2030 SDValue CmpVal = Mem->getOperand(2); 2031 2032 // XXX - Do we care about glue operands? 2033 2034 SDValue Ops[] = { 2035 CmpVal, VAddr, SRsrc, SOffset, Offset, SLC, Mem->getChain() 2036 }; 2037 2038 CmpSwap = CurDAG->getMachineNode(Opcode, SL, Mem->getVTList(), Ops); 2039 } 2040 } 2041 2042 if (!CmpSwap) { 2043 SDValue SRsrc, SOffset, Offset, SLC; 2044 if (SelectMUBUFOffset(Mem->getBasePtr(), SRsrc, SOffset, Offset, SLC)) { 2045 unsigned Opcode = Is32 ? AMDGPU::BUFFER_ATOMIC_CMPSWAP_OFFSET_RTN : 2046 AMDGPU::BUFFER_ATOMIC_CMPSWAP_X2_OFFSET_RTN; 2047 2048 SDValue CmpVal = Mem->getOperand(2); 2049 SDValue Ops[] = { 2050 CmpVal, SRsrc, SOffset, Offset, SLC, Mem->getChain() 2051 }; 2052 2053 CmpSwap = CurDAG->getMachineNode(Opcode, SL, Mem->getVTList(), Ops); 2054 } 2055 } 2056 2057 if (!CmpSwap) { 2058 SelectCode(N); 2059 return; 2060 } 2061 2062 MachineMemOperand *MMO = Mem->getMemOperand(); 2063 CurDAG->setNodeMemRefs(CmpSwap, {MMO}); 2064 2065 unsigned SubReg = Is32 ? AMDGPU::sub0 : AMDGPU::sub0_sub1; 2066 SDValue Extract 2067 = CurDAG->getTargetExtractSubreg(SubReg, SL, VT, SDValue(CmpSwap, 0)); 2068 2069 ReplaceUses(SDValue(N, 0), Extract); 2070 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 1)); 2071 CurDAG->RemoveDeadNode(N); 2072 } 2073 2074 void AMDGPUDAGToDAGISel::SelectDSAppendConsume(SDNode *N, unsigned IntrID) { 2075 // The address is assumed to be uniform, so if it ends up in a VGPR, it will 2076 // be copied to an SGPR with readfirstlane. 2077 unsigned Opc = IntrID == Intrinsic::amdgcn_ds_append ? 2078 AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME; 2079 2080 SDValue Chain = N->getOperand(0); 2081 SDValue Ptr = N->getOperand(2); 2082 MemIntrinsicSDNode *M = cast<MemIntrinsicSDNode>(N); 2083 MachineMemOperand *MMO = M->getMemOperand(); 2084 bool IsGDS = M->getAddressSpace() == AMDGPUAS::REGION_ADDRESS; 2085 2086 SDValue Offset; 2087 if (CurDAG->isBaseWithConstantOffset(Ptr)) { 2088 SDValue PtrBase = Ptr.getOperand(0); 2089 SDValue PtrOffset = Ptr.getOperand(1); 2090 2091 const APInt &OffsetVal = cast<ConstantSDNode>(PtrOffset)->getAPIntValue(); 2092 if (isDSOffsetLegal(PtrBase, OffsetVal.getZExtValue(), 16)) { 2093 N = glueCopyToM0(N, PtrBase); 2094 Offset = CurDAG->getTargetConstant(OffsetVal, SDLoc(), MVT::i32); 2095 } 2096 } 2097 2098 if (!Offset) { 2099 N = glueCopyToM0(N, Ptr); 2100 Offset = CurDAG->getTargetConstant(0, SDLoc(), MVT::i32); 2101 } 2102 2103 SDValue Ops[] = { 2104 Offset, 2105 CurDAG->getTargetConstant(IsGDS, SDLoc(), MVT::i32), 2106 Chain, 2107 N->getOperand(N->getNumOperands() - 1) // New glue 2108 }; 2109 2110 SDNode *Selected = CurDAG->SelectNodeTo(N, Opc, N->getVTList(), Ops); 2111 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Selected), {MMO}); 2112 } 2113 2114 static unsigned gwsIntrinToOpcode(unsigned IntrID) { 2115 switch (IntrID) { 2116 case Intrinsic::amdgcn_ds_gws_init: 2117 return AMDGPU::DS_GWS_INIT; 2118 case Intrinsic::amdgcn_ds_gws_barrier: 2119 return AMDGPU::DS_GWS_BARRIER; 2120 case Intrinsic::amdgcn_ds_gws_sema_v: 2121 return AMDGPU::DS_GWS_SEMA_V; 2122 case Intrinsic::amdgcn_ds_gws_sema_br: 2123 return AMDGPU::DS_GWS_SEMA_BR; 2124 case Intrinsic::amdgcn_ds_gws_sema_p: 2125 return AMDGPU::DS_GWS_SEMA_P; 2126 case Intrinsic::amdgcn_ds_gws_sema_release_all: 2127 return AMDGPU::DS_GWS_SEMA_RELEASE_ALL; 2128 default: 2129 llvm_unreachable("not a gws intrinsic"); 2130 } 2131 } 2132 2133 void AMDGPUDAGToDAGISel::SelectDS_GWS(SDNode *N, unsigned IntrID) { 2134 if (IntrID == Intrinsic::amdgcn_ds_gws_sema_release_all && 2135 !Subtarget->hasGWSSemaReleaseAll()) { 2136 // Let this error. 2137 SelectCode(N); 2138 return; 2139 } 2140 2141 // Chain, intrinsic ID, vsrc, offset 2142 const bool HasVSrc = N->getNumOperands() == 4; 2143 assert(HasVSrc || N->getNumOperands() == 3); 2144 2145 SDLoc SL(N); 2146 SDValue BaseOffset = N->getOperand(HasVSrc ? 3 : 2); 2147 int ImmOffset = 0; 2148 MemIntrinsicSDNode *M = cast<MemIntrinsicSDNode>(N); 2149 MachineMemOperand *MMO = M->getMemOperand(); 2150 2151 // Don't worry if the offset ends up in a VGPR. Only one lane will have 2152 // effect, so SIFixSGPRCopies will validly insert readfirstlane. 2153 2154 // The resource id offset is computed as (<isa opaque base> + M0[21:16] + 2155 // offset field) % 64. Some versions of the programming guide omit the m0 2156 // part, or claim it's from offset 0. 2157 if (ConstantSDNode *ConstOffset = dyn_cast<ConstantSDNode>(BaseOffset)) { 2158 // If we have a constant offset, try to use the default value for m0 as a 2159 // base to possibly avoid setting it up. 2160 glueCopyToM0(N, CurDAG->getTargetConstant(-1, SL, MVT::i32)); 2161 ImmOffset = ConstOffset->getZExtValue() + 1; 2162 } else { 2163 if (CurDAG->isBaseWithConstantOffset(BaseOffset)) { 2164 ImmOffset = BaseOffset.getConstantOperandVal(1); 2165 BaseOffset = BaseOffset.getOperand(0); 2166 } 2167 2168 // Prefer to do the shift in an SGPR since it should be possible to use m0 2169 // as the result directly. If it's already an SGPR, it will be eliminated 2170 // later. 2171 SDNode *SGPROffset 2172 = CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32, 2173 BaseOffset); 2174 // Shift to offset in m0 2175 SDNode *M0Base 2176 = CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32, 2177 SDValue(SGPROffset, 0), 2178 CurDAG->getTargetConstant(16, SL, MVT::i32)); 2179 glueCopyToM0(N, SDValue(M0Base, 0)); 2180 } 2181 2182 SDValue V0; 2183 SDValue Chain = N->getOperand(0); 2184 SDValue Glue; 2185 if (HasVSrc) { 2186 SDValue VSrc0 = N->getOperand(2); 2187 2188 // The manual doesn't mention this, but it seems only v0 works. 2189 V0 = CurDAG->getRegister(AMDGPU::VGPR0, MVT::i32); 2190 2191 SDValue CopyToV0 = CurDAG->getCopyToReg( 2192 N->getOperand(0), SL, V0, VSrc0, 2193 N->getOperand(N->getNumOperands() - 1)); 2194 Chain = CopyToV0; 2195 Glue = CopyToV0.getValue(1); 2196 } 2197 2198 SDValue OffsetField = CurDAG->getTargetConstant(ImmOffset, SL, MVT::i32); 2199 2200 // TODO: Can this just be removed from the instruction? 2201 SDValue GDS = CurDAG->getTargetConstant(1, SL, MVT::i1); 2202 2203 const unsigned Opc = gwsIntrinToOpcode(IntrID); 2204 SmallVector<SDValue, 5> Ops; 2205 if (HasVSrc) 2206 Ops.push_back(V0); 2207 Ops.push_back(OffsetField); 2208 Ops.push_back(GDS); 2209 Ops.push_back(Chain); 2210 2211 if (HasVSrc) 2212 Ops.push_back(Glue); 2213 2214 SDNode *Selected = CurDAG->SelectNodeTo(N, Opc, N->getVTList(), Ops); 2215 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Selected), {MMO}); 2216 } 2217 2218 void AMDGPUDAGToDAGISel::SelectINTRINSIC_W_CHAIN(SDNode *N) { 2219 unsigned IntrID = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 2220 switch (IntrID) { 2221 case Intrinsic::amdgcn_ds_append: 2222 case Intrinsic::amdgcn_ds_consume: { 2223 if (N->getValueType(0) != MVT::i32) 2224 break; 2225 SelectDSAppendConsume(N, IntrID); 2226 return; 2227 } 2228 } 2229 2230 SelectCode(N); 2231 } 2232 2233 void AMDGPUDAGToDAGISel::SelectINTRINSIC_VOID(SDNode *N) { 2234 unsigned IntrID = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 2235 switch (IntrID) { 2236 case Intrinsic::amdgcn_ds_gws_init: 2237 case Intrinsic::amdgcn_ds_gws_barrier: 2238 case Intrinsic::amdgcn_ds_gws_sema_v: 2239 case Intrinsic::amdgcn_ds_gws_sema_br: 2240 case Intrinsic::amdgcn_ds_gws_sema_p: 2241 case Intrinsic::amdgcn_ds_gws_sema_release_all: 2242 SelectDS_GWS(N, IntrID); 2243 return; 2244 default: 2245 break; 2246 } 2247 2248 SelectCode(N); 2249 } 2250 2251 bool AMDGPUDAGToDAGISel::SelectVOP3ModsImpl(SDValue In, SDValue &Src, 2252 unsigned &Mods) const { 2253 Mods = 0; 2254 Src = In; 2255 2256 if (Src.getOpcode() == ISD::FNEG) { 2257 Mods |= SISrcMods::NEG; 2258 Src = Src.getOperand(0); 2259 } 2260 2261 if (Src.getOpcode() == ISD::FABS) { 2262 Mods |= SISrcMods::ABS; 2263 Src = Src.getOperand(0); 2264 } 2265 2266 return true; 2267 } 2268 2269 bool AMDGPUDAGToDAGISel::SelectVOP3Mods(SDValue In, SDValue &Src, 2270 SDValue &SrcMods) const { 2271 unsigned Mods; 2272 if (SelectVOP3ModsImpl(In, Src, Mods)) { 2273 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32); 2274 return true; 2275 } 2276 2277 return false; 2278 } 2279 2280 bool AMDGPUDAGToDAGISel::SelectVOP3Mods_NNaN(SDValue In, SDValue &Src, 2281 SDValue &SrcMods) const { 2282 SelectVOP3Mods(In, Src, SrcMods); 2283 return isNoNanSrc(Src); 2284 } 2285 2286 bool AMDGPUDAGToDAGISel::SelectVOP3NoMods(SDValue In, SDValue &Src) const { 2287 if (In.getOpcode() == ISD::FABS || In.getOpcode() == ISD::FNEG) 2288 return false; 2289 2290 Src = In; 2291 return true; 2292 } 2293 2294 bool AMDGPUDAGToDAGISel::SelectVOP3Mods0(SDValue In, SDValue &Src, 2295 SDValue &SrcMods, SDValue &Clamp, 2296 SDValue &Omod) const { 2297 SDLoc DL(In); 2298 Clamp = CurDAG->getTargetConstant(0, DL, MVT::i1); 2299 Omod = CurDAG->getTargetConstant(0, DL, MVT::i1); 2300 2301 return SelectVOP3Mods(In, Src, SrcMods); 2302 } 2303 2304 bool AMDGPUDAGToDAGISel::SelectVOP3Mods0Clamp0OMod(SDValue In, SDValue &Src, 2305 SDValue &SrcMods, 2306 SDValue &Clamp, 2307 SDValue &Omod) const { 2308 Clamp = Omod = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32); 2309 return SelectVOP3Mods(In, Src, SrcMods); 2310 } 2311 2312 bool AMDGPUDAGToDAGISel::SelectVOP3OMods(SDValue In, SDValue &Src, 2313 SDValue &Clamp, SDValue &Omod) const { 2314 Src = In; 2315 2316 SDLoc DL(In); 2317 Clamp = CurDAG->getTargetConstant(0, DL, MVT::i1); 2318 Omod = CurDAG->getTargetConstant(0, DL, MVT::i1); 2319 2320 return true; 2321 } 2322 2323 bool AMDGPUDAGToDAGISel::SelectVOP3PMods(SDValue In, SDValue &Src, 2324 SDValue &SrcMods) const { 2325 unsigned Mods = 0; 2326 Src = In; 2327 2328 if (Src.getOpcode() == ISD::FNEG) { 2329 Mods ^= (SISrcMods::NEG | SISrcMods::NEG_HI); 2330 Src = Src.getOperand(0); 2331 } 2332 2333 if (Src.getOpcode() == ISD::BUILD_VECTOR) { 2334 unsigned VecMods = Mods; 2335 2336 SDValue Lo = stripBitcast(Src.getOperand(0)); 2337 SDValue Hi = stripBitcast(Src.getOperand(1)); 2338 2339 if (Lo.getOpcode() == ISD::FNEG) { 2340 Lo = stripBitcast(Lo.getOperand(0)); 2341 Mods ^= SISrcMods::NEG; 2342 } 2343 2344 if (Hi.getOpcode() == ISD::FNEG) { 2345 Hi = stripBitcast(Hi.getOperand(0)); 2346 Mods ^= SISrcMods::NEG_HI; 2347 } 2348 2349 if (isExtractHiElt(Lo, Lo)) 2350 Mods |= SISrcMods::OP_SEL_0; 2351 2352 if (isExtractHiElt(Hi, Hi)) 2353 Mods |= SISrcMods::OP_SEL_1; 2354 2355 Lo = stripExtractLoElt(Lo); 2356 Hi = stripExtractLoElt(Hi); 2357 2358 if (Lo == Hi && !isInlineImmediate(Lo.getNode())) { 2359 // Really a scalar input. Just select from the low half of the register to 2360 // avoid packing. 2361 2362 Src = Lo; 2363 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32); 2364 return true; 2365 } 2366 2367 Mods = VecMods; 2368 } 2369 2370 // Packed instructions do not have abs modifiers. 2371 Mods |= SISrcMods::OP_SEL_1; 2372 2373 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32); 2374 return true; 2375 } 2376 2377 bool AMDGPUDAGToDAGISel::SelectVOP3PMods0(SDValue In, SDValue &Src, 2378 SDValue &SrcMods, 2379 SDValue &Clamp) const { 2380 SDLoc SL(In); 2381 2382 // FIXME: Handle clamp and op_sel 2383 Clamp = CurDAG->getTargetConstant(0, SL, MVT::i32); 2384 2385 return SelectVOP3PMods(In, Src, SrcMods); 2386 } 2387 2388 bool AMDGPUDAGToDAGISel::SelectVOP3OpSel(SDValue In, SDValue &Src, 2389 SDValue &SrcMods) const { 2390 Src = In; 2391 // FIXME: Handle op_sel 2392 SrcMods = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32); 2393 return true; 2394 } 2395 2396 bool AMDGPUDAGToDAGISel::SelectVOP3OpSel0(SDValue In, SDValue &Src, 2397 SDValue &SrcMods, 2398 SDValue &Clamp) const { 2399 SDLoc SL(In); 2400 2401 // FIXME: Handle clamp 2402 Clamp = CurDAG->getTargetConstant(0, SL, MVT::i32); 2403 2404 return SelectVOP3OpSel(In, Src, SrcMods); 2405 } 2406 2407 bool AMDGPUDAGToDAGISel::SelectVOP3OpSelMods(SDValue In, SDValue &Src, 2408 SDValue &SrcMods) const { 2409 // FIXME: Handle op_sel 2410 return SelectVOP3Mods(In, Src, SrcMods); 2411 } 2412 2413 bool AMDGPUDAGToDAGISel::SelectVOP3OpSelMods0(SDValue In, SDValue &Src, 2414 SDValue &SrcMods, 2415 SDValue &Clamp) const { 2416 SDLoc SL(In); 2417 2418 // FIXME: Handle clamp 2419 Clamp = CurDAG->getTargetConstant(0, SL, MVT::i32); 2420 2421 return SelectVOP3OpSelMods(In, Src, SrcMods); 2422 } 2423 2424 // The return value is not whether the match is possible (which it always is), 2425 // but whether or not it a conversion is really used. 2426 bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsImpl(SDValue In, SDValue &Src, 2427 unsigned &Mods) const { 2428 Mods = 0; 2429 SelectVOP3ModsImpl(In, Src, Mods); 2430 2431 if (Src.getOpcode() == ISD::FP_EXTEND) { 2432 Src = Src.getOperand(0); 2433 assert(Src.getValueType() == MVT::f16); 2434 Src = stripBitcast(Src); 2435 2436 // Be careful about folding modifiers if we already have an abs. fneg is 2437 // applied last, so we don't want to apply an earlier fneg. 2438 if ((Mods & SISrcMods::ABS) == 0) { 2439 unsigned ModsTmp; 2440 SelectVOP3ModsImpl(Src, Src, ModsTmp); 2441 2442 if ((ModsTmp & SISrcMods::NEG) != 0) 2443 Mods ^= SISrcMods::NEG; 2444 2445 if ((ModsTmp & SISrcMods::ABS) != 0) 2446 Mods |= SISrcMods::ABS; 2447 } 2448 2449 // op_sel/op_sel_hi decide the source type and source. 2450 // If the source's op_sel_hi is set, it indicates to do a conversion from fp16. 2451 // If the sources's op_sel is set, it picks the high half of the source 2452 // register. 2453 2454 Mods |= SISrcMods::OP_SEL_1; 2455 if (isExtractHiElt(Src, Src)) { 2456 Mods |= SISrcMods::OP_SEL_0; 2457 2458 // TODO: Should we try to look for neg/abs here? 2459 } 2460 2461 return true; 2462 } 2463 2464 return false; 2465 } 2466 2467 bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixMods(SDValue In, SDValue &Src, 2468 SDValue &SrcMods) const { 2469 unsigned Mods = 0; 2470 SelectVOP3PMadMixModsImpl(In, Src, Mods); 2471 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32); 2472 return true; 2473 } 2474 2475 SDValue AMDGPUDAGToDAGISel::getHi16Elt(SDValue In) const { 2476 if (In.isUndef()) 2477 return CurDAG->getUNDEF(MVT::i32); 2478 2479 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(In)) { 2480 SDLoc SL(In); 2481 return CurDAG->getConstant(C->getZExtValue() << 16, SL, MVT::i32); 2482 } 2483 2484 if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(In)) { 2485 SDLoc SL(In); 2486 return CurDAG->getConstant( 2487 C->getValueAPF().bitcastToAPInt().getZExtValue() << 16, SL, MVT::i32); 2488 } 2489 2490 SDValue Src; 2491 if (isExtractHiElt(In, Src)) 2492 return Src; 2493 2494 return SDValue(); 2495 } 2496 2497 bool AMDGPUDAGToDAGISel::isVGPRImm(const SDNode * N) const { 2498 assert(CurDAG->getTarget().getTargetTriple().getArch() == Triple::amdgcn); 2499 2500 const SIRegisterInfo *SIRI = 2501 static_cast<const SIRegisterInfo *>(Subtarget->getRegisterInfo()); 2502 const SIInstrInfo * SII = 2503 static_cast<const SIInstrInfo *>(Subtarget->getInstrInfo()); 2504 2505 unsigned Limit = 0; 2506 bool AllUsesAcceptSReg = true; 2507 for (SDNode::use_iterator U = N->use_begin(), E = SDNode::use_end(); 2508 Limit < 10 && U != E; ++U, ++Limit) { 2509 const TargetRegisterClass *RC = getOperandRegClass(*U, U.getOperandNo()); 2510 2511 // If the register class is unknown, it could be an unknown 2512 // register class that needs to be an SGPR, e.g. an inline asm 2513 // constraint 2514 if (!RC || SIRI->isSGPRClass(RC)) 2515 return false; 2516 2517 if (RC != &AMDGPU::VS_32RegClass) { 2518 AllUsesAcceptSReg = false; 2519 SDNode * User = *U; 2520 if (User->isMachineOpcode()) { 2521 unsigned Opc = User->getMachineOpcode(); 2522 MCInstrDesc Desc = SII->get(Opc); 2523 if (Desc.isCommutable()) { 2524 unsigned OpIdx = Desc.getNumDefs() + U.getOperandNo(); 2525 unsigned CommuteIdx1 = TargetInstrInfo::CommuteAnyOperandIndex; 2526 if (SII->findCommutedOpIndices(Desc, OpIdx, CommuteIdx1)) { 2527 unsigned CommutedOpNo = CommuteIdx1 - Desc.getNumDefs(); 2528 const TargetRegisterClass *CommutedRC = getOperandRegClass(*U, CommutedOpNo); 2529 if (CommutedRC == &AMDGPU::VS_32RegClass) 2530 AllUsesAcceptSReg = true; 2531 } 2532 } 2533 } 2534 // If "AllUsesAcceptSReg == false" so far we haven't suceeded 2535 // commuting current user. This means have at least one use 2536 // that strictly require VGPR. Thus, we will not attempt to commute 2537 // other user instructions. 2538 if (!AllUsesAcceptSReg) 2539 break; 2540 } 2541 } 2542 return !AllUsesAcceptSReg && (Limit < 10); 2543 } 2544 2545 bool AMDGPUDAGToDAGISel::isUniformLoad(const SDNode * N) const { 2546 auto Ld = cast<LoadSDNode>(N); 2547 2548 return Ld->getAlignment() >= 4 && 2549 ( 2550 ( 2551 ( 2552 Ld->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS || 2553 Ld->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT 2554 ) 2555 && 2556 !N->isDivergent() 2557 ) 2558 || 2559 ( 2560 Subtarget->getScalarizeGlobalBehavior() && 2561 Ld->getAddressSpace() == AMDGPUAS::GLOBAL_ADDRESS && 2562 !Ld->isVolatile() && 2563 !N->isDivergent() && 2564 static_cast<const SITargetLowering *>( 2565 getTargetLowering())->isMemOpHasNoClobberedMemOperand(N) 2566 ) 2567 ); 2568 } 2569 2570 void AMDGPUDAGToDAGISel::PostprocessISelDAG() { 2571 const AMDGPUTargetLowering& Lowering = 2572 *static_cast<const AMDGPUTargetLowering*>(getTargetLowering()); 2573 bool IsModified = false; 2574 do { 2575 IsModified = false; 2576 2577 // Go over all selected nodes and try to fold them a bit more 2578 SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_begin(); 2579 while (Position != CurDAG->allnodes_end()) { 2580 SDNode *Node = &*Position++; 2581 MachineSDNode *MachineNode = dyn_cast<MachineSDNode>(Node); 2582 if (!MachineNode) 2583 continue; 2584 2585 SDNode *ResNode = Lowering.PostISelFolding(MachineNode, *CurDAG); 2586 if (ResNode != Node) { 2587 if (ResNode) 2588 ReplaceUses(Node, ResNode); 2589 IsModified = true; 2590 } 2591 } 2592 CurDAG->RemoveDeadNodes(); 2593 } while (IsModified); 2594 } 2595 2596 bool R600DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 2597 Subtarget = &MF.getSubtarget<R600Subtarget>(); 2598 return SelectionDAGISel::runOnMachineFunction(MF); 2599 } 2600 2601 bool R600DAGToDAGISel::isConstantLoad(const MemSDNode *N, int CbId) const { 2602 if (!N->readMem()) 2603 return false; 2604 if (CbId == -1) 2605 return N->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS || 2606 N->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT; 2607 2608 return N->getAddressSpace() == AMDGPUAS::CONSTANT_BUFFER_0 + CbId; 2609 } 2610 2611 bool R600DAGToDAGISel::SelectGlobalValueConstantOffset(SDValue Addr, 2612 SDValue& IntPtr) { 2613 if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Addr)) { 2614 IntPtr = CurDAG->getIntPtrConstant(Cst->getZExtValue() / 4, SDLoc(Addr), 2615 true); 2616 return true; 2617 } 2618 return false; 2619 } 2620 2621 bool R600DAGToDAGISel::SelectGlobalValueVariableOffset(SDValue Addr, 2622 SDValue& BaseReg, SDValue &Offset) { 2623 if (!isa<ConstantSDNode>(Addr)) { 2624 BaseReg = Addr; 2625 Offset = CurDAG->getIntPtrConstant(0, SDLoc(Addr), true); 2626 return true; 2627 } 2628 return false; 2629 } 2630 2631 void R600DAGToDAGISel::Select(SDNode *N) { 2632 unsigned int Opc = N->getOpcode(); 2633 if (N->isMachineOpcode()) { 2634 N->setNodeId(-1); 2635 return; // Already selected. 2636 } 2637 2638 switch (Opc) { 2639 default: break; 2640 case AMDGPUISD::BUILD_VERTICAL_VECTOR: 2641 case ISD::SCALAR_TO_VECTOR: 2642 case ISD::BUILD_VECTOR: { 2643 EVT VT = N->getValueType(0); 2644 unsigned NumVectorElts = VT.getVectorNumElements(); 2645 unsigned RegClassID; 2646 // BUILD_VECTOR was lowered into an IMPLICIT_DEF + 4 INSERT_SUBREG 2647 // that adds a 128 bits reg copy when going through TwoAddressInstructions 2648 // pass. We want to avoid 128 bits copies as much as possible because they 2649 // can't be bundled by our scheduler. 2650 switch(NumVectorElts) { 2651 case 2: RegClassID = R600::R600_Reg64RegClassID; break; 2652 case 4: 2653 if (Opc == AMDGPUISD::BUILD_VERTICAL_VECTOR) 2654 RegClassID = R600::R600_Reg128VerticalRegClassID; 2655 else 2656 RegClassID = R600::R600_Reg128RegClassID; 2657 break; 2658 default: llvm_unreachable("Do not know how to lower this BUILD_VECTOR"); 2659 } 2660 SelectBuildVector(N, RegClassID); 2661 return; 2662 } 2663 } 2664 2665 SelectCode(N); 2666 } 2667 2668 bool R600DAGToDAGISel::SelectADDRIndirect(SDValue Addr, SDValue &Base, 2669 SDValue &Offset) { 2670 ConstantSDNode *C; 2671 SDLoc DL(Addr); 2672 2673 if ((C = dyn_cast<ConstantSDNode>(Addr))) { 2674 Base = CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32); 2675 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 2676 } else if ((Addr.getOpcode() == AMDGPUISD::DWORDADDR) && 2677 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(0)))) { 2678 Base = CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32); 2679 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 2680 } else if ((Addr.getOpcode() == ISD::ADD || Addr.getOpcode() == ISD::OR) && 2681 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) { 2682 Base = Addr.getOperand(0); 2683 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 2684 } else { 2685 Base = Addr; 2686 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); 2687 } 2688 2689 return true; 2690 } 2691 2692 bool R600DAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base, 2693 SDValue &Offset) { 2694 ConstantSDNode *IMMOffset; 2695 2696 if (Addr.getOpcode() == ISD::ADD 2697 && (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 2698 && isInt<16>(IMMOffset->getZExtValue())) { 2699 2700 Base = Addr.getOperand(0); 2701 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr), 2702 MVT::i32); 2703 return true; 2704 // If the pointer address is constant, we can move it to the offset field. 2705 } else if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr)) 2706 && isInt<16>(IMMOffset->getZExtValue())) { 2707 Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), 2708 SDLoc(CurDAG->getEntryNode()), 2709 R600::ZERO, MVT::i32); 2710 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr), 2711 MVT::i32); 2712 return true; 2713 } 2714 2715 // Default case, no offset 2716 Base = Addr; 2717 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 2718 return true; 2719 } 2720