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