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