LLVM 24.0.0git
RISCVISelDAGToDAG.cpp
Go to the documentation of this file.
1//===-- RISCVISelDAGToDAG.cpp - A dag to dag inst selector for RISC-V -----===//
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 RISC-V target.
10//
11//===----------------------------------------------------------------------===//
12
13#include "RISCVISelDAGToDAG.h"
17#include "RISCVISelLowering.h"
18#include "RISCVInstrInfo.h"
22#include "llvm/IR/IntrinsicsRISCV.h"
24#include "llvm/Support/Debug.h"
27
28using namespace llvm;
29
30#define DEBUG_TYPE "riscv-isel"
31#define PASS_NAME "RISC-V DAG->DAG Pattern Instruction Selection"
32
34
36 "riscv-use-rematerializable-movimm", cl::Hidden,
37 cl::desc("Use a rematerializable pseudoinstruction for 2 instruction "
38 "constant materialization"),
39 cl::init(false));
40
41#define GET_DAGISEL_BODY RISCVDAGToDAGISel
42#include "RISCVGenDAGISel.inc"
43
45 SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end();
46
47 bool MadeChange = false;
48 while (Position != CurDAG->allnodes_begin()) {
49 SDNode *N = &*--Position;
50 if (N->use_empty())
51 continue;
52
53 SDValue Result;
54 switch (N->getOpcode()) {
55 case ISD::SPLAT_VECTOR: {
56 if (Subtarget->hasStdExtP())
57 break;
58 // Convert integer SPLAT_VECTOR to VMV_V_X_VL and floating-point
59 // SPLAT_VECTOR to VFMV_V_F_VL to reduce isel burden.
60 MVT VT = N->getSimpleValueType(0);
61 unsigned Opc =
62 VT.isInteger() ? RISCVISD::VMV_V_X_VL : RISCVISD::VFMV_V_F_VL;
63 SDLoc DL(N);
64 SDValue VL = CurDAG->getRegister(RISCV::X0, Subtarget->getXLenVT());
65 SDValue Src = N->getOperand(0);
66 if (VT.isInteger())
67 Src = CurDAG->getNode(ISD::ANY_EXTEND, DL, Subtarget->getXLenVT(),
68 N->getOperand(0));
69 Result = CurDAG->getNode(Opc, DL, VT, CurDAG->getUNDEF(VT), Src, VL);
70 break;
71 }
72 case RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL: {
73 // Lower SPLAT_VECTOR_SPLIT_I64 to two scalar stores and a stride 0 vector
74 // load. Done after lowering and combining so that we have a chance to
75 // optimize this to VMV_V_X_VL when the upper bits aren't needed.
76 assert(N->getNumOperands() == 4 && "Unexpected number of operands");
77 MVT VT = N->getSimpleValueType(0);
78 SDValue Passthru = N->getOperand(0);
79 SDValue Lo = N->getOperand(1);
80 SDValue Hi = N->getOperand(2);
81 SDValue VL = N->getOperand(3);
82 assert(VT.getVectorElementType() == MVT::i64 && VT.isScalableVector() &&
83 Lo.getValueType() == MVT::i32 && Hi.getValueType() == MVT::i32 &&
84 "Unexpected VTs!");
85 MachineFunction &MF = CurDAG->getMachineFunction();
86 SDLoc DL(N);
87
88 // Create temporary stack for each expanding node.
89 SDValue StackSlot =
90 CurDAG->CreateStackTemporary(TypeSize::getFixed(8), Align(8));
91 int FI = cast<FrameIndexSDNode>(StackSlot.getNode())->getIndex();
93
94 SDValue Chain = CurDAG->getEntryNode();
95 Lo = CurDAG->getStore(Chain, DL, Lo, StackSlot, MPI, Align(8));
96
97 SDValue OffsetSlot =
98 CurDAG->getMemBasePlusOffset(StackSlot, TypeSize::getFixed(4), DL);
99 Hi = CurDAG->getStore(Chain, DL, Hi, OffsetSlot, MPI.getWithOffset(4),
100 Align(8));
101
102 Chain = CurDAG->getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
103
104 SDVTList VTs = CurDAG->getVTList({VT, MVT::Other});
105 SDValue IntID =
106 CurDAG->getTargetConstant(Intrinsic::riscv_vlse, DL, MVT::i64);
107 SDValue Ops[] = {Chain,
108 IntID,
109 Passthru,
110 StackSlot,
111 CurDAG->getRegister(RISCV::X0, MVT::i64),
112 VL};
113
114 Result = CurDAG->getMemIntrinsicNode(ISD::INTRINSIC_W_CHAIN, DL, VTs, Ops,
115 MVT::i64, MPI, Align(8),
117 break;
118 }
119 case ISD::FP_EXTEND: {
120 // We only have vector patterns for riscv_fpextend_vl in isel.
121 SDLoc DL(N);
122 MVT VT = N->getSimpleValueType(0);
123 if (!VT.isVector())
124 break;
125 SDValue VLMAX = CurDAG->getRegister(RISCV::X0, Subtarget->getXLenVT());
126 SDValue TrueMask = CurDAG->getNode(
127 RISCVISD::VMSET_VL, DL, VT.changeVectorElementType(MVT::i1), VLMAX);
128 Result = CurDAG->getNode(RISCVISD::FP_EXTEND_VL, DL, VT, N->getOperand(0),
129 TrueMask, VLMAX);
130 break;
131 }
132 }
133
134 if (Result) {
135 LLVM_DEBUG(dbgs() << "RISC-V DAG preprocessing replacing:\nOld: ");
136 LLVM_DEBUG(N->dump(CurDAG));
137 LLVM_DEBUG(dbgs() << "\nNew: ");
138 LLVM_DEBUG(Result->dump(CurDAG));
139 LLVM_DEBUG(dbgs() << "\n");
140
141 CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), Result);
142 MadeChange = true;
143 }
144 }
145
146 if (MadeChange)
147 CurDAG->RemoveDeadNodes();
148}
149
151 HandleSDNode Dummy(CurDAG->getRoot());
152 SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end();
153
154 bool MadeChange = false;
155 while (Position != CurDAG->allnodes_begin()) {
156 SDNode *N = &*--Position;
157 // Skip dead nodes and any non-machine opcodes.
158 if (N->use_empty() || !N->isMachineOpcode())
159 continue;
160
161 MadeChange |= doPeepholeSExtW(N);
162
163 // FIXME: This is here only because the VMerge transform doesn't
164 // know how to handle masked true inputs. Once that has been moved
165 // to post-ISEL, this can be deleted as well.
166 MadeChange |= doPeepholeMaskedRVV(cast<MachineSDNode>(N));
167 }
168
169 CurDAG->setRoot(Dummy.getValue());
170
171 // After we're done with everything else, convert IMPLICIT_DEF
172 // passthru operands to NoRegister. This is required to workaround
173 // an optimization deficiency in MachineCSE. This really should
174 // be merged back into each of the patterns (i.e. there's no good
175 // reason not to go directly to NoReg), but is being done this way
176 // to allow easy backporting.
177 MadeChange |= doPeepholeNoRegPassThru();
178
179 if (MadeChange)
180 CurDAG->RemoveDeadNodes();
181}
182
183static SDValue selectImmSeq(SelectionDAG *CurDAG, const SDLoc &DL, const MVT VT,
185 SDValue SrcReg = CurDAG->getRegister(RISCV::X0, VT);
186 for (const RISCVMatInt::Inst &Inst : Seq) {
187 SDValue SDImm = CurDAG->getSignedTargetConstant(Inst.getImm(), DL, VT);
188 SDNode *Result = nullptr;
189 switch (Inst.getOpndKind()) {
190 case RISCVMatInt::Imm:
191 Result = CurDAG->getMachineNode(Inst.getOpcode(), DL, VT, SDImm);
192 break;
194 Result = CurDAG->getMachineNode(Inst.getOpcode(), DL, VT, SrcReg,
195 CurDAG->getRegister(RISCV::X0, VT));
196 break;
198 Result = CurDAG->getMachineNode(Inst.getOpcode(), DL, VT, SrcReg, SrcReg);
199 break;
201 Result = CurDAG->getMachineNode(Inst.getOpcode(), DL, VT, SrcReg, SDImm);
202 break;
203 }
204
205 // Only the first instruction has X0 as its source.
206 SrcReg = SDValue(Result, 0);
207 }
208
209 return SrcReg;
210}
211
212static SDValue selectImm(SelectionDAG *CurDAG, const SDLoc &DL, const MVT VT,
213 int64_t Imm, const RISCVSubtarget &Subtarget) {
215
216 // Use a rematerializable pseudo instruction for short sequences if enabled.
217 if (Seq.size() == 2 && UsePseudoMovImm)
218 return SDValue(
219 CurDAG->getMachineNode(RISCV::PseudoMovImm, DL, VT,
220 CurDAG->getSignedTargetConstant(Imm, DL, VT)),
221 0);
222
223 // See if we can create this constant as (ADD (SLLI X, C), X) where X is at
224 // worst an LUI+ADDIW. This will require an extra register, but avoids a
225 // constant pool.
226 // If we have Zba we can use (ADD_UW X, (SLLI X, 32)) to handle cases where
227 // low and high 32 bits are the same and bit 31 and 63 are set.
228 if (Seq.size() > 3) {
229 unsigned ShiftAmt, AddOpc;
231 RISCVMatInt::generateTwoRegInstSeq(Imm, Subtarget, ShiftAmt, AddOpc);
232 if (!SeqLo.empty() && (SeqLo.size() + 2) < Seq.size()) {
233 SDValue Lo = selectImmSeq(CurDAG, DL, VT, SeqLo);
234
235 SDValue SLLI = SDValue(
236 CurDAG->getMachineNode(RISCV::SLLI, DL, VT, Lo,
237 CurDAG->getTargetConstant(ShiftAmt, DL, VT)),
238 0);
239 return SDValue(CurDAG->getMachineNode(AddOpc, DL, VT, Lo, SLLI), 0);
240 }
241 }
242
243 // Otherwise, use the original sequence.
244 return selectImmSeq(CurDAG, DL, VT, Seq);
245}
246
248 SDNode *Node, unsigned Log2SEW, const SDLoc &DL, unsigned CurOp,
249 bool IsMasked, bool IsStridedOrIndexed, SmallVectorImpl<SDValue> &Operands,
250 bool IsLoad, MVT *IndexVT) {
251 SDValue Chain = Node->getOperand(0);
252
253 Operands.push_back(Node->getOperand(CurOp++)); // Base pointer.
254
255 if (IsStridedOrIndexed) {
256 Operands.push_back(Node->getOperand(CurOp++)); // Index.
257 if (IndexVT)
258 *IndexVT = Operands.back()->getSimpleValueType(0);
259 }
260
261 if (IsMasked) {
262 SDValue Mask = Node->getOperand(CurOp++);
263 Operands.push_back(Mask);
264 }
265 SDValue VL;
266 selectVLOp(Node->getOperand(CurOp++), VL);
267 Operands.push_back(VL);
268
269 MVT XLenVT = Subtarget->getXLenVT();
270 SDValue SEWOp = CurDAG->getTargetConstant(Log2SEW, DL, XLenVT);
271 Operands.push_back(SEWOp);
272
273 // At the IR layer, all the masked load intrinsics have policy operands,
274 // none of the others do. All have passthru operands. For our pseudos,
275 // all loads have policy operands.
276 if (IsLoad) {
277 uint64_t Policy = RISCVVType::MASK_AGNOSTIC;
278 if (IsMasked)
279 Policy = Node->getConstantOperandVal(CurOp++);
280 SDValue PolicyOp = CurDAG->getTargetConstant(Policy, DL, XLenVT);
281 Operands.push_back(PolicyOp);
282 }
283
284 Operands.push_back(Chain); // Chain.
285}
286
287void RISCVDAGToDAGISel::selectVLSEG(SDNode *Node, unsigned NF, bool IsMasked,
288 bool IsStrided) {
289 SDLoc DL(Node);
290 MVT VT = Node->getSimpleValueType(0);
291 unsigned Log2SEW = Node->getConstantOperandVal(Node->getNumOperands() - 1);
293
294 unsigned CurOp = 2;
296
297 Operands.push_back(Node->getOperand(CurOp++));
298
299 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked, IsStrided,
300 Operands, /*IsLoad=*/true);
301
302 const RISCV::VLSEGPseudo *P =
303 RISCV::getVLSEGPseudo(NF, IsMasked, IsStrided, /*FF*/ false, Log2SEW,
304 static_cast<unsigned>(LMUL));
306 CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, MVT::Other, Operands);
307
308 CurDAG->setNodeMemRefs(Load, {cast<MemSDNode>(Node)->getMemOperand()});
309
312 CurDAG->RemoveDeadNode(Node);
313}
314
316 bool IsMasked) {
317 SDLoc DL(Node);
318 MVT VT = Node->getSimpleValueType(0);
319 MVT XLenVT = Subtarget->getXLenVT();
320 unsigned Log2SEW = Node->getConstantOperandVal(Node->getNumOperands() - 1);
322
323 unsigned CurOp = 2;
325
326 Operands.push_back(Node->getOperand(CurOp++));
327
328 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked,
329 /*IsStridedOrIndexed*/ false, Operands,
330 /*IsLoad=*/true);
331
332 const RISCV::VLSEGPseudo *P =
333 RISCV::getVLSEGPseudo(NF, IsMasked, /*Strided*/ false, /*FF*/ true,
334 Log2SEW, static_cast<unsigned>(LMUL));
335 MachineSDNode *Load = CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped,
336 XLenVT, MVT::Other, Operands);
337
338 CurDAG->setNodeMemRefs(Load, {cast<MemSDNode>(Node)->getMemOperand()});
339
340 ReplaceUses(SDValue(Node, 0), SDValue(Load, 0)); // Result
341 ReplaceUses(SDValue(Node, 1), SDValue(Load, 1)); // VL
342 ReplaceUses(SDValue(Node, 2), SDValue(Load, 2)); // Chain
343 CurDAG->RemoveDeadNode(Node);
344}
345
346void RISCVDAGToDAGISel::selectVLXSEG(SDNode *Node, unsigned NF, bool IsMasked,
347 bool IsOrdered) {
348 SDLoc DL(Node);
349 MVT VT = Node->getSimpleValueType(0);
350 unsigned Log2SEW = Node->getConstantOperandVal(Node->getNumOperands() - 1);
352
353 unsigned CurOp = 2;
355
356 Operands.push_back(Node->getOperand(CurOp++));
357
358 MVT IndexVT;
359 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked,
360 /*IsStridedOrIndexed*/ true, Operands,
361 /*IsLoad=*/true, &IndexVT);
362
363#ifndef NDEBUG
364 // Number of element = RVVBitsPerBlock * LMUL / SEW
365 unsigned ContainedTyNumElts = RISCV::RVVBitsPerBlock >> Log2SEW;
366 auto DecodedLMUL = RISCVVType::decodeVLMUL(LMUL);
367 if (DecodedLMUL.second)
368 ContainedTyNumElts /= DecodedLMUL.first;
369 else
370 ContainedTyNumElts *= DecodedLMUL.first;
371 assert(ContainedTyNumElts == IndexVT.getVectorMinNumElements() &&
372 "Element count mismatch");
373#endif
374
376 unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
377 if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
378 reportFatalUsageError("The V extension does not support EEW=64 for index "
379 "values when XLEN=32");
380 }
381 const RISCV::VLXSEGPseudo *P = RISCV::getVLXSEGPseudo(
382 NF, IsMasked, IsOrdered, IndexLog2EEW, static_cast<unsigned>(LMUL),
383 static_cast<unsigned>(IndexLMUL));
385 CurDAG->getMachineNode(P->Pseudo, DL, MVT::Untyped, MVT::Other, Operands);
386
387 CurDAG->setNodeMemRefs(Load, {cast<MemSDNode>(Node)->getMemOperand()});
388
391 CurDAG->RemoveDeadNode(Node);
392}
393
394void RISCVDAGToDAGISel::selectVSSEG(SDNode *Node, unsigned NF, bool IsMasked,
395 bool IsStrided) {
396 SDLoc DL(Node);
397 MVT VT = Node->getOperand(2)->getSimpleValueType(0);
398 unsigned Log2SEW = Node->getConstantOperandVal(Node->getNumOperands() - 1);
400
401 unsigned CurOp = 2;
403
404 Operands.push_back(Node->getOperand(CurOp++));
405
406 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked, IsStrided,
407 Operands);
408
409 const RISCV::VSSEGPseudo *P = RISCV::getVSSEGPseudo(
410 NF, IsMasked, IsStrided, Log2SEW, static_cast<unsigned>(LMUL));
412 CurDAG->getMachineNode(P->Pseudo, DL, Node->getValueType(0), Operands);
413
414 CurDAG->setNodeMemRefs(Store, {cast<MemSDNode>(Node)->getMemOperand()});
415
417}
418
419void RISCVDAGToDAGISel::selectVSXSEG(SDNode *Node, unsigned NF, bool IsMasked,
420 bool IsOrdered) {
421 SDLoc DL(Node);
422 MVT VT = Node->getOperand(2)->getSimpleValueType(0);
423 unsigned Log2SEW = Node->getConstantOperandVal(Node->getNumOperands() - 1);
425
426 unsigned CurOp = 2;
428
429 Operands.push_back(Node->getOperand(CurOp++));
430
431 MVT IndexVT;
432 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked,
433 /*IsStridedOrIndexed*/ true, Operands,
434 /*IsLoad=*/false, &IndexVT);
435
436#ifndef NDEBUG
437 // Number of element = RVVBitsPerBlock * LMUL / SEW
438 unsigned ContainedTyNumElts = RISCV::RVVBitsPerBlock >> Log2SEW;
439 auto DecodedLMUL = RISCVVType::decodeVLMUL(LMUL);
440 if (DecodedLMUL.second)
441 ContainedTyNumElts /= DecodedLMUL.first;
442 else
443 ContainedTyNumElts *= DecodedLMUL.first;
444 assert(ContainedTyNumElts == IndexVT.getVectorMinNumElements() &&
445 "Element count mismatch");
446#endif
447
449 unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
450 if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
451 reportFatalUsageError("The V extension does not support EEW=64 for index "
452 "values when XLEN=32");
453 }
454 const RISCV::VSXSEGPseudo *P = RISCV::getVSXSEGPseudo(
455 NF, IsMasked, IsOrdered, IndexLog2EEW, static_cast<unsigned>(LMUL),
456 static_cast<unsigned>(IndexLMUL));
458 CurDAG->getMachineNode(P->Pseudo, DL, Node->getValueType(0), Operands);
459
460 CurDAG->setNodeMemRefs(Store, {cast<MemSDNode>(Node)->getMemOperand()});
461
463}
464
466 if (!Subtarget->hasVInstructions())
467 return;
468
469 assert(Node->getOpcode() == ISD::INTRINSIC_WO_CHAIN && "Unexpected opcode");
470
471 SDLoc DL(Node);
472 MVT XLenVT = Subtarget->getXLenVT();
473
474 unsigned IntNo = Node->getConstantOperandVal(0);
475
476 assert((IntNo == Intrinsic::riscv_vsetvli ||
477 IntNo == Intrinsic::riscv_vsetvlimax) &&
478 "Unexpected vsetvli intrinsic");
479
480 bool VLMax = IntNo == Intrinsic::riscv_vsetvlimax;
481 unsigned Offset = (VLMax ? 1 : 2);
482
483 assert(Node->getNumOperands() == Offset + 2 &&
484 "Unexpected number of operands");
485
486 unsigned SEW =
487 RISCVVType::decodeVSEW(Node->getConstantOperandVal(Offset) & 0x7);
488 RISCVVType::VLMUL VLMul = static_cast<RISCVVType::VLMUL>(
489 Node->getConstantOperandVal(Offset + 1) & 0x7);
490
491 unsigned VTypeI = RISCVVType::encodeVTYPE(VLMul, SEW, /*TailAgnostic*/ true,
492 /*MaskAgnostic*/ true);
493 SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT);
494
495 SDValue VLOperand;
496 unsigned Opcode = RISCV::PseudoVSETVLI;
497 if (auto *C = dyn_cast<ConstantSDNode>(Node->getOperand(1))) {
498 if (auto VLEN = Subtarget->getRealVLen())
499 if (*VLEN / RISCVVType::getSEWLMULRatio(SEW, VLMul) == C->getZExtValue())
500 VLMax = true;
501 }
502 if (VLMax || isAllOnesConstant(Node->getOperand(1))) {
503 VLOperand = CurDAG->getRegister(RISCV::X0, XLenVT);
504 Opcode = RISCV::PseudoVSETVLIX0;
505 } else {
506 VLOperand = Node->getOperand(1);
507
508 if (auto *C = dyn_cast<ConstantSDNode>(VLOperand)) {
509 uint64_t AVL = C->getZExtValue();
510 if (isUInt<5>(AVL)) {
511 SDValue VLImm = CurDAG->getTargetConstant(AVL, DL, XLenVT);
512 ReplaceNode(Node, CurDAG->getMachineNode(RISCV::PseudoVSETIVLI, DL,
513 XLenVT, VLImm, VTypeIOp));
514 return;
515 }
516 }
517 }
518
520 CurDAG->getMachineNode(Opcode, DL, XLenVT, VLOperand, VTypeIOp));
521}
522
524 if (!Subtarget->hasVendorXSfmmbase())
525 return;
526
527 assert(Node->getOpcode() == ISD::INTRINSIC_WO_CHAIN && "Unexpected opcode");
528
529 SDLoc DL(Node);
530 MVT XLenVT = Subtarget->getXLenVT();
531
532 unsigned IntNo = Node->getConstantOperandVal(0);
533
534 assert((IntNo == Intrinsic::riscv_sf_vsettnt ||
535 IntNo == Intrinsic::riscv_sf_vsettm ||
536 IntNo == Intrinsic::riscv_sf_vsettk) &&
537 "Unexpected XSfmm vset intrinsic");
538
539 unsigned SEW = RISCVVType::decodeVSEW(Node->getConstantOperandVal(2));
540 unsigned Widen = RISCVVType::decodeTWiden(Node->getConstantOperandVal(3));
541 unsigned PseudoOpCode =
542 IntNo == Intrinsic::riscv_sf_vsettnt ? RISCV::PseudoSF_VSETTNT
543 : IntNo == Intrinsic::riscv_sf_vsettm ? RISCV::PseudoSF_VSETTM
544 : RISCV::PseudoSF_VSETTK;
545
546 if (IntNo == Intrinsic::riscv_sf_vsettnt) {
547 unsigned VTypeI = RISCVVType::encodeXSfmmVType(SEW, Widen, 0);
548 SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT);
549
550 ReplaceNode(Node, CurDAG->getMachineNode(PseudoOpCode, DL, XLenVT,
551 Node->getOperand(1), VTypeIOp));
552 } else {
553 SDValue Log2SEW = CurDAG->getTargetConstant(Log2_32(SEW), DL, XLenVT);
554 SDValue TWiden = CurDAG->getTargetConstant(Widen, DL, XLenVT);
556 CurDAG->getMachineNode(PseudoOpCode, DL, XLenVT,
557 Node->getOperand(1), Log2SEW, TWiden));
558 }
559}
560
562 MVT VT = Node->getSimpleValueType(0);
563 unsigned Opcode = Node->getOpcode();
564 assert((Opcode == ISD::AND || Opcode == ISD::OR || Opcode == ISD::XOR) &&
565 "Unexpected opcode");
566 SDLoc DL(Node);
567
568 // For operations of the form (x << C1) op C2, check if we can use
569 // ANDI/ORI/XORI by transforming it into (x op (C2>>C1)) << C1.
570 SDValue N0 = Node->getOperand(0);
571 SDValue N1 = Node->getOperand(1);
572
574 if (!Cst)
575 return false;
576
577 int64_t Val = Cst->getSExtValue();
578
579 // Check if immediate can already use ANDI/ORI/XORI.
580 if (isInt<12>(Val))
581 return false;
582
583 SDValue Shift = N0;
584
585 // If Val is simm32 and we have a sext_inreg from i32, then the binop
586 // produces at least 33 sign bits. We can peek through the sext_inreg and use
587 // a SLLIW at the end.
588 bool SignExt = false;
589 if (isInt<32>(Val) && N0.getOpcode() == ISD::SIGN_EXTEND_INREG &&
590 N0.hasOneUse() && cast<VTSDNode>(N0.getOperand(1))->getVT() == MVT::i32) {
591 SignExt = true;
592 Shift = N0.getOperand(0);
593 }
594
595 if (Shift.getOpcode() != ISD::SHL || !Shift.hasOneUse())
596 return false;
597
599 if (!ShlCst)
600 return false;
601
602 uint64_t ShAmt = ShlCst->getZExtValue();
603
604 // Make sure that we don't change the operation by removing bits.
605 // This only matters for OR and XOR, AND is unaffected.
606 uint64_t RemovedBitsMask = maskTrailingOnes<uint64_t>(ShAmt);
607 if (Opcode != ISD::AND && (Val & RemovedBitsMask) != 0)
608 return false;
609
610 int64_t ShiftedVal = Val >> ShAmt;
611 if (!isInt<12>(ShiftedVal))
612 return false;
613
614 // If we peeked through a sext_inreg, make sure the shift is valid for SLLIW.
615 if (SignExt && ShAmt >= 32)
616 return false;
617
618 // Ok, we can reorder to get a smaller immediate.
619 unsigned BinOpc;
620 switch (Opcode) {
621 default: llvm_unreachable("Unexpected opcode");
622 case ISD::AND: BinOpc = RISCV::ANDI; break;
623 case ISD::OR: BinOpc = RISCV::ORI; break;
624 case ISD::XOR: BinOpc = RISCV::XORI; break;
625 }
626
627 unsigned ShOpc = SignExt ? RISCV::SLLIW : RISCV::SLLI;
628
629 SDNode *BinOp = CurDAG->getMachineNode(
630 BinOpc, DL, VT, Shift.getOperand(0),
631 CurDAG->getSignedTargetConstant(ShiftedVal, DL, VT));
632 SDNode *SLLI =
633 CurDAG->getMachineNode(ShOpc, DL, VT, SDValue(BinOp, 0),
634 CurDAG->getTargetConstant(ShAmt, DL, VT));
635 ReplaceNode(Node, SLLI);
636 return true;
637}
638
640 unsigned Opc;
641
642 if (Subtarget->hasVendorXTHeadBb())
643 Opc = RISCV::TH_EXT;
644 else if (Subtarget->hasVendorXAndesPerf())
645 Opc = RISCV::NDS_BFOS;
646 else if (Subtarget->hasVendorXqcibm())
647 Opc = RISCV::QC_EXT;
648 else
649 // Only supported with XTHeadBb/XAndesPerf/Xqcibm at the moment.
650 return false;
651
652 auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1));
653 if (!N1C)
654 return false;
655
656 SDValue N0 = Node->getOperand(0);
657 if (!N0.hasOneUse())
658 return false;
659
660 auto BitfieldExtract = [&](SDValue N0, unsigned Msb, unsigned Lsb,
661 const SDLoc &DL, MVT VT) {
662 if (Opc == RISCV::QC_EXT) {
663 // QC.EXT X, width, shamt
664 // shamt is the same as Lsb
665 // width is the number of bits to extract from the Lsb
666 Msb = Msb - Lsb + 1;
667 }
668 return CurDAG->getMachineNode(Opc, DL, VT, N0.getOperand(0),
669 CurDAG->getTargetConstant(Msb, DL, VT),
670 CurDAG->getTargetConstant(Lsb, DL, VT));
671 };
672
673 SDLoc DL(Node);
674 MVT VT = Node->getSimpleValueType(0);
675 const unsigned RightShAmt = N1C->getZExtValue();
676
677 // Transform (sra (shl X, C1) C2) with C1 < C2
678 // -> (SignedBitfieldExtract X, msb, lsb)
679 if (N0.getOpcode() == ISD::SHL) {
680 auto *N01C = dyn_cast<ConstantSDNode>(N0.getOperand(1));
681 if (!N01C)
682 return false;
683
684 const unsigned LeftShAmt = N01C->getZExtValue();
685 // Make sure that this is a bitfield extraction (i.e., the shift-right
686 // amount can not be less than the left-shift).
687 if (LeftShAmt > RightShAmt)
688 return false;
689
690 const unsigned MsbPlusOne = VT.getSizeInBits() - LeftShAmt;
691 const unsigned Msb = MsbPlusOne - 1;
692 const unsigned Lsb = RightShAmt - LeftShAmt;
693
694 SDNode *Sbe = BitfieldExtract(N0, Msb, Lsb, DL, VT);
695 ReplaceNode(Node, Sbe);
696 return true;
697 }
698
699 // Transform (sra (sext_inreg X, _), C) ->
700 // (SignedBitfieldExtract X, msb, lsb)
701 if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG) {
702 unsigned ExtSize =
703 cast<VTSDNode>(N0.getOperand(1))->getVT().getSizeInBits();
704
705 // ExtSize of 32 should use sraiw via tablegen pattern.
706 if (ExtSize == 32)
707 return false;
708
709 const unsigned Msb = ExtSize - 1;
710 // If the shift-right amount is greater than Msb, it means that extracts
711 // the X[Msb] bit and sign-extend it.
712 const unsigned Lsb = RightShAmt > Msb ? Msb : RightShAmt;
713
714 SDNode *Sbe = BitfieldExtract(N0, Msb, Lsb, DL, VT);
715 ReplaceNode(Node, Sbe);
716 return true;
717 }
718
719 return false;
720}
721
723 // Only supported with XAndesPerf at the moment.
724 if (!Subtarget->hasVendorXAndesPerf())
725 return false;
726
727 auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1));
728 if (!N1C)
729 return false;
730
731 SDValue N0 = Node->getOperand(0);
732 if (!N0.hasOneUse())
733 return false;
734
735 auto BitfieldInsert = [&](SDValue N0, unsigned Msb, unsigned Lsb,
736 const SDLoc &DL, MVT VT) {
737 unsigned Opc = RISCV::NDS_BFOS;
738 // If the Lsb is equal to the Msb, then the Lsb should be 0.
739 if (Lsb == Msb)
740 Lsb = 0;
741 return CurDAG->getMachineNode(Opc, DL, VT, N0.getOperand(0),
742 CurDAG->getTargetConstant(Lsb, DL, VT),
743 CurDAG->getTargetConstant(Msb, DL, VT));
744 };
745
746 SDLoc DL(Node);
747 MVT VT = Node->getSimpleValueType(0);
748 const unsigned RightShAmt = N1C->getZExtValue();
749
750 // Transform (sra (shl X, C1) C2) with C1 > C2
751 // -> (NDS.BFOS X, lsb, msb)
752 if (N0.getOpcode() == ISD::SHL) {
753 auto *N01C = dyn_cast<ConstantSDNode>(N0.getOperand(1));
754 if (!N01C)
755 return false;
756
757 const unsigned LeftShAmt = N01C->getZExtValue();
758 // Make sure that this is a bitfield insertion (i.e., the shift-right
759 // amount should be less than the left-shift).
760 if (LeftShAmt <= RightShAmt)
761 return false;
762
763 const unsigned MsbPlusOne = VT.getSizeInBits() - RightShAmt;
764 const unsigned Msb = MsbPlusOne - 1;
765 const unsigned Lsb = LeftShAmt - RightShAmt;
766
767 SDNode *Sbi = BitfieldInsert(N0, Msb, Lsb, DL, VT);
768 ReplaceNode(Node, Sbi);
769 return true;
770 }
771
772 return false;
773}
774
776 const SDLoc &DL, MVT VT,
777 SDValue X, unsigned Msb,
778 unsigned Lsb) {
779 unsigned Opc;
780
781 if (Subtarget->hasVendorXTHeadBb()) {
782 Opc = RISCV::TH_EXTU;
783 } else if (Subtarget->hasVendorXAndesPerf()) {
784 Opc = RISCV::NDS_BFOZ;
785 } else if (Subtarget->hasVendorXqcibm()) {
786 Opc = RISCV::QC_EXTU;
787 // QC.EXTU X, width, shamt
788 // shamt is the same as Lsb
789 // width is the number of bits to extract from the Lsb
790 Msb = Msb - Lsb + 1;
791 } else {
792 // Only supported with XTHeadBb/XAndesPerf/Xqcibm at the moment.
793 return false;
794 }
795
796 SDNode *Ube = CurDAG->getMachineNode(Opc, DL, VT, X,
797 CurDAG->getTargetConstant(Msb, DL, VT),
798 CurDAG->getTargetConstant(Lsb, DL, VT));
799 ReplaceNode(Node, Ube);
800 return true;
801}
802
804 const SDLoc &DL, MVT VT,
805 SDValue X, unsigned Msb,
806 unsigned Lsb) {
807 // Only supported with XAndesPerf at the moment.
808 if (!Subtarget->hasVendorXAndesPerf())
809 return false;
810
811 unsigned Opc = RISCV::NDS_BFOZ;
812
813 // If the Lsb is equal to the Msb, then the Lsb should be 0.
814 if (Lsb == Msb)
815 Lsb = 0;
816 SDNode *Ubi = CurDAG->getMachineNode(Opc, DL, VT, X,
817 CurDAG->getTargetConstant(Lsb, DL, VT),
818 CurDAG->getTargetConstant(Msb, DL, VT));
819 ReplaceNode(Node, Ubi);
820 return true;
821}
822
824 // Target does not support indexed loads.
825 if (!Subtarget->hasVendorXTHeadMemIdx())
826 return false;
827
830 if (AM == ISD::UNINDEXED)
831 return false;
832
834 if (!C)
835 return false;
836
837 EVT LoadVT = Ld->getMemoryVT();
838 assert((AM == ISD::PRE_INC || AM == ISD::POST_INC) &&
839 "Unexpected addressing mode");
840 bool IsPre = AM == ISD::PRE_INC;
841 bool IsPost = AM == ISD::POST_INC;
842 int64_t Offset = C->getSExtValue();
843
844 // The constants that can be encoded in the THeadMemIdx instructions
845 // are of the form (sign_extend(imm5) << imm2).
846 unsigned Shift;
847 for (Shift = 0; Shift < 4; Shift++)
848 if (isInt<5>(Offset >> Shift) && ((Offset % (1LL << Shift)) == 0))
849 break;
850
851 // Constant cannot be encoded.
852 if (Shift == 4)
853 return false;
854
855 bool IsZExt = (Ld->getExtensionType() == ISD::ZEXTLOAD);
856 unsigned Opcode;
857 if (LoadVT == MVT::i8 && IsPre)
858 Opcode = IsZExt ? RISCV::TH_LBUIB : RISCV::TH_LBIB;
859 else if (LoadVT == MVT::i8 && IsPost)
860 Opcode = IsZExt ? RISCV::TH_LBUIA : RISCV::TH_LBIA;
861 else if (LoadVT == MVT::i16 && IsPre)
862 Opcode = IsZExt ? RISCV::TH_LHUIB : RISCV::TH_LHIB;
863 else if (LoadVT == MVT::i16 && IsPost)
864 Opcode = IsZExt ? RISCV::TH_LHUIA : RISCV::TH_LHIA;
865 else if (LoadVT == MVT::i32 && IsPre)
866 Opcode = IsZExt ? RISCV::TH_LWUIB : RISCV::TH_LWIB;
867 else if (LoadVT == MVT::i32 && IsPost)
868 Opcode = IsZExt ? RISCV::TH_LWUIA : RISCV::TH_LWIA;
869 else if (LoadVT == MVT::i64 && IsPre)
870 Opcode = RISCV::TH_LDIB;
871 else if (LoadVT == MVT::i64 && IsPost)
872 Opcode = RISCV::TH_LDIA;
873 else
874 return false;
875
876 EVT Ty = Ld->getOffset().getValueType();
877 SDValue Ops[] = {
878 Ld->getBasePtr(),
879 CurDAG->getSignedTargetConstant(Offset >> Shift, SDLoc(Node), Ty),
880 CurDAG->getTargetConstant(Shift, SDLoc(Node), Ty), Ld->getChain()};
881 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(Node), Ld->getValueType(0),
882 Ld->getValueType(1), MVT::Other, Ops);
883
884 MachineMemOperand *MemOp = cast<MemSDNode>(Node)->getMemOperand();
885 CurDAG->setNodeMemRefs(cast<MachineSDNode>(New), {MemOp});
886
887 ReplaceNode(Node, New);
888
889 return true;
890}
891
892static SDValue buildGPRPair(SelectionDAG *CurDAG, const SDLoc &DL, MVT VT,
893 SDValue Lo, SDValue Hi) {
894 SDValue Ops[] = {
895 CurDAG->getTargetConstant(RISCV::GPRPairRegClassID, DL, MVT::i32), Lo,
896 CurDAG->getTargetConstant(RISCV::sub_gpr_even, DL, MVT::i32), Hi,
897 CurDAG->getTargetConstant(RISCV::sub_gpr_odd, DL, MVT::i32)};
898
899 return SDValue(
900 CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, VT, Ops), 0);
901}
902
903// Helper to extract Lo and Hi values from a GPR pair.
904static std::pair<SDValue, SDValue>
906 SDValue Lo =
907 CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_even, DL, MVT::i32, Pair);
908 SDValue Hi =
909 CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_odd, DL, MVT::i32, Pair);
910 return {Lo, Hi};
911}
912
913// Try to match WMACC pattern: ADDD where one operand pair comes from a
914// widening multiply (both results of UMUL_LOHI, SMUL_LOHI, or WMULSU).
916 assert(Node->getOpcode() == RISCVISD::ADDD && "Expected ADDD");
917
918 SDValue Op0Lo = Node->getOperand(0);
919 SDValue Op0Hi = Node->getOperand(1);
920 SDValue Op1Lo = Node->getOperand(2);
921 SDValue Op1Hi = Node->getOperand(3);
922
923 auto IsSupportedMulWithOneUse = [](SDValue Lo, SDValue Hi) {
924 unsigned Opc = Lo.getOpcode();
925 if (Opc != ISD::UMUL_LOHI && Opc != ISD::SMUL_LOHI &&
926 Opc != RISCVISD::WMULSU)
927 return false;
928 return Lo.getNode() == Hi.getNode() && Lo.getResNo() == 0 &&
929 Hi.getResNo() == 1 && Lo.hasOneUse() && Hi.hasOneUse();
930 };
931
932 SDNode *MulNode = nullptr;
933 SDValue AddLo, AddHi;
934
935 // Check if first operand pair is a supported multiply with single use.
936 if (IsSupportedMulWithOneUse(Op0Lo, Op0Hi)) {
937 MulNode = Op0Lo.getNode();
938 AddLo = Op1Lo;
939 AddHi = Op1Hi;
940 }
941 // ADDD is commutative. Check if second operand pair is a supported multiply
942 // with single use.
943 else if (IsSupportedMulWithOneUse(Op1Lo, Op1Hi)) {
944 MulNode = Op1Lo.getNode();
945 AddLo = Op0Lo;
946 AddHi = Op0Hi;
947 } else {
948 return false;
949 }
950
951 unsigned Opc;
952 switch (MulNode->getOpcode()) {
953 default:
954 llvm_unreachable("Unexpected multiply opcode");
955 case ISD::UMUL_LOHI:
956 Opc = RISCV::WMACCU;
957 break;
958 case ISD::SMUL_LOHI:
959 Opc = RISCV::WMACC;
960 break;
961 case RISCVISD::WMULSU:
962 Opc = RISCV::WMACCSU;
963 break;
964 }
965
966 SDValue Acc = buildGPRPair(CurDAG, DL, MVT::Untyped, AddLo, AddHi);
967
968 // WMACC instruction format: rd, rs1, rs2 (rd is accumulator).
969 SDValue M0 = MulNode->getOperand(0);
970 SDValue M1 = MulNode->getOperand(1);
971 MachineSDNode *New =
972 CurDAG->getMachineNode(Opc, DL, MVT::Untyped, Acc, M0, M1);
973
974 auto [Lo, Hi] = extractGPRPair(CurDAG, DL, SDValue(New, 0));
977 CurDAG->RemoveDeadNode(Node);
978 return true;
979}
980
981static Register getTileReg(uint64_t TileNum) {
982 assert(TileNum <= 15 && "Invalid tile number");
983 return RISCV::T0 + TileNum;
984}
985
987 if (!Subtarget->hasVInstructions())
988 return;
989
990 assert(Node->getOpcode() == ISD::INTRINSIC_VOID && "Unexpected opcode");
991
992 SDLoc DL(Node);
993 unsigned IntNo = Node->getConstantOperandVal(1);
994
995 assert((IntNo == Intrinsic::riscv_sf_vc_x_se ||
996 IntNo == Intrinsic::riscv_sf_vc_i_se) &&
997 "Unexpected vsetvli intrinsic");
998
999 // imm, imm, imm, simm5/scalar, sew, log2lmul, vl
1000 unsigned Log2SEW = Log2_32(Node->getConstantOperandVal(6));
1001 SDValue SEWOp =
1002 CurDAG->getTargetConstant(Log2SEW, DL, Subtarget->getXLenVT());
1003 SmallVector<SDValue, 8> Operands = {Node->getOperand(2), Node->getOperand(3),
1004 Node->getOperand(4), Node->getOperand(5),
1005 Node->getOperand(8), SEWOp,
1006 Node->getOperand(0)};
1007
1008 unsigned Opcode;
1009 auto *LMulSDNode = cast<ConstantSDNode>(Node->getOperand(7));
1010 switch (LMulSDNode->getSExtValue()) {
1011 case 5:
1012 Opcode = IntNo == Intrinsic::riscv_sf_vc_x_se ? RISCV::PseudoSF_VC_X_SE_MF8
1013 : RISCV::PseudoSF_VC_I_SE_MF8;
1014 break;
1015 case 6:
1016 Opcode = IntNo == Intrinsic::riscv_sf_vc_x_se ? RISCV::PseudoSF_VC_X_SE_MF4
1017 : RISCV::PseudoSF_VC_I_SE_MF4;
1018 break;
1019 case 7:
1020 Opcode = IntNo == Intrinsic::riscv_sf_vc_x_se ? RISCV::PseudoSF_VC_X_SE_MF2
1021 : RISCV::PseudoSF_VC_I_SE_MF2;
1022 break;
1023 case 0:
1024 Opcode = IntNo == Intrinsic::riscv_sf_vc_x_se ? RISCV::PseudoSF_VC_X_SE_M1
1025 : RISCV::PseudoSF_VC_I_SE_M1;
1026 break;
1027 case 1:
1028 Opcode = IntNo == Intrinsic::riscv_sf_vc_x_se ? RISCV::PseudoSF_VC_X_SE_M2
1029 : RISCV::PseudoSF_VC_I_SE_M2;
1030 break;
1031 case 2:
1032 Opcode = IntNo == Intrinsic::riscv_sf_vc_x_se ? RISCV::PseudoSF_VC_X_SE_M4
1033 : RISCV::PseudoSF_VC_I_SE_M4;
1034 break;
1035 case 3:
1036 Opcode = IntNo == Intrinsic::riscv_sf_vc_x_se ? RISCV::PseudoSF_VC_X_SE_M8
1037 : RISCV::PseudoSF_VC_I_SE_M8;
1038 break;
1039 }
1040
1041 ReplaceNode(Node, CurDAG->getMachineNode(
1042 Opcode, DL, Node->getSimpleValueType(0), Operands));
1043}
1044
1045static unsigned getSegInstNF(unsigned Intrinsic) {
1046#define INST_NF_CASE(NAME, NF) \
1047 case Intrinsic::riscv_##NAME##NF: \
1048 return NF;
1049#define INST_NF_CASE_MASK(NAME, NF) \
1050 case Intrinsic::riscv_##NAME##NF##_mask: \
1051 return NF;
1052#define INST_NF_CASE_FF(NAME, NF) \
1053 case Intrinsic::riscv_##NAME##NF##ff: \
1054 return NF;
1055#define INST_NF_CASE_FF_MASK(NAME, NF) \
1056 case Intrinsic::riscv_##NAME##NF##ff_mask: \
1057 return NF;
1058#define INST_ALL_NF_CASE_BASE(MACRO_NAME, NAME) \
1059 MACRO_NAME(NAME, 2) \
1060 MACRO_NAME(NAME, 3) \
1061 MACRO_NAME(NAME, 4) \
1062 MACRO_NAME(NAME, 5) \
1063 MACRO_NAME(NAME, 6) \
1064 MACRO_NAME(NAME, 7) \
1065 MACRO_NAME(NAME, 8)
1066#define INST_ALL_NF_CASE(NAME) \
1067 INST_ALL_NF_CASE_BASE(INST_NF_CASE, NAME) \
1068 INST_ALL_NF_CASE_BASE(INST_NF_CASE_MASK, NAME)
1069#define INST_ALL_NF_CASE_WITH_FF(NAME) \
1070 INST_ALL_NF_CASE(NAME) \
1071 INST_ALL_NF_CASE_BASE(INST_NF_CASE_FF, NAME) \
1072 INST_ALL_NF_CASE_BASE(INST_NF_CASE_FF_MASK, NAME)
1073 switch (Intrinsic) {
1074 default:
1075 llvm_unreachable("Unexpected segment load/store intrinsic");
1077 INST_ALL_NF_CASE(vlsseg)
1078 INST_ALL_NF_CASE(vloxseg)
1079 INST_ALL_NF_CASE(vluxseg)
1080 INST_ALL_NF_CASE(vsseg)
1081 INST_ALL_NF_CASE(vssseg)
1082 INST_ALL_NF_CASE(vsoxseg)
1083 INST_ALL_NF_CASE(vsuxseg)
1084 }
1085}
1086
1087static bool isApplicableToPLIOrPLUI(int Val) {
1088 // Check if the immediate is packed i8 or i10
1089 int16_t Bit31To16 = Val >> 16;
1090 int16_t Bit15To0 = Val;
1091 int8_t Bit15To8 = Bit15To0 >> 8;
1092 int8_t Bit7To0 = Val;
1093 if (Bit31To16 != Bit15To0)
1094 return false;
1095
1096 return isInt<10>(Bit15To0) || isShiftedInt<10, 6>(Bit15To0) ||
1097 Bit15To8 == Bit7To0;
1098}
1099
1101 // If we have a custom node, we have already selected.
1102 if (Node->isMachineOpcode()) {
1103 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n");
1104 Node->setNodeId(-1);
1105 return;
1106 }
1107
1108 // Instruction Selection not handled by the auto-generated tablegen selection
1109 // should be handled here.
1110 unsigned Opcode = Node->getOpcode();
1111 MVT XLenVT = Subtarget->getXLenVT();
1112 SDLoc DL(Node);
1113 MVT VT = Node->getSimpleValueType(0);
1114
1115 bool HasBitTest = Subtarget->hasBEXTILike();
1116
1117 switch (Opcode) {
1118 case ISD::Constant: {
1119 assert(VT == Subtarget->getXLenVT() && "Unexpected VT");
1120 auto *ConstNode = cast<ConstantSDNode>(Node);
1121 if (ConstNode->isZero()) {
1122 SDValue New =
1123 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, RISCV::X0, VT);
1124 ReplaceNode(Node, New.getNode());
1125 return;
1126 }
1127 int64_t Imm = ConstNode->getSExtValue();
1128 // If only the lower 8 bits are used, try to convert this to a simm6 by
1129 // sign-extending bit 7. This is neutral without the C extension, and
1130 // allows C.LI to be used if C is present.
1134 // If the upper XLen-16 bits are not used, try to convert this to a simm12
1135 // by sign extending bit 15.
1136 else if (!isInt<16>(Imm) && isUInt<16>(Imm) &&
1139
1140 // If the upper XLen-16 bits are not used, the lower 2 bytes are the same,
1141 // and we can't use li, convert to an xlen splat so we can use pli.b.
1142 if (Subtarget->hasStdExtP() && !isInt<12>(Imm) &&
1143 (Imm & 0xff) == ((Imm >> 8) & 0xff) && hasAllHUsers(Node)) {
1144 // Splat the lower 16 bits to XLen. Sign extend for RV32.
1145 uint64_t Splat = Imm & 0xffff;
1146 Splat = (Splat << 16) | Splat;
1147 if (VT == MVT::i64)
1148 Imm = Splat << 32 | Splat;
1149 else
1151 } else {
1152 // If the upper 32-bits are not used try to convert this into a simm32 by
1153 // sign extending bit 32.
1156
1157 if (VT == MVT::i64 && !isInt<12>(Imm) && !isShiftedInt<20, 12>(Imm) &&
1158 Subtarget->hasStdExtP() && isApplicableToPLIOrPLUI(Imm) &&
1159 hasAllWUsers(Node)) {
1160 // If it's 4 packed 8-bit integers or 2 packed signed 16-bit integers,
1161 // we can simply copy lower 32 bits to higher 32 bits to make it able to
1162 // rematerialize to PLI_B or PLI_H
1163 Imm = ((uint64_t)Imm << 32) | (Imm & 0xFFFFFFFF);
1164 }
1165 }
1166
1167 ReplaceNode(Node, selectImm(CurDAG, DL, VT, Imm, *Subtarget).getNode());
1168 return;
1169 }
1170 case ISD::ConstantFP: {
1171 const APFloat &APF = cast<ConstantFPSDNode>(Node)->getValueAPF();
1172
1173 bool Is64Bit = Subtarget->is64Bit();
1174 bool HasZdinx = Subtarget->hasStdExtZdinx();
1175
1176 bool NegZeroF64 = APF.isNegZero() && VT == MVT::f64;
1177 SDValue Imm;
1178 // For +0.0 or f64 -0.0 we need to start from X0. For all others, we will
1179 // create an integer immediate.
1180 if (APF.isPosZero() || NegZeroF64) {
1181 if (VT == MVT::f64 && HasZdinx && !Is64Bit)
1182 Imm = CurDAG->getRegister(RISCV::X0_Pair, MVT::f64);
1183 else
1184 Imm = CurDAG->getRegister(RISCV::X0, XLenVT);
1185 } else {
1186 Imm = selectImm(CurDAG, DL, XLenVT, APF.bitcastToAPInt().getSExtValue(),
1187 *Subtarget);
1188 }
1189
1190 unsigned Opc;
1191 switch (VT.SimpleTy) {
1192 default:
1193 llvm_unreachable("Unexpected size");
1194 case MVT::bf16:
1195 assert(Subtarget->hasStdExtZfbfmin());
1196 Opc = RISCV::FMV_H_X;
1197 break;
1198 case MVT::f16:
1199 Opc = Subtarget->hasStdExtZhinxmin() ? RISCV::COPY : RISCV::FMV_H_X;
1200 break;
1201 case MVT::f32:
1202 Opc = Subtarget->hasStdExtZfinx() ? RISCV::COPY : RISCV::FMV_W_X;
1203 break;
1204 case MVT::f64:
1205 // For RV32, we can't move from a GPR, we need to convert instead. This
1206 // should only happen for +0.0 and -0.0.
1207 assert((Subtarget->is64Bit() || APF.isZero()) && "Unexpected constant");
1208 if (HasZdinx)
1209 Opc = RISCV::COPY;
1210 else
1211 Opc = Is64Bit ? RISCV::FMV_D_X : RISCV::FCVT_D_W;
1212 break;
1213 }
1214
1215 SDNode *Res;
1216 if (VT.SimpleTy == MVT::f16 && Opc == RISCV::COPY) {
1217 Res =
1218 CurDAG->getTargetExtractSubreg(RISCV::sub_16, DL, VT, Imm).getNode();
1219 } else if (VT.SimpleTy == MVT::f32 && Opc == RISCV::COPY) {
1220 Res =
1221 CurDAG->getTargetExtractSubreg(RISCV::sub_32, DL, VT, Imm).getNode();
1222 } else if (Opc == RISCV::FCVT_D_W_IN32X || Opc == RISCV::FCVT_D_W)
1223 Res = CurDAG->getMachineNode(
1224 Opc, DL, VT, Imm,
1225 CurDAG->getTargetConstant(RISCVFPRndMode::RNE, DL, XLenVT));
1226 else
1227 Res = CurDAG->getMachineNode(Opc, DL, VT, Imm);
1228
1229 // For f64 -0.0, we need to insert a fneg.d idiom.
1230 if (NegZeroF64) {
1231 Opc = RISCV::FSGNJN_D;
1232 if (HasZdinx)
1233 Opc = Is64Bit ? RISCV::FSGNJN_D_INX : RISCV::FSGNJN_D_IN32X;
1234 Res =
1235 CurDAG->getMachineNode(Opc, DL, VT, SDValue(Res, 0), SDValue(Res, 0));
1236 }
1237
1238 ReplaceNode(Node, Res);
1239 return;
1240 }
1241 case RISCVISD::BuildGPRPair:
1242 case RISCVISD::BuildPairF64:
1243 case RISCVISD::BuildPairGPRVec: {
1244 if (Opcode == RISCVISD::BuildPairF64 && !Subtarget->hasStdExtZdinx())
1245 break;
1246
1247 assert((!Subtarget->is64Bit() || Opcode != RISCVISD::BuildPairF64) &&
1248 "BuildPairF64 only handled here on rv32i_zdinx");
1249
1250 SDValue N =
1251 buildGPRPair(CurDAG, DL, VT, Node->getOperand(0), Node->getOperand(1));
1252 ReplaceNode(Node, N.getNode());
1253 return;
1254 }
1255 case RISCVISD::SplitGPRPair:
1256 case RISCVISD::SplitF64:
1257 case RISCVISD::SplitGPRVec: {
1258 if (Subtarget->hasStdExtZdinx() || Opcode != RISCVISD::SplitF64) {
1259 assert((!Subtarget->is64Bit() || Opcode != RISCVISD::SplitF64) &&
1260 "SplitF64 only handled here on rv32i_zdinx");
1261
1262 if (!SDValue(Node, 0).use_empty()) {
1263 SDValue Lo = CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_even, DL,
1264 Node->getValueType(0),
1265 Node->getOperand(0));
1266 ReplaceUses(SDValue(Node, 0), Lo);
1267 }
1268
1269 if (!SDValue(Node, 1).use_empty()) {
1270 SDValue Hi = CurDAG->getTargetExtractSubreg(
1271 RISCV::sub_gpr_odd, DL, Node->getValueType(1), Node->getOperand(0));
1272 ReplaceUses(SDValue(Node, 1), Hi);
1273 }
1274
1275 CurDAG->RemoveDeadNode(Node);
1276 return;
1277 }
1278
1279 if (!Subtarget->hasStdExtZfa())
1280 break;
1281 assert(Subtarget->hasStdExtD() && !Subtarget->is64Bit() &&
1282 "Unexpected subtarget");
1283
1284 // With Zfa, lower to fmv.x.w and fmvh.x.d.
1285 if (!SDValue(Node, 0).use_empty()) {
1286 SDNode *Lo = CurDAG->getMachineNode(RISCV::FMV_X_W_FPR64, DL, VT,
1287 Node->getOperand(0));
1288 ReplaceUses(SDValue(Node, 0), SDValue(Lo, 0));
1289 }
1290 if (!SDValue(Node, 1).use_empty()) {
1291 SDNode *Hi = CurDAG->getMachineNode(RISCV::FMVH_X_D, DL, VT,
1292 Node->getOperand(0));
1293 ReplaceUses(SDValue(Node, 1), SDValue(Hi, 0));
1294 }
1295
1296 CurDAG->RemoveDeadNode(Node);
1297 return;
1298 }
1299 case ISD::SHL: {
1300 auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1));
1301 if (!N1C)
1302 break;
1303 SDValue N0 = Node->getOperand(0);
1304 if (N0.getOpcode() != ISD::AND || !N0.hasOneUse() ||
1306 break;
1307 unsigned ShAmt = N1C->getZExtValue();
1308 uint64_t Mask = N0.getConstantOperandVal(1);
1309
1310 if (isShiftedMask_64(Mask)) {
1311 unsigned XLen = Subtarget->getXLen();
1312 unsigned LeadingZeros = XLen - llvm::bit_width(Mask);
1313 unsigned TrailingZeros = llvm::countr_zero(Mask);
1314 if (ShAmt <= 32 && TrailingZeros > 0 && LeadingZeros == 32) {
1315 // Optimize (shl (and X, C2), C) -> (slli (srliw X, C3), C3+C)
1316 // where C2 has 32 leading zeros and C3 trailing zeros.
1317 SDNode *SRLIW = CurDAG->getMachineNode(
1318 RISCV::SRLIW, DL, VT, N0.getOperand(0),
1319 CurDAG->getTargetConstant(TrailingZeros, DL, VT));
1320 SDNode *SLLI = CurDAG->getMachineNode(
1321 RISCV::SLLI, DL, VT, SDValue(SRLIW, 0),
1322 CurDAG->getTargetConstant(TrailingZeros + ShAmt, DL, VT));
1323 ReplaceNode(Node, SLLI);
1324 return;
1325 }
1326 if (TrailingZeros == 0 && LeadingZeros > ShAmt &&
1327 XLen - LeadingZeros > 11 && LeadingZeros != 32) {
1328 // Optimize (shl (and X, C2), C) -> (srli (slli X, C4), C4-C)
1329 // where C2 has C4 leading zeros and no trailing zeros.
1330 // This is profitable if the "and" was to be lowered to
1331 // (srli (slli X, C4), C4) and not (andi X, C2).
1332 // For "LeadingZeros == 32":
1333 // - with Zba it's just (slli.uw X, C)
1334 // - without Zba a tablegen pattern applies the very same
1335 // transform as we would have done here
1336 SDNode *SLLI = CurDAG->getMachineNode(
1337 RISCV::SLLI, DL, VT, N0.getOperand(0),
1338 CurDAG->getTargetConstant(LeadingZeros, DL, VT));
1339 SDNode *SRLI = CurDAG->getMachineNode(
1340 RISCV::SRLI, DL, VT, SDValue(SLLI, 0),
1341 CurDAG->getTargetConstant(LeadingZeros - ShAmt, DL, VT));
1342 ReplaceNode(Node, SRLI);
1343 return;
1344 }
1345 }
1346 break;
1347 }
1348 case ISD::SRL: {
1349 auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1));
1350 if (!N1C)
1351 break;
1352 SDValue N0 = Node->getOperand(0);
1353 if (N0.getOpcode() != ISD::AND || !isa<ConstantSDNode>(N0.getOperand(1)))
1354 break;
1355 unsigned ShAmt = N1C->getZExtValue();
1356 uint64_t Mask = N0.getConstantOperandVal(1);
1357
1358 // Optimize (srl (and X, C2), C) -> (slli (srliw X, C3), C3-C) where C2 has
1359 // 32 leading zeros and C3 trailing zeros.
1360 if (isShiftedMask_64(Mask) && N0.hasOneUse()) {
1361 unsigned XLen = Subtarget->getXLen();
1362 unsigned LeadingZeros = XLen - llvm::bit_width(Mask);
1363 unsigned TrailingZeros = llvm::countr_zero(Mask);
1364 if (LeadingZeros == 32 && TrailingZeros > ShAmt) {
1365 SDNode *SRLIW = CurDAG->getMachineNode(
1366 RISCV::SRLIW, DL, VT, N0.getOperand(0),
1367 CurDAG->getTargetConstant(TrailingZeros, DL, VT));
1368 SDNode *SLLI = CurDAG->getMachineNode(
1369 RISCV::SLLI, DL, VT, SDValue(SRLIW, 0),
1370 CurDAG->getTargetConstant(TrailingZeros - ShAmt, DL, VT));
1371 ReplaceNode(Node, SLLI);
1372 return;
1373 }
1374 }
1375
1376 // Optimize (srl (and X, C2), C) ->
1377 // (srli (slli X, (XLen-C3), (XLen-C3) + C)
1378 // Where C2 is a mask with C3 trailing ones.
1379 // Taking into account that the C2 may have had lower bits unset by
1380 // SimplifyDemandedBits. This avoids materializing the C2 immediate.
1381 // This pattern occurs when type legalizing right shifts for types with
1382 // less than XLen bits.
1383 Mask |= maskTrailingOnes<uint64_t>(ShAmt);
1384 if (!isMask_64(Mask))
1385 break;
1386 unsigned TrailingOnes = llvm::countr_one(Mask);
1387 if (ShAmt >= TrailingOnes)
1388 break;
1389 // If the mask has 32 trailing ones, use SRLI on RV32 or SRLIW on RV64.
1390 if (TrailingOnes == 32) {
1391 SDNode *SRLI = CurDAG->getMachineNode(
1392 Subtarget->is64Bit() ? RISCV::SRLIW : RISCV::SRLI, DL, VT,
1393 N0.getOperand(0), CurDAG->getTargetConstant(ShAmt, DL, VT));
1394 ReplaceNode(Node, SRLI);
1395 return;
1396 }
1397
1398 // Only do the remaining transforms if the AND has one use.
1399 if (!N0.hasOneUse())
1400 break;
1401
1402 // If C2 is (1 << ShAmt) use bexti or th.tst if possible.
1403 if (HasBitTest && ShAmt + 1 == TrailingOnes) {
1404 SDNode *BEXTI = CurDAG->getMachineNode(
1405 Subtarget->hasStdExtZbs() ? RISCV::BEXTI : RISCV::TH_TST, DL, VT,
1406 N0.getOperand(0), CurDAG->getTargetConstant(ShAmt, DL, VT));
1407 ReplaceNode(Node, BEXTI);
1408 return;
1409 }
1410
1411 const unsigned Msb = TrailingOnes - 1;
1412 const unsigned Lsb = ShAmt;
1413 if (tryUnsignedBitfieldExtract(Node, DL, VT, N0.getOperand(0), Msb, Lsb))
1414 return;
1415
1416 unsigned LShAmt = Subtarget->getXLen() - TrailingOnes;
1417 SDNode *SLLI =
1418 CurDAG->getMachineNode(RISCV::SLLI, DL, VT, N0.getOperand(0),
1419 CurDAG->getTargetConstant(LShAmt, DL, VT));
1420 SDNode *SRLI = CurDAG->getMachineNode(
1421 RISCV::SRLI, DL, VT, SDValue(SLLI, 0),
1422 CurDAG->getTargetConstant(LShAmt + ShAmt, DL, VT));
1423 ReplaceNode(Node, SRLI);
1424 return;
1425 }
1426 case ISD::SRA: {
1428 return;
1429
1431 return;
1432
1433 // Optimize (sra (sext_inreg X, i16), C) ->
1434 // (srai (slli X, (XLen-16), (XLen-16) + C)
1435 // And (sra (sext_inreg X, i8), C) ->
1436 // (srai (slli X, (XLen-8), (XLen-8) + C)
1437 // This can occur when Zbb is enabled, which makes sext_inreg i16/i8 legal.
1438 // This transform matches the code we get without Zbb. The shifts are more
1439 // compressible, and this can help expose CSE opportunities in the sdiv by
1440 // constant optimization.
1441 auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1));
1442 if (!N1C)
1443 break;
1444 SDValue N0 = Node->getOperand(0);
1445 if (N0.getOpcode() != ISD::SIGN_EXTEND_INREG || !N0.hasOneUse())
1446 break;
1447 unsigned ShAmt = N1C->getZExtValue();
1448 unsigned ExtSize =
1449 cast<VTSDNode>(N0.getOperand(1))->getVT().getSizeInBits();
1450 // ExtSize of 32 should use sraiw via tablegen pattern.
1451 if (ExtSize >= 32 || ShAmt >= ExtSize)
1452 break;
1453 unsigned LShAmt = Subtarget->getXLen() - ExtSize;
1454 SDNode *SLLI =
1455 CurDAG->getMachineNode(RISCV::SLLI, DL, VT, N0.getOperand(0),
1456 CurDAG->getTargetConstant(LShAmt, DL, VT));
1457 SDNode *SRAI = CurDAG->getMachineNode(
1458 RISCV::SRAI, DL, VT, SDValue(SLLI, 0),
1459 CurDAG->getTargetConstant(LShAmt + ShAmt, DL, VT));
1460 ReplaceNode(Node, SRAI);
1461 return;
1462 }
1464 // Optimize (sext_inreg (srl X, C), i8/i16) ->
1465 // (srai (slli X, XLen-ExtSize-C), XLen-ExtSize)
1466 // This is a bitfield extract pattern where we're extracting a signed
1467 // 8-bit or 16-bit field from position C.
1468 SDValue N0 = Node->getOperand(0);
1469 if (N0.getOpcode() != ISD::SRL || !N0.hasOneUse())
1470 break;
1471
1472 auto *ShAmtC = dyn_cast<ConstantSDNode>(N0.getOperand(1));
1473 if (!ShAmtC)
1474 break;
1475
1476 unsigned ExtSize =
1477 cast<VTSDNode>(Node->getOperand(1))->getVT().getSizeInBits();
1478 unsigned ShAmt = ShAmtC->getZExtValue();
1479 unsigned XLen = Subtarget->getXLen();
1480
1481 // Only handle types less than 32, and make sure the shift amount is valid.
1482 if (ExtSize >= 32 || ShAmt >= XLen - ExtSize)
1483 break;
1484
1485 unsigned LShAmt = XLen - ExtSize - ShAmt;
1486 SDNode *SLLI =
1487 CurDAG->getMachineNode(RISCV::SLLI, DL, VT, N0.getOperand(0),
1488 CurDAG->getTargetConstant(LShAmt, DL, VT));
1489 SDNode *SRAI = CurDAG->getMachineNode(
1490 RISCV::SRAI, DL, VT, SDValue(SLLI, 0),
1491 CurDAG->getTargetConstant(XLen - ExtSize, DL, VT));
1492 ReplaceNode(Node, SRAI);
1493 return;
1494 }
1495 case ISD::OR: {
1497 return;
1498
1499 break;
1500 }
1501 case ISD::XOR:
1503 return;
1504
1505 break;
1506 case ISD::AND: {
1507 auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1));
1508 if (!N1C)
1509 break;
1510
1511 SDValue N0 = Node->getOperand(0);
1512
1513 bool LeftShift = N0.getOpcode() == ISD::SHL;
1514 if (LeftShift || N0.getOpcode() == ISD::SRL) {
1515 auto *C = dyn_cast<ConstantSDNode>(N0.getOperand(1));
1516 if (!C)
1517 break;
1518 unsigned C2 = C->getZExtValue();
1519 unsigned XLen = Subtarget->getXLen();
1520 assert((C2 > 0 && C2 < XLen) && "Unexpected shift amount!");
1521
1522 // Keep track of whether this is a c.andi. If we can't use c.andi, the
1523 // shift pair might offer more compression opportunities.
1524 // TODO: We could check for C extension here, but we don't have many lit
1525 // tests with the C extension enabled so not checking gets better
1526 // coverage.
1527 // TODO: What if ANDI faster than shift?
1528 bool IsCANDI = isInt<6>(N1C->getSExtValue());
1529
1530 uint64_t C1 = N1C->getZExtValue();
1531
1532 // Clear irrelevant bits in the mask.
1533 if (LeftShift)
1535 else
1536 C1 &= maskTrailingOnes<uint64_t>(XLen - C2);
1537
1538 // Some transforms should only be done if the shift has a single use or
1539 // the AND would become (srli (slli X, 32), 32)
1540 bool OneUseOrZExtW = N0.hasOneUse() || C1 == UINT64_C(0xFFFFFFFF);
1541
1542 SDValue X = N0.getOperand(0);
1543
1544 // Turn (and (srl x, c2) c1) -> (srli (slli x, c3-c2), c3) if c1 is a mask
1545 // with c3 leading zeros.
1546 if (!LeftShift && isMask_64(C1)) {
1547 unsigned Leading = XLen - llvm::bit_width(C1);
1548 if (C2 < Leading) {
1549 // If the number of leading zeros is C2+32 this can be SRLIW.
1550 if (C2 + 32 == Leading) {
1551 SDNode *SRLIW = CurDAG->getMachineNode(
1552 RISCV::SRLIW, DL, VT, X, CurDAG->getTargetConstant(C2, DL, VT));
1553 ReplaceNode(Node, SRLIW);
1554 return;
1555 }
1556
1557 // (and (srl (sexti32 Y), c2), c1) -> (srliw (sraiw Y, 31), c3 - 32)
1558 // if c1 is a mask with c3 leading zeros and c2 >= 32 and c3-c2==1.
1559 //
1560 // This pattern occurs when (i32 (srl (sra 31), c3 - 32)) is type
1561 // legalized and goes through DAG combine.
1562 if (C2 >= 32 && (Leading - C2) == 1 && N0.hasOneUse() &&
1563 X.getOpcode() == ISD::SIGN_EXTEND_INREG &&
1564 cast<VTSDNode>(X.getOperand(1))->getVT() == MVT::i32) {
1565 SDNode *SRAIW =
1566 CurDAG->getMachineNode(RISCV::SRAIW, DL, VT, X.getOperand(0),
1567 CurDAG->getTargetConstant(31, DL, VT));
1568 SDNode *SRLIW = CurDAG->getMachineNode(
1569 RISCV::SRLIW, DL, VT, SDValue(SRAIW, 0),
1570 CurDAG->getTargetConstant(Leading - 32, DL, VT));
1571 ReplaceNode(Node, SRLIW);
1572 return;
1573 }
1574
1575 // Try to use an unsigned bitfield extract (e.g., th.extu) if
1576 // available.
1577 // Transform (and (srl x, C2), C1)
1578 // -> (<bfextract> x, msb, lsb)
1579 //
1580 // Make sure to keep this below the SRLIW cases, as we always want to
1581 // prefer the more common instruction.
1582 const unsigned Msb = llvm::bit_width(C1) + C2 - 1;
1583 const unsigned Lsb = C2;
1584 if (tryUnsignedBitfieldExtract(Node, DL, VT, X, Msb, Lsb))
1585 return;
1586
1587 // (srli (slli x, c3-c2), c3).
1588 // Skip if we could use (zext.w (sraiw X, C2)).
1589 bool Skip = Subtarget->hasStdExtZba() && Leading == 32 &&
1590 X.getOpcode() == ISD::SIGN_EXTEND_INREG &&
1591 cast<VTSDNode>(X.getOperand(1))->getVT() == MVT::i32;
1592 // Also Skip if we can use bexti or th.tst.
1593 Skip |= HasBitTest && Leading == XLen - 1;
1594 if (OneUseOrZExtW && !Skip) {
1595 SDNode *SLLI = CurDAG->getMachineNode(
1596 RISCV::SLLI, DL, VT, X,
1597 CurDAG->getTargetConstant(Leading - C2, DL, VT));
1598 SDNode *SRLI = CurDAG->getMachineNode(
1599 RISCV::SRLI, DL, VT, SDValue(SLLI, 0),
1600 CurDAG->getTargetConstant(Leading, DL, VT));
1601 ReplaceNode(Node, SRLI);
1602 return;
1603 }
1604 }
1605 }
1606
1607 // Turn (and (shl x, c2), c1) -> (srli (slli c2+c3), c3) if c1 is a mask
1608 // shifted by c2 bits with c3 leading zeros.
1609 if (LeftShift && isShiftedMask_64(C1)) {
1610 unsigned Leading = XLen - llvm::bit_width(C1);
1611
1612 if (C2 + Leading < XLen &&
1613 C1 == (maskTrailingOnes<uint64_t>(XLen - (C2 + Leading)) << C2)) {
1614 // Use slli.uw when possible.
1615 if ((XLen - (C2 + Leading)) == 32 && Subtarget->hasStdExtZba()) {
1616 SDNode *SLLI_UW =
1617 CurDAG->getMachineNode(RISCV::SLLI_UW, DL, VT, X,
1618 CurDAG->getTargetConstant(C2, DL, VT));
1619 ReplaceNode(Node, SLLI_UW);
1620 return;
1621 }
1622
1623 // Try to use an unsigned bitfield insert (e.g., nds.bfoz) if
1624 // available.
1625 // Transform (and (shl x, c2), c1)
1626 // -> (<bfinsert> x, msb, lsb)
1627 // e.g.
1628 // (and (shl x, 12), 0x00fff000)
1629 // If XLen = 32 and C2 = 12, then
1630 // Msb = 32 - 8 - 1 = 23 and Lsb = 12
1631 const unsigned Msb = XLen - Leading - 1;
1632 const unsigned Lsb = C2;
1633 if (tryUnsignedBitfieldInsertInZero(Node, DL, VT, X, Msb, Lsb))
1634 return;
1635
1636 if (OneUseOrZExtW && !IsCANDI) {
1637 // (packh x0, X)
1638 if (Subtarget->hasStdExtZbkb() && C1 == 0xff00 && C2 == 8) {
1639 SDNode *PACKH = CurDAG->getMachineNode(
1640 RISCV::PACKH, DL, VT,
1641 CurDAG->getRegister(RISCV::X0, Subtarget->getXLenVT()), X);
1642 ReplaceNode(Node, PACKH);
1643 return;
1644 }
1645 // (srli (slli c2+c3), c3)
1646 SDNode *SLLI = CurDAG->getMachineNode(
1647 RISCV::SLLI, DL, VT, X,
1648 CurDAG->getTargetConstant(C2 + Leading, DL, VT));
1649 SDNode *SRLI = CurDAG->getMachineNode(
1650 RISCV::SRLI, DL, VT, SDValue(SLLI, 0),
1651 CurDAG->getTargetConstant(Leading, DL, VT));
1652 ReplaceNode(Node, SRLI);
1653 return;
1654 }
1655 }
1656 }
1657
1658 // Turn (and (shr x, c2), c1) -> (slli (srli x, c2+c3), c3) if c1 is a
1659 // shifted mask with c2 leading zeros and c3 trailing zeros.
1660 if (!LeftShift && isShiftedMask_64(C1)) {
1661 unsigned Leading = XLen - llvm::bit_width(C1);
1662 unsigned Trailing = llvm::countr_zero(C1);
1663 if (Leading == C2 && C2 + Trailing < XLen && OneUseOrZExtW &&
1664 !IsCANDI) {
1665 unsigned SrliOpc = RISCV::SRLI;
1666 // If the input is zexti32 we should use SRLIW.
1667 if (X.getOpcode() == ISD::AND &&
1668 isa<ConstantSDNode>(X.getOperand(1)) &&
1669 X.getConstantOperandVal(1) == UINT64_C(0xFFFFFFFF)) {
1670 SrliOpc = RISCV::SRLIW;
1671 X = X.getOperand(0);
1672 }
1673 SDNode *SRLI = CurDAG->getMachineNode(
1674 SrliOpc, DL, VT, X,
1675 CurDAG->getTargetConstant(C2 + Trailing, DL, VT));
1676 SDNode *SLLI = CurDAG->getMachineNode(
1677 RISCV::SLLI, DL, VT, SDValue(SRLI, 0),
1678 CurDAG->getTargetConstant(Trailing, DL, VT));
1679 ReplaceNode(Node, SLLI);
1680 return;
1681 }
1682 // If the leading zero count is C2+32, we can use SRLIW instead of SRLI.
1683 if (Leading > 32 && (Leading - 32) == C2 && C2 + Trailing < 32 &&
1684 OneUseOrZExtW && !IsCANDI) {
1685 SDNode *SRLIW = CurDAG->getMachineNode(
1686 RISCV::SRLIW, DL, VT, X,
1687 CurDAG->getTargetConstant(C2 + Trailing, DL, VT));
1688 SDNode *SLLI = CurDAG->getMachineNode(
1689 RISCV::SLLI, DL, VT, SDValue(SRLIW, 0),
1690 CurDAG->getTargetConstant(Trailing, DL, VT));
1691 ReplaceNode(Node, SLLI);
1692 return;
1693 }
1694 // If we have 32 bits in the mask, we can use SLLI_UW instead of SLLI.
1695 if (Trailing > 0 && Leading + Trailing == 32 && C2 + Trailing < XLen &&
1696 OneUseOrZExtW && Subtarget->hasStdExtZba()) {
1697 SDNode *SRLI = CurDAG->getMachineNode(
1698 RISCV::SRLI, DL, VT, X,
1699 CurDAG->getTargetConstant(C2 + Trailing, DL, VT));
1700 SDNode *SLLI_UW = CurDAG->getMachineNode(
1701 RISCV::SLLI_UW, DL, VT, SDValue(SRLI, 0),
1702 CurDAG->getTargetConstant(Trailing, DL, VT));
1703 ReplaceNode(Node, SLLI_UW);
1704 return;
1705 }
1706 }
1707
1708 // Turn (and (shl x, c2), c1) -> (slli (srli x, c3-c2), c3) if c1 is a
1709 // shifted mask with no leading zeros and c3 trailing zeros.
1710 if (LeftShift && isShiftedMask_64(C1)) {
1711 unsigned Leading = XLen - llvm::bit_width(C1);
1712 unsigned Trailing = llvm::countr_zero(C1);
1713 if (Leading == 0 && C2 < Trailing && OneUseOrZExtW && !IsCANDI) {
1714 SDNode *SRLI = CurDAG->getMachineNode(
1715 RISCV::SRLI, DL, VT, X,
1716 CurDAG->getTargetConstant(Trailing - C2, DL, VT));
1717 SDNode *SLLI = CurDAG->getMachineNode(
1718 RISCV::SLLI, DL, VT, SDValue(SRLI, 0),
1719 CurDAG->getTargetConstant(Trailing, DL, VT));
1720 ReplaceNode(Node, SLLI);
1721 return;
1722 }
1723 // If we have (32-C2) leading zeros, we can use SRLIW instead of SRLI.
1724 if (C2 < Trailing && Leading + C2 == 32 && OneUseOrZExtW && !IsCANDI) {
1725 SDNode *SRLIW = CurDAG->getMachineNode(
1726 RISCV::SRLIW, DL, VT, X,
1727 CurDAG->getTargetConstant(Trailing - C2, DL, VT));
1728 SDNode *SLLI = CurDAG->getMachineNode(
1729 RISCV::SLLI, DL, VT, SDValue(SRLIW, 0),
1730 CurDAG->getTargetConstant(Trailing, DL, VT));
1731 ReplaceNode(Node, SLLI);
1732 return;
1733 }
1734
1735 // If we have 32 bits in the mask, we can use SLLI_UW instead of SLLI.
1736 if (C2 < Trailing && Leading + Trailing == 32 && OneUseOrZExtW &&
1737 Subtarget->hasStdExtZba()) {
1738 SDNode *SRLI = CurDAG->getMachineNode(
1739 RISCV::SRLI, DL, VT, X,
1740 CurDAG->getTargetConstant(Trailing - C2, DL, VT));
1741 SDNode *SLLI_UW = CurDAG->getMachineNode(
1742 RISCV::SLLI_UW, DL, VT, SDValue(SRLI, 0),
1743 CurDAG->getTargetConstant(Trailing, DL, VT));
1744 ReplaceNode(Node, SLLI_UW);
1745 return;
1746 }
1747 }
1748 }
1749
1750 const uint64_t C1 = N1C->getZExtValue();
1751
1752 if (N0.getOpcode() == ISD::SRA && isa<ConstantSDNode>(N0.getOperand(1)) &&
1753 N0.hasOneUse()) {
1754 unsigned C2 = N0.getConstantOperandVal(1);
1755 unsigned XLen = Subtarget->getXLen();
1756 assert((C2 > 0 && C2 < XLen) && "Unexpected shift amount!");
1757
1758 SDValue X = N0.getOperand(0);
1759
1760 // Prefer SRAIW + ANDI when possible.
1761 bool Skip = C2 > 32 && isInt<12>(N1C->getSExtValue()) &&
1762 X.getOpcode() == ISD::SHL &&
1763 isa<ConstantSDNode>(X.getOperand(1)) &&
1764 X.getConstantOperandVal(1) == 32;
1765 // Turn (and (sra x, c2), c1) -> (srli (srai x, c2-c3), c3) if c1 is a
1766 // mask with c3 leading zeros and c2 is larger than c3.
1767 if (isMask_64(C1) && !Skip) {
1768 unsigned Leading = XLen - llvm::bit_width(C1);
1769 if (C2 > Leading) {
1770 SDNode *SRAI = CurDAG->getMachineNode(
1771 RISCV::SRAI, DL, VT, X,
1772 CurDAG->getTargetConstant(C2 - Leading, DL, VT));
1773 SDNode *SRLI = CurDAG->getMachineNode(
1774 RISCV::SRLI, DL, VT, SDValue(SRAI, 0),
1775 CurDAG->getTargetConstant(Leading, DL, VT));
1776 ReplaceNode(Node, SRLI);
1777 return;
1778 }
1779 }
1780
1781 // Look for (and (sra y, c2), c1) where c1 is a shifted mask with c3
1782 // leading zeros and c4 trailing zeros. If c2 is greater than c3, we can
1783 // use (slli (srli (srai y, c2 - c3), c3 + c4), c4).
1784 if (isShiftedMask_64(C1) && !Skip) {
1785 unsigned Leading = XLen - llvm::bit_width(C1);
1786 unsigned Trailing = llvm::countr_zero(C1);
1787 if (C2 > Leading && Leading > 0 && Trailing > 0) {
1788 SDNode *SRAI = CurDAG->getMachineNode(
1789 RISCV::SRAI, DL, VT, N0.getOperand(0),
1790 CurDAG->getTargetConstant(C2 - Leading, DL, VT));
1791 SDNode *SRLI = CurDAG->getMachineNode(
1792 RISCV::SRLI, DL, VT, SDValue(SRAI, 0),
1793 CurDAG->getTargetConstant(Leading + Trailing, DL, VT));
1794 SDNode *SLLI = CurDAG->getMachineNode(
1795 RISCV::SLLI, DL, VT, SDValue(SRLI, 0),
1796 CurDAG->getTargetConstant(Trailing, DL, VT));
1797 ReplaceNode(Node, SLLI);
1798 return;
1799 }
1800 }
1801 }
1802
1803 // If C1 masks off the upper bits only (but can't be formed as an
1804 // ANDI), use an unsigned bitfield extract (e.g., th.extu), if
1805 // available.
1806 // Transform (and x, C1)
1807 // -> (<bfextract> x, msb, lsb)
1808 if (isMask_64(C1) && !isInt<12>(N1C->getSExtValue()) &&
1809 !(C1 == 0xffff && Subtarget->hasStdExtZbb()) &&
1810 !(C1 == 0xffffffff && Subtarget->hasStdExtZba())) {
1811 const unsigned Msb = llvm::bit_width(C1) - 1;
1812 if (tryUnsignedBitfieldExtract(Node, DL, VT, N0, Msb, 0))
1813 return;
1814 }
1815
1817 return;
1818
1819 break;
1820 }
1821 case ISD::MUL: {
1822 // Special case for calculating (mul (and X, C2), C1) where the full product
1823 // fits in XLen bits. We can shift X left by the number of leading zeros in
1824 // C2 and shift C1 left by XLen-lzcnt(C2). This will ensure the final
1825 // product has XLen trailing zeros, putting it in the output of MULHU. This
1826 // can avoid materializing a constant in a register for C2.
1827
1828 // RHS should be a constant.
1829 auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1));
1830 if (!N1C || !N1C->hasOneUse())
1831 break;
1832
1833 // LHS should be an AND with constant.
1834 SDValue N0 = Node->getOperand(0);
1835 if (N0.getOpcode() != ISD::AND || !isa<ConstantSDNode>(N0.getOperand(1)))
1836 break;
1837
1838 uint64_t C2 = N0.getConstantOperandVal(1);
1839
1840 // Constant should be a mask.
1841 if (!isMask_64(C2))
1842 break;
1843
1844 // If this can be an ANDI or ZEXT.H, don't do this if the ANDI/ZEXT has
1845 // multiple users or the constant is a simm12. This prevents inserting a
1846 // shift and still have uses of the AND/ZEXT. Shifting a simm12 will likely
1847 // make it more costly to materialize. Otherwise, using a SLLI might allow
1848 // it to be compressed.
1849 bool IsANDIOrZExt =
1850 isInt<12>(C2) ||
1851 (C2 == UINT64_C(0xFFFF) && Subtarget->hasStdExtZbb());
1852 // With XTHeadBb, we can use TH.EXTU.
1853 IsANDIOrZExt |= C2 == UINT64_C(0xFFFF) && Subtarget->hasVendorXTHeadBb();
1854 if (IsANDIOrZExt && (isInt<12>(N1C->getSExtValue()) || !N0.hasOneUse()))
1855 break;
1856 // If this can be a ZEXT.w, don't do this if the ZEXT has multiple users or
1857 // the constant is a simm32.
1858 bool IsZExtW = C2 == UINT64_C(0xFFFFFFFF) && Subtarget->hasStdExtZba();
1859 // With XTHeadBb, we can use TH.EXTU.
1860 IsZExtW |= C2 == UINT64_C(0xFFFFFFFF) && Subtarget->hasVendorXTHeadBb();
1861 if (IsZExtW && (isInt<32>(N1C->getSExtValue()) || !N0.hasOneUse()))
1862 break;
1863
1864 // We need to shift left the AND input and C1 by a total of XLen bits.
1865
1866 // How far left do we need to shift the AND input?
1867 unsigned XLen = Subtarget->getXLen();
1868 unsigned LeadingZeros = XLen - llvm::bit_width(C2);
1869
1870 // The constant gets shifted by the remaining amount unless that would
1871 // shift bits out.
1872 uint64_t C1 = N1C->getZExtValue();
1873 unsigned ConstantShift = XLen - LeadingZeros;
1874 if (ConstantShift > (XLen - llvm::bit_width(C1)))
1875 break;
1876
1877 uint64_t ShiftedC1 = C1 << ConstantShift;
1878 // If this RV32, we need to sign extend the constant.
1879 if (XLen == 32)
1880 ShiftedC1 = SignExtend64<32>(ShiftedC1);
1881
1882 // Create (mulhu (slli X, lzcnt(C2)), C1 << (XLen - lzcnt(C2))).
1883 SDNode *Imm = selectImm(CurDAG, DL, VT, ShiftedC1, *Subtarget).getNode();
1884 SDNode *SLLI =
1885 CurDAG->getMachineNode(RISCV::SLLI, DL, VT, N0.getOperand(0),
1886 CurDAG->getTargetConstant(LeadingZeros, DL, VT));
1887 SDNode *MULHU = CurDAG->getMachineNode(RISCV::MULHU, DL, VT,
1888 SDValue(SLLI, 0), SDValue(Imm, 0));
1889 ReplaceNode(Node, MULHU);
1890 return;
1891 }
1892 case ISD::SMUL_LOHI:
1893 case ISD::UMUL_LOHI:
1894 case RISCVISD::WMULSU:
1895 case RISCVISD::WADD:
1896 case RISCVISD::WSUB:
1897 case RISCVISD::WADDU:
1898 case RISCVISD::WSUBU: {
1899 assert(Subtarget->hasStdExtP() && !Subtarget->is64Bit() && VT == MVT::i32 &&
1900 "Unexpected opcode");
1901
1902 unsigned Opc;
1903 switch (Node->getOpcode()) {
1904 default:
1905 llvm_unreachable("Unexpected opcode");
1906 case ISD::SMUL_LOHI:
1907 Opc = RISCV::WMUL;
1908 break;
1909 case ISD::UMUL_LOHI:
1910 Opc = RISCV::WMULU;
1911 break;
1912 case RISCVISD::WMULSU:
1913 Opc = RISCV::WMULSU;
1914 break;
1915 case RISCVISD::WADD:
1916 Opc = RISCV::WADD;
1917 break;
1918 case RISCVISD::WSUB:
1919 Opc = RISCV::WSUB;
1920 break;
1921 case RISCVISD::WADDU:
1922 Opc = RISCV::WADDU;
1923 break;
1924 case RISCVISD::WSUBU:
1925 Opc = RISCV::WSUBU;
1926 break;
1927 }
1928
1929 SDNode *Result = CurDAG->getMachineNode(
1930 Opc, DL, MVT::Untyped, Node->getOperand(0), Node->getOperand(1));
1931
1932 auto [Lo, Hi] = extractGPRPair(CurDAG, DL, SDValue(Result, 0));
1933 ReplaceUses(SDValue(Node, 0), Lo);
1934 ReplaceUses(SDValue(Node, 1), Hi);
1935 CurDAG->RemoveDeadNode(Node);
1936 return;
1937 }
1938 case RISCVISD::WSLL:
1939 case RISCVISD::WSLA: {
1940 // Custom select WSLL/WSLA for RV32P.
1941 assert(Subtarget->hasStdExtP() && !Subtarget->is64Bit() && VT == MVT::i32 &&
1942 "Unexpected opcode");
1943
1944 bool IsSigned = Node->getOpcode() == RISCVISD::WSLA;
1945
1946 SDValue ShAmt = Node->getOperand(1);
1947
1948 unsigned Opc;
1949
1950 auto *ShAmtC = dyn_cast<ConstantSDNode>(ShAmt);
1951 if (ShAmtC && ShAmtC->getZExtValue() < 64) {
1952 Opc = IsSigned ? RISCV::WSLAI : RISCV::WSLLI;
1953 ShAmt = CurDAG->getTargetConstant(ShAmtC->getZExtValue(), DL, XLenVT);
1954 } else {
1955 Opc = IsSigned ? RISCV::WSLA : RISCV::WSLL;
1956 }
1957
1958 SDNode *WShift = CurDAG->getMachineNode(Opc, DL, MVT::Untyped,
1959 Node->getOperand(0), ShAmt);
1960
1961 auto [Lo, Hi] = extractGPRPair(CurDAG, DL, SDValue(WShift, 0));
1962 ReplaceUses(SDValue(Node, 0), Lo);
1963 ReplaceUses(SDValue(Node, 1), Hi);
1964 CurDAG->RemoveDeadNode(Node);
1965 return;
1966 }
1967 case ISD::LOAD: {
1968 if (tryIndexedLoad(Node))
1969 return;
1970
1971 if (Subtarget->hasVendorXCVmem() && !Subtarget->is64Bit()) {
1972 // We match post-incrementing load here
1974 if (Load->getAddressingMode() != ISD::POST_INC)
1975 break;
1976
1977 SDValue Chain = Node->getOperand(0);
1978 SDValue Base = Node->getOperand(1);
1979 SDValue Offset = Node->getOperand(2);
1980
1981 bool Simm12 = false;
1982 bool SignExtend = Load->getExtensionType() == ISD::SEXTLOAD;
1983
1984 if (auto ConstantOffset = dyn_cast<ConstantSDNode>(Offset)) {
1985 int ConstantVal = ConstantOffset->getSExtValue();
1986 Simm12 = isInt<12>(ConstantVal);
1987 if (Simm12)
1988 Offset = CurDAG->getSignedTargetConstant(ConstantVal, SDLoc(Offset),
1989 Offset.getValueType());
1990 }
1991
1992 unsigned Opcode = 0;
1993 switch (Load->getMemoryVT().getSimpleVT().SimpleTy) {
1994 case MVT::i8:
1995 if (Simm12 && SignExtend)
1996 Opcode = RISCV::CV_LB_ri_inc;
1997 else if (Simm12 && !SignExtend)
1998 Opcode = RISCV::CV_LBU_ri_inc;
1999 else if (!Simm12 && SignExtend)
2000 Opcode = RISCV::CV_LB_rr_inc;
2001 else
2002 Opcode = RISCV::CV_LBU_rr_inc;
2003 break;
2004 case MVT::i16:
2005 if (Simm12 && SignExtend)
2006 Opcode = RISCV::CV_LH_ri_inc;
2007 else if (Simm12 && !SignExtend)
2008 Opcode = RISCV::CV_LHU_ri_inc;
2009 else if (!Simm12 && SignExtend)
2010 Opcode = RISCV::CV_LH_rr_inc;
2011 else
2012 Opcode = RISCV::CV_LHU_rr_inc;
2013 break;
2014 case MVT::i32:
2015 if (Simm12)
2016 Opcode = RISCV::CV_LW_ri_inc;
2017 else
2018 Opcode = RISCV::CV_LW_rr_inc;
2019 break;
2020 default:
2021 break;
2022 }
2023 if (!Opcode)
2024 break;
2025
2026 ReplaceNode(Node, CurDAG->getMachineNode(Opcode, DL, XLenVT, XLenVT,
2027 Chain.getSimpleValueType(), Base,
2028 Offset, Chain));
2029 return;
2030 }
2031 break;
2032 }
2033 case RISCVISD::LD_RV32: {
2034 assert(Subtarget->hasStdExtZilsd() && "LD_RV32 is only used with Zilsd");
2035
2037 SDValue Chain = Node->getOperand(0);
2038 SDValue Addr = Node->getOperand(1);
2040
2041 SDValue Ops[] = {Base, Offset, Chain};
2042 MachineSDNode *New = CurDAG->getMachineNode(
2043 RISCV::LD_RV32, DL, {MVT::Untyped, MVT::Other}, Ops);
2044 auto [Lo, Hi] = extractGPRPair(CurDAG, DL, SDValue(New, 0));
2045 CurDAG->setNodeMemRefs(New, {cast<MemSDNode>(Node)->getMemOperand()});
2046 ReplaceUses(SDValue(Node, 0), Lo);
2047 ReplaceUses(SDValue(Node, 1), Hi);
2048 ReplaceUses(SDValue(Node, 2), SDValue(New, 1));
2049 CurDAG->RemoveDeadNode(Node);
2050 return;
2051 }
2052 case RISCVISD::SD_RV32: {
2054 SDValue Chain = Node->getOperand(0);
2055 SDValue Addr = Node->getOperand(3);
2057
2058 SDValue Lo = Node->getOperand(1);
2059 SDValue Hi = Node->getOperand(2);
2060
2061 SDValue RegPair;
2062 // Peephole to use X0_Pair for storing zero.
2064 RegPair = CurDAG->getRegister(RISCV::X0_Pair, MVT::Untyped);
2065 } else {
2066 RegPair = buildGPRPair(CurDAG, DL, MVT::Untyped, Lo, Hi);
2067 }
2068
2069 MachineSDNode *New = CurDAG->getMachineNode(RISCV::SD_RV32, DL, MVT::Other,
2070 {RegPair, Base, Offset, Chain});
2071 CurDAG->setNodeMemRefs(New, {cast<MemSDNode>(Node)->getMemOperand()});
2072 ReplaceUses(SDValue(Node, 0), SDValue(New, 0));
2073 CurDAG->RemoveDeadNode(Node);
2074 return;
2075 }
2076 case RISCVISD::MQWACC:
2077 case RISCVISD::MQRWACC: {
2078 assert(!Subtarget->is64Bit() && Subtarget->hasStdExtP() &&
2079 "Unexpected opcode");
2080
2081 SDValue Op0 = buildGPRPair(CurDAG, DL, MVT::Untyped, Node->getOperand(0),
2082 Node->getOperand(1));
2083 unsigned Opc = Opcode == RISCVISD::MQRWACC ? RISCV::MQRWACC : RISCV::MQWACC;
2084 MachineSDNode *New = CurDAG->getMachineNode(
2085 Opc, DL, MVT::Untyped, Op0, Node->getOperand(2), Node->getOperand(3));
2086 auto [Lo, Hi] = extractGPRPair(CurDAG, DL, SDValue(New, 0));
2087 ReplaceUses(SDValue(Node, 0), Lo);
2088 ReplaceUses(SDValue(Node, 1), Hi);
2089 CurDAG->RemoveDeadNode(Node);
2090 return;
2091 }
2092 case RISCVISD::ADDD:
2093 // Try to match WMACC pattern: ADDD where one operand pair comes from a
2094 // widening multiply.
2096 return;
2097
2098 // Fall through to regular ADDD selection.
2099 [[fallthrough]];
2100 case RISCVISD::SUBD:
2101 case RISCVISD::WADDAU:
2102 case RISCVISD::WSUBAU:
2103 case RISCVISD::WADDA:
2104 case RISCVISD::WSUBA: {
2105 assert(!Subtarget->is64Bit() && Subtarget->hasStdExtP() &&
2106 "Unexpected opcode");
2107
2108 SDValue Op0Lo = Node->getOperand(0);
2109 SDValue Op0Hi = Node->getOperand(1);
2110
2111 SDValue Op0;
2112 if (isNullConstant(Op0Lo) && isNullConstant(Op0Hi)) {
2113 Op0 = CurDAG->getRegister(RISCV::X0_Pair, MVT::Untyped);
2114 } else {
2115 Op0 = buildGPRPair(CurDAG, DL, MVT::Untyped, Op0Lo, Op0Hi);
2116 }
2117
2118 SDValue Op1Lo = Node->getOperand(2);
2119 SDValue Op1Hi = Node->getOperand(3);
2120
2121 MachineSDNode *New;
2122 if (Opcode == RISCVISD::WADDAU || Opcode == RISCVISD::WSUBAU ||
2123 Opcode == RISCVISD::WADDA || Opcode == RISCVISD::WSUBA) {
2124 // Widening accumulate: Op0 is the accumulator (GPRPair), Op1Lo and Op1Hi
2125 // are the two 32-bit values.
2126 unsigned Opc;
2127 switch (Opcode) {
2128 default:
2129 llvm_unreachable("Unexpected opcode");
2130 case RISCVISD::WADDAU:
2131 Opc = RISCV::WADDAU;
2132 break;
2133 case RISCVISD::WSUBAU:
2134 Opc = RISCV::WSUBAU;
2135 break;
2136 case RISCVISD::WADDA:
2137 Opc = RISCV::WADDA;
2138 break;
2139 case RISCVISD::WSUBA:
2140 Opc = RISCV::WSUBA;
2141 break;
2142 }
2143 New = CurDAG->getMachineNode(Opc, DL, MVT::Untyped, Op0, Op1Lo, Op1Hi);
2144 } else {
2145 SDValue Op1 = buildGPRPair(CurDAG, DL, MVT::Untyped, Op1Lo, Op1Hi);
2146
2147 unsigned Opc;
2148 switch (Opcode) {
2149 default:
2150 llvm_unreachable("Unexpected opcode");
2151 case RISCVISD::ADDD:
2152 Opc = RISCV::ADDD;
2153 break;
2154 case RISCVISD::SUBD:
2155 Opc = RISCV::SUBD;
2156 break;
2157 }
2158 New = CurDAG->getMachineNode(Opc, DL, MVT::Untyped, Op0, Op1);
2159 }
2160
2161 auto [Lo, Hi] = extractGPRPair(CurDAG, DL, SDValue(New, 0));
2162 ReplaceUses(SDValue(Node, 0), Lo);
2163 ReplaceUses(SDValue(Node, 1), Hi);
2164 CurDAG->RemoveDeadNode(Node);
2165 return;
2166 }
2168 unsigned IntNo = Node->getConstantOperandVal(0);
2169 switch (IntNo) {
2170 // By default we do not custom select any intrinsic.
2171 default:
2172 break;
2173 case Intrinsic::riscv_vmsgeu:
2174 case Intrinsic::riscv_vmsge: {
2175 SDValue Src1 = Node->getOperand(1);
2176 SDValue Src2 = Node->getOperand(2);
2177 bool IsUnsigned = IntNo == Intrinsic::riscv_vmsgeu;
2178 bool IsCmpConstant = false;
2179 bool IsCmpMinimum = false;
2180 // Only custom select scalar second operand.
2181 if (Src2.getValueType() != XLenVT)
2182 break;
2183 // Small constants are handled with patterns.
2184 int64_t CVal = 0;
2185 MVT Src1VT = Src1.getSimpleValueType();
2186 if (auto *C = dyn_cast<ConstantSDNode>(Src2)) {
2187 IsCmpConstant = true;
2188 CVal = C->getSExtValue();
2189 if (CVal >= -15 && CVal <= 16) {
2190 if (!IsUnsigned || CVal != 0)
2191 break;
2192 IsCmpMinimum = true;
2193 } else if (!IsUnsigned && CVal == APInt::getSignedMinValue(
2194 Src1VT.getScalarSizeInBits())
2195 .getSExtValue()) {
2196 IsCmpMinimum = true;
2197 }
2198 }
2199 unsigned VMSLTOpcode, VMNANDOpcode, VMSetOpcode, VMSGTOpcode;
2200 switch (RISCVTargetLowering::getLMUL(Src1VT)) {
2201 default:
2202 llvm_unreachable("Unexpected LMUL!");
2203#define CASE_VMSLT_OPCODES(lmulenum, suffix) \
2204 case RISCVVType::lmulenum: \
2205 VMSLTOpcode = IsUnsigned ? RISCV::PseudoVMSLTU_VX_##suffix \
2206 : RISCV::PseudoVMSLT_VX_##suffix; \
2207 VMSGTOpcode = IsUnsigned ? RISCV::PseudoVMSGTU_VX_##suffix \
2208 : RISCV::PseudoVMSGT_VX_##suffix; \
2209 break;
2210 CASE_VMSLT_OPCODES(LMUL_F8, MF8)
2211 CASE_VMSLT_OPCODES(LMUL_F4, MF4)
2212 CASE_VMSLT_OPCODES(LMUL_F2, MF2)
2213 CASE_VMSLT_OPCODES(LMUL_1, M1)
2214 CASE_VMSLT_OPCODES(LMUL_2, M2)
2215 CASE_VMSLT_OPCODES(LMUL_4, M4)
2216 CASE_VMSLT_OPCODES(LMUL_8, M8)
2217#undef CASE_VMSLT_OPCODES
2218 }
2219 // Mask operations use the LMUL from the mask type.
2220 switch (RISCVTargetLowering::getLMUL(VT)) {
2221 default:
2222 llvm_unreachable("Unexpected LMUL!");
2223#define CASE_VMNAND_VMSET_OPCODES(lmulenum, suffix) \
2224 case RISCVVType::lmulenum: \
2225 VMNANDOpcode = RISCV::PseudoVMNAND_MM_##suffix; \
2226 VMSetOpcode = RISCV::PseudoVMSET_M_##suffix; \
2227 break;
2228 CASE_VMNAND_VMSET_OPCODES(LMUL_F8, B64)
2229 CASE_VMNAND_VMSET_OPCODES(LMUL_F4, B32)
2230 CASE_VMNAND_VMSET_OPCODES(LMUL_F2, B16)
2231 CASE_VMNAND_VMSET_OPCODES(LMUL_1, B8)
2232 CASE_VMNAND_VMSET_OPCODES(LMUL_2, B4)
2233 CASE_VMNAND_VMSET_OPCODES(LMUL_4, B2)
2234 CASE_VMNAND_VMSET_OPCODES(LMUL_8, B1)
2235#undef CASE_VMNAND_VMSET_OPCODES
2236 }
2237 SDValue SEW = CurDAG->getTargetConstant(
2238 Log2_32(Src1VT.getScalarSizeInBits()), DL, XLenVT);
2239 SDValue MaskSEW = CurDAG->getTargetConstant(0, DL, XLenVT);
2240 SDValue VL;
2241 selectVLOp(Node->getOperand(3), VL);
2242
2243 // If vmsge(u) with minimum value, expand it to vmset.
2244 if (IsCmpMinimum) {
2246 CurDAG->getMachineNode(VMSetOpcode, DL, VT, VL, MaskSEW));
2247 return;
2248 }
2249
2250 if (IsCmpConstant) {
2251 SDValue Imm =
2252 selectImm(CurDAG, SDLoc(Src2), XLenVT, CVal - 1, *Subtarget);
2253
2254 ReplaceNode(Node, CurDAG->getMachineNode(VMSGTOpcode, DL, VT,
2255 {Src1, Imm, VL, SEW}));
2256 return;
2257 }
2258
2259 // Expand to
2260 // vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
2261 SDValue Cmp = SDValue(
2262 CurDAG->getMachineNode(VMSLTOpcode, DL, VT, {Src1, Src2, VL, SEW}),
2263 0);
2264 ReplaceNode(Node, CurDAG->getMachineNode(VMNANDOpcode, DL, VT,
2265 {Cmp, Cmp, VL, MaskSEW}));
2266 return;
2267 }
2268 case Intrinsic::riscv_vmsgeu_mask:
2269 case Intrinsic::riscv_vmsge_mask: {
2270 SDValue Src1 = Node->getOperand(2);
2271 SDValue Src2 = Node->getOperand(3);
2272 bool IsUnsigned = IntNo == Intrinsic::riscv_vmsgeu_mask;
2273 bool IsCmpConstant = false;
2274 bool IsCmpMinimum = false;
2275 // Only custom select scalar second operand.
2276 if (Src2.getValueType() != XLenVT)
2277 break;
2278 // Small constants are handled with patterns.
2279 MVT Src1VT = Src1.getSimpleValueType();
2280 int64_t CVal = 0;
2281 if (auto *C = dyn_cast<ConstantSDNode>(Src2)) {
2282 IsCmpConstant = true;
2283 CVal = C->getSExtValue();
2284 if (CVal >= -15 && CVal <= 16) {
2285 if (!IsUnsigned || CVal != 0)
2286 break;
2287 IsCmpMinimum = true;
2288 } else if (!IsUnsigned && CVal == APInt::getSignedMinValue(
2289 Src1VT.getScalarSizeInBits())
2290 .getSExtValue()) {
2291 IsCmpMinimum = true;
2292 }
2293 }
2294 unsigned VMSLTOpcode, VMSLTMaskOpcode, VMXOROpcode, VMANDNOpcode,
2295 VMOROpcode, VMSGTMaskOpcode;
2296 switch (RISCVTargetLowering::getLMUL(Src1VT)) {
2297 default:
2298 llvm_unreachable("Unexpected LMUL!");
2299#define CASE_VMSLT_OPCODES(lmulenum, suffix) \
2300 case RISCVVType::lmulenum: \
2301 VMSLTOpcode = IsUnsigned ? RISCV::PseudoVMSLTU_VX_##suffix \
2302 : RISCV::PseudoVMSLT_VX_##suffix; \
2303 VMSLTMaskOpcode = IsUnsigned ? RISCV::PseudoVMSLTU_VX_##suffix##_MASK \
2304 : RISCV::PseudoVMSLT_VX_##suffix##_MASK; \
2305 VMSGTMaskOpcode = IsUnsigned ? RISCV::PseudoVMSGTU_VX_##suffix##_MASK \
2306 : RISCV::PseudoVMSGT_VX_##suffix##_MASK; \
2307 break;
2308 CASE_VMSLT_OPCODES(LMUL_F8, MF8)
2309 CASE_VMSLT_OPCODES(LMUL_F4, MF4)
2310 CASE_VMSLT_OPCODES(LMUL_F2, MF2)
2311 CASE_VMSLT_OPCODES(LMUL_1, M1)
2312 CASE_VMSLT_OPCODES(LMUL_2, M2)
2313 CASE_VMSLT_OPCODES(LMUL_4, M4)
2314 CASE_VMSLT_OPCODES(LMUL_8, M8)
2315#undef CASE_VMSLT_OPCODES
2316 }
2317 // Mask operations use the LMUL from the mask type.
2318 switch (RISCVTargetLowering::getLMUL(VT)) {
2319 default:
2320 llvm_unreachable("Unexpected LMUL!");
2321#define CASE_VMXOR_VMANDN_VMOR_OPCODES(lmulenum, suffix) \
2322 case RISCVVType::lmulenum: \
2323 VMXOROpcode = RISCV::PseudoVMXOR_MM_##suffix; \
2324 VMANDNOpcode = RISCV::PseudoVMANDN_MM_##suffix; \
2325 VMOROpcode = RISCV::PseudoVMOR_MM_##suffix; \
2326 break;
2327 CASE_VMXOR_VMANDN_VMOR_OPCODES(LMUL_F8, B64)
2328 CASE_VMXOR_VMANDN_VMOR_OPCODES(LMUL_F4, B32)
2329 CASE_VMXOR_VMANDN_VMOR_OPCODES(LMUL_F2, B16)
2334#undef CASE_VMXOR_VMANDN_VMOR_OPCODES
2335 }
2336 SDValue SEW = CurDAG->getTargetConstant(
2337 Log2_32(Src1VT.getScalarSizeInBits()), DL, XLenVT);
2338 SDValue MaskSEW = CurDAG->getTargetConstant(0, DL, XLenVT);
2339 SDValue VL;
2340 selectVLOp(Node->getOperand(5), VL);
2341 SDValue MaskedOff = Node->getOperand(1);
2342 SDValue Mask = Node->getOperand(4);
2343
2344 // If vmsge(u) with minimum value, expand it to vmor mask, maskedoff.
2345 if (IsCmpMinimum) {
2346 // We don't need vmor if the MaskedOff and the Mask are the same
2347 // value.
2348 if (Mask == MaskedOff) {
2349 ReplaceUses(Node, Mask.getNode());
2350 return;
2351 }
2353 CurDAG->getMachineNode(VMOROpcode, DL, VT,
2354 {Mask, MaskedOff, VL, MaskSEW}));
2355 return;
2356 }
2357
2358 // If the MaskedOff value and the Mask are the same value use
2359 // vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
2360 // This avoids needing to copy v0 to vd before starting the next sequence.
2361 if (Mask == MaskedOff) {
2362 SDValue Cmp = SDValue(
2363 CurDAG->getMachineNode(VMSLTOpcode, DL, VT, {Src1, Src2, VL, SEW}),
2364 0);
2365 ReplaceNode(Node, CurDAG->getMachineNode(VMANDNOpcode, DL, VT,
2366 {Mask, Cmp, VL, MaskSEW}));
2367 return;
2368 }
2369
2370 SDValue PolicyOp =
2371 CurDAG->getTargetConstant(RISCVVType::TAIL_AGNOSTIC, DL, XLenVT);
2372
2373 if (IsCmpConstant) {
2374 SDValue Imm =
2375 selectImm(CurDAG, SDLoc(Src2), XLenVT, CVal - 1, *Subtarget);
2376
2377 ReplaceNode(Node, CurDAG->getMachineNode(
2378 VMSGTMaskOpcode, DL, VT,
2379 {MaskedOff, Src1, Imm, Mask, VL, SEW, PolicyOp}));
2380 return;
2381 }
2382
2383 // Otherwise use
2384 // vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
2385 // The result is mask undisturbed.
2386 // We use the same instructions to emulate mask agnostic behavior, because
2387 // the agnostic result can be either undisturbed or all 1.
2388 SDValue Cmp = SDValue(CurDAG->getMachineNode(VMSLTMaskOpcode, DL, VT,
2389 {MaskedOff, Src1, Src2, Mask,
2390 VL, SEW, PolicyOp}),
2391 0);
2392 // vmxor.mm vd, vd, v0 is used to update active value.
2393 ReplaceNode(Node, CurDAG->getMachineNode(VMXOROpcode, DL, VT,
2394 {Cmp, Mask, VL, MaskSEW}));
2395 return;
2396 }
2397 case Intrinsic::riscv_vsetvli:
2398 case Intrinsic::riscv_vsetvlimax:
2399 return selectVSETVLI(Node);
2400 case Intrinsic::riscv_sf_vsettnt:
2401 case Intrinsic::riscv_sf_vsettm:
2402 case Intrinsic::riscv_sf_vsettk:
2403 return selectXSfmmVSET(Node);
2404 }
2405 break;
2406 }
2408 unsigned IntNo = Node->getConstantOperandVal(1);
2409 switch (IntNo) {
2410 // By default we do not custom select any intrinsic.
2411 default:
2412 break;
2413 case Intrinsic::riscv_vlseg2:
2414 case Intrinsic::riscv_vlseg3:
2415 case Intrinsic::riscv_vlseg4:
2416 case Intrinsic::riscv_vlseg5:
2417 case Intrinsic::riscv_vlseg6:
2418 case Intrinsic::riscv_vlseg7:
2419 case Intrinsic::riscv_vlseg8: {
2420 selectVLSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2421 /*IsStrided*/ false);
2422 return;
2423 }
2424 case Intrinsic::riscv_vlseg2_mask:
2425 case Intrinsic::riscv_vlseg3_mask:
2426 case Intrinsic::riscv_vlseg4_mask:
2427 case Intrinsic::riscv_vlseg5_mask:
2428 case Intrinsic::riscv_vlseg6_mask:
2429 case Intrinsic::riscv_vlseg7_mask:
2430 case Intrinsic::riscv_vlseg8_mask: {
2431 selectVLSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2432 /*IsStrided*/ false);
2433 return;
2434 }
2435 case Intrinsic::riscv_vlsseg2:
2436 case Intrinsic::riscv_vlsseg3:
2437 case Intrinsic::riscv_vlsseg4:
2438 case Intrinsic::riscv_vlsseg5:
2439 case Intrinsic::riscv_vlsseg6:
2440 case Intrinsic::riscv_vlsseg7:
2441 case Intrinsic::riscv_vlsseg8: {
2442 selectVLSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2443 /*IsStrided*/ true);
2444 return;
2445 }
2446 case Intrinsic::riscv_vlsseg2_mask:
2447 case Intrinsic::riscv_vlsseg3_mask:
2448 case Intrinsic::riscv_vlsseg4_mask:
2449 case Intrinsic::riscv_vlsseg5_mask:
2450 case Intrinsic::riscv_vlsseg6_mask:
2451 case Intrinsic::riscv_vlsseg7_mask:
2452 case Intrinsic::riscv_vlsseg8_mask: {
2453 selectVLSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2454 /*IsStrided*/ true);
2455 return;
2456 }
2457 case Intrinsic::riscv_vloxseg2:
2458 case Intrinsic::riscv_vloxseg3:
2459 case Intrinsic::riscv_vloxseg4:
2460 case Intrinsic::riscv_vloxseg5:
2461 case Intrinsic::riscv_vloxseg6:
2462 case Intrinsic::riscv_vloxseg7:
2463 case Intrinsic::riscv_vloxseg8:
2464 selectVLXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2465 /*IsOrdered*/ true);
2466 return;
2467 case Intrinsic::riscv_vluxseg2:
2468 case Intrinsic::riscv_vluxseg3:
2469 case Intrinsic::riscv_vluxseg4:
2470 case Intrinsic::riscv_vluxseg5:
2471 case Intrinsic::riscv_vluxseg6:
2472 case Intrinsic::riscv_vluxseg7:
2473 case Intrinsic::riscv_vluxseg8:
2474 selectVLXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2475 /*IsOrdered*/ false);
2476 return;
2477 case Intrinsic::riscv_vloxseg2_mask:
2478 case Intrinsic::riscv_vloxseg3_mask:
2479 case Intrinsic::riscv_vloxseg4_mask:
2480 case Intrinsic::riscv_vloxseg5_mask:
2481 case Intrinsic::riscv_vloxseg6_mask:
2482 case Intrinsic::riscv_vloxseg7_mask:
2483 case Intrinsic::riscv_vloxseg8_mask:
2484 selectVLXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2485 /*IsOrdered*/ true);
2486 return;
2487 case Intrinsic::riscv_vluxseg2_mask:
2488 case Intrinsic::riscv_vluxseg3_mask:
2489 case Intrinsic::riscv_vluxseg4_mask:
2490 case Intrinsic::riscv_vluxseg5_mask:
2491 case Intrinsic::riscv_vluxseg6_mask:
2492 case Intrinsic::riscv_vluxseg7_mask:
2493 case Intrinsic::riscv_vluxseg8_mask:
2494 selectVLXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2495 /*IsOrdered*/ false);
2496 return;
2497 case Intrinsic::riscv_vlseg8ff:
2498 case Intrinsic::riscv_vlseg7ff:
2499 case Intrinsic::riscv_vlseg6ff:
2500 case Intrinsic::riscv_vlseg5ff:
2501 case Intrinsic::riscv_vlseg4ff:
2502 case Intrinsic::riscv_vlseg3ff:
2503 case Intrinsic::riscv_vlseg2ff: {
2504 selectVLSEGFF(Node, getSegInstNF(IntNo), /*IsMasked*/ false);
2505 return;
2506 }
2507 case Intrinsic::riscv_vlseg8ff_mask:
2508 case Intrinsic::riscv_vlseg7ff_mask:
2509 case Intrinsic::riscv_vlseg6ff_mask:
2510 case Intrinsic::riscv_vlseg5ff_mask:
2511 case Intrinsic::riscv_vlseg4ff_mask:
2512 case Intrinsic::riscv_vlseg3ff_mask:
2513 case Intrinsic::riscv_vlseg2ff_mask: {
2514 selectVLSEGFF(Node, getSegInstNF(IntNo), /*IsMasked*/ true);
2515 return;
2516 }
2517 case Intrinsic::riscv_vloxei:
2518 case Intrinsic::riscv_vloxei_mask:
2519 case Intrinsic::riscv_vluxei:
2520 case Intrinsic::riscv_vluxei_mask: {
2521 bool IsMasked = IntNo == Intrinsic::riscv_vloxei_mask ||
2522 IntNo == Intrinsic::riscv_vluxei_mask;
2523 bool IsOrdered = IntNo == Intrinsic::riscv_vloxei ||
2524 IntNo == Intrinsic::riscv_vloxei_mask;
2525
2526 MVT VT = Node->getSimpleValueType(0);
2527 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2528
2529 unsigned CurOp = 2;
2531 Operands.push_back(Node->getOperand(CurOp++));
2532
2533 MVT IndexVT;
2534 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked,
2535 /*IsStridedOrIndexed*/ true, Operands,
2536 /*IsLoad=*/true, &IndexVT);
2537
2539 "Element count mismatch");
2540
2543 unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
2544 if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
2545 reportFatalUsageError("The V extension does not support EEW=64 for "
2546 "index values when XLEN=32");
2547 }
2548 const RISCV::VLX_VSXPseudo *P = RISCV::getVLXPseudo(
2549 IsMasked, IsOrdered, IndexLog2EEW, static_cast<unsigned>(LMUL),
2550 static_cast<unsigned>(IndexLMUL));
2552 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands);
2553
2554 CurDAG->setNodeMemRefs(Load, {cast<MemSDNode>(Node)->getMemOperand()});
2555
2557 return;
2558 }
2559 case Intrinsic::riscv_vlm:
2560 case Intrinsic::riscv_vle:
2561 case Intrinsic::riscv_vle_mask:
2562 case Intrinsic::riscv_vlse:
2563 case Intrinsic::riscv_vlse_mask: {
2564 bool IsMasked = IntNo == Intrinsic::riscv_vle_mask ||
2565 IntNo == Intrinsic::riscv_vlse_mask;
2566 bool IsStrided =
2567 IntNo == Intrinsic::riscv_vlse || IntNo == Intrinsic::riscv_vlse_mask;
2568
2569 MVT VT = Node->getSimpleValueType(0);
2570 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2571
2572 // The riscv_vlm intrinsic are always tail agnostic and no passthru
2573 // operand at the IR level. In pseudos, they have both policy and
2574 // passthru operand. The passthru operand is needed to track the
2575 // "tail undefined" state, and the policy is there just for
2576 // for consistency - it will always be "don't care" for the
2577 // unmasked form.
2578 bool HasPassthruOperand = IntNo != Intrinsic::riscv_vlm;
2579 unsigned CurOp = 2;
2581 if (HasPassthruOperand)
2582 Operands.push_back(Node->getOperand(CurOp++));
2583 else {
2584 // We eagerly lower to implicit_def (instead of undef), as we
2585 // otherwise fail to select nodes such as: nxv1i1 = undef
2586 SDNode *Passthru =
2587 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, VT);
2588 Operands.push_back(SDValue(Passthru, 0));
2589 }
2590 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked, IsStrided,
2591 Operands, /*IsLoad=*/true);
2592
2594 const RISCV::VLEPseudo *P =
2595 RISCV::getVLEPseudo(IsMasked, IsStrided, /*FF*/ false, Log2SEW,
2596 static_cast<unsigned>(LMUL));
2598 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands);
2599
2600 CurDAG->setNodeMemRefs(Load, {cast<MemSDNode>(Node)->getMemOperand()});
2601
2603 return;
2604 }
2605 case Intrinsic::riscv_vleff:
2606 case Intrinsic::riscv_vleff_mask: {
2607 bool IsMasked = IntNo == Intrinsic::riscv_vleff_mask;
2608
2609 MVT VT = Node->getSimpleValueType(0);
2610 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2611
2612 unsigned CurOp = 2;
2614 Operands.push_back(Node->getOperand(CurOp++));
2615 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked,
2616 /*IsStridedOrIndexed*/ false, Operands,
2617 /*IsLoad=*/true);
2618
2620 const RISCV::VLEPseudo *P =
2621 RISCV::getVLEPseudo(IsMasked, /*Strided*/ false, /*FF*/ true,
2622 Log2SEW, static_cast<unsigned>(LMUL));
2623 MachineSDNode *Load = CurDAG->getMachineNode(
2624 P->Pseudo, DL, Node->getVTList(), Operands);
2625 CurDAG->setNodeMemRefs(Load, {cast<MemSDNode>(Node)->getMemOperand()});
2626
2628 return;
2629 }
2630 case Intrinsic::riscv_nds_vln:
2631 case Intrinsic::riscv_nds_vln_mask:
2632 case Intrinsic::riscv_nds_vlnu:
2633 case Intrinsic::riscv_nds_vlnu_mask: {
2634 bool IsMasked = IntNo == Intrinsic::riscv_nds_vln_mask ||
2635 IntNo == Intrinsic::riscv_nds_vlnu_mask;
2636 bool IsUnsigned = IntNo == Intrinsic::riscv_nds_vlnu ||
2637 IntNo == Intrinsic::riscv_nds_vlnu_mask;
2638
2639 MVT VT = Node->getSimpleValueType(0);
2640 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2641 unsigned CurOp = 2;
2643
2644 Operands.push_back(Node->getOperand(CurOp++));
2645 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked,
2646 /*IsStridedOrIndexed=*/false, Operands,
2647 /*IsLoad=*/true);
2648
2650 const RISCV::NDSVLNPseudo *P = RISCV::getNDSVLNPseudo(
2651 IsMasked, IsUnsigned, Log2SEW, static_cast<unsigned>(LMUL));
2653 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands);
2654
2655 if (auto *MemOp = dyn_cast<MemSDNode>(Node))
2656 CurDAG->setNodeMemRefs(Load, {MemOp->getMemOperand()});
2657
2659 return;
2660 }
2661 }
2662 break;
2663 }
2664 case ISD::INTRINSIC_VOID: {
2665 unsigned IntNo = Node->getConstantOperandVal(1);
2666 switch (IntNo) {
2667 case Intrinsic::riscv_vsseg2:
2668 case Intrinsic::riscv_vsseg3:
2669 case Intrinsic::riscv_vsseg4:
2670 case Intrinsic::riscv_vsseg5:
2671 case Intrinsic::riscv_vsseg6:
2672 case Intrinsic::riscv_vsseg7:
2673 case Intrinsic::riscv_vsseg8: {
2674 selectVSSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2675 /*IsStrided*/ false);
2676 return;
2677 }
2678 case Intrinsic::riscv_vsseg2_mask:
2679 case Intrinsic::riscv_vsseg3_mask:
2680 case Intrinsic::riscv_vsseg4_mask:
2681 case Intrinsic::riscv_vsseg5_mask:
2682 case Intrinsic::riscv_vsseg6_mask:
2683 case Intrinsic::riscv_vsseg7_mask:
2684 case Intrinsic::riscv_vsseg8_mask: {
2685 selectVSSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2686 /*IsStrided*/ false);
2687 return;
2688 }
2689 case Intrinsic::riscv_vssseg2:
2690 case Intrinsic::riscv_vssseg3:
2691 case Intrinsic::riscv_vssseg4:
2692 case Intrinsic::riscv_vssseg5:
2693 case Intrinsic::riscv_vssseg6:
2694 case Intrinsic::riscv_vssseg7:
2695 case Intrinsic::riscv_vssseg8: {
2696 selectVSSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2697 /*IsStrided*/ true);
2698 return;
2699 }
2700 case Intrinsic::riscv_vssseg2_mask:
2701 case Intrinsic::riscv_vssseg3_mask:
2702 case Intrinsic::riscv_vssseg4_mask:
2703 case Intrinsic::riscv_vssseg5_mask:
2704 case Intrinsic::riscv_vssseg6_mask:
2705 case Intrinsic::riscv_vssseg7_mask:
2706 case Intrinsic::riscv_vssseg8_mask: {
2707 selectVSSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2708 /*IsStrided*/ true);
2709 return;
2710 }
2711 case Intrinsic::riscv_vsoxseg2:
2712 case Intrinsic::riscv_vsoxseg3:
2713 case Intrinsic::riscv_vsoxseg4:
2714 case Intrinsic::riscv_vsoxseg5:
2715 case Intrinsic::riscv_vsoxseg6:
2716 case Intrinsic::riscv_vsoxseg7:
2717 case Intrinsic::riscv_vsoxseg8:
2718 selectVSXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2719 /*IsOrdered*/ true);
2720 return;
2721 case Intrinsic::riscv_vsuxseg2:
2722 case Intrinsic::riscv_vsuxseg3:
2723 case Intrinsic::riscv_vsuxseg4:
2724 case Intrinsic::riscv_vsuxseg5:
2725 case Intrinsic::riscv_vsuxseg6:
2726 case Intrinsic::riscv_vsuxseg7:
2727 case Intrinsic::riscv_vsuxseg8:
2728 selectVSXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2729 /*IsOrdered*/ false);
2730 return;
2731 case Intrinsic::riscv_vsoxseg2_mask:
2732 case Intrinsic::riscv_vsoxseg3_mask:
2733 case Intrinsic::riscv_vsoxseg4_mask:
2734 case Intrinsic::riscv_vsoxseg5_mask:
2735 case Intrinsic::riscv_vsoxseg6_mask:
2736 case Intrinsic::riscv_vsoxseg7_mask:
2737 case Intrinsic::riscv_vsoxseg8_mask:
2738 selectVSXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2739 /*IsOrdered*/ true);
2740 return;
2741 case Intrinsic::riscv_vsuxseg2_mask:
2742 case Intrinsic::riscv_vsuxseg3_mask:
2743 case Intrinsic::riscv_vsuxseg4_mask:
2744 case Intrinsic::riscv_vsuxseg5_mask:
2745 case Intrinsic::riscv_vsuxseg6_mask:
2746 case Intrinsic::riscv_vsuxseg7_mask:
2747 case Intrinsic::riscv_vsuxseg8_mask:
2748 selectVSXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2749 /*IsOrdered*/ false);
2750 return;
2751 case Intrinsic::riscv_vsoxei:
2752 case Intrinsic::riscv_vsoxei_mask:
2753 case Intrinsic::riscv_vsuxei:
2754 case Intrinsic::riscv_vsuxei_mask: {
2755 bool IsMasked = IntNo == Intrinsic::riscv_vsoxei_mask ||
2756 IntNo == Intrinsic::riscv_vsuxei_mask;
2757 bool IsOrdered = IntNo == Intrinsic::riscv_vsoxei ||
2758 IntNo == Intrinsic::riscv_vsoxei_mask;
2759
2760 MVT VT = Node->getOperand(2)->getSimpleValueType(0);
2761 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2762
2763 unsigned CurOp = 2;
2765 Operands.push_back(Node->getOperand(CurOp++)); // Store value.
2766
2767 MVT IndexVT;
2768 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked,
2769 /*IsStridedOrIndexed*/ true, Operands,
2770 /*IsLoad=*/false, &IndexVT);
2771
2773 "Element count mismatch");
2774
2777 unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
2778 if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
2779 reportFatalUsageError("The V extension does not support EEW=64 for "
2780 "index values when XLEN=32");
2781 }
2782 const RISCV::VLX_VSXPseudo *P = RISCV::getVSXPseudo(
2783 IsMasked, IsOrdered, IndexLog2EEW,
2784 static_cast<unsigned>(LMUL), static_cast<unsigned>(IndexLMUL));
2786 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands);
2787
2788 CurDAG->setNodeMemRefs(Store, {cast<MemSDNode>(Node)->getMemOperand()});
2789
2791 return;
2792 }
2793 case Intrinsic::riscv_vsm:
2794 case Intrinsic::riscv_vse:
2795 case Intrinsic::riscv_vse_mask:
2796 case Intrinsic::riscv_vsse:
2797 case Intrinsic::riscv_vsse_mask: {
2798 bool IsMasked = IntNo == Intrinsic::riscv_vse_mask ||
2799 IntNo == Intrinsic::riscv_vsse_mask;
2800 bool IsStrided =
2801 IntNo == Intrinsic::riscv_vsse || IntNo == Intrinsic::riscv_vsse_mask;
2802
2803 MVT VT = Node->getOperand(2)->getSimpleValueType(0);
2804 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2805
2806 unsigned CurOp = 2;
2808 Operands.push_back(Node->getOperand(CurOp++)); // Store value.
2809
2810 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked, IsStrided,
2811 Operands);
2812
2814 const RISCV::VSEPseudo *P = RISCV::getVSEPseudo(
2815 IsMasked, IsStrided, Log2SEW, static_cast<unsigned>(LMUL));
2817 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands);
2818 CurDAG->setNodeMemRefs(Store, {cast<MemSDNode>(Node)->getMemOperand()});
2819
2821 return;
2822 }
2823 case Intrinsic::riscv_sf_vc_x_se:
2824 case Intrinsic::riscv_sf_vc_i_se:
2826 return;
2827 case Intrinsic::riscv_sf_vlte8:
2828 case Intrinsic::riscv_sf_vlte16:
2829 case Intrinsic::riscv_sf_vlte32:
2830 case Intrinsic::riscv_sf_vlte64: {
2831 unsigned Log2SEW;
2832 unsigned PseudoInst;
2833 switch (IntNo) {
2834 case Intrinsic::riscv_sf_vlte8:
2835 PseudoInst = RISCV::PseudoSF_VLTE8;
2836 Log2SEW = 3;
2837 break;
2838 case Intrinsic::riscv_sf_vlte16:
2839 PseudoInst = RISCV::PseudoSF_VLTE16;
2840 Log2SEW = 4;
2841 break;
2842 case Intrinsic::riscv_sf_vlte32:
2843 PseudoInst = RISCV::PseudoSF_VLTE32;
2844 Log2SEW = 5;
2845 break;
2846 case Intrinsic::riscv_sf_vlte64:
2847 PseudoInst = RISCV::PseudoSF_VLTE64;
2848 Log2SEW = 6;
2849 break;
2850 }
2851
2852 SDValue SEWOp = CurDAG->getTargetConstant(Log2SEW, DL, XLenVT);
2853 SDValue TWidenOp = CurDAG->getTargetConstant(1, DL, XLenVT);
2854 SDValue Operands[] = {Node->getOperand(2),
2855 Node->getOperand(3),
2856 Node->getOperand(4),
2857 SEWOp,
2858 TWidenOp,
2859 Node->getOperand(0)};
2860
2861 MachineSDNode *TileLoad =
2862 CurDAG->getMachineNode(PseudoInst, DL, Node->getVTList(), Operands);
2863 CurDAG->setNodeMemRefs(TileLoad,
2864 {cast<MemSDNode>(Node)->getMemOperand()});
2865
2866 ReplaceNode(Node, TileLoad);
2867 return;
2868 }
2869 case Intrinsic::riscv_sf_mm_s_s:
2870 case Intrinsic::riscv_sf_mm_s_u:
2871 case Intrinsic::riscv_sf_mm_u_s:
2872 case Intrinsic::riscv_sf_mm_u_u:
2873 case Intrinsic::riscv_sf_mm_e5m2_e5m2:
2874 case Intrinsic::riscv_sf_mm_e5m2_e4m3:
2875 case Intrinsic::riscv_sf_mm_e4m3_e5m2:
2876 case Intrinsic::riscv_sf_mm_e4m3_e4m3:
2877 case Intrinsic::riscv_sf_mm_f_f: {
2878 bool HasFRM = false;
2879 unsigned PseudoInst;
2880 switch (IntNo) {
2881 case Intrinsic::riscv_sf_mm_s_s:
2882 PseudoInst = RISCV::PseudoSF_MM_S_S;
2883 break;
2884 case Intrinsic::riscv_sf_mm_s_u:
2885 PseudoInst = RISCV::PseudoSF_MM_S_U;
2886 break;
2887 case Intrinsic::riscv_sf_mm_u_s:
2888 PseudoInst = RISCV::PseudoSF_MM_U_S;
2889 break;
2890 case Intrinsic::riscv_sf_mm_u_u:
2891 PseudoInst = RISCV::PseudoSF_MM_U_U;
2892 break;
2893 case Intrinsic::riscv_sf_mm_e5m2_e5m2:
2894 PseudoInst = RISCV::PseudoSF_MM_E5M2_E5M2;
2895 HasFRM = true;
2896 break;
2897 case Intrinsic::riscv_sf_mm_e5m2_e4m3:
2898 PseudoInst = RISCV::PseudoSF_MM_E5M2_E4M3;
2899 HasFRM = true;
2900 break;
2901 case Intrinsic::riscv_sf_mm_e4m3_e5m2:
2902 PseudoInst = RISCV::PseudoSF_MM_E4M3_E5M2;
2903 HasFRM = true;
2904 break;
2905 case Intrinsic::riscv_sf_mm_e4m3_e4m3:
2906 PseudoInst = RISCV::PseudoSF_MM_E4M3_E4M3;
2907 HasFRM = true;
2908 break;
2909 case Intrinsic::riscv_sf_mm_f_f:
2910 if (Node->getOperand(3).getValueType().getScalarType() == MVT::bf16)
2911 PseudoInst = RISCV::PseudoSF_MM_F_F_ALT;
2912 else
2913 PseudoInst = RISCV::PseudoSF_MM_F_F;
2914 HasFRM = true;
2915 break;
2916 }
2917 uint64_t TileNum = Node->getConstantOperandVal(2);
2918 SDValue Op1 = Node->getOperand(3);
2919 SDValue Op2 = Node->getOperand(4);
2920 MVT VT = Op1->getSimpleValueType(0);
2921 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2922 SDValue TmOp = Node->getOperand(5);
2923 SDValue TnOp = Node->getOperand(6);
2924 SDValue TkOp = Node->getOperand(7);
2925 SDValue TWidenOp = Node->getOperand(8);
2926 SDValue Chain = Node->getOperand(0);
2927
2928 // sf.mm.f.f with sew=32, twiden=2 is invalid
2929 if (IntNo == Intrinsic::riscv_sf_mm_f_f && Log2SEW == 5 &&
2930 TWidenOp->getAsZExtVal() == 2)
2931 reportFatalUsageError("sf.mm.f.f doesn't support (sew=32, twiden=2)");
2932
2934 {CurDAG->getRegister(getTileReg(TileNum), XLenVT), Op1, Op2});
2935 if (HasFRM)
2936 Operands.push_back(
2937 CurDAG->getTargetConstant(RISCVFPRndMode::DYN, DL, XLenVT));
2938 Operands.append({TmOp, TnOp, TkOp,
2939 CurDAG->getTargetConstant(Log2SEW, DL, XLenVT), TWidenOp,
2940 Chain});
2941
2942 auto *NewNode =
2943 CurDAG->getMachineNode(PseudoInst, DL, Node->getVTList(), Operands);
2944
2945 ReplaceNode(Node, NewNode);
2946 return;
2947 }
2948 case Intrinsic::riscv_sf_vtzero_t: {
2949 uint64_t TileNum = Node->getConstantOperandVal(2);
2950 SDValue Tm = Node->getOperand(3);
2951 SDValue Tn = Node->getOperand(4);
2952 SDValue Log2SEW = Node->getOperand(5);
2953 SDValue TWiden = Node->getOperand(6);
2954 SDValue Chain = Node->getOperand(0);
2955 auto *NewNode = CurDAG->getMachineNode(
2956 RISCV::PseudoSF_VTZERO_T, DL, Node->getVTList(),
2957 {CurDAG->getRegister(getTileReg(TileNum), XLenVT), Tm, Tn, Log2SEW,
2958 TWiden, Chain});
2959
2960 ReplaceNode(Node, NewNode);
2961 return;
2962 }
2963 }
2964 break;
2965 }
2966 case ISD::BITCAST: {
2967 MVT SrcVT = Node->getOperand(0).getSimpleValueType();
2968 // Just drop bitcasts between vectors if both are fixed or both are
2969 // scalable.
2970 if ((VT.isScalableVector() && SrcVT.isScalableVector()) ||
2971 (VT.isFixedLengthVector() && SrcVT.isFixedLengthVector())) {
2972 ReplaceUses(SDValue(Node, 0), Node->getOperand(0));
2973 CurDAG->RemoveDeadNode(Node);
2974 return;
2975 }
2976 if (Subtarget->hasStdExtP()) {
2977 bool Is32BitCast =
2978 (VT == MVT::i32 && (SrcVT == MVT::v4i8 || SrcVT == MVT::v2i16)) ||
2979 (SrcVT == MVT::i32 && (VT == MVT::v4i8 || VT == MVT::v2i16));
2980 bool Is64BitCast =
2981 (VT == MVT::i64 && (SrcVT == MVT::v8i8 || SrcVT == MVT::v4i16 ||
2982 SrcVT == MVT::v2i32)) ||
2983 (SrcVT == MVT::i64 &&
2984 (VT == MVT::v8i8 || VT == MVT::v4i16 || VT == MVT::v2i32));
2985 if (Is32BitCast || Is64BitCast) {
2986 ReplaceUses(SDValue(Node, 0), Node->getOperand(0));
2987 CurDAG->RemoveDeadNode(Node);
2988 return;
2989 }
2990 }
2991 break;
2992 }
2993 case ISD::SPLAT_VECTOR: {
2994 if (!Subtarget->hasStdExtP())
2995 break;
2996 if (auto *ConstNode = dyn_cast<ConstantSDNode>(Node->getOperand(0))) {
2997 bool IsDoubleWide = Subtarget->isPExtPackedDoubleType(VT);
2998
2999 if (ConstNode->isZero()) {
3000 MCPhysReg X0Reg = IsDoubleWide ? RISCV::X0_Pair : RISCV::X0;
3001 SDValue New =
3002 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, X0Reg, VT);
3003 ReplaceNode(Node, New.getNode());
3004 return;
3005 }
3006
3007 unsigned EltSize = VT.getVectorElementType().getSizeInBits();
3008 APInt Val = ConstNode->getAPIntValue().trunc(EltSize);
3009
3010 // Use LI for all ones since it can be compressed to c.li.
3011 if (Val.isAllOnes() && !IsDoubleWide) {
3012 SDNode *NewNode = CurDAG->getMachineNode(
3013 RISCV::ADDI, DL, VT, CurDAG->getRegister(RISCV::X0, VT),
3014 CurDAG->getAllOnesConstant(DL, XLenVT, /*IsTarget=*/true));
3015 ReplaceNode(Node, NewNode);
3016 return;
3017 }
3018
3019 // Find the smallest splat.
3020 if (Val.getBitWidth() > 16 && Val.isSplat(16))
3021 Val = Val.trunc(16);
3022 if (Val.getBitWidth() > 8 && Val.isSplat(8))
3023 Val = Val.trunc(8);
3024
3025 EltSize = Val.getBitWidth();
3026 int64_t Imm = Val.getSExtValue();
3027
3028 unsigned Opc = 0;
3029 if (EltSize == 8) {
3030 Opc = IsDoubleWide ? RISCV::PLI_DB : RISCV::PLI_B;
3031 } else if (EltSize == 16 && isInt<10>(Imm)) {
3032 Opc = IsDoubleWide ? RISCV::PLI_DH : RISCV::PLI_H;
3033 } else if (!IsDoubleWide && EltSize == 32 && isInt<10>(Imm)) {
3034 Opc = RISCV::PLI_W;
3035 } else if (EltSize == 16 && isShiftedInt<10, 6>(Imm)) {
3036 Opc = IsDoubleWide ? RISCV::PLUI_DH : RISCV::PLUI_H;
3037 Imm = Imm >> 6;
3038 } else if (!IsDoubleWide && EltSize == 32 && isShiftedInt<10, 22>(Imm)) {
3039 Opc = RISCV::PLUI_W;
3040 Imm = Imm >> 22;
3041 }
3042
3043 if (Opc) {
3044 SDNode *NewNode = CurDAG->getMachineNode(
3045 Opc, DL, VT, CurDAG->getSignedTargetConstant(Imm, DL, XLenVT));
3046 ReplaceNode(Node, NewNode);
3047 return;
3048 }
3049 }
3050
3051 break;
3052 }
3054 if (Subtarget->hasStdExtP()) {
3055 MVT SrcVT = Node->getOperand(0).getSimpleValueType();
3056 if ((VT == MVT::v2i32 && SrcVT == MVT::i64) ||
3057 (VT == MVT::v4i8 && SrcVT == MVT::i32)) {
3058 ReplaceUses(SDValue(Node, 0), Node->getOperand(0));
3059 CurDAG->RemoveDeadNode(Node);
3060 return;
3061 }
3062 }
3063 break;
3065 case RISCVISD::TUPLE_INSERT: {
3066 SDValue V = Node->getOperand(0);
3067 SDValue SubV = Node->getOperand(1);
3068 SDLoc DL(SubV);
3069 auto Idx = Node->getConstantOperandVal(2);
3070 MVT SubVecVT = SubV.getSimpleValueType();
3071
3072 const RISCVTargetLowering &TLI = *Subtarget->getTargetLowering();
3073 MVT SubVecContainerVT = SubVecVT;
3074 // Establish the correct scalable-vector types for any fixed-length type.
3075 if (SubVecVT.isFixedLengthVector()) {
3076 SubVecContainerVT = TLI.getContainerForFixedLengthVector(SubVecVT);
3078 [[maybe_unused]] bool ExactlyVecRegSized =
3079 Subtarget->expandVScale(SubVecVT.getSizeInBits())
3080 .isKnownMultipleOf(Subtarget->expandVScale(VecRegSize));
3081 assert(isPowerOf2_64(Subtarget->expandVScale(SubVecVT.getSizeInBits())
3082 .getKnownMinValue()));
3083 assert(Idx == 0 && (ExactlyVecRegSized || V.isUndef()));
3084 }
3085 MVT ContainerVT = VT;
3086 if (VT.isFixedLengthVector())
3087 ContainerVT = TLI.getContainerForFixedLengthVector(VT);
3088
3089 const auto *TRI = Subtarget->getRegisterInfo();
3090 unsigned SubRegIdx;
3091 std::tie(SubRegIdx, Idx) =
3093 ContainerVT, SubVecContainerVT, Idx, TRI);
3094
3095 // If the Idx hasn't been completely eliminated then this is a subvector
3096 // insert which doesn't naturally align to a vector register. These must
3097 // be handled using instructions to manipulate the vector registers.
3098 if (Idx != 0)
3099 break;
3100
3101 RISCVVType::VLMUL SubVecLMUL =
3102 RISCVTargetLowering::getLMUL(SubVecContainerVT);
3103 [[maybe_unused]] bool IsSubVecPartReg =
3104 SubVecLMUL == RISCVVType::VLMUL::LMUL_F2 ||
3105 SubVecLMUL == RISCVVType::VLMUL::LMUL_F4 ||
3106 SubVecLMUL == RISCVVType::VLMUL::LMUL_F8;
3107 assert((V.getValueType().isRISCVVectorTuple() || !IsSubVecPartReg ||
3108 V.isUndef()) &&
3109 "Expecting lowering to have created legal INSERT_SUBVECTORs when "
3110 "the subvector is smaller than a full-sized register");
3111
3112 // If we haven't set a SubRegIdx, then we must be going between
3113 // equally-sized LMUL groups (e.g. VR -> VR). This can be done as a copy.
3114 if (SubRegIdx == RISCV::NoSubRegister) {
3115 unsigned InRegClassID =
3118 InRegClassID &&
3119 "Unexpected subvector extraction");
3120 SDValue RC = CurDAG->getTargetConstant(InRegClassID, DL, XLenVT);
3121 SDNode *NewNode = CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
3122 DL, VT, SubV, RC);
3123 ReplaceNode(Node, NewNode);
3124 return;
3125 }
3126
3127 SDValue Insert = CurDAG->getTargetInsertSubreg(SubRegIdx, DL, VT, V, SubV);
3128 ReplaceNode(Node, Insert.getNode());
3129 return;
3130 }
3132 case RISCVISD::TUPLE_EXTRACT: {
3133 if (Subtarget->hasStdExtP())
3134 break;
3135
3136 SDValue V = Node->getOperand(0);
3137 auto Idx = Node->getConstantOperandVal(1);
3138 MVT InVT = V.getSimpleValueType();
3139
3140 SDLoc DL(V);
3141
3142 const RISCVTargetLowering &TLI = *Subtarget->getTargetLowering();
3143 MVT SubVecContainerVT = VT;
3144 // Establish the correct scalable-vector types for any fixed-length type.
3145 if (VT.isFixedLengthVector()) {
3146 assert(Idx == 0);
3147 SubVecContainerVT = TLI.getContainerForFixedLengthVector(VT);
3148 }
3149 if (InVT.isFixedLengthVector())
3150 InVT = TLI.getContainerForFixedLengthVector(InVT);
3151
3152 const auto *TRI = Subtarget->getRegisterInfo();
3153 unsigned SubRegIdx;
3154 std::tie(SubRegIdx, Idx) =
3156 InVT, SubVecContainerVT, Idx, TRI);
3157
3158 // If the Idx hasn't been completely eliminated then this is a subvector
3159 // extract which doesn't naturally align to a vector register. These must
3160 // be handled using instructions to manipulate the vector registers.
3161 if (Idx != 0)
3162 break;
3163
3164 // If we haven't set a SubRegIdx, then we must be going between
3165 // equally-sized LMUL types (e.g. VR -> VR). This can be done as a copy.
3166 if (SubRegIdx == RISCV::NoSubRegister) {
3167 unsigned InRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(InVT);
3169 InRegClassID &&
3170 "Unexpected subvector extraction");
3171 SDValue RC = CurDAG->getTargetConstant(InRegClassID, DL, XLenVT);
3172 SDNode *NewNode =
3173 CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, DL, VT, V, RC);
3174 ReplaceNode(Node, NewNode);
3175 return;
3176 }
3177
3178 SDValue Extract = CurDAG->getTargetExtractSubreg(SubRegIdx, DL, VT, V);
3179 ReplaceNode(Node, Extract.getNode());
3180 return;
3181 }
3182 case RISCVISD::VMV_S_X_VL:
3183 case RISCVISD::VFMV_S_F_VL:
3184 case RISCVISD::VMV_V_X_VL:
3185 case RISCVISD::VFMV_V_F_VL: {
3186 // Try to match splat of a scalar load to a strided load with stride of x0.
3187 bool IsScalarMove = Node->getOpcode() == RISCVISD::VMV_S_X_VL ||
3188 Node->getOpcode() == RISCVISD::VFMV_S_F_VL;
3189 if (!Node->getOperand(0).isUndef())
3190 break;
3191 SDValue Src = Node->getOperand(1);
3192 auto *Ld = dyn_cast<LoadSDNode>(Src);
3193 // Can't fold load update node because the second
3194 // output is used so that load update node can't be removed.
3195 if (!Ld || Ld->isIndexed())
3196 break;
3197 EVT MemVT = Ld->getMemoryVT();
3198 // The memory VT should be the same size as the element type.
3199 if (MemVT.getStoreSize() != VT.getVectorElementType().getStoreSize())
3200 break;
3201 if (!IsProfitableToFold(Src, Node, Node) ||
3202 !IsLegalToFold(Src, Node, Node, TM.getOptLevel()))
3203 break;
3204
3205 SDValue VL;
3206 if (IsScalarMove) {
3207 // We could deal with more VL if we update the VSETVLI insert pass to
3208 // avoid introducing more VSETVLI.
3209 if (!isOneConstant(Node->getOperand(2)))
3210 break;
3211 selectVLOp(Node->getOperand(2), VL);
3212 } else
3213 selectVLOp(Node->getOperand(2), VL);
3214
3215 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
3216 SDValue SEW = CurDAG->getTargetConstant(Log2SEW, DL, XLenVT);
3217
3218 // If VL=1, then we don't need to do a strided load and can just do a
3219 // regular load.
3220 bool IsStrided = !isOneConstant(VL);
3221
3222 // Only do a strided load if we have optimized zero-stride vector load.
3223 if (IsStrided && !Subtarget->hasOptimizedZeroStrideLoad())
3224 break;
3225
3227 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, VT), 0),
3228 Ld->getBasePtr()};
3229 if (IsStrided)
3230 Operands.push_back(CurDAG->getRegister(RISCV::X0, XLenVT));
3232 SDValue PolicyOp = CurDAG->getTargetConstant(Policy, DL, XLenVT);
3233 Operands.append({VL, SEW, PolicyOp, Ld->getChain()});
3234
3236 const RISCV::VLEPseudo *P = RISCV::getVLEPseudo(
3237 /*IsMasked*/ false, IsStrided, /*FF*/ false,
3238 Log2SEW, static_cast<unsigned>(LMUL));
3240 CurDAG->getMachineNode(P->Pseudo, DL, {VT, MVT::Other}, Operands);
3241 // Update the chain.
3242 ReplaceUses(Src.getValue(1), SDValue(Load, 1));
3243 // Record the mem-refs
3244 CurDAG->setNodeMemRefs(Load, {Ld->getMemOperand()});
3245 // Replace the splat with the vlse.
3247 return;
3248 }
3249 case RISCVISD::LPAD_CALL:
3250 case RISCVISD::LPAD_CALL_INDIRECT: {
3251 bool IsIndirect = Opcode == RISCVISD::LPAD_CALL_INDIRECT;
3252 unsigned PseudoOpc = IsIndirect ? RISCV::PseudoCALLIndirectLpadAlign
3253 : RISCV::PseudoCALLLpadAlign;
3254
3255 uint32_t LpadLabel = 0;
3256 if (PreferredLandingPadLabel.getNumOccurrences() > 0) {
3258 report_fatal_error("riscv-landing-pad-label=<val>, <val> needs to fit "
3259 "in unsigned 20-bits");
3260 LpadLabel = PreferredLandingPadLabel;
3261 }
3262
3263 // Preserve the argument-register and register-mask operands, between
3264 // Callee and the optional glue, so the pseudo call still reports its
3265 // call-preserved mask to the register allocator.
3267 Ops.push_back(Node->getOperand(1));
3268 Ops.push_back(CurDAG->getTargetConstant(LpadLabel, DL, XLenVT));
3269
3270 unsigned NumOps = Node->getNumOperands();
3271 bool HasGlue = Node->getGluedNode() != nullptr;
3272 unsigned RegOperandsEnd = HasGlue ? NumOps - 1 : NumOps;
3273 for (unsigned I = 2; I != RegOperandsEnd; ++I)
3274 Ops.push_back(Node->getOperand(I));
3275
3276 Ops.push_back(Node->getOperand(0));
3277 if (HasGlue)
3278 Ops.push_back(Node->getOperand(NumOps - 1));
3279
3281 CurDAG->getMachineNode(PseudoOpc, DL, Node->getVTList(), Ops));
3282 return;
3283 }
3284 case ISD::PREFETCH:
3285 // MIPS's prefetch instruction already encodes the hint within the
3286 // instruction itself, so no extra NTL hint is needed.
3287 if (Subtarget->hasVendorXMIPSCBOP())
3288 break;
3289
3290 unsigned Locality = Node->getConstantOperandVal(3);
3291 if (Locality > 2)
3292 break;
3293
3294 auto *LoadStoreMem = cast<MemSDNode>(Node);
3295 MachineMemOperand *MMO = LoadStoreMem->getMemOperand();
3297
3298 int NontemporalLevel = 0;
3299 switch (Locality) {
3300 case 0:
3301 NontemporalLevel = 3; // NTL.ALL
3302 break;
3303 case 1:
3304 NontemporalLevel = 1; // NTL.PALL
3305 break;
3306 case 2:
3307 NontemporalLevel = 0; // NTL.P1
3308 break;
3309 default:
3310 llvm_unreachable("unexpected locality value.");
3311 }
3312
3313 if (NontemporalLevel & 0b1)
3315 if (NontemporalLevel & 0b10)
3317 break;
3318 }
3319
3320 // Select the default instruction.
3321 SelectCode(Node);
3322}
3323
3325 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
3326 std::vector<SDValue> &OutOps) {
3327 // Always produce a register and immediate operand, as expected by
3328 // RISCVAsmPrinter::PrintAsmMemoryOperand.
3329 switch (ConstraintID) {
3332 SDValue Op0, Op1;
3333 [[maybe_unused]] bool Found = SelectAddrRegImm(Op, Op0, Op1);
3334 assert(Found && "SelectAddrRegImm should always succeed");
3335 OutOps.push_back(Op0);
3336 OutOps.push_back(Op1);
3337 return false;
3338 }
3340 OutOps.push_back(Op);
3341 OutOps.push_back(
3342 CurDAG->getTargetConstant(0, SDLoc(Op), Subtarget->getXLenVT()));
3343 return false;
3344 default:
3345 report_fatal_error("Unexpected asm memory constraint " +
3346 InlineAsm::getMemConstraintName(ConstraintID));
3347 }
3348
3349 return true;
3350}
3351
3353 SDValue &Offset) {
3354 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
3355 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT());
3356 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Subtarget->getXLenVT());
3357 return true;
3358 }
3359
3360 return false;
3361}
3362
3363// Fold constant addresses.
3364static bool selectConstantAddr(SelectionDAG *CurDAG, const SDLoc &DL,
3365 const MVT VT, const RISCVSubtarget *Subtarget,
3367 bool IsPrefetch = false) {
3368 if (!isa<ConstantSDNode>(Addr))
3369 return false;
3370
3371 int64_t CVal = cast<ConstantSDNode>(Addr)->getSExtValue();
3372
3373 // If the constant is a simm12, we can fold the whole constant and use X0 as
3374 // the base. If the constant can be materialized with LUI+simm12, use LUI as
3375 // the base. We can't use generateInstSeq because it favors LUI+ADDIW.
3376 int64_t Lo12 = SignExtend64<12>(CVal);
3377 int64_t Hi = (uint64_t)CVal - (uint64_t)Lo12;
3378 if (!Subtarget->is64Bit() || isInt<32>(Hi)) {
3379 if (IsPrefetch && (Lo12 & 0b11111) != 0)
3380 return false;
3381 if (Hi) {
3382 int64_t Hi20 = (Hi >> 12) & 0xfffff;
3383 Base = SDValue(
3384 CurDAG->getMachineNode(RISCV::LUI, DL, VT,
3385 CurDAG->getTargetConstant(Hi20, DL, VT)),
3386 0);
3387 } else {
3388 Base = CurDAG->getRegister(RISCV::X0, VT);
3389 }
3390 Offset = CurDAG->getSignedTargetConstant(Lo12, DL, VT);
3391 return true;
3392 }
3393
3394 // Ask how constant materialization would handle this constant.
3395 RISCVMatInt::InstSeq Seq = RISCVMatInt::generateInstSeq(CVal, *Subtarget);
3396
3397 // If the last instruction would be an ADDI, we can fold its immediate and
3398 // emit the rest of the sequence as the base.
3399 if (Seq.back().getOpcode() != RISCV::ADDI)
3400 return false;
3401 Lo12 = Seq.back().getImm();
3402 if (IsPrefetch && (Lo12 & 0b11111) != 0)
3403 return false;
3404
3405 // Drop the last instruction.
3406 Seq.pop_back();
3407 assert(!Seq.empty() && "Expected more instructions in sequence");
3408
3409 Base = selectImmSeq(CurDAG, DL, VT, Seq);
3410 Offset = CurDAG->getSignedTargetConstant(Lo12, DL, VT);
3411 return true;
3412}
3413
3414// Is this ADD instruction only used as the base pointer of scalar loads and
3415// stores?
3417 for (auto *User : Add->users()) {
3418 if (User->getOpcode() != ISD::LOAD && User->getOpcode() != ISD::STORE &&
3419 User->getOpcode() != RISCVISD::LD_RV32 &&
3420 User->getOpcode() != RISCVISD::SD_RV32 &&
3421 User->getOpcode() != ISD::ATOMIC_LOAD &&
3422 User->getOpcode() != ISD::ATOMIC_STORE)
3423 return false;
3424 EVT VT = cast<MemSDNode>(User)->getMemoryVT();
3425 if (!VT.isScalarInteger() && VT != MVT::f16 && VT != MVT::f32 &&
3426 VT != MVT::f64)
3427 return false;
3428 // Don't allow stores of the value. It must be used as the address.
3429 if (User->getOpcode() == ISD::STORE &&
3430 cast<StoreSDNode>(User)->getValue() == Add)
3431 return false;
3432 if (User->getOpcode() == ISD::ATOMIC_STORE &&
3433 cast<AtomicSDNode>(User)->getVal() == Add)
3434 return false;
3435 if (User->getOpcode() == RISCVISD::SD_RV32 &&
3436 (User->getOperand(0) == Add || User->getOperand(1) == Add))
3437 return false;
3438 if (isStrongerThanMonotonic(cast<MemSDNode>(User)->getSuccessOrdering()))
3439 return false;
3440 }
3441
3442 return true;
3443}
3444
3446 switch (User->getOpcode()) {
3447 default:
3448 return false;
3449 case ISD::LOAD:
3450 case RISCVISD::LD_RV32:
3451 case ISD::ATOMIC_LOAD:
3452 break;
3453 case ISD::STORE:
3454 // Don't allow stores of Add. It must only be used as the address.
3456 return false;
3457 break;
3458 case RISCVISD::SD_RV32:
3459 // Don't allow stores of Add. It must only be used as the address.
3460 if (User->getOperand(0) == Add || User->getOperand(1) == Add)
3461 return false;
3462 break;
3463 case ISD::ATOMIC_STORE:
3464 // Don't allow stores of Add. It must only be used as the address.
3465 if (cast<AtomicSDNode>(User)->getVal() == Add)
3466 return false;
3467 break;
3468 }
3469
3470 return true;
3471}
3472
3473// To prevent SelectAddrRegImm from folding offsets that conflict with the
3474// fusion of PseudoMovAddr, check if the offset of every use of a given address
3475// is within the alignment.
3477 Align Alignment) {
3478 assert(Addr->getOpcode() == RISCVISD::ADD_LO);
3479 for (auto *User : Addr->users()) {
3480 // If the user is a load or store, then the offset is 0 which is always
3481 // within alignment.
3482 if (isRegImmLoadOrStore(User, Addr))
3483 continue;
3484
3485 if (CurDAG->isBaseWithConstantOffset(SDValue(User, 0))) {
3486 int64_t CVal = cast<ConstantSDNode>(User->getOperand(1))->getSExtValue();
3487 if (!isInt<12>(CVal) || Alignment <= CVal)
3488 return false;
3489
3490 // Make sure all uses are foldable load/stores.
3491 for (auto *AddUser : User->users())
3492 if (!isRegImmLoadOrStore(AddUser, SDValue(User, 0)))
3493 return false;
3494
3495 continue;
3496 }
3497
3498 return false;
3499 }
3500
3501 return true;
3502}
3503
3505 SDValue &Offset) {
3506 if (SelectAddrFrameIndex(Addr, Base, Offset))
3507 return true;
3508
3509 SDLoc DL(Addr);
3510 MVT VT = Addr.getSimpleValueType();
3511
3512 if (Addr.getOpcode() == RISCVISD::ADD_LO) {
3513 bool CanFold = true;
3514 // Unconditionally fold if operand 1 is not a global address (e.g.
3515 // externsymbol)
3516 if (auto *GA = dyn_cast<GlobalAddressSDNode>(Addr.getOperand(1))) {
3517 const DataLayout &DL = CurDAG->getDataLayout();
3518 Align Alignment = commonAlignment(
3519 GA->getGlobal()->getPointerAlignment(DL), GA->getOffset());
3520 if (!areOffsetsWithinAlignment(Addr, Alignment))
3521 CanFold = false;
3522 }
3523 if (CanFold) {
3524 Base = Addr.getOperand(0);
3525 Offset = Addr.getOperand(1);
3526 return true;
3527 }
3528 }
3529
3530 if (CurDAG->isBaseWithConstantOffset(Addr)) {
3531 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3532 if (isInt<12>(CVal)) {
3533 Base = Addr.getOperand(0);
3534 if (Base.getOpcode() == RISCVISD::ADD_LO) {
3535 SDValue LoOperand = Base.getOperand(1);
3536 if (auto *GA = dyn_cast<GlobalAddressSDNode>(LoOperand)) {
3537 // If the Lo in (ADD_LO hi, lo) is a global variable's address
3538 // (its low part, really), then we can rely on the alignment of that
3539 // variable to provide a margin of safety before low part can overflow
3540 // the 12 bits of the load/store offset. Check if CVal falls within
3541 // that margin; if so (low part + CVal) can't overflow.
3542 const DataLayout &DL = CurDAG->getDataLayout();
3543 Align Alignment = commonAlignment(
3544 GA->getGlobal()->getPointerAlignment(DL), GA->getOffset());
3545 if ((CVal == 0 || Alignment > CVal) &&
3546 areOffsetsWithinAlignment(Base, Alignment)) {
3547 int64_t CombinedOffset = CVal + GA->getOffset();
3548 Base = Base.getOperand(0);
3549 Offset = CurDAG->getTargetGlobalAddress(
3550 GA->getGlobal(), SDLoc(LoOperand), LoOperand.getValueType(),
3551 CombinedOffset, GA->getTargetFlags());
3552 return true;
3553 }
3554 }
3555 }
3556
3557 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Base))
3558 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), VT);
3559 Offset = CurDAG->getSignedTargetConstant(CVal, DL, VT);
3560 return true;
3561 }
3562 }
3563
3564 // Handle ADD with large immediates.
3565 if (Addr.getOpcode() == ISD::ADD && isa<ConstantSDNode>(Addr.getOperand(1))) {
3566 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3567 assert(!isInt<12>(CVal) && "simm12 not already handled?");
3568
3569 // Handle immediates in the range [-4096,-2049] or [2048, 4094]. We can use
3570 // an ADDI for part of the offset and fold the rest into the load/store.
3571 // This mirrors the AddiPair PatFrag in RISCVInstrInfo.td.
3572 if (CVal >= -4096 && CVal <= 4094) {
3573 int64_t Adj = CVal < 0 ? -2048 : 2047;
3574 Base = SDValue(
3575 CurDAG->getMachineNode(RISCV::ADDI, DL, VT, Addr.getOperand(0),
3576 CurDAG->getSignedTargetConstant(Adj, DL, VT)),
3577 0);
3578 Offset = CurDAG->getSignedTargetConstant(CVal - Adj, DL, VT);
3579 return true;
3580 }
3581
3582 // For larger immediates, we might be able to save one instruction from
3583 // constant materialization by folding the Lo12 bits of the immediate into
3584 // the address. We should only do this if the ADD is only used by loads and
3585 // stores that can fold the lo12 bits. Otherwise, the ADD will get iseled
3586 // separately with the full materialized immediate creating extra
3587 // instructions.
3588 if (isWorthFoldingAdd(Addr) &&
3589 selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr.getOperand(1), Base,
3590 Offset, /*IsPrefetch=*/false)) {
3591 // Insert an ADD instruction with the materialized Hi52 bits.
3592 Base = SDValue(
3593 CurDAG->getMachineNode(RISCV::ADD, DL, VT, Addr.getOperand(0), Base),
3594 0);
3595 return true;
3596 }
3597 }
3598
3599 if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset,
3600 /*IsPrefetch=*/false))
3601 return true;
3602
3603 Base = Addr;
3604 Offset = CurDAG->getTargetConstant(0, DL, VT);
3605 return true;
3606}
3607
3608/// Similar to SelectAddrRegImm, except that the offset is a 26-bit signed
3609/// immediate. This is used by the Qualcomm Xqcilo large offset load/store
3610/// instructions (qc.e.lw/qc.e.sw), whose offset field is 26 bits wide.
3611/// Only matches offsets that do not fit a 12-bit signed immediate, so that
3612/// offsets in the simm12 range keep using the shorter (and possibly
3613/// compressible) standard load/store instructions.
3615 SDValue &Offset) {
3616 SDLoc DL(Addr);
3617 MVT VT = Addr.getSimpleValueType();
3618
3619 if (CurDAG->isBaseWithConstantOffset(Addr)) {
3620 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3621 // Fold a 26-bit (but not 12-bit) signed offset directly into the
3622 // load/store.
3623 if (isInt<26>(CVal) && !isInt<12>(CVal)) {
3624 Base = Addr.getOperand(0);
3625 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Base))
3626 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), VT);
3627 Offset = CurDAG->getSignedTargetConstant(CVal, DL, VT);
3628 return true;
3629 }
3630 }
3631
3632 // The offset is just outside the 26-bit range. Split off a small (simm12)
3633 // adjustment with a plain ADDI and fold the remaining 26-bit offset into the
3634 // load/store. A plain ADDI is used (rather than the wide
3635 // qc.e.addi/qc.e.addai) because the adjustment fits simm12: this keeps it a
3636 // short, compressible (c.addi) instruction and is available without Xqcilia.
3637 //
3638 // Skip the split if the address is used other than as a foldable load/store
3639 // base. `isWorthFoldingAdd()` returns true when every user of the add node is
3640 // a scalar load/store using it as an address operand. If it return false, it
3641 // means that some use consumes the add result as a value (e.g. it feeds
3642 // another add, is a stored value, is used in arithmetic) and that use forces
3643 // the add to be materialized into a register.
3644 if (Addr.getOpcode() == ISD::ADD && isa<ConstantSDNode>(Addr.getOperand(1)) &&
3645 isWorthFoldingAdd(Addr)) {
3646 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3647 if (!isInt<26>(CVal)) {
3648 // check if lw in lui + add + lw combination can be compressed.
3649 // The check here purely based on the immediate value and hopes that
3650 // register allocator would assign a register from a GPRC set so that the
3651 // instruction can get compressed.
3652 bool IsLwCompressable = isShiftedUInt<5, 2>(CVal & ((1 << 12) - 1));
3653
3654 int64_t Imm26 = CVal < 0 ? minIntN(26) : maxIntN(26);
3655 int64_t Adj = CVal - Imm26;
3656 // If Adj fits within 6-bits, then both combinations will take 8 bytes
3657 // however c.addi + qc.e.lw/sw will take 1 less cycle. Also, if lw is not
3658 // compressable then both combination would take 10 bytes but again
3659 // addi + qc.e.lw/sw will take 1 less cycle.
3660 if (isInt<6>(Adj) || (isInt<12>(Adj) && !IsLwCompressable)) {
3661 Base = SDValue(CurDAG->getMachineNode(
3662 RISCV::ADDI, DL, VT, Addr.getOperand(0),
3663 CurDAG->getSignedTargetConstant(Adj, DL, VT)),
3664 0);
3665 Offset = CurDAG->getSignedTargetConstant(Imm26, DL, VT);
3666 return true;
3667 }
3668 }
3669 }
3670
3671 // Don't match: let the standard addressing modes handle it.
3672 return false;
3673}
3674
3675/// Similar to SelectAddrRegImm, except that the offset is restricted to uimm9.
3677 SDValue &Offset) {
3678 if (SelectAddrFrameIndex(Addr, Base, Offset))
3679 return true;
3680
3681 SDLoc DL(Addr);
3682 MVT VT = Addr.getSimpleValueType();
3683
3684 if (CurDAG->isBaseWithConstantOffset(Addr)) {
3685 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3686 if (isUInt<9>(CVal)) {
3687 Base = Addr.getOperand(0);
3688
3689 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Base))
3690 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), VT);
3691 Offset = CurDAG->getSignedTargetConstant(CVal, DL, VT);
3692 return true;
3693 }
3694 }
3695
3696 Base = Addr;
3697 Offset = CurDAG->getTargetConstant(0, DL, VT);
3698 return true;
3699}
3700
3701/// Similar to SelectAddrRegImm, except that the least significant 5 bits of
3702/// Offset should be all zeros.
3704 SDValue &Offset) {
3705 if (SelectAddrFrameIndex(Addr, Base, Offset))
3706 return true;
3707
3708 SDLoc DL(Addr);
3709 MVT VT = Addr.getSimpleValueType();
3710
3711 if (CurDAG->isBaseWithConstantOffset(Addr)) {
3712 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3713 if (isInt<12>(CVal)) {
3714 Base = Addr.getOperand(0);
3715
3716 // Early-out if not a valid offset.
3717 if ((CVal & 0b11111) != 0) {
3718 Base = Addr;
3719 Offset = CurDAG->getTargetConstant(0, DL, VT);
3720 return true;
3721 }
3722
3723 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Base))
3724 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), VT);
3725 Offset = CurDAG->getSignedTargetConstant(CVal, DL, VT);
3726 return true;
3727 }
3728 }
3729
3730 // Handle ADD with large immediates.
3731 if (Addr.getOpcode() == ISD::ADD && isa<ConstantSDNode>(Addr.getOperand(1))) {
3732 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3733 assert(!isInt<12>(CVal) && "simm12 not already handled?");
3734
3735 // Handle immediates in the range [-4096,-2049] or [2017, 4063]. We can save
3736 // one instruction by folding adjustment (-2048 or 2016) into the address.
3737 // The upper bound keeps CVal - 2016 within simm12 ([−2048, 2047]).
3738 if ((-2049 >= CVal && CVal >= -4096) || (4063 >= CVal && CVal >= 2017)) {
3739 int64_t Adj = CVal < 0 ? -2048 : 2016;
3740 int64_t AdjustedOffset = CVal - Adj;
3741 Base =
3742 SDValue(CurDAG->getMachineNode(
3743 RISCV::ADDI, DL, VT, Addr.getOperand(0),
3744 CurDAG->getSignedTargetConstant(AdjustedOffset, DL, VT)),
3745 0);
3746 Offset = CurDAG->getSignedTargetConstant(Adj, DL, VT);
3747 return true;
3748 }
3749
3750 if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr.getOperand(1), Base,
3751 Offset, /*IsPrefetch=*/true)) {
3752 // Insert an ADD instruction with the materialized Hi52 bits.
3753 Base = SDValue(
3754 CurDAG->getMachineNode(RISCV::ADD, DL, VT, Addr.getOperand(0), Base),
3755 0);
3756 return true;
3757 }
3758 }
3759
3760 if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset,
3761 /*IsPrefetch=*/true))
3762 return true;
3763
3764 Base = Addr;
3765 Offset = CurDAG->getTargetConstant(0, DL, VT);
3766 return true;
3767}
3768
3769/// Return true if this a load/store that we have a RegRegScale instruction for.
3771 const RISCVSubtarget &Subtarget) {
3772 unsigned UserOpc = User->getOpcode();
3773 if (UserOpc != ISD::LOAD && UserOpc != ISD::STORE)
3774 return false;
3775 EVT VT = cast<MemSDNode>(User)->getMemoryVT();
3776 // Zilx only provides indexed loads, so it must not enable reg+reg-scale
3777 // address folding for stores. XTheadMemIdx and Xqcisls have scaled stores.
3778 bool HasScalarIntegerMemIdx =
3779 Subtarget.hasVendorXTHeadMemIdx() || Subtarget.hasVendorXqcisls() ||
3780 (Subtarget.hasStdExtZilx() && UserOpc == ISD::LOAD);
3781 if (!(VT.isScalarInteger() && HasScalarIntegerMemIdx) &&
3782 !((VT == MVT::f32 || VT == MVT::f64) &&
3783 Subtarget.hasVendorXTHeadFMemIdx()))
3784 return false;
3785 // Don't allow stores of the value. It must be used as the address.
3786 if (UserOpc == ISD::STORE && cast<StoreSDNode>(User)->getValue() == Add)
3787 return false;
3788
3789 return true;
3790}
3791
3792/// Is it profitable to fold this Add into RegRegScale load/store. If \p
3793/// Shift is non-null, then we have matched a shl+add. We allow reassociating
3794/// (add (add (shl A C2) B) C1) -> (add (add B C1) (shl A C2)) if there is a
3795/// single addi and we don't have a SHXADD instruction we could use.
3796/// FIXME: May still need to check how many and what kind of users the SHL has.
3798 SDValue Add,
3799 SDValue Shift = SDValue()) {
3800 bool FoundADDI = false;
3801 for (auto *User : Add->users()) {
3802 if (isRegRegScaleLoadOrStore(User, Add, Subtarget))
3803 continue;
3804
3805 // Allow a single ADDI that is used by loads/stores if we matched a shift.
3806 if (!Shift || FoundADDI || User->getOpcode() != ISD::ADD ||
3808 !isInt<12>(cast<ConstantSDNode>(User->getOperand(1))->getSExtValue()))
3809 return false;
3810
3811 FoundADDI = true;
3812
3813 // If we have a SHXADD instruction, prefer that over reassociating an ADDI.
3814 assert(Shift.getOpcode() == ISD::SHL);
3815 unsigned ShiftAmt = Shift.getConstantOperandVal(1);
3816 if (Subtarget.hasShlAdd(ShiftAmt))
3817 return false;
3818
3819 // All users of the ADDI should be load/store.
3820 for (auto *ADDIUser : User->users())
3821 if (!isRegRegScaleLoadOrStore(ADDIUser, SDValue(User, 0), Subtarget))
3822 return false;
3823 }
3824
3825 return true;
3826}
3827
3829 ArrayRef<unsigned> Amounts,
3830 SDValue &Base, SDValue &Index,
3831 SDValue &Scale) {
3832 if (Addr.getOpcode() != ISD::ADD)
3833 return false;
3834 SDValue LHS = Addr.getOperand(0);
3835 SDValue RHS = Addr.getOperand(1);
3836
3837 EVT VT = Addr.getSimpleValueType();
3838 auto SelectShl = [this, VT, Amounts](SDValue N, SDValue &Index,
3839 SDValue &Shift) {
3840 if (N.getOpcode() != ISD::SHL || !isa<ConstantSDNode>(N.getOperand(1)))
3841 return false;
3842
3843 // Only match shifts by a value in range [0, MaxShiftAmount].
3844 unsigned ShiftAmt = N.getConstantOperandVal(1);
3845 if (!llvm::is_contained(Amounts, ShiftAmt))
3846 return false;
3847
3848 Index = N.getOperand(0);
3849 Shift = CurDAG->getTargetConstant(ShiftAmt, SDLoc(N), VT);
3850 return true;
3851 };
3852
3853 if (auto *C1 = dyn_cast<ConstantSDNode>(RHS)) {
3854 // (add (add (shl A C2) B) C1) -> (add (add B C1) (shl A C2))
3855 if (LHS.getOpcode() == ISD::ADD &&
3856 !isa<ConstantSDNode>(LHS.getOperand(1)) &&
3857 isInt<12>(C1->getSExtValue())) {
3858 if (SelectShl(LHS.getOperand(1), Index, Scale) &&
3859 isWorthFoldingIntoRegRegScale(*Subtarget, LHS, LHS.getOperand(1))) {
3860 SDValue C1Val = CurDAG->getTargetConstant(*C1->getConstantIntValue(),
3861 SDLoc(Addr), VT);
3862 Base = SDValue(CurDAG->getMachineNode(RISCV::ADDI, SDLoc(Addr), VT,
3863 LHS.getOperand(0), C1Val),
3864 0);
3865 return true;
3866 }
3867
3868 // Add is commutative so we need to check both operands.
3869 if (SelectShl(LHS.getOperand(0), Index, Scale) &&
3870 isWorthFoldingIntoRegRegScale(*Subtarget, LHS, LHS.getOperand(0))) {
3871 SDValue C1Val = CurDAG->getTargetConstant(*C1->getConstantIntValue(),
3872 SDLoc(Addr), VT);
3873 Base = SDValue(CurDAG->getMachineNode(RISCV::ADDI, SDLoc(Addr), VT,
3874 LHS.getOperand(1), C1Val),
3875 0);
3876 return true;
3877 }
3878 }
3879
3880 // Don't match add with constants.
3881 // FIXME: Is this profitable for large constants that have 0s in the lower
3882 // 12 bits that we can materialize with LUI?
3883 return false;
3884 }
3885
3886 // Try to match a shift on the RHS.
3887 if (SelectShl(RHS, Index, Scale)) {
3888 if (!isWorthFoldingIntoRegRegScale(*Subtarget, Addr, RHS))
3889 return false;
3890 Base = LHS;
3891 return true;
3892 }
3893
3894 // Try to match a shift on the LHS.
3895 if (SelectShl(LHS, Index, Scale)) {
3896 if (!isWorthFoldingIntoRegRegScale(*Subtarget, Addr, LHS))
3897 return false;
3898 Base = RHS;
3899 return true;
3900 }
3901
3902 if (!isWorthFoldingIntoRegRegScale(*Subtarget, Addr))
3903 return false;
3904
3905 // Bail out if 0 is not in candidate shift amounts.
3906 if (!llvm::is_contained(Amounts, 0))
3907 return false;
3908
3909 Base = LHS;
3910 Index = RHS;
3911 Scale = CurDAG->getTargetConstant(0, SDLoc(Addr), VT);
3912 return true;
3913}
3914
3916 ArrayRef<unsigned> Amounts,
3917 unsigned Bits, SDValue &Base,
3918 SDValue &Index,
3919 SDValue &Scale) {
3920 if (!SelectAddrRegRegScale(Addr, Amounts, Base, Index, Scale))
3921 return false;
3922
3923 if (Index.getOpcode() == ISD::AND) {
3924 auto *C = dyn_cast<ConstantSDNode>(Index.getOperand(1));
3925 if (C && C->getZExtValue() == maskTrailingOnes<uint64_t>(Bits)) {
3926 Index = Index.getOperand(0);
3927 return true;
3928 }
3929 }
3930
3931 return false;
3932}
3933
3935 SDValue &Offset) {
3936 if (Addr.getOpcode() != ISD::ADD)
3937 return false;
3938
3939 if (isa<ConstantSDNode>(Addr.getOperand(1)))
3940 return false;
3941
3942 Base = Addr.getOperand(0);
3943 Offset = Addr.getOperand(1);
3944 return true;
3945}
3946
3948 SDValue &ShAmt) {
3949 ShAmt = N;
3950
3951 // Peek through zext.
3952 if (ShAmt->getOpcode() == ISD::ZERO_EXTEND)
3953 ShAmt = ShAmt.getOperand(0);
3954
3955 // Shift instructions on RISC-V only read the lower 5 or 6 bits of the shift
3956 // amount. If there is an AND on the shift amount, we can bypass it if it
3957 // doesn't affect any of those bits.
3958 if (ShAmt.getOpcode() == ISD::AND &&
3959 isa<ConstantSDNode>(ShAmt.getOperand(1))) {
3960 const APInt &AndMask = ShAmt.getConstantOperandAPInt(1);
3961
3962 // Since the max shift amount is a power of 2 we can subtract 1 to make a
3963 // mask that covers the bits needed to represent all shift amounts.
3964 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
3965 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
3966
3967 if (ShMask.isSubsetOf(AndMask)) {
3968 ShAmt = ShAmt.getOperand(0);
3969 } else {
3970 // SimplifyDemandedBits may have optimized the mask so try restoring any
3971 // bits that are known zero.
3972 KnownBits Known = CurDAG->computeKnownBits(ShAmt.getOperand(0));
3973 if (!ShMask.isSubsetOf(AndMask | Known.Zero))
3974 return true;
3975 ShAmt = ShAmt.getOperand(0);
3976 }
3977 }
3978
3979 if (ShAmt.getOpcode() == ISD::ADD &&
3980 isa<ConstantSDNode>(ShAmt.getOperand(1))) {
3981 uint64_t Imm = ShAmt.getConstantOperandVal(1);
3982 // If we are shifting by X+N where N == 0 mod Size, then just shift by X
3983 // to avoid the ADD.
3984 if (Imm != 0 && Imm % ShiftWidth == 0) {
3985 ShAmt = ShAmt.getOperand(0);
3986 return true;
3987 }
3988 } else if (ShAmt.getOpcode() == ISD::SUB &&
3989 isa<ConstantSDNode>(ShAmt.getOperand(0))) {
3990 uint64_t Imm = ShAmt.getConstantOperandVal(0);
3991 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to
3992 // generate a NEG instead of a SUB of a constant.
3993 if (Imm != 0 && Imm % ShiftWidth == 0) {
3994 SDLoc DL(ShAmt);
3995 EVT VT = ShAmt.getValueType();
3996 SDValue Zero = CurDAG->getRegister(RISCV::X0, VT);
3997 unsigned NegOpc = VT == MVT::i64 ? RISCV::SUBW : RISCV::SUB;
3998 MachineSDNode *Neg = CurDAG->getMachineNode(NegOpc, DL, VT, Zero,
3999 ShAmt.getOperand(1));
4000 ShAmt = SDValue(Neg, 0);
4001 return true;
4002 }
4003 // If we are shifting by N-X where N == -1 mod Size, then just shift by ~X
4004 // to generate a NOT instead of a SUB of a constant.
4005 if (Imm % ShiftWidth == ShiftWidth - 1) {
4006 SDLoc DL(ShAmt);
4007 EVT VT = ShAmt.getValueType();
4008 MachineSDNode *Not = CurDAG->getMachineNode(
4009 RISCV::XORI, DL, VT, ShAmt.getOperand(1),
4010 CurDAG->getAllOnesConstant(DL, VT, /*isTarget=*/true));
4011 ShAmt = SDValue(Not, 0);
4012 return true;
4013 }
4014 }
4015
4016 return true;
4017}
4018
4019/// RISC-V doesn't have general instructions for integer setne/seteq, but we can
4020/// check for equality with 0. This function emits instructions that convert the
4021/// seteq/setne into something that can be compared with 0.
4022/// \p ExpectedCCVal indicates the condition code to attempt to match (e.g.
4023/// ISD::SETNE).
4025 SDValue &Val) {
4026 assert(ISD::isIntEqualitySetCC(ExpectedCCVal) &&
4027 "Unexpected condition code!");
4028
4029 // We're looking for a setcc.
4030 if (N->getOpcode() != ISD::SETCC)
4031 return false;
4032
4033 // Must be an equality comparison.
4034 ISD::CondCode CCVal = cast<CondCodeSDNode>(N->getOperand(2))->get();
4035 if (CCVal != ExpectedCCVal)
4036 return false;
4037
4038 SDValue LHS = N->getOperand(0);
4039 SDValue RHS = N->getOperand(1);
4040
4041 if (!LHS.getValueType().isScalarInteger())
4042 return false;
4043
4044 // If the RHS side is 0, we don't need any extra instructions, return the LHS.
4045 if (isNullConstant(RHS)) {
4046 Val = LHS;
4047 return true;
4048 }
4049
4050 SDLoc DL(N);
4051
4052 if (auto *C = dyn_cast<ConstantSDNode>(RHS)) {
4053 int64_t CVal = C->getSExtValue();
4054 // If the RHS is -2048, we can use xori to produce 0 if the LHS is -2048 and
4055 // non-zero otherwise.
4056 if (CVal == -2048) {
4057 Val = SDValue(
4058 CurDAG->getMachineNode(
4059 RISCV::XORI, DL, N->getValueType(0), LHS,
4060 CurDAG->getSignedTargetConstant(CVal, DL, N->getValueType(0))),
4061 0);
4062 return true;
4063 }
4064 // If the RHS is [-2047,2048], we can use addi/addiw with -RHS to produce 0
4065 // if the LHS is equal to the RHS and non-zero otherwise.
4066 if (isInt<12>(CVal) || CVal == 2048) {
4067 unsigned Opc = RISCV::ADDI;
4068 if (LHS.getOpcode() == ISD::SIGN_EXTEND_INREG &&
4069 cast<VTSDNode>(LHS.getOperand(1))->getVT() == MVT::i32) {
4070 Opc = RISCV::ADDIW;
4071 LHS = LHS.getOperand(0);
4072 }
4073
4074 Val = SDValue(CurDAG->getMachineNode(Opc, DL, N->getValueType(0), LHS,
4075 CurDAG->getSignedTargetConstant(
4076 -CVal, DL, N->getValueType(0))),
4077 0);
4078 return true;
4079 }
4080 if (isPowerOf2_64(CVal) && Subtarget->hasStdExtZbs()) {
4081 Val = SDValue(
4082 CurDAG->getMachineNode(
4083 RISCV::BINVI, DL, N->getValueType(0), LHS,
4084 CurDAG->getTargetConstant(Log2_64(CVal), DL, N->getValueType(0))),
4085 0);
4086 return true;
4087 }
4088 // Same as the addi case above but for larger immediates (signed 26-bit) use
4089 // the QC_E_ADDI instruction from the Xqcilia extension, if available. Avoid
4090 // anything which can be done with a single lui as it might be compressible.
4091 if (Subtarget->hasVendorXqcilia() && isInt<26>(CVal) &&
4092 (CVal & 0xFFF) != 0) {
4093 Val = SDValue(
4094 CurDAG->getMachineNode(
4095 RISCV::QC_E_ADDI, DL, N->getValueType(0), LHS,
4096 CurDAG->getSignedTargetConstant(-CVal, DL, N->getValueType(0))),
4097 0);
4098 return true;
4099 }
4100 }
4101
4102 // If nothing else we can XOR the LHS and RHS to produce zero if they are
4103 // equal and a non-zero value if they aren't.
4104 Val = SDValue(
4105 CurDAG->getMachineNode(RISCV::XOR, DL, N->getValueType(0), LHS, RHS), 0);
4106 return true;
4107}
4108
4110 if (N.getOpcode() == ISD::SIGN_EXTEND_INREG &&
4111 cast<VTSDNode>(N.getOperand(1))->getVT().getSizeInBits() == Bits) {
4112 Val = N.getOperand(0);
4113 return true;
4114 }
4115
4116 auto UnwrapShlSra = [](SDValue N, unsigned ShiftAmt) {
4117 if (N.getOpcode() != ISD::SRA || !isa<ConstantSDNode>(N.getOperand(1)))
4118 return N;
4119
4120 SDValue N0 = N.getOperand(0);
4121 if (N0.getOpcode() == ISD::SHL && isa<ConstantSDNode>(N0.getOperand(1)) &&
4122 N.getConstantOperandVal(1) == ShiftAmt &&
4123 N0.getConstantOperandVal(1) == ShiftAmt)
4124 return N0.getOperand(0);
4125
4126 return N;
4127 };
4128
4129 MVT VT = N.getSimpleValueType();
4130 if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - Bits)) {
4131 Val = UnwrapShlSra(N, VT.getSizeInBits() - Bits);
4132 return true;
4133 }
4134
4135 return false;
4136}
4137
4139 if (N.getOpcode() == ISD::AND) {
4140 auto *C = dyn_cast<ConstantSDNode>(N.getOperand(1));
4141 if (C && C->getZExtValue() == maskTrailingOnes<uint64_t>(Bits)) {
4142 Val = N.getOperand(0);
4143 return true;
4144 }
4145 }
4146 MVT VT = N.getSimpleValueType();
4147 APInt Mask = APInt::getBitsSetFrom(VT.getSizeInBits(), Bits);
4148 if (CurDAG->MaskedValueIsZero(N, Mask)) {
4149 Val = N;
4150 return true;
4151 }
4152
4153 return false;
4154}
4155
4156/// Look for various patterns that can be done with a SHL that can be folded
4157/// into a SHXADD. \p ShAmt contains 1, 2, or 3 and is set based on which
4158/// SHXADD we are trying to match.
4160 SDValue &Val) {
4161 if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1))) {
4162 SDValue N0 = N.getOperand(0);
4163
4164 if (bool LeftShift = N0.getOpcode() == ISD::SHL;
4165 (LeftShift || N0.getOpcode() == ISD::SRL) &&
4167 uint64_t Mask = N.getConstantOperandVal(1);
4168 unsigned C2 = N0.getConstantOperandVal(1);
4169
4170 unsigned XLen = Subtarget->getXLen();
4171 if (LeftShift)
4172 Mask &= maskTrailingZeros<uint64_t>(C2);
4173 else
4174 Mask &= maskTrailingOnes<uint64_t>(XLen - C2);
4175
4176 if (isShiftedMask_64(Mask)) {
4177 unsigned Leading = XLen - llvm::bit_width(Mask);
4178 unsigned Trailing = llvm::countr_zero(Mask);
4179 if (Trailing != ShAmt)
4180 return false;
4181
4182 unsigned Opcode;
4183 // Look for (and (shl y, c2), c1) where c1 is a shifted mask with no
4184 // leading zeros and c3 trailing zeros. We can use an SRLI by c3-c2
4185 // followed by a SHXADD with c3 for the X amount.
4186 if (LeftShift && Leading == 0 && C2 < Trailing)
4187 Opcode = RISCV::SRLI;
4188 // Look for (and (shl y, c2), c1) where c1 is a shifted mask with 32-c2
4189 // leading zeros and c3 trailing zeros. We can use an SRLIW by c3-c2
4190 // followed by a SHXADD with c3 for the X amount.
4191 else if (LeftShift && Leading == 32 - C2 && C2 < Trailing)
4192 Opcode = RISCV::SRLIW;
4193 // Look for (and (shr y, c2), c1) where c1 is a shifted mask with c2
4194 // leading zeros and c3 trailing zeros. We can use an SRLI by c2+c3
4195 // followed by a SHXADD using c3 for the X amount.
4196 else if (!LeftShift && Leading == C2)
4197 Opcode = RISCV::SRLI;
4198 // Look for (and (shr y, c2), c1) where c1 is a shifted mask with 32+c2
4199 // leading zeros and c3 trailing zeros. We can use an SRLIW by c2+c3
4200 // followed by a SHXADD using c3 for the X amount.
4201 else if (!LeftShift && Leading == 32 + C2)
4202 Opcode = RISCV::SRLIW;
4203 else
4204 return false;
4205
4206 SDLoc DL(N);
4207 EVT VT = N.getValueType();
4208 ShAmt = LeftShift ? Trailing - C2 : Trailing + C2;
4209 Val = SDValue(
4210 CurDAG->getMachineNode(Opcode, DL, VT, N0.getOperand(0),
4211 CurDAG->getTargetConstant(ShAmt, DL, VT)),
4212 0);
4213 return true;
4214 }
4215 } else if (N0.getOpcode() == ISD::SRA && N0.hasOneUse() &&
4217 uint64_t Mask = N.getConstantOperandVal(1);
4218 unsigned C2 = N0.getConstantOperandVal(1);
4219
4220 // Look for (and (sra y, c2), c1) where c1 is a shifted mask with c3
4221 // leading zeros and c4 trailing zeros. If c2 is greater than c3, we can
4222 // use (srli (srai y, c2 - c3), c3 + c4) followed by a SHXADD with c4 as
4223 // the X amount.
4224 if (isShiftedMask_64(Mask)) {
4225 unsigned XLen = Subtarget->getXLen();
4226 unsigned Leading = XLen - llvm::bit_width(Mask);
4227 unsigned Trailing = llvm::countr_zero(Mask);
4228 if (C2 > Leading && Leading > 0 && Trailing == ShAmt) {
4229 SDLoc DL(N);
4230 EVT VT = N.getValueType();
4231 Val = SDValue(CurDAG->getMachineNode(
4232 RISCV::SRAI, DL, VT, N0.getOperand(0),
4233 CurDAG->getTargetConstant(C2 - Leading, DL, VT)),
4234 0);
4235 Val = SDValue(CurDAG->getMachineNode(
4236 RISCV::SRLI, DL, VT, Val,
4237 CurDAG->getTargetConstant(Leading + ShAmt, DL, VT)),
4238 0);
4239 return true;
4240 }
4241 }
4242 }
4243 } else if (bool LeftShift = N.getOpcode() == ISD::SHL;
4244 (LeftShift || N.getOpcode() == ISD::SRL) &&
4245 isa<ConstantSDNode>(N.getOperand(1))) {
4246 SDValue N0 = N.getOperand(0);
4247 if (N0.getOpcode() == ISD::AND && N0.hasOneUse() &&
4249 uint64_t Mask = N0.getConstantOperandVal(1);
4250 if (isShiftedMask_64(Mask)) {
4251 unsigned C1 = N.getConstantOperandVal(1);
4252 unsigned XLen = Subtarget->getXLen();
4253 unsigned Leading = XLen - llvm::bit_width(Mask);
4254 unsigned Trailing = llvm::countr_zero(Mask);
4255 // Look for (shl (and X, Mask), C1) where Mask has 32 leading zeros and
4256 // C3 trailing zeros. If C1+C3==ShAmt we can use SRLIW+SHXADD.
4257 if (LeftShift && Leading == 32 && Trailing > 0 &&
4258 (Trailing + C1) == ShAmt) {
4259 SDLoc DL(N);
4260 EVT VT = N.getValueType();
4261 Val = SDValue(CurDAG->getMachineNode(
4262 RISCV::SRLIW, DL, VT, N0.getOperand(0),
4263 CurDAG->getTargetConstant(Trailing, DL, VT)),
4264 0);
4265 return true;
4266 }
4267 // Look for (srl (and X, Mask), C1) where Mask has 32 leading zeros and
4268 // C3 trailing zeros. If C3-C1==ShAmt we can use SRLIW+SHXADD.
4269 if (!LeftShift && Leading == 32 && Trailing > C1 &&
4270 (Trailing - C1) == ShAmt) {
4271 SDLoc DL(N);
4272 EVT VT = N.getValueType();
4273 Val = SDValue(CurDAG->getMachineNode(
4274 RISCV::SRLIW, DL, VT, N0.getOperand(0),
4275 CurDAG->getTargetConstant(Trailing, DL, VT)),
4276 0);
4277 return true;
4278 }
4279 }
4280 }
4281 }
4282
4283 return false;
4284}
4285
4286/// Look for various patterns that can be done with a SHL that can be folded
4287/// into a SHXADD_UW. \p ShAmt contains 1, 2, or 3 and is set based on which
4288/// SHXADD_UW we are trying to match.
4290 SDValue &Val) {
4291 if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1)) &&
4292 N.hasOneUse()) {
4293 SDValue N0 = N.getOperand(0);
4294 if (N0.getOpcode() == ISD::SHL && isa<ConstantSDNode>(N0.getOperand(1)) &&
4295 N0.hasOneUse()) {
4296 uint64_t Mask = N.getConstantOperandVal(1);
4297 unsigned C2 = N0.getConstantOperandVal(1);
4298
4299 Mask &= maskTrailingZeros<uint64_t>(C2);
4300
4301 // Look for (and (shl y, c2), c1) where c1 is a shifted mask with
4302 // 32-ShAmt leading zeros and c2 trailing zeros. We can use SLLI by
4303 // c2-ShAmt followed by SHXADD_UW with ShAmt for the X amount.
4304 if (isShiftedMask_64(Mask)) {
4305 unsigned Leading = llvm::countl_zero(Mask);
4306 unsigned Trailing = llvm::countr_zero(Mask);
4307 if (Leading == 32 - ShAmt && Trailing == C2 && Trailing > ShAmt) {
4308 SDLoc DL(N);
4309 EVT VT = N.getValueType();
4310 Val = SDValue(CurDAG->getMachineNode(
4311 RISCV::SLLI, DL, VT, N0.getOperand(0),
4312 CurDAG->getTargetConstant(C2 - ShAmt, DL, VT)),
4313 0);
4314 return true;
4315 }
4316 }
4317 }
4318 }
4319
4320 return false;
4321}
4322
4324 assert(N->getOpcode() == ISD::OR || N->getOpcode() == RISCVISD::OR_VL);
4325 if (N->getFlags().hasDisjoint())
4326 return true;
4327 return CurDAG->haveNoCommonBitsSet(N->getOperand(0), N->getOperand(1));
4328}
4329
4330bool RISCVDAGToDAGISel::selectImm64IfCheaper(int64_t Imm, int64_t OrigImm,
4331 SDValue N, SDValue &Val) {
4332 int OrigCost = RISCVMatInt::getIntMatCost(APInt(64, OrigImm), 64, *Subtarget,
4333 /*CompressionCost=*/true);
4334 int Cost = RISCVMatInt::getIntMatCost(APInt(64, Imm), 64, *Subtarget,
4335 /*CompressionCost=*/true);
4336 if (OrigCost <= Cost)
4337 return false;
4338
4339 Val = selectImm(CurDAG, SDLoc(N), N->getSimpleValueType(0), Imm, *Subtarget);
4340 return true;
4341}
4342
4344 if (!isa<ConstantSDNode>(N))
4345 return false;
4346 int64_t Imm = cast<ConstantSDNode>(N)->getSExtValue();
4347 if ((Imm >> 31) != 1)
4348 return false;
4349
4350 for (const SDNode *U : N->users()) {
4351 switch (U->getOpcode()) {
4352 case ISD::ADD:
4353 break;
4354 case ISD::OR:
4355 if (orDisjoint(U))
4356 break;
4357 return false;
4358 default:
4359 return false;
4360 }
4361 }
4362
4363 return selectImm64IfCheaper(0xffffffff00000000 | Imm, Imm, N, Val);
4364}
4365
4367 if (!isa<ConstantSDNode>(N))
4368 return false;
4369 int64_t Imm = cast<ConstantSDNode>(N)->getSExtValue();
4370 if (isInt<32>(Imm))
4371 return false;
4372 if (Imm == INT64_MIN)
4373 return false;
4374
4375 for (const SDNode *U : N->users()) {
4376 switch (U->getOpcode()) {
4377 case ISD::ADD:
4378 break;
4379 case RISCVISD::VMV_V_X_VL:
4380 if (!all_of(U->users(), [](const SDNode *V) {
4381 return V->getOpcode() == ISD::ADD ||
4382 V->getOpcode() == RISCVISD::ADD_VL;
4383 }))
4384 return false;
4385 break;
4386 default:
4387 return false;
4388 }
4389 }
4390
4391 return selectImm64IfCheaper(-Imm, Imm, N, Val);
4392}
4393
4395 if (!isa<ConstantSDNode>(N))
4396 return false;
4397 int64_t Imm = cast<ConstantSDNode>(N)->getSExtValue();
4398
4399 // For 32-bit signed constants, we can only substitute LUI+ADDI with LUI.
4400 if (isInt<32>(Imm) && ((Imm & 0xfff) != 0xfff || Imm == -1))
4401 return false;
4402
4403 // Abandon this transform if the constant is needed elsewhere.
4404 for (const SDNode *U : N->users()) {
4405 switch (U->getOpcode()) {
4406 case ISD::AND:
4407 case ISD::OR:
4408 case ISD::XOR:
4409 if (!(Subtarget->hasStdExtZbb() || Subtarget->hasStdExtZbkb()))
4410 return false;
4411 break;
4412 case RISCVISD::VMV_V_X_VL:
4413 if (!Subtarget->hasStdExtZvkb())
4414 return false;
4415 if (!all_of(U->users(), [](const SDNode *V) {
4416 return V->getOpcode() == ISD::AND ||
4417 V->getOpcode() == RISCVISD::AND_VL;
4418 }))
4419 return false;
4420 break;
4421 default:
4422 return false;
4423 }
4424 }
4425
4426 if (isInt<32>(Imm)) {
4427 Val =
4428 selectImm(CurDAG, SDLoc(N), N->getSimpleValueType(0), ~Imm, *Subtarget);
4429 return true;
4430 }
4431
4432 // For 64-bit constants, the instruction sequences get complex,
4433 // so we select inverted only if it's cheaper.
4434 return selectImm64IfCheaper(~Imm, Imm, N, Val);
4435}
4436
4437static bool vectorPseudoHasAllNBitUsers(SDNode *User, unsigned UserOpNo,
4438 unsigned Bits,
4439 const TargetInstrInfo *TII) {
4440 unsigned MCOpcode = RISCV::getRVVMCOpcode(User->getMachineOpcode());
4441
4442 if (!MCOpcode)
4443 return false;
4444
4445 const MCInstrDesc &MCID = TII->get(User->getMachineOpcode());
4446 const uint64_t TSFlags = MCID.TSFlags;
4447 if (!RISCVII::hasSEWOp(TSFlags))
4448 return false;
4449 assert(RISCVII::hasVLOp(TSFlags));
4450
4451 unsigned ChainOpIdx = User->getNumOperands() - 1;
4452 bool HasChainOp = User->getOperand(ChainOpIdx).getValueType() == MVT::Other;
4453 bool HasVecPolicyOp = RISCVII::hasVecPolicyOp(TSFlags);
4454 unsigned VLIdx = User->getNumOperands() - HasVecPolicyOp - HasChainOp - 2;
4455 const unsigned Log2SEW = User->getConstantOperandVal(VLIdx + 1);
4456
4457 if (UserOpNo == VLIdx)
4458 return false;
4459
4460 auto NumDemandedBits =
4461 RISCV::getVectorLowDemandedScalarBits(MCOpcode, Log2SEW);
4462 return NumDemandedBits && Bits >= *NumDemandedBits;
4463}
4464
4465// Return true if all users of this SDNode* only consume the lower \p Bits.
4466// This can be used to form W instructions for add/sub/mul/shl even when the
4467// root isn't a sext_inreg. This can allow the ADDW/SUBW/MULW/SLLIW to CSE if
4468// SimplifyDemandedBits has made it so some users see a sext_inreg and some
4469// don't. The sext_inreg+add/sub/mul/shl will get selected, but still leave
4470// the add/sub/mul/shl to become non-W instructions. By checking the users we
4471// may be able to use a W instruction and CSE with the other instruction if
4472// this has happened. We could try to detect that the CSE opportunity exists
4473// before doing this, but that would be more complicated.
4475 const unsigned Depth) const {
4476 assert((Node->getOpcode() == ISD::ADD || Node->getOpcode() == ISD::SUB ||
4477 Node->getOpcode() == ISD::MUL || Node->getOpcode() == ISD::SHL ||
4478 Node->getOpcode() == ISD::SRL || Node->getOpcode() == ISD::AND ||
4479 Node->getOpcode() == ISD::OR || Node->getOpcode() == ISD::XOR ||
4480 Node->getOpcode() == ISD::SIGN_EXTEND_INREG ||
4481 isa<ConstantSDNode>(Node) || Depth != 0) &&
4482 "Unexpected opcode");
4483
4485 return false;
4486
4487 // The PatFrags that call this may run before RISCVGenDAGISel.inc has checked
4488 // the VT. Ensure the type is scalar to avoid wasting time on vectors.
4489 if (Depth == 0 && !Node->getValueType(0).isScalarInteger())
4490 return false;
4491
4492 for (SDUse &Use : Node->uses()) {
4493 SDNode *User = Use.getUser();
4494 // Users of this node should have already been instruction selected
4495 if (!User->isMachineOpcode())
4496 return false;
4497
4498 // TODO: Add more opcodes?
4499 switch (User->getMachineOpcode()) {
4500 default:
4502 break;
4503 return false;
4504 case RISCV::ADDW:
4505 case RISCV::ADDIW:
4506 case RISCV::SUBW:
4507 case RISCV::MULW:
4508 case RISCV::SLLW:
4509 case RISCV::SLLIW:
4510 case RISCV::SRAW:
4511 case RISCV::SRAIW:
4512 case RISCV::SRLW:
4513 case RISCV::SRLIW:
4514 case RISCV::DIVW:
4515 case RISCV::DIVUW:
4516 case RISCV::REMW:
4517 case RISCV::REMUW:
4518 case RISCV::ROLW:
4519 case RISCV::RORW:
4520 case RISCV::RORIW:
4521 case RISCV::CLSW:
4522 case RISCV::CLZW:
4523 case RISCV::CTZW:
4524 case RISCV::CPOPW:
4525 case RISCV::SLLI_UW:
4526 case RISCV::ABSW:
4527 case RISCV::FMV_W_X:
4528 case RISCV::FCVT_H_W:
4529 case RISCV::FCVT_H_W_INX:
4530 case RISCV::FCVT_H_WU:
4531 case RISCV::FCVT_H_WU_INX:
4532 case RISCV::FCVT_S_W:
4533 case RISCV::FCVT_S_W_INX:
4534 case RISCV::FCVT_S_WU:
4535 case RISCV::FCVT_S_WU_INX:
4536 case RISCV::FCVT_D_W:
4537 case RISCV::FCVT_D_W_INX:
4538 case RISCV::FCVT_D_WU:
4539 case RISCV::FCVT_D_WU_INX:
4540 case RISCV::TH_REVW:
4541 case RISCV::TH_SRRIW:
4542 if (Bits >= 32)
4543 break;
4544 return false;
4545 case RISCV::SLL:
4546 case RISCV::SRA:
4547 case RISCV::SRL:
4548 case RISCV::ROL:
4549 case RISCV::ROR:
4550 case RISCV::BSET:
4551 case RISCV::BCLR:
4552 case RISCV::BINV:
4553 // Shift amount operands only use log2(Xlen) bits.
4554 if (Use.getOperandNo() == 1 && Bits >= Log2_32(Subtarget->getXLen()))
4555 break;
4556 return false;
4557 case RISCV::SLLI:
4558 // SLLI only uses the lower (XLen - ShAmt) bits.
4559 if (Bits >= Subtarget->getXLen() - User->getConstantOperandVal(1))
4560 break;
4561 return false;
4562 case RISCV::ANDI:
4563 if (Bits >= (unsigned)llvm::bit_width(User->getConstantOperandVal(1)))
4564 break;
4565 goto RecCheck;
4566 case RISCV::ORI: {
4567 uint64_t Imm = cast<ConstantSDNode>(User->getOperand(1))->getSExtValue();
4568 if (Bits >= (unsigned)llvm::bit_width<uint64_t>(~Imm))
4569 break;
4570 [[fallthrough]];
4571 }
4572 case RISCV::AND:
4573 case RISCV::OR:
4574 case RISCV::XOR:
4575 case RISCV::XORI:
4576 case RISCV::ANDN:
4577 case RISCV::ORN:
4578 case RISCV::XNOR:
4579 case RISCV::SH1ADD:
4580 case RISCV::SH2ADD:
4581 case RISCV::SH3ADD:
4582 RecCheck:
4583 if (hasAllNBitUsers(User, Bits, Depth + 1))
4584 break;
4585 return false;
4586 case RISCV::SRLI: {
4587 unsigned ShAmt = User->getConstantOperandVal(1);
4588 // If we are shifting right by less than Bits, and users don't demand any
4589 // bits that were shifted into [Bits-1:0], then we can consider this as an
4590 // N-Bit user.
4591 if (Bits > ShAmt && hasAllNBitUsers(User, Bits - ShAmt, Depth + 1))
4592 break;
4593 return false;
4594 }
4595 case RISCV::SEXT_B:
4596 case RISCV::PACKH:
4597 if (Bits >= 8)
4598 break;
4599 return false;
4600 case RISCV::SEXT_H:
4601 case RISCV::FMV_H_X:
4602 case RISCV::ZEXT_H_RV32:
4603 case RISCV::ZEXT_H_RV64:
4604 case RISCV::PACKW:
4605 if (Bits >= 16)
4606 break;
4607 return false;
4608 case RISCV::PACK:
4609 if (Bits >= (Subtarget->getXLen() / 2))
4610 break;
4611 return false;
4612 case RISCV::PPAIRE_H:
4613 // If only the lower 32-bits of the result are used, then only the
4614 // lower 16 bits of the inputs are used.
4615 if (Bits >= 16 && hasAllNBitUsers(User, 32, Depth + 1))
4616 break;
4617 return false;
4618 case RISCV::ADD_UW:
4619 case RISCV::SH1ADD_UW:
4620 case RISCV::SH2ADD_UW:
4621 case RISCV::SH3ADD_UW:
4622 // The first operand to add.uw/shXadd.uw is implicitly zero extended from
4623 // 32 bits.
4624 if (Use.getOperandNo() == 0 && Bits >= 32)
4625 break;
4626 return false;
4627 case RISCV::SB:
4628 if (Use.getOperandNo() == 0 && Bits >= 8)
4629 break;
4630 return false;
4631 case RISCV::SH:
4632 if (Use.getOperandNo() == 0 && Bits >= 16)
4633 break;
4634 return false;
4635 case RISCV::SW:
4636 if (Use.getOperandNo() == 0 && Bits >= 32)
4637 break;
4638 return false;
4639 case RISCV::TH_EXT:
4640 case RISCV::TH_EXTU: {
4641 unsigned Msb = User->getConstantOperandVal(1);
4642 unsigned Lsb = User->getConstantOperandVal(2);
4643 // Behavior of Msb < Lsb is not well documented.
4644 if (Msb >= Lsb && Bits > Msb)
4645 break;
4646 return false;
4647 }
4648 }
4649 }
4650
4651 return true;
4652}
4653
4654// Select a constant that can be represented as (sign_extend(imm5) << imm2).
4656 SDValue &Shl2) {
4657 auto *C = dyn_cast<ConstantSDNode>(N);
4658 if (!C)
4659 return false;
4660
4661 int64_t Offset = C->getSExtValue();
4662 for (unsigned Shift = 0; Shift < 4; Shift++) {
4663 if (isInt<5>(Offset >> Shift) && ((Offset % (1LL << Shift)) == 0)) {
4664 EVT VT = N->getValueType(0);
4665 Simm5 = CurDAG->getSignedTargetConstant(Offset >> Shift, SDLoc(N), VT);
4666 Shl2 = CurDAG->getTargetConstant(Shift, SDLoc(N), VT);
4667 return true;
4668 }
4669 }
4670
4671 return false;
4672}
4673
4674// Select VL as a 5 bit immediate or a value that will become a register. This
4675// allows us to choose between VSETIVLI or VSETVLI later.
4677 auto *C = dyn_cast<ConstantSDNode>(N);
4678 if (C && isUInt<5>(C->getZExtValue())) {
4679 VL = CurDAG->getTargetConstant(C->getZExtValue(), SDLoc(N),
4680 N->getValueType(0));
4681 } else if (C && C->isAllOnes()) {
4682 // Treat all ones as VLMax.
4683 VL = CurDAG->getSignedTargetConstant(RISCV::VLMaxSentinel, SDLoc(N),
4684 N->getValueType(0));
4685 } else if (isa<RegisterSDNode>(N) &&
4686 cast<RegisterSDNode>(N)->getReg() == RISCV::X0) {
4687 // All our VL operands use an operand that allows GPRNoX0 or an immediate
4688 // as the register class. Convert X0 to a special immediate to pass the
4689 // MachineVerifier. This is recognized specially by the vsetvli insertion
4690 // pass.
4691 VL = CurDAG->getSignedTargetConstant(RISCV::VLMaxSentinel, SDLoc(N),
4692 N->getValueType(0));
4693 } else {
4694 VL = N;
4695 }
4696
4697 return true;
4698}
4699
4701 if (N.getOpcode() == ISD::INSERT_SUBVECTOR) {
4702 if (!N.getOperand(0).isUndef())
4703 return SDValue();
4704 N = N.getOperand(1);
4705 }
4706 SDValue Splat = N;
4707 if ((Splat.getOpcode() != RISCVISD::VMV_V_X_VL &&
4708 Splat.getOpcode() != RISCVISD::VMV_S_X_VL) ||
4709 !Splat.getOperand(0).isUndef())
4710 return SDValue();
4711 assert(Splat.getNumOperands() == 3 && "Unexpected number of operands");
4712 return Splat;
4713}
4714
4717 if (!Splat)
4718 return false;
4719
4720 SplatVal = Splat.getOperand(1);
4721 return true;
4722}
4723
4725 SelectionDAG &DAG,
4726 const RISCVSubtarget &Subtarget,
4727 std::function<bool(int64_t)> ValidateImm,
4728 bool Decrement = false) {
4730 if (!Splat || !isa<ConstantSDNode>(Splat.getOperand(1)))
4731 return false;
4732
4733 const unsigned SplatEltSize = Splat.getScalarValueSizeInBits();
4734 assert(Subtarget.getXLenVT() == Splat.getOperand(1).getSimpleValueType() &&
4735 "Unexpected splat operand type");
4736
4737 // The semantics of RISCVISD::VMV_V_X_VL is that when the operand
4738 // type is wider than the resulting vector element type: an implicit
4739 // truncation first takes place. Therefore, perform a manual
4740 // truncation/sign-extension in order to ignore any truncated bits and catch
4741 // any zero-extended immediate.
4742 // For example, we wish to match (i8 -1) -> (XLenVT 255) as a simm5 by first
4743 // sign-extending to (XLenVT -1).
4744 APInt SplatConst = Splat.getConstantOperandAPInt(1).sextOrTrunc(SplatEltSize);
4745
4746 int64_t SplatImm = SplatConst.getSExtValue();
4747
4748 if (!ValidateImm(SplatImm))
4749 return false;
4750
4751 if (Decrement)
4752 SplatImm -= 1;
4753
4754 SplatVal =
4755 DAG.getSignedTargetConstant(SplatImm, SDLoc(N), Subtarget.getXLenVT());
4756 return true;
4757}
4758
4760 return selectVSplatImmHelper(N, SplatVal, *CurDAG, *Subtarget,
4761 [](int64_t Imm) { return isInt<5>(Imm); });
4762}
4763
4765 return selectVSplatImmHelper(
4766 N, SplatVal, *CurDAG, *Subtarget,
4767 [](int64_t Imm) { return Imm >= -15 && Imm <= 16; },
4768 /*Decrement=*/true);
4769}
4770
4772 return selectVSplatImmHelper(
4773 N, SplatVal, *CurDAG, *Subtarget,
4774 [](int64_t Imm) { return Imm >= -15 && Imm <= 16; },
4775 /*Decrement=*/false);
4776}
4777
4779 SDValue &SplatVal) {
4780 return selectVSplatImmHelper(
4781 N, SplatVal, *CurDAG, *Subtarget,
4782 [](int64_t Imm) { return Imm != 0 && Imm >= -15 && Imm <= 16; },
4783 /*Decrement=*/true);
4784}
4785
4787 SDValue &SplatVal) {
4788 return selectVSplatImmHelper(
4789 N, SplatVal, *CurDAG, *Subtarget,
4790 [Bits](int64_t Imm) { return isUIntN(Bits, Imm); });
4791}
4792
4795 return Splat && selectNegImm(Splat.getOperand(1), SplatVal);
4796}
4797
4799 auto IsExtOrTrunc = [](SDValue N) {
4800 switch (N->getOpcode()) {
4801 case ISD::SIGN_EXTEND:
4802 case ISD::ZERO_EXTEND:
4803 // There's no passthru on these _VL nodes so any VL/mask is ok, since any
4804 // inactive elements will be undef.
4805 case RISCVISD::TRUNCATE_VECTOR_VL:
4806 case RISCVISD::VSEXT_VL:
4807 case RISCVISD::VZEXT_VL:
4808 return true;
4809 default:
4810 return false;
4811 }
4812 };
4813
4814 // We can have multiple nested nodes, so unravel them all if needed.
4815 while (IsExtOrTrunc(N)) {
4816 if (!N.hasOneUse() || N.getScalarValueSizeInBits() < 8)
4817 return false;
4818 N = N->getOperand(0);
4819 }
4820
4821 return selectVSplat(N, SplatVal);
4822}
4823
4825 // Allow bitcasts from XLenVT -> FP.
4826 if (N.getOpcode() == ISD::BITCAST &&
4827 N.getOperand(0).getValueType() == Subtarget->getXLenVT()) {
4828 Imm = N.getOperand(0);
4829 return true;
4830 }
4831 // Allow moves from XLenVT to FP.
4832 if (N.getOpcode() == RISCVISD::FMV_H_X ||
4833 N.getOpcode() == RISCVISD::FMV_W_X_RV64) {
4834 Imm = N.getOperand(0);
4835 return true;
4836 }
4837
4838 // Otherwise, look for FP constants that can materialized with scalar int.
4840 if (!CFP)
4841 return false;
4842 const APFloat &APF = CFP->getValueAPF();
4843 // td can handle +0.0 already.
4844 if (APF.isPosZero())
4845 return false;
4846
4847 MVT VT = CFP->getSimpleValueType(0);
4848
4849 MVT XLenVT = Subtarget->getXLenVT();
4850 if (VT == MVT::f64 && !Subtarget->is64Bit()) {
4851 assert(APF.isNegZero() && "Unexpected constant.");
4852 return false;
4853 }
4854 SDLoc DL(N);
4855 Imm = selectImm(CurDAG, DL, XLenVT, APF.bitcastToAPInt().getSExtValue(),
4856 *Subtarget);
4857 return true;
4858}
4859
4861 SDValue &Imm) {
4862 if (auto *C = dyn_cast<ConstantSDNode>(N)) {
4863 int64_t ImmVal = SignExtend64(C->getSExtValue(), Width);
4864
4865 if (!isInt<5>(ImmVal))
4866 return false;
4867
4868 Imm = CurDAG->getSignedTargetConstant(ImmVal, SDLoc(N),
4869 Subtarget->getXLenVT());
4870 return true;
4871 }
4872
4873 return false;
4874}
4875
4876// Match XOR with a VMSET_VL operand. Return the other operand.
4878 if (N.getOpcode() != ISD::XOR)
4879 return false;
4880
4881 if (N.getOperand(0).getOpcode() == RISCVISD::VMSET_VL) {
4882 Res = N.getOperand(1);
4883 return true;
4884 }
4885
4886 if (N.getOperand(1).getOpcode() == RISCVISD::VMSET_VL) {
4887 Res = N.getOperand(0);
4888 return true;
4889 }
4890
4891 return false;
4892}
4893
4894// Match VMXOR_VL with a VMSET_VL operand. Making sure that that VL operand
4895// matches the parent's VL. Return the other operand of the VMXOR_VL.
4897 SDValue &Res) {
4898 if (N.getOpcode() != RISCVISD::VMXOR_VL)
4899 return false;
4900
4901 assert(Parent &&
4902 (Parent->getOpcode() == RISCVISD::VMAND_VL ||
4903 Parent->getOpcode() == RISCVISD::VMOR_VL ||
4904 Parent->getOpcode() == RISCVISD::VMXOR_VL) &&
4905 "Unexpected parent");
4906
4907 // The VL should match the parent.
4908 if (Parent->getOperand(2) != N->getOperand(2))
4909 return false;
4910
4911 if (N.getOperand(0).getOpcode() == RISCVISD::VMSET_VL) {
4912 Res = N.getOperand(1);
4913 return true;
4914 }
4915
4916 if (N.getOperand(1).getOpcode() == RISCVISD::VMSET_VL) {
4917 Res = N.getOperand(0);
4918 return true;
4919 }
4920
4921 return false;
4922}
4923
4924// Try to remove sext.w if the input is a W instruction or can be made into
4925// a W instruction cheaply.
4926bool RISCVDAGToDAGISel::doPeepholeSExtW(SDNode *N) {
4927 // Look for the sext.w pattern, addiw rd, rs1, 0.
4928 if (N->getMachineOpcode() != RISCV::ADDIW ||
4929 !isNullConstant(N->getOperand(1)))
4930 return false;
4931
4932 SDValue N0 = N->getOperand(0);
4933 if (!N0.isMachineOpcode())
4934 return false;
4935
4936 switch (N0.getMachineOpcode()) {
4937 default:
4938 break;
4939 case RISCV::ADD:
4940 case RISCV::ADDI:
4941 case RISCV::SUB:
4942 case RISCV::MUL:
4943 case RISCV::SLLI: {
4944 // Convert sext.w+add/sub/mul to their W instructions. This will create
4945 // a new independent instruction. This improves latency.
4946 unsigned Opc;
4947 switch (N0.getMachineOpcode()) {
4948 default:
4949 llvm_unreachable("Unexpected opcode!");
4950 case RISCV::ADD: Opc = RISCV::ADDW; break;
4951 case RISCV::ADDI: Opc = RISCV::ADDIW; break;
4952 case RISCV::SUB: Opc = RISCV::SUBW; break;
4953 case RISCV::MUL: Opc = RISCV::MULW; break;
4954 case RISCV::SLLI: Opc = RISCV::SLLIW; break;
4955 }
4956
4957 SDValue N00 = N0.getOperand(0);
4958 SDValue N01 = N0.getOperand(1);
4959
4960 // Shift amount needs to be uimm5.
4961 if (N0.getMachineOpcode() == RISCV::SLLI &&
4962 !isUInt<5>(cast<ConstantSDNode>(N01)->getSExtValue()))
4963 break;
4964
4965 SDNode *Result =
4966 CurDAG->getMachineNode(Opc, SDLoc(N), N->getValueType(0),
4967 N00, N01);
4968 ReplaceUses(N, Result);
4969 return true;
4970 }
4971 case RISCV::ADDW:
4972 case RISCV::ADDIW:
4973 case RISCV::SUBW:
4974 case RISCV::MULW:
4975 case RISCV::SLLIW:
4976 case RISCV::PACKW:
4977 case RISCV::TH_MULAW:
4978 case RISCV::TH_MULAH:
4979 case RISCV::TH_MULSW:
4980 case RISCV::TH_MULSH:
4981 if (N0.getValueType() == MVT::i32)
4982 break;
4983
4984 // Result is already sign extended just remove the sext.w.
4985 // NOTE: We only handle the nodes that are selected with hasAllWUsers.
4986 ReplaceUses(N, N0.getNode());
4987 return true;
4988 }
4989
4990 return false;
4991}
4992
4993static bool usesAllOnesMask(SDValue MaskOp) {
4994 const auto IsVMSet = [](unsigned Opc) {
4995 return Opc == RISCV::PseudoVMSET_M_B1 || Opc == RISCV::PseudoVMSET_M_B16 ||
4996 Opc == RISCV::PseudoVMSET_M_B2 || Opc == RISCV::PseudoVMSET_M_B32 ||
4997 Opc == RISCV::PseudoVMSET_M_B4 || Opc == RISCV::PseudoVMSET_M_B64 ||
4998 Opc == RISCV::PseudoVMSET_M_B8;
4999 };
5000
5001 // TODO: Check that the VMSET is the expected bitwidth? The pseudo has
5002 // undefined behaviour if it's the wrong bitwidth, so we could choose to
5003 // assume that it's all-ones? Same applies to its VL.
5004 return MaskOp->isMachineOpcode() && IsVMSet(MaskOp.getMachineOpcode());
5005}
5006
5007static bool isImplicitDef(SDValue V) {
5008 if (!V.isMachineOpcode())
5009 return false;
5010 if (V.getMachineOpcode() == TargetOpcode::REG_SEQUENCE) {
5011 for (unsigned I = 1; I < V.getNumOperands(); I += 2)
5012 if (!isImplicitDef(V.getOperand(I)))
5013 return false;
5014 return true;
5015 }
5016 return V.getMachineOpcode() == TargetOpcode::IMPLICIT_DEF;
5017}
5018
5019// Optimize masked RVV pseudo instructions with a known all-ones mask to their
5020// corresponding "unmasked" pseudo versions.
5021bool RISCVDAGToDAGISel::doPeepholeMaskedRVV(MachineSDNode *N) {
5022 const RISCV::RISCVMaskedPseudoInfo *I =
5023 RISCV::getMaskedPseudoInfo(N->getMachineOpcode());
5024 if (!I)
5025 return false;
5026
5027 unsigned MaskOpIdx = I->MaskOpIdx;
5028 if (!usesAllOnesMask(N->getOperand(MaskOpIdx)))
5029 return false;
5030
5031 // There are two classes of pseudos in the table - compares and
5032 // everything else. See the comment on RISCVMaskedPseudo for details.
5033 const unsigned Opc = I->UnmaskedPseudo;
5034 const MCInstrDesc &MCID = TII->get(Opc);
5035 const bool HasPassthru = RISCVII::isFirstDefTiedToFirstUse(MCID);
5036
5037 const MCInstrDesc &MaskedMCID = TII->get(N->getMachineOpcode());
5038 const bool MaskedHasPassthru = RISCVII::isFirstDefTiedToFirstUse(MaskedMCID);
5039
5040 assert((RISCVII::hasVecPolicyOp(MaskedMCID.TSFlags) ||
5042 "Unmasked pseudo has policy but masked pseudo doesn't?");
5043 assert(RISCVII::hasVecPolicyOp(MCID.TSFlags) == HasPassthru &&
5044 "Unexpected pseudo structure");
5045 assert(!(HasPassthru && !MaskedHasPassthru) &&
5046 "Unmasked pseudo has passthru but masked pseudo doesn't?");
5047
5049 // Skip the passthru operand at index 0 if the unmasked don't have one.
5050 bool ShouldSkip = !HasPassthru && MaskedHasPassthru;
5051 bool DropPolicy = !RISCVII::hasVecPolicyOp(MCID.TSFlags) &&
5052 RISCVII::hasVecPolicyOp(MaskedMCID.TSFlags);
5053 bool HasChainOp =
5054 N->getOperand(N->getNumOperands() - 1).getValueType() == MVT::Other;
5055 unsigned LastOpNum = N->getNumOperands() - 1 - HasChainOp;
5056 for (unsigned I = ShouldSkip, E = N->getNumOperands(); I != E; I++) {
5057 // Skip the mask
5058 SDValue Op = N->getOperand(I);
5059 if (I == MaskOpIdx)
5060 continue;
5061 if (DropPolicy && I == LastOpNum)
5062 continue;
5063 Ops.push_back(Op);
5064 }
5065
5066 MachineSDNode *Result =
5067 CurDAG->getMachineNode(Opc, SDLoc(N), N->getVTList(), Ops);
5068
5069 if (!N->memoperands_empty())
5070 CurDAG->setNodeMemRefs(Result, N->memoperands());
5071
5072 Result->setFlags(N->getFlags());
5073 ReplaceUses(N, Result);
5074
5075 return true;
5076}
5077
5078/// If our passthru is an implicit_def, use noreg instead. This side
5079/// steps issues with MachineCSE not being able to CSE expressions with
5080/// IMPLICIT_DEF operands while preserving the semantic intent. See
5081/// pr64282 for context. Note that this transform is the last one
5082/// performed at ISEL DAG to DAG.
5083bool RISCVDAGToDAGISel::doPeepholeNoRegPassThru() {
5084 bool MadeChange = false;
5085 SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end();
5086
5087 while (Position != CurDAG->allnodes_begin()) {
5088 SDNode *N = &*--Position;
5089 if (N->use_empty() || !N->isMachineOpcode())
5090 continue;
5091
5092 const unsigned Opc = N->getMachineOpcode();
5093 if (!RISCVVPseudosTable::getPseudoInfo(Opc) ||
5095 !isImplicitDef(N->getOperand(0)))
5096 continue;
5097
5099 Ops.push_back(CurDAG->getRegister(RISCV::NoRegister, N->getValueType(0)));
5100 for (unsigned I = 1, E = N->getNumOperands(); I != E; I++) {
5101 SDValue Op = N->getOperand(I);
5102 Ops.push_back(Op);
5103 }
5104
5105 MachineSDNode *Result =
5106 CurDAG->getMachineNode(Opc, SDLoc(N), N->getVTList(), Ops);
5107 Result->setFlags(N->getFlags());
5108 CurDAG->setNodeMemRefs(Result, cast<MachineSDNode>(N)->memoperands());
5109 ReplaceUses(N, Result);
5110 MadeChange = true;
5111 }
5112 return MadeChange;
5113}
5114
5115
5116// This pass converts a legalized DAG into a RISCV-specific DAG, ready
5117// for instruction scheduling.
5122
5126
5128
5133
static SDValue Widen(SelectionDAG *CurDAG, SDValue N)
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
unsigned Imm
unsigned uint64_t
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_TYPE
const HexagonInstrInfo * TII
static constexpr Value * getValue(Ty &ValueOrUse)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define P(N)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool getVal(MDTuple *MD, const char *Key, uint64_t &Val)
static bool usesAllOnesMask(SDValue MaskOp)
static Register getTileReg(uint64_t TileNum)
static SDValue selectImm(SelectionDAG *CurDAG, const SDLoc &DL, const MVT VT, int64_t Imm, const RISCVSubtarget &Subtarget)
static bool isRegRegScaleLoadOrStore(SDNode *User, SDValue Add, const RISCVSubtarget &Subtarget)
Return true if this a load/store that we have a RegRegScale instruction for.
static std::pair< SDValue, SDValue > extractGPRPair(SelectionDAG *CurDAG, const SDLoc &DL, SDValue Pair)
#define CASE_VMNAND_VMSET_OPCODES(lmulenum, suffix)
static bool isWorthFoldingAdd(SDValue Add)
static SDValue selectImmSeq(SelectionDAG *CurDAG, const SDLoc &DL, const MVT VT, RISCVMatInt::InstSeq &Seq)
static bool isImplicitDef(SDValue V)
#define CASE_VMXOR_VMANDN_VMOR_OPCODES(lmulenum, suffix)
static bool selectVSplatImmHelper(SDValue N, SDValue &SplatVal, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, std::function< bool(int64_t)> ValidateImm, bool Decrement=false)
static unsigned getSegInstNF(unsigned Intrinsic)
static bool isWorthFoldingIntoRegRegScale(const RISCVSubtarget &Subtarget, SDValue Add, SDValue Shift=SDValue())
Is it profitable to fold this Add into RegRegScale load/store.
static bool vectorPseudoHasAllNBitUsers(SDNode *User, unsigned UserOpNo, unsigned Bits, const TargetInstrInfo *TII)
static bool selectConstantAddr(SelectionDAG *CurDAG, const SDLoc &DL, const MVT VT, const RISCVSubtarget *Subtarget, SDValue Addr, SDValue &Base, SDValue &Offset, bool IsPrefetch=false)
#define INST_ALL_NF_CASE_WITH_FF(NAME)
#define CASE_VMSLT_OPCODES(lmulenum, suffix)
static SDValue buildGPRPair(SelectionDAG *CurDAG, const SDLoc &DL, MVT VT, SDValue Lo, SDValue Hi)
bool isRegImmLoadOrStore(SDNode *User, SDValue Add)
static cl::opt< bool > UsePseudoMovImm("riscv-use-rematerializable-movimm", cl::Hidden, cl::desc("Use a rematerializable pseudoinstruction for 2 instruction " "constant materialization"), cl::init(false))
static SDValue findVSplat(SDValue N)
static bool isApplicableToPLIOrPLUI(int Val)
#define INST_ALL_NF_CASE(NAME)
cl::opt< uint32_t > PreferredLandingPadLabel("riscv-landing-pad-label", cl::ReallyHidden, cl::desc("Use preferred fixed label for all labels"))
Contains matchers for matching SelectionDAG nodes and values.
SI Fold Operands
#define LLVM_DEBUG(...)
Definition Debug.h:119
#define PASS_NAME
DEMANGLE_DUMP_METHOD void dump() const
bool isZero() const
Definition APFloat.h:1571
APInt bitcastToAPInt() const
Definition APFloat.h:1467
bool isPosZero() const
Definition APFloat.h:1586
bool isNegZero() const
Definition APFloat.h:1587
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
Definition APInt.cpp:969
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:368
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1509
LLVM_ABI bool isSplat(unsigned SplatSizeInBits) const
Check if the APInt consists of a repeated bit pattern.
Definition APInt.cpp:626
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
Definition APInt.h:216
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
Definition APInt.h:1262
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
Definition APInt.h:283
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1583
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const APFloat & getValueAPF() const
uint64_t getZExtValue() const
int64_t getSExtValue() const
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
This class is used to form a handle around another node that is persistent and is updated across invo...
const SDValue & getValue() const
static StringRef getMemConstraintName(ConstraintCode C)
Definition InlineAsm.h:475
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
Describe properties that are true of each instruction in the target description file.
Machine Value Type.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
SimpleValueType SimpleTy
uint64_t getScalarSizeInBits() const
MVT changeVectorElementType(MVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isFixedLengthVector() const
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
MVT getVectorElementType() const
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
void setFlags(Flags f)
Bitwise OR the current flags with the given flags.
An SDNode that represents everything that will be needed to construct a MachineInstr.
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
RISCVDAGToDAGISelLegacy(RISCVTargetMachine &TargetMachine, CodeGenOptLevel OptLevel)
bool selectSETCC(SDValue N, ISD::CondCode ExpectedCCVal, SDValue &Val)
RISC-V doesn't have general instructions for integer setne/seteq, but we can check for equality with ...
bool selectSExtBits(SDValue N, unsigned Bits, SDValue &Val)
bool selectNegImm(SDValue N, SDValue &Val)
bool selectZExtBits(SDValue N, unsigned Bits, SDValue &Val)
bool selectSHXADD_UWOp(SDValue N, unsigned ShAmt, SDValue &Val)
Look for various patterns that can be done with a SHL that can be folded into a SHXADD_UW.
bool areOffsetsWithinAlignment(SDValue Addr, Align Alignment)
bool hasAllNBitUsers(SDNode *Node, unsigned Bits, const unsigned Depth=0) const
bool SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base, SDValue &Offset)
Similar to SelectAddrRegImm, except that the least significant 5 bits of Offset should be all zeros.
bool selectZExtImm32(SDValue N, SDValue &Val)
bool SelectAddrRegReg(SDValue Addr, SDValue &Base, SDValue &Offset)
bool selectVMNOT_VLOp(SDNode *Parent, SDValue N, SDValue &Res)
void selectVSXSEG(SDNode *Node, unsigned NF, bool IsMasked, bool IsOrdered)
void selectVLSEGFF(SDNode *Node, unsigned NF, bool IsMasked)
bool selectVSplatSimm5Plus1NoDec(SDValue N, SDValue &SplatVal)
bool SelectAddrRegImm26(SDValue Addr, SDValue &Base, SDValue &Offset)
Similar to SelectAddrRegImm, except that the offset is a 26-bit signed immediate.
bool selectSimm5Shl2(SDValue N, SDValue &Simm5, SDValue &Shl2)
void selectSF_VC_X_SE(SDNode *Node)
bool orDisjoint(const SDNode *Node) const
bool tryWideningMulAcc(SDNode *Node, const SDLoc &DL)
bool selectLow8BitsVSplat(SDValue N, SDValue &SplatVal)
bool hasAllHUsers(SDNode *Node) const
bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps) override
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
bool selectVSplatSimm5(SDValue N, SDValue &SplatVal)
bool selectRVVSimm5(SDValue N, unsigned Width, SDValue &Imm)
bool SelectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset)
bool tryUnsignedBitfieldInsertInZero(SDNode *Node, const SDLoc &DL, MVT VT, SDValue X, unsigned Msb, unsigned Lsb)
bool hasAllWUsers(SDNode *Node) const
void PreprocessISelDAG() override
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
bool selectInvLogicImm(SDValue N, SDValue &Val)
bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset)
bool SelectAddrRegRegScale(SDValue Addr, ArrayRef< unsigned > Amounts, SDValue &Base, SDValue &Index, SDValue &Scale)
void Select(SDNode *Node) override
Main hook for targets to transform nodes into machine nodes.
void selectXSfmmVSET(SDNode *Node)
bool trySignedBitfieldInsertInSign(SDNode *Node)
bool selectVSplat(SDValue N, SDValue &SplatVal)
void addVectorLoadStoreOperands(SDNode *Node, unsigned SEWImm, const SDLoc &DL, unsigned CurOp, bool IsMasked, bool IsStridedOrIndexed, SmallVectorImpl< SDValue > &Operands, bool IsLoad=false, MVT *IndexVT=nullptr)
void PostprocessISelDAG() override
PostprocessISelDAG() - This hook allows the target to hack on the graph right after selection.
bool SelectAddrRegImm9(SDValue Addr, SDValue &Base, SDValue &Offset)
Similar to SelectAddrRegImm, except that the offset is restricted to uimm9.
bool selectScalarFPAsInt(SDValue N, SDValue &Imm)
bool hasAllBUsers(SDNode *Node) const
void selectVLSEG(SDNode *Node, unsigned NF, bool IsMasked, bool IsStrided)
bool tryShrinkShlLogicImm(SDNode *Node)
void selectVSETVLI(SDNode *Node)
bool selectVLOp(SDValue N, SDValue &VL)
bool trySignedBitfieldExtract(SDNode *Node)
bool selectVSplatSimm5Plus1(SDValue N, SDValue &SplatVal)
bool SelectAddrRegZextRegScale(SDValue Addr, ArrayRef< unsigned > Amounts, unsigned Bits, SDValue &Base, SDValue &Index, SDValue &Scale)
bool selectVMNOTOp(SDValue N, SDValue &Res)
void selectVSSEG(SDNode *Node, unsigned NF, bool IsMasked, bool IsStrided)
bool selectVSplatImm64Neg(SDValue N, SDValue &SplatVal)
bool selectVSplatSimm5Plus1NonZero(SDValue N, SDValue &SplatVal)
bool tryUnsignedBitfieldExtract(SDNode *Node, const SDLoc &DL, MVT VT, SDValue X, unsigned Msb, unsigned Lsb)
void selectVLXSEG(SDNode *Node, unsigned NF, bool IsMasked, bool IsOrdered)
bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt)
bool selectSHXADDOp(SDValue N, unsigned ShAmt, SDValue &Val)
Look for various patterns that can be done with a SHL that can be folded into a SHXADD.
bool tryIndexedLoad(SDNode *Node)
bool selectVSplatUimm(SDValue N, unsigned Bits, SDValue &SplatVal)
RISCVISelDAGToDAGPass(RISCVTargetMachine &TM, CodeGenOptLevel OptLevel)
bool hasShlAdd(int64_t ShAmt) const
static std::pair< unsigned, unsigned > decomposeSubvectorInsertExtractToSubRegs(MVT VecVT, MVT SubVecVT, unsigned InsertExtractIdx, const RISCVRegisterInfo *TRI)
static unsigned getRegClassIDForVecVT(MVT VT)
static RISCVVType::VLMUL getLMUL(MVT VT)
Wrapper class representing virtual and physical registers.
Definition Register.h:20
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
iterator_range< user_iterator > users()
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
EVT getValueType() const
Return the ValueType of the referenced return value.
bool isMachineOpcode() const
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getMachineOpcode() const
unsigned getOpcode() const
SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
const TargetLowering * TLI
const TargetInstrInfo * TII
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
virtual bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const
IsProfitableToFold - Returns true if it's profitable to fold the specific operand node N of U during ...
static bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root, CodeGenOptLevel OptLevel, bool IgnoreChains=false)
IsLegalToFold - Returns true if the specific operand node N of U can be folded during instruction sel...
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
static constexpr unsigned MaxRecursionDepth
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
ilist< SDNode >::iterator allnodes_iterator
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:346
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
Definition Use.cpp:36
User * getUser() const
Returns the User that contains this Use.
Definition Use.h:61
Value * getOperand(unsigned i) const
Definition User.h:207
unsigned getNumOperands() const
Definition User.h:229
iterator_range< user_iterator > users()
Definition Value.h:426
#define INT64_MIN
Definition DataTypes.h:74
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:829
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:275
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:602
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:863
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition ISDOpcodes.h:220
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:667
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:674
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:616
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:898
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:988
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:213
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
static bool hasVLOp(uint64_t TSFlags)
static bool hasVecPolicyOp(uint64_t TSFlags)
static bool hasSEWOp(uint64_t TSFlags)
static bool isFirstDefTiedToFirstUse(const MCInstrDesc &Desc)
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
int getIntMatCost(const APInt &Val, unsigned Size, const MCSubtargetInfo &STI, bool CompressionCost, bool FreeZeroes)
InstSeq generateTwoRegInstSeq(int64_t Val, const MCSubtargetInfo &STI, unsigned &ShiftAmt, unsigned &AddOpc)
SmallVector< Inst, 8 > InstSeq
Definition RISCVMatInt.h:43
static unsigned decodeVSEW(unsigned VSEW)
LLVM_ABI unsigned encodeXSfmmVType(unsigned SEW, unsigned Widen, bool AltFmt)
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
LLVM_ABI unsigned getSEWLMULRatio(unsigned SEW, VLMUL VLMul)
static unsigned decodeTWiden(unsigned TWiden)
LLVM_ABI unsigned encodeVTYPE(VLMUL VLMUL, unsigned SEW, bool TailAgnostic, bool MaskAgnostic, bool AltFmt=false)
unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode)
std::optional< unsigned > getVectorLowDemandedScalarBits(unsigned Opcode, unsigned Log2SEW)
static constexpr unsigned RVVBitsPerBlock
static constexpr int64_t VLMaxSentinel
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
static const MachineMemOperand::Flags MONontemporalBit1
InstructionCost Cost
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Known
Known to have no common set bits.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isStrongerThanMonotonic(AtomicOrdering AO)
FunctionPass * createRISCVISelDagLegacyPass(RISCVTargetMachine &TM, CodeGenOptLevel OptLevel)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
Definition bit.h:315
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
Definition MathExtras.h:224
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:325
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition MathExtras.h:244
static const MachineMemOperand::Flags MONontemporalBit0
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
Definition MathExtras.h:274
unsigned M1(unsigned Val)
Definition VE.h:377
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
Definition bit.h:263
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
Definition MathExtras.h:262
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:149
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
constexpr T maskTrailingZeros(unsigned N)
Create a bitmask with the N right-most bits set to 0, and all other bits set to 1.
Definition MathExtras.h:95
@ Add
Sum of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
Definition VE.h:376
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
Definition MathExtras.h:183
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
Definition MathExtras.h:233
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:201
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:567
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
Definition MathExtras.h:199
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Extended Value Type.
Definition ValueTypes.h:35
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
Definition ValueTypes.h:418
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
Definition ValueTypes.h:165
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.