1 //===-- RISCVISelDAGToDAG.cpp - A dag to dag inst selector for RISCV ------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines an instruction selector for the RISCV target. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "RISCVISelDAGToDAG.h" 14 #include "MCTargetDesc/RISCVMCTargetDesc.h" 15 #include "MCTargetDesc/RISCVMatInt.h" 16 #include "llvm/CodeGen/MachineFrameInfo.h" 17 #include "llvm/IR/IntrinsicsRISCV.h" 18 #include "llvm/Support/Alignment.h" 19 #include "llvm/Support/Debug.h" 20 #include "llvm/Support/MathExtras.h" 21 #include "llvm/Support/raw_ostream.h" 22 23 using namespace llvm; 24 25 #define DEBUG_TYPE "riscv-isel" 26 27 void RISCVDAGToDAGISel::PostprocessISelDAG() { 28 doPeepholeLoadStoreADDI(); 29 } 30 31 static SDNode *selectImm(SelectionDAG *CurDAG, const SDLoc &DL, int64_t Imm, 32 MVT XLenVT) { 33 RISCVMatInt::InstSeq Seq; 34 RISCVMatInt::generateInstSeq(Imm, XLenVT == MVT::i64, Seq); 35 36 SDNode *Result = nullptr; 37 SDValue SrcReg = CurDAG->getRegister(RISCV::X0, XLenVT); 38 for (RISCVMatInt::Inst &Inst : Seq) { 39 SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, XLenVT); 40 if (Inst.Opc == RISCV::LUI) 41 Result = CurDAG->getMachineNode(RISCV::LUI, DL, XLenVT, SDImm); 42 else 43 Result = CurDAG->getMachineNode(Inst.Opc, DL, XLenVT, SrcReg, SDImm); 44 45 // Only the first instruction has X0 as its source. 46 SrcReg = SDValue(Result, 0); 47 } 48 49 return Result; 50 } 51 52 void RISCVDAGToDAGISel::Select(SDNode *Node) { 53 // If we have a custom node, we have already selected. 54 if (Node->isMachineOpcode()) { 55 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n"); 56 Node->setNodeId(-1); 57 return; 58 } 59 60 // Instruction Selection not handled by the auto-generated tablegen selection 61 // should be handled here. 62 unsigned Opcode = Node->getOpcode(); 63 MVT XLenVT = Subtarget->getXLenVT(); 64 SDLoc DL(Node); 65 EVT VT = Node->getValueType(0); 66 67 switch (Opcode) { 68 case ISD::ADD: { 69 // Optimize (add r, imm) to (addi (addi r, imm0) imm1) if applicable. The 70 // immediate must be in specific ranges and have a single use. 71 if (auto *ConstOp = dyn_cast<ConstantSDNode>(Node->getOperand(1))) { 72 if (!(ConstOp->hasOneUse())) 73 break; 74 // The imm must be in range [-4096,-2049] or [2048,4094]. 75 int64_t Imm = ConstOp->getSExtValue(); 76 if (!(-4096 <= Imm && Imm <= -2049) && !(2048 <= Imm && Imm <= 4094)) 77 break; 78 // Break the imm to imm0+imm1. 79 EVT VT = Node->getValueType(0); 80 const SDValue ImmOp0 = CurDAG->getTargetConstant(Imm - Imm / 2, DL, VT); 81 const SDValue ImmOp1 = CurDAG->getTargetConstant(Imm / 2, DL, VT); 82 auto *NodeAddi0 = CurDAG->getMachineNode(RISCV::ADDI, DL, VT, 83 Node->getOperand(0), ImmOp0); 84 auto *NodeAddi1 = CurDAG->getMachineNode(RISCV::ADDI, DL, VT, 85 SDValue(NodeAddi0, 0), ImmOp1); 86 ReplaceNode(Node, NodeAddi1); 87 return; 88 } 89 break; 90 } 91 case ISD::Constant: { 92 auto ConstNode = cast<ConstantSDNode>(Node); 93 if (VT == XLenVT && ConstNode->isNullValue()) { 94 SDValue New = 95 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, RISCV::X0, XLenVT); 96 ReplaceNode(Node, New.getNode()); 97 return; 98 } 99 int64_t Imm = ConstNode->getSExtValue(); 100 if (XLenVT == MVT::i64) { 101 ReplaceNode(Node, selectImm(CurDAG, DL, Imm, XLenVT)); 102 return; 103 } 104 break; 105 } 106 case ISD::FrameIndex: { 107 SDValue Imm = CurDAG->getTargetConstant(0, DL, XLenVT); 108 int FI = cast<FrameIndexSDNode>(Node)->getIndex(); 109 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); 110 ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm)); 111 return; 112 } 113 case ISD::INTRINSIC_W_CHAIN: { 114 unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue(); 115 switch (IntNo) { 116 // By default we do not custom select any intrinsic. 117 default: 118 break; 119 120 case Intrinsic::riscv_vsetvli: { 121 if (!Subtarget->hasStdExtV()) 122 break; 123 124 assert(Node->getNumOperands() == 5); 125 126 RISCVVSEW VSEW = 127 static_cast<RISCVVSEW>(Node->getConstantOperandVal(3) & 0x7); 128 RISCVVLMUL VLMul = 129 static_cast<RISCVVLMUL>(Node->getConstantOperandVal(4) & 0x7); 130 131 unsigned VTypeI = RISCVVType::encodeVTYPE( 132 VLMul, VSEW, /*TailAgnostic*/ true, /*MaskAgnostic*/ false); 133 SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT); 134 135 SDValue VLOperand = Node->getOperand(2); 136 if (auto *C = dyn_cast<ConstantSDNode>(VLOperand)) { 137 if (C->isNullValue()) { 138 VLOperand = SDValue( 139 CurDAG->getMachineNode(RISCV::ADDI, DL, XLenVT, 140 CurDAG->getRegister(RISCV::X0, XLenVT), 141 CurDAG->getTargetConstant(0, DL, XLenVT)), 142 0); 143 } 144 } 145 146 ReplaceNode(Node, 147 CurDAG->getMachineNode(RISCV::PseudoVSETVLI, DL, XLenVT, 148 MVT::Other, VLOperand, VTypeIOp, 149 /* Chain */ Node->getOperand(0))); 150 return; 151 } 152 case Intrinsic::riscv_vsetvlimax: { 153 if (!Subtarget->hasStdExtV()) 154 break; 155 156 assert(Node->getNumOperands() == 4); 157 158 RISCVVSEW VSEW = 159 static_cast<RISCVVSEW>(Node->getConstantOperandVal(2) & 0x7); 160 RISCVVLMUL VLMul = 161 static_cast<RISCVVLMUL>(Node->getConstantOperandVal(3) & 0x7); 162 163 unsigned VTypeI = RISCVVType::encodeVTYPE( 164 VLMul, VSEW, /*TailAgnostic*/ true, /*MaskAgnostic*/ false); 165 SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT); 166 167 SDValue VLOperand = CurDAG->getRegister(RISCV::X0, XLenVT); 168 ReplaceNode(Node, 169 CurDAG->getMachineNode(RISCV::PseudoVSETVLI, DL, XLenVT, 170 MVT::Other, VLOperand, VTypeIOp, 171 /* Chain */ Node->getOperand(0))); 172 return; 173 } 174 } 175 break; 176 } 177 } 178 179 // Select the default instruction. 180 SelectCode(Node); 181 } 182 183 bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand( 184 const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) { 185 switch (ConstraintID) { 186 case InlineAsm::Constraint_m: 187 // We just support simple memory operands that have a single address 188 // operand and need no special handling. 189 OutOps.push_back(Op); 190 return false; 191 case InlineAsm::Constraint_A: 192 OutOps.push_back(Op); 193 return false; 194 default: 195 break; 196 } 197 198 return true; 199 } 200 201 bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) { 202 if (auto FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 203 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT()); 204 return true; 205 } 206 return false; 207 } 208 209 // Match (srl (and val, mask), imm) where the result would be a 210 // zero-extended 32-bit integer. i.e. the mask is 0xffffffff or the result 211 // is equivalent to this (SimplifyDemandedBits may have removed lower bits 212 // from the mask that aren't necessary due to the right-shifting). 213 bool RISCVDAGToDAGISel::MatchSRLIW(SDNode *N) const { 214 assert(N->getOpcode() == ISD::SRL); 215 assert(N->getOperand(0).getOpcode() == ISD::AND); 216 assert(isa<ConstantSDNode>(N->getOperand(1))); 217 assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1))); 218 219 // The IsRV64 predicate is checked after PatFrag predicates so we can get 220 // here even on RV32. 221 if (!Subtarget->is64Bit()) 222 return false; 223 224 SDValue And = N->getOperand(0); 225 uint64_t ShAmt = N->getConstantOperandVal(1); 226 uint64_t Mask = And.getConstantOperandVal(1); 227 return (Mask | maskTrailingOnes<uint64_t>(ShAmt)) == 0xffffffff; 228 } 229 230 // Check that it is a SLOI (Shift Left Ones Immediate). A PatFrag has already 231 // determined it has the right structure: 232 // 233 // (OR (SHL RS1, VC2), VC1) 234 // 235 // Check that VC1, the mask used to fill with ones, is compatible 236 // with VC2, the shamt: 237 // 238 // VC1 == maskTrailingOnes(VC2) 239 // 240 bool RISCVDAGToDAGISel::MatchSLOI(SDNode *N) const { 241 assert(N->getOpcode() == ISD::OR); 242 assert(N->getOperand(0).getOpcode() == ISD::SHL); 243 assert(isa<ConstantSDNode>(N->getOperand(1))); 244 assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1))); 245 246 SDValue Shl = N->getOperand(0); 247 if (Subtarget->is64Bit()) { 248 uint64_t VC1 = N->getConstantOperandVal(1); 249 uint64_t VC2 = Shl.getConstantOperandVal(1); 250 return VC1 == maskTrailingOnes<uint64_t>(VC2); 251 } 252 253 uint32_t VC1 = N->getConstantOperandVal(1); 254 uint32_t VC2 = Shl.getConstantOperandVal(1); 255 return VC1 == maskTrailingOnes<uint32_t>(VC2); 256 } 257 258 // Check that it is a SROI (Shift Right Ones Immediate). A PatFrag has already 259 // determined it has the right structure: 260 // 261 // (OR (SRL RS1, VC2), VC1) 262 // 263 // Check that VC1, the mask used to fill with ones, is compatible 264 // with VC2, the shamt: 265 // 266 // VC1 == maskLeadingOnes(VC2) 267 // 268 bool RISCVDAGToDAGISel::MatchSROI(SDNode *N) const { 269 assert(N->getOpcode() == ISD::OR); 270 assert(N->getOperand(0).getOpcode() == ISD::SRL); 271 assert(isa<ConstantSDNode>(N->getOperand(1))); 272 assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1))); 273 274 SDValue Srl = N->getOperand(0); 275 if (Subtarget->is64Bit()) { 276 uint64_t VC1 = N->getConstantOperandVal(1); 277 uint64_t VC2 = Srl.getConstantOperandVal(1); 278 return VC1 == maskLeadingOnes<uint64_t>(VC2); 279 } 280 281 uint32_t VC1 = N->getConstantOperandVal(1); 282 uint32_t VC2 = Srl.getConstantOperandVal(1); 283 return VC1 == maskLeadingOnes<uint32_t>(VC2); 284 } 285 286 // Check that it is a SROIW (Shift Right Ones Immediate i32 on RV64). A PatFrag 287 // has already determined it has the right structure: 288 // 289 // (OR (SRL RS1, VC2), VC1) 290 // 291 // and then we check that VC1, the mask used to fill with ones, is compatible 292 // with VC2, the shamt: 293 // 294 // VC2 < 32 295 // VC1 == maskTrailingZeros<uint64_t>(32 - VC2) 296 // 297 bool RISCVDAGToDAGISel::MatchSROIW(SDNode *N) const { 298 assert(N->getOpcode() == ISD::OR); 299 assert(N->getOperand(0).getOpcode() == ISD::SRL); 300 assert(isa<ConstantSDNode>(N->getOperand(1))); 301 assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1))); 302 303 // The IsRV64 predicate is checked after PatFrag predicates so we can get 304 // here even on RV32. 305 if (!Subtarget->is64Bit()) 306 return false; 307 308 SDValue Srl = N->getOperand(0); 309 uint64_t VC1 = N->getConstantOperandVal(1); 310 uint64_t VC2 = Srl.getConstantOperandVal(1); 311 312 // Immediate range should be enforced by uimm5 predicate. 313 assert(VC2 < 32 && "Unexpected immediate"); 314 return VC1 == maskTrailingZeros<uint64_t>(32 - VC2); 315 } 316 317 // Check that it is a SLLIUW (Shift Logical Left Immediate Unsigned i32 318 // on RV64). 319 // SLLIUW is the same as SLLI except for the fact that it clears the bits 320 // XLEN-1:32 of the input RS1 before shifting. 321 // A PatFrag has already checked that it has the right structure: 322 // 323 // (AND (SHL RS1, VC2), VC1) 324 // 325 // We check that VC2, the shamt is less than 32, otherwise the pattern is 326 // exactly the same as SLLI and we give priority to that. 327 // Eventually we check that VC1, the mask used to clear the upper 32 bits 328 // of RS1, is correct: 329 // 330 // VC1 == (0xFFFFFFFF << VC2) 331 // 332 bool RISCVDAGToDAGISel::MatchSLLIUW(SDNode *N) const { 333 assert(N->getOpcode() == ISD::AND); 334 assert(N->getOperand(0).getOpcode() == ISD::SHL); 335 assert(isa<ConstantSDNode>(N->getOperand(1))); 336 assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1))); 337 338 // The IsRV64 predicate is checked after PatFrag predicates so we can get 339 // here even on RV32. 340 if (!Subtarget->is64Bit()) 341 return false; 342 343 SDValue Shl = N->getOperand(0); 344 uint64_t VC1 = N->getConstantOperandVal(1); 345 uint64_t VC2 = Shl.getConstantOperandVal(1); 346 347 // Immediate range should be enforced by uimm5 predicate. 348 assert(VC2 < 32 && "Unexpected immediate"); 349 return VC1 == ((uint64_t)0xFFFFFFFF << VC2); 350 } 351 352 bool RISCVDAGToDAGISel::selectVSplat(SDValue N, SDValue &SplatVal) { 353 if (N.getOpcode() != ISD::SPLAT_VECTOR && 354 N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64) 355 return false; 356 SplatVal = N.getOperand(0); 357 return true; 358 } 359 360 bool RISCVDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &SplatVal) { 361 if ((N.getOpcode() != ISD::SPLAT_VECTOR && 362 N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64) || 363 !isa<ConstantSDNode>(N.getOperand(0))) 364 return false; 365 366 int64_t SplatImm = cast<ConstantSDNode>(N.getOperand(0))->getSExtValue(); 367 368 // Both ISD::SPLAT_VECTOR and RISCVISD::SPLAT_VECTOR_I64 share semantics when 369 // the operand type is wider than the resulting vector element type: an 370 // implicit truncation first takes place. Therefore, perform a manual 371 // truncation/sign-extension in order to ignore any truncated bits and catch 372 // any zero-extended immediate. 373 // For example, we wish to match (i8 -1) -> (XLenVT 255) as a simm5 by first 374 // sign-extending to (XLenVT -1). 375 auto XLenVT = Subtarget->getXLenVT(); 376 assert(XLenVT == N.getOperand(0).getSimpleValueType() && 377 "Unexpected splat operand type"); 378 auto EltVT = N.getValueType().getVectorElementType(); 379 if (EltVT.bitsLT(XLenVT)) { 380 SplatImm = SignExtend64(SplatImm, EltVT.getSizeInBits()); 381 } 382 383 if (!isInt<5>(SplatImm)) 384 return false; 385 386 SplatVal = CurDAG->getTargetConstant(SplatImm, SDLoc(N), XLenVT); 387 return true; 388 } 389 390 bool RISCVDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &SplatVal) { 391 if ((N.getOpcode() != ISD::SPLAT_VECTOR && 392 N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64) || 393 !isa<ConstantSDNode>(N.getOperand(0))) 394 return false; 395 396 int64_t SplatImm = cast<ConstantSDNode>(N.getOperand(0))->getSExtValue(); 397 398 if (!isUInt<5>(SplatImm)) 399 return false; 400 401 SplatVal = 402 CurDAG->getTargetConstant(SplatImm, SDLoc(N), Subtarget->getXLenVT()); 403 404 return true; 405 } 406 407 // Merge an ADDI into the offset of a load/store instruction where possible. 408 // (load (addi base, off1), off2) -> (load base, off1+off2) 409 // (store val, (addi base, off1), off2) -> (store val, base, off1+off2) 410 // This is possible when off1+off2 fits a 12-bit immediate. 411 void RISCVDAGToDAGISel::doPeepholeLoadStoreADDI() { 412 SelectionDAG::allnodes_iterator Position(CurDAG->getRoot().getNode()); 413 ++Position; 414 415 while (Position != CurDAG->allnodes_begin()) { 416 SDNode *N = &*--Position; 417 // Skip dead nodes and any non-machine opcodes. 418 if (N->use_empty() || !N->isMachineOpcode()) 419 continue; 420 421 int OffsetOpIdx; 422 int BaseOpIdx; 423 424 // Only attempt this optimisation for I-type loads and S-type stores. 425 switch (N->getMachineOpcode()) { 426 default: 427 continue; 428 case RISCV::LB: 429 case RISCV::LH: 430 case RISCV::LW: 431 case RISCV::LBU: 432 case RISCV::LHU: 433 case RISCV::LWU: 434 case RISCV::LD: 435 case RISCV::FLH: 436 case RISCV::FLW: 437 case RISCV::FLD: 438 BaseOpIdx = 0; 439 OffsetOpIdx = 1; 440 break; 441 case RISCV::SB: 442 case RISCV::SH: 443 case RISCV::SW: 444 case RISCV::SD: 445 case RISCV::FSH: 446 case RISCV::FSW: 447 case RISCV::FSD: 448 BaseOpIdx = 1; 449 OffsetOpIdx = 2; 450 break; 451 } 452 453 if (!isa<ConstantSDNode>(N->getOperand(OffsetOpIdx))) 454 continue; 455 456 SDValue Base = N->getOperand(BaseOpIdx); 457 458 // If the base is an ADDI, we can merge it in to the load/store. 459 if (!Base.isMachineOpcode() || Base.getMachineOpcode() != RISCV::ADDI) 460 continue; 461 462 SDValue ImmOperand = Base.getOperand(1); 463 uint64_t Offset2 = N->getConstantOperandVal(OffsetOpIdx); 464 465 if (auto Const = dyn_cast<ConstantSDNode>(ImmOperand)) { 466 int64_t Offset1 = Const->getSExtValue(); 467 int64_t CombinedOffset = Offset1 + Offset2; 468 if (!isInt<12>(CombinedOffset)) 469 continue; 470 ImmOperand = CurDAG->getTargetConstant(CombinedOffset, SDLoc(ImmOperand), 471 ImmOperand.getValueType()); 472 } else if (auto GA = dyn_cast<GlobalAddressSDNode>(ImmOperand)) { 473 // If the off1 in (addi base, off1) is a global variable's address (its 474 // low part, really), then we can rely on the alignment of that variable 475 // to provide a margin of safety before off1 can overflow the 12 bits. 476 // Check if off2 falls within that margin; if so off1+off2 can't overflow. 477 const DataLayout &DL = CurDAG->getDataLayout(); 478 Align Alignment = GA->getGlobal()->getPointerAlignment(DL); 479 if (Offset2 != 0 && Alignment <= Offset2) 480 continue; 481 int64_t Offset1 = GA->getOffset(); 482 int64_t CombinedOffset = Offset1 + Offset2; 483 ImmOperand = CurDAG->getTargetGlobalAddress( 484 GA->getGlobal(), SDLoc(ImmOperand), ImmOperand.getValueType(), 485 CombinedOffset, GA->getTargetFlags()); 486 } else if (auto CP = dyn_cast<ConstantPoolSDNode>(ImmOperand)) { 487 // Ditto. 488 Align Alignment = CP->getAlign(); 489 if (Offset2 != 0 && Alignment <= Offset2) 490 continue; 491 int64_t Offset1 = CP->getOffset(); 492 int64_t CombinedOffset = Offset1 + Offset2; 493 ImmOperand = CurDAG->getTargetConstantPool( 494 CP->getConstVal(), ImmOperand.getValueType(), CP->getAlign(), 495 CombinedOffset, CP->getTargetFlags()); 496 } else { 497 continue; 498 } 499 500 LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase: "); 501 LLVM_DEBUG(Base->dump(CurDAG)); 502 LLVM_DEBUG(dbgs() << "\nN: "); 503 LLVM_DEBUG(N->dump(CurDAG)); 504 LLVM_DEBUG(dbgs() << "\n"); 505 506 // Modify the offset operand of the load/store. 507 if (BaseOpIdx == 0) // Load 508 CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand, 509 N->getOperand(2)); 510 else // Store 511 CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0), 512 ImmOperand, N->getOperand(3)); 513 514 // The add-immediate may now be dead, in which case remove it. 515 if (Base.getNode()->use_empty()) 516 CurDAG->RemoveDeadNode(Base.getNode()); 517 } 518 } 519 520 // This pass converts a legalized DAG into a RISCV-specific DAG, ready 521 // for instruction scheduling. 522 FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) { 523 return new RISCVDAGToDAGISel(TM); 524 } 525