1 //===-- AMDGPUISelDAGToDAG.cpp - A dag to dag inst selector for AMDGPU ----===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //==-----------------------------------------------------------------------===// 9 // 10 /// \file 11 /// \brief Defines an instruction selector for the AMDGPU target. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "AMDGPU.h" 16 #include "AMDGPUArgumentUsageInfo.h" 17 #include "AMDGPUISelLowering.h" // For AMDGPUISD 18 #include "AMDGPUInstrInfo.h" 19 #include "AMDGPURegisterInfo.h" 20 #include "AMDGPUSubtarget.h" 21 #include "SIDefines.h" 22 #include "SIISelLowering.h" 23 #include "SIInstrInfo.h" 24 #include "SIMachineFunctionInfo.h" 25 #include "SIRegisterInfo.h" 26 #include "llvm/ADT/APInt.h" 27 #include "llvm/ADT/SmallVector.h" 28 #include "llvm/ADT/StringRef.h" 29 #include "llvm/Analysis/ValueTracking.h" 30 #include "llvm/CodeGen/FunctionLoweringInfo.h" 31 #include "llvm/CodeGen/ISDOpcodes.h" 32 #include "llvm/CodeGen/MachineFunction.h" 33 #include "llvm/CodeGen/MachineRegisterInfo.h" 34 #include "llvm/CodeGen/MachineValueType.h" 35 #include "llvm/CodeGen/SelectionDAG.h" 36 #include "llvm/CodeGen/SelectionDAGISel.h" 37 #include "llvm/CodeGen/SelectionDAGNodes.h" 38 #include "llvm/CodeGen/ValueTypes.h" 39 #include "llvm/IR/BasicBlock.h" 40 #include "llvm/IR/Instruction.h" 41 #include "llvm/MC/MCInstrDesc.h" 42 #include "llvm/Support/Casting.h" 43 #include "llvm/Support/CodeGen.h" 44 #include "llvm/Support/ErrorHandling.h" 45 #include "llvm/Support/MathExtras.h" 46 #include <cassert> 47 #include <cstdint> 48 #include <new> 49 #include <vector> 50 51 using namespace llvm; 52 53 namespace llvm { 54 55 class R600InstrInfo; 56 57 } // end namespace llvm 58 59 //===----------------------------------------------------------------------===// 60 // Instruction Selector Implementation 61 //===----------------------------------------------------------------------===// 62 63 namespace { 64 65 /// AMDGPU specific code to select AMDGPU machine instructions for 66 /// SelectionDAG operations. 67 class AMDGPUDAGToDAGISel : public SelectionDAGISel { 68 // Subtarget - Keep a pointer to the AMDGPU Subtarget around so that we can 69 // make the right decision when generating code for different targets. 70 const AMDGPUSubtarget *Subtarget; 71 AMDGPUAS AMDGPUASI; 72 73 public: 74 explicit AMDGPUDAGToDAGISel(TargetMachine *TM = nullptr, 75 CodeGenOpt::Level OptLevel = CodeGenOpt::Default) 76 : SelectionDAGISel(*TM, OptLevel) { 77 AMDGPUASI = AMDGPU::getAMDGPUAS(*TM); 78 } 79 ~AMDGPUDAGToDAGISel() override = default; 80 81 void getAnalysisUsage(AnalysisUsage &AU) const override { 82 AU.addRequired<AMDGPUArgumentUsageInfo>(); 83 SelectionDAGISel::getAnalysisUsage(AU); 84 } 85 86 bool runOnMachineFunction(MachineFunction &MF) override; 87 void Select(SDNode *N) override; 88 StringRef getPassName() const override; 89 void PostprocessISelDAG() override; 90 91 protected: 92 void SelectBuildVector(SDNode *N, unsigned RegClassID); 93 94 private: 95 std::pair<SDValue, SDValue> foldFrameIndex(SDValue N) const; 96 bool isNoNanSrc(SDValue N) const; 97 bool isInlineImmediate(const SDNode *N) const; 98 bool FoldOperand(SDValue &Src, SDValue &Sel, SDValue &Neg, SDValue &Abs, 99 const R600InstrInfo *TII); 100 bool FoldOperands(unsigned, const R600InstrInfo *, std::vector<SDValue> &); 101 bool FoldDotOperands(unsigned, const R600InstrInfo *, std::vector<SDValue> &); 102 103 bool isConstantLoad(const MemSDNode *N, int cbID) const; 104 bool isUniformBr(const SDNode *N) const; 105 106 SDNode *glueCopyToM0(SDNode *N) const; 107 108 const TargetRegisterClass *getOperandRegClass(SDNode *N, unsigned OpNo) const; 109 bool SelectGlobalValueConstantOffset(SDValue Addr, SDValue& IntPtr); 110 bool SelectGlobalValueVariableOffset(SDValue Addr, SDValue &BaseReg, 111 SDValue& Offset); 112 virtual bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, SDValue &Offset); 113 virtual bool SelectADDRIndirect(SDValue Addr, SDValue &Base, SDValue &Offset); 114 bool isDSOffsetLegal(const SDValue &Base, unsigned Offset, 115 unsigned OffsetBits) const; 116 bool SelectDS1Addr1Offset(SDValue Ptr, SDValue &Base, SDValue &Offset) const; 117 bool SelectDS64Bit4ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0, 118 SDValue &Offset1) const; 119 bool SelectMUBUF(SDValue Addr, SDValue &SRsrc, SDValue &VAddr, 120 SDValue &SOffset, SDValue &Offset, SDValue &Offen, 121 SDValue &Idxen, SDValue &Addr64, SDValue &GLC, SDValue &SLC, 122 SDValue &TFE) const; 123 bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, SDValue &VAddr, 124 SDValue &SOffset, SDValue &Offset, SDValue &GLC, 125 SDValue &SLC, SDValue &TFE) const; 126 bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, 127 SDValue &VAddr, SDValue &SOffset, SDValue &Offset, 128 SDValue &SLC) const; 129 bool SelectMUBUFScratchOffen(SDNode *Root, 130 SDValue Addr, SDValue &RSrc, SDValue &VAddr, 131 SDValue &SOffset, SDValue &ImmOffset) const; 132 bool SelectMUBUFScratchOffset(SDNode *Root, 133 SDValue Addr, SDValue &SRsrc, SDValue &Soffset, 134 SDValue &Offset) const; 135 136 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &SOffset, 137 SDValue &Offset, SDValue &GLC, SDValue &SLC, 138 SDValue &TFE) const; 139 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset, 140 SDValue &Offset, SDValue &SLC) const; 141 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset, 142 SDValue &Offset) const; 143 bool SelectMUBUFConstant(SDValue Constant, 144 SDValue &SOffset, 145 SDValue &ImmOffset) const; 146 bool SelectMUBUFIntrinsicOffset(SDValue Offset, SDValue &SOffset, 147 SDValue &ImmOffset) const; 148 bool SelectMUBUFIntrinsicVOffset(SDValue Offset, SDValue &SOffset, 149 SDValue &ImmOffset, SDValue &VOffset) const; 150 151 bool SelectFlatAtomic(SDValue Addr, SDValue &VAddr, 152 SDValue &Offset, SDValue &SLC) const; 153 bool SelectFlatAtomicSigned(SDValue Addr, SDValue &VAddr, 154 SDValue &Offset, SDValue &SLC) const; 155 156 template <bool IsSigned> 157 bool SelectFlatOffset(SDValue Addr, SDValue &VAddr, 158 SDValue &Offset, SDValue &SLC) const; 159 160 bool SelectSMRDOffset(SDValue ByteOffsetNode, SDValue &Offset, 161 bool &Imm) const; 162 bool SelectSMRD(SDValue Addr, SDValue &SBase, SDValue &Offset, 163 bool &Imm) const; 164 bool SelectSMRDImm(SDValue Addr, SDValue &SBase, SDValue &Offset) const; 165 bool SelectSMRDImm32(SDValue Addr, SDValue &SBase, SDValue &Offset) const; 166 bool SelectSMRDSgpr(SDValue Addr, SDValue &SBase, SDValue &Offset) const; 167 bool SelectSMRDBufferImm(SDValue Addr, SDValue &Offset) const; 168 bool SelectSMRDBufferImm32(SDValue Addr, SDValue &Offset) const; 169 bool SelectSMRDBufferSgpr(SDValue Addr, SDValue &Offset) const; 170 bool SelectMOVRELOffset(SDValue Index, SDValue &Base, SDValue &Offset) const; 171 172 bool SelectVOP3Mods_NNaN(SDValue In, SDValue &Src, SDValue &SrcMods) const; 173 bool SelectVOP3Mods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 174 bool SelectVOP3NoMods(SDValue In, SDValue &Src) const; 175 bool SelectVOP3Mods0(SDValue In, SDValue &Src, SDValue &SrcMods, 176 SDValue &Clamp, SDValue &Omod) const; 177 bool SelectVOP3NoMods0(SDValue In, SDValue &Src, SDValue &SrcMods, 178 SDValue &Clamp, SDValue &Omod) const; 179 180 bool SelectVOP3Mods0Clamp0OMod(SDValue In, SDValue &Src, SDValue &SrcMods, 181 SDValue &Clamp, 182 SDValue &Omod) const; 183 184 bool SelectVOP3OMods(SDValue In, SDValue &Src, 185 SDValue &Clamp, SDValue &Omod) const; 186 187 bool SelectVOP3PMods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 188 bool SelectVOP3PMods0(SDValue In, SDValue &Src, SDValue &SrcMods, 189 SDValue &Clamp) const; 190 191 bool SelectVOP3OpSel(SDValue In, SDValue &Src, SDValue &SrcMods) const; 192 bool SelectVOP3OpSel0(SDValue In, SDValue &Src, SDValue &SrcMods, 193 SDValue &Clamp) const; 194 195 bool SelectVOP3OpSelMods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 196 bool SelectVOP3OpSelMods0(SDValue In, SDValue &Src, SDValue &SrcMods, 197 SDValue &Clamp) const; 198 199 void SelectADD_SUB_I64(SDNode *N); 200 void SelectUADDO_USUBO(SDNode *N); 201 void SelectDIV_SCALE(SDNode *N); 202 void SelectFMA_W_CHAIN(SDNode *N); 203 void SelectFMUL_W_CHAIN(SDNode *N); 204 205 SDNode *getS_BFE(unsigned Opcode, const SDLoc &DL, SDValue Val, 206 uint32_t Offset, uint32_t Width); 207 void SelectS_BFEFromShifts(SDNode *N); 208 void SelectS_BFE(SDNode *N); 209 bool isCBranchSCC(const SDNode *N) const; 210 void SelectBRCOND(SDNode *N); 211 void SelectATOMIC_CMP_SWAP(SDNode *N); 212 213 protected: 214 // Include the pieces autogenerated from the target description. 215 #include "AMDGPUGenDAGISel.inc" 216 }; 217 218 class R600DAGToDAGISel : public AMDGPUDAGToDAGISel { 219 public: 220 explicit R600DAGToDAGISel(TargetMachine *TM, CodeGenOpt::Level OptLevel) : 221 AMDGPUDAGToDAGISel(TM, OptLevel) {} 222 223 void Select(SDNode *N) override; 224 225 bool SelectADDRIndirect(SDValue Addr, SDValue &Base, 226 SDValue &Offset) override; 227 bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, 228 SDValue &Offset) override; 229 }; 230 231 } // end anonymous namespace 232 233 INITIALIZE_PASS_BEGIN(AMDGPUDAGToDAGISel, "isel", 234 "AMDGPU DAG->DAG Pattern Instruction Selection", false, false) 235 INITIALIZE_PASS_DEPENDENCY(AMDGPUArgumentUsageInfo) 236 INITIALIZE_PASS_END(AMDGPUDAGToDAGISel, "isel", 237 "AMDGPU DAG->DAG Pattern Instruction Selection", false, false) 238 239 /// \brief This pass converts a legalized DAG into a AMDGPU-specific 240 // DAG, ready for instruction scheduling. 241 FunctionPass *llvm::createAMDGPUISelDag(TargetMachine *TM, 242 CodeGenOpt::Level OptLevel) { 243 return new AMDGPUDAGToDAGISel(TM, OptLevel); 244 } 245 246 /// \brief This pass converts a legalized DAG into a R600-specific 247 // DAG, ready for instruction scheduling. 248 FunctionPass *llvm::createR600ISelDag(TargetMachine *TM, 249 CodeGenOpt::Level OptLevel) { 250 return new R600DAGToDAGISel(TM, OptLevel); 251 } 252 253 bool AMDGPUDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 254 Subtarget = &MF.getSubtarget<AMDGPUSubtarget>(); 255 return SelectionDAGISel::runOnMachineFunction(MF); 256 } 257 258 bool AMDGPUDAGToDAGISel::isNoNanSrc(SDValue N) const { 259 if (TM.Options.NoNaNsFPMath) 260 return true; 261 262 // TODO: Move into isKnownNeverNaN 263 if (N->getFlags().isDefined()) 264 return N->getFlags().hasNoNaNs(); 265 266 return CurDAG->isKnownNeverNaN(N); 267 } 268 269 bool AMDGPUDAGToDAGISel::isInlineImmediate(const SDNode *N) const { 270 const SIInstrInfo *TII 271 = static_cast<const SISubtarget *>(Subtarget)->getInstrInfo(); 272 273 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) 274 return TII->isInlineConstant(C->getAPIntValue()); 275 276 if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N)) 277 return TII->isInlineConstant(C->getValueAPF().bitcastToAPInt()); 278 279 return false; 280 } 281 282 /// \brief Determine the register class for \p OpNo 283 /// \returns The register class of the virtual register that will be used for 284 /// the given operand number \OpNo or NULL if the register class cannot be 285 /// determined. 286 const TargetRegisterClass *AMDGPUDAGToDAGISel::getOperandRegClass(SDNode *N, 287 unsigned OpNo) const { 288 if (!N->isMachineOpcode()) { 289 if (N->getOpcode() == ISD::CopyToReg) { 290 unsigned Reg = cast<RegisterSDNode>(N->getOperand(1))->getReg(); 291 if (TargetRegisterInfo::isVirtualRegister(Reg)) { 292 MachineRegisterInfo &MRI = CurDAG->getMachineFunction().getRegInfo(); 293 return MRI.getRegClass(Reg); 294 } 295 296 const SIRegisterInfo *TRI 297 = static_cast<const SISubtarget *>(Subtarget)->getRegisterInfo(); 298 return TRI->getPhysRegClass(Reg); 299 } 300 301 return nullptr; 302 } 303 304 switch (N->getMachineOpcode()) { 305 default: { 306 const MCInstrDesc &Desc = 307 Subtarget->getInstrInfo()->get(N->getMachineOpcode()); 308 unsigned OpIdx = Desc.getNumDefs() + OpNo; 309 if (OpIdx >= Desc.getNumOperands()) 310 return nullptr; 311 int RegClass = Desc.OpInfo[OpIdx].RegClass; 312 if (RegClass == -1) 313 return nullptr; 314 315 return Subtarget->getRegisterInfo()->getRegClass(RegClass); 316 } 317 case AMDGPU::REG_SEQUENCE: { 318 unsigned RCID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); 319 const TargetRegisterClass *SuperRC = 320 Subtarget->getRegisterInfo()->getRegClass(RCID); 321 322 SDValue SubRegOp = N->getOperand(OpNo + 1); 323 unsigned SubRegIdx = cast<ConstantSDNode>(SubRegOp)->getZExtValue(); 324 return Subtarget->getRegisterInfo()->getSubClassWithSubReg(SuperRC, 325 SubRegIdx); 326 } 327 } 328 } 329 330 SDNode *AMDGPUDAGToDAGISel::glueCopyToM0(SDNode *N) const { 331 if (cast<MemSDNode>(N)->getAddressSpace() != AMDGPUASI.LOCAL_ADDRESS) 332 return N; 333 334 const SITargetLowering& Lowering = 335 *static_cast<const SITargetLowering*>(getTargetLowering()); 336 337 // Write max value to m0 before each load operation 338 339 SDValue M0 = Lowering.copyToM0(*CurDAG, CurDAG->getEntryNode(), SDLoc(N), 340 CurDAG->getTargetConstant(-1, SDLoc(N), MVT::i32)); 341 342 SDValue Glue = M0.getValue(1); 343 344 SmallVector <SDValue, 8> Ops; 345 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { 346 Ops.push_back(N->getOperand(i)); 347 } 348 Ops.push_back(Glue); 349 CurDAG->MorphNodeTo(N, N->getOpcode(), N->getVTList(), Ops); 350 351 return N; 352 } 353 354 static unsigned selectSGPRVectorRegClassID(unsigned NumVectorElts) { 355 switch (NumVectorElts) { 356 case 1: 357 return AMDGPU::SReg_32_XM0RegClassID; 358 case 2: 359 return AMDGPU::SReg_64RegClassID; 360 case 4: 361 return AMDGPU::SReg_128RegClassID; 362 case 8: 363 return AMDGPU::SReg_256RegClassID; 364 case 16: 365 return AMDGPU::SReg_512RegClassID; 366 } 367 368 llvm_unreachable("invalid vector size"); 369 } 370 371 static bool getConstantValue(SDValue N, uint32_t &Out) { 372 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 373 Out = C->getAPIntValue().getZExtValue(); 374 return true; 375 } 376 377 if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N)) { 378 Out = C->getValueAPF().bitcastToAPInt().getZExtValue(); 379 return true; 380 } 381 382 return false; 383 } 384 385 void AMDGPUDAGToDAGISel::SelectBuildVector(SDNode *N, unsigned RegClassID) { 386 EVT VT = N->getValueType(0); 387 unsigned NumVectorElts = VT.getVectorNumElements(); 388 EVT EltVT = VT.getVectorElementType(); 389 const AMDGPURegisterInfo *TRI = Subtarget->getRegisterInfo(); 390 SDLoc DL(N); 391 SDValue RegClass = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32); 392 393 if (NumVectorElts == 1) { 394 CurDAG->SelectNodeTo(N, AMDGPU::COPY_TO_REGCLASS, EltVT, N->getOperand(0), 395 RegClass); 396 return; 397 } 398 399 assert(NumVectorElts <= 16 && "Vectors with more than 16 elements not " 400 "supported yet"); 401 // 16 = Max Num Vector Elements 402 // 2 = 2 REG_SEQUENCE operands per element (value, subreg index) 403 // 1 = Vector Register Class 404 SmallVector<SDValue, 16 * 2 + 1> RegSeqArgs(NumVectorElts * 2 + 1); 405 406 RegSeqArgs[0] = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32); 407 bool IsRegSeq = true; 408 unsigned NOps = N->getNumOperands(); 409 for (unsigned i = 0; i < NOps; i++) { 410 // XXX: Why is this here? 411 if (isa<RegisterSDNode>(N->getOperand(i))) { 412 IsRegSeq = false; 413 break; 414 } 415 RegSeqArgs[1 + (2 * i)] = N->getOperand(i); 416 RegSeqArgs[1 + (2 * i) + 1] = 417 CurDAG->getTargetConstant(TRI->getSubRegFromChannel(i), DL, 418 MVT::i32); 419 } 420 if (NOps != NumVectorElts) { 421 // Fill in the missing undef elements if this was a scalar_to_vector. 422 assert(N->getOpcode() == ISD::SCALAR_TO_VECTOR && NOps < NumVectorElts); 423 MachineSDNode *ImpDef = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, 424 DL, EltVT); 425 for (unsigned i = NOps; i < NumVectorElts; ++i) { 426 RegSeqArgs[1 + (2 * i)] = SDValue(ImpDef, 0); 427 RegSeqArgs[1 + (2 * i) + 1] = 428 CurDAG->getTargetConstant(TRI->getSubRegFromChannel(i), DL, MVT::i32); 429 } 430 } 431 432 if (!IsRegSeq) 433 SelectCode(N); 434 CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, N->getVTList(), RegSeqArgs); 435 } 436 437 void AMDGPUDAGToDAGISel::Select(SDNode *N) { 438 unsigned int Opc = N->getOpcode(); 439 if (N->isMachineOpcode()) { 440 N->setNodeId(-1); 441 return; // Already selected. 442 } 443 444 if (isa<AtomicSDNode>(N) || 445 (Opc == AMDGPUISD::ATOMIC_INC || Opc == AMDGPUISD::ATOMIC_DEC)) 446 N = glueCopyToM0(N); 447 448 switch (Opc) { 449 default: break; 450 // We are selecting i64 ADD here instead of custom lower it during 451 // DAG legalization, so we can fold some i64 ADDs used for address 452 // calculation into the LOAD and STORE instructions. 453 case ISD::ADD: 454 case ISD::ADDC: 455 case ISD::ADDE: 456 case ISD::SUB: 457 case ISD::SUBC: 458 case ISD::SUBE: { 459 if (N->getValueType(0) != MVT::i64) 460 break; 461 462 SelectADD_SUB_I64(N); 463 return; 464 } 465 case ISD::UADDO: 466 case ISD::USUBO: { 467 SelectUADDO_USUBO(N); 468 return; 469 } 470 case AMDGPUISD::FMUL_W_CHAIN: { 471 SelectFMUL_W_CHAIN(N); 472 return; 473 } 474 case AMDGPUISD::FMA_W_CHAIN: { 475 SelectFMA_W_CHAIN(N); 476 return; 477 } 478 479 case ISD::SCALAR_TO_VECTOR: 480 case ISD::BUILD_VECTOR: { 481 EVT VT = N->getValueType(0); 482 unsigned NumVectorElts = VT.getVectorNumElements(); 483 484 if (VT == MVT::v2i16 || VT == MVT::v2f16) { 485 if (Opc == ISD::BUILD_VECTOR) { 486 uint32_t LHSVal, RHSVal; 487 if (getConstantValue(N->getOperand(0), LHSVal) && 488 getConstantValue(N->getOperand(1), RHSVal)) { 489 uint32_t K = LHSVal | (RHSVal << 16); 490 CurDAG->SelectNodeTo(N, AMDGPU::S_MOV_B32, VT, 491 CurDAG->getTargetConstant(K, SDLoc(N), MVT::i32)); 492 return; 493 } 494 } 495 496 break; 497 } 498 499 assert(VT.getVectorElementType().bitsEq(MVT::i32)); 500 unsigned RegClassID = selectSGPRVectorRegClassID(NumVectorElts); 501 SelectBuildVector(N, RegClassID); 502 return; 503 } 504 case ISD::BUILD_PAIR: { 505 SDValue RC, SubReg0, SubReg1; 506 SDLoc DL(N); 507 if (N->getValueType(0) == MVT::i128) { 508 RC = CurDAG->getTargetConstant(AMDGPU::SReg_128RegClassID, DL, MVT::i32); 509 SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32); 510 SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32); 511 } else if (N->getValueType(0) == MVT::i64) { 512 RC = CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32); 513 SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32); 514 SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32); 515 } else { 516 llvm_unreachable("Unhandled value type for BUILD_PAIR"); 517 } 518 const SDValue Ops[] = { RC, N->getOperand(0), SubReg0, 519 N->getOperand(1), SubReg1 }; 520 ReplaceNode(N, CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, 521 N->getValueType(0), Ops)); 522 return; 523 } 524 525 case ISD::Constant: 526 case ISD::ConstantFP: { 527 if (N->getValueType(0).getSizeInBits() != 64 || isInlineImmediate(N)) 528 break; 529 530 uint64_t Imm; 531 if (ConstantFPSDNode *FP = dyn_cast<ConstantFPSDNode>(N)) 532 Imm = FP->getValueAPF().bitcastToAPInt().getZExtValue(); 533 else { 534 ConstantSDNode *C = cast<ConstantSDNode>(N); 535 Imm = C->getZExtValue(); 536 } 537 538 SDLoc DL(N); 539 SDNode *Lo = CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, 540 CurDAG->getConstant(Imm & 0xFFFFFFFF, DL, 541 MVT::i32)); 542 SDNode *Hi = CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, 543 CurDAG->getConstant(Imm >> 32, DL, MVT::i32)); 544 const SDValue Ops[] = { 545 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32), 546 SDValue(Lo, 0), CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32), 547 SDValue(Hi, 0), CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32) 548 }; 549 550 ReplaceNode(N, CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, 551 N->getValueType(0), Ops)); 552 return; 553 } 554 case ISD::LOAD: 555 case ISD::STORE: { 556 N = glueCopyToM0(N); 557 break; 558 } 559 560 case AMDGPUISD::BFE_I32: 561 case AMDGPUISD::BFE_U32: { 562 // There is a scalar version available, but unlike the vector version which 563 // has a separate operand for the offset and width, the scalar version packs 564 // the width and offset into a single operand. Try to move to the scalar 565 // version if the offsets are constant, so that we can try to keep extended 566 // loads of kernel arguments in SGPRs. 567 568 // TODO: Technically we could try to pattern match scalar bitshifts of 569 // dynamic values, but it's probably not useful. 570 ConstantSDNode *Offset = dyn_cast<ConstantSDNode>(N->getOperand(1)); 571 if (!Offset) 572 break; 573 574 ConstantSDNode *Width = dyn_cast<ConstantSDNode>(N->getOperand(2)); 575 if (!Width) 576 break; 577 578 bool Signed = Opc == AMDGPUISD::BFE_I32; 579 580 uint32_t OffsetVal = Offset->getZExtValue(); 581 uint32_t WidthVal = Width->getZExtValue(); 582 583 ReplaceNode(N, getS_BFE(Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32, 584 SDLoc(N), N->getOperand(0), OffsetVal, WidthVal)); 585 return; 586 } 587 case AMDGPUISD::DIV_SCALE: { 588 SelectDIV_SCALE(N); 589 return; 590 } 591 case ISD::CopyToReg: { 592 const SITargetLowering& Lowering = 593 *static_cast<const SITargetLowering*>(getTargetLowering()); 594 N = Lowering.legalizeTargetIndependentNode(N, *CurDAG); 595 break; 596 } 597 case ISD::AND: 598 case ISD::SRL: 599 case ISD::SRA: 600 case ISD::SIGN_EXTEND_INREG: 601 if (N->getValueType(0) != MVT::i32) 602 break; 603 604 SelectS_BFE(N); 605 return; 606 case ISD::BRCOND: 607 SelectBRCOND(N); 608 return; 609 610 case AMDGPUISD::ATOMIC_CMP_SWAP: 611 SelectATOMIC_CMP_SWAP(N); 612 return; 613 } 614 615 SelectCode(N); 616 } 617 618 bool AMDGPUDAGToDAGISel::isConstantLoad(const MemSDNode *N, int CbId) const { 619 if (!N->readMem()) 620 return false; 621 if (CbId == -1) 622 return N->getAddressSpace() == AMDGPUASI.CONSTANT_ADDRESS; 623 624 return N->getAddressSpace() == AMDGPUASI.CONSTANT_BUFFER_0 + CbId; 625 } 626 627 bool AMDGPUDAGToDAGISel::isUniformBr(const SDNode *N) const { 628 const BasicBlock *BB = FuncInfo->MBB->getBasicBlock(); 629 const Instruction *Term = BB->getTerminator(); 630 return Term->getMetadata("amdgpu.uniform") || 631 Term->getMetadata("structurizecfg.uniform"); 632 } 633 634 StringRef AMDGPUDAGToDAGISel::getPassName() const { 635 return "AMDGPU DAG->DAG Pattern Instruction Selection"; 636 } 637 638 //===----------------------------------------------------------------------===// 639 // Complex Patterns 640 //===----------------------------------------------------------------------===// 641 642 bool AMDGPUDAGToDAGISel::SelectGlobalValueConstantOffset(SDValue Addr, 643 SDValue& IntPtr) { 644 if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Addr)) { 645 IntPtr = CurDAG->getIntPtrConstant(Cst->getZExtValue() / 4, SDLoc(Addr), 646 true); 647 return true; 648 } 649 return false; 650 } 651 652 bool AMDGPUDAGToDAGISel::SelectGlobalValueVariableOffset(SDValue Addr, 653 SDValue& BaseReg, SDValue &Offset) { 654 if (!isa<ConstantSDNode>(Addr)) { 655 BaseReg = Addr; 656 Offset = CurDAG->getIntPtrConstant(0, SDLoc(Addr), true); 657 return true; 658 } 659 return false; 660 } 661 662 bool AMDGPUDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base, 663 SDValue &Offset) { 664 return false; 665 } 666 667 bool AMDGPUDAGToDAGISel::SelectADDRIndirect(SDValue Addr, SDValue &Base, 668 SDValue &Offset) { 669 ConstantSDNode *C; 670 SDLoc DL(Addr); 671 672 if ((C = dyn_cast<ConstantSDNode>(Addr))) { 673 Base = CurDAG->getRegister(AMDGPU::INDIRECT_BASE_ADDR, MVT::i32); 674 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 675 } else if ((Addr.getOpcode() == AMDGPUISD::DWORDADDR) && 676 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(0)))) { 677 Base = CurDAG->getRegister(AMDGPU::INDIRECT_BASE_ADDR, MVT::i32); 678 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 679 } else if ((Addr.getOpcode() == ISD::ADD || Addr.getOpcode() == ISD::OR) && 680 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) { 681 Base = Addr.getOperand(0); 682 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 683 } else { 684 Base = Addr; 685 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); 686 } 687 688 return true; 689 } 690 691 void AMDGPUDAGToDAGISel::SelectADD_SUB_I64(SDNode *N) { 692 SDLoc DL(N); 693 SDValue LHS = N->getOperand(0); 694 SDValue RHS = N->getOperand(1); 695 696 unsigned Opcode = N->getOpcode(); 697 bool ConsumeCarry = (Opcode == ISD::ADDE || Opcode == ISD::SUBE); 698 bool ProduceCarry = 699 ConsumeCarry || Opcode == ISD::ADDC || Opcode == ISD::SUBC; 700 bool IsAdd = 701 (Opcode == ISD::ADD || Opcode == ISD::ADDC || Opcode == ISD::ADDE); 702 703 SDValue Sub0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32); 704 SDValue Sub1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32); 705 706 SDNode *Lo0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 707 DL, MVT::i32, LHS, Sub0); 708 SDNode *Hi0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 709 DL, MVT::i32, LHS, Sub1); 710 711 SDNode *Lo1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 712 DL, MVT::i32, RHS, Sub0); 713 SDNode *Hi1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 714 DL, MVT::i32, RHS, Sub1); 715 716 SDVTList VTList = CurDAG->getVTList(MVT::i32, MVT::Glue); 717 718 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32; 719 unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32; 720 721 SDNode *AddLo; 722 if (!ConsumeCarry) { 723 SDValue Args[] = { SDValue(Lo0, 0), SDValue(Lo1, 0) }; 724 AddLo = CurDAG->getMachineNode(Opc, DL, VTList, Args); 725 } else { 726 SDValue Args[] = { SDValue(Lo0, 0), SDValue(Lo1, 0), N->getOperand(2) }; 727 AddLo = CurDAG->getMachineNode(CarryOpc, DL, VTList, Args); 728 } 729 SDValue AddHiArgs[] = { 730 SDValue(Hi0, 0), 731 SDValue(Hi1, 0), 732 SDValue(AddLo, 1) 733 }; 734 SDNode *AddHi = CurDAG->getMachineNode(CarryOpc, DL, VTList, AddHiArgs); 735 736 SDValue RegSequenceArgs[] = { 737 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32), 738 SDValue(AddLo,0), 739 Sub0, 740 SDValue(AddHi,0), 741 Sub1, 742 }; 743 SDNode *RegSequence = CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, DL, 744 MVT::i64, RegSequenceArgs); 745 746 if (ProduceCarry) { 747 // Replace the carry-use 748 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 1), SDValue(AddHi, 1)); 749 } 750 751 // Replace the remaining uses. 752 CurDAG->ReplaceAllUsesWith(N, RegSequence); 753 CurDAG->RemoveDeadNode(N); 754 } 755 756 void AMDGPUDAGToDAGISel::SelectUADDO_USUBO(SDNode *N) { 757 // The name of the opcodes are misleading. v_add_i32/v_sub_i32 have unsigned 758 // carry out despite the _i32 name. These were renamed in VI to _U32. 759 // FIXME: We should probably rename the opcodes here. 760 unsigned Opc = N->getOpcode() == ISD::UADDO ? 761 AMDGPU::V_ADD_I32_e64 : AMDGPU::V_SUB_I32_e64; 762 763 CurDAG->SelectNodeTo(N, Opc, N->getVTList(), 764 { N->getOperand(0), N->getOperand(1) }); 765 } 766 767 void AMDGPUDAGToDAGISel::SelectFMA_W_CHAIN(SDNode *N) { 768 SDLoc SL(N); 769 // src0_modifiers, src0, src1_modifiers, src1, src2_modifiers, src2, clamp, omod 770 SDValue Ops[10]; 771 772 SelectVOP3Mods0(N->getOperand(1), Ops[1], Ops[0], Ops[6], Ops[7]); 773 SelectVOP3Mods(N->getOperand(2), Ops[3], Ops[2]); 774 SelectVOP3Mods(N->getOperand(3), Ops[5], Ops[4]); 775 Ops[8] = N->getOperand(0); 776 Ops[9] = N->getOperand(4); 777 778 CurDAG->SelectNodeTo(N, AMDGPU::V_FMA_F32, N->getVTList(), Ops); 779 } 780 781 void AMDGPUDAGToDAGISel::SelectFMUL_W_CHAIN(SDNode *N) { 782 SDLoc SL(N); 783 // src0_modifiers, src0, src1_modifiers, src1, clamp, omod 784 SDValue Ops[8]; 785 786 SelectVOP3Mods0(N->getOperand(1), Ops[1], Ops[0], Ops[4], Ops[5]); 787 SelectVOP3Mods(N->getOperand(2), Ops[3], Ops[2]); 788 Ops[6] = N->getOperand(0); 789 Ops[7] = N->getOperand(3); 790 791 CurDAG->SelectNodeTo(N, AMDGPU::V_MUL_F32_e64, N->getVTList(), Ops); 792 } 793 794 // We need to handle this here because tablegen doesn't support matching 795 // instructions with multiple outputs. 796 void AMDGPUDAGToDAGISel::SelectDIV_SCALE(SDNode *N) { 797 SDLoc SL(N); 798 EVT VT = N->getValueType(0); 799 800 assert(VT == MVT::f32 || VT == MVT::f64); 801 802 unsigned Opc 803 = (VT == MVT::f64) ? AMDGPU::V_DIV_SCALE_F64 : AMDGPU::V_DIV_SCALE_F32; 804 805 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2) }; 806 CurDAG->SelectNodeTo(N, Opc, N->getVTList(), Ops); 807 } 808 809 bool AMDGPUDAGToDAGISel::isDSOffsetLegal(const SDValue &Base, unsigned Offset, 810 unsigned OffsetBits) const { 811 if ((OffsetBits == 16 && !isUInt<16>(Offset)) || 812 (OffsetBits == 8 && !isUInt<8>(Offset))) 813 return false; 814 815 if (Subtarget->getGeneration() >= AMDGPUSubtarget::SEA_ISLANDS || 816 Subtarget->unsafeDSOffsetFoldingEnabled()) 817 return true; 818 819 // On Southern Islands instruction with a negative base value and an offset 820 // don't seem to work. 821 return CurDAG->SignBitIsZero(Base); 822 } 823 824 bool AMDGPUDAGToDAGISel::SelectDS1Addr1Offset(SDValue Addr, SDValue &Base, 825 SDValue &Offset) const { 826 SDLoc DL(Addr); 827 if (CurDAG->isBaseWithConstantOffset(Addr)) { 828 SDValue N0 = Addr.getOperand(0); 829 SDValue N1 = Addr.getOperand(1); 830 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 831 if (isDSOffsetLegal(N0, C1->getSExtValue(), 16)) { 832 // (add n0, c0) 833 Base = N0; 834 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16); 835 return true; 836 } 837 } else if (Addr.getOpcode() == ISD::SUB) { 838 // sub C, x -> add (sub 0, x), C 839 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Addr.getOperand(0))) { 840 int64_t ByteOffset = C->getSExtValue(); 841 if (isUInt<16>(ByteOffset)) { 842 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32); 843 844 // XXX - This is kind of hacky. Create a dummy sub node so we can check 845 // the known bits in isDSOffsetLegal. We need to emit the selected node 846 // here, so this is thrown away. 847 SDValue Sub = CurDAG->getNode(ISD::SUB, DL, MVT::i32, 848 Zero, Addr.getOperand(1)); 849 850 if (isDSOffsetLegal(Sub, ByteOffset, 16)) { 851 MachineSDNode *MachineSub 852 = CurDAG->getMachineNode(AMDGPU::V_SUB_I32_e32, DL, MVT::i32, 853 Zero, Addr.getOperand(1)); 854 855 Base = SDValue(MachineSub, 0); 856 Offset = CurDAG->getTargetConstant(ByteOffset, DL, MVT::i16); 857 return true; 858 } 859 } 860 } 861 } else if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) { 862 // If we have a constant address, prefer to put the constant into the 863 // offset. This can save moves to load the constant address since multiple 864 // operations can share the zero base address register, and enables merging 865 // into read2 / write2 instructions. 866 867 SDLoc DL(Addr); 868 869 if (isUInt<16>(CAddr->getZExtValue())) { 870 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32); 871 MachineSDNode *MovZero = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, 872 DL, MVT::i32, Zero); 873 Base = SDValue(MovZero, 0); 874 Offset = CurDAG->getTargetConstant(CAddr->getZExtValue(), DL, MVT::i16); 875 return true; 876 } 877 } 878 879 // default case 880 Base = Addr; 881 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i16); 882 return true; 883 } 884 885 // TODO: If offset is too big, put low 16-bit into offset. 886 bool AMDGPUDAGToDAGISel::SelectDS64Bit4ByteAligned(SDValue Addr, SDValue &Base, 887 SDValue &Offset0, 888 SDValue &Offset1) const { 889 SDLoc DL(Addr); 890 891 if (CurDAG->isBaseWithConstantOffset(Addr)) { 892 SDValue N0 = Addr.getOperand(0); 893 SDValue N1 = Addr.getOperand(1); 894 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 895 unsigned DWordOffset0 = C1->getZExtValue() / 4; 896 unsigned DWordOffset1 = DWordOffset0 + 1; 897 // (add n0, c0) 898 if (isDSOffsetLegal(N0, DWordOffset1, 8)) { 899 Base = N0; 900 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8); 901 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8); 902 return true; 903 } 904 } else if (Addr.getOpcode() == ISD::SUB) { 905 // sub C, x -> add (sub 0, x), C 906 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Addr.getOperand(0))) { 907 unsigned DWordOffset0 = C->getZExtValue() / 4; 908 unsigned DWordOffset1 = DWordOffset0 + 1; 909 910 if (isUInt<8>(DWordOffset0)) { 911 SDLoc DL(Addr); 912 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32); 913 914 // XXX - This is kind of hacky. Create a dummy sub node so we can check 915 // the known bits in isDSOffsetLegal. We need to emit the selected node 916 // here, so this is thrown away. 917 SDValue Sub = CurDAG->getNode(ISD::SUB, DL, MVT::i32, 918 Zero, Addr.getOperand(1)); 919 920 if (isDSOffsetLegal(Sub, DWordOffset1, 8)) { 921 MachineSDNode *MachineSub 922 = CurDAG->getMachineNode(AMDGPU::V_SUB_I32_e32, DL, MVT::i32, 923 Zero, Addr.getOperand(1)); 924 925 Base = SDValue(MachineSub, 0); 926 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8); 927 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8); 928 return true; 929 } 930 } 931 } 932 } else if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) { 933 unsigned DWordOffset0 = CAddr->getZExtValue() / 4; 934 unsigned DWordOffset1 = DWordOffset0 + 1; 935 assert(4 * DWordOffset0 == CAddr->getZExtValue()); 936 937 if (isUInt<8>(DWordOffset0) && isUInt<8>(DWordOffset1)) { 938 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32); 939 MachineSDNode *MovZero 940 = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, 941 DL, MVT::i32, Zero); 942 Base = SDValue(MovZero, 0); 943 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8); 944 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8); 945 return true; 946 } 947 } 948 949 // default case 950 951 // FIXME: This is broken on SI where we still need to check if the base 952 // pointer is positive here. 953 Base = Addr; 954 Offset0 = CurDAG->getTargetConstant(0, DL, MVT::i8); 955 Offset1 = CurDAG->getTargetConstant(1, DL, MVT::i8); 956 return true; 957 } 958 959 static bool isLegalMUBUFImmOffset(unsigned Imm) { 960 return isUInt<12>(Imm); 961 } 962 963 static bool isLegalMUBUFImmOffset(const ConstantSDNode *Imm) { 964 return isLegalMUBUFImmOffset(Imm->getZExtValue()); 965 } 966 967 bool AMDGPUDAGToDAGISel::SelectMUBUF(SDValue Addr, SDValue &Ptr, 968 SDValue &VAddr, SDValue &SOffset, 969 SDValue &Offset, SDValue &Offen, 970 SDValue &Idxen, SDValue &Addr64, 971 SDValue &GLC, SDValue &SLC, 972 SDValue &TFE) const { 973 // Subtarget prefers to use flat instruction 974 if (Subtarget->useFlatForGlobal()) 975 return false; 976 977 SDLoc DL(Addr); 978 979 if (!GLC.getNode()) 980 GLC = CurDAG->getTargetConstant(0, DL, MVT::i1); 981 if (!SLC.getNode()) 982 SLC = CurDAG->getTargetConstant(0, DL, MVT::i1); 983 TFE = CurDAG->getTargetConstant(0, DL, MVT::i1); 984 985 Idxen = CurDAG->getTargetConstant(0, DL, MVT::i1); 986 Offen = CurDAG->getTargetConstant(0, DL, MVT::i1); 987 Addr64 = CurDAG->getTargetConstant(0, DL, MVT::i1); 988 SOffset = CurDAG->getTargetConstant(0, DL, MVT::i32); 989 990 if (CurDAG->isBaseWithConstantOffset(Addr)) { 991 SDValue N0 = Addr.getOperand(0); 992 SDValue N1 = Addr.getOperand(1); 993 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 994 995 if (N0.getOpcode() == ISD::ADD) { 996 // (add (add N2, N3), C1) -> addr64 997 SDValue N2 = N0.getOperand(0); 998 SDValue N3 = N0.getOperand(1); 999 Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1); 1000 Ptr = N2; 1001 VAddr = N3; 1002 } else { 1003 // (add N0, C1) -> offset 1004 VAddr = CurDAG->getTargetConstant(0, DL, MVT::i32); 1005 Ptr = N0; 1006 } 1007 1008 if (isLegalMUBUFImmOffset(C1)) { 1009 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16); 1010 return true; 1011 } 1012 1013 if (isUInt<32>(C1->getZExtValue())) { 1014 // Illegal offset, store it in soffset. 1015 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16); 1016 SOffset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, 1017 CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i32)), 1018 0); 1019 return true; 1020 } 1021 } 1022 1023 if (Addr.getOpcode() == ISD::ADD) { 1024 // (add N0, N1) -> addr64 1025 SDValue N0 = Addr.getOperand(0); 1026 SDValue N1 = Addr.getOperand(1); 1027 Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1); 1028 Ptr = N0; 1029 VAddr = N1; 1030 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16); 1031 return true; 1032 } 1033 1034 // default case -> offset 1035 VAddr = CurDAG->getTargetConstant(0, DL, MVT::i32); 1036 Ptr = Addr; 1037 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16); 1038 1039 return true; 1040 } 1041 1042 bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, 1043 SDValue &VAddr, SDValue &SOffset, 1044 SDValue &Offset, SDValue &GLC, 1045 SDValue &SLC, SDValue &TFE) const { 1046 SDValue Ptr, Offen, Idxen, Addr64; 1047 1048 // addr64 bit was removed for volcanic islands. 1049 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS) 1050 return false; 1051 1052 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64, 1053 GLC, SLC, TFE)) 1054 return false; 1055 1056 ConstantSDNode *C = cast<ConstantSDNode>(Addr64); 1057 if (C->getSExtValue()) { 1058 SDLoc DL(Addr); 1059 1060 const SITargetLowering& Lowering = 1061 *static_cast<const SITargetLowering*>(getTargetLowering()); 1062 1063 SRsrc = SDValue(Lowering.wrapAddr64Rsrc(*CurDAG, DL, Ptr), 0); 1064 return true; 1065 } 1066 1067 return false; 1068 } 1069 1070 bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, 1071 SDValue &VAddr, SDValue &SOffset, 1072 SDValue &Offset, 1073 SDValue &SLC) const { 1074 SLC = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i1); 1075 SDValue GLC, TFE; 1076 1077 return SelectMUBUFAddr64(Addr, SRsrc, VAddr, SOffset, Offset, GLC, SLC, TFE); 1078 } 1079 1080 static bool isStackPtrRelative(const MachinePointerInfo &PtrInfo) { 1081 auto PSV = PtrInfo.V.dyn_cast<const PseudoSourceValue *>(); 1082 return PSV && PSV->isStack(); 1083 } 1084 1085 std::pair<SDValue, SDValue> AMDGPUDAGToDAGISel::foldFrameIndex(SDValue N) const { 1086 const MachineFunction &MF = CurDAG->getMachineFunction(); 1087 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>(); 1088 1089 if (auto FI = dyn_cast<FrameIndexSDNode>(N)) { 1090 SDValue TFI = CurDAG->getTargetFrameIndex(FI->getIndex(), 1091 FI->getValueType(0)); 1092 1093 // If we can resolve this to a frame index access, this is relative to the 1094 // frame pointer SGPR. 1095 return std::make_pair(TFI, CurDAG->getRegister(Info->getFrameOffsetReg(), 1096 MVT::i32)); 1097 } 1098 1099 // If we don't know this private access is a local stack object, it needs to 1100 // be relative to the entry point's scratch wave offset register. 1101 return std::make_pair(N, CurDAG->getRegister(Info->getScratchWaveOffsetReg(), 1102 MVT::i32)); 1103 } 1104 1105 bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(SDNode *Root, 1106 SDValue Addr, SDValue &Rsrc, 1107 SDValue &VAddr, SDValue &SOffset, 1108 SDValue &ImmOffset) const { 1109 1110 SDLoc DL(Addr); 1111 MachineFunction &MF = CurDAG->getMachineFunction(); 1112 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>(); 1113 1114 Rsrc = CurDAG->getRegister(Info->getScratchRSrcReg(), MVT::v4i32); 1115 1116 if (ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) { 1117 unsigned Imm = CAddr->getZExtValue(); 1118 assert(!isLegalMUBUFImmOffset(Imm) && 1119 "should have been selected by other pattern"); 1120 1121 SDValue HighBits = CurDAG->getTargetConstant(Imm & ~4095, DL, MVT::i32); 1122 MachineSDNode *MovHighBits = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, 1123 DL, MVT::i32, HighBits); 1124 VAddr = SDValue(MovHighBits, 0); 1125 1126 // In a call sequence, stores to the argument stack area are relative to the 1127 // stack pointer. 1128 const MachinePointerInfo &PtrInfo = cast<MemSDNode>(Root)->getPointerInfo(); 1129 unsigned SOffsetReg = isStackPtrRelative(PtrInfo) ? 1130 Info->getStackPtrOffsetReg() : Info->getScratchWaveOffsetReg(); 1131 1132 SOffset = CurDAG->getRegister(SOffsetReg, MVT::i32); 1133 ImmOffset = CurDAG->getTargetConstant(Imm & 4095, DL, MVT::i16); 1134 return true; 1135 } 1136 1137 if (CurDAG->isBaseWithConstantOffset(Addr)) { 1138 // (add n0, c1) 1139 1140 SDValue N0 = Addr.getOperand(0); 1141 SDValue N1 = Addr.getOperand(1); 1142 1143 // Offsets in vaddr must be positive. 1144 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 1145 if (isLegalMUBUFImmOffset(C1)) { 1146 std::tie(VAddr, SOffset) = foldFrameIndex(N0); 1147 ImmOffset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16); 1148 return true; 1149 } 1150 } 1151 1152 // (node) 1153 std::tie(VAddr, SOffset) = foldFrameIndex(Addr); 1154 ImmOffset = CurDAG->getTargetConstant(0, DL, MVT::i16); 1155 return true; 1156 } 1157 1158 bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffset(SDNode *Root, 1159 SDValue Addr, 1160 SDValue &SRsrc, 1161 SDValue &SOffset, 1162 SDValue &Offset) const { 1163 ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr); 1164 if (!CAddr || !isLegalMUBUFImmOffset(CAddr)) 1165 return false; 1166 1167 SDLoc DL(Addr); 1168 MachineFunction &MF = CurDAG->getMachineFunction(); 1169 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>(); 1170 1171 SRsrc = CurDAG->getRegister(Info->getScratchRSrcReg(), MVT::v4i32); 1172 1173 const MachinePointerInfo &PtrInfo = cast<MemSDNode>(Root)->getPointerInfo(); 1174 unsigned SOffsetReg = isStackPtrRelative(PtrInfo) ? 1175 Info->getStackPtrOffsetReg() : Info->getScratchWaveOffsetReg(); 1176 1177 // FIXME: Get from MachinePointerInfo? We should only be using the frame 1178 // offset if we know this is in a call sequence. 1179 SOffset = CurDAG->getRegister(SOffsetReg, MVT::i32); 1180 1181 Offset = CurDAG->getTargetConstant(CAddr->getZExtValue(), DL, MVT::i16); 1182 return true; 1183 } 1184 1185 bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, 1186 SDValue &SOffset, SDValue &Offset, 1187 SDValue &GLC, SDValue &SLC, 1188 SDValue &TFE) const { 1189 SDValue Ptr, VAddr, Offen, Idxen, Addr64; 1190 const SIInstrInfo *TII = 1191 static_cast<const SIInstrInfo *>(Subtarget->getInstrInfo()); 1192 1193 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64, 1194 GLC, SLC, TFE)) 1195 return false; 1196 1197 if (!cast<ConstantSDNode>(Offen)->getSExtValue() && 1198 !cast<ConstantSDNode>(Idxen)->getSExtValue() && 1199 !cast<ConstantSDNode>(Addr64)->getSExtValue()) { 1200 uint64_t Rsrc = TII->getDefaultRsrcDataFormat() | 1201 APInt::getAllOnesValue(32).getZExtValue(); // Size 1202 SDLoc DL(Addr); 1203 1204 const SITargetLowering& Lowering = 1205 *static_cast<const SITargetLowering*>(getTargetLowering()); 1206 1207 SRsrc = SDValue(Lowering.buildRSRC(*CurDAG, DL, Ptr, 0, Rsrc), 0); 1208 return true; 1209 } 1210 return false; 1211 } 1212 1213 bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, 1214 SDValue &Soffset, SDValue &Offset 1215 ) const { 1216 SDValue GLC, SLC, TFE; 1217 1218 return SelectMUBUFOffset(Addr, SRsrc, Soffset, Offset, GLC, SLC, TFE); 1219 } 1220 bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, 1221 SDValue &Soffset, SDValue &Offset, 1222 SDValue &SLC) const { 1223 SDValue GLC, TFE; 1224 1225 return SelectMUBUFOffset(Addr, SRsrc, Soffset, Offset, GLC, SLC, TFE); 1226 } 1227 1228 bool AMDGPUDAGToDAGISel::SelectMUBUFConstant(SDValue Constant, 1229 SDValue &SOffset, 1230 SDValue &ImmOffset) const { 1231 SDLoc DL(Constant); 1232 uint32_t Imm = cast<ConstantSDNode>(Constant)->getZExtValue(); 1233 uint32_t Overflow = 0; 1234 1235 if (Imm >= 4096) { 1236 if (Imm <= 4095 + 64) { 1237 // Use an SOffset inline constant for 1..64 1238 Overflow = Imm - 4095; 1239 Imm = 4095; 1240 } else { 1241 // Try to keep the same value in SOffset for adjacent loads, so that 1242 // the corresponding register contents can be re-used. 1243 // 1244 // Load values with all low-bits set into SOffset, so that a larger 1245 // range of values can be covered using s_movk_i32 1246 uint32_t High = (Imm + 1) & ~4095; 1247 uint32_t Low = (Imm + 1) & 4095; 1248 Imm = Low; 1249 Overflow = High - 1; 1250 } 1251 } 1252 1253 // There is a hardware bug in SI and CI which prevents address clamping in 1254 // MUBUF instructions from working correctly with SOffsets. The immediate 1255 // offset is unaffected. 1256 if (Overflow > 0 && 1257 Subtarget->getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS) 1258 return false; 1259 1260 ImmOffset = CurDAG->getTargetConstant(Imm, DL, MVT::i16); 1261 1262 if (Overflow <= 64) 1263 SOffset = CurDAG->getTargetConstant(Overflow, DL, MVT::i32); 1264 else 1265 SOffset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, 1266 CurDAG->getTargetConstant(Overflow, DL, MVT::i32)), 1267 0); 1268 1269 return true; 1270 } 1271 1272 bool AMDGPUDAGToDAGISel::SelectMUBUFIntrinsicOffset(SDValue Offset, 1273 SDValue &SOffset, 1274 SDValue &ImmOffset) const { 1275 SDLoc DL(Offset); 1276 1277 if (!isa<ConstantSDNode>(Offset)) 1278 return false; 1279 1280 return SelectMUBUFConstant(Offset, SOffset, ImmOffset); 1281 } 1282 1283 bool AMDGPUDAGToDAGISel::SelectMUBUFIntrinsicVOffset(SDValue Offset, 1284 SDValue &SOffset, 1285 SDValue &ImmOffset, 1286 SDValue &VOffset) const { 1287 SDLoc DL(Offset); 1288 1289 // Don't generate an unnecessary voffset for constant offsets. 1290 if (isa<ConstantSDNode>(Offset)) { 1291 SDValue Tmp1, Tmp2; 1292 1293 // When necessary, use a voffset in <= CI anyway to work around a hardware 1294 // bug. 1295 if (Subtarget->getGeneration() > AMDGPUSubtarget::SEA_ISLANDS || 1296 SelectMUBUFConstant(Offset, Tmp1, Tmp2)) 1297 return false; 1298 } 1299 1300 if (CurDAG->isBaseWithConstantOffset(Offset)) { 1301 SDValue N0 = Offset.getOperand(0); 1302 SDValue N1 = Offset.getOperand(1); 1303 if (cast<ConstantSDNode>(N1)->getSExtValue() >= 0 && 1304 SelectMUBUFConstant(N1, SOffset, ImmOffset)) { 1305 VOffset = N0; 1306 return true; 1307 } 1308 } 1309 1310 SOffset = CurDAG->getTargetConstant(0, DL, MVT::i32); 1311 ImmOffset = CurDAG->getTargetConstant(0, DL, MVT::i16); 1312 VOffset = Offset; 1313 1314 return true; 1315 } 1316 1317 template <bool IsSigned> 1318 bool AMDGPUDAGToDAGISel::SelectFlatOffset(SDValue Addr, 1319 SDValue &VAddr, 1320 SDValue &Offset, 1321 SDValue &SLC) const { 1322 int64_t OffsetVal = 0; 1323 1324 if (Subtarget->hasFlatInstOffsets() && 1325 CurDAG->isBaseWithConstantOffset(Addr)) { 1326 SDValue N0 = Addr.getOperand(0); 1327 SDValue N1 = Addr.getOperand(1); 1328 int64_t COffsetVal = cast<ConstantSDNode>(N1)->getSExtValue(); 1329 1330 if ((IsSigned && isInt<13>(COffsetVal)) || 1331 (!IsSigned && isUInt<12>(COffsetVal))) { 1332 Addr = N0; 1333 OffsetVal = COffsetVal; 1334 } 1335 } 1336 1337 VAddr = Addr; 1338 Offset = CurDAG->getTargetConstant(OffsetVal, SDLoc(), MVT::i16); 1339 SLC = CurDAG->getTargetConstant(0, SDLoc(), MVT::i1); 1340 1341 return true; 1342 } 1343 1344 bool AMDGPUDAGToDAGISel::SelectFlatAtomic(SDValue Addr, 1345 SDValue &VAddr, 1346 SDValue &Offset, 1347 SDValue &SLC) const { 1348 return SelectFlatOffset<false>(Addr, VAddr, Offset, SLC); 1349 } 1350 1351 bool AMDGPUDAGToDAGISel::SelectFlatAtomicSigned(SDValue Addr, 1352 SDValue &VAddr, 1353 SDValue &Offset, 1354 SDValue &SLC) const { 1355 return SelectFlatOffset<true>(Addr, VAddr, Offset, SLC); 1356 } 1357 1358 bool AMDGPUDAGToDAGISel::SelectSMRDOffset(SDValue ByteOffsetNode, 1359 SDValue &Offset, bool &Imm) const { 1360 1361 // FIXME: Handle non-constant offsets. 1362 ConstantSDNode *C = dyn_cast<ConstantSDNode>(ByteOffsetNode); 1363 if (!C) 1364 return false; 1365 1366 SDLoc SL(ByteOffsetNode); 1367 AMDGPUSubtarget::Generation Gen = Subtarget->getGeneration(); 1368 int64_t ByteOffset = C->getSExtValue(); 1369 int64_t EncodedOffset = AMDGPU::getSMRDEncodedOffset(*Subtarget, ByteOffset); 1370 1371 if (AMDGPU::isLegalSMRDImmOffset(*Subtarget, ByteOffset)) { 1372 Offset = CurDAG->getTargetConstant(EncodedOffset, SL, MVT::i32); 1373 Imm = true; 1374 return true; 1375 } 1376 1377 if (!isUInt<32>(EncodedOffset) || !isUInt<32>(ByteOffset)) 1378 return false; 1379 1380 if (Gen == AMDGPUSubtarget::SEA_ISLANDS && isUInt<32>(EncodedOffset)) { 1381 // 32-bit Immediates are supported on Sea Islands. 1382 Offset = CurDAG->getTargetConstant(EncodedOffset, SL, MVT::i32); 1383 } else { 1384 SDValue C32Bit = CurDAG->getTargetConstant(ByteOffset, SL, MVT::i32); 1385 Offset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, 1386 C32Bit), 0); 1387 } 1388 Imm = false; 1389 return true; 1390 } 1391 1392 bool AMDGPUDAGToDAGISel::SelectSMRD(SDValue Addr, SDValue &SBase, 1393 SDValue &Offset, bool &Imm) const { 1394 SDLoc SL(Addr); 1395 if (CurDAG->isBaseWithConstantOffset(Addr)) { 1396 SDValue N0 = Addr.getOperand(0); 1397 SDValue N1 = Addr.getOperand(1); 1398 1399 if (SelectSMRDOffset(N1, Offset, Imm)) { 1400 SBase = N0; 1401 return true; 1402 } 1403 } 1404 SBase = Addr; 1405 Offset = CurDAG->getTargetConstant(0, SL, MVT::i32); 1406 Imm = true; 1407 return true; 1408 } 1409 1410 bool AMDGPUDAGToDAGISel::SelectSMRDImm(SDValue Addr, SDValue &SBase, 1411 SDValue &Offset) const { 1412 bool Imm; 1413 return SelectSMRD(Addr, SBase, Offset, Imm) && Imm; 1414 } 1415 1416 bool AMDGPUDAGToDAGISel::SelectSMRDImm32(SDValue Addr, SDValue &SBase, 1417 SDValue &Offset) const { 1418 1419 if (Subtarget->getGeneration() != AMDGPUSubtarget::SEA_ISLANDS) 1420 return false; 1421 1422 bool Imm; 1423 if (!SelectSMRD(Addr, SBase, Offset, Imm)) 1424 return false; 1425 1426 return !Imm && isa<ConstantSDNode>(Offset); 1427 } 1428 1429 bool AMDGPUDAGToDAGISel::SelectSMRDSgpr(SDValue Addr, SDValue &SBase, 1430 SDValue &Offset) const { 1431 bool Imm; 1432 return SelectSMRD(Addr, SBase, Offset, Imm) && !Imm && 1433 !isa<ConstantSDNode>(Offset); 1434 } 1435 1436 bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm(SDValue Addr, 1437 SDValue &Offset) const { 1438 bool Imm; 1439 return SelectSMRDOffset(Addr, Offset, Imm) && Imm; 1440 } 1441 1442 bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm32(SDValue Addr, 1443 SDValue &Offset) const { 1444 if (Subtarget->getGeneration() != AMDGPUSubtarget::SEA_ISLANDS) 1445 return false; 1446 1447 bool Imm; 1448 if (!SelectSMRDOffset(Addr, Offset, Imm)) 1449 return false; 1450 1451 return !Imm && isa<ConstantSDNode>(Offset); 1452 } 1453 1454 bool AMDGPUDAGToDAGISel::SelectSMRDBufferSgpr(SDValue Addr, 1455 SDValue &Offset) const { 1456 bool Imm; 1457 return SelectSMRDOffset(Addr, Offset, Imm) && !Imm && 1458 !isa<ConstantSDNode>(Offset); 1459 } 1460 1461 bool AMDGPUDAGToDAGISel::SelectMOVRELOffset(SDValue Index, 1462 SDValue &Base, 1463 SDValue &Offset) const { 1464 SDLoc DL(Index); 1465 1466 if (CurDAG->isBaseWithConstantOffset(Index)) { 1467 SDValue N0 = Index.getOperand(0); 1468 SDValue N1 = Index.getOperand(1); 1469 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 1470 1471 // (add n0, c0) 1472 Base = N0; 1473 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i32); 1474 return true; 1475 } 1476 1477 if (isa<ConstantSDNode>(Index)) 1478 return false; 1479 1480 Base = Index; 1481 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); 1482 return true; 1483 } 1484 1485 SDNode *AMDGPUDAGToDAGISel::getS_BFE(unsigned Opcode, const SDLoc &DL, 1486 SDValue Val, uint32_t Offset, 1487 uint32_t Width) { 1488 // Transformation function, pack the offset and width of a BFE into 1489 // the format expected by the S_BFE_I32 / S_BFE_U32. In the second 1490 // source, bits [5:0] contain the offset and bits [22:16] the width. 1491 uint32_t PackedVal = Offset | (Width << 16); 1492 SDValue PackedConst = CurDAG->getTargetConstant(PackedVal, DL, MVT::i32); 1493 1494 return CurDAG->getMachineNode(Opcode, DL, MVT::i32, Val, PackedConst); 1495 } 1496 1497 void AMDGPUDAGToDAGISel::SelectS_BFEFromShifts(SDNode *N) { 1498 // "(a << b) srl c)" ---> "BFE_U32 a, (c-b), (32-c) 1499 // "(a << b) sra c)" ---> "BFE_I32 a, (c-b), (32-c) 1500 // Predicate: 0 < b <= c < 32 1501 1502 const SDValue &Shl = N->getOperand(0); 1503 ConstantSDNode *B = dyn_cast<ConstantSDNode>(Shl->getOperand(1)); 1504 ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1)); 1505 1506 if (B && C) { 1507 uint32_t BVal = B->getZExtValue(); 1508 uint32_t CVal = C->getZExtValue(); 1509 1510 if (0 < BVal && BVal <= CVal && CVal < 32) { 1511 bool Signed = N->getOpcode() == ISD::SRA; 1512 unsigned Opcode = Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32; 1513 1514 ReplaceNode(N, getS_BFE(Opcode, SDLoc(N), Shl.getOperand(0), CVal - BVal, 1515 32 - CVal)); 1516 return; 1517 } 1518 } 1519 SelectCode(N); 1520 } 1521 1522 void AMDGPUDAGToDAGISel::SelectS_BFE(SDNode *N) { 1523 switch (N->getOpcode()) { 1524 case ISD::AND: 1525 if (N->getOperand(0).getOpcode() == ISD::SRL) { 1526 // "(a srl b) & mask" ---> "BFE_U32 a, b, popcount(mask)" 1527 // Predicate: isMask(mask) 1528 const SDValue &Srl = N->getOperand(0); 1529 ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(Srl.getOperand(1)); 1530 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(N->getOperand(1)); 1531 1532 if (Shift && Mask) { 1533 uint32_t ShiftVal = Shift->getZExtValue(); 1534 uint32_t MaskVal = Mask->getZExtValue(); 1535 1536 if (isMask_32(MaskVal)) { 1537 uint32_t WidthVal = countPopulation(MaskVal); 1538 1539 ReplaceNode(N, getS_BFE(AMDGPU::S_BFE_U32, SDLoc(N), 1540 Srl.getOperand(0), ShiftVal, WidthVal)); 1541 return; 1542 } 1543 } 1544 } 1545 break; 1546 case ISD::SRL: 1547 if (N->getOperand(0).getOpcode() == ISD::AND) { 1548 // "(a & mask) srl b)" ---> "BFE_U32 a, b, popcount(mask >> b)" 1549 // Predicate: isMask(mask >> b) 1550 const SDValue &And = N->getOperand(0); 1551 ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(N->getOperand(1)); 1552 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(And->getOperand(1)); 1553 1554 if (Shift && Mask) { 1555 uint32_t ShiftVal = Shift->getZExtValue(); 1556 uint32_t MaskVal = Mask->getZExtValue() >> ShiftVal; 1557 1558 if (isMask_32(MaskVal)) { 1559 uint32_t WidthVal = countPopulation(MaskVal); 1560 1561 ReplaceNode(N, getS_BFE(AMDGPU::S_BFE_U32, SDLoc(N), 1562 And.getOperand(0), ShiftVal, WidthVal)); 1563 return; 1564 } 1565 } 1566 } else if (N->getOperand(0).getOpcode() == ISD::SHL) { 1567 SelectS_BFEFromShifts(N); 1568 return; 1569 } 1570 break; 1571 case ISD::SRA: 1572 if (N->getOperand(0).getOpcode() == ISD::SHL) { 1573 SelectS_BFEFromShifts(N); 1574 return; 1575 } 1576 break; 1577 1578 case ISD::SIGN_EXTEND_INREG: { 1579 // sext_inreg (srl x, 16), i8 -> bfe_i32 x, 16, 8 1580 SDValue Src = N->getOperand(0); 1581 if (Src.getOpcode() != ISD::SRL) 1582 break; 1583 1584 const ConstantSDNode *Amt = dyn_cast<ConstantSDNode>(Src.getOperand(1)); 1585 if (!Amt) 1586 break; 1587 1588 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits(); 1589 ReplaceNode(N, getS_BFE(AMDGPU::S_BFE_I32, SDLoc(N), Src.getOperand(0), 1590 Amt->getZExtValue(), Width)); 1591 return; 1592 } 1593 } 1594 1595 SelectCode(N); 1596 } 1597 1598 bool AMDGPUDAGToDAGISel::isCBranchSCC(const SDNode *N) const { 1599 assert(N->getOpcode() == ISD::BRCOND); 1600 if (!N->hasOneUse()) 1601 return false; 1602 1603 SDValue Cond = N->getOperand(1); 1604 if (Cond.getOpcode() == ISD::CopyToReg) 1605 Cond = Cond.getOperand(2); 1606 1607 if (Cond.getOpcode() != ISD::SETCC || !Cond.hasOneUse()) 1608 return false; 1609 1610 MVT VT = Cond.getOperand(0).getSimpleValueType(); 1611 if (VT == MVT::i32) 1612 return true; 1613 1614 if (VT == MVT::i64) { 1615 auto ST = static_cast<const SISubtarget *>(Subtarget); 1616 1617 ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get(); 1618 return (CC == ISD::SETEQ || CC == ISD::SETNE) && ST->hasScalarCompareEq64(); 1619 } 1620 1621 return false; 1622 } 1623 1624 void AMDGPUDAGToDAGISel::SelectBRCOND(SDNode *N) { 1625 SDValue Cond = N->getOperand(1); 1626 1627 if (Cond.isUndef()) { 1628 CurDAG->SelectNodeTo(N, AMDGPU::SI_BR_UNDEF, MVT::Other, 1629 N->getOperand(2), N->getOperand(0)); 1630 return; 1631 } 1632 1633 if (isCBranchSCC(N)) { 1634 // This brcond will use S_CBRANCH_SCC*, so let tablegen handle it. 1635 SelectCode(N); 1636 return; 1637 } 1638 1639 SDLoc SL(N); 1640 1641 SDValue VCC = CurDAG->getCopyToReg(N->getOperand(0), SL, AMDGPU::VCC, Cond); 1642 CurDAG->SelectNodeTo(N, AMDGPU::S_CBRANCH_VCCNZ, MVT::Other, 1643 N->getOperand(2), // Basic Block 1644 VCC.getValue(0)); 1645 } 1646 1647 // This is here because there isn't a way to use the generated sub0_sub1 as the 1648 // subreg index to EXTRACT_SUBREG in tablegen. 1649 void AMDGPUDAGToDAGISel::SelectATOMIC_CMP_SWAP(SDNode *N) { 1650 MemSDNode *Mem = cast<MemSDNode>(N); 1651 unsigned AS = Mem->getAddressSpace(); 1652 if (AS == AMDGPUASI.FLAT_ADDRESS) { 1653 SelectCode(N); 1654 return; 1655 } 1656 1657 MVT VT = N->getSimpleValueType(0); 1658 bool Is32 = (VT == MVT::i32); 1659 SDLoc SL(N); 1660 1661 MachineSDNode *CmpSwap = nullptr; 1662 if (Subtarget->hasAddr64()) { 1663 SDValue SRsrc, VAddr, SOffset, Offset, GLC, SLC; 1664 1665 if (SelectMUBUFAddr64(Mem->getBasePtr(), SRsrc, VAddr, SOffset, Offset, SLC)) { 1666 unsigned Opcode = Is32 ? AMDGPU::BUFFER_ATOMIC_CMPSWAP_ADDR64_RTN : 1667 AMDGPU::BUFFER_ATOMIC_CMPSWAP_X2_ADDR64_RTN; 1668 SDValue CmpVal = Mem->getOperand(2); 1669 1670 // XXX - Do we care about glue operands? 1671 1672 SDValue Ops[] = { 1673 CmpVal, VAddr, SRsrc, SOffset, Offset, SLC, Mem->getChain() 1674 }; 1675 1676 CmpSwap = CurDAG->getMachineNode(Opcode, SL, Mem->getVTList(), Ops); 1677 } 1678 } 1679 1680 if (!CmpSwap) { 1681 SDValue SRsrc, SOffset, Offset, SLC; 1682 if (SelectMUBUFOffset(Mem->getBasePtr(), SRsrc, SOffset, Offset, SLC)) { 1683 unsigned Opcode = Is32 ? AMDGPU::BUFFER_ATOMIC_CMPSWAP_OFFSET_RTN : 1684 AMDGPU::BUFFER_ATOMIC_CMPSWAP_X2_OFFSET_RTN; 1685 1686 SDValue CmpVal = Mem->getOperand(2); 1687 SDValue Ops[] = { 1688 CmpVal, SRsrc, SOffset, Offset, SLC, Mem->getChain() 1689 }; 1690 1691 CmpSwap = CurDAG->getMachineNode(Opcode, SL, Mem->getVTList(), Ops); 1692 } 1693 } 1694 1695 if (!CmpSwap) { 1696 SelectCode(N); 1697 return; 1698 } 1699 1700 MachineSDNode::mmo_iterator MMOs = MF->allocateMemRefsArray(1); 1701 *MMOs = Mem->getMemOperand(); 1702 CmpSwap->setMemRefs(MMOs, MMOs + 1); 1703 1704 unsigned SubReg = Is32 ? AMDGPU::sub0 : AMDGPU::sub0_sub1; 1705 SDValue Extract 1706 = CurDAG->getTargetExtractSubreg(SubReg, SL, VT, SDValue(CmpSwap, 0)); 1707 1708 ReplaceUses(SDValue(N, 0), Extract); 1709 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 1)); 1710 CurDAG->RemoveDeadNode(N); 1711 } 1712 1713 bool AMDGPUDAGToDAGISel::SelectVOP3Mods(SDValue In, SDValue &Src, 1714 SDValue &SrcMods) const { 1715 unsigned Mods = 0; 1716 Src = In; 1717 1718 if (Src.getOpcode() == ISD::FNEG) { 1719 Mods |= SISrcMods::NEG; 1720 Src = Src.getOperand(0); 1721 } 1722 1723 if (Src.getOpcode() == ISD::FABS) { 1724 Mods |= SISrcMods::ABS; 1725 Src = Src.getOperand(0); 1726 } 1727 1728 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32); 1729 return true; 1730 } 1731 1732 bool AMDGPUDAGToDAGISel::SelectVOP3Mods_NNaN(SDValue In, SDValue &Src, 1733 SDValue &SrcMods) const { 1734 SelectVOP3Mods(In, Src, SrcMods); 1735 return isNoNanSrc(Src); 1736 } 1737 1738 bool AMDGPUDAGToDAGISel::SelectVOP3NoMods(SDValue In, SDValue &Src) const { 1739 if (In.getOpcode() == ISD::FABS || In.getOpcode() == ISD::FNEG) 1740 return false; 1741 1742 Src = In; 1743 return true; 1744 } 1745 1746 bool AMDGPUDAGToDAGISel::SelectVOP3Mods0(SDValue In, SDValue &Src, 1747 SDValue &SrcMods, SDValue &Clamp, 1748 SDValue &Omod) const { 1749 SDLoc DL(In); 1750 Clamp = CurDAG->getTargetConstant(0, DL, MVT::i1); 1751 Omod = CurDAG->getTargetConstant(0, DL, MVT::i1); 1752 1753 return SelectVOP3Mods(In, Src, SrcMods); 1754 } 1755 1756 bool AMDGPUDAGToDAGISel::SelectVOP3Mods0Clamp0OMod(SDValue In, SDValue &Src, 1757 SDValue &SrcMods, 1758 SDValue &Clamp, 1759 SDValue &Omod) const { 1760 Clamp = Omod = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32); 1761 return SelectVOP3Mods(In, Src, SrcMods); 1762 } 1763 1764 bool AMDGPUDAGToDAGISel::SelectVOP3OMods(SDValue In, SDValue &Src, 1765 SDValue &Clamp, SDValue &Omod) const { 1766 Src = In; 1767 1768 SDLoc DL(In); 1769 Clamp = CurDAG->getTargetConstant(0, DL, MVT::i1); 1770 Omod = CurDAG->getTargetConstant(0, DL, MVT::i1); 1771 1772 return true; 1773 } 1774 1775 static SDValue stripBitcast(SDValue Val) { 1776 return Val.getOpcode() == ISD::BITCAST ? Val.getOperand(0) : Val; 1777 } 1778 1779 // Figure out if this is really an extract of the high 16-bits of a dword. 1780 static bool isExtractHiElt(SDValue In, SDValue &Out) { 1781 In = stripBitcast(In); 1782 if (In.getOpcode() != ISD::TRUNCATE) 1783 return false; 1784 1785 SDValue Srl = In.getOperand(0); 1786 if (Srl.getOpcode() == ISD::SRL) { 1787 if (ConstantSDNode *ShiftAmt = dyn_cast<ConstantSDNode>(Srl.getOperand(1))) { 1788 if (ShiftAmt->getZExtValue() == 16) { 1789 Out = stripBitcast(Srl.getOperand(0)); 1790 return true; 1791 } 1792 } 1793 } 1794 1795 return false; 1796 } 1797 1798 // Look through operations that obscure just looking at the low 16-bits of the 1799 // same register. 1800 static SDValue stripExtractLoElt(SDValue In) { 1801 if (In.getOpcode() == ISD::TRUNCATE) { 1802 SDValue Src = In.getOperand(0); 1803 if (Src.getValueType().getSizeInBits() == 32) 1804 return stripBitcast(Src); 1805 } 1806 1807 return In; 1808 } 1809 1810 bool AMDGPUDAGToDAGISel::SelectVOP3PMods(SDValue In, SDValue &Src, 1811 SDValue &SrcMods) const { 1812 unsigned Mods = 0; 1813 Src = In; 1814 1815 if (Src.getOpcode() == ISD::FNEG) { 1816 Mods ^= (SISrcMods::NEG | SISrcMods::NEG_HI); 1817 Src = Src.getOperand(0); 1818 } 1819 1820 if (Src.getOpcode() == ISD::BUILD_VECTOR) { 1821 unsigned VecMods = Mods; 1822 1823 SDValue Lo = stripBitcast(Src.getOperand(0)); 1824 SDValue Hi = stripBitcast(Src.getOperand(1)); 1825 1826 if (Lo.getOpcode() == ISD::FNEG) { 1827 Lo = stripBitcast(Lo.getOperand(0)); 1828 Mods ^= SISrcMods::NEG; 1829 } 1830 1831 if (Hi.getOpcode() == ISD::FNEG) { 1832 Hi = stripBitcast(Hi.getOperand(0)); 1833 Mods ^= SISrcMods::NEG_HI; 1834 } 1835 1836 if (isExtractHiElt(Lo, Lo)) 1837 Mods |= SISrcMods::OP_SEL_0; 1838 1839 if (isExtractHiElt(Hi, Hi)) 1840 Mods |= SISrcMods::OP_SEL_1; 1841 1842 Lo = stripExtractLoElt(Lo); 1843 Hi = stripExtractLoElt(Hi); 1844 1845 if (Lo == Hi && !isInlineImmediate(Lo.getNode())) { 1846 // Really a scalar input. Just select from the low half of the register to 1847 // avoid packing. 1848 1849 Src = Lo; 1850 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32); 1851 return true; 1852 } 1853 1854 Mods = VecMods; 1855 } 1856 1857 // Packed instructions do not have abs modifiers. 1858 Mods |= SISrcMods::OP_SEL_1; 1859 1860 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32); 1861 return true; 1862 } 1863 1864 bool AMDGPUDAGToDAGISel::SelectVOP3PMods0(SDValue In, SDValue &Src, 1865 SDValue &SrcMods, 1866 SDValue &Clamp) const { 1867 SDLoc SL(In); 1868 1869 // FIXME: Handle clamp and op_sel 1870 Clamp = CurDAG->getTargetConstant(0, SL, MVT::i32); 1871 1872 return SelectVOP3PMods(In, Src, SrcMods); 1873 } 1874 1875 bool AMDGPUDAGToDAGISel::SelectVOP3OpSel(SDValue In, SDValue &Src, 1876 SDValue &SrcMods) const { 1877 Src = In; 1878 // FIXME: Handle op_sel 1879 SrcMods = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32); 1880 return true; 1881 } 1882 1883 bool AMDGPUDAGToDAGISel::SelectVOP3OpSel0(SDValue In, SDValue &Src, 1884 SDValue &SrcMods, 1885 SDValue &Clamp) const { 1886 SDLoc SL(In); 1887 1888 // FIXME: Handle clamp 1889 Clamp = CurDAG->getTargetConstant(0, SL, MVT::i32); 1890 1891 return SelectVOP3OpSel(In, Src, SrcMods); 1892 } 1893 1894 bool AMDGPUDAGToDAGISel::SelectVOP3OpSelMods(SDValue In, SDValue &Src, 1895 SDValue &SrcMods) const { 1896 // FIXME: Handle op_sel 1897 return SelectVOP3Mods(In, Src, SrcMods); 1898 } 1899 1900 bool AMDGPUDAGToDAGISel::SelectVOP3OpSelMods0(SDValue In, SDValue &Src, 1901 SDValue &SrcMods, 1902 SDValue &Clamp) const { 1903 SDLoc SL(In); 1904 1905 // FIXME: Handle clamp 1906 Clamp = CurDAG->getTargetConstant(0, SL, MVT::i32); 1907 1908 return SelectVOP3OpSelMods(In, Src, SrcMods); 1909 } 1910 1911 void AMDGPUDAGToDAGISel::PostprocessISelDAG() { 1912 const AMDGPUTargetLowering& Lowering = 1913 *static_cast<const AMDGPUTargetLowering*>(getTargetLowering()); 1914 bool IsModified = false; 1915 do { 1916 IsModified = false; 1917 // Go over all selected nodes and try to fold them a bit more 1918 for (SDNode &Node : CurDAG->allnodes()) { 1919 MachineSDNode *MachineNode = dyn_cast<MachineSDNode>(&Node); 1920 if (!MachineNode) 1921 continue; 1922 1923 SDNode *ResNode = Lowering.PostISelFolding(MachineNode, *CurDAG); 1924 if (ResNode != &Node) { 1925 ReplaceUses(&Node, ResNode); 1926 IsModified = true; 1927 } 1928 } 1929 CurDAG->RemoveDeadNodes(); 1930 } while (IsModified); 1931 } 1932 1933 void R600DAGToDAGISel::Select(SDNode *N) { 1934 unsigned int Opc = N->getOpcode(); 1935 if (N->isMachineOpcode()) { 1936 N->setNodeId(-1); 1937 return; // Already selected. 1938 } 1939 1940 switch (Opc) { 1941 default: break; 1942 case AMDGPUISD::BUILD_VERTICAL_VECTOR: 1943 case ISD::SCALAR_TO_VECTOR: 1944 case ISD::BUILD_VECTOR: { 1945 EVT VT = N->getValueType(0); 1946 unsigned NumVectorElts = VT.getVectorNumElements(); 1947 unsigned RegClassID; 1948 // BUILD_VECTOR was lowered into an IMPLICIT_DEF + 4 INSERT_SUBREG 1949 // that adds a 128 bits reg copy when going through TwoAddressInstructions 1950 // pass. We want to avoid 128 bits copies as much as possible because they 1951 // can't be bundled by our scheduler. 1952 switch(NumVectorElts) { 1953 case 2: RegClassID = AMDGPU::R600_Reg64RegClassID; break; 1954 case 4: 1955 if (Opc == AMDGPUISD::BUILD_VERTICAL_VECTOR) 1956 RegClassID = AMDGPU::R600_Reg128VerticalRegClassID; 1957 else 1958 RegClassID = AMDGPU::R600_Reg128RegClassID; 1959 break; 1960 default: llvm_unreachable("Do not know how to lower this BUILD_VECTOR"); 1961 } 1962 SelectBuildVector(N, RegClassID); 1963 return; 1964 } 1965 } 1966 1967 SelectCode(N); 1968 } 1969 1970 bool R600DAGToDAGISel::SelectADDRIndirect(SDValue Addr, SDValue &Base, 1971 SDValue &Offset) { 1972 ConstantSDNode *C; 1973 SDLoc DL(Addr); 1974 1975 if ((C = dyn_cast<ConstantSDNode>(Addr))) { 1976 Base = CurDAG->getRegister(AMDGPU::INDIRECT_BASE_ADDR, MVT::i32); 1977 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 1978 } else if ((Addr.getOpcode() == AMDGPUISD::DWORDADDR) && 1979 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(0)))) { 1980 Base = CurDAG->getRegister(AMDGPU::INDIRECT_BASE_ADDR, MVT::i32); 1981 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 1982 } else if ((Addr.getOpcode() == ISD::ADD || Addr.getOpcode() == ISD::OR) && 1983 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) { 1984 Base = Addr.getOperand(0); 1985 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 1986 } else { 1987 Base = Addr; 1988 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); 1989 } 1990 1991 return true; 1992 } 1993 1994 bool R600DAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base, 1995 SDValue &Offset) { 1996 ConstantSDNode *IMMOffset; 1997 1998 if (Addr.getOpcode() == ISD::ADD 1999 && (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 2000 && isInt<16>(IMMOffset->getZExtValue())) { 2001 2002 Base = Addr.getOperand(0); 2003 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr), 2004 MVT::i32); 2005 return true; 2006 // If the pointer address is constant, we can move it to the offset field. 2007 } else if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr)) 2008 && isInt<16>(IMMOffset->getZExtValue())) { 2009 Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), 2010 SDLoc(CurDAG->getEntryNode()), 2011 AMDGPU::ZERO, MVT::i32); 2012 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr), 2013 MVT::i32); 2014 return true; 2015 } 2016 2017 // Default case, no offset 2018 Base = Addr; 2019 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 2020 return true; 2021 } 2022