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 "RISCVISelLowering.h" 17 #include "llvm/CodeGen/MachineFrameInfo.h" 18 #include "llvm/IR/IntrinsicsRISCV.h" 19 #include "llvm/Support/Alignment.h" 20 #include "llvm/Support/Debug.h" 21 #include "llvm/Support/KnownBits.h" 22 #include "llvm/Support/MathExtras.h" 23 #include "llvm/Support/raw_ostream.h" 24 25 using namespace llvm; 26 27 #define DEBUG_TYPE "riscv-isel" 28 29 namespace llvm { 30 namespace RISCV { 31 #define GET_RISCVVSSEGTable_IMPL 32 #define GET_RISCVVLSEGTable_IMPL 33 #define GET_RISCVVLXSEGTable_IMPL 34 #define GET_RISCVVSXSEGTable_IMPL 35 #define GET_RISCVVLETable_IMPL 36 #define GET_RISCVVSETable_IMPL 37 #define GET_RISCVVLXTable_IMPL 38 #define GET_RISCVVSXTable_IMPL 39 #include "RISCVGenSearchableTables.inc" 40 } // namespace RISCV 41 } // namespace llvm 42 43 void RISCVDAGToDAGISel::PostprocessISelDAG() { 44 doPeepholeLoadStoreADDI(); 45 } 46 47 static SDNode *selectImm(SelectionDAG *CurDAG, const SDLoc &DL, int64_t Imm, 48 MVT XLenVT) { 49 RISCVMatInt::InstSeq Seq = RISCVMatInt::generateInstSeq(Imm, XLenVT == MVT::i64); 50 51 SDNode *Result = nullptr; 52 SDValue SrcReg = CurDAG->getRegister(RISCV::X0, XLenVT); 53 for (RISCVMatInt::Inst &Inst : Seq) { 54 SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, XLenVT); 55 if (Inst.Opc == RISCV::LUI) 56 Result = CurDAG->getMachineNode(RISCV::LUI, DL, XLenVT, SDImm); 57 else 58 Result = CurDAG->getMachineNode(Inst.Opc, DL, XLenVT, SrcReg, SDImm); 59 60 // Only the first instruction has X0 as its source. 61 SrcReg = SDValue(Result, 0); 62 } 63 64 return Result; 65 } 66 67 static SDValue createTupleImpl(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs, 68 unsigned RegClassID, unsigned SubReg0) { 69 assert(Regs.size() >= 2 && Regs.size() <= 8); 70 71 SDLoc DL(Regs[0]); 72 SmallVector<SDValue, 8> Ops; 73 74 Ops.push_back(CurDAG.getTargetConstant(RegClassID, DL, MVT::i32)); 75 76 for (unsigned I = 0; I < Regs.size(); ++I) { 77 Ops.push_back(Regs[I]); 78 Ops.push_back(CurDAG.getTargetConstant(SubReg0 + I, DL, MVT::i32)); 79 } 80 SDNode *N = 81 CurDAG.getMachineNode(TargetOpcode::REG_SEQUENCE, DL, MVT::Untyped, Ops); 82 return SDValue(N, 0); 83 } 84 85 static SDValue createM1Tuple(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs, 86 unsigned NF) { 87 static const unsigned RegClassIDs[] = { 88 RISCV::VRN2M1RegClassID, RISCV::VRN3M1RegClassID, RISCV::VRN4M1RegClassID, 89 RISCV::VRN5M1RegClassID, RISCV::VRN6M1RegClassID, RISCV::VRN7M1RegClassID, 90 RISCV::VRN8M1RegClassID}; 91 92 return createTupleImpl(CurDAG, Regs, RegClassIDs[NF - 2], RISCV::sub_vrm1_0); 93 } 94 95 static SDValue createM2Tuple(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs, 96 unsigned NF) { 97 static const unsigned RegClassIDs[] = {RISCV::VRN2M2RegClassID, 98 RISCV::VRN3M2RegClassID, 99 RISCV::VRN4M2RegClassID}; 100 101 return createTupleImpl(CurDAG, Regs, RegClassIDs[NF - 2], RISCV::sub_vrm2_0); 102 } 103 104 static SDValue createM4Tuple(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs, 105 unsigned NF) { 106 return createTupleImpl(CurDAG, Regs, RISCV::VRN2M4RegClassID, 107 RISCV::sub_vrm4_0); 108 } 109 110 static SDValue createTuple(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs, 111 unsigned NF, RISCVVLMUL LMUL) { 112 switch (LMUL) { 113 default: 114 llvm_unreachable("Invalid LMUL."); 115 case RISCVVLMUL::LMUL_F8: 116 case RISCVVLMUL::LMUL_F4: 117 case RISCVVLMUL::LMUL_F2: 118 case RISCVVLMUL::LMUL_1: 119 return createM1Tuple(CurDAG, Regs, NF); 120 case RISCVVLMUL::LMUL_2: 121 return createM2Tuple(CurDAG, Regs, NF); 122 case RISCVVLMUL::LMUL_4: 123 return createM4Tuple(CurDAG, Regs, NF); 124 } 125 } 126 127 void RISCVDAGToDAGISel::addVectorLoadStoreOperands( 128 SDNode *Node, unsigned SEWImm, const SDLoc &DL, unsigned CurOp, 129 bool IsMasked, bool IsStridedOrIndexed, SmallVectorImpl<SDValue> &Operands, 130 MVT *IndexVT) { 131 SDValue Chain = Node->getOperand(0); 132 SDValue Glue; 133 134 SDValue Base; 135 SelectBaseAddr(Node->getOperand(CurOp++), Base); 136 Operands.push_back(Base); // Base pointer. 137 138 if (IsStridedOrIndexed) { 139 Operands.push_back(Node->getOperand(CurOp++)); // Index. 140 if (IndexVT) 141 *IndexVT = Operands.back()->getSimpleValueType(0); 142 } 143 144 if (IsMasked) { 145 // Mask needs to be copied to V0. 146 SDValue Mask = Node->getOperand(CurOp++); 147 Chain = CurDAG->getCopyToReg(Chain, DL, RISCV::V0, Mask, SDValue()); 148 Glue = Chain.getValue(1); 149 Operands.push_back(CurDAG->getRegister(RISCV::V0, Mask.getValueType())); 150 } 151 SDValue VL; 152 selectVLOp(Node->getOperand(CurOp++), VL); 153 Operands.push_back(VL); 154 155 MVT XLenVT = Subtarget->getXLenVT(); 156 SDValue SEW = CurDAG->getTargetConstant(SEWImm, DL, XLenVT); 157 Operands.push_back(SEW); 158 159 Operands.push_back(Chain); // Chain. 160 if (Glue) 161 Operands.push_back(Glue); 162 } 163 164 void RISCVDAGToDAGISel::selectVLSEG(SDNode *Node, bool IsMasked, 165 bool IsStrided) { 166 SDLoc DL(Node); 167 unsigned NF = Node->getNumValues() - 1; 168 MVT VT = Node->getSimpleValueType(0); 169 unsigned ScalarSize = VT.getScalarSizeInBits(); 170 RISCVVLMUL LMUL = RISCVTargetLowering::getLMUL(VT); 171 172 unsigned CurOp = 2; 173 SmallVector<SDValue, 8> Operands; 174 if (IsMasked) { 175 SmallVector<SDValue, 8> Regs(Node->op_begin() + CurOp, 176 Node->op_begin() + CurOp + NF); 177 SDValue MaskedOff = createTuple(*CurDAG, Regs, NF, LMUL); 178 Operands.push_back(MaskedOff); 179 CurOp += NF; 180 } 181 182 addVectorLoadStoreOperands(Node, ScalarSize, DL, CurOp, IsMasked, IsStrided, 183 Operands); 184 185 const RISCV::VLSEGPseudo *P = 186 RISCV::getVLSEGPseudo(NF, IsMasked, IsStrided, /*FF*/ false, ScalarSize, 187 static_cast<unsigned>(LMUL)); 188 MachineSDNode *Load = 189 CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, MVT::Other, Operands); 190 191 if (auto *MemOp = dyn_cast<MemSDNode>(Node)) 192 CurDAG->setNodeMemRefs(Load, {MemOp->getMemOperand()}); 193 194 SDValue SuperReg = SDValue(Load, 0); 195 for (unsigned I = 0; I < NF; ++I) { 196 unsigned SubRegIdx = RISCVTargetLowering::getSubregIndexByMVT(VT, I); 197 ReplaceUses(SDValue(Node, I), 198 CurDAG->getTargetExtractSubreg(SubRegIdx, DL, VT, SuperReg)); 199 } 200 201 ReplaceUses(SDValue(Node, NF), SDValue(Load, 1)); 202 CurDAG->RemoveDeadNode(Node); 203 } 204 205 void RISCVDAGToDAGISel::selectVLSEGFF(SDNode *Node, bool IsMasked) { 206 SDLoc DL(Node); 207 unsigned NF = Node->getNumValues() - 2; // Do not count VL and Chain. 208 MVT VT = Node->getSimpleValueType(0); 209 MVT XLenVT = Subtarget->getXLenVT(); 210 unsigned ScalarSize = VT.getScalarSizeInBits(); 211 RISCVVLMUL LMUL = RISCVTargetLowering::getLMUL(VT); 212 213 unsigned CurOp = 2; 214 SmallVector<SDValue, 7> Operands; 215 if (IsMasked) { 216 SmallVector<SDValue, 8> Regs(Node->op_begin() + CurOp, 217 Node->op_begin() + CurOp + NF); 218 SDValue MaskedOff = createTuple(*CurDAG, Regs, NF, LMUL); 219 Operands.push_back(MaskedOff); 220 CurOp += NF; 221 } 222 223 addVectorLoadStoreOperands(Node, ScalarSize, DL, CurOp, IsMasked, 224 /*IsStridedOrIndexed*/ false, Operands); 225 226 const RISCV::VLSEGPseudo *P = 227 RISCV::getVLSEGPseudo(NF, IsMasked, /*Strided*/ false, /*FF*/ true, 228 ScalarSize, static_cast<unsigned>(LMUL)); 229 MachineSDNode *Load = CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, 230 MVT::Other, MVT::Glue, Operands); 231 SDNode *ReadVL = CurDAG->getMachineNode(RISCV::PseudoReadVL, DL, XLenVT, 232 /*Glue*/ SDValue(Load, 2)); 233 234 if (auto *MemOp = dyn_cast<MemSDNode>(Node)) 235 CurDAG->setNodeMemRefs(Load, {MemOp->getMemOperand()}); 236 237 SDValue SuperReg = SDValue(Load, 0); 238 for (unsigned I = 0; I < NF; ++I) { 239 unsigned SubRegIdx = RISCVTargetLowering::getSubregIndexByMVT(VT, I); 240 ReplaceUses(SDValue(Node, I), 241 CurDAG->getTargetExtractSubreg(SubRegIdx, DL, VT, SuperReg)); 242 } 243 244 ReplaceUses(SDValue(Node, NF), SDValue(ReadVL, 0)); // VL 245 ReplaceUses(SDValue(Node, NF + 1), SDValue(Load, 1)); // Chain 246 CurDAG->RemoveDeadNode(Node); 247 } 248 249 void RISCVDAGToDAGISel::selectVLXSEG(SDNode *Node, bool IsMasked, 250 bool IsOrdered) { 251 SDLoc DL(Node); 252 unsigned NF = Node->getNumValues() - 1; 253 MVT VT = Node->getSimpleValueType(0); 254 unsigned ScalarSize = VT.getScalarSizeInBits(); 255 RISCVVLMUL LMUL = RISCVTargetLowering::getLMUL(VT); 256 257 unsigned CurOp = 2; 258 SmallVector<SDValue, 8> Operands; 259 if (IsMasked) { 260 SmallVector<SDValue, 8> Regs(Node->op_begin() + CurOp, 261 Node->op_begin() + CurOp + NF); 262 SDValue MaskedOff = createTuple(*CurDAG, Regs, NF, LMUL); 263 Operands.push_back(MaskedOff); 264 CurOp += NF; 265 } 266 267 MVT IndexVT; 268 addVectorLoadStoreOperands(Node, ScalarSize, DL, CurOp, IsMasked, 269 /*IsStridedOrIndexed*/ true, Operands, &IndexVT); 270 271 assert(VT.getVectorElementCount() == IndexVT.getVectorElementCount() && 272 "Element count mismatch"); 273 274 RISCVVLMUL IndexLMUL = RISCVTargetLowering::getLMUL(IndexVT); 275 unsigned IndexScalarSize = IndexVT.getScalarSizeInBits(); 276 const RISCV::VLXSEGPseudo *P = RISCV::getVLXSEGPseudo( 277 NF, IsMasked, IsOrdered, IndexScalarSize, static_cast<unsigned>(LMUL), 278 static_cast<unsigned>(IndexLMUL)); 279 MachineSDNode *Load = 280 CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, MVT::Other, Operands); 281 282 if (auto *MemOp = dyn_cast<MemSDNode>(Node)) 283 CurDAG->setNodeMemRefs(Load, {MemOp->getMemOperand()}); 284 285 SDValue SuperReg = SDValue(Load, 0); 286 for (unsigned I = 0; I < NF; ++I) { 287 unsigned SubRegIdx = RISCVTargetLowering::getSubregIndexByMVT(VT, I); 288 ReplaceUses(SDValue(Node, I), 289 CurDAG->getTargetExtractSubreg(SubRegIdx, DL, VT, SuperReg)); 290 } 291 292 ReplaceUses(SDValue(Node, NF), SDValue(Load, 1)); 293 CurDAG->RemoveDeadNode(Node); 294 } 295 296 void RISCVDAGToDAGISel::selectVSSEG(SDNode *Node, bool IsMasked, 297 bool IsStrided) { 298 SDLoc DL(Node); 299 unsigned NF = Node->getNumOperands() - 4; 300 if (IsStrided) 301 NF--; 302 if (IsMasked) 303 NF--; 304 MVT VT = Node->getOperand(2)->getSimpleValueType(0); 305 unsigned ScalarSize = VT.getScalarSizeInBits(); 306 RISCVVLMUL LMUL = RISCVTargetLowering::getLMUL(VT); 307 SmallVector<SDValue, 8> Regs(Node->op_begin() + 2, Node->op_begin() + 2 + NF); 308 SDValue StoreVal = createTuple(*CurDAG, Regs, NF, LMUL); 309 310 SmallVector<SDValue, 8> Operands; 311 Operands.push_back(StoreVal); 312 unsigned CurOp = 2 + NF; 313 314 addVectorLoadStoreOperands(Node, ScalarSize, DL, CurOp, IsMasked, IsStrided, 315 Operands); 316 317 const RISCV::VSSEGPseudo *P = RISCV::getVSSEGPseudo( 318 NF, IsMasked, IsStrided, ScalarSize, static_cast<unsigned>(LMUL)); 319 MachineSDNode *Store = 320 CurDAG->getMachineNode(P->Pseudo, DL, Node->getValueType(0), Operands); 321 322 if (auto *MemOp = dyn_cast<MemSDNode>(Node)) 323 CurDAG->setNodeMemRefs(Store, {MemOp->getMemOperand()}); 324 325 ReplaceNode(Node, Store); 326 } 327 328 void RISCVDAGToDAGISel::selectVSXSEG(SDNode *Node, bool IsMasked, 329 bool IsOrdered) { 330 SDLoc DL(Node); 331 unsigned NF = Node->getNumOperands() - 5; 332 if (IsMasked) 333 --NF; 334 MVT VT = Node->getOperand(2)->getSimpleValueType(0); 335 unsigned ScalarSize = VT.getScalarSizeInBits(); 336 RISCVVLMUL LMUL = RISCVTargetLowering::getLMUL(VT); 337 SmallVector<SDValue, 8> Regs(Node->op_begin() + 2, Node->op_begin() + 2 + NF); 338 SDValue StoreVal = createTuple(*CurDAG, Regs, NF, LMUL); 339 340 SmallVector<SDValue, 8> Operands; 341 Operands.push_back(StoreVal); 342 unsigned CurOp = 2 + NF; 343 344 MVT IndexVT; 345 addVectorLoadStoreOperands(Node, ScalarSize, DL, CurOp, IsMasked, 346 /*IsStridedOrIndexed*/ true, Operands, &IndexVT); 347 348 assert(VT.getVectorElementCount() == IndexVT.getVectorElementCount() && 349 "Element count mismatch"); 350 351 RISCVVLMUL IndexLMUL = RISCVTargetLowering::getLMUL(IndexVT); 352 unsigned IndexScalarSize = IndexVT.getScalarSizeInBits(); 353 const RISCV::VSXSEGPseudo *P = RISCV::getVSXSEGPseudo( 354 NF, IsMasked, IsOrdered, IndexScalarSize, static_cast<unsigned>(LMUL), 355 static_cast<unsigned>(IndexLMUL)); 356 MachineSDNode *Store = 357 CurDAG->getMachineNode(P->Pseudo, DL, Node->getValueType(0), Operands); 358 359 if (auto *MemOp = dyn_cast<MemSDNode>(Node)) 360 CurDAG->setNodeMemRefs(Store, {MemOp->getMemOperand()}); 361 362 ReplaceNode(Node, Store); 363 } 364 365 366 void RISCVDAGToDAGISel::Select(SDNode *Node) { 367 // If we have a custom node, we have already selected. 368 if (Node->isMachineOpcode()) { 369 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n"); 370 Node->setNodeId(-1); 371 return; 372 } 373 374 // Instruction Selection not handled by the auto-generated tablegen selection 375 // should be handled here. 376 unsigned Opcode = Node->getOpcode(); 377 MVT XLenVT = Subtarget->getXLenVT(); 378 SDLoc DL(Node); 379 MVT VT = Node->getSimpleValueType(0); 380 381 switch (Opcode) { 382 case ISD::Constant: { 383 auto *ConstNode = cast<ConstantSDNode>(Node); 384 if (VT == XLenVT && ConstNode->isNullValue()) { 385 SDValue New = 386 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, RISCV::X0, XLenVT); 387 ReplaceNode(Node, New.getNode()); 388 return; 389 } 390 ReplaceNode(Node, selectImm(CurDAG, DL, ConstNode->getSExtValue(), XLenVT)); 391 return; 392 } 393 case ISD::FrameIndex: { 394 SDValue Imm = CurDAG->getTargetConstant(0, DL, XLenVT); 395 int FI = cast<FrameIndexSDNode>(Node)->getIndex(); 396 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); 397 ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm)); 398 return; 399 } 400 case ISD::SRL: { 401 // We don't need this transform if zext.h is supported. 402 if (Subtarget->hasStdExtZbb() || Subtarget->hasStdExtZbp()) 403 break; 404 // Optimize (srl (and X, 0xffff), C) -> 405 // (srli (slli X, (XLen-16), (XLen-16) + C) 406 // Taking into account that the 0xffff may have had lower bits unset by 407 // SimplifyDemandedBits. This avoids materializing the 0xffff immediate. 408 // This pattern occurs when type legalizing i16 right shifts. 409 // FIXME: This could be extended to other AND masks. 410 auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1)); 411 if (N1C) { 412 uint64_t ShAmt = N1C->getZExtValue(); 413 SDValue N0 = Node->getOperand(0); 414 if (ShAmt < 16 && N0.getOpcode() == ISD::AND && N0.hasOneUse() && 415 isa<ConstantSDNode>(N0.getOperand(1))) { 416 uint64_t Mask = N0.getConstantOperandVal(1); 417 Mask |= maskTrailingOnes<uint64_t>(ShAmt); 418 if (Mask == 0xffff) { 419 unsigned LShAmt = Subtarget->getXLen() - 16; 420 SDNode *SLLI = 421 CurDAG->getMachineNode(RISCV::SLLI, DL, VT, N0->getOperand(0), 422 CurDAG->getTargetConstant(LShAmt, DL, VT)); 423 SDNode *SRLI = CurDAG->getMachineNode( 424 RISCV::SRLI, DL, VT, SDValue(SLLI, 0), 425 CurDAG->getTargetConstant(LShAmt + ShAmt, DL, VT)); 426 ReplaceNode(Node, SRLI); 427 return; 428 } 429 } 430 } 431 432 break; 433 } 434 case ISD::INTRINSIC_W_CHAIN: { 435 unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue(); 436 switch (IntNo) { 437 // By default we do not custom select any intrinsic. 438 default: 439 break; 440 441 case Intrinsic::riscv_vsetvli: 442 case Intrinsic::riscv_vsetvlimax: { 443 if (!Subtarget->hasStdExtV()) 444 break; 445 446 bool VLMax = IntNo == Intrinsic::riscv_vsetvlimax; 447 unsigned Offset = VLMax ? 2 : 3; 448 449 assert(Node->getNumOperands() == Offset + 2 && 450 "Unexpected number of operands"); 451 452 RISCVVSEW VSEW = 453 static_cast<RISCVVSEW>(Node->getConstantOperandVal(Offset) & 0x7); 454 RISCVVLMUL VLMul = static_cast<RISCVVLMUL>( 455 Node->getConstantOperandVal(Offset + 1) & 0x7); 456 457 unsigned VTypeI = RISCVVType::encodeVTYPE( 458 VLMul, VSEW, /*TailAgnostic*/ true, /*MaskAgnostic*/ false); 459 SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT); 460 461 SDValue VLOperand; 462 if (VLMax) { 463 VLOperand = CurDAG->getRegister(RISCV::X0, XLenVT); 464 } else { 465 VLOperand = Node->getOperand(2); 466 467 if (auto *C = dyn_cast<ConstantSDNode>(VLOperand)) { 468 uint64_t AVL = C->getZExtValue(); 469 if (isUInt<5>(AVL)) { 470 SDValue VLImm = CurDAG->getTargetConstant(AVL, DL, XLenVT); 471 ReplaceNode( 472 Node, CurDAG->getMachineNode(RISCV::PseudoVSETIVLI, DL, XLenVT, 473 MVT::Other, VLImm, VTypeIOp, 474 /* Chain */ Node->getOperand(0))); 475 return; 476 } 477 } 478 } 479 480 ReplaceNode(Node, 481 CurDAG->getMachineNode(RISCV::PseudoVSETVLI, DL, XLenVT, 482 MVT::Other, VLOperand, VTypeIOp, 483 /* Chain */ Node->getOperand(0))); 484 return; 485 } 486 case Intrinsic::riscv_vlseg2: 487 case Intrinsic::riscv_vlseg3: 488 case Intrinsic::riscv_vlseg4: 489 case Intrinsic::riscv_vlseg5: 490 case Intrinsic::riscv_vlseg6: 491 case Intrinsic::riscv_vlseg7: 492 case Intrinsic::riscv_vlseg8: { 493 selectVLSEG(Node, /*IsMasked*/ false, /*IsStrided*/ false); 494 return; 495 } 496 case Intrinsic::riscv_vlseg2_mask: 497 case Intrinsic::riscv_vlseg3_mask: 498 case Intrinsic::riscv_vlseg4_mask: 499 case Intrinsic::riscv_vlseg5_mask: 500 case Intrinsic::riscv_vlseg6_mask: 501 case Intrinsic::riscv_vlseg7_mask: 502 case Intrinsic::riscv_vlseg8_mask: { 503 selectVLSEG(Node, /*IsMasked*/ true, /*IsStrided*/ false); 504 return; 505 } 506 case Intrinsic::riscv_vlsseg2: 507 case Intrinsic::riscv_vlsseg3: 508 case Intrinsic::riscv_vlsseg4: 509 case Intrinsic::riscv_vlsseg5: 510 case Intrinsic::riscv_vlsseg6: 511 case Intrinsic::riscv_vlsseg7: 512 case Intrinsic::riscv_vlsseg8: { 513 selectVLSEG(Node, /*IsMasked*/ false, /*IsStrided*/ true); 514 return; 515 } 516 case Intrinsic::riscv_vlsseg2_mask: 517 case Intrinsic::riscv_vlsseg3_mask: 518 case Intrinsic::riscv_vlsseg4_mask: 519 case Intrinsic::riscv_vlsseg5_mask: 520 case Intrinsic::riscv_vlsseg6_mask: 521 case Intrinsic::riscv_vlsseg7_mask: 522 case Intrinsic::riscv_vlsseg8_mask: { 523 selectVLSEG(Node, /*IsMasked*/ true, /*IsStrided*/ true); 524 return; 525 } 526 case Intrinsic::riscv_vloxseg2: 527 case Intrinsic::riscv_vloxseg3: 528 case Intrinsic::riscv_vloxseg4: 529 case Intrinsic::riscv_vloxseg5: 530 case Intrinsic::riscv_vloxseg6: 531 case Intrinsic::riscv_vloxseg7: 532 case Intrinsic::riscv_vloxseg8: 533 selectVLXSEG(Node, /*IsMasked*/ false, /*IsOrdered*/ true); 534 return; 535 case Intrinsic::riscv_vluxseg2: 536 case Intrinsic::riscv_vluxseg3: 537 case Intrinsic::riscv_vluxseg4: 538 case Intrinsic::riscv_vluxseg5: 539 case Intrinsic::riscv_vluxseg6: 540 case Intrinsic::riscv_vluxseg7: 541 case Intrinsic::riscv_vluxseg8: 542 selectVLXSEG(Node, /*IsMasked*/ false, /*IsOrdered*/ false); 543 return; 544 case Intrinsic::riscv_vloxseg2_mask: 545 case Intrinsic::riscv_vloxseg3_mask: 546 case Intrinsic::riscv_vloxseg4_mask: 547 case Intrinsic::riscv_vloxseg5_mask: 548 case Intrinsic::riscv_vloxseg6_mask: 549 case Intrinsic::riscv_vloxseg7_mask: 550 case Intrinsic::riscv_vloxseg8_mask: 551 selectVLXSEG(Node, /*IsMasked*/ true, /*IsOrdered*/ true); 552 return; 553 case Intrinsic::riscv_vluxseg2_mask: 554 case Intrinsic::riscv_vluxseg3_mask: 555 case Intrinsic::riscv_vluxseg4_mask: 556 case Intrinsic::riscv_vluxseg5_mask: 557 case Intrinsic::riscv_vluxseg6_mask: 558 case Intrinsic::riscv_vluxseg7_mask: 559 case Intrinsic::riscv_vluxseg8_mask: 560 selectVLXSEG(Node, /*IsMasked*/ true, /*IsOrdered*/ false); 561 return; 562 case Intrinsic::riscv_vlseg8ff: 563 case Intrinsic::riscv_vlseg7ff: 564 case Intrinsic::riscv_vlseg6ff: 565 case Intrinsic::riscv_vlseg5ff: 566 case Intrinsic::riscv_vlseg4ff: 567 case Intrinsic::riscv_vlseg3ff: 568 case Intrinsic::riscv_vlseg2ff: { 569 selectVLSEGFF(Node, /*IsMasked*/ false); 570 return; 571 } 572 case Intrinsic::riscv_vlseg8ff_mask: 573 case Intrinsic::riscv_vlseg7ff_mask: 574 case Intrinsic::riscv_vlseg6ff_mask: 575 case Intrinsic::riscv_vlseg5ff_mask: 576 case Intrinsic::riscv_vlseg4ff_mask: 577 case Intrinsic::riscv_vlseg3ff_mask: 578 case Intrinsic::riscv_vlseg2ff_mask: { 579 selectVLSEGFF(Node, /*IsMasked*/ true); 580 return; 581 } 582 case Intrinsic::riscv_vloxei: 583 case Intrinsic::riscv_vloxei_mask: 584 case Intrinsic::riscv_vluxei: 585 case Intrinsic::riscv_vluxei_mask: { 586 bool IsMasked = IntNo == Intrinsic::riscv_vloxei_mask || 587 IntNo == Intrinsic::riscv_vluxei_mask; 588 bool IsOrdered = IntNo == Intrinsic::riscv_vloxei || 589 IntNo == Intrinsic::riscv_vloxei_mask; 590 591 MVT VT = Node->getSimpleValueType(0); 592 unsigned ScalarSize = VT.getScalarSizeInBits(); 593 594 unsigned CurOp = 2; 595 SmallVector<SDValue, 8> Operands; 596 if (IsMasked) 597 Operands.push_back(Node->getOperand(CurOp++)); 598 599 MVT IndexVT; 600 addVectorLoadStoreOperands(Node, ScalarSize, DL, CurOp, IsMasked, 601 /*IsStridedOrIndexed*/ true, Operands, 602 &IndexVT); 603 604 assert(VT.getVectorElementCount() == IndexVT.getVectorElementCount() && 605 "Element count mismatch"); 606 607 RISCVVLMUL LMUL = RISCVTargetLowering::getLMUL(VT); 608 RISCVVLMUL IndexLMUL = RISCVTargetLowering::getLMUL(IndexVT); 609 unsigned IndexScalarSize = IndexVT.getScalarSizeInBits(); 610 const RISCV::VLX_VSXPseudo *P = RISCV::getVLXPseudo( 611 IsMasked, IsOrdered, IndexScalarSize, static_cast<unsigned>(LMUL), 612 static_cast<unsigned>(IndexLMUL)); 613 MachineSDNode *Load = 614 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands); 615 616 if (auto *MemOp = dyn_cast<MemSDNode>(Node)) 617 CurDAG->setNodeMemRefs(Load, {MemOp->getMemOperand()}); 618 619 ReplaceNode(Node, Load); 620 return; 621 } 622 case Intrinsic::riscv_vle1: 623 case Intrinsic::riscv_vle: 624 case Intrinsic::riscv_vle_mask: 625 case Intrinsic::riscv_vlse: 626 case Intrinsic::riscv_vlse_mask: { 627 bool IsMasked = IntNo == Intrinsic::riscv_vle_mask || 628 IntNo == Intrinsic::riscv_vlse_mask; 629 bool IsStrided = 630 IntNo == Intrinsic::riscv_vlse || IntNo == Intrinsic::riscv_vlse_mask; 631 632 MVT VT = Node->getSimpleValueType(0); 633 unsigned ScalarSize = VT.getScalarSizeInBits(); 634 // VLE1 uses an SEW of 8. 635 unsigned SEWImm = (IntNo == Intrinsic::riscv_vle1) ? 8 : ScalarSize; 636 637 unsigned CurOp = 2; 638 SmallVector<SDValue, 8> Operands; 639 if (IsMasked) 640 Operands.push_back(Node->getOperand(CurOp++)); 641 642 addVectorLoadStoreOperands(Node, SEWImm, DL, CurOp, IsMasked, IsStrided, 643 Operands); 644 645 RISCVVLMUL LMUL = RISCVTargetLowering::getLMUL(VT); 646 const RISCV::VLEPseudo *P = 647 RISCV::getVLEPseudo(IsMasked, IsStrided, /*FF*/ false, ScalarSize, 648 static_cast<unsigned>(LMUL)); 649 MachineSDNode *Load = 650 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands); 651 652 if (auto *MemOp = dyn_cast<MemSDNode>(Node)) 653 CurDAG->setNodeMemRefs(Load, {MemOp->getMemOperand()}); 654 655 ReplaceNode(Node, Load); 656 return; 657 } 658 case Intrinsic::riscv_vleff: 659 case Intrinsic::riscv_vleff_mask: { 660 bool IsMasked = IntNo == Intrinsic::riscv_vleff_mask; 661 662 MVT VT = Node->getSimpleValueType(0); 663 unsigned ScalarSize = VT.getScalarSizeInBits(); 664 665 unsigned CurOp = 2; 666 SmallVector<SDValue, 7> Operands; 667 if (IsMasked) 668 Operands.push_back(Node->getOperand(CurOp++)); 669 670 addVectorLoadStoreOperands(Node, ScalarSize, DL, CurOp, IsMasked, 671 /*IsStridedOrIndexed*/ false, Operands); 672 673 RISCVVLMUL LMUL = RISCVTargetLowering::getLMUL(VT); 674 const RISCV::VLEPseudo *P = 675 RISCV::getVLEPseudo(IsMasked, /*Strided*/ false, /*FF*/ true, 676 ScalarSize, static_cast<unsigned>(LMUL)); 677 MachineSDNode *Load = 678 CurDAG->getMachineNode(P->Pseudo, DL, Node->getValueType(0), 679 MVT::Other, MVT::Glue, Operands); 680 SDNode *ReadVL = CurDAG->getMachineNode(RISCV::PseudoReadVL, DL, XLenVT, 681 /*Glue*/ SDValue(Load, 2)); 682 683 if (auto *MemOp = dyn_cast<MemSDNode>(Node)) 684 CurDAG->setNodeMemRefs(Load, {MemOp->getMemOperand()}); 685 686 ReplaceUses(SDValue(Node, 0), SDValue(Load, 0)); 687 ReplaceUses(SDValue(Node, 1), SDValue(ReadVL, 0)); // VL 688 ReplaceUses(SDValue(Node, 2), SDValue(Load, 1)); // Chain 689 CurDAG->RemoveDeadNode(Node); 690 return; 691 } 692 } 693 break; 694 } 695 case ISD::INTRINSIC_VOID: { 696 unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue(); 697 switch (IntNo) { 698 case Intrinsic::riscv_vsseg2: 699 case Intrinsic::riscv_vsseg3: 700 case Intrinsic::riscv_vsseg4: 701 case Intrinsic::riscv_vsseg5: 702 case Intrinsic::riscv_vsseg6: 703 case Intrinsic::riscv_vsseg7: 704 case Intrinsic::riscv_vsseg8: { 705 selectVSSEG(Node, /*IsMasked*/ false, /*IsStrided*/ false); 706 return; 707 } 708 case Intrinsic::riscv_vsseg2_mask: 709 case Intrinsic::riscv_vsseg3_mask: 710 case Intrinsic::riscv_vsseg4_mask: 711 case Intrinsic::riscv_vsseg5_mask: 712 case Intrinsic::riscv_vsseg6_mask: 713 case Intrinsic::riscv_vsseg7_mask: 714 case Intrinsic::riscv_vsseg8_mask: { 715 selectVSSEG(Node, /*IsMasked*/ true, /*IsStrided*/ false); 716 return; 717 } 718 case Intrinsic::riscv_vssseg2: 719 case Intrinsic::riscv_vssseg3: 720 case Intrinsic::riscv_vssseg4: 721 case Intrinsic::riscv_vssseg5: 722 case Intrinsic::riscv_vssseg6: 723 case Intrinsic::riscv_vssseg7: 724 case Intrinsic::riscv_vssseg8: { 725 selectVSSEG(Node, /*IsMasked*/ false, /*IsStrided*/ true); 726 return; 727 } 728 case Intrinsic::riscv_vssseg2_mask: 729 case Intrinsic::riscv_vssseg3_mask: 730 case Intrinsic::riscv_vssseg4_mask: 731 case Intrinsic::riscv_vssseg5_mask: 732 case Intrinsic::riscv_vssseg6_mask: 733 case Intrinsic::riscv_vssseg7_mask: 734 case Intrinsic::riscv_vssseg8_mask: { 735 selectVSSEG(Node, /*IsMasked*/ true, /*IsStrided*/ true); 736 return; 737 } 738 case Intrinsic::riscv_vsoxseg2: 739 case Intrinsic::riscv_vsoxseg3: 740 case Intrinsic::riscv_vsoxseg4: 741 case Intrinsic::riscv_vsoxseg5: 742 case Intrinsic::riscv_vsoxseg6: 743 case Intrinsic::riscv_vsoxseg7: 744 case Intrinsic::riscv_vsoxseg8: 745 selectVSXSEG(Node, /*IsMasked*/ false, /*IsOrdered*/ true); 746 return; 747 case Intrinsic::riscv_vsuxseg2: 748 case Intrinsic::riscv_vsuxseg3: 749 case Intrinsic::riscv_vsuxseg4: 750 case Intrinsic::riscv_vsuxseg5: 751 case Intrinsic::riscv_vsuxseg6: 752 case Intrinsic::riscv_vsuxseg7: 753 case Intrinsic::riscv_vsuxseg8: 754 selectVSXSEG(Node, /*IsMasked*/ false, /*IsOrdered*/ false); 755 return; 756 case Intrinsic::riscv_vsoxseg2_mask: 757 case Intrinsic::riscv_vsoxseg3_mask: 758 case Intrinsic::riscv_vsoxseg4_mask: 759 case Intrinsic::riscv_vsoxseg5_mask: 760 case Intrinsic::riscv_vsoxseg6_mask: 761 case Intrinsic::riscv_vsoxseg7_mask: 762 case Intrinsic::riscv_vsoxseg8_mask: 763 selectVSXSEG(Node, /*IsMasked*/ true, /*IsOrdered*/ true); 764 return; 765 case Intrinsic::riscv_vsuxseg2_mask: 766 case Intrinsic::riscv_vsuxseg3_mask: 767 case Intrinsic::riscv_vsuxseg4_mask: 768 case Intrinsic::riscv_vsuxseg5_mask: 769 case Intrinsic::riscv_vsuxseg6_mask: 770 case Intrinsic::riscv_vsuxseg7_mask: 771 case Intrinsic::riscv_vsuxseg8_mask: 772 selectVSXSEG(Node, /*IsMasked*/ true, /*IsOrdered*/ false); 773 return; 774 case Intrinsic::riscv_vsoxei: 775 case Intrinsic::riscv_vsoxei_mask: 776 case Intrinsic::riscv_vsuxei: 777 case Intrinsic::riscv_vsuxei_mask: { 778 bool IsMasked = IntNo == Intrinsic::riscv_vsoxei_mask || 779 IntNo == Intrinsic::riscv_vsuxei_mask; 780 bool IsOrdered = IntNo == Intrinsic::riscv_vsoxei || 781 IntNo == Intrinsic::riscv_vsoxei_mask; 782 783 MVT VT = Node->getOperand(2)->getSimpleValueType(0); 784 unsigned ScalarSize = VT.getScalarSizeInBits(); 785 786 unsigned CurOp = 2; 787 SmallVector<SDValue, 8> Operands; 788 Operands.push_back(Node->getOperand(CurOp++)); // Store value. 789 790 MVT IndexVT; 791 addVectorLoadStoreOperands(Node, ScalarSize, DL, CurOp, IsMasked, 792 /*IsStridedOrIndexed*/ true, Operands, 793 &IndexVT); 794 795 assert(VT.getVectorElementCount() == IndexVT.getVectorElementCount() && 796 "Element count mismatch"); 797 798 RISCVVLMUL LMUL = RISCVTargetLowering::getLMUL(VT); 799 RISCVVLMUL IndexLMUL = RISCVTargetLowering::getLMUL(IndexVT); 800 unsigned IndexScalarSize = IndexVT.getScalarSizeInBits(); 801 const RISCV::VLX_VSXPseudo *P = RISCV::getVSXPseudo( 802 IsMasked, IsOrdered, IndexScalarSize, static_cast<unsigned>(LMUL), 803 static_cast<unsigned>(IndexLMUL)); 804 MachineSDNode *Store = 805 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands); 806 807 if (auto *MemOp = dyn_cast<MemSDNode>(Node)) 808 CurDAG->setNodeMemRefs(Store, {MemOp->getMemOperand()}); 809 810 ReplaceNode(Node, Store); 811 return; 812 } 813 case Intrinsic::riscv_vse1: 814 case Intrinsic::riscv_vse: 815 case Intrinsic::riscv_vse_mask: 816 case Intrinsic::riscv_vsse: 817 case Intrinsic::riscv_vsse_mask: { 818 bool IsMasked = IntNo == Intrinsic::riscv_vse_mask || 819 IntNo == Intrinsic::riscv_vsse_mask; 820 bool IsStrided = 821 IntNo == Intrinsic::riscv_vsse || IntNo == Intrinsic::riscv_vsse_mask; 822 823 MVT VT = Node->getOperand(2)->getSimpleValueType(0); 824 unsigned ScalarSize = VT.getScalarSizeInBits(); 825 // VSE1 uses an SEW of 8. 826 unsigned SEWImm = (IntNo == Intrinsic::riscv_vse1) ? 8 : ScalarSize; 827 828 unsigned CurOp = 2; 829 SmallVector<SDValue, 8> Operands; 830 Operands.push_back(Node->getOperand(CurOp++)); // Store value. 831 832 addVectorLoadStoreOperands(Node, SEWImm, DL, CurOp, IsMasked, IsStrided, 833 Operands); 834 835 RISCVVLMUL LMUL = RISCVTargetLowering::getLMUL(VT); 836 const RISCV::VSEPseudo *P = RISCV::getVSEPseudo( 837 IsMasked, IsStrided, ScalarSize, static_cast<unsigned>(LMUL)); 838 MachineSDNode *Store = 839 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands); 840 if (auto *MemOp = dyn_cast<MemSDNode>(Node)) 841 CurDAG->setNodeMemRefs(Store, {MemOp->getMemOperand()}); 842 843 ReplaceNode(Node, Store); 844 return; 845 } 846 } 847 break; 848 } 849 case ISD::BITCAST: { 850 MVT SrcVT = Node->getOperand(0).getSimpleValueType(); 851 // Just drop bitcasts between vectors if both are fixed or both are 852 // scalable. 853 if ((VT.isScalableVector() && SrcVT.isScalableVector()) || 854 (VT.isFixedLengthVector() && SrcVT.isFixedLengthVector())) { 855 ReplaceUses(SDValue(Node, 0), Node->getOperand(0)); 856 CurDAG->RemoveDeadNode(Node); 857 return; 858 } 859 break; 860 } 861 case ISD::INSERT_SUBVECTOR: { 862 SDValue V = Node->getOperand(0); 863 SDValue SubV = Node->getOperand(1); 864 SDLoc DL(SubV); 865 auto Idx = Node->getConstantOperandVal(2); 866 MVT SubVecVT = SubV.getSimpleValueType(); 867 868 MVT SubVecContainerVT = SubVecVT; 869 // Establish the correct scalable-vector types for any fixed-length type. 870 if (SubVecVT.isFixedLengthVector()) 871 SubVecContainerVT = RISCVTargetLowering::getContainerForFixedLengthVector( 872 *CurDAG, SubVecVT, *Subtarget); 873 if (VT.isFixedLengthVector()) 874 VT = RISCVTargetLowering::getContainerForFixedLengthVector(*CurDAG, VT, 875 *Subtarget); 876 877 const auto *TRI = Subtarget->getRegisterInfo(); 878 unsigned SubRegIdx; 879 std::tie(SubRegIdx, Idx) = 880 RISCVTargetLowering::decomposeSubvectorInsertExtractToSubRegs( 881 VT, SubVecContainerVT, Idx, TRI); 882 883 // If the Idx hasn't been completely eliminated then this is a subvector 884 // insert which doesn't naturally align to a vector register. These must 885 // be handled using instructions to manipulate the vector registers. 886 if (Idx != 0) 887 break; 888 889 RISCVVLMUL SubVecLMUL = RISCVTargetLowering::getLMUL(SubVecContainerVT); 890 bool IsSubVecPartReg = SubVecLMUL == RISCVVLMUL::LMUL_F2 || 891 SubVecLMUL == RISCVVLMUL::LMUL_F4 || 892 SubVecLMUL == RISCVVLMUL::LMUL_F8; 893 (void)IsSubVecPartReg; // Silence unused variable warning without asserts. 894 assert((!IsSubVecPartReg || V.isUndef()) && 895 "Expecting lowering to have created legal INSERT_SUBVECTORs when " 896 "the subvector is smaller than a full-sized register"); 897 898 // If we haven't set a SubRegIdx, then we must be going between 899 // equally-sized LMUL groups (e.g. VR -> VR). This can be done as a copy. 900 if (SubRegIdx == RISCV::NoSubRegister) { 901 unsigned InRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(VT); 902 assert(RISCVTargetLowering::getRegClassIDForVecVT(SubVecContainerVT) == 903 InRegClassID && 904 "Unexpected subvector extraction"); 905 SDValue RC = CurDAG->getTargetConstant(InRegClassID, DL, XLenVT); 906 SDNode *NewNode = CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, 907 DL, VT, SubV, RC); 908 ReplaceNode(Node, NewNode); 909 return; 910 } 911 912 SDValue Insert = CurDAG->getTargetInsertSubreg(SubRegIdx, DL, VT, V, SubV); 913 ReplaceNode(Node, Insert.getNode()); 914 return; 915 } 916 case ISD::EXTRACT_SUBVECTOR: { 917 SDValue V = Node->getOperand(0); 918 auto Idx = Node->getConstantOperandVal(1); 919 MVT InVT = V.getSimpleValueType(); 920 SDLoc DL(V); 921 922 MVT SubVecContainerVT = VT; 923 // Establish the correct scalable-vector types for any fixed-length type. 924 if (VT.isFixedLengthVector()) 925 SubVecContainerVT = RISCVTargetLowering::getContainerForFixedLengthVector( 926 *CurDAG, VT, *Subtarget); 927 if (InVT.isFixedLengthVector()) 928 InVT = RISCVTargetLowering::getContainerForFixedLengthVector( 929 *CurDAG, InVT, *Subtarget); 930 931 const auto *TRI = Subtarget->getRegisterInfo(); 932 unsigned SubRegIdx; 933 std::tie(SubRegIdx, Idx) = 934 RISCVTargetLowering::decomposeSubvectorInsertExtractToSubRegs( 935 InVT, SubVecContainerVT, Idx, TRI); 936 937 // If the Idx hasn't been completely eliminated then this is a subvector 938 // extract which doesn't naturally align to a vector register. These must 939 // be handled using instructions to manipulate the vector registers. 940 if (Idx != 0) 941 break; 942 943 // If we haven't set a SubRegIdx, then we must be going between 944 // equally-sized LMUL types (e.g. VR -> VR). This can be done as a copy. 945 if (SubRegIdx == RISCV::NoSubRegister) { 946 unsigned InRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(InVT); 947 assert(RISCVTargetLowering::getRegClassIDForVecVT(SubVecContainerVT) == 948 InRegClassID && 949 "Unexpected subvector extraction"); 950 SDValue RC = CurDAG->getTargetConstant(InRegClassID, DL, XLenVT); 951 SDNode *NewNode = 952 CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, DL, VT, V, RC); 953 ReplaceNode(Node, NewNode); 954 return; 955 } 956 957 SDValue Extract = CurDAG->getTargetExtractSubreg(SubRegIdx, DL, VT, V); 958 ReplaceNode(Node, Extract.getNode()); 959 return; 960 } 961 } 962 963 // Select the default instruction. 964 SelectCode(Node); 965 } 966 967 bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand( 968 const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) { 969 switch (ConstraintID) { 970 case InlineAsm::Constraint_m: 971 // We just support simple memory operands that have a single address 972 // operand and need no special handling. 973 OutOps.push_back(Op); 974 return false; 975 case InlineAsm::Constraint_A: 976 OutOps.push_back(Op); 977 return false; 978 default: 979 break; 980 } 981 982 return true; 983 } 984 985 bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) { 986 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 987 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT()); 988 return true; 989 } 990 return false; 991 } 992 993 bool RISCVDAGToDAGISel::SelectBaseAddr(SDValue Addr, SDValue &Base) { 994 // If this is FrameIndex, select it directly. Otherwise just let it get 995 // selected to a register independently. 996 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr)) 997 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT()); 998 else 999 Base = Addr; 1000 return true; 1001 } 1002 1003 bool RISCVDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth, 1004 SDValue &ShAmt) { 1005 // Shift instructions on RISCV only read the lower 5 or 6 bits of the shift 1006 // amount. If there is an AND on the shift amount, we can bypass it if it 1007 // doesn't affect any of those bits. 1008 if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1))) { 1009 const APInt &AndMask = N->getConstantOperandAPInt(1); 1010 1011 // Since the max shift amount is a power of 2 we can subtract 1 to make a 1012 // mask that covers the bits needed to represent all shift amounts. 1013 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!"); 1014 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1); 1015 1016 if (ShMask.isSubsetOf(AndMask)) { 1017 ShAmt = N.getOperand(0); 1018 return true; 1019 } 1020 1021 // SimplifyDemandedBits may have optimized the mask so try restoring any 1022 // bits that are known zero. 1023 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0)); 1024 if (ShMask.isSubsetOf(AndMask | Known.Zero)) { 1025 ShAmt = N.getOperand(0); 1026 return true; 1027 } 1028 } 1029 1030 ShAmt = N; 1031 return true; 1032 } 1033 1034 bool RISCVDAGToDAGISel::selectSExti32(SDValue N, SDValue &Val) { 1035 if (N.getOpcode() == ISD::SIGN_EXTEND_INREG && 1036 cast<VTSDNode>(N.getOperand(1))->getVT() == MVT::i32) { 1037 Val = N.getOperand(0); 1038 return true; 1039 } 1040 // FIXME: Should we just call computeNumSignBits here? 1041 if (N.getOpcode() == ISD::AssertSext && 1042 cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32)) { 1043 Val = N; 1044 return true; 1045 } 1046 if (N.getOpcode() == ISD::AssertZext && 1047 cast<VTSDNode>(N->getOperand(1))->getVT().bitsLT(MVT::i32)) { 1048 Val = N; 1049 return true; 1050 } 1051 1052 return false; 1053 } 1054 1055 bool RISCVDAGToDAGISel::selectZExti32(SDValue N, SDValue &Val) { 1056 if (N.getOpcode() == ISD::AND) { 1057 auto *C = dyn_cast<ConstantSDNode>(N.getOperand(1)); 1058 if (C && C->getZExtValue() == UINT64_C(0xFFFFFFFF)) { 1059 Val = N.getOperand(0); 1060 return true; 1061 } 1062 } 1063 // FIXME: Should we just call computeKnownBits here? 1064 if (N.getOpcode() == ISD::AssertZext && 1065 cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32)) { 1066 Val = N; 1067 return true; 1068 } 1069 1070 return false; 1071 } 1072 1073 // Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1), 1074 // in which imm = imm0 + imm1 and both imm0 and imm1 are simm12. 1075 bool RISCVDAGToDAGISel::selectAddiPair(SDValue N, SDValue &Val) { 1076 if (auto *ConstOp = dyn_cast<ConstantSDNode>(N)) { 1077 // The immediate operand must have only use. 1078 if (!(ConstOp->hasOneUse())) 1079 return false; 1080 // The immediate operand must be in range [-4096,-2049] or [2048,4094]. 1081 int64_t Imm = ConstOp->getSExtValue(); 1082 if ((-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094)) { 1083 Val = N; 1084 return true; 1085 } 1086 } 1087 return false; 1088 } 1089 1090 // Check that it is a SLLIUW (Shift Logical Left Immediate Unsigned i32 1091 // on RV64). 1092 // SLLIUW is the same as SLLI except for the fact that it clears the bits 1093 // XLEN-1:32 of the input RS1 before shifting. 1094 // A PatFrag has already checked that it has the right structure: 1095 // 1096 // (AND (SHL RS1, VC2), VC1) 1097 // 1098 // We check that VC2, the shamt is less than 32, otherwise the pattern is 1099 // exactly the same as SLLI and we give priority to that. 1100 // Eventually we check that VC1, the mask used to clear the upper 32 bits 1101 // of RS1, is correct: 1102 // 1103 // VC1 == (0xFFFFFFFF << VC2) 1104 // 1105 bool RISCVDAGToDAGISel::MatchSLLIUW(SDNode *N) const { 1106 assert(N->getOpcode() == ISD::AND); 1107 assert(N->getOperand(0).getOpcode() == ISD::SHL); 1108 assert(isa<ConstantSDNode>(N->getOperand(1))); 1109 assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1))); 1110 1111 // The IsRV64 predicate is checked after PatFrag predicates so we can get 1112 // here even on RV32. 1113 if (!Subtarget->is64Bit()) 1114 return false; 1115 1116 SDValue Shl = N->getOperand(0); 1117 uint64_t VC1 = N->getConstantOperandVal(1); 1118 uint64_t VC2 = Shl.getConstantOperandVal(1); 1119 1120 // Immediate range should be enforced by uimm5 predicate. 1121 assert(VC2 < 32 && "Unexpected immediate"); 1122 return (VC1 >> VC2) == UINT64_C(0xFFFFFFFF); 1123 } 1124 1125 // X0 has special meaning for vsetvl/vsetvli. 1126 // rd | rs1 | AVL value | Effect on vl 1127 //-------------------------------------------------------------- 1128 // !X0 | X0 | VLMAX | Set vl to VLMAX 1129 // X0 | X0 | Value in vl | Keep current vl, just change vtype. 1130 bool RISCVDAGToDAGISel::selectVLOp(SDValue N, SDValue &VL) { 1131 // If the VL value is a constant 0, manually select it to an ADDI with 0 1132 // immediate to prevent the default selection path from matching it to X0. 1133 auto *C = dyn_cast<ConstantSDNode>(N); 1134 if (C && C->isNullValue()) 1135 VL = SDValue(selectImm(CurDAG, SDLoc(N), 0, Subtarget->getXLenVT()), 0); 1136 else 1137 VL = N; 1138 1139 return true; 1140 } 1141 1142 bool RISCVDAGToDAGISel::selectVSplat(SDValue N, SDValue &SplatVal) { 1143 if (N.getOpcode() != ISD::SPLAT_VECTOR && 1144 N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64 && 1145 N.getOpcode() != RISCVISD::VMV_V_X_VL) 1146 return false; 1147 SplatVal = N.getOperand(0); 1148 return true; 1149 } 1150 1151 using ValidateFn = bool (*)(int64_t); 1152 1153 static bool selectVSplatSimmHelper(SDValue N, SDValue &SplatVal, 1154 SelectionDAG &DAG, 1155 const RISCVSubtarget &Subtarget, 1156 ValidateFn ValidateImm) { 1157 if ((N.getOpcode() != ISD::SPLAT_VECTOR && 1158 N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64 && 1159 N.getOpcode() != RISCVISD::VMV_V_X_VL) || 1160 !isa<ConstantSDNode>(N.getOperand(0))) 1161 return false; 1162 1163 int64_t SplatImm = cast<ConstantSDNode>(N.getOperand(0))->getSExtValue(); 1164 1165 // ISD::SPLAT_VECTOR, RISCVISD::SPLAT_VECTOR_I64 and RISCVISD::VMV_V_X_VL 1166 // share semantics when the operand type is wider than the resulting vector 1167 // element type: an implicit truncation first takes place. Therefore, perform 1168 // a manual truncation/sign-extension in order to ignore any truncated bits 1169 // and catch any zero-extended immediate. 1170 // For example, we wish to match (i8 -1) -> (XLenVT 255) as a simm5 by first 1171 // sign-extending to (XLenVT -1). 1172 MVT XLenVT = Subtarget.getXLenVT(); 1173 assert(XLenVT == N.getOperand(0).getSimpleValueType() && 1174 "Unexpected splat operand type"); 1175 MVT EltVT = N.getSimpleValueType().getVectorElementType(); 1176 if (EltVT.bitsLT(XLenVT)) 1177 SplatImm = SignExtend64(SplatImm, EltVT.getSizeInBits()); 1178 1179 if (!ValidateImm(SplatImm)) 1180 return false; 1181 1182 SplatVal = DAG.getTargetConstant(SplatImm, SDLoc(N), XLenVT); 1183 return true; 1184 } 1185 1186 bool RISCVDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &SplatVal) { 1187 return selectVSplatSimmHelper(N, SplatVal, *CurDAG, *Subtarget, 1188 [](int64_t Imm) { return isInt<5>(Imm); }); 1189 } 1190 1191 bool RISCVDAGToDAGISel::selectVSplatSimm5Plus1(SDValue N, SDValue &SplatVal) { 1192 return selectVSplatSimmHelper( 1193 N, SplatVal, *CurDAG, *Subtarget, 1194 [](int64_t Imm) { return (isInt<5>(Imm) && Imm != -16) || Imm == 16; }); 1195 } 1196 1197 bool RISCVDAGToDAGISel::selectVSplatSimm5Plus1NonZero(SDValue N, 1198 SDValue &SplatVal) { 1199 return selectVSplatSimmHelper( 1200 N, SplatVal, *CurDAG, *Subtarget, [](int64_t Imm) { 1201 return Imm != 0 && ((isInt<5>(Imm) && Imm != -16) || Imm == 16); 1202 }); 1203 } 1204 1205 bool RISCVDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &SplatVal) { 1206 if ((N.getOpcode() != ISD::SPLAT_VECTOR && 1207 N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64 && 1208 N.getOpcode() != RISCVISD::VMV_V_X_VL) || 1209 !isa<ConstantSDNode>(N.getOperand(0))) 1210 return false; 1211 1212 int64_t SplatImm = cast<ConstantSDNode>(N.getOperand(0))->getSExtValue(); 1213 1214 if (!isUInt<5>(SplatImm)) 1215 return false; 1216 1217 SplatVal = 1218 CurDAG->getTargetConstant(SplatImm, SDLoc(N), Subtarget->getXLenVT()); 1219 1220 return true; 1221 } 1222 1223 bool RISCVDAGToDAGISel::selectRVVSimm5(SDValue N, unsigned Width, 1224 SDValue &Imm) { 1225 if (auto *C = dyn_cast<ConstantSDNode>(N)) { 1226 int64_t ImmVal = SignExtend64(C->getSExtValue(), Width); 1227 1228 if (!isInt<5>(ImmVal)) 1229 return false; 1230 1231 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(N), Subtarget->getXLenVT()); 1232 return true; 1233 } 1234 1235 return false; 1236 } 1237 1238 bool RISCVDAGToDAGISel::selectRVVUimm5(SDValue N, unsigned Width, 1239 SDValue &Imm) { 1240 if (auto *C = dyn_cast<ConstantSDNode>(N)) { 1241 int64_t ImmVal = C->getSExtValue(); 1242 1243 if (!isUInt<5>(ImmVal)) 1244 return false; 1245 1246 Imm = CurDAG->getTargetConstant(ImmVal, SDLoc(N), Subtarget->getXLenVT()); 1247 return true; 1248 } 1249 1250 return false; 1251 } 1252 1253 // Merge an ADDI into the offset of a load/store instruction where possible. 1254 // (load (addi base, off1), off2) -> (load base, off1+off2) 1255 // (store val, (addi base, off1), off2) -> (store val, base, off1+off2) 1256 // This is possible when off1+off2 fits a 12-bit immediate. 1257 void RISCVDAGToDAGISel::doPeepholeLoadStoreADDI() { 1258 SelectionDAG::allnodes_iterator Position(CurDAG->getRoot().getNode()); 1259 ++Position; 1260 1261 while (Position != CurDAG->allnodes_begin()) { 1262 SDNode *N = &*--Position; 1263 // Skip dead nodes and any non-machine opcodes. 1264 if (N->use_empty() || !N->isMachineOpcode()) 1265 continue; 1266 1267 int OffsetOpIdx; 1268 int BaseOpIdx; 1269 1270 // Only attempt this optimisation for I-type loads and S-type stores. 1271 switch (N->getMachineOpcode()) { 1272 default: 1273 continue; 1274 case RISCV::LB: 1275 case RISCV::LH: 1276 case RISCV::LW: 1277 case RISCV::LBU: 1278 case RISCV::LHU: 1279 case RISCV::LWU: 1280 case RISCV::LD: 1281 case RISCV::FLH: 1282 case RISCV::FLW: 1283 case RISCV::FLD: 1284 BaseOpIdx = 0; 1285 OffsetOpIdx = 1; 1286 break; 1287 case RISCV::SB: 1288 case RISCV::SH: 1289 case RISCV::SW: 1290 case RISCV::SD: 1291 case RISCV::FSH: 1292 case RISCV::FSW: 1293 case RISCV::FSD: 1294 BaseOpIdx = 1; 1295 OffsetOpIdx = 2; 1296 break; 1297 } 1298 1299 if (!isa<ConstantSDNode>(N->getOperand(OffsetOpIdx))) 1300 continue; 1301 1302 SDValue Base = N->getOperand(BaseOpIdx); 1303 1304 // If the base is an ADDI, we can merge it in to the load/store. 1305 if (!Base.isMachineOpcode() || Base.getMachineOpcode() != RISCV::ADDI) 1306 continue; 1307 1308 SDValue ImmOperand = Base.getOperand(1); 1309 uint64_t Offset2 = N->getConstantOperandVal(OffsetOpIdx); 1310 1311 if (auto *Const = dyn_cast<ConstantSDNode>(ImmOperand)) { 1312 int64_t Offset1 = Const->getSExtValue(); 1313 int64_t CombinedOffset = Offset1 + Offset2; 1314 if (!isInt<12>(CombinedOffset)) 1315 continue; 1316 ImmOperand = CurDAG->getTargetConstant(CombinedOffset, SDLoc(ImmOperand), 1317 ImmOperand.getValueType()); 1318 } else if (auto *GA = dyn_cast<GlobalAddressSDNode>(ImmOperand)) { 1319 // If the off1 in (addi base, off1) is a global variable's address (its 1320 // low part, really), then we can rely on the alignment of that variable 1321 // to provide a margin of safety before off1 can overflow the 12 bits. 1322 // Check if off2 falls within that margin; if so off1+off2 can't overflow. 1323 const DataLayout &DL = CurDAG->getDataLayout(); 1324 Align Alignment = GA->getGlobal()->getPointerAlignment(DL); 1325 if (Offset2 != 0 && Alignment <= Offset2) 1326 continue; 1327 int64_t Offset1 = GA->getOffset(); 1328 int64_t CombinedOffset = Offset1 + Offset2; 1329 ImmOperand = CurDAG->getTargetGlobalAddress( 1330 GA->getGlobal(), SDLoc(ImmOperand), ImmOperand.getValueType(), 1331 CombinedOffset, GA->getTargetFlags()); 1332 } else if (auto *CP = dyn_cast<ConstantPoolSDNode>(ImmOperand)) { 1333 // Ditto. 1334 Align Alignment = CP->getAlign(); 1335 if (Offset2 != 0 && Alignment <= Offset2) 1336 continue; 1337 int64_t Offset1 = CP->getOffset(); 1338 int64_t CombinedOffset = Offset1 + Offset2; 1339 ImmOperand = CurDAG->getTargetConstantPool( 1340 CP->getConstVal(), ImmOperand.getValueType(), CP->getAlign(), 1341 CombinedOffset, CP->getTargetFlags()); 1342 } else { 1343 continue; 1344 } 1345 1346 LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase: "); 1347 LLVM_DEBUG(Base->dump(CurDAG)); 1348 LLVM_DEBUG(dbgs() << "\nN: "); 1349 LLVM_DEBUG(N->dump(CurDAG)); 1350 LLVM_DEBUG(dbgs() << "\n"); 1351 1352 // Modify the offset operand of the load/store. 1353 if (BaseOpIdx == 0) // Load 1354 CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand, 1355 N->getOperand(2)); 1356 else // Store 1357 CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0), 1358 ImmOperand, N->getOperand(3)); 1359 1360 // The add-immediate may now be dead, in which case remove it. 1361 if (Base.getNode()->use_empty()) 1362 CurDAG->RemoveDeadNode(Base.getNode()); 1363 } 1364 } 1365 1366 // This pass converts a legalized DAG into a RISCV-specific DAG, ready 1367 // for instruction scheduling. 1368 FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) { 1369 return new RISCVDAGToDAGISel(TM); 1370 } 1371