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