1 //===-- RISCVISelDAGToDAG.cpp - A dag to dag inst selector for RISCV ------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines an instruction selector for the RISCV target. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "RISCVISelDAGToDAG.h" 14 #include "MCTargetDesc/RISCVMCTargetDesc.h" 15 #include "MCTargetDesc/RISCVMatInt.h" 16 #include "llvm/CodeGen/MachineFrameInfo.h" 17 #include "llvm/IR/IntrinsicsRISCV.h" 18 #include "llvm/Support/Alignment.h" 19 #include "llvm/Support/Debug.h" 20 #include "llvm/Support/MathExtras.h" 21 #include "llvm/Support/raw_ostream.h" 22 23 using namespace llvm; 24 25 #define DEBUG_TYPE "riscv-isel" 26 27 void RISCVDAGToDAGISel::PostprocessISelDAG() { 28 doPeepholeLoadStoreADDI(); 29 } 30 31 static SDNode *selectImm(SelectionDAG *CurDAG, const SDLoc &DL, int64_t Imm, 32 MVT XLenVT) { 33 RISCVMatInt::InstSeq Seq; 34 RISCVMatInt::generateInstSeq(Imm, XLenVT == MVT::i64, Seq); 35 36 SDNode *Result = nullptr; 37 SDValue SrcReg = CurDAG->getRegister(RISCV::X0, XLenVT); 38 for (RISCVMatInt::Inst &Inst : Seq) { 39 SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, XLenVT); 40 if (Inst.Opc == RISCV::LUI) 41 Result = CurDAG->getMachineNode(RISCV::LUI, DL, XLenVT, SDImm); 42 else 43 Result = CurDAG->getMachineNode(Inst.Opc, DL, XLenVT, SrcReg, SDImm); 44 45 // Only the first instruction has X0 as its source. 46 SrcReg = SDValue(Result, 0); 47 } 48 49 return Result; 50 } 51 52 static RISCVVLMUL getLMUL(EVT VT) { 53 switch (VT.getSizeInBits().getKnownMinValue() / 8) { 54 default: 55 llvm_unreachable("Invalid LMUL."); 56 case 1: 57 return RISCVVLMUL::LMUL_F8; 58 case 2: 59 return RISCVVLMUL::LMUL_F4; 60 case 4: 61 return RISCVVLMUL::LMUL_F2; 62 case 8: 63 return RISCVVLMUL::LMUL_1; 64 case 16: 65 return RISCVVLMUL::LMUL_2; 66 case 32: 67 return RISCVVLMUL::LMUL_4; 68 case 64: 69 return RISCVVLMUL::LMUL_8; 70 } 71 } 72 73 static unsigned getSubregIndexByEVT(EVT VT, unsigned Index) { 74 RISCVVLMUL LMUL = getLMUL(VT); 75 if (LMUL == RISCVVLMUL::LMUL_F8 || LMUL == RISCVVLMUL::LMUL_F4 || 76 LMUL == RISCVVLMUL::LMUL_F2 || LMUL == RISCVVLMUL::LMUL_1) { 77 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7, 78 "Unexpected subreg numbering"); 79 return RISCV::sub_vrm1_0 + Index; 80 } else if (LMUL == RISCVVLMUL::LMUL_2) { 81 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3, 82 "Unexpected subreg numbering"); 83 return RISCV::sub_vrm2_0 + Index; 84 } else if (LMUL == RISCVVLMUL::LMUL_4) { 85 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1, 86 "Unexpected subreg numbering"); 87 return RISCV::sub_vrm4_0 + Index; 88 } 89 llvm_unreachable("Invalid vector type."); 90 } 91 92 static SDValue createTupleImpl(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs, 93 unsigned RegClassID, unsigned SubReg0) { 94 assert(Regs.size() >= 2 && Regs.size() <= 8); 95 96 SDLoc DL(Regs[0]); 97 SmallVector<SDValue, 8> Ops; 98 99 Ops.push_back(CurDAG.getTargetConstant(RegClassID, DL, MVT::i32)); 100 101 for (unsigned I = 0; I < Regs.size(); ++I) { 102 Ops.push_back(Regs[I]); 103 Ops.push_back(CurDAG.getTargetConstant(SubReg0 + I, DL, MVT::i32)); 104 } 105 SDNode *N = 106 CurDAG.getMachineNode(TargetOpcode::REG_SEQUENCE, DL, MVT::Untyped, Ops); 107 return SDValue(N, 0); 108 } 109 110 static SDValue createM1Tuple(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs, 111 unsigned NF) { 112 static const unsigned RegClassIDs[] = { 113 RISCV::VRN2M1RegClassID, RISCV::VRN3M1RegClassID, RISCV::VRN4M1RegClassID, 114 RISCV::VRN5M1RegClassID, RISCV::VRN6M1RegClassID, RISCV::VRN7M1RegClassID, 115 RISCV::VRN8M1RegClassID}; 116 117 return createTupleImpl(CurDAG, Regs, RegClassIDs[NF - 2], RISCV::sub_vrm1_0); 118 } 119 120 static SDValue createM2Tuple(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs, 121 unsigned NF) { 122 static const unsigned RegClassIDs[] = {RISCV::VRN2M2RegClassID, 123 RISCV::VRN3M2RegClassID, 124 RISCV::VRN4M2RegClassID}; 125 126 return createTupleImpl(CurDAG, Regs, RegClassIDs[NF - 2], RISCV::sub_vrm2_0); 127 } 128 129 static SDValue createM4Tuple(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs, 130 unsigned NF) { 131 return createTupleImpl(CurDAG, Regs, RISCV::VRN2M4RegClassID, 132 RISCV::sub_vrm4_0); 133 } 134 135 static SDValue createTuple(SelectionDAG &CurDAG, ArrayRef<SDValue> Regs, 136 unsigned NF, RISCVVLMUL LMUL) { 137 switch (LMUL) { 138 default: 139 llvm_unreachable("Invalid LMUL."); 140 case RISCVVLMUL::LMUL_F8: 141 case RISCVVLMUL::LMUL_F4: 142 case RISCVVLMUL::LMUL_F2: 143 case RISCVVLMUL::LMUL_1: 144 return createM1Tuple(CurDAG, Regs, NF); 145 case RISCVVLMUL::LMUL_2: 146 return createM2Tuple(CurDAG, Regs, NF); 147 case RISCVVLMUL::LMUL_4: 148 return createM4Tuple(CurDAG, Regs, NF); 149 } 150 } 151 152 void RISCVDAGToDAGISel::selectVLSEG(SDNode *Node, unsigned IntNo, 153 bool IsStrided) { 154 SDLoc DL(Node); 155 unsigned NF = Node->getNumValues() - 1; 156 EVT VT = Node->getValueType(0); 157 unsigned ScalarSize = VT.getScalarSizeInBits(); 158 MVT XLenVT = Subtarget->getXLenVT(); 159 RISCVVLMUL LMUL = getLMUL(VT); 160 SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT); 161 SmallVector<SDValue, 5> Operands; 162 Operands.push_back(Node->getOperand(2)); // Base pointer. 163 if (IsStrided) { 164 Operands.push_back(Node->getOperand(3)); // Stride. 165 Operands.push_back(Node->getOperand(4)); // VL. 166 } else { 167 Operands.push_back(Node->getOperand(3)); // VL. 168 } 169 Operands.push_back(SEW); 170 Operands.push_back(Node->getOperand(0)); // Chain. 171 const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo( 172 IntNo, ScalarSize, static_cast<unsigned>(LMUL)); 173 SDNode *Load = 174 CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, MVT::Other, Operands); 175 SDValue SuperReg = SDValue(Load, 0); 176 for (unsigned I = 0; I < NF; ++I) 177 ReplaceUses(SDValue(Node, I), 178 CurDAG->getTargetExtractSubreg(getSubregIndexByEVT(VT, I), DL, 179 VT, SuperReg)); 180 181 ReplaceUses(SDValue(Node, NF), SDValue(Load, 1)); 182 CurDAG->RemoveDeadNode(Node); 183 } 184 185 void RISCVDAGToDAGISel::selectVLSEGMask(SDNode *Node, unsigned IntNo, 186 bool IsStrided) { 187 SDLoc DL(Node); 188 unsigned NF = Node->getNumValues() - 1; 189 EVT VT = Node->getValueType(0); 190 unsigned ScalarSize = VT.getScalarSizeInBits(); 191 MVT XLenVT = Subtarget->getXLenVT(); 192 RISCVVLMUL LMUL = getLMUL(VT); 193 SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT); 194 SmallVector<SDValue, 8> Regs(Node->op_begin() + 2, Node->op_begin() + 2 + NF); 195 SDValue MaskedOff = createTuple(*CurDAG, Regs, NF, LMUL); 196 SmallVector<SDValue, 7> Operands; 197 Operands.push_back(MaskedOff); 198 Operands.push_back(Node->getOperand(NF + 2)); // Base pointer. 199 if (IsStrided) { 200 Operands.push_back(Node->getOperand(NF + 3)); // Stride. 201 Operands.push_back(Node->getOperand(NF + 4)); // Mask. 202 Operands.push_back(Node->getOperand(NF + 5)); // VL. 203 } else { 204 Operands.push_back(Node->getOperand(NF + 3)); // Mask. 205 Operands.push_back(Node->getOperand(NF + 4)); // VL. 206 } 207 Operands.push_back(SEW); 208 Operands.push_back(Node->getOperand(0)); /// Chain. 209 const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo( 210 IntNo, ScalarSize, static_cast<unsigned>(LMUL)); 211 SDNode *Load = 212 CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, MVT::Other, Operands); 213 SDValue SuperReg = SDValue(Load, 0); 214 for (unsigned I = 0; I < NF; ++I) 215 ReplaceUses(SDValue(Node, I), 216 CurDAG->getTargetExtractSubreg(getSubregIndexByEVT(VT, I), DL, 217 VT, SuperReg)); 218 219 ReplaceUses(SDValue(Node, NF), SDValue(Load, 1)); 220 CurDAG->RemoveDeadNode(Node); 221 } 222 223 void RISCVDAGToDAGISel::selectVSSEG(SDNode *Node, unsigned IntNo, 224 bool IsStrided) { 225 SDLoc DL(Node); 226 unsigned NF = Node->getNumOperands() - 4; 227 if (IsStrided) 228 NF--; 229 EVT VT = Node->getOperand(2)->getValueType(0); 230 unsigned ScalarSize = VT.getScalarSizeInBits(); 231 MVT XLenVT = Subtarget->getXLenVT(); 232 RISCVVLMUL LMUL = getLMUL(VT); 233 SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT); 234 SmallVector<SDValue, 8> Regs(Node->op_begin() + 2, Node->op_begin() + 2 + NF); 235 SDValue StoreVal = createTuple(*CurDAG, Regs, NF, LMUL); 236 SmallVector<SDValue, 6> Operands; 237 Operands.push_back(StoreVal); 238 Operands.push_back(Node->getOperand(2 + NF)); // Base pointer. 239 if (IsStrided) { 240 Operands.push_back(Node->getOperand(3 + NF)); // Stride. 241 Operands.push_back(Node->getOperand(4 + NF)); // VL. 242 } else { 243 Operands.push_back(Node->getOperand(3 + NF)); // VL. 244 } 245 Operands.push_back(SEW); 246 Operands.push_back(Node->getOperand(0)); // Chain. 247 const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo( 248 IntNo, ScalarSize, static_cast<unsigned>(LMUL)); 249 SDNode *Store = 250 CurDAG->getMachineNode(P->Pseudo, DL, Node->getValueType(0), Operands); 251 ReplaceNode(Node, Store); 252 } 253 254 void RISCVDAGToDAGISel::selectVSSEGMask(SDNode *Node, unsigned IntNo, 255 bool IsStrided) { 256 SDLoc DL(Node); 257 unsigned NF = Node->getNumOperands() - 5; 258 if (IsStrided) 259 NF--; 260 EVT VT = Node->getOperand(2)->getValueType(0); 261 unsigned ScalarSize = VT.getScalarSizeInBits(); 262 MVT XLenVT = Subtarget->getXLenVT(); 263 RISCVVLMUL LMUL = getLMUL(VT); 264 SDValue SEW = CurDAG->getTargetConstant(ScalarSize, DL, XLenVT); 265 SmallVector<SDValue, 8> Regs(Node->op_begin() + 2, Node->op_begin() + 2 + NF); 266 SDValue StoreVal = createTuple(*CurDAG, Regs, NF, LMUL); 267 SmallVector<SDValue, 7> Operands; 268 Operands.push_back(StoreVal); 269 Operands.push_back(Node->getOperand(2 + NF)); // Base pointer. 270 if (IsStrided) { 271 Operands.push_back(Node->getOperand(3 + NF)); // Stride. 272 Operands.push_back(Node->getOperand(4 + NF)); // Mask. 273 Operands.push_back(Node->getOperand(5 + NF)); // VL. 274 } else { 275 Operands.push_back(Node->getOperand(3 + NF)); // Mask. 276 Operands.push_back(Node->getOperand(4 + NF)); // VL. 277 } 278 Operands.push_back(SEW); 279 Operands.push_back(Node->getOperand(0)); // Chain. 280 const RISCVZvlssegTable::RISCVZvlsseg *P = RISCVZvlssegTable::getPseudo( 281 IntNo, ScalarSize, static_cast<unsigned>(LMUL)); 282 SDNode *Store = 283 CurDAG->getMachineNode(P->Pseudo, DL, Node->getValueType(0), Operands); 284 ReplaceNode(Node, Store); 285 } 286 287 void RISCVDAGToDAGISel::Select(SDNode *Node) { 288 // If we have a custom node, we have already selected. 289 if (Node->isMachineOpcode()) { 290 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n"); 291 Node->setNodeId(-1); 292 return; 293 } 294 295 // Instruction Selection not handled by the auto-generated tablegen selection 296 // should be handled here. 297 unsigned Opcode = Node->getOpcode(); 298 MVT XLenVT = Subtarget->getXLenVT(); 299 SDLoc DL(Node); 300 EVT VT = Node->getValueType(0); 301 302 switch (Opcode) { 303 case ISD::ADD: { 304 // Optimize (add r, imm) to (addi (addi r, imm0) imm1) if applicable. The 305 // immediate must be in specific ranges and have a single use. 306 if (auto *ConstOp = dyn_cast<ConstantSDNode>(Node->getOperand(1))) { 307 if (!(ConstOp->hasOneUse())) 308 break; 309 // The imm must be in range [-4096,-2049] or [2048,4094]. 310 int64_t Imm = ConstOp->getSExtValue(); 311 if (!(-4096 <= Imm && Imm <= -2049) && !(2048 <= Imm && Imm <= 4094)) 312 break; 313 // Break the imm to imm0+imm1. 314 EVT VT = Node->getValueType(0); 315 const SDValue ImmOp0 = CurDAG->getTargetConstant(Imm - Imm / 2, DL, VT); 316 const SDValue ImmOp1 = CurDAG->getTargetConstant(Imm / 2, DL, VT); 317 auto *NodeAddi0 = CurDAG->getMachineNode(RISCV::ADDI, DL, VT, 318 Node->getOperand(0), ImmOp0); 319 auto *NodeAddi1 = CurDAG->getMachineNode(RISCV::ADDI, DL, VT, 320 SDValue(NodeAddi0, 0), ImmOp1); 321 ReplaceNode(Node, NodeAddi1); 322 return; 323 } 324 break; 325 } 326 case ISD::Constant: { 327 auto ConstNode = cast<ConstantSDNode>(Node); 328 if (VT == XLenVT && ConstNode->isNullValue()) { 329 SDValue New = 330 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, RISCV::X0, XLenVT); 331 ReplaceNode(Node, New.getNode()); 332 return; 333 } 334 int64_t Imm = ConstNode->getSExtValue(); 335 if (XLenVT == MVT::i64) { 336 ReplaceNode(Node, selectImm(CurDAG, DL, Imm, XLenVT)); 337 return; 338 } 339 break; 340 } 341 case ISD::FrameIndex: { 342 SDValue Imm = CurDAG->getTargetConstant(0, DL, XLenVT); 343 int FI = cast<FrameIndexSDNode>(Node)->getIndex(); 344 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); 345 ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm)); 346 return; 347 } 348 case ISD::INTRINSIC_W_CHAIN: { 349 unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue(); 350 switch (IntNo) { 351 // By default we do not custom select any intrinsic. 352 default: 353 break; 354 355 case Intrinsic::riscv_vsetvli: { 356 if (!Subtarget->hasStdExtV()) 357 break; 358 359 assert(Node->getNumOperands() == 5); 360 361 RISCVVSEW VSEW = 362 static_cast<RISCVVSEW>(Node->getConstantOperandVal(3) & 0x7); 363 RISCVVLMUL VLMul = 364 static_cast<RISCVVLMUL>(Node->getConstantOperandVal(4) & 0x7); 365 366 unsigned VTypeI = RISCVVType::encodeVTYPE( 367 VLMul, VSEW, /*TailAgnostic*/ true, /*MaskAgnostic*/ false); 368 SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT); 369 370 SDValue VLOperand = Node->getOperand(2); 371 if (auto *C = dyn_cast<ConstantSDNode>(VLOperand)) { 372 if (C->isNullValue()) { 373 VLOperand = SDValue( 374 CurDAG->getMachineNode(RISCV::ADDI, DL, XLenVT, 375 CurDAG->getRegister(RISCV::X0, XLenVT), 376 CurDAG->getTargetConstant(0, DL, XLenVT)), 377 0); 378 } 379 } 380 381 ReplaceNode(Node, 382 CurDAG->getMachineNode(RISCV::PseudoVSETVLI, DL, XLenVT, 383 MVT::Other, VLOperand, VTypeIOp, 384 /* Chain */ Node->getOperand(0))); 385 return; 386 } 387 case Intrinsic::riscv_vsetvlimax: { 388 if (!Subtarget->hasStdExtV()) 389 break; 390 391 assert(Node->getNumOperands() == 4); 392 393 RISCVVSEW VSEW = 394 static_cast<RISCVVSEW>(Node->getConstantOperandVal(2) & 0x7); 395 RISCVVLMUL VLMul = 396 static_cast<RISCVVLMUL>(Node->getConstantOperandVal(3) & 0x7); 397 398 unsigned VTypeI = RISCVVType::encodeVTYPE( 399 VLMul, VSEW, /*TailAgnostic*/ true, /*MaskAgnostic*/ false); 400 SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT); 401 402 SDValue VLOperand = CurDAG->getRegister(RISCV::X0, XLenVT); 403 ReplaceNode(Node, 404 CurDAG->getMachineNode(RISCV::PseudoVSETVLI, DL, XLenVT, 405 MVT::Other, VLOperand, VTypeIOp, 406 /* Chain */ Node->getOperand(0))); 407 return; 408 } 409 case Intrinsic::riscv_vlseg2: 410 case Intrinsic::riscv_vlseg3: 411 case Intrinsic::riscv_vlseg4: 412 case Intrinsic::riscv_vlseg5: 413 case Intrinsic::riscv_vlseg6: 414 case Intrinsic::riscv_vlseg7: 415 case Intrinsic::riscv_vlseg8: { 416 selectVLSEG(Node, IntNo, /*IsStrided=*/false); 417 return; 418 } 419 case Intrinsic::riscv_vlseg2_mask: 420 case Intrinsic::riscv_vlseg3_mask: 421 case Intrinsic::riscv_vlseg4_mask: 422 case Intrinsic::riscv_vlseg5_mask: 423 case Intrinsic::riscv_vlseg6_mask: 424 case Intrinsic::riscv_vlseg7_mask: 425 case Intrinsic::riscv_vlseg8_mask: { 426 selectVLSEGMask(Node, IntNo, /*IsStrided=*/false); 427 return; 428 } 429 case Intrinsic::riscv_vlsseg2: 430 case Intrinsic::riscv_vlsseg3: 431 case Intrinsic::riscv_vlsseg4: 432 case Intrinsic::riscv_vlsseg5: 433 case Intrinsic::riscv_vlsseg6: 434 case Intrinsic::riscv_vlsseg7: 435 case Intrinsic::riscv_vlsseg8: { 436 selectVLSEG(Node, IntNo, /*IsStrided=*/true); 437 return; 438 } 439 case Intrinsic::riscv_vlsseg2_mask: 440 case Intrinsic::riscv_vlsseg3_mask: 441 case Intrinsic::riscv_vlsseg4_mask: 442 case Intrinsic::riscv_vlsseg5_mask: 443 case Intrinsic::riscv_vlsseg6_mask: 444 case Intrinsic::riscv_vlsseg7_mask: 445 case Intrinsic::riscv_vlsseg8_mask: { 446 selectVLSEGMask(Node, IntNo, /*IsStrided=*/true); 447 return; 448 } 449 } 450 break; 451 } 452 case ISD::INTRINSIC_VOID: { 453 unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue(); 454 switch (IntNo) { 455 case Intrinsic::riscv_vsseg2: 456 case Intrinsic::riscv_vsseg3: 457 case Intrinsic::riscv_vsseg4: 458 case Intrinsic::riscv_vsseg5: 459 case Intrinsic::riscv_vsseg6: 460 case Intrinsic::riscv_vsseg7: 461 case Intrinsic::riscv_vsseg8: { 462 selectVSSEG(Node, IntNo, /*IsStrided=*/false); 463 return; 464 } 465 case Intrinsic::riscv_vsseg2_mask: 466 case Intrinsic::riscv_vsseg3_mask: 467 case Intrinsic::riscv_vsseg4_mask: 468 case Intrinsic::riscv_vsseg5_mask: 469 case Intrinsic::riscv_vsseg6_mask: 470 case Intrinsic::riscv_vsseg7_mask: 471 case Intrinsic::riscv_vsseg8_mask: { 472 selectVSSEGMask(Node, IntNo, /*IsStrided=*/false); 473 return; 474 } 475 case Intrinsic::riscv_vssseg2: 476 case Intrinsic::riscv_vssseg3: 477 case Intrinsic::riscv_vssseg4: 478 case Intrinsic::riscv_vssseg5: 479 case Intrinsic::riscv_vssseg6: 480 case Intrinsic::riscv_vssseg7: 481 case Intrinsic::riscv_vssseg8: { 482 selectVSSEG(Node, IntNo, /*IsStrided=*/true); 483 return; 484 } 485 case Intrinsic::riscv_vssseg2_mask: 486 case Intrinsic::riscv_vssseg3_mask: 487 case Intrinsic::riscv_vssseg4_mask: 488 case Intrinsic::riscv_vssseg5_mask: 489 case Intrinsic::riscv_vssseg6_mask: 490 case Intrinsic::riscv_vssseg7_mask: 491 case Intrinsic::riscv_vssseg8_mask: { 492 selectVSSEGMask(Node, IntNo, /*IsStrided=*/true); 493 return; 494 } 495 } 496 break; 497 } 498 } 499 500 // Select the default instruction. 501 SelectCode(Node); 502 } 503 504 bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand( 505 const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) { 506 switch (ConstraintID) { 507 case InlineAsm::Constraint_m: 508 // We just support simple memory operands that have a single address 509 // operand and need no special handling. 510 OutOps.push_back(Op); 511 return false; 512 case InlineAsm::Constraint_A: 513 OutOps.push_back(Op); 514 return false; 515 default: 516 break; 517 } 518 519 return true; 520 } 521 522 bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) { 523 if (auto FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 524 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT()); 525 return true; 526 } 527 return false; 528 } 529 530 // Match (srl (and val, mask), imm) where the result would be a 531 // zero-extended 32-bit integer. i.e. the mask is 0xffffffff or the result 532 // is equivalent to this (SimplifyDemandedBits may have removed lower bits 533 // from the mask that aren't necessary due to the right-shifting). 534 bool RISCVDAGToDAGISel::MatchSRLIW(SDNode *N) const { 535 assert(N->getOpcode() == ISD::SRL); 536 assert(N->getOperand(0).getOpcode() == ISD::AND); 537 assert(isa<ConstantSDNode>(N->getOperand(1))); 538 assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1))); 539 540 // The IsRV64 predicate is checked after PatFrag predicates so we can get 541 // here even on RV32. 542 if (!Subtarget->is64Bit()) 543 return false; 544 545 SDValue And = N->getOperand(0); 546 uint64_t ShAmt = N->getConstantOperandVal(1); 547 uint64_t Mask = And.getConstantOperandVal(1); 548 return (Mask | maskTrailingOnes<uint64_t>(ShAmt)) == 0xffffffff; 549 } 550 551 // Check that it is a SLOI (Shift Left Ones Immediate). A PatFrag has already 552 // determined it has the right structure: 553 // 554 // (OR (SHL RS1, VC2), VC1) 555 // 556 // Check that VC1, the mask used to fill with ones, is compatible 557 // with VC2, the shamt: 558 // 559 // VC1 == maskTrailingOnes(VC2) 560 // 561 bool RISCVDAGToDAGISel::MatchSLOI(SDNode *N) const { 562 assert(N->getOpcode() == ISD::OR); 563 assert(N->getOperand(0).getOpcode() == ISD::SHL); 564 assert(isa<ConstantSDNode>(N->getOperand(1))); 565 assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1))); 566 567 SDValue Shl = N->getOperand(0); 568 if (Subtarget->is64Bit()) { 569 uint64_t VC1 = N->getConstantOperandVal(1); 570 uint64_t VC2 = Shl.getConstantOperandVal(1); 571 return VC1 == maskTrailingOnes<uint64_t>(VC2); 572 } 573 574 uint32_t VC1 = N->getConstantOperandVal(1); 575 uint32_t VC2 = Shl.getConstantOperandVal(1); 576 return VC1 == maskTrailingOnes<uint32_t>(VC2); 577 } 578 579 // Check that it is a SROI (Shift Right Ones Immediate). A PatFrag has already 580 // determined it has the right structure: 581 // 582 // (OR (SRL RS1, VC2), VC1) 583 // 584 // Check that VC1, the mask used to fill with ones, is compatible 585 // with VC2, the shamt: 586 // 587 // VC1 == maskLeadingOnes(VC2) 588 // 589 bool RISCVDAGToDAGISel::MatchSROI(SDNode *N) const { 590 assert(N->getOpcode() == ISD::OR); 591 assert(N->getOperand(0).getOpcode() == ISD::SRL); 592 assert(isa<ConstantSDNode>(N->getOperand(1))); 593 assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1))); 594 595 SDValue Srl = N->getOperand(0); 596 if (Subtarget->is64Bit()) { 597 uint64_t VC1 = N->getConstantOperandVal(1); 598 uint64_t VC2 = Srl.getConstantOperandVal(1); 599 return VC1 == maskLeadingOnes<uint64_t>(VC2); 600 } 601 602 uint32_t VC1 = N->getConstantOperandVal(1); 603 uint32_t VC2 = Srl.getConstantOperandVal(1); 604 return VC1 == maskLeadingOnes<uint32_t>(VC2); 605 } 606 607 // Check that it is a SROIW (Shift Right Ones Immediate i32 on RV64). A PatFrag 608 // has already determined it has the right structure: 609 // 610 // (OR (SRL RS1, VC2), VC1) 611 // 612 // and then we check that VC1, the mask used to fill with ones, is compatible 613 // with VC2, the shamt: 614 // 615 // VC2 < 32 616 // VC1 == maskTrailingZeros<uint64_t>(32 - VC2) 617 // 618 bool RISCVDAGToDAGISel::MatchSROIW(SDNode *N) const { 619 assert(N->getOpcode() == ISD::OR); 620 assert(N->getOperand(0).getOpcode() == ISD::SRL); 621 assert(isa<ConstantSDNode>(N->getOperand(1))); 622 assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1))); 623 624 // The IsRV64 predicate is checked after PatFrag predicates so we can get 625 // here even on RV32. 626 if (!Subtarget->is64Bit()) 627 return false; 628 629 SDValue Srl = N->getOperand(0); 630 uint64_t VC1 = N->getConstantOperandVal(1); 631 uint64_t VC2 = Srl.getConstantOperandVal(1); 632 633 // Immediate range should be enforced by uimm5 predicate. 634 assert(VC2 < 32 && "Unexpected immediate"); 635 return VC1 == maskTrailingZeros<uint64_t>(32 - VC2); 636 } 637 638 // Check that it is a SLLIUW (Shift Logical Left Immediate Unsigned i32 639 // on RV64). 640 // SLLIUW is the same as SLLI except for the fact that it clears the bits 641 // XLEN-1:32 of the input RS1 before shifting. 642 // A PatFrag has already checked that it has the right structure: 643 // 644 // (AND (SHL RS1, VC2), VC1) 645 // 646 // We check that VC2, the shamt is less than 32, otherwise the pattern is 647 // exactly the same as SLLI and we give priority to that. 648 // Eventually we check that VC1, the mask used to clear the upper 32 bits 649 // of RS1, is correct: 650 // 651 // VC1 == (0xFFFFFFFF << VC2) 652 // 653 bool RISCVDAGToDAGISel::MatchSLLIUW(SDNode *N) const { 654 assert(N->getOpcode() == ISD::AND); 655 assert(N->getOperand(0).getOpcode() == ISD::SHL); 656 assert(isa<ConstantSDNode>(N->getOperand(1))); 657 assert(isa<ConstantSDNode>(N->getOperand(0).getOperand(1))); 658 659 // The IsRV64 predicate is checked after PatFrag predicates so we can get 660 // here even on RV32. 661 if (!Subtarget->is64Bit()) 662 return false; 663 664 SDValue Shl = N->getOperand(0); 665 uint64_t VC1 = N->getConstantOperandVal(1); 666 uint64_t VC2 = Shl.getConstantOperandVal(1); 667 668 // Immediate range should be enforced by uimm5 predicate. 669 assert(VC2 < 32 && "Unexpected immediate"); 670 return VC1 == ((uint64_t)0xFFFFFFFF << VC2); 671 } 672 673 bool RISCVDAGToDAGISel::selectVSplat(SDValue N, SDValue &SplatVal) { 674 if (N.getOpcode() != ISD::SPLAT_VECTOR && 675 N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64) 676 return false; 677 SplatVal = N.getOperand(0); 678 return true; 679 } 680 681 bool RISCVDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &SplatVal) { 682 if ((N.getOpcode() != ISD::SPLAT_VECTOR && 683 N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64) || 684 !isa<ConstantSDNode>(N.getOperand(0))) 685 return false; 686 687 int64_t SplatImm = cast<ConstantSDNode>(N.getOperand(0))->getSExtValue(); 688 689 // Both ISD::SPLAT_VECTOR and RISCVISD::SPLAT_VECTOR_I64 share semantics when 690 // the operand type is wider than the resulting vector element type: an 691 // implicit truncation first takes place. Therefore, perform a manual 692 // truncation/sign-extension in order to ignore any truncated bits and catch 693 // any zero-extended immediate. 694 // For example, we wish to match (i8 -1) -> (XLenVT 255) as a simm5 by first 695 // sign-extending to (XLenVT -1). 696 auto XLenVT = Subtarget->getXLenVT(); 697 assert(XLenVT == N.getOperand(0).getSimpleValueType() && 698 "Unexpected splat operand type"); 699 auto EltVT = N.getValueType().getVectorElementType(); 700 if (EltVT.bitsLT(XLenVT)) { 701 SplatImm = SignExtend64(SplatImm, EltVT.getSizeInBits()); 702 } 703 704 if (!isInt<5>(SplatImm)) 705 return false; 706 707 SplatVal = CurDAG->getTargetConstant(SplatImm, SDLoc(N), XLenVT); 708 return true; 709 } 710 711 bool RISCVDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &SplatVal) { 712 if ((N.getOpcode() != ISD::SPLAT_VECTOR && 713 N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64) || 714 !isa<ConstantSDNode>(N.getOperand(0))) 715 return false; 716 717 int64_t SplatImm = cast<ConstantSDNode>(N.getOperand(0))->getSExtValue(); 718 719 if (!isUInt<5>(SplatImm)) 720 return false; 721 722 SplatVal = 723 CurDAG->getTargetConstant(SplatImm, SDLoc(N), Subtarget->getXLenVT()); 724 725 return true; 726 } 727 728 // Merge an ADDI into the offset of a load/store instruction where possible. 729 // (load (addi base, off1), off2) -> (load base, off1+off2) 730 // (store val, (addi base, off1), off2) -> (store val, base, off1+off2) 731 // This is possible when off1+off2 fits a 12-bit immediate. 732 void RISCVDAGToDAGISel::doPeepholeLoadStoreADDI() { 733 SelectionDAG::allnodes_iterator Position(CurDAG->getRoot().getNode()); 734 ++Position; 735 736 while (Position != CurDAG->allnodes_begin()) { 737 SDNode *N = &*--Position; 738 // Skip dead nodes and any non-machine opcodes. 739 if (N->use_empty() || !N->isMachineOpcode()) 740 continue; 741 742 int OffsetOpIdx; 743 int BaseOpIdx; 744 745 // Only attempt this optimisation for I-type loads and S-type stores. 746 switch (N->getMachineOpcode()) { 747 default: 748 continue; 749 case RISCV::LB: 750 case RISCV::LH: 751 case RISCV::LW: 752 case RISCV::LBU: 753 case RISCV::LHU: 754 case RISCV::LWU: 755 case RISCV::LD: 756 case RISCV::FLH: 757 case RISCV::FLW: 758 case RISCV::FLD: 759 BaseOpIdx = 0; 760 OffsetOpIdx = 1; 761 break; 762 case RISCV::SB: 763 case RISCV::SH: 764 case RISCV::SW: 765 case RISCV::SD: 766 case RISCV::FSH: 767 case RISCV::FSW: 768 case RISCV::FSD: 769 BaseOpIdx = 1; 770 OffsetOpIdx = 2; 771 break; 772 } 773 774 if (!isa<ConstantSDNode>(N->getOperand(OffsetOpIdx))) 775 continue; 776 777 SDValue Base = N->getOperand(BaseOpIdx); 778 779 // If the base is an ADDI, we can merge it in to the load/store. 780 if (!Base.isMachineOpcode() || Base.getMachineOpcode() != RISCV::ADDI) 781 continue; 782 783 SDValue ImmOperand = Base.getOperand(1); 784 uint64_t Offset2 = N->getConstantOperandVal(OffsetOpIdx); 785 786 if (auto Const = dyn_cast<ConstantSDNode>(ImmOperand)) { 787 int64_t Offset1 = Const->getSExtValue(); 788 int64_t CombinedOffset = Offset1 + Offset2; 789 if (!isInt<12>(CombinedOffset)) 790 continue; 791 ImmOperand = CurDAG->getTargetConstant(CombinedOffset, SDLoc(ImmOperand), 792 ImmOperand.getValueType()); 793 } else if (auto GA = dyn_cast<GlobalAddressSDNode>(ImmOperand)) { 794 // If the off1 in (addi base, off1) is a global variable's address (its 795 // low part, really), then we can rely on the alignment of that variable 796 // to provide a margin of safety before off1 can overflow the 12 bits. 797 // Check if off2 falls within that margin; if so off1+off2 can't overflow. 798 const DataLayout &DL = CurDAG->getDataLayout(); 799 Align Alignment = GA->getGlobal()->getPointerAlignment(DL); 800 if (Offset2 != 0 && Alignment <= Offset2) 801 continue; 802 int64_t Offset1 = GA->getOffset(); 803 int64_t CombinedOffset = Offset1 + Offset2; 804 ImmOperand = CurDAG->getTargetGlobalAddress( 805 GA->getGlobal(), SDLoc(ImmOperand), ImmOperand.getValueType(), 806 CombinedOffset, GA->getTargetFlags()); 807 } else if (auto CP = dyn_cast<ConstantPoolSDNode>(ImmOperand)) { 808 // Ditto. 809 Align Alignment = CP->getAlign(); 810 if (Offset2 != 0 && Alignment <= Offset2) 811 continue; 812 int64_t Offset1 = CP->getOffset(); 813 int64_t CombinedOffset = Offset1 + Offset2; 814 ImmOperand = CurDAG->getTargetConstantPool( 815 CP->getConstVal(), ImmOperand.getValueType(), CP->getAlign(), 816 CombinedOffset, CP->getTargetFlags()); 817 } else { 818 continue; 819 } 820 821 LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase: "); 822 LLVM_DEBUG(Base->dump(CurDAG)); 823 LLVM_DEBUG(dbgs() << "\nN: "); 824 LLVM_DEBUG(N->dump(CurDAG)); 825 LLVM_DEBUG(dbgs() << "\n"); 826 827 // Modify the offset operand of the load/store. 828 if (BaseOpIdx == 0) // Load 829 CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand, 830 N->getOperand(2)); 831 else // Store 832 CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0), 833 ImmOperand, N->getOperand(3)); 834 835 // The add-immediate may now be dead, in which case remove it. 836 if (Base.getNode()->use_empty()) 837 CurDAG->RemoveDeadNode(Base.getNode()); 838 } 839 } 840 841 // This pass converts a legalized DAG into a RISCV-specific DAG, ready 842 // for instruction scheduling. 843 FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) { 844 return new RISCVDAGToDAGISel(TM); 845 } 846