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 "AMDGPUInstrInfo.h" 16 #include "AMDGPUIntrinsicInfo.h" 17 #include "AMDGPUISelLowering.h" // For AMDGPUISD 18 #include "AMDGPUSubtarget.h" 19 #include "SIISelLowering.h" 20 #include "SIMachineFunctionInfo.h" 21 #include "llvm/Analysis/ValueTracking.h" 22 #include "llvm/CodeGen/FunctionLoweringInfo.h" 23 #include "llvm/CodeGen/MachineFrameInfo.h" 24 #include "llvm/CodeGen/PseudoSourceValue.h" 25 #include "llvm/CodeGen/SelectionDAG.h" 26 #include "llvm/CodeGen/SelectionDAGISel.h" 27 #include "llvm/IR/DiagnosticInfo.h" 28 29 using namespace llvm; 30 31 namespace llvm { 32 class R600InstrInfo; 33 } 34 35 //===----------------------------------------------------------------------===// 36 // Instruction Selector Implementation 37 //===----------------------------------------------------------------------===// 38 39 namespace { 40 41 static bool isCBranchSCC(const SDNode *N) { 42 assert(N->getOpcode() == ISD::BRCOND); 43 if (!N->hasOneUse()) 44 return false; 45 46 SDValue Cond = N->getOperand(1); 47 if (Cond.getOpcode() == ISD::CopyToReg) 48 Cond = Cond.getOperand(2); 49 return Cond.getOpcode() == ISD::SETCC && 50 Cond.getOperand(0).getValueType() == MVT::i32 && Cond.hasOneUse(); 51 } 52 53 /// AMDGPU specific code to select AMDGPU machine instructions for 54 /// SelectionDAG operations. 55 class AMDGPUDAGToDAGISel : public SelectionDAGISel { 56 // Subtarget - Keep a pointer to the AMDGPU Subtarget around so that we can 57 // make the right decision when generating code for different targets. 58 const AMDGPUSubtarget *Subtarget; 59 60 public: 61 AMDGPUDAGToDAGISel(TargetMachine &TM); 62 virtual ~AMDGPUDAGToDAGISel(); 63 bool runOnMachineFunction(MachineFunction &MF) override; 64 void Select(SDNode *N) override; 65 const char *getPassName() const override; 66 void PreprocessISelDAG() override; 67 void PostprocessISelDAG() override; 68 69 private: 70 bool isInlineImmediate(SDNode *N) const; 71 bool FoldOperand(SDValue &Src, SDValue &Sel, SDValue &Neg, SDValue &Abs, 72 const R600InstrInfo *TII); 73 bool FoldOperands(unsigned, const R600InstrInfo *, std::vector<SDValue> &); 74 bool FoldDotOperands(unsigned, const R600InstrInfo *, std::vector<SDValue> &); 75 76 bool isConstantLoad(const MemSDNode *N, int cbID) const; 77 bool isUniformBr(const SDNode *N) const; 78 79 SDNode *glueCopyToM0(SDNode *N) const; 80 81 const TargetRegisterClass *getOperandRegClass(SDNode *N, unsigned OpNo) const; 82 bool SelectGlobalValueConstantOffset(SDValue Addr, SDValue& IntPtr); 83 bool SelectGlobalValueVariableOffset(SDValue Addr, SDValue &BaseReg, 84 SDValue& Offset); 85 bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, SDValue &Offset); 86 bool SelectADDRIndirect(SDValue Addr, SDValue &Base, SDValue &Offset); 87 bool isDSOffsetLegal(const SDValue &Base, unsigned Offset, 88 unsigned OffsetBits) const; 89 bool SelectDS1Addr1Offset(SDValue Ptr, SDValue &Base, SDValue &Offset) const; 90 bool SelectDS64Bit4ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0, 91 SDValue &Offset1) const; 92 bool SelectMUBUF(SDValue Addr, SDValue &SRsrc, SDValue &VAddr, 93 SDValue &SOffset, SDValue &Offset, SDValue &Offen, 94 SDValue &Idxen, SDValue &Addr64, SDValue &GLC, SDValue &SLC, 95 SDValue &TFE) const; 96 bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, SDValue &VAddr, 97 SDValue &SOffset, SDValue &Offset, SDValue &GLC, 98 SDValue &SLC, SDValue &TFE) const; 99 bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, 100 SDValue &VAddr, SDValue &SOffset, SDValue &Offset, 101 SDValue &SLC) const; 102 bool SelectMUBUFScratch(SDValue Addr, SDValue &RSrc, SDValue &VAddr, 103 SDValue &SOffset, SDValue &ImmOffset) const; 104 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &SOffset, 105 SDValue &Offset, SDValue &GLC, SDValue &SLC, 106 SDValue &TFE) const; 107 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset, 108 SDValue &Offset, SDValue &SLC) const; 109 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset, 110 SDValue &Offset) const; 111 bool SelectMUBUFConstant(SDValue Constant, 112 SDValue &SOffset, 113 SDValue &ImmOffset) const; 114 bool SelectMUBUFIntrinsicOffset(SDValue Offset, SDValue &SOffset, 115 SDValue &ImmOffset) const; 116 bool SelectMUBUFIntrinsicVOffset(SDValue Offset, SDValue &SOffset, 117 SDValue &ImmOffset, SDValue &VOffset) const; 118 119 bool SelectFlat(SDValue Addr, SDValue &VAddr, 120 SDValue &SLC, SDValue &TFE) const; 121 122 bool SelectSMRDOffset(SDValue ByteOffsetNode, SDValue &Offset, 123 bool &Imm) const; 124 bool SelectSMRD(SDValue Addr, SDValue &SBase, SDValue &Offset, 125 bool &Imm) const; 126 bool SelectSMRDImm(SDValue Addr, SDValue &SBase, SDValue &Offset) const; 127 bool SelectSMRDImm32(SDValue Addr, SDValue &SBase, SDValue &Offset) const; 128 bool SelectSMRDSgpr(SDValue Addr, SDValue &SBase, SDValue &Offset) const; 129 bool SelectSMRDBufferImm(SDValue Addr, SDValue &Offset) const; 130 bool SelectSMRDBufferImm32(SDValue Addr, SDValue &Offset) const; 131 bool SelectSMRDBufferSgpr(SDValue Addr, SDValue &Offset) const; 132 bool SelectVOP3Mods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 133 bool SelectVOP3NoMods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 134 bool SelectVOP3Mods0(SDValue In, SDValue &Src, SDValue &SrcMods, 135 SDValue &Clamp, SDValue &Omod) const; 136 bool SelectVOP3NoMods0(SDValue In, SDValue &Src, SDValue &SrcMods, 137 SDValue &Clamp, SDValue &Omod) const; 138 139 bool SelectVOP3Mods0Clamp(SDValue In, SDValue &Src, SDValue &SrcMods, 140 SDValue &Omod) const; 141 bool SelectVOP3Mods0Clamp0OMod(SDValue In, SDValue &Src, SDValue &SrcMods, 142 SDValue &Clamp, 143 SDValue &Omod) const; 144 145 void SelectADD_SUB_I64(SDNode *N); 146 void SelectDIV_SCALE(SDNode *N); 147 148 SDNode *getS_BFE(unsigned Opcode, const SDLoc &DL, SDValue Val, 149 uint32_t Offset, uint32_t Width); 150 void SelectS_BFEFromShifts(SDNode *N); 151 void SelectS_BFE(SDNode *N); 152 void SelectBRCOND(SDNode *N); 153 void SelectATOMIC_CMP_SWAP(SDNode *N); 154 155 // Include the pieces autogenerated from the target description. 156 #include "AMDGPUGenDAGISel.inc" 157 }; 158 } // end anonymous namespace 159 160 /// \brief This pass converts a legalized DAG into a AMDGPU-specific 161 // DAG, ready for instruction scheduling. 162 FunctionPass *llvm::createAMDGPUISelDag(TargetMachine &TM) { 163 return new AMDGPUDAGToDAGISel(TM); 164 } 165 166 AMDGPUDAGToDAGISel::AMDGPUDAGToDAGISel(TargetMachine &TM) 167 : SelectionDAGISel(TM) {} 168 169 bool AMDGPUDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 170 Subtarget = &MF.getSubtarget<AMDGPUSubtarget>(); 171 return SelectionDAGISel::runOnMachineFunction(MF); 172 } 173 174 AMDGPUDAGToDAGISel::~AMDGPUDAGToDAGISel() { 175 } 176 177 bool AMDGPUDAGToDAGISel::isInlineImmediate(SDNode *N) const { 178 const SITargetLowering *TL 179 = static_cast<const SITargetLowering *>(getTargetLowering()); 180 return TL->analyzeImmediate(N) == 0; 181 } 182 183 /// \brief Determine the register class for \p OpNo 184 /// \returns The register class of the virtual register that will be used for 185 /// the given operand number \OpNo or NULL if the register class cannot be 186 /// determined. 187 const TargetRegisterClass *AMDGPUDAGToDAGISel::getOperandRegClass(SDNode *N, 188 unsigned OpNo) const { 189 if (!N->isMachineOpcode()) 190 return nullptr; 191 192 switch (N->getMachineOpcode()) { 193 default: { 194 const MCInstrDesc &Desc = 195 Subtarget->getInstrInfo()->get(N->getMachineOpcode()); 196 unsigned OpIdx = Desc.getNumDefs() + OpNo; 197 if (OpIdx >= Desc.getNumOperands()) 198 return nullptr; 199 int RegClass = Desc.OpInfo[OpIdx].RegClass; 200 if (RegClass == -1) 201 return nullptr; 202 203 return Subtarget->getRegisterInfo()->getRegClass(RegClass); 204 } 205 case AMDGPU::REG_SEQUENCE: { 206 unsigned RCID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); 207 const TargetRegisterClass *SuperRC = 208 Subtarget->getRegisterInfo()->getRegClass(RCID); 209 210 SDValue SubRegOp = N->getOperand(OpNo + 1); 211 unsigned SubRegIdx = cast<ConstantSDNode>(SubRegOp)->getZExtValue(); 212 return Subtarget->getRegisterInfo()->getSubClassWithSubReg(SuperRC, 213 SubRegIdx); 214 } 215 } 216 } 217 218 SDNode *AMDGPUDAGToDAGISel::glueCopyToM0(SDNode *N) const { 219 if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS || 220 cast<MemSDNode>(N)->getAddressSpace() != AMDGPUAS::LOCAL_ADDRESS) 221 return N; 222 223 const SITargetLowering& Lowering = 224 *static_cast<const SITargetLowering*>(getTargetLowering()); 225 226 // Write max value to m0 before each load operation 227 228 SDValue M0 = Lowering.copyToM0(*CurDAG, CurDAG->getEntryNode(), SDLoc(N), 229 CurDAG->getTargetConstant(-1, SDLoc(N), MVT::i32)); 230 231 SDValue Glue = M0.getValue(1); 232 233 SmallVector <SDValue, 8> Ops; 234 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { 235 Ops.push_back(N->getOperand(i)); 236 } 237 Ops.push_back(Glue); 238 CurDAG->MorphNodeTo(N, N->getOpcode(), N->getVTList(), Ops); 239 240 return N; 241 } 242 243 static unsigned selectSGPRVectorRegClassID(unsigned NumVectorElts) { 244 switch (NumVectorElts) { 245 case 1: 246 return AMDGPU::SReg_32RegClassID; 247 case 2: 248 return AMDGPU::SReg_64RegClassID; 249 case 4: 250 return AMDGPU::SReg_128RegClassID; 251 case 8: 252 return AMDGPU::SReg_256RegClassID; 253 case 16: 254 return AMDGPU::SReg_512RegClassID; 255 } 256 257 llvm_unreachable("invalid vector size"); 258 } 259 260 void AMDGPUDAGToDAGISel::Select(SDNode *N) { 261 unsigned int Opc = N->getOpcode(); 262 if (N->isMachineOpcode()) { 263 N->setNodeId(-1); 264 return; // Already selected. 265 } 266 267 if (isa<AtomicSDNode>(N) || 268 (Opc == AMDGPUISD::ATOMIC_INC || Opc == AMDGPUISD::ATOMIC_DEC)) 269 N = glueCopyToM0(N); 270 271 switch (Opc) { 272 default: break; 273 // We are selecting i64 ADD here instead of custom lower it during 274 // DAG legalization, so we can fold some i64 ADDs used for address 275 // calculation into the LOAD and STORE instructions. 276 case ISD::ADD: 277 case ISD::SUB: { 278 if (N->getValueType(0) != MVT::i64 || 279 Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS) 280 break; 281 282 SelectADD_SUB_I64(N); 283 return; 284 } 285 case ISD::SCALAR_TO_VECTOR: 286 case AMDGPUISD::BUILD_VERTICAL_VECTOR: 287 case ISD::BUILD_VECTOR: { 288 unsigned RegClassID; 289 const AMDGPURegisterInfo *TRI = Subtarget->getRegisterInfo(); 290 EVT VT = N->getValueType(0); 291 unsigned NumVectorElts = VT.getVectorNumElements(); 292 EVT EltVT = VT.getVectorElementType(); 293 assert(EltVT.bitsEq(MVT::i32)); 294 if (Subtarget->getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) { 295 RegClassID = selectSGPRVectorRegClassID(NumVectorElts); 296 } else { 297 // BUILD_VECTOR was lowered into an IMPLICIT_DEF + 4 INSERT_SUBREG 298 // that adds a 128 bits reg copy when going through TwoAddressInstructions 299 // pass. We want to avoid 128 bits copies as much as possible because they 300 // can't be bundled by our scheduler. 301 switch(NumVectorElts) { 302 case 2: RegClassID = AMDGPU::R600_Reg64RegClassID; break; 303 case 4: 304 if (Opc == AMDGPUISD::BUILD_VERTICAL_VECTOR) 305 RegClassID = AMDGPU::R600_Reg128VerticalRegClassID; 306 else 307 RegClassID = AMDGPU::R600_Reg128RegClassID; 308 break; 309 default: llvm_unreachable("Do not know how to lower this BUILD_VECTOR"); 310 } 311 } 312 313 SDLoc DL(N); 314 SDValue RegClass = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32); 315 316 if (NumVectorElts == 1) { 317 CurDAG->SelectNodeTo(N, AMDGPU::COPY_TO_REGCLASS, EltVT, N->getOperand(0), 318 RegClass); 319 return; 320 } 321 322 assert(NumVectorElts <= 16 && "Vectors with more than 16 elements not " 323 "supported yet"); 324 // 16 = Max Num Vector Elements 325 // 2 = 2 REG_SEQUENCE operands per element (value, subreg index) 326 // 1 = Vector Register Class 327 SmallVector<SDValue, 16 * 2 + 1> RegSeqArgs(NumVectorElts * 2 + 1); 328 329 RegSeqArgs[0] = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32); 330 bool IsRegSeq = true; 331 unsigned NOps = N->getNumOperands(); 332 for (unsigned i = 0; i < NOps; i++) { 333 // XXX: Why is this here? 334 if (isa<RegisterSDNode>(N->getOperand(i))) { 335 IsRegSeq = false; 336 break; 337 } 338 RegSeqArgs[1 + (2 * i)] = N->getOperand(i); 339 RegSeqArgs[1 + (2 * i) + 1] = 340 CurDAG->getTargetConstant(TRI->getSubRegFromChannel(i), DL, 341 MVT::i32); 342 } 343 344 if (NOps != NumVectorElts) { 345 // Fill in the missing undef elements if this was a scalar_to_vector. 346 assert(Opc == ISD::SCALAR_TO_VECTOR && NOps < NumVectorElts); 347 348 MachineSDNode *ImpDef = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, 349 DL, EltVT); 350 for (unsigned i = NOps; i < NumVectorElts; ++i) { 351 RegSeqArgs[1 + (2 * i)] = SDValue(ImpDef, 0); 352 RegSeqArgs[1 + (2 * i) + 1] = 353 CurDAG->getTargetConstant(TRI->getSubRegFromChannel(i), DL, MVT::i32); 354 } 355 } 356 357 if (!IsRegSeq) 358 break; 359 CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, N->getVTList(), RegSeqArgs); 360 return; 361 } 362 case ISD::BUILD_PAIR: { 363 SDValue RC, SubReg0, SubReg1; 364 if (Subtarget->getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) { 365 break; 366 } 367 SDLoc DL(N); 368 if (N->getValueType(0) == MVT::i128) { 369 RC = CurDAG->getTargetConstant(AMDGPU::SReg_128RegClassID, DL, MVT::i32); 370 SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32); 371 SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32); 372 } else if (N->getValueType(0) == MVT::i64) { 373 RC = CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32); 374 SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32); 375 SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32); 376 } else { 377 llvm_unreachable("Unhandled value type for BUILD_PAIR"); 378 } 379 const SDValue Ops[] = { RC, N->getOperand(0), SubReg0, 380 N->getOperand(1), SubReg1 }; 381 ReplaceNode(N, CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, 382 N->getValueType(0), Ops)); 383 return; 384 } 385 386 case ISD::Constant: 387 case ISD::ConstantFP: { 388 if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS || 389 N->getValueType(0).getSizeInBits() != 64 || isInlineImmediate(N)) 390 break; 391 392 uint64_t Imm; 393 if (ConstantFPSDNode *FP = dyn_cast<ConstantFPSDNode>(N)) 394 Imm = FP->getValueAPF().bitcastToAPInt().getZExtValue(); 395 else { 396 ConstantSDNode *C = cast<ConstantSDNode>(N); 397 Imm = C->getZExtValue(); 398 } 399 400 SDLoc DL(N); 401 SDNode *Lo = CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, 402 CurDAG->getConstant(Imm & 0xFFFFFFFF, DL, 403 MVT::i32)); 404 SDNode *Hi = CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, 405 CurDAG->getConstant(Imm >> 32, DL, MVT::i32)); 406 const SDValue Ops[] = { 407 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32), 408 SDValue(Lo, 0), CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32), 409 SDValue(Hi, 0), CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32) 410 }; 411 412 ReplaceNode(N, CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, 413 N->getValueType(0), Ops)); 414 return; 415 } 416 case ISD::LOAD: 417 case ISD::STORE: { 418 N = glueCopyToM0(N); 419 break; 420 } 421 422 case AMDGPUISD::BFE_I32: 423 case AMDGPUISD::BFE_U32: { 424 if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS) 425 break; 426 427 // There is a scalar version available, but unlike the vector version which 428 // has a separate operand for the offset and width, the scalar version packs 429 // the width and offset into a single operand. Try to move to the scalar 430 // version if the offsets are constant, so that we can try to keep extended 431 // loads of kernel arguments in SGPRs. 432 433 // TODO: Technically we could try to pattern match scalar bitshifts of 434 // dynamic values, but it's probably not useful. 435 ConstantSDNode *Offset = dyn_cast<ConstantSDNode>(N->getOperand(1)); 436 if (!Offset) 437 break; 438 439 ConstantSDNode *Width = dyn_cast<ConstantSDNode>(N->getOperand(2)); 440 if (!Width) 441 break; 442 443 bool Signed = Opc == AMDGPUISD::BFE_I32; 444 445 uint32_t OffsetVal = Offset->getZExtValue(); 446 uint32_t WidthVal = Width->getZExtValue(); 447 448 ReplaceNode(N, getS_BFE(Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32, 449 SDLoc(N), N->getOperand(0), OffsetVal, WidthVal)); 450 return; 451 } 452 case AMDGPUISD::DIV_SCALE: { 453 SelectDIV_SCALE(N); 454 return; 455 } 456 case ISD::CopyToReg: { 457 const SITargetLowering& Lowering = 458 *static_cast<const SITargetLowering*>(getTargetLowering()); 459 Lowering.legalizeTargetIndependentNode(N, *CurDAG); 460 break; 461 } 462 case ISD::AND: 463 case ISD::SRL: 464 case ISD::SRA: 465 case ISD::SIGN_EXTEND_INREG: 466 if (N->getValueType(0) != MVT::i32 || 467 Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS) 468 break; 469 470 SelectS_BFE(N); 471 return; 472 case ISD::BRCOND: 473 SelectBRCOND(N); 474 return; 475 476 case AMDGPUISD::ATOMIC_CMP_SWAP: 477 SelectATOMIC_CMP_SWAP(N); 478 return; 479 } 480 481 SelectCode(N); 482 } 483 484 bool AMDGPUDAGToDAGISel::isConstantLoad(const MemSDNode *N, int CbId) const { 485 if (!N->readMem()) 486 return false; 487 if (CbId == -1) 488 return N->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS; 489 490 return N->getAddressSpace() == AMDGPUAS::CONSTANT_BUFFER_0 + CbId; 491 } 492 493 bool AMDGPUDAGToDAGISel::isUniformBr(const SDNode *N) const { 494 const BasicBlock *BB = FuncInfo->MBB->getBasicBlock(); 495 const Instruction *Term = BB->getTerminator(); 496 return Term->getMetadata("amdgpu.uniform") || 497 Term->getMetadata("structurizecfg.uniform"); 498 } 499 500 const char *AMDGPUDAGToDAGISel::getPassName() const { 501 return "AMDGPU DAG->DAG Pattern Instruction Selection"; 502 } 503 504 //===----------------------------------------------------------------------===// 505 // Complex Patterns 506 //===----------------------------------------------------------------------===// 507 508 bool AMDGPUDAGToDAGISel::SelectGlobalValueConstantOffset(SDValue Addr, 509 SDValue& IntPtr) { 510 if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Addr)) { 511 IntPtr = CurDAG->getIntPtrConstant(Cst->getZExtValue() / 4, SDLoc(Addr), 512 true); 513 return true; 514 } 515 return false; 516 } 517 518 bool AMDGPUDAGToDAGISel::SelectGlobalValueVariableOffset(SDValue Addr, 519 SDValue& BaseReg, SDValue &Offset) { 520 if (!isa<ConstantSDNode>(Addr)) { 521 BaseReg = Addr; 522 Offset = CurDAG->getIntPtrConstant(0, SDLoc(Addr), true); 523 return true; 524 } 525 return false; 526 } 527 528 bool AMDGPUDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base, 529 SDValue &Offset) { 530 ConstantSDNode *IMMOffset; 531 532 if (Addr.getOpcode() == ISD::ADD 533 && (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 534 && isInt<16>(IMMOffset->getZExtValue())) { 535 536 Base = Addr.getOperand(0); 537 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr), 538 MVT::i32); 539 return true; 540 // If the pointer address is constant, we can move it to the offset field. 541 } else if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr)) 542 && isInt<16>(IMMOffset->getZExtValue())) { 543 Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), 544 SDLoc(CurDAG->getEntryNode()), 545 AMDGPU::ZERO, MVT::i32); 546 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr), 547 MVT::i32); 548 return true; 549 } 550 551 // Default case, no offset 552 Base = Addr; 553 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 554 return true; 555 } 556 557 bool AMDGPUDAGToDAGISel::SelectADDRIndirect(SDValue Addr, SDValue &Base, 558 SDValue &Offset) { 559 ConstantSDNode *C; 560 SDLoc DL(Addr); 561 562 if ((C = dyn_cast<ConstantSDNode>(Addr))) { 563 Base = CurDAG->getRegister(AMDGPU::INDIRECT_BASE_ADDR, MVT::i32); 564 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 565 } else if ((Addr.getOpcode() == ISD::ADD || Addr.getOpcode() == ISD::OR) && 566 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) { 567 Base = Addr.getOperand(0); 568 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 569 } else { 570 Base = Addr; 571 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); 572 } 573 574 return true; 575 } 576 577 void AMDGPUDAGToDAGISel::SelectADD_SUB_I64(SDNode *N) { 578 SDLoc DL(N); 579 SDValue LHS = N->getOperand(0); 580 SDValue RHS = N->getOperand(1); 581 582 bool IsAdd = (N->getOpcode() == ISD::ADD); 583 584 SDValue Sub0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32); 585 SDValue Sub1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32); 586 587 SDNode *Lo0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 588 DL, MVT::i32, LHS, Sub0); 589 SDNode *Hi0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 590 DL, MVT::i32, LHS, Sub1); 591 592 SDNode *Lo1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 593 DL, MVT::i32, RHS, Sub0); 594 SDNode *Hi1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 595 DL, MVT::i32, RHS, Sub1); 596 597 SDVTList VTList = CurDAG->getVTList(MVT::i32, MVT::Glue); 598 SDValue AddLoArgs[] = { SDValue(Lo0, 0), SDValue(Lo1, 0) }; 599 600 unsigned Opc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32; 601 unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32; 602 603 SDNode *AddLo = CurDAG->getMachineNode( Opc, DL, VTList, AddLoArgs); 604 SDValue Carry(AddLo, 1); 605 SDNode *AddHi 606 = CurDAG->getMachineNode(CarryOpc, DL, MVT::i32, 607 SDValue(Hi0, 0), SDValue(Hi1, 0), Carry); 608 609 SDValue Args[5] = { 610 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32), 611 SDValue(AddLo,0), 612 Sub0, 613 SDValue(AddHi,0), 614 Sub1, 615 }; 616 CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, MVT::i64, Args); 617 } 618 619 // We need to handle this here because tablegen doesn't support matching 620 // instructions with multiple outputs. 621 void AMDGPUDAGToDAGISel::SelectDIV_SCALE(SDNode *N) { 622 SDLoc SL(N); 623 EVT VT = N->getValueType(0); 624 625 assert(VT == MVT::f32 || VT == MVT::f64); 626 627 unsigned Opc 628 = (VT == MVT::f64) ? AMDGPU::V_DIV_SCALE_F64 : AMDGPU::V_DIV_SCALE_F32; 629 630 // src0_modifiers, src0, src1_modifiers, src1, src2_modifiers, src2, clamp, 631 // omod 632 SDValue Ops[8]; 633 634 SelectVOP3Mods0(N->getOperand(0), Ops[1], Ops[0], Ops[6], Ops[7]); 635 SelectVOP3Mods(N->getOperand(1), Ops[3], Ops[2]); 636 SelectVOP3Mods(N->getOperand(2), Ops[5], Ops[4]); 637 CurDAG->SelectNodeTo(N, Opc, VT, MVT::i1, Ops); 638 } 639 640 bool AMDGPUDAGToDAGISel::isDSOffsetLegal(const SDValue &Base, unsigned Offset, 641 unsigned OffsetBits) const { 642 if ((OffsetBits == 16 && !isUInt<16>(Offset)) || 643 (OffsetBits == 8 && !isUInt<8>(Offset))) 644 return false; 645 646 if (Subtarget->getGeneration() >= AMDGPUSubtarget::SEA_ISLANDS || 647 Subtarget->unsafeDSOffsetFoldingEnabled()) 648 return true; 649 650 // On Southern Islands instruction with a negative base value and an offset 651 // don't seem to work. 652 return CurDAG->SignBitIsZero(Base); 653 } 654 655 bool AMDGPUDAGToDAGISel::SelectDS1Addr1Offset(SDValue Addr, SDValue &Base, 656 SDValue &Offset) const { 657 SDLoc DL(Addr); 658 if (CurDAG->isBaseWithConstantOffset(Addr)) { 659 SDValue N0 = Addr.getOperand(0); 660 SDValue N1 = Addr.getOperand(1); 661 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 662 if (isDSOffsetLegal(N0, C1->getSExtValue(), 16)) { 663 // (add n0, c0) 664 Base = N0; 665 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16); 666 return true; 667 } 668 } else if (Addr.getOpcode() == ISD::SUB) { 669 // sub C, x -> add (sub 0, x), C 670 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Addr.getOperand(0))) { 671 int64_t ByteOffset = C->getSExtValue(); 672 if (isUInt<16>(ByteOffset)) { 673 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32); 674 675 // XXX - This is kind of hacky. Create a dummy sub node so we can check 676 // the known bits in isDSOffsetLegal. We need to emit the selected node 677 // here, so this is thrown away. 678 SDValue Sub = CurDAG->getNode(ISD::SUB, DL, MVT::i32, 679 Zero, Addr.getOperand(1)); 680 681 if (isDSOffsetLegal(Sub, ByteOffset, 16)) { 682 MachineSDNode *MachineSub 683 = CurDAG->getMachineNode(AMDGPU::V_SUB_I32_e32, DL, MVT::i32, 684 Zero, Addr.getOperand(1)); 685 686 Base = SDValue(MachineSub, 0); 687 Offset = CurDAG->getTargetConstant(ByteOffset, DL, MVT::i16); 688 return true; 689 } 690 } 691 } 692 } else if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) { 693 // If we have a constant address, prefer to put the constant into the 694 // offset. This can save moves to load the constant address since multiple 695 // operations can share the zero base address register, and enables merging 696 // into read2 / write2 instructions. 697 698 SDLoc DL(Addr); 699 700 if (isUInt<16>(CAddr->getZExtValue())) { 701 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32); 702 MachineSDNode *MovZero = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, 703 DL, MVT::i32, Zero); 704 Base = SDValue(MovZero, 0); 705 Offset = CurDAG->getTargetConstant(CAddr->getZExtValue(), DL, MVT::i16); 706 return true; 707 } 708 } 709 710 // default case 711 Base = Addr; 712 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i16); 713 return true; 714 } 715 716 // TODO: If offset is too big, put low 16-bit into offset. 717 bool AMDGPUDAGToDAGISel::SelectDS64Bit4ByteAligned(SDValue Addr, SDValue &Base, 718 SDValue &Offset0, 719 SDValue &Offset1) const { 720 SDLoc DL(Addr); 721 722 if (CurDAG->isBaseWithConstantOffset(Addr)) { 723 SDValue N0 = Addr.getOperand(0); 724 SDValue N1 = Addr.getOperand(1); 725 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 726 unsigned DWordOffset0 = C1->getZExtValue() / 4; 727 unsigned DWordOffset1 = DWordOffset0 + 1; 728 // (add n0, c0) 729 if (isDSOffsetLegal(N0, DWordOffset1, 8)) { 730 Base = N0; 731 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8); 732 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8); 733 return true; 734 } 735 } else if (Addr.getOpcode() == ISD::SUB) { 736 // sub C, x -> add (sub 0, x), C 737 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Addr.getOperand(0))) { 738 unsigned DWordOffset0 = C->getZExtValue() / 4; 739 unsigned DWordOffset1 = DWordOffset0 + 1; 740 741 if (isUInt<8>(DWordOffset0)) { 742 SDLoc DL(Addr); 743 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32); 744 745 // XXX - This is kind of hacky. Create a dummy sub node so we can check 746 // the known bits in isDSOffsetLegal. We need to emit the selected node 747 // here, so this is thrown away. 748 SDValue Sub = CurDAG->getNode(ISD::SUB, DL, MVT::i32, 749 Zero, Addr.getOperand(1)); 750 751 if (isDSOffsetLegal(Sub, DWordOffset1, 8)) { 752 MachineSDNode *MachineSub 753 = CurDAG->getMachineNode(AMDGPU::V_SUB_I32_e32, DL, MVT::i32, 754 Zero, Addr.getOperand(1)); 755 756 Base = SDValue(MachineSub, 0); 757 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8); 758 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8); 759 return true; 760 } 761 } 762 } 763 } else if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) { 764 unsigned DWordOffset0 = CAddr->getZExtValue() / 4; 765 unsigned DWordOffset1 = DWordOffset0 + 1; 766 assert(4 * DWordOffset0 == CAddr->getZExtValue()); 767 768 if (isUInt<8>(DWordOffset0) && isUInt<8>(DWordOffset1)) { 769 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32); 770 MachineSDNode *MovZero 771 = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, 772 DL, MVT::i32, Zero); 773 Base = SDValue(MovZero, 0); 774 Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8); 775 Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8); 776 return true; 777 } 778 } 779 780 // default case 781 Base = Addr; 782 Offset0 = CurDAG->getTargetConstant(0, DL, MVT::i8); 783 Offset1 = CurDAG->getTargetConstant(1, DL, MVT::i8); 784 return true; 785 } 786 787 static bool isLegalMUBUFImmOffset(const ConstantSDNode *Imm) { 788 return isUInt<12>(Imm->getZExtValue()); 789 } 790 791 bool AMDGPUDAGToDAGISel::SelectMUBUF(SDValue Addr, SDValue &Ptr, 792 SDValue &VAddr, SDValue &SOffset, 793 SDValue &Offset, SDValue &Offen, 794 SDValue &Idxen, SDValue &Addr64, 795 SDValue &GLC, SDValue &SLC, 796 SDValue &TFE) const { 797 // Subtarget prefers to use flat instruction 798 if (Subtarget->useFlatForGlobal()) 799 return false; 800 801 SDLoc DL(Addr); 802 803 if (!GLC.getNode()) 804 GLC = CurDAG->getTargetConstant(0, DL, MVT::i1); 805 if (!SLC.getNode()) 806 SLC = CurDAG->getTargetConstant(0, DL, MVT::i1); 807 TFE = CurDAG->getTargetConstant(0, DL, MVT::i1); 808 809 Idxen = CurDAG->getTargetConstant(0, DL, MVT::i1); 810 Offen = CurDAG->getTargetConstant(0, DL, MVT::i1); 811 Addr64 = CurDAG->getTargetConstant(0, DL, MVT::i1); 812 SOffset = CurDAG->getTargetConstant(0, DL, MVT::i32); 813 814 if (CurDAG->isBaseWithConstantOffset(Addr)) { 815 SDValue N0 = Addr.getOperand(0); 816 SDValue N1 = Addr.getOperand(1); 817 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 818 819 if (N0.getOpcode() == ISD::ADD) { 820 // (add (add N2, N3), C1) -> addr64 821 SDValue N2 = N0.getOperand(0); 822 SDValue N3 = N0.getOperand(1); 823 Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1); 824 Ptr = N2; 825 VAddr = N3; 826 } else { 827 828 // (add N0, C1) -> offset 829 VAddr = CurDAG->getTargetConstant(0, DL, MVT::i32); 830 Ptr = N0; 831 } 832 833 if (isLegalMUBUFImmOffset(C1)) { 834 Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16); 835 return true; 836 } 837 838 if (isUInt<32>(C1->getZExtValue())) { 839 // Illegal offset, store it in soffset. 840 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16); 841 SOffset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, 842 CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i32)), 843 0); 844 return true; 845 } 846 } 847 848 if (Addr.getOpcode() == ISD::ADD) { 849 // (add N0, N1) -> addr64 850 SDValue N0 = Addr.getOperand(0); 851 SDValue N1 = Addr.getOperand(1); 852 Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1); 853 Ptr = N0; 854 VAddr = N1; 855 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16); 856 return true; 857 } 858 859 // default case -> offset 860 VAddr = CurDAG->getTargetConstant(0, DL, MVT::i32); 861 Ptr = Addr; 862 Offset = CurDAG->getTargetConstant(0, DL, MVT::i16); 863 864 return true; 865 } 866 867 bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, 868 SDValue &VAddr, SDValue &SOffset, 869 SDValue &Offset, SDValue &GLC, 870 SDValue &SLC, SDValue &TFE) const { 871 SDValue Ptr, Offen, Idxen, Addr64; 872 873 // addr64 bit was removed for volcanic islands. 874 if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS) 875 return false; 876 877 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64, 878 GLC, SLC, TFE)) 879 return false; 880 881 ConstantSDNode *C = cast<ConstantSDNode>(Addr64); 882 if (C->getSExtValue()) { 883 SDLoc DL(Addr); 884 885 const SITargetLowering& Lowering = 886 *static_cast<const SITargetLowering*>(getTargetLowering()); 887 888 SRsrc = SDValue(Lowering.wrapAddr64Rsrc(*CurDAG, DL, Ptr), 0); 889 return true; 890 } 891 892 return false; 893 } 894 895 bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, 896 SDValue &VAddr, SDValue &SOffset, 897 SDValue &Offset, 898 SDValue &SLC) const { 899 SLC = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i1); 900 SDValue GLC, TFE; 901 902 return SelectMUBUFAddr64(Addr, SRsrc, VAddr, SOffset, Offset, GLC, SLC, TFE); 903 } 904 905 bool AMDGPUDAGToDAGISel::SelectMUBUFScratch(SDValue Addr, SDValue &Rsrc, 906 SDValue &VAddr, SDValue &SOffset, 907 SDValue &ImmOffset) const { 908 909 SDLoc DL(Addr); 910 MachineFunction &MF = CurDAG->getMachineFunction(); 911 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>(); 912 913 Rsrc = CurDAG->getRegister(Info->getScratchRSrcReg(), MVT::v4i32); 914 SOffset = CurDAG->getRegister(Info->getScratchWaveOffsetReg(), MVT::i32); 915 916 // (add n0, c1) 917 if (CurDAG->isBaseWithConstantOffset(Addr)) { 918 SDValue N0 = Addr.getOperand(0); 919 SDValue N1 = Addr.getOperand(1); 920 921 // Offsets in vaddr must be positive. 922 ConstantSDNode *C1 = cast<ConstantSDNode>(N1); 923 if (isLegalMUBUFImmOffset(C1)) { 924 VAddr = N0; 925 ImmOffset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16); 926 return true; 927 } 928 } 929 930 // (node) 931 VAddr = Addr; 932 ImmOffset = CurDAG->getTargetConstant(0, DL, MVT::i16); 933 return true; 934 } 935 936 bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, 937 SDValue &SOffset, SDValue &Offset, 938 SDValue &GLC, SDValue &SLC, 939 SDValue &TFE) const { 940 SDValue Ptr, VAddr, Offen, Idxen, Addr64; 941 const SIInstrInfo *TII = 942 static_cast<const SIInstrInfo *>(Subtarget->getInstrInfo()); 943 944 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64, 945 GLC, SLC, TFE)) 946 return false; 947 948 if (!cast<ConstantSDNode>(Offen)->getSExtValue() && 949 !cast<ConstantSDNode>(Idxen)->getSExtValue() && 950 !cast<ConstantSDNode>(Addr64)->getSExtValue()) { 951 uint64_t Rsrc = TII->getDefaultRsrcDataFormat() | 952 APInt::getAllOnesValue(32).getZExtValue(); // Size 953 SDLoc DL(Addr); 954 955 const SITargetLowering& Lowering = 956 *static_cast<const SITargetLowering*>(getTargetLowering()); 957 958 SRsrc = SDValue(Lowering.buildRSRC(*CurDAG, DL, Ptr, 0, Rsrc), 0); 959 return true; 960 } 961 return false; 962 } 963 964 bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, 965 SDValue &Soffset, SDValue &Offset 966 ) const { 967 SDValue GLC, SLC, TFE; 968 969 return SelectMUBUFOffset(Addr, SRsrc, Soffset, Offset, GLC, SLC, TFE); 970 } 971 bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, 972 SDValue &Soffset, SDValue &Offset, 973 SDValue &SLC) const { 974 SDValue GLC, TFE; 975 976 return SelectMUBUFOffset(Addr, SRsrc, Soffset, Offset, GLC, SLC, TFE); 977 } 978 979 bool AMDGPUDAGToDAGISel::SelectMUBUFConstant(SDValue Constant, 980 SDValue &SOffset, 981 SDValue &ImmOffset) const { 982 SDLoc DL(Constant); 983 uint32_t Imm = cast<ConstantSDNode>(Constant)->getZExtValue(); 984 uint32_t Overflow = 0; 985 986 if (Imm >= 4096) { 987 if (Imm <= 4095 + 64) { 988 // Use an SOffset inline constant for 1..64 989 Overflow = Imm - 4095; 990 Imm = 4095; 991 } else { 992 // Try to keep the same value in SOffset for adjacent loads, so that 993 // the corresponding register contents can be re-used. 994 // 995 // Load values with all low-bits set into SOffset, so that a larger 996 // range of values can be covered using s_movk_i32 997 uint32_t High = (Imm + 1) & ~4095; 998 uint32_t Low = (Imm + 1) & 4095; 999 Imm = Low; 1000 Overflow = High - 1; 1001 } 1002 } 1003 1004 // There is a hardware bug in SI and CI which prevents address clamping in 1005 // MUBUF instructions from working correctly with SOffsets. The immediate 1006 // offset is unaffected. 1007 if (Overflow > 0 && 1008 Subtarget->getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS) 1009 return false; 1010 1011 ImmOffset = CurDAG->getTargetConstant(Imm, DL, MVT::i16); 1012 1013 if (Overflow <= 64) 1014 SOffset = CurDAG->getTargetConstant(Overflow, DL, MVT::i32); 1015 else 1016 SOffset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, 1017 CurDAG->getTargetConstant(Overflow, DL, MVT::i32)), 1018 0); 1019 1020 return true; 1021 } 1022 1023 bool AMDGPUDAGToDAGISel::SelectMUBUFIntrinsicOffset(SDValue Offset, 1024 SDValue &SOffset, 1025 SDValue &ImmOffset) const { 1026 SDLoc DL(Offset); 1027 1028 if (!isa<ConstantSDNode>(Offset)) 1029 return false; 1030 1031 return SelectMUBUFConstant(Offset, SOffset, ImmOffset); 1032 } 1033 1034 bool AMDGPUDAGToDAGISel::SelectMUBUFIntrinsicVOffset(SDValue Offset, 1035 SDValue &SOffset, 1036 SDValue &ImmOffset, 1037 SDValue &VOffset) const { 1038 SDLoc DL(Offset); 1039 1040 // Don't generate an unnecessary voffset for constant offsets. 1041 if (isa<ConstantSDNode>(Offset)) { 1042 SDValue Tmp1, Tmp2; 1043 1044 // When necessary, use a voffset in <= CI anyway to work around a hardware 1045 // bug. 1046 if (Subtarget->getGeneration() > AMDGPUSubtarget::SEA_ISLANDS || 1047 SelectMUBUFConstant(Offset, Tmp1, Tmp2)) 1048 return false; 1049 } 1050 1051 if (CurDAG->isBaseWithConstantOffset(Offset)) { 1052 SDValue N0 = Offset.getOperand(0); 1053 SDValue N1 = Offset.getOperand(1); 1054 if (cast<ConstantSDNode>(N1)->getSExtValue() >= 0 && 1055 SelectMUBUFConstant(N1, SOffset, ImmOffset)) { 1056 VOffset = N0; 1057 return true; 1058 } 1059 } 1060 1061 SOffset = CurDAG->getTargetConstant(0, DL, MVT::i32); 1062 ImmOffset = CurDAG->getTargetConstant(0, DL, MVT::i16); 1063 VOffset = Offset; 1064 1065 return true; 1066 } 1067 1068 bool AMDGPUDAGToDAGISel::SelectFlat(SDValue Addr, 1069 SDValue &VAddr, 1070 SDValue &SLC, 1071 SDValue &TFE) const { 1072 VAddr = Addr; 1073 TFE = SLC = CurDAG->getTargetConstant(0, SDLoc(), MVT::i1); 1074 return true; 1075 } 1076 1077 /// 1078 /// \param EncodedOffset This is the immediate value that will be encoded 1079 /// directly into the instruction. On SI/CI the \p EncodedOffset 1080 /// will be in units of dwords and on VI+ it will be units of bytes. 1081 static bool isLegalSMRDImmOffset(const AMDGPUSubtarget *ST, 1082 int64_t EncodedOffset) { 1083 return ST->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS ? 1084 isUInt<8>(EncodedOffset) : isUInt<20>(EncodedOffset); 1085 } 1086 1087 bool AMDGPUDAGToDAGISel::SelectSMRDOffset(SDValue ByteOffsetNode, 1088 SDValue &Offset, bool &Imm) const { 1089 1090 // FIXME: Handle non-constant offsets. 1091 ConstantSDNode *C = dyn_cast<ConstantSDNode>(ByteOffsetNode); 1092 if (!C) 1093 return false; 1094 1095 SDLoc SL(ByteOffsetNode); 1096 AMDGPUSubtarget::Generation Gen = Subtarget->getGeneration(); 1097 int64_t ByteOffset = C->getSExtValue(); 1098 int64_t EncodedOffset = Gen < AMDGPUSubtarget::VOLCANIC_ISLANDS ? 1099 ByteOffset >> 2 : ByteOffset; 1100 1101 if (isLegalSMRDImmOffset(Subtarget, EncodedOffset)) { 1102 Offset = CurDAG->getTargetConstant(EncodedOffset, SL, MVT::i32); 1103 Imm = true; 1104 return true; 1105 } 1106 1107 if (!isUInt<32>(EncodedOffset) || !isUInt<32>(ByteOffset)) 1108 return false; 1109 1110 if (Gen == AMDGPUSubtarget::SEA_ISLANDS && isUInt<32>(EncodedOffset)) { 1111 // 32-bit Immediates are supported on Sea Islands. 1112 Offset = CurDAG->getTargetConstant(EncodedOffset, SL, MVT::i32); 1113 } else { 1114 SDValue C32Bit = CurDAG->getTargetConstant(ByteOffset, SL, MVT::i32); 1115 Offset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, 1116 C32Bit), 0); 1117 } 1118 Imm = false; 1119 return true; 1120 } 1121 1122 bool AMDGPUDAGToDAGISel::SelectSMRD(SDValue Addr, SDValue &SBase, 1123 SDValue &Offset, bool &Imm) const { 1124 1125 SDLoc SL(Addr); 1126 if (CurDAG->isBaseWithConstantOffset(Addr)) { 1127 SDValue N0 = Addr.getOperand(0); 1128 SDValue N1 = Addr.getOperand(1); 1129 1130 if (SelectSMRDOffset(N1, Offset, Imm)) { 1131 SBase = N0; 1132 return true; 1133 } 1134 } 1135 SBase = Addr; 1136 Offset = CurDAG->getTargetConstant(0, SL, MVT::i32); 1137 Imm = true; 1138 return true; 1139 } 1140 1141 bool AMDGPUDAGToDAGISel::SelectSMRDImm(SDValue Addr, SDValue &SBase, 1142 SDValue &Offset) const { 1143 bool Imm; 1144 return SelectSMRD(Addr, SBase, Offset, Imm) && Imm; 1145 } 1146 1147 bool AMDGPUDAGToDAGISel::SelectSMRDImm32(SDValue Addr, SDValue &SBase, 1148 SDValue &Offset) const { 1149 1150 if (Subtarget->getGeneration() != AMDGPUSubtarget::SEA_ISLANDS) 1151 return false; 1152 1153 bool Imm; 1154 if (!SelectSMRD(Addr, SBase, Offset, Imm)) 1155 return false; 1156 1157 return !Imm && isa<ConstantSDNode>(Offset); 1158 } 1159 1160 bool AMDGPUDAGToDAGISel::SelectSMRDSgpr(SDValue Addr, SDValue &SBase, 1161 SDValue &Offset) const { 1162 bool Imm; 1163 return SelectSMRD(Addr, SBase, Offset, Imm) && !Imm && 1164 !isa<ConstantSDNode>(Offset); 1165 } 1166 1167 bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm(SDValue Addr, 1168 SDValue &Offset) const { 1169 bool Imm; 1170 return SelectSMRDOffset(Addr, Offset, Imm) && Imm; 1171 } 1172 1173 bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm32(SDValue Addr, 1174 SDValue &Offset) const { 1175 if (Subtarget->getGeneration() != AMDGPUSubtarget::SEA_ISLANDS) 1176 return false; 1177 1178 bool Imm; 1179 if (!SelectSMRDOffset(Addr, Offset, Imm)) 1180 return false; 1181 1182 return !Imm && isa<ConstantSDNode>(Offset); 1183 } 1184 1185 bool AMDGPUDAGToDAGISel::SelectSMRDBufferSgpr(SDValue Addr, 1186 SDValue &Offset) const { 1187 bool Imm; 1188 return SelectSMRDOffset(Addr, Offset, Imm) && !Imm && 1189 !isa<ConstantSDNode>(Offset); 1190 } 1191 1192 SDNode *AMDGPUDAGToDAGISel::getS_BFE(unsigned Opcode, const SDLoc &DL, 1193 SDValue Val, uint32_t Offset, 1194 uint32_t Width) { 1195 // Transformation function, pack the offset and width of a BFE into 1196 // the format expected by the S_BFE_I32 / S_BFE_U32. In the second 1197 // source, bits [5:0] contain the offset and bits [22:16] the width. 1198 uint32_t PackedVal = Offset | (Width << 16); 1199 SDValue PackedConst = CurDAG->getTargetConstant(PackedVal, DL, MVT::i32); 1200 1201 return CurDAG->getMachineNode(Opcode, DL, MVT::i32, Val, PackedConst); 1202 } 1203 1204 void AMDGPUDAGToDAGISel::SelectS_BFEFromShifts(SDNode *N) { 1205 // "(a << b) srl c)" ---> "BFE_U32 a, (c-b), (32-c) 1206 // "(a << b) sra c)" ---> "BFE_I32 a, (c-b), (32-c) 1207 // Predicate: 0 < b <= c < 32 1208 1209 const SDValue &Shl = N->getOperand(0); 1210 ConstantSDNode *B = dyn_cast<ConstantSDNode>(Shl->getOperand(1)); 1211 ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1)); 1212 1213 if (B && C) { 1214 uint32_t BVal = B->getZExtValue(); 1215 uint32_t CVal = C->getZExtValue(); 1216 1217 if (0 < BVal && BVal <= CVal && CVal < 32) { 1218 bool Signed = N->getOpcode() == ISD::SRA; 1219 unsigned Opcode = Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32; 1220 1221 ReplaceNode(N, getS_BFE(Opcode, SDLoc(N), Shl.getOperand(0), CVal - BVal, 1222 32 - CVal)); 1223 return; 1224 } 1225 } 1226 SelectCode(N); 1227 } 1228 1229 void AMDGPUDAGToDAGISel::SelectS_BFE(SDNode *N) { 1230 switch (N->getOpcode()) { 1231 case ISD::AND: 1232 if (N->getOperand(0).getOpcode() == ISD::SRL) { 1233 // "(a srl b) & mask" ---> "BFE_U32 a, b, popcount(mask)" 1234 // Predicate: isMask(mask) 1235 const SDValue &Srl = N->getOperand(0); 1236 ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(Srl.getOperand(1)); 1237 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(N->getOperand(1)); 1238 1239 if (Shift && Mask) { 1240 uint32_t ShiftVal = Shift->getZExtValue(); 1241 uint32_t MaskVal = Mask->getZExtValue(); 1242 1243 if (isMask_32(MaskVal)) { 1244 uint32_t WidthVal = countPopulation(MaskVal); 1245 1246 ReplaceNode(N, getS_BFE(AMDGPU::S_BFE_U32, SDLoc(N), 1247 Srl.getOperand(0), ShiftVal, WidthVal)); 1248 return; 1249 } 1250 } 1251 } 1252 break; 1253 case ISD::SRL: 1254 if (N->getOperand(0).getOpcode() == ISD::AND) { 1255 // "(a & mask) srl b)" ---> "BFE_U32 a, b, popcount(mask >> b)" 1256 // Predicate: isMask(mask >> b) 1257 const SDValue &And = N->getOperand(0); 1258 ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(N->getOperand(1)); 1259 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(And->getOperand(1)); 1260 1261 if (Shift && Mask) { 1262 uint32_t ShiftVal = Shift->getZExtValue(); 1263 uint32_t MaskVal = Mask->getZExtValue() >> ShiftVal; 1264 1265 if (isMask_32(MaskVal)) { 1266 uint32_t WidthVal = countPopulation(MaskVal); 1267 1268 ReplaceNode(N, getS_BFE(AMDGPU::S_BFE_U32, SDLoc(N), 1269 And.getOperand(0), ShiftVal, WidthVal)); 1270 return; 1271 } 1272 } 1273 } else if (N->getOperand(0).getOpcode() == ISD::SHL) { 1274 SelectS_BFEFromShifts(N); 1275 return; 1276 } 1277 break; 1278 case ISD::SRA: 1279 if (N->getOperand(0).getOpcode() == ISD::SHL) { 1280 SelectS_BFEFromShifts(N); 1281 return; 1282 } 1283 break; 1284 1285 case ISD::SIGN_EXTEND_INREG: { 1286 // sext_inreg (srl x, 16), i8 -> bfe_i32 x, 16, 8 1287 SDValue Src = N->getOperand(0); 1288 if (Src.getOpcode() != ISD::SRL) 1289 break; 1290 1291 const ConstantSDNode *Amt = dyn_cast<ConstantSDNode>(Src.getOperand(1)); 1292 if (!Amt) 1293 break; 1294 1295 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits(); 1296 ReplaceNode(N, getS_BFE(AMDGPU::S_BFE_I32, SDLoc(N), Src.getOperand(0), 1297 Amt->getZExtValue(), Width)); 1298 return; 1299 } 1300 } 1301 1302 SelectCode(N); 1303 } 1304 1305 void AMDGPUDAGToDAGISel::SelectBRCOND(SDNode *N) { 1306 SDValue Cond = N->getOperand(1); 1307 1308 if (isCBranchSCC(N)) { 1309 // This brcond will use S_CBRANCH_SCC*, so let tablegen handle it. 1310 SelectCode(N); 1311 return; 1312 } 1313 1314 // The result of VOPC instructions is or'd against ~EXEC before it is 1315 // written to vcc or another SGPR. This means that the value '1' is always 1316 // written to the corresponding bit for results that are masked. In order 1317 // to correctly check against vccz, we need to and VCC with the EXEC 1318 // register in order to clear the value from the masked bits. 1319 1320 SDLoc SL(N); 1321 1322 SDNode *MaskedCond = 1323 CurDAG->getMachineNode(AMDGPU::S_AND_B64, SL, MVT::i1, 1324 CurDAG->getRegister(AMDGPU::EXEC, MVT::i1), 1325 Cond); 1326 SDValue VCC = CurDAG->getCopyToReg(N->getOperand(0), SL, AMDGPU::VCC, 1327 SDValue(MaskedCond, 0), 1328 SDValue()); // Passing SDValue() adds a 1329 // glue output. 1330 CurDAG->SelectNodeTo(N, AMDGPU::S_CBRANCH_VCCNZ, MVT::Other, 1331 N->getOperand(2), // Basic Block 1332 VCC.getValue(0), // Chain 1333 VCC.getValue(1)); // Glue 1334 return; 1335 } 1336 1337 // This is here because there isn't a way to use the generated sub0_sub1 as the 1338 // subreg index to EXTRACT_SUBREG in tablegen. 1339 void AMDGPUDAGToDAGISel::SelectATOMIC_CMP_SWAP(SDNode *N) { 1340 MemSDNode *Mem = cast<MemSDNode>(N); 1341 unsigned AS = Mem->getAddressSpace(); 1342 if (AS == AMDGPUAS::FLAT_ADDRESS) { 1343 SelectCode(N); 1344 return; 1345 } 1346 1347 MVT VT = N->getSimpleValueType(0); 1348 bool Is32 = (VT == MVT::i32); 1349 SDLoc SL(N); 1350 1351 MachineSDNode *CmpSwap = nullptr; 1352 if (Subtarget->hasAddr64()) { 1353 SDValue SRsrc, VAddr, SOffset, Offset, GLC, SLC; 1354 1355 if (SelectMUBUFAddr64(Mem->getBasePtr(), SRsrc, VAddr, SOffset, Offset, SLC)) { 1356 unsigned Opcode = Is32 ? AMDGPU::BUFFER_ATOMIC_CMPSWAP_RTN_ADDR64 : 1357 AMDGPU::BUFFER_ATOMIC_CMPSWAP_X2_RTN_ADDR64; 1358 SDValue CmpVal = Mem->getOperand(2); 1359 1360 // XXX - Do we care about glue operands? 1361 1362 SDValue Ops[] = { 1363 CmpVal, VAddr, SRsrc, SOffset, Offset, SLC, Mem->getChain() 1364 }; 1365 1366 CmpSwap = CurDAG->getMachineNode(Opcode, SL, Mem->getVTList(), Ops); 1367 } 1368 } 1369 1370 if (!CmpSwap) { 1371 SDValue SRsrc, SOffset, Offset, SLC; 1372 if (SelectMUBUFOffset(Mem->getBasePtr(), SRsrc, SOffset, Offset, SLC)) { 1373 unsigned Opcode = Is32 ? AMDGPU::BUFFER_ATOMIC_CMPSWAP_RTN_OFFSET : 1374 AMDGPU::BUFFER_ATOMIC_CMPSWAP_X2_RTN_OFFSET; 1375 1376 SDValue CmpVal = Mem->getOperand(2); 1377 SDValue Ops[] = { 1378 CmpVal, SRsrc, SOffset, Offset, SLC, Mem->getChain() 1379 }; 1380 1381 CmpSwap = CurDAG->getMachineNode(Opcode, SL, Mem->getVTList(), Ops); 1382 } 1383 } 1384 1385 if (!CmpSwap) { 1386 SelectCode(N); 1387 return; 1388 } 1389 1390 MachineSDNode::mmo_iterator MMOs = MF->allocateMemRefsArray(1); 1391 *MMOs = Mem->getMemOperand(); 1392 CmpSwap->setMemRefs(MMOs, MMOs + 1); 1393 1394 unsigned SubReg = Is32 ? AMDGPU::sub0 : AMDGPU::sub0_sub1; 1395 SDValue Extract 1396 = CurDAG->getTargetExtractSubreg(SubReg, SL, VT, SDValue(CmpSwap, 0)); 1397 1398 ReplaceUses(SDValue(N, 0), Extract); 1399 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 1)); 1400 CurDAG->RemoveDeadNode(N); 1401 } 1402 1403 bool AMDGPUDAGToDAGISel::SelectVOP3Mods(SDValue In, SDValue &Src, 1404 SDValue &SrcMods) const { 1405 1406 unsigned Mods = 0; 1407 1408 Src = In; 1409 1410 if (Src.getOpcode() == ISD::FNEG) { 1411 Mods |= SISrcMods::NEG; 1412 Src = Src.getOperand(0); 1413 } 1414 1415 if (Src.getOpcode() == ISD::FABS) { 1416 Mods |= SISrcMods::ABS; 1417 Src = Src.getOperand(0); 1418 } 1419 1420 SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32); 1421 1422 return true; 1423 } 1424 1425 bool AMDGPUDAGToDAGISel::SelectVOP3NoMods(SDValue In, SDValue &Src, 1426 SDValue &SrcMods) const { 1427 bool Res = SelectVOP3Mods(In, Src, SrcMods); 1428 return Res && cast<ConstantSDNode>(SrcMods)->isNullValue(); 1429 } 1430 1431 bool AMDGPUDAGToDAGISel::SelectVOP3Mods0(SDValue In, SDValue &Src, 1432 SDValue &SrcMods, SDValue &Clamp, 1433 SDValue &Omod) const { 1434 SDLoc DL(In); 1435 // FIXME: Handle Clamp and Omod 1436 Clamp = CurDAG->getTargetConstant(0, DL, MVT::i32); 1437 Omod = CurDAG->getTargetConstant(0, DL, MVT::i32); 1438 1439 return SelectVOP3Mods(In, Src, SrcMods); 1440 } 1441 1442 bool AMDGPUDAGToDAGISel::SelectVOP3NoMods0(SDValue In, SDValue &Src, 1443 SDValue &SrcMods, SDValue &Clamp, 1444 SDValue &Omod) const { 1445 bool Res = SelectVOP3Mods0(In, Src, SrcMods, Clamp, Omod); 1446 1447 return Res && cast<ConstantSDNode>(SrcMods)->isNullValue() && 1448 cast<ConstantSDNode>(Clamp)->isNullValue() && 1449 cast<ConstantSDNode>(Omod)->isNullValue(); 1450 } 1451 1452 bool AMDGPUDAGToDAGISel::SelectVOP3Mods0Clamp(SDValue In, SDValue &Src, 1453 SDValue &SrcMods, 1454 SDValue &Omod) const { 1455 // FIXME: Handle Omod 1456 Omod = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32); 1457 1458 return SelectVOP3Mods(In, Src, SrcMods); 1459 } 1460 1461 bool AMDGPUDAGToDAGISel::SelectVOP3Mods0Clamp0OMod(SDValue In, SDValue &Src, 1462 SDValue &SrcMods, 1463 SDValue &Clamp, 1464 SDValue &Omod) const { 1465 Clamp = Omod = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32); 1466 return SelectVOP3Mods(In, Src, SrcMods); 1467 } 1468 1469 void AMDGPUDAGToDAGISel::PreprocessISelDAG() { 1470 MachineFrameInfo *MFI = CurDAG->getMachineFunction().getFrameInfo(); 1471 1472 // Handle the perverse case where a frame index is being stored. We don't 1473 // want to see multiple frame index operands on the same instruction since 1474 // it complicates things and violates some assumptions about frame index 1475 // lowering. 1476 for (int I = MFI->getObjectIndexBegin(), E = MFI->getObjectIndexEnd(); 1477 I != E; ++I) { 1478 SDValue FI = CurDAG->getTargetFrameIndex(I, MVT::i32); 1479 1480 // It's possible that we have a frame index defined in the function that 1481 // isn't used in this block. 1482 if (FI.use_empty()) 1483 continue; 1484 1485 // Skip over the AssertZext inserted during lowering. 1486 SDValue EffectiveFI = FI; 1487 auto It = FI->use_begin(); 1488 if (It->getOpcode() == ISD::AssertZext && FI->hasOneUse()) { 1489 EffectiveFI = SDValue(*It, 0); 1490 It = EffectiveFI->use_begin(); 1491 } 1492 1493 for (auto It = EffectiveFI->use_begin(); !It.atEnd(); ) { 1494 SDUse &Use = It.getUse(); 1495 SDNode *User = Use.getUser(); 1496 unsigned OpIdx = It.getOperandNo(); 1497 ++It; 1498 1499 if (MemSDNode *M = dyn_cast<MemSDNode>(User)) { 1500 unsigned PtrIdx = M->getOpcode() == ISD::STORE ? 2 : 1; 1501 if (OpIdx == PtrIdx) 1502 continue; 1503 1504 unsigned OpN = M->getNumOperands(); 1505 SDValue NewOps[8]; 1506 1507 assert(OpN < array_lengthof(NewOps)); 1508 for (unsigned Op = 0; Op != OpN; ++Op) { 1509 if (Op != OpIdx) { 1510 NewOps[Op] = M->getOperand(Op); 1511 continue; 1512 } 1513 1514 MachineSDNode *Mov = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, 1515 SDLoc(M), MVT::i32, FI); 1516 NewOps[Op] = SDValue(Mov, 0); 1517 } 1518 1519 CurDAG->UpdateNodeOperands(M, makeArrayRef(NewOps, OpN)); 1520 } 1521 } 1522 } 1523 } 1524 1525 void AMDGPUDAGToDAGISel::PostprocessISelDAG() { 1526 const AMDGPUTargetLowering& Lowering = 1527 *static_cast<const AMDGPUTargetLowering*>(getTargetLowering()); 1528 bool IsModified = false; 1529 do { 1530 IsModified = false; 1531 // Go over all selected nodes and try to fold them a bit more 1532 for (SDNode &Node : CurDAG->allnodes()) { 1533 MachineSDNode *MachineNode = dyn_cast<MachineSDNode>(&Node); 1534 if (!MachineNode) 1535 continue; 1536 1537 SDNode *ResNode = Lowering.PostISelFolding(MachineNode, *CurDAG); 1538 if (ResNode != &Node) { 1539 ReplaceUses(&Node, ResNode); 1540 IsModified = true; 1541 } 1542 } 1543 CurDAG->RemoveDeadNodes(); 1544 } while (IsModified); 1545 } 1546