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 case RISCVISD::WMACC:
2078 case RISCVISD::WMACCU:
2079 case RISCVISD::WMACCSU: {
2080 assert(!Subtarget->is64Bit() && Subtarget->hasStdExtP() &&
2081 "Unexpected opcode");
2082
2083 SDValue Op0 = buildGPRPair(CurDAG, DL, MVT::Untyped, Node->getOperand(0),
2084 Node->getOperand(1));
2085 unsigned Opc;
2086 switch (Opcode) {
2087 default:
2088 llvm_unreachable("Unexpected opcode");
2089 case RISCVISD::MQWACC:
2090 Opc = RISCV::MQWACC;
2091 break;
2092 case RISCVISD::MQRWACC:
2093 Opc = RISCV::MQRWACC;
2094 break;
2095 case RISCVISD::WMACC:
2096 Opc = RISCV::WMACC;
2097 break;
2098 case RISCVISD::WMACCU:
2099 Opc = RISCV::WMACCU;
2100 break;
2101 case RISCVISD::WMACCSU:
2102 Opc = RISCV::WMACCSU;
2103 break;
2104 }
2105 MachineSDNode *New = CurDAG->getMachineNode(
2106 Opc, DL, MVT::Untyped, Op0, Node->getOperand(2), Node->getOperand(3));
2107 auto [Lo, Hi] = extractGPRPair(CurDAG, DL, SDValue(New, 0));
2108 ReplaceUses(SDValue(Node, 0), Lo);
2109 ReplaceUses(SDValue(Node, 1), Hi);
2110 CurDAG->RemoveDeadNode(Node);
2111 return;
2112 }
2113 case RISCVISD::ADDD:
2114 // Try to match WMACC pattern: ADDD where one operand pair comes from a
2115 // widening multiply.
2117 return;
2118
2119 // Fall through to regular ADDD selection.
2120 [[fallthrough]];
2121 case RISCVISD::SUBD:
2122 case RISCVISD::WADDAU:
2123 case RISCVISD::WSUBAU:
2124 case RISCVISD::WADDA:
2125 case RISCVISD::WSUBA: {
2126 assert(!Subtarget->is64Bit() && Subtarget->hasStdExtP() &&
2127 "Unexpected opcode");
2128
2129 SDValue Op0Lo = Node->getOperand(0);
2130 SDValue Op0Hi = Node->getOperand(1);
2131
2132 SDValue Op0;
2133 if (isNullConstant(Op0Lo) && isNullConstant(Op0Hi)) {
2134 Op0 = CurDAG->getRegister(RISCV::X0_Pair, MVT::Untyped);
2135 } else {
2136 Op0 = buildGPRPair(CurDAG, DL, MVT::Untyped, Op0Lo, Op0Hi);
2137 }
2138
2139 SDValue Op1Lo = Node->getOperand(2);
2140 SDValue Op1Hi = Node->getOperand(3);
2141
2142 MachineSDNode *New;
2143 if (Opcode == RISCVISD::WADDAU || Opcode == RISCVISD::WSUBAU ||
2144 Opcode == RISCVISD::WADDA || Opcode == RISCVISD::WSUBA) {
2145 // Widening accumulate: Op0 is the accumulator (GPRPair), Op1Lo and Op1Hi
2146 // are the two 32-bit values.
2147 unsigned Opc;
2148 switch (Opcode) {
2149 default:
2150 llvm_unreachable("Unexpected opcode");
2151 case RISCVISD::WADDAU:
2152 Opc = RISCV::WADDAU;
2153 break;
2154 case RISCVISD::WSUBAU:
2155 Opc = RISCV::WSUBAU;
2156 break;
2157 case RISCVISD::WADDA:
2158 Opc = RISCV::WADDA;
2159 break;
2160 case RISCVISD::WSUBA:
2161 Opc = RISCV::WSUBA;
2162 break;
2163 }
2164 New = CurDAG->getMachineNode(Opc, DL, MVT::Untyped, Op0, Op1Lo, Op1Hi);
2165 } else {
2166 SDValue Op1 = buildGPRPair(CurDAG, DL, MVT::Untyped, Op1Lo, Op1Hi);
2167
2168 unsigned Opc;
2169 switch (Opcode) {
2170 default:
2171 llvm_unreachable("Unexpected opcode");
2172 case RISCVISD::ADDD:
2173 Opc = RISCV::ADDD;
2174 break;
2175 case RISCVISD::SUBD:
2176 Opc = RISCV::SUBD;
2177 break;
2178 }
2179 New = CurDAG->getMachineNode(Opc, DL, MVT::Untyped, Op0, Op1);
2180 }
2181
2182 auto [Lo, Hi] = extractGPRPair(CurDAG, DL, SDValue(New, 0));
2183 ReplaceUses(SDValue(Node, 0), Lo);
2184 ReplaceUses(SDValue(Node, 1), Hi);
2185 CurDAG->RemoveDeadNode(Node);
2186 return;
2187 }
2189 unsigned IntNo = Node->getConstantOperandVal(0);
2190 switch (IntNo) {
2191 // By default we do not custom select any intrinsic.
2192 default:
2193 break;
2194 case Intrinsic::riscv_vmsgeu:
2195 case Intrinsic::riscv_vmsge: {
2196 SDValue Src1 = Node->getOperand(1);
2197 SDValue Src2 = Node->getOperand(2);
2198 bool IsUnsigned = IntNo == Intrinsic::riscv_vmsgeu;
2199 bool IsCmpConstant = false;
2200 bool IsCmpMinimum = false;
2201 // Only custom select scalar second operand.
2202 if (Src2.getValueType() != XLenVT)
2203 break;
2204 // Small constants are handled with patterns.
2205 int64_t CVal = 0;
2206 MVT Src1VT = Src1.getSimpleValueType();
2207 if (auto *C = dyn_cast<ConstantSDNode>(Src2)) {
2208 IsCmpConstant = true;
2209 CVal = C->getSExtValue();
2210 if (CVal >= -15 && CVal <= 16) {
2211 if (!IsUnsigned || CVal != 0)
2212 break;
2213 IsCmpMinimum = true;
2214 } else if (!IsUnsigned && CVal == APInt::getSignedMinValue(
2215 Src1VT.getScalarSizeInBits())
2216 .getSExtValue()) {
2217 IsCmpMinimum = true;
2218 }
2219 }
2220 unsigned VMSLTOpcode, VMNANDOpcode, VMSetOpcode, VMSGTOpcode;
2221 switch (RISCVTargetLowering::getLMUL(Src1VT)) {
2222 default:
2223 llvm_unreachable("Unexpected LMUL!");
2224#define CASE_VMSLT_OPCODES(lmulenum, suffix) \
2225 case RISCVVType::lmulenum: \
2226 VMSLTOpcode = IsUnsigned ? RISCV::PseudoVMSLTU_VX_##suffix \
2227 : RISCV::PseudoVMSLT_VX_##suffix; \
2228 VMSGTOpcode = IsUnsigned ? RISCV::PseudoVMSGTU_VX_##suffix \
2229 : RISCV::PseudoVMSGT_VX_##suffix; \
2230 break;
2231 CASE_VMSLT_OPCODES(LMUL_F8, MF8)
2232 CASE_VMSLT_OPCODES(LMUL_F4, MF4)
2233 CASE_VMSLT_OPCODES(LMUL_F2, MF2)
2234 CASE_VMSLT_OPCODES(LMUL_1, M1)
2235 CASE_VMSLT_OPCODES(LMUL_2, M2)
2236 CASE_VMSLT_OPCODES(LMUL_4, M4)
2237 CASE_VMSLT_OPCODES(LMUL_8, M8)
2238#undef CASE_VMSLT_OPCODES
2239 }
2240 // Mask operations use the LMUL from the mask type.
2241 switch (RISCVTargetLowering::getLMUL(VT)) {
2242 default:
2243 llvm_unreachable("Unexpected LMUL!");
2244#define CASE_VMNAND_VMSET_OPCODES(lmulenum, suffix) \
2245 case RISCVVType::lmulenum: \
2246 VMNANDOpcode = RISCV::PseudoVMNAND_MM_##suffix; \
2247 VMSetOpcode = RISCV::PseudoVMSET_M_##suffix; \
2248 break;
2249 CASE_VMNAND_VMSET_OPCODES(LMUL_F8, B64)
2250 CASE_VMNAND_VMSET_OPCODES(LMUL_F4, B32)
2251 CASE_VMNAND_VMSET_OPCODES(LMUL_F2, B16)
2252 CASE_VMNAND_VMSET_OPCODES(LMUL_1, B8)
2253 CASE_VMNAND_VMSET_OPCODES(LMUL_2, B4)
2254 CASE_VMNAND_VMSET_OPCODES(LMUL_4, B2)
2255 CASE_VMNAND_VMSET_OPCODES(LMUL_8, B1)
2256#undef CASE_VMNAND_VMSET_OPCODES
2257 }
2258 SDValue SEW = CurDAG->getTargetConstant(
2259 Log2_32(Src1VT.getScalarSizeInBits()), DL, XLenVT);
2260 SDValue MaskSEW = CurDAG->getTargetConstant(0, DL, XLenVT);
2261 SDValue VL;
2262 selectVLOp(Node->getOperand(3), VL);
2263
2264 // If vmsge(u) with minimum value, expand it to vmset.
2265 if (IsCmpMinimum) {
2267 CurDAG->getMachineNode(VMSetOpcode, DL, VT, VL, MaskSEW));
2268 return;
2269 }
2270
2271 if (IsCmpConstant) {
2272 SDValue Imm =
2273 selectImm(CurDAG, SDLoc(Src2), XLenVT, CVal - 1, *Subtarget);
2274
2275 ReplaceNode(Node, CurDAG->getMachineNode(VMSGTOpcode, DL, VT,
2276 {Src1, Imm, VL, SEW}));
2277 return;
2278 }
2279
2280 // Expand to
2281 // vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
2282 SDValue Cmp = SDValue(
2283 CurDAG->getMachineNode(VMSLTOpcode, DL, VT, {Src1, Src2, VL, SEW}),
2284 0);
2285 ReplaceNode(Node, CurDAG->getMachineNode(VMNANDOpcode, DL, VT,
2286 {Cmp, Cmp, VL, MaskSEW}));
2287 return;
2288 }
2289 case Intrinsic::riscv_vmsgeu_mask:
2290 case Intrinsic::riscv_vmsge_mask: {
2291 SDValue Src1 = Node->getOperand(2);
2292 SDValue Src2 = Node->getOperand(3);
2293 bool IsUnsigned = IntNo == Intrinsic::riscv_vmsgeu_mask;
2294 bool IsCmpConstant = false;
2295 bool IsCmpMinimum = false;
2296 // Only custom select scalar second operand.
2297 if (Src2.getValueType() != XLenVT)
2298 break;
2299 // Small constants are handled with patterns.
2300 MVT Src1VT = Src1.getSimpleValueType();
2301 int64_t CVal = 0;
2302 if (auto *C = dyn_cast<ConstantSDNode>(Src2)) {
2303 IsCmpConstant = true;
2304 CVal = C->getSExtValue();
2305 if (CVal >= -15 && CVal <= 16) {
2306 if (!IsUnsigned || CVal != 0)
2307 break;
2308 IsCmpMinimum = true;
2309 } else if (!IsUnsigned && CVal == APInt::getSignedMinValue(
2310 Src1VT.getScalarSizeInBits())
2311 .getSExtValue()) {
2312 IsCmpMinimum = true;
2313 }
2314 }
2315 unsigned VMSLTOpcode, VMSLTMaskOpcode, VMXOROpcode, VMANDNOpcode,
2316 VMOROpcode, VMSGTMaskOpcode;
2317 switch (RISCVTargetLowering::getLMUL(Src1VT)) {
2318 default:
2319 llvm_unreachable("Unexpected LMUL!");
2320#define CASE_VMSLT_OPCODES(lmulenum, suffix) \
2321 case RISCVVType::lmulenum: \
2322 VMSLTOpcode = IsUnsigned ? RISCV::PseudoVMSLTU_VX_##suffix \
2323 : RISCV::PseudoVMSLT_VX_##suffix; \
2324 VMSLTMaskOpcode = IsUnsigned ? RISCV::PseudoVMSLTU_VX_##suffix##_MASK \
2325 : RISCV::PseudoVMSLT_VX_##suffix##_MASK; \
2326 VMSGTMaskOpcode = IsUnsigned ? RISCV::PseudoVMSGTU_VX_##suffix##_MASK \
2327 : RISCV::PseudoVMSGT_VX_##suffix##_MASK; \
2328 break;
2329 CASE_VMSLT_OPCODES(LMUL_F8, MF8)
2330 CASE_VMSLT_OPCODES(LMUL_F4, MF4)
2331 CASE_VMSLT_OPCODES(LMUL_F2, MF2)
2332 CASE_VMSLT_OPCODES(LMUL_1, M1)
2333 CASE_VMSLT_OPCODES(LMUL_2, M2)
2334 CASE_VMSLT_OPCODES(LMUL_4, M4)
2335 CASE_VMSLT_OPCODES(LMUL_8, M8)
2336#undef CASE_VMSLT_OPCODES
2337 }
2338 // Mask operations use the LMUL from the mask type.
2339 switch (RISCVTargetLowering::getLMUL(VT)) {
2340 default:
2341 llvm_unreachable("Unexpected LMUL!");
2342#define CASE_VMXOR_VMANDN_VMOR_OPCODES(lmulenum, suffix) \
2343 case RISCVVType::lmulenum: \
2344 VMXOROpcode = RISCV::PseudoVMXOR_MM_##suffix; \
2345 VMANDNOpcode = RISCV::PseudoVMANDN_MM_##suffix; \
2346 VMOROpcode = RISCV::PseudoVMOR_MM_##suffix; \
2347 break;
2348 CASE_VMXOR_VMANDN_VMOR_OPCODES(LMUL_F8, B64)
2349 CASE_VMXOR_VMANDN_VMOR_OPCODES(LMUL_F4, B32)
2350 CASE_VMXOR_VMANDN_VMOR_OPCODES(LMUL_F2, B16)
2355#undef CASE_VMXOR_VMANDN_VMOR_OPCODES
2356 }
2357 SDValue SEW = CurDAG->getTargetConstant(
2358 Log2_32(Src1VT.getScalarSizeInBits()), DL, XLenVT);
2359 SDValue MaskSEW = CurDAG->getTargetConstant(0, DL, XLenVT);
2360 SDValue VL;
2361 selectVLOp(Node->getOperand(5), VL);
2362 SDValue MaskedOff = Node->getOperand(1);
2363 SDValue Mask = Node->getOperand(4);
2364
2365 // If vmsge(u) with minimum value, expand it to vmor mask, maskedoff.
2366 if (IsCmpMinimum) {
2367 // We don't need vmor if the MaskedOff and the Mask are the same
2368 // value.
2369 if (Mask == MaskedOff) {
2370 ReplaceUses(Node, Mask.getNode());
2371 return;
2372 }
2374 CurDAG->getMachineNode(VMOROpcode, DL, VT,
2375 {Mask, MaskedOff, VL, MaskSEW}));
2376 return;
2377 }
2378
2379 // If the MaskedOff value and the Mask are the same value use
2380 // vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
2381 // This avoids needing to copy v0 to vd before starting the next sequence.
2382 if (Mask == MaskedOff) {
2383 SDValue Cmp = SDValue(
2384 CurDAG->getMachineNode(VMSLTOpcode, DL, VT, {Src1, Src2, VL, SEW}),
2385 0);
2386 ReplaceNode(Node, CurDAG->getMachineNode(VMANDNOpcode, DL, VT,
2387 {Mask, Cmp, VL, MaskSEW}));
2388 return;
2389 }
2390
2391 SDValue PolicyOp =
2392 CurDAG->getTargetConstant(RISCVVType::TAIL_AGNOSTIC, DL, XLenVT);
2393
2394 if (IsCmpConstant) {
2395 SDValue Imm =
2396 selectImm(CurDAG, SDLoc(Src2), XLenVT, CVal - 1, *Subtarget);
2397
2398 ReplaceNode(Node, CurDAG->getMachineNode(
2399 VMSGTMaskOpcode, DL, VT,
2400 {MaskedOff, Src1, Imm, Mask, VL, SEW, PolicyOp}));
2401 return;
2402 }
2403
2404 // Otherwise use
2405 // vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
2406 // The result is mask undisturbed.
2407 // We use the same instructions to emulate mask agnostic behavior, because
2408 // the agnostic result can be either undisturbed or all 1.
2409 SDValue Cmp = SDValue(CurDAG->getMachineNode(VMSLTMaskOpcode, DL, VT,
2410 {MaskedOff, Src1, Src2, Mask,
2411 VL, SEW, PolicyOp}),
2412 0);
2413 // vmxor.mm vd, vd, v0 is used to update active value.
2414 ReplaceNode(Node, CurDAG->getMachineNode(VMXOROpcode, DL, VT,
2415 {Cmp, Mask, VL, MaskSEW}));
2416 return;
2417 }
2418 case Intrinsic::riscv_vsetvli:
2419 case Intrinsic::riscv_vsetvlimax:
2420 return selectVSETVLI(Node);
2421 case Intrinsic::riscv_sf_vsettnt:
2422 case Intrinsic::riscv_sf_vsettm:
2423 case Intrinsic::riscv_sf_vsettk:
2424 return selectXSfmmVSET(Node);
2425 }
2426 break;
2427 }
2429 unsigned IntNo = Node->getConstantOperandVal(1);
2430 switch (IntNo) {
2431 // By default we do not custom select any intrinsic.
2432 default:
2433 break;
2434 case Intrinsic::riscv_vlseg2:
2435 case Intrinsic::riscv_vlseg3:
2436 case Intrinsic::riscv_vlseg4:
2437 case Intrinsic::riscv_vlseg5:
2438 case Intrinsic::riscv_vlseg6:
2439 case Intrinsic::riscv_vlseg7:
2440 case Intrinsic::riscv_vlseg8: {
2441 selectVLSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2442 /*IsStrided*/ false);
2443 return;
2444 }
2445 case Intrinsic::riscv_vlseg2_mask:
2446 case Intrinsic::riscv_vlseg3_mask:
2447 case Intrinsic::riscv_vlseg4_mask:
2448 case Intrinsic::riscv_vlseg5_mask:
2449 case Intrinsic::riscv_vlseg6_mask:
2450 case Intrinsic::riscv_vlseg7_mask:
2451 case Intrinsic::riscv_vlseg8_mask: {
2452 selectVLSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2453 /*IsStrided*/ false);
2454 return;
2455 }
2456 case Intrinsic::riscv_vlsseg2:
2457 case Intrinsic::riscv_vlsseg3:
2458 case Intrinsic::riscv_vlsseg4:
2459 case Intrinsic::riscv_vlsseg5:
2460 case Intrinsic::riscv_vlsseg6:
2461 case Intrinsic::riscv_vlsseg7:
2462 case Intrinsic::riscv_vlsseg8: {
2463 selectVLSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2464 /*IsStrided*/ true);
2465 return;
2466 }
2467 case Intrinsic::riscv_vlsseg2_mask:
2468 case Intrinsic::riscv_vlsseg3_mask:
2469 case Intrinsic::riscv_vlsseg4_mask:
2470 case Intrinsic::riscv_vlsseg5_mask:
2471 case Intrinsic::riscv_vlsseg6_mask:
2472 case Intrinsic::riscv_vlsseg7_mask:
2473 case Intrinsic::riscv_vlsseg8_mask: {
2474 selectVLSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2475 /*IsStrided*/ true);
2476 return;
2477 }
2478 case Intrinsic::riscv_vloxseg2:
2479 case Intrinsic::riscv_vloxseg3:
2480 case Intrinsic::riscv_vloxseg4:
2481 case Intrinsic::riscv_vloxseg5:
2482 case Intrinsic::riscv_vloxseg6:
2483 case Intrinsic::riscv_vloxseg7:
2484 case Intrinsic::riscv_vloxseg8:
2485 selectVLXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2486 /*IsOrdered*/ true);
2487 return;
2488 case Intrinsic::riscv_vluxseg2:
2489 case Intrinsic::riscv_vluxseg3:
2490 case Intrinsic::riscv_vluxseg4:
2491 case Intrinsic::riscv_vluxseg5:
2492 case Intrinsic::riscv_vluxseg6:
2493 case Intrinsic::riscv_vluxseg7:
2494 case Intrinsic::riscv_vluxseg8:
2495 selectVLXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2496 /*IsOrdered*/ false);
2497 return;
2498 case Intrinsic::riscv_vloxseg2_mask:
2499 case Intrinsic::riscv_vloxseg3_mask:
2500 case Intrinsic::riscv_vloxseg4_mask:
2501 case Intrinsic::riscv_vloxseg5_mask:
2502 case Intrinsic::riscv_vloxseg6_mask:
2503 case Intrinsic::riscv_vloxseg7_mask:
2504 case Intrinsic::riscv_vloxseg8_mask:
2505 selectVLXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2506 /*IsOrdered*/ true);
2507 return;
2508 case Intrinsic::riscv_vluxseg2_mask:
2509 case Intrinsic::riscv_vluxseg3_mask:
2510 case Intrinsic::riscv_vluxseg4_mask:
2511 case Intrinsic::riscv_vluxseg5_mask:
2512 case Intrinsic::riscv_vluxseg6_mask:
2513 case Intrinsic::riscv_vluxseg7_mask:
2514 case Intrinsic::riscv_vluxseg8_mask:
2515 selectVLXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2516 /*IsOrdered*/ false);
2517 return;
2518 case Intrinsic::riscv_vlseg8ff:
2519 case Intrinsic::riscv_vlseg7ff:
2520 case Intrinsic::riscv_vlseg6ff:
2521 case Intrinsic::riscv_vlseg5ff:
2522 case Intrinsic::riscv_vlseg4ff:
2523 case Intrinsic::riscv_vlseg3ff:
2524 case Intrinsic::riscv_vlseg2ff: {
2525 selectVLSEGFF(Node, getSegInstNF(IntNo), /*IsMasked*/ false);
2526 return;
2527 }
2528 case Intrinsic::riscv_vlseg8ff_mask:
2529 case Intrinsic::riscv_vlseg7ff_mask:
2530 case Intrinsic::riscv_vlseg6ff_mask:
2531 case Intrinsic::riscv_vlseg5ff_mask:
2532 case Intrinsic::riscv_vlseg4ff_mask:
2533 case Intrinsic::riscv_vlseg3ff_mask:
2534 case Intrinsic::riscv_vlseg2ff_mask: {
2535 selectVLSEGFF(Node, getSegInstNF(IntNo), /*IsMasked*/ true);
2536 return;
2537 }
2538 case Intrinsic::riscv_vloxei:
2539 case Intrinsic::riscv_vloxei_mask:
2540 case Intrinsic::riscv_vluxei:
2541 case Intrinsic::riscv_vluxei_mask: {
2542 bool IsMasked = IntNo == Intrinsic::riscv_vloxei_mask ||
2543 IntNo == Intrinsic::riscv_vluxei_mask;
2544 bool IsOrdered = IntNo == Intrinsic::riscv_vloxei ||
2545 IntNo == Intrinsic::riscv_vloxei_mask;
2546
2547 MVT VT = Node->getSimpleValueType(0);
2548 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2549
2550 unsigned CurOp = 2;
2552 Operands.push_back(Node->getOperand(CurOp++));
2553
2554 MVT IndexVT;
2555 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked,
2556 /*IsStridedOrIndexed*/ true, Operands,
2557 /*IsLoad=*/true, &IndexVT);
2558
2560 "Element count mismatch");
2561
2564 unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
2565 if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
2566 reportFatalUsageError("The V extension does not support EEW=64 for "
2567 "index values when XLEN=32");
2568 }
2569 const RISCV::VLX_VSXPseudo *P = RISCV::getVLXPseudo(
2570 IsMasked, IsOrdered, IndexLog2EEW, static_cast<unsigned>(LMUL),
2571 static_cast<unsigned>(IndexLMUL));
2573 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands);
2574
2575 CurDAG->setNodeMemRefs(Load, {cast<MemSDNode>(Node)->getMemOperand()});
2576
2578 return;
2579 }
2580 case Intrinsic::riscv_vlm:
2581 case Intrinsic::riscv_vle:
2582 case Intrinsic::riscv_vle_mask:
2583 case Intrinsic::riscv_vlse:
2584 case Intrinsic::riscv_vlse_mask: {
2585 bool IsMasked = IntNo == Intrinsic::riscv_vle_mask ||
2586 IntNo == Intrinsic::riscv_vlse_mask;
2587 bool IsStrided =
2588 IntNo == Intrinsic::riscv_vlse || IntNo == Intrinsic::riscv_vlse_mask;
2589
2590 MVT VT = Node->getSimpleValueType(0);
2591 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2592
2593 // The riscv_vlm intrinsic are always tail agnostic and no passthru
2594 // operand at the IR level. In pseudos, they have both policy and
2595 // passthru operand. The passthru operand is needed to track the
2596 // "tail undefined" state, and the policy is there just for
2597 // for consistency - it will always be "don't care" for the
2598 // unmasked form.
2599 bool HasPassthruOperand = IntNo != Intrinsic::riscv_vlm;
2600 unsigned CurOp = 2;
2602 if (HasPassthruOperand)
2603 Operands.push_back(Node->getOperand(CurOp++));
2604 else {
2605 // We eagerly lower to implicit_def (instead of undef), as we
2606 // otherwise fail to select nodes such as: nxv1i1 = undef
2607 SDNode *Passthru =
2608 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, VT);
2609 Operands.push_back(SDValue(Passthru, 0));
2610 }
2611 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked, IsStrided,
2612 Operands, /*IsLoad=*/true);
2613
2615 const RISCV::VLEPseudo *P =
2616 RISCV::getVLEPseudo(IsMasked, IsStrided, /*FF*/ false, Log2SEW,
2617 static_cast<unsigned>(LMUL));
2619 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands);
2620
2621 CurDAG->setNodeMemRefs(Load, {cast<MemSDNode>(Node)->getMemOperand()});
2622
2624 return;
2625 }
2626 case Intrinsic::riscv_vleff:
2627 case Intrinsic::riscv_vleff_mask: {
2628 bool IsMasked = IntNo == Intrinsic::riscv_vleff_mask;
2629
2630 MVT VT = Node->getSimpleValueType(0);
2631 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2632
2633 unsigned CurOp = 2;
2635 Operands.push_back(Node->getOperand(CurOp++));
2636 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked,
2637 /*IsStridedOrIndexed*/ false, Operands,
2638 /*IsLoad=*/true);
2639
2641 const RISCV::VLEPseudo *P =
2642 RISCV::getVLEPseudo(IsMasked, /*Strided*/ false, /*FF*/ true,
2643 Log2SEW, static_cast<unsigned>(LMUL));
2644 MachineSDNode *Load = CurDAG->getMachineNode(
2645 P->Pseudo, DL, Node->getVTList(), Operands);
2646 CurDAG->setNodeMemRefs(Load, {cast<MemSDNode>(Node)->getMemOperand()});
2647
2649 return;
2650 }
2651 case Intrinsic::riscv_nds_vln:
2652 case Intrinsic::riscv_nds_vln_mask:
2653 case Intrinsic::riscv_nds_vlnu:
2654 case Intrinsic::riscv_nds_vlnu_mask: {
2655 bool IsMasked = IntNo == Intrinsic::riscv_nds_vln_mask ||
2656 IntNo == Intrinsic::riscv_nds_vlnu_mask;
2657 bool IsUnsigned = IntNo == Intrinsic::riscv_nds_vlnu ||
2658 IntNo == Intrinsic::riscv_nds_vlnu_mask;
2659
2660 MVT VT = Node->getSimpleValueType(0);
2661 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2662 unsigned CurOp = 2;
2664
2665 Operands.push_back(Node->getOperand(CurOp++));
2666 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked,
2667 /*IsStridedOrIndexed=*/false, Operands,
2668 /*IsLoad=*/true);
2669
2671 const RISCV::NDSVLNPseudo *P = RISCV::getNDSVLNPseudo(
2672 IsMasked, IsUnsigned, Log2SEW, static_cast<unsigned>(LMUL));
2674 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands);
2675
2676 if (auto *MemOp = dyn_cast<MemSDNode>(Node))
2677 CurDAG->setNodeMemRefs(Load, {MemOp->getMemOperand()});
2678
2680 return;
2681 }
2682 }
2683 break;
2684 }
2685 case ISD::INTRINSIC_VOID: {
2686 unsigned IntNo = Node->getConstantOperandVal(1);
2687 switch (IntNo) {
2688 case Intrinsic::riscv_vsseg2:
2689 case Intrinsic::riscv_vsseg3:
2690 case Intrinsic::riscv_vsseg4:
2691 case Intrinsic::riscv_vsseg5:
2692 case Intrinsic::riscv_vsseg6:
2693 case Intrinsic::riscv_vsseg7:
2694 case Intrinsic::riscv_vsseg8: {
2695 selectVSSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2696 /*IsStrided*/ false);
2697 return;
2698 }
2699 case Intrinsic::riscv_vsseg2_mask:
2700 case Intrinsic::riscv_vsseg3_mask:
2701 case Intrinsic::riscv_vsseg4_mask:
2702 case Intrinsic::riscv_vsseg5_mask:
2703 case Intrinsic::riscv_vsseg6_mask:
2704 case Intrinsic::riscv_vsseg7_mask:
2705 case Intrinsic::riscv_vsseg8_mask: {
2706 selectVSSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2707 /*IsStrided*/ false);
2708 return;
2709 }
2710 case Intrinsic::riscv_vssseg2:
2711 case Intrinsic::riscv_vssseg3:
2712 case Intrinsic::riscv_vssseg4:
2713 case Intrinsic::riscv_vssseg5:
2714 case Intrinsic::riscv_vssseg6:
2715 case Intrinsic::riscv_vssseg7:
2716 case Intrinsic::riscv_vssseg8: {
2717 selectVSSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2718 /*IsStrided*/ true);
2719 return;
2720 }
2721 case Intrinsic::riscv_vssseg2_mask:
2722 case Intrinsic::riscv_vssseg3_mask:
2723 case Intrinsic::riscv_vssseg4_mask:
2724 case Intrinsic::riscv_vssseg5_mask:
2725 case Intrinsic::riscv_vssseg6_mask:
2726 case Intrinsic::riscv_vssseg7_mask:
2727 case Intrinsic::riscv_vssseg8_mask: {
2728 selectVSSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2729 /*IsStrided*/ true);
2730 return;
2731 }
2732 case Intrinsic::riscv_vsoxseg2:
2733 case Intrinsic::riscv_vsoxseg3:
2734 case Intrinsic::riscv_vsoxseg4:
2735 case Intrinsic::riscv_vsoxseg5:
2736 case Intrinsic::riscv_vsoxseg6:
2737 case Intrinsic::riscv_vsoxseg7:
2738 case Intrinsic::riscv_vsoxseg8:
2739 selectVSXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2740 /*IsOrdered*/ true);
2741 return;
2742 case Intrinsic::riscv_vsuxseg2:
2743 case Intrinsic::riscv_vsuxseg3:
2744 case Intrinsic::riscv_vsuxseg4:
2745 case Intrinsic::riscv_vsuxseg5:
2746 case Intrinsic::riscv_vsuxseg6:
2747 case Intrinsic::riscv_vsuxseg7:
2748 case Intrinsic::riscv_vsuxseg8:
2749 selectVSXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ false,
2750 /*IsOrdered*/ false);
2751 return;
2752 case Intrinsic::riscv_vsoxseg2_mask:
2753 case Intrinsic::riscv_vsoxseg3_mask:
2754 case Intrinsic::riscv_vsoxseg4_mask:
2755 case Intrinsic::riscv_vsoxseg5_mask:
2756 case Intrinsic::riscv_vsoxseg6_mask:
2757 case Intrinsic::riscv_vsoxseg7_mask:
2758 case Intrinsic::riscv_vsoxseg8_mask:
2759 selectVSXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2760 /*IsOrdered*/ true);
2761 return;
2762 case Intrinsic::riscv_vsuxseg2_mask:
2763 case Intrinsic::riscv_vsuxseg3_mask:
2764 case Intrinsic::riscv_vsuxseg4_mask:
2765 case Intrinsic::riscv_vsuxseg5_mask:
2766 case Intrinsic::riscv_vsuxseg6_mask:
2767 case Intrinsic::riscv_vsuxseg7_mask:
2768 case Intrinsic::riscv_vsuxseg8_mask:
2769 selectVSXSEG(Node, getSegInstNF(IntNo), /*IsMasked*/ true,
2770 /*IsOrdered*/ false);
2771 return;
2772 case Intrinsic::riscv_vsoxei:
2773 case Intrinsic::riscv_vsoxei_mask:
2774 case Intrinsic::riscv_vsuxei:
2775 case Intrinsic::riscv_vsuxei_mask: {
2776 bool IsMasked = IntNo == Intrinsic::riscv_vsoxei_mask ||
2777 IntNo == Intrinsic::riscv_vsuxei_mask;
2778 bool IsOrdered = IntNo == Intrinsic::riscv_vsoxei ||
2779 IntNo == Intrinsic::riscv_vsoxei_mask;
2780
2781 MVT VT = Node->getOperand(2)->getSimpleValueType(0);
2782 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2783
2784 unsigned CurOp = 2;
2786 Operands.push_back(Node->getOperand(CurOp++)); // Store value.
2787
2788 MVT IndexVT;
2789 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked,
2790 /*IsStridedOrIndexed*/ true, Operands,
2791 /*IsLoad=*/false, &IndexVT);
2792
2794 "Element count mismatch");
2795
2798 unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
2799 if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
2800 reportFatalUsageError("The V extension does not support EEW=64 for "
2801 "index values when XLEN=32");
2802 }
2803 const RISCV::VLX_VSXPseudo *P = RISCV::getVSXPseudo(
2804 IsMasked, IsOrdered, IndexLog2EEW,
2805 static_cast<unsigned>(LMUL), static_cast<unsigned>(IndexLMUL));
2807 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands);
2808
2809 CurDAG->setNodeMemRefs(Store, {cast<MemSDNode>(Node)->getMemOperand()});
2810
2812 return;
2813 }
2814 case Intrinsic::riscv_vsm:
2815 case Intrinsic::riscv_vse:
2816 case Intrinsic::riscv_vse_mask:
2817 case Intrinsic::riscv_vsse:
2818 case Intrinsic::riscv_vsse_mask: {
2819 bool IsMasked = IntNo == Intrinsic::riscv_vse_mask ||
2820 IntNo == Intrinsic::riscv_vsse_mask;
2821 bool IsStrided =
2822 IntNo == Intrinsic::riscv_vsse || IntNo == Intrinsic::riscv_vsse_mask;
2823
2824 MVT VT = Node->getOperand(2)->getSimpleValueType(0);
2825 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2826
2827 unsigned CurOp = 2;
2829 Operands.push_back(Node->getOperand(CurOp++)); // Store value.
2830
2831 addVectorLoadStoreOperands(Node, Log2SEW, DL, CurOp, IsMasked, IsStrided,
2832 Operands);
2833
2835 const RISCV::VSEPseudo *P = RISCV::getVSEPseudo(
2836 IsMasked, IsStrided, Log2SEW, static_cast<unsigned>(LMUL));
2838 CurDAG->getMachineNode(P->Pseudo, DL, Node->getVTList(), Operands);
2839 CurDAG->setNodeMemRefs(Store, {cast<MemSDNode>(Node)->getMemOperand()});
2840
2842 return;
2843 }
2844 case Intrinsic::riscv_sf_vc_x_se:
2845 case Intrinsic::riscv_sf_vc_i_se:
2847 return;
2848 case Intrinsic::riscv_sf_vlte8:
2849 case Intrinsic::riscv_sf_vlte16:
2850 case Intrinsic::riscv_sf_vlte32:
2851 case Intrinsic::riscv_sf_vlte64: {
2852 unsigned Log2SEW;
2853 unsigned PseudoInst;
2854 switch (IntNo) {
2855 case Intrinsic::riscv_sf_vlte8:
2856 PseudoInst = RISCV::PseudoSF_VLTE8;
2857 Log2SEW = 3;
2858 break;
2859 case Intrinsic::riscv_sf_vlte16:
2860 PseudoInst = RISCV::PseudoSF_VLTE16;
2861 Log2SEW = 4;
2862 break;
2863 case Intrinsic::riscv_sf_vlte32:
2864 PseudoInst = RISCV::PseudoSF_VLTE32;
2865 Log2SEW = 5;
2866 break;
2867 case Intrinsic::riscv_sf_vlte64:
2868 PseudoInst = RISCV::PseudoSF_VLTE64;
2869 Log2SEW = 6;
2870 break;
2871 }
2872
2873 SDValue SEWOp = CurDAG->getTargetConstant(Log2SEW, DL, XLenVT);
2874 SDValue TWidenOp = CurDAG->getTargetConstant(1, DL, XLenVT);
2875 SDValue Operands[] = {Node->getOperand(2),
2876 Node->getOperand(3),
2877 Node->getOperand(4),
2878 SEWOp,
2879 TWidenOp,
2880 Node->getOperand(0)};
2881
2882 MachineSDNode *TileLoad =
2883 CurDAG->getMachineNode(PseudoInst, DL, Node->getVTList(), Operands);
2884 CurDAG->setNodeMemRefs(TileLoad,
2885 {cast<MemSDNode>(Node)->getMemOperand()});
2886
2887 ReplaceNode(Node, TileLoad);
2888 return;
2889 }
2890 case Intrinsic::riscv_sf_mm_s_s:
2891 case Intrinsic::riscv_sf_mm_s_u:
2892 case Intrinsic::riscv_sf_mm_u_s:
2893 case Intrinsic::riscv_sf_mm_u_u:
2894 case Intrinsic::riscv_sf_mm_e5m2_e5m2:
2895 case Intrinsic::riscv_sf_mm_e5m2_e4m3:
2896 case Intrinsic::riscv_sf_mm_e4m3_e5m2:
2897 case Intrinsic::riscv_sf_mm_e4m3_e4m3:
2898 case Intrinsic::riscv_sf_mm_f_f: {
2899 bool HasFRM = false;
2900 unsigned PseudoInst;
2901 switch (IntNo) {
2902 case Intrinsic::riscv_sf_mm_s_s:
2903 PseudoInst = RISCV::PseudoSF_MM_S_S;
2904 break;
2905 case Intrinsic::riscv_sf_mm_s_u:
2906 PseudoInst = RISCV::PseudoSF_MM_S_U;
2907 break;
2908 case Intrinsic::riscv_sf_mm_u_s:
2909 PseudoInst = RISCV::PseudoSF_MM_U_S;
2910 break;
2911 case Intrinsic::riscv_sf_mm_u_u:
2912 PseudoInst = RISCV::PseudoSF_MM_U_U;
2913 break;
2914 case Intrinsic::riscv_sf_mm_e5m2_e5m2:
2915 PseudoInst = RISCV::PseudoSF_MM_E5M2_E5M2;
2916 HasFRM = true;
2917 break;
2918 case Intrinsic::riscv_sf_mm_e5m2_e4m3:
2919 PseudoInst = RISCV::PseudoSF_MM_E5M2_E4M3;
2920 HasFRM = true;
2921 break;
2922 case Intrinsic::riscv_sf_mm_e4m3_e5m2:
2923 PseudoInst = RISCV::PseudoSF_MM_E4M3_E5M2;
2924 HasFRM = true;
2925 break;
2926 case Intrinsic::riscv_sf_mm_e4m3_e4m3:
2927 PseudoInst = RISCV::PseudoSF_MM_E4M3_E4M3;
2928 HasFRM = true;
2929 break;
2930 case Intrinsic::riscv_sf_mm_f_f:
2931 if (Node->getOperand(3).getValueType().getScalarType() == MVT::bf16)
2932 PseudoInst = RISCV::PseudoSF_MM_F_F_ALT;
2933 else
2934 PseudoInst = RISCV::PseudoSF_MM_F_F;
2935 HasFRM = true;
2936 break;
2937 }
2938 uint64_t TileNum = Node->getConstantOperandVal(2);
2939 SDValue Op1 = Node->getOperand(3);
2940 SDValue Op2 = Node->getOperand(4);
2941 MVT VT = Op1->getSimpleValueType(0);
2942 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
2943 SDValue TmOp = Node->getOperand(5);
2944 SDValue TnOp = Node->getOperand(6);
2945 SDValue TkOp = Node->getOperand(7);
2946 SDValue TWidenOp = Node->getOperand(8);
2947 SDValue Chain = Node->getOperand(0);
2948
2949 // sf.mm.f.f with sew=32, twiden=2 is invalid
2950 if (IntNo == Intrinsic::riscv_sf_mm_f_f && Log2SEW == 5 &&
2951 TWidenOp->getAsZExtVal() == 2)
2952 reportFatalUsageError("sf.mm.f.f doesn't support (sew=32, twiden=2)");
2953
2955 {CurDAG->getRegister(getTileReg(TileNum), XLenVT), Op1, Op2});
2956 if (HasFRM)
2957 Operands.push_back(
2958 CurDAG->getTargetConstant(RISCVFPRndMode::DYN, DL, XLenVT));
2959 Operands.append({TmOp, TnOp, TkOp,
2960 CurDAG->getTargetConstant(Log2SEW, DL, XLenVT), TWidenOp,
2961 Chain});
2962
2963 auto *NewNode =
2964 CurDAG->getMachineNode(PseudoInst, DL, Node->getVTList(), Operands);
2965
2966 ReplaceNode(Node, NewNode);
2967 return;
2968 }
2969 case Intrinsic::riscv_sf_vtzero_t: {
2970 uint64_t TileNum = Node->getConstantOperandVal(2);
2971 SDValue Tm = Node->getOperand(3);
2972 SDValue Tn = Node->getOperand(4);
2973 SDValue Log2SEW = Node->getOperand(5);
2974 SDValue TWiden = Node->getOperand(6);
2975 SDValue Chain = Node->getOperand(0);
2976 auto *NewNode = CurDAG->getMachineNode(
2977 RISCV::PseudoSF_VTZERO_T, DL, Node->getVTList(),
2978 {CurDAG->getRegister(getTileReg(TileNum), XLenVT), Tm, Tn, Log2SEW,
2979 TWiden, Chain});
2980
2981 ReplaceNode(Node, NewNode);
2982 return;
2983 }
2984 }
2985 break;
2986 }
2987 case ISD::BITCAST: {
2988 MVT SrcVT = Node->getOperand(0).getSimpleValueType();
2989 // Just drop bitcasts between vectors if both are fixed or both are
2990 // scalable.
2991 if ((VT.isScalableVector() && SrcVT.isScalableVector()) ||
2992 (VT.isFixedLengthVector() && SrcVT.isFixedLengthVector())) {
2993 ReplaceUses(SDValue(Node, 0), Node->getOperand(0));
2994 CurDAG->RemoveDeadNode(Node);
2995 return;
2996 }
2997 if (Subtarget->hasStdExtP()) {
2998 bool Is32BitCast =
2999 (VT == MVT::i32 && (SrcVT == MVT::v4i8 || SrcVT == MVT::v2i16)) ||
3000 (SrcVT == MVT::i32 && (VT == MVT::v4i8 || VT == MVT::v2i16));
3001 bool Is64BitCast =
3002 (VT == MVT::i64 && (SrcVT == MVT::v8i8 || SrcVT == MVT::v4i16 ||
3003 SrcVT == MVT::v2i32)) ||
3004 (SrcVT == MVT::i64 &&
3005 (VT == MVT::v8i8 || VT == MVT::v4i16 || VT == MVT::v2i32));
3006 if (Is32BitCast || Is64BitCast) {
3007 ReplaceUses(SDValue(Node, 0), Node->getOperand(0));
3008 CurDAG->RemoveDeadNode(Node);
3009 return;
3010 }
3011 }
3012 break;
3013 }
3014 case ISD::SPLAT_VECTOR: {
3015 if (!Subtarget->hasStdExtP())
3016 break;
3017 if (auto *ConstNode = dyn_cast<ConstantSDNode>(Node->getOperand(0))) {
3018 bool IsDoubleWide = Subtarget->isPExtPackedDoubleType(VT);
3019
3020 if (ConstNode->isZero()) {
3021 MCPhysReg X0Reg = IsDoubleWide ? RISCV::X0_Pair : RISCV::X0;
3022 SDValue New =
3023 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, X0Reg, VT);
3024 ReplaceNode(Node, New.getNode());
3025 return;
3026 }
3027
3028 unsigned EltSize = VT.getVectorElementType().getSizeInBits();
3029 APInt Val = ConstNode->getAPIntValue().trunc(EltSize);
3030
3031 // Use LI for all ones since it can be compressed to c.li.
3032 if (Val.isAllOnes() && !IsDoubleWide) {
3033 SDNode *NewNode = CurDAG->getMachineNode(
3034 RISCV::ADDI, DL, VT, CurDAG->getRegister(RISCV::X0, VT),
3035 CurDAG->getAllOnesConstant(DL, XLenVT, /*IsTarget=*/true));
3036 ReplaceNode(Node, NewNode);
3037 return;
3038 }
3039
3040 // Find the smallest splat.
3041 if (Val.getBitWidth() > 16 && Val.isSplat(16))
3042 Val = Val.trunc(16);
3043 if (Val.getBitWidth() > 8 && Val.isSplat(8))
3044 Val = Val.trunc(8);
3045
3046 EltSize = Val.getBitWidth();
3047 int64_t Imm = Val.getSExtValue();
3048
3049 unsigned Opc = 0;
3050 if (EltSize == 8) {
3051 Opc = IsDoubleWide ? RISCV::PLI_DB : RISCV::PLI_B;
3052 } else if (EltSize == 16 && isInt<10>(Imm)) {
3053 Opc = IsDoubleWide ? RISCV::PLI_DH : RISCV::PLI_H;
3054 } else if (!IsDoubleWide && EltSize == 32 && isInt<10>(Imm)) {
3055 Opc = RISCV::PLI_W;
3056 } else if (EltSize == 16 && isShiftedInt<10, 6>(Imm)) {
3057 Opc = IsDoubleWide ? RISCV::PLUI_DH : RISCV::PLUI_H;
3058 Imm = Imm >> 6;
3059 } else if (!IsDoubleWide && EltSize == 32 && isShiftedInt<10, 22>(Imm)) {
3060 Opc = RISCV::PLUI_W;
3061 Imm = Imm >> 22;
3062 }
3063
3064 if (Opc) {
3065 SDNode *NewNode = CurDAG->getMachineNode(
3066 Opc, DL, VT, CurDAG->getSignedTargetConstant(Imm, DL, XLenVT));
3067 ReplaceNode(Node, NewNode);
3068 return;
3069 }
3070 }
3071
3072 break;
3073 }
3075 if (Subtarget->hasStdExtP()) {
3076 MVT SrcVT = Node->getOperand(0).getSimpleValueType();
3077 if ((VT == MVT::v2i32 && SrcVT == MVT::i64) ||
3078 (VT == MVT::v4i8 && SrcVT == MVT::i32)) {
3079 ReplaceUses(SDValue(Node, 0), Node->getOperand(0));
3080 CurDAG->RemoveDeadNode(Node);
3081 return;
3082 }
3083 }
3084 break;
3086 case RISCVISD::TUPLE_INSERT: {
3087 SDValue V = Node->getOperand(0);
3088 SDValue SubV = Node->getOperand(1);
3089 SDLoc DL(SubV);
3090 auto Idx = Node->getConstantOperandVal(2);
3091 MVT SubVecVT = SubV.getSimpleValueType();
3092
3093 const RISCVTargetLowering &TLI = *Subtarget->getTargetLowering();
3094 MVT SubVecContainerVT = SubVecVT;
3095 // Establish the correct scalable-vector types for any fixed-length type.
3096 if (SubVecVT.isFixedLengthVector()) {
3097 SubVecContainerVT = TLI.getContainerForFixedLengthVector(SubVecVT);
3099 [[maybe_unused]] bool ExactlyVecRegSized =
3100 Subtarget->expandVScale(SubVecVT.getSizeInBits())
3101 .isKnownMultipleOf(Subtarget->expandVScale(VecRegSize));
3102 assert(isPowerOf2_64(Subtarget->expandVScale(SubVecVT.getSizeInBits())
3103 .getKnownMinValue()));
3104 assert(Idx == 0 && (ExactlyVecRegSized || V.isUndef()));
3105 }
3106 MVT ContainerVT = VT;
3107 if (VT.isFixedLengthVector())
3108 ContainerVT = TLI.getContainerForFixedLengthVector(VT);
3109
3110 const auto *TRI = Subtarget->getRegisterInfo();
3111 unsigned SubRegIdx;
3112 std::tie(SubRegIdx, Idx) =
3114 ContainerVT, SubVecContainerVT, Idx, TRI);
3115
3116 // If the Idx hasn't been completely eliminated then this is a subvector
3117 // insert which doesn't naturally align to a vector register. These must
3118 // be handled using instructions to manipulate the vector registers.
3119 if (Idx != 0)
3120 break;
3121
3122 RISCVVType::VLMUL SubVecLMUL =
3123 RISCVTargetLowering::getLMUL(SubVecContainerVT);
3124 [[maybe_unused]] bool IsSubVecPartReg =
3125 SubVecLMUL == RISCVVType::VLMUL::LMUL_F2 ||
3126 SubVecLMUL == RISCVVType::VLMUL::LMUL_F4 ||
3127 SubVecLMUL == RISCVVType::VLMUL::LMUL_F8;
3128 assert((V.getValueType().isRISCVVectorTuple() || !IsSubVecPartReg ||
3129 V.isUndef()) &&
3130 "Expecting lowering to have created legal INSERT_SUBVECTORs when "
3131 "the subvector is smaller than a full-sized register");
3132
3133 // If we haven't set a SubRegIdx, then we must be going between
3134 // equally-sized LMUL groups (e.g. VR -> VR). This can be done as a copy.
3135 if (SubRegIdx == RISCV::NoSubRegister) {
3136 unsigned InRegClassID =
3139 InRegClassID &&
3140 "Unexpected subvector extraction");
3141 SDValue RC = CurDAG->getTargetConstant(InRegClassID, DL, XLenVT);
3142 SDNode *NewNode = CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
3143 DL, VT, SubV, RC);
3144 ReplaceNode(Node, NewNode);
3145 return;
3146 }
3147
3148 SDValue Insert = CurDAG->getTargetInsertSubreg(SubRegIdx, DL, VT, V, SubV);
3149 ReplaceNode(Node, Insert.getNode());
3150 return;
3151 }
3153 case RISCVISD::TUPLE_EXTRACT: {
3154 if (Subtarget->hasStdExtP())
3155 break;
3156
3157 SDValue V = Node->getOperand(0);
3158 auto Idx = Node->getConstantOperandVal(1);
3159 MVT InVT = V.getSimpleValueType();
3160
3161 SDLoc DL(V);
3162
3163 const RISCVTargetLowering &TLI = *Subtarget->getTargetLowering();
3164 MVT SubVecContainerVT = VT;
3165 // Establish the correct scalable-vector types for any fixed-length type.
3166 if (VT.isFixedLengthVector()) {
3167 assert(Idx == 0);
3168 SubVecContainerVT = TLI.getContainerForFixedLengthVector(VT);
3169 }
3170 if (InVT.isFixedLengthVector())
3171 InVT = TLI.getContainerForFixedLengthVector(InVT);
3172
3173 const auto *TRI = Subtarget->getRegisterInfo();
3174 unsigned SubRegIdx;
3175 std::tie(SubRegIdx, Idx) =
3177 InVT, SubVecContainerVT, Idx, TRI);
3178
3179 // If the Idx hasn't been completely eliminated then this is a subvector
3180 // extract which doesn't naturally align to a vector register. These must
3181 // be handled using instructions to manipulate the vector registers.
3182 if (Idx != 0)
3183 break;
3184
3185 // If we haven't set a SubRegIdx, then we must be going between
3186 // equally-sized LMUL types (e.g. VR -> VR). This can be done as a copy.
3187 if (SubRegIdx == RISCV::NoSubRegister) {
3188 unsigned InRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(InVT);
3190 InRegClassID &&
3191 "Unexpected subvector extraction");
3192 SDValue RC = CurDAG->getTargetConstant(InRegClassID, DL, XLenVT);
3193 SDNode *NewNode =
3194 CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS, DL, VT, V, RC);
3195 ReplaceNode(Node, NewNode);
3196 return;
3197 }
3198
3199 SDValue Extract = CurDAG->getTargetExtractSubreg(SubRegIdx, DL, VT, V);
3200 ReplaceNode(Node, Extract.getNode());
3201 return;
3202 }
3203 case RISCVISD::VMV_S_X_VL:
3204 case RISCVISD::VFMV_S_F_VL:
3205 case RISCVISD::VMV_V_X_VL:
3206 case RISCVISD::VFMV_V_F_VL: {
3207 // Try to match splat of a scalar load to a strided load with stride of x0.
3208 bool IsScalarMove = Node->getOpcode() == RISCVISD::VMV_S_X_VL ||
3209 Node->getOpcode() == RISCVISD::VFMV_S_F_VL;
3210 if (!Node->getOperand(0).isUndef())
3211 break;
3212 SDValue Src = Node->getOperand(1);
3213 auto *Ld = dyn_cast<LoadSDNode>(Src);
3214 // Can't fold load update node because the second
3215 // output is used so that load update node can't be removed.
3216 if (!Ld || Ld->isIndexed())
3217 break;
3218 EVT MemVT = Ld->getMemoryVT();
3219 // The memory VT should be the same size as the element type.
3220 if (MemVT.getStoreSize() != VT.getVectorElementType().getStoreSize())
3221 break;
3222 if (!IsProfitableToFold(Src, Node, Node) ||
3223 !IsLegalToFold(Src, Node, Node, TM.getOptLevel()))
3224 break;
3225
3226 SDValue VL;
3227 if (IsScalarMove) {
3228 // We could deal with more VL if we update the VSETVLI insert pass to
3229 // avoid introducing more VSETVLI.
3230 if (!isOneConstant(Node->getOperand(2)))
3231 break;
3232 selectVLOp(Node->getOperand(2), VL);
3233 } else
3234 selectVLOp(Node->getOperand(2), VL);
3235
3236 unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());
3237 SDValue SEW = CurDAG->getTargetConstant(Log2SEW, DL, XLenVT);
3238
3239 // If VL=1, then we don't need to do a strided load and can just do a
3240 // regular load.
3241 bool IsStrided = !isOneConstant(VL);
3242
3243 // Only do a strided load if we have optimized zero-stride vector load.
3244 if (IsStrided && !Subtarget->hasOptimizedZeroStrideLoad())
3245 break;
3246
3248 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, VT), 0),
3249 Ld->getBasePtr()};
3250 if (IsStrided)
3251 Operands.push_back(CurDAG->getRegister(RISCV::X0, XLenVT));
3253 SDValue PolicyOp = CurDAG->getTargetConstant(Policy, DL, XLenVT);
3254 Operands.append({VL, SEW, PolicyOp, Ld->getChain()});
3255
3257 const RISCV::VLEPseudo *P = RISCV::getVLEPseudo(
3258 /*IsMasked*/ false, IsStrided, /*FF*/ false,
3259 Log2SEW, static_cast<unsigned>(LMUL));
3261 CurDAG->getMachineNode(P->Pseudo, DL, {VT, MVT::Other}, Operands);
3262 // Update the chain.
3263 ReplaceUses(Src.getValue(1), SDValue(Load, 1));
3264 // Record the mem-refs
3265 CurDAG->setNodeMemRefs(Load, {Ld->getMemOperand()});
3266 // Replace the splat with the vlse.
3268 return;
3269 }
3270 case RISCVISD::LPAD_CALL:
3271 case RISCVISD::LPAD_CALL_INDIRECT: {
3272 bool IsIndirect = Opcode == RISCVISD::LPAD_CALL_INDIRECT;
3273 unsigned PseudoOpc = IsIndirect ? RISCV::PseudoCALLIndirectLpadAlign
3274 : RISCV::PseudoCALLLpadAlign;
3275
3276 uint32_t LpadLabel = 0;
3277 if (PreferredLandingPadLabel.getNumOccurrences() > 0) {
3279 report_fatal_error("riscv-landing-pad-label=<val>, <val> needs to fit "
3280 "in unsigned 20-bits");
3281 LpadLabel = PreferredLandingPadLabel;
3282 }
3283
3284 // Preserve the argument-register and register-mask operands, between
3285 // Callee and the optional glue, so the pseudo call still reports its
3286 // call-preserved mask to the register allocator.
3288 Ops.push_back(Node->getOperand(1));
3289 Ops.push_back(CurDAG->getTargetConstant(LpadLabel, DL, XLenVT));
3290
3291 unsigned NumOps = Node->getNumOperands();
3292 bool HasGlue = Node->getGluedNode() != nullptr;
3293 unsigned RegOperandsEnd = HasGlue ? NumOps - 1 : NumOps;
3294 for (unsigned I = 2; I != RegOperandsEnd; ++I)
3295 Ops.push_back(Node->getOperand(I));
3296
3297 Ops.push_back(Node->getOperand(0));
3298 if (HasGlue)
3299 Ops.push_back(Node->getOperand(NumOps - 1));
3300
3302 CurDAG->getMachineNode(PseudoOpc, DL, Node->getVTList(), Ops));
3303 return;
3304 }
3305 case ISD::PREFETCH:
3306 // MIPS's prefetch instruction already encodes the hint within the
3307 // instruction itself, so no extra NTL hint is needed.
3308 if (Subtarget->hasVendorXMIPSCBOP())
3309 break;
3310
3311 unsigned Locality = Node->getConstantOperandVal(3);
3312 if (Locality > 2)
3313 break;
3314
3315 auto *LoadStoreMem = cast<MemSDNode>(Node);
3316 MachineMemOperand *MMO = LoadStoreMem->getMemOperand();
3318
3319 int NontemporalLevel = 0;
3320 switch (Locality) {
3321 case 0:
3322 NontemporalLevel = 3; // NTL.ALL
3323 break;
3324 case 1:
3325 NontemporalLevel = 1; // NTL.PALL
3326 break;
3327 case 2:
3328 NontemporalLevel = 0; // NTL.P1
3329 break;
3330 default:
3331 llvm_unreachable("unexpected locality value.");
3332 }
3333
3334 if (NontemporalLevel & 0b1)
3336 if (NontemporalLevel & 0b10)
3338 break;
3339 }
3340
3341 // Select the default instruction.
3342 SelectCode(Node);
3343}
3344
3346 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
3347 std::vector<SDValue> &OutOps) {
3348 // Always produce a register and immediate operand, as expected by
3349 // RISCVAsmPrinter::PrintAsmMemoryOperand.
3350 switch (ConstraintID) {
3353 SDValue Op0, Op1;
3354 [[maybe_unused]] bool Found = SelectAddrRegImm(Op, Op0, Op1);
3355 assert(Found && "SelectAddrRegImm should always succeed");
3356 OutOps.push_back(Op0);
3357 OutOps.push_back(Op1);
3358 return false;
3359 }
3361 OutOps.push_back(Op);
3362 OutOps.push_back(
3363 CurDAG->getTargetConstant(0, SDLoc(Op), Subtarget->getXLenVT()));
3364 return false;
3365 default:
3366 report_fatal_error("Unexpected asm memory constraint " +
3367 InlineAsm::getMemConstraintName(ConstraintID));
3368 }
3369
3370 return true;
3371}
3372
3374 SDValue &Offset) {
3375 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
3376 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT());
3377 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Subtarget->getXLenVT());
3378 return true;
3379 }
3380
3381 return false;
3382}
3383
3384// Fold constant addresses.
3385static bool selectConstantAddr(SelectionDAG *CurDAG, const SDLoc &DL,
3386 const MVT VT, const RISCVSubtarget *Subtarget,
3388 bool IsPrefetch = false) {
3389 if (!isa<ConstantSDNode>(Addr))
3390 return false;
3391
3392 int64_t CVal = cast<ConstantSDNode>(Addr)->getSExtValue();
3393
3394 // If the constant is a simm12, we can fold the whole constant and use X0 as
3395 // the base. If the constant can be materialized with LUI+simm12, use LUI as
3396 // the base. We can't use generateInstSeq because it favors LUI+ADDIW.
3397 int64_t Lo12 = SignExtend64<12>(CVal);
3398 int64_t Hi = (uint64_t)CVal - (uint64_t)Lo12;
3399 if (!Subtarget->is64Bit() || isInt<32>(Hi)) {
3400 if (IsPrefetch && (Lo12 & 0b11111) != 0)
3401 return false;
3402 if (Hi) {
3403 int64_t Hi20 = (Hi >> 12) & 0xfffff;
3404 Base = SDValue(
3405 CurDAG->getMachineNode(RISCV::LUI, DL, VT,
3406 CurDAG->getTargetConstant(Hi20, DL, VT)),
3407 0);
3408 } else {
3409 Base = CurDAG->getRegister(RISCV::X0, VT);
3410 }
3411 Offset = CurDAG->getSignedTargetConstant(Lo12, DL, VT);
3412 return true;
3413 }
3414
3415 // Ask how constant materialization would handle this constant.
3416 RISCVMatInt::InstSeq Seq = RISCVMatInt::generateInstSeq(CVal, *Subtarget);
3417
3418 // If the last instruction would be an ADDI, we can fold its immediate and
3419 // emit the rest of the sequence as the base.
3420 if (Seq.back().getOpcode() != RISCV::ADDI)
3421 return false;
3422 Lo12 = Seq.back().getImm();
3423 if (IsPrefetch && (Lo12 & 0b11111) != 0)
3424 return false;
3425
3426 // Drop the last instruction.
3427 Seq.pop_back();
3428 assert(!Seq.empty() && "Expected more instructions in sequence");
3429
3430 Base = selectImmSeq(CurDAG, DL, VT, Seq);
3431 Offset = CurDAG->getSignedTargetConstant(Lo12, DL, VT);
3432 return true;
3433}
3434
3435// Is this ADD instruction only used as the base pointer of scalar loads and
3436// stores?
3438 for (auto *User : Add->users()) {
3439 if (User->getOpcode() != ISD::LOAD && User->getOpcode() != ISD::STORE &&
3440 User->getOpcode() != RISCVISD::LD_RV32 &&
3441 User->getOpcode() != RISCVISD::SD_RV32 &&
3442 User->getOpcode() != ISD::ATOMIC_LOAD &&
3443 User->getOpcode() != ISD::ATOMIC_STORE)
3444 return false;
3445 EVT VT = cast<MemSDNode>(User)->getMemoryVT();
3446 if (!VT.isScalarInteger() && VT != MVT::f16 && VT != MVT::f32 &&
3447 VT != MVT::f64)
3448 return false;
3449 // Don't allow stores of the value. It must be used as the address.
3450 if (User->getOpcode() == ISD::STORE &&
3451 cast<StoreSDNode>(User)->getValue() == Add)
3452 return false;
3453 if (User->getOpcode() == ISD::ATOMIC_STORE &&
3454 cast<AtomicSDNode>(User)->getVal() == Add)
3455 return false;
3456 if (User->getOpcode() == RISCVISD::SD_RV32 &&
3457 (User->getOperand(0) == Add || User->getOperand(1) == Add))
3458 return false;
3459 if (isStrongerThanMonotonic(cast<MemSDNode>(User)->getSuccessOrdering()))
3460 return false;
3461 }
3462
3463 return true;
3464}
3465
3467 switch (User->getOpcode()) {
3468 default:
3469 return false;
3470 case ISD::LOAD:
3471 case RISCVISD::LD_RV32:
3472 case ISD::ATOMIC_LOAD:
3473 break;
3474 case ISD::STORE:
3475 // Don't allow stores of Add. It must only be used as the address.
3477 return false;
3478 break;
3479 case RISCVISD::SD_RV32:
3480 // Don't allow stores of Add. It must only be used as the address.
3481 if (User->getOperand(0) == Add || User->getOperand(1) == Add)
3482 return false;
3483 break;
3484 case ISD::ATOMIC_STORE:
3485 // Don't allow stores of Add. It must only be used as the address.
3486 if (cast<AtomicSDNode>(User)->getVal() == Add)
3487 return false;
3488 break;
3489 }
3490
3491 return true;
3492}
3493
3494// To prevent SelectAddrRegImm from folding offsets that conflict with the
3495// fusion of PseudoMovAddr, check if the offset of every use of a given address
3496// is within the alignment.
3498 Align Alignment) {
3499 assert(Addr->getOpcode() == RISCVISD::ADD_LO);
3500 for (auto *User : Addr->users()) {
3501 // If the user is a load or store, then the offset is 0 which is always
3502 // within alignment.
3503 if (isRegImmLoadOrStore(User, Addr))
3504 continue;
3505
3506 if (CurDAG->isBaseWithConstantOffset(SDValue(User, 0))) {
3507 int64_t CVal = cast<ConstantSDNode>(User->getOperand(1))->getSExtValue();
3508 if (!isInt<12>(CVal) || Alignment <= CVal)
3509 return false;
3510
3511 // Make sure all uses are foldable load/stores.
3512 for (auto *AddUser : User->users())
3513 if (!isRegImmLoadOrStore(AddUser, SDValue(User, 0)))
3514 return false;
3515
3516 continue;
3517 }
3518
3519 return false;
3520 }
3521
3522 return true;
3523}
3524
3526 SDValue &Offset) {
3527 if (SelectAddrFrameIndex(Addr, Base, Offset))
3528 return true;
3529
3530 SDLoc DL(Addr);
3531 MVT VT = Addr.getSimpleValueType();
3532
3533 if (Addr.getOpcode() == RISCVISD::ADD_LO) {
3534 bool CanFold = true;
3535 // Unconditionally fold if operand 1 is not a global address (e.g.
3536 // externsymbol)
3537 if (auto *GA = dyn_cast<GlobalAddressSDNode>(Addr.getOperand(1))) {
3538 const DataLayout &DL = CurDAG->getDataLayout();
3539 Align Alignment = commonAlignment(
3540 GA->getGlobal()->getPointerAlignment(DL), GA->getOffset());
3541 if (!areOffsetsWithinAlignment(Addr, Alignment))
3542 CanFold = false;
3543 }
3544 if (CanFold) {
3545 Base = Addr.getOperand(0);
3546 Offset = Addr.getOperand(1);
3547 return true;
3548 }
3549 }
3550
3551 if (CurDAG->isBaseWithConstantOffset(Addr)) {
3552 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3553 if (isInt<12>(CVal)) {
3554 Base = Addr.getOperand(0);
3555 if (Base.getOpcode() == RISCVISD::ADD_LO) {
3556 SDValue LoOperand = Base.getOperand(1);
3557 if (auto *GA = dyn_cast<GlobalAddressSDNode>(LoOperand)) {
3558 // If the Lo in (ADD_LO hi, lo) is a global variable's address
3559 // (its low part, really), then we can rely on the alignment of that
3560 // variable to provide a margin of safety before low part can overflow
3561 // the 12 bits of the load/store offset. Check if CVal falls within
3562 // that margin; if so (low part + CVal) can't overflow.
3563 const DataLayout &DL = CurDAG->getDataLayout();
3564 Align Alignment = commonAlignment(
3565 GA->getGlobal()->getPointerAlignment(DL), GA->getOffset());
3566 if ((CVal == 0 || Alignment > CVal) &&
3567 areOffsetsWithinAlignment(Base, Alignment)) {
3568 int64_t CombinedOffset = CVal + GA->getOffset();
3569 Base = Base.getOperand(0);
3570 Offset = CurDAG->getTargetGlobalAddress(
3571 GA->getGlobal(), SDLoc(LoOperand), LoOperand.getValueType(),
3572 CombinedOffset, GA->getTargetFlags());
3573 return true;
3574 }
3575 }
3576 }
3577
3578 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Base))
3579 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), VT);
3580 Offset = CurDAG->getSignedTargetConstant(CVal, DL, VT);
3581 return true;
3582 }
3583 }
3584
3585 // Handle ADD with large immediates.
3586 if (Addr.getOpcode() == ISD::ADD && isa<ConstantSDNode>(Addr.getOperand(1))) {
3587 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3588 assert(!isInt<12>(CVal) && "simm12 not already handled?");
3589
3590 // Handle immediates in the range [-4096,-2049] or [2048, 4094]. We can use
3591 // an ADDI for part of the offset and fold the rest into the load/store.
3592 // This mirrors the AddiPair PatFrag in RISCVInstrInfo.td.
3593 if (CVal >= -4096 && CVal <= 4094) {
3594 int64_t Adj = CVal < 0 ? -2048 : 2047;
3595 Base = SDValue(
3596 CurDAG->getMachineNode(RISCV::ADDI, DL, VT, Addr.getOperand(0),
3597 CurDAG->getSignedTargetConstant(Adj, DL, VT)),
3598 0);
3599 Offset = CurDAG->getSignedTargetConstant(CVal - Adj, DL, VT);
3600 return true;
3601 }
3602
3603 // For larger immediates, we might be able to save one instruction from
3604 // constant materialization by folding the Lo12 bits of the immediate into
3605 // the address. We should only do this if the ADD is only used by loads and
3606 // stores that can fold the lo12 bits. Otherwise, the ADD will get iseled
3607 // separately with the full materialized immediate creating extra
3608 // instructions.
3609 if (isWorthFoldingAdd(Addr) &&
3610 selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr.getOperand(1), Base,
3611 Offset, /*IsPrefetch=*/false)) {
3612 // Insert an ADD instruction with the materialized Hi52 bits.
3613 Base = SDValue(
3614 CurDAG->getMachineNode(RISCV::ADD, DL, VT, Addr.getOperand(0), Base),
3615 0);
3616 return true;
3617 }
3618 }
3619
3620 if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset,
3621 /*IsPrefetch=*/false))
3622 return true;
3623
3624 Base = Addr;
3625 Offset = CurDAG->getTargetConstant(0, DL, VT);
3626 return true;
3627}
3628
3629/// Similar to SelectAddrRegImm, except that the offset is a 26-bit signed
3630/// immediate. This is used by the Qualcomm Xqcilo large offset load/store
3631/// instructions (qc.e.lw/qc.e.sw), whose offset field is 26 bits wide.
3632/// Only matches offsets that do not fit a 12-bit signed immediate, so that
3633/// offsets in the simm12 range keep using the shorter (and possibly
3634/// compressible) standard load/store instructions.
3636 SDValue &Offset) {
3637 SDLoc DL(Addr);
3638 MVT VT = Addr.getSimpleValueType();
3639
3640 if (CurDAG->isBaseWithConstantOffset(Addr)) {
3641 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3642 // Fold a 26-bit (but not 12-bit) signed offset directly into the
3643 // load/store.
3644 if (isInt<26>(CVal) && !isInt<12>(CVal)) {
3645 Base = Addr.getOperand(0);
3646 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Base))
3647 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), VT);
3648 Offset = CurDAG->getSignedTargetConstant(CVal, DL, VT);
3649 return true;
3650 }
3651 }
3652
3653 // The offset is just outside the 26-bit range. Split off a small (simm12)
3654 // adjustment with a plain ADDI and fold the remaining 26-bit offset into the
3655 // load/store. A plain ADDI is used (rather than the wide
3656 // qc.e.addi/qc.e.addai) because the adjustment fits simm12: this keeps it a
3657 // short, compressible (c.addi) instruction and is available without Xqcilia.
3658 //
3659 // Skip the split if the address is used other than as a foldable load/store
3660 // base. `isWorthFoldingAdd()` returns true when every user of the add node is
3661 // a scalar load/store using it as an address operand. If it return false, it
3662 // means that some use consumes the add result as a value (e.g. it feeds
3663 // another add, is a stored value, is used in arithmetic) and that use forces
3664 // the add to be materialized into a register.
3665 if (Addr.getOpcode() == ISD::ADD && isa<ConstantSDNode>(Addr.getOperand(1)) &&
3666 isWorthFoldingAdd(Addr)) {
3667 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3668 if (!isInt<26>(CVal)) {
3669 // check if lw in lui + add + lw combination can be compressed.
3670 // The check here purely based on the immediate value and hopes that
3671 // register allocator would assign a register from a GPRC set so that the
3672 // instruction can get compressed.
3673 bool IsLwCompressable = isShiftedUInt<5, 2>(CVal & ((1 << 12) - 1));
3674
3675 int64_t Imm26 = CVal < 0 ? minIntN(26) : maxIntN(26);
3676 int64_t Adj = CVal - Imm26;
3677 // If Adj fits within 6-bits, then both combinations will take 8 bytes
3678 // however c.addi + qc.e.lw/sw will take 1 less cycle. Also, if lw is not
3679 // compressable then both combination would take 10 bytes but again
3680 // addi + qc.e.lw/sw will take 1 less cycle.
3681 if (isInt<6>(Adj) || (isInt<12>(Adj) && !IsLwCompressable)) {
3682 Base = SDValue(CurDAG->getMachineNode(
3683 RISCV::ADDI, DL, VT, Addr.getOperand(0),
3684 CurDAG->getSignedTargetConstant(Adj, DL, VT)),
3685 0);
3686 Offset = CurDAG->getSignedTargetConstant(Imm26, DL, VT);
3687 return true;
3688 }
3689 }
3690 }
3691
3692 // Don't match: let the standard addressing modes handle it.
3693 return false;
3694}
3695
3696/// Similar to SelectAddrRegImm, except that the offset is restricted to uimm9.
3698 SDValue &Offset) {
3699 if (SelectAddrFrameIndex(Addr, Base, Offset))
3700 return true;
3701
3702 SDLoc DL(Addr);
3703 MVT VT = Addr.getSimpleValueType();
3704
3705 if (CurDAG->isBaseWithConstantOffset(Addr)) {
3706 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3707 if (isUInt<9>(CVal)) {
3708 Base = Addr.getOperand(0);
3709
3710 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Base))
3711 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), VT);
3712 Offset = CurDAG->getSignedTargetConstant(CVal, DL, VT);
3713 return true;
3714 }
3715 }
3716
3717 Base = Addr;
3718 Offset = CurDAG->getTargetConstant(0, DL, VT);
3719 return true;
3720}
3721
3722/// Similar to SelectAddrRegImm, except that the least significant 5 bits of
3723/// Offset should be all zeros.
3725 SDValue &Offset) {
3726 if (SelectAddrFrameIndex(Addr, Base, Offset))
3727 return true;
3728
3729 SDLoc DL(Addr);
3730 MVT VT = Addr.getSimpleValueType();
3731
3732 if (CurDAG->isBaseWithConstantOffset(Addr)) {
3733 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3734 if (isInt<12>(CVal)) {
3735 Base = Addr.getOperand(0);
3736
3737 // Early-out if not a valid offset.
3738 if ((CVal & 0b11111) != 0) {
3739 Base = Addr;
3740 Offset = CurDAG->getTargetConstant(0, DL, VT);
3741 return true;
3742 }
3743
3744 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Base))
3745 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), VT);
3746 Offset = CurDAG->getSignedTargetConstant(CVal, DL, VT);
3747 return true;
3748 }
3749 }
3750
3751 // Handle ADD with large immediates.
3752 if (Addr.getOpcode() == ISD::ADD && isa<ConstantSDNode>(Addr.getOperand(1))) {
3753 int64_t CVal = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
3754 assert(!isInt<12>(CVal) && "simm12 not already handled?");
3755
3756 // Handle immediates in the range [-4096,-2049] or [2017, 4063]. We can save
3757 // one instruction by folding adjustment (-2048 or 2016) into the address.
3758 // The upper bound keeps CVal - 2016 within simm12 ([−2048, 2047]).
3759 if ((-2049 >= CVal && CVal >= -4096) || (4063 >= CVal && CVal >= 2017)) {
3760 int64_t Adj = CVal < 0 ? -2048 : 2016;
3761 int64_t AdjustedOffset = CVal - Adj;
3762 Base =
3763 SDValue(CurDAG->getMachineNode(
3764 RISCV::ADDI, DL, VT, Addr.getOperand(0),
3765 CurDAG->getSignedTargetConstant(AdjustedOffset, DL, VT)),
3766 0);
3767 Offset = CurDAG->getSignedTargetConstant(Adj, DL, VT);
3768 return true;
3769 }
3770
3771 if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr.getOperand(1), Base,
3772 Offset, /*IsPrefetch=*/true)) {
3773 // Insert an ADD instruction with the materialized Hi52 bits.
3774 Base = SDValue(
3775 CurDAG->getMachineNode(RISCV::ADD, DL, VT, Addr.getOperand(0), Base),
3776 0);
3777 return true;
3778 }
3779 }
3780
3781 if (selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr, Base, Offset,
3782 /*IsPrefetch=*/true))
3783 return true;
3784
3785 Base = Addr;
3786 Offset = CurDAG->getTargetConstant(0, DL, VT);
3787 return true;
3788}
3789
3790/// Return true if this a load/store that we have a RegRegScale instruction for.
3792 const RISCVSubtarget &Subtarget) {
3793 unsigned UserOpc = User->getOpcode();
3794 if (UserOpc != ISD::LOAD && UserOpc != ISD::STORE)
3795 return false;
3796 EVT VT = cast<MemSDNode>(User)->getMemoryVT();
3797 // Zilx only provides indexed loads, so it must not enable reg+reg-scale
3798 // address folding for stores. XTheadMemIdx and Xqcisls have scaled stores.
3799 bool HasScalarIntegerMemIdx =
3800 Subtarget.hasVendorXTHeadMemIdx() || Subtarget.hasVendorXqcisls() ||
3801 (Subtarget.hasStdExtZilx() && UserOpc == ISD::LOAD);
3802 if (!(VT.isScalarInteger() && HasScalarIntegerMemIdx) &&
3803 !((VT == MVT::f32 || VT == MVT::f64) &&
3804 Subtarget.hasVendorXTHeadFMemIdx()))
3805 return false;
3806 // Don't allow stores of the value. It must be used as the address.
3807 if (UserOpc == ISD::STORE && cast<StoreSDNode>(User)->getValue() == Add)
3808 return false;
3809
3810 return true;
3811}
3812
3813/// Is it profitable to fold this Add into RegRegScale load/store. If \p
3814/// Shift is non-null, then we have matched a shl+add. We allow reassociating
3815/// (add (add (shl A C2) B) C1) -> (add (add B C1) (shl A C2)) if there is a
3816/// single addi and we don't have a SHXADD instruction we could use.
3817/// FIXME: May still need to check how many and what kind of users the SHL has.
3819 SDValue Add,
3820 SDValue Shift = SDValue()) {
3821 bool FoundADDI = false;
3822 for (auto *User : Add->users()) {
3823 if (isRegRegScaleLoadOrStore(User, Add, Subtarget))
3824 continue;
3825
3826 // Allow a single ADDI that is used by loads/stores if we matched a shift.
3827 if (!Shift || FoundADDI || User->getOpcode() != ISD::ADD ||
3829 !isInt<12>(cast<ConstantSDNode>(User->getOperand(1))->getSExtValue()))
3830 return false;
3831
3832 FoundADDI = true;
3833
3834 // If we have a SHXADD instruction, prefer that over reassociating an ADDI.
3835 assert(Shift.getOpcode() == ISD::SHL);
3836 unsigned ShiftAmt = Shift.getConstantOperandVal(1);
3837 if (Subtarget.hasShlAdd(ShiftAmt))
3838 return false;
3839
3840 // All users of the ADDI should be load/store.
3841 for (auto *ADDIUser : User->users())
3842 if (!isRegRegScaleLoadOrStore(ADDIUser, SDValue(User, 0), Subtarget))
3843 return false;
3844 }
3845
3846 return true;
3847}
3848
3850 ArrayRef<unsigned> Amounts,
3851 SDValue &Base, SDValue &Index,
3852 SDValue &Scale) {
3853 if (Addr.getOpcode() != ISD::ADD)
3854 return false;
3855 SDValue LHS = Addr.getOperand(0);
3856 SDValue RHS = Addr.getOperand(1);
3857
3858 EVT VT = Addr.getSimpleValueType();
3859 auto SelectShl = [this, VT, Amounts](SDValue N, SDValue &Index,
3860 SDValue &Shift) {
3861 if (N.getOpcode() != ISD::SHL || !isa<ConstantSDNode>(N.getOperand(1)))
3862 return false;
3863
3864 // Only match shifts by a value in range [0, MaxShiftAmount].
3865 unsigned ShiftAmt = N.getConstantOperandVal(1);
3866 if (!llvm::is_contained(Amounts, ShiftAmt))
3867 return false;
3868
3869 Index = N.getOperand(0);
3870 Shift = CurDAG->getTargetConstant(ShiftAmt, SDLoc(N), VT);
3871 return true;
3872 };
3873
3874 if (auto *C1 = dyn_cast<ConstantSDNode>(RHS)) {
3875 // (add (add (shl A C2) B) C1) -> (add (add B C1) (shl A C2))
3876 if (LHS.getOpcode() == ISD::ADD &&
3877 !isa<ConstantSDNode>(LHS.getOperand(1)) &&
3878 isInt<12>(C1->getSExtValue())) {
3879 if (SelectShl(LHS.getOperand(1), Index, Scale) &&
3880 isWorthFoldingIntoRegRegScale(*Subtarget, LHS, LHS.getOperand(1))) {
3881 SDValue C1Val = CurDAG->getTargetConstant(*C1->getConstantIntValue(),
3882 SDLoc(Addr), VT);
3883 Base = SDValue(CurDAG->getMachineNode(RISCV::ADDI, SDLoc(Addr), VT,
3884 LHS.getOperand(0), C1Val),
3885 0);
3886 return true;
3887 }
3888
3889 // Add is commutative so we need to check both operands.
3890 if (SelectShl(LHS.getOperand(0), Index, Scale) &&
3891 isWorthFoldingIntoRegRegScale(*Subtarget, LHS, LHS.getOperand(0))) {
3892 SDValue C1Val = CurDAG->getTargetConstant(*C1->getConstantIntValue(),
3893 SDLoc(Addr), VT);
3894 Base = SDValue(CurDAG->getMachineNode(RISCV::ADDI, SDLoc(Addr), VT,
3895 LHS.getOperand(1), C1Val),
3896 0);
3897 return true;
3898 }
3899 }
3900
3901 // Don't match add with constants.
3902 // FIXME: Is this profitable for large constants that have 0s in the lower
3903 // 12 bits that we can materialize with LUI?
3904 return false;
3905 }
3906
3907 // Try to match a shift on the RHS.
3908 if (SelectShl(RHS, Index, Scale)) {
3909 if (!isWorthFoldingIntoRegRegScale(*Subtarget, Addr, RHS))
3910 return false;
3911 Base = LHS;
3912 return true;
3913 }
3914
3915 // Try to match a shift on the LHS.
3916 if (SelectShl(LHS, Index, Scale)) {
3917 if (!isWorthFoldingIntoRegRegScale(*Subtarget, Addr, LHS))
3918 return false;
3919 Base = RHS;
3920 return true;
3921 }
3922
3923 if (!isWorthFoldingIntoRegRegScale(*Subtarget, Addr))
3924 return false;
3925
3926 // Bail out if 0 is not in candidate shift amounts.
3927 if (!llvm::is_contained(Amounts, 0))
3928 return false;
3929
3930 Base = LHS;
3931 Index = RHS;
3932 Scale = CurDAG->getTargetConstant(0, SDLoc(Addr), VT);
3933 return true;
3934}
3935
3937 ArrayRef<unsigned> Amounts,
3938 unsigned Bits, SDValue &Base,
3939 SDValue &Index,
3940 SDValue &Scale) {
3941 if (!SelectAddrRegRegScale(Addr, Amounts, Base, Index, Scale))
3942 return false;
3943
3944 if (Index.getOpcode() == ISD::AND) {
3945 auto *C = dyn_cast<ConstantSDNode>(Index.getOperand(1));
3946 if (C && C->getZExtValue() == maskTrailingOnes<uint64_t>(Bits)) {
3947 Index = Index.getOperand(0);
3948 return true;
3949 }
3950 }
3951
3952 return false;
3953}
3954
3956 SDValue &Offset) {
3957 if (Addr.getOpcode() != ISD::ADD)
3958 return false;
3959
3960 if (isa<ConstantSDNode>(Addr.getOperand(1)))
3961 return false;
3962
3963 Base = Addr.getOperand(0);
3964 Offset = Addr.getOperand(1);
3965 return true;
3966}
3967
3969 SDValue &ShAmt) {
3970 ShAmt = N;
3971
3972 // Peek through zext.
3973 if (ShAmt->getOpcode() == ISD::ZERO_EXTEND)
3974 ShAmt = ShAmt.getOperand(0);
3975
3976 // Shift instructions on RISC-V only read the lower 5 or 6 bits of the shift
3977 // amount. If there is an AND on the shift amount, we can bypass it if it
3978 // doesn't affect any of those bits.
3979 if (ShAmt.getOpcode() == ISD::AND &&
3980 isa<ConstantSDNode>(ShAmt.getOperand(1))) {
3981 const APInt &AndMask = ShAmt.getConstantOperandAPInt(1);
3982
3983 // Since the max shift amount is a power of 2 we can subtract 1 to make a
3984 // mask that covers the bits needed to represent all shift amounts.
3985 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
3986 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
3987
3988 if (ShMask.isSubsetOf(AndMask)) {
3989 ShAmt = ShAmt.getOperand(0);
3990 } else {
3991 // SimplifyDemandedBits may have optimized the mask so try restoring any
3992 // bits that are known zero.
3993 KnownBits Known = CurDAG->computeKnownBits(ShAmt.getOperand(0));
3994 if (!ShMask.isSubsetOf(AndMask | Known.Zero))
3995 return true;
3996 ShAmt = ShAmt.getOperand(0);
3997 }
3998 }
3999
4000 if (ShAmt.getOpcode() == ISD::ADD &&
4001 isa<ConstantSDNode>(ShAmt.getOperand(1))) {
4002 uint64_t Imm = ShAmt.getConstantOperandVal(1);
4003 // If we are shifting by X+N where N == 0 mod Size, then just shift by X
4004 // to avoid the ADD.
4005 if (Imm != 0 && Imm % ShiftWidth == 0) {
4006 ShAmt = ShAmt.getOperand(0);
4007 return true;
4008 }
4009 } else if (ShAmt.getOpcode() == ISD::SUB &&
4010 isa<ConstantSDNode>(ShAmt.getOperand(0))) {
4011 uint64_t Imm = ShAmt.getConstantOperandVal(0);
4012 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to
4013 // generate a NEG instead of a SUB of a constant.
4014 if (Imm != 0 && Imm % ShiftWidth == 0) {
4015 SDLoc DL(ShAmt);
4016 EVT VT = ShAmt.getValueType();
4017 SDValue Zero = CurDAG->getRegister(RISCV::X0, VT);
4018 unsigned NegOpc = VT == MVT::i64 ? RISCV::SUBW : RISCV::SUB;
4019 MachineSDNode *Neg = CurDAG->getMachineNode(NegOpc, DL, VT, Zero,
4020 ShAmt.getOperand(1));
4021 ShAmt = SDValue(Neg, 0);
4022 return true;
4023 }
4024 // If we are shifting by N-X where N == -1 mod Size, then just shift by ~X
4025 // to generate a NOT instead of a SUB of a constant.
4026 if (Imm % ShiftWidth == ShiftWidth - 1) {
4027 SDLoc DL(ShAmt);
4028 EVT VT = ShAmt.getValueType();
4029 MachineSDNode *Not = CurDAG->getMachineNode(
4030 RISCV::XORI, DL, VT, ShAmt.getOperand(1),
4031 CurDAG->getAllOnesConstant(DL, VT, /*isTarget=*/true));
4032 ShAmt = SDValue(Not, 0);
4033 return true;
4034 }
4035 }
4036
4037 return true;
4038}
4039
4040/// RISC-V doesn't have general instructions for integer setne/seteq, but we can
4041/// check for equality with 0. This function emits instructions that convert the
4042/// seteq/setne into something that can be compared with 0.
4043/// \p ExpectedCCVal indicates the condition code to attempt to match (e.g.
4044/// ISD::SETNE).
4046 SDValue &Val, bool OneUse) {
4047 assert(ISD::isIntEqualitySetCC(ExpectedCCVal) &&
4048 "Unexpected condition code!");
4049
4050 // We're looking for a setcc.
4051 if (N->getOpcode() != ISD::SETCC)
4052 return false;
4053
4054 if (OneUse && !N->hasOneUse())
4055 return false;
4056
4057 // Must be an equality comparison.
4058 ISD::CondCode CCVal = cast<CondCodeSDNode>(N->getOperand(2))->get();
4059 if (CCVal != ExpectedCCVal)
4060 return false;
4061
4062 SDValue LHS = N->getOperand(0);
4063 SDValue RHS = N->getOperand(1);
4064
4065 if (!LHS.getValueType().isScalarInteger())
4066 return false;
4067
4068 // If the RHS side is 0, we don't need any extra instructions, return the LHS.
4069 if (isNullConstant(RHS)) {
4070 Val = LHS;
4071 return true;
4072 }
4073
4074 SDLoc DL(N);
4075
4076 if (auto *C = dyn_cast<ConstantSDNode>(RHS)) {
4077 int64_t CVal = C->getSExtValue();
4078 // If the RHS is -2048, we can use xori to produce 0 if the LHS is -2048 and
4079 // non-zero otherwise.
4080 if (CVal == -2048) {
4081 Val = SDValue(
4082 CurDAG->getMachineNode(
4083 RISCV::XORI, DL, N->getValueType(0), LHS,
4084 CurDAG->getSignedTargetConstant(CVal, DL, N->getValueType(0))),
4085 0);
4086 return true;
4087 }
4088 // If the RHS is [-2047,2048], we can use addi/addiw with -RHS to produce 0
4089 // if the LHS is equal to the RHS and non-zero otherwise.
4090 if (isInt<12>(CVal) || CVal == 2048) {
4091 unsigned Opc = RISCV::ADDI;
4092 if (LHS.getOpcode() == ISD::SIGN_EXTEND_INREG &&
4093 cast<VTSDNode>(LHS.getOperand(1))->getVT() == MVT::i32) {
4094 Opc = RISCV::ADDIW;
4095 LHS = LHS.getOperand(0);
4096 }
4097
4098 Val = SDValue(CurDAG->getMachineNode(Opc, DL, N->getValueType(0), LHS,
4099 CurDAG->getSignedTargetConstant(
4100 -CVal, DL, N->getValueType(0))),
4101 0);
4102 return true;
4103 }
4104 if (isPowerOf2_64(CVal) && Subtarget->hasStdExtZbs()) {
4105 Val = SDValue(
4106 CurDAG->getMachineNode(
4107 RISCV::BINVI, DL, N->getValueType(0), LHS,
4108 CurDAG->getTargetConstant(Log2_64(CVal), DL, N->getValueType(0))),
4109 0);
4110 return true;
4111 }
4112 // Same as the addi case above but for larger immediates (signed 26-bit) use
4113 // the QC_E_ADDI instruction from the Xqcilia extension, if available. Avoid
4114 // anything which can be done with a single lui as it might be compressible.
4115 if (Subtarget->hasVendorXqcilia() && isInt<26>(CVal) &&
4116 (CVal & 0xFFF) != 0) {
4117 Val = SDValue(
4118 CurDAG->getMachineNode(
4119 RISCV::QC_E_ADDI, DL, N->getValueType(0), LHS,
4120 CurDAG->getSignedTargetConstant(-CVal, DL, N->getValueType(0))),
4121 0);
4122 return true;
4123 }
4124 }
4125
4126 // If nothing else we can XOR the LHS and RHS to produce zero if they are
4127 // equal and a non-zero value if they aren't.
4128 Val = SDValue(
4129 CurDAG->getMachineNode(RISCV::XOR, DL, N->getValueType(0), LHS, RHS), 0);
4130 return true;
4131}
4132
4134 if (N.getOpcode() == ISD::SIGN_EXTEND_INREG &&
4135 cast<VTSDNode>(N.getOperand(1))->getVT().getSizeInBits() == Bits) {
4136 Val = N.getOperand(0);
4137 return true;
4138 }
4139
4140 auto UnwrapShlSra = [](SDValue N, unsigned ShiftAmt) {
4141 if (N.getOpcode() != ISD::SRA || !isa<ConstantSDNode>(N.getOperand(1)))
4142 return N;
4143
4144 SDValue N0 = N.getOperand(0);
4145 if (N0.getOpcode() == ISD::SHL && isa<ConstantSDNode>(N0.getOperand(1)) &&
4146 N.getConstantOperandVal(1) == ShiftAmt &&
4147 N0.getConstantOperandVal(1) == ShiftAmt)
4148 return N0.getOperand(0);
4149
4150 return N;
4151 };
4152
4153 MVT VT = N.getSimpleValueType();
4154 if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - Bits)) {
4155 Val = UnwrapShlSra(N, VT.getSizeInBits() - Bits);
4156 return true;
4157 }
4158
4159 return false;
4160}
4161
4163 if (N.getOpcode() == ISD::AND) {
4164 auto *C = dyn_cast<ConstantSDNode>(N.getOperand(1));
4165 if (C && C->getZExtValue() == maskTrailingOnes<uint64_t>(Bits)) {
4166 Val = N.getOperand(0);
4167 return true;
4168 }
4169 }
4170 MVT VT = N.getSimpleValueType();
4171 APInt Mask = APInt::getBitsSetFrom(VT.getSizeInBits(), Bits);
4172 if (CurDAG->MaskedValueIsZero(N, Mask)) {
4173 Val = N;
4174 return true;
4175 }
4176
4177 return false;
4178}
4179
4180/// Look for various patterns that can be done with a SHL that can be folded
4181/// into a SHXADD. \p ShAmt contains 1, 2, or 3 and is set based on which
4182/// SHXADD we are trying to match.
4184 SDValue &Val) {
4185 if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1))) {
4186 SDValue N0 = N.getOperand(0);
4187
4188 if (bool LeftShift = N0.getOpcode() == ISD::SHL;
4189 (LeftShift || N0.getOpcode() == ISD::SRL) &&
4191 uint64_t Mask = N.getConstantOperandVal(1);
4192 unsigned C2 = N0.getConstantOperandVal(1);
4193
4194 unsigned XLen = Subtarget->getXLen();
4195 if (LeftShift)
4196 Mask &= maskTrailingZeros<uint64_t>(C2);
4197 else
4198 Mask &= maskTrailingOnes<uint64_t>(XLen - C2);
4199
4200 if (isShiftedMask_64(Mask)) {
4201 unsigned Leading = XLen - llvm::bit_width(Mask);
4202 unsigned Trailing = llvm::countr_zero(Mask);
4203 if (Trailing != ShAmt)
4204 return false;
4205
4206 unsigned Opcode;
4207 // Look for (and (shl y, c2), c1) where c1 is a shifted mask with no
4208 // leading zeros and c3 trailing zeros. We can use an SRLI by c3-c2
4209 // followed by a SHXADD with c3 for the X amount.
4210 if (LeftShift && Leading == 0 && C2 < Trailing)
4211 Opcode = RISCV::SRLI;
4212 // Look for (and (shl y, c2), c1) where c1 is a shifted mask with 32-c2
4213 // leading zeros and c3 trailing zeros. We can use an SRLIW by c3-c2
4214 // followed by a SHXADD with c3 for the X amount.
4215 else if (LeftShift && Leading == 32 - C2 && C2 < Trailing)
4216 Opcode = RISCV::SRLIW;
4217 // Look for (and (shr y, c2), c1) where c1 is a shifted mask with c2
4218 // leading zeros and c3 trailing zeros. We can use an SRLI by c2+c3
4219 // followed by a SHXADD using c3 for the X amount.
4220 else if (!LeftShift && Leading == C2)
4221 Opcode = RISCV::SRLI;
4222 // Look for (and (shr y, c2), c1) where c1 is a shifted mask with 32+c2
4223 // leading zeros and c3 trailing zeros. We can use an SRLIW by c2+c3
4224 // followed by a SHXADD using c3 for the X amount.
4225 else if (!LeftShift && Leading == 32 + C2)
4226 Opcode = RISCV::SRLIW;
4227 else
4228 return false;
4229
4230 SDLoc DL(N);
4231 EVT VT = N.getValueType();
4232 ShAmt = LeftShift ? Trailing - C2 : Trailing + C2;
4233 Val = SDValue(
4234 CurDAG->getMachineNode(Opcode, DL, VT, N0.getOperand(0),
4235 CurDAG->getTargetConstant(ShAmt, DL, VT)),
4236 0);
4237 return true;
4238 }
4239 } else if (N0.getOpcode() == ISD::SRA && N0.hasOneUse() &&
4241 uint64_t Mask = N.getConstantOperandVal(1);
4242 unsigned C2 = N0.getConstantOperandVal(1);
4243
4244 // Look for (and (sra y, c2), c1) where c1 is a shifted mask with c3
4245 // leading zeros and c4 trailing zeros. If c2 is greater than c3, we can
4246 // use (srli (srai y, c2 - c3), c3 + c4) followed by a SHXADD with c4 as
4247 // the X amount.
4248 if (isShiftedMask_64(Mask)) {
4249 unsigned XLen = Subtarget->getXLen();
4250 unsigned Leading = XLen - llvm::bit_width(Mask);
4251 unsigned Trailing = llvm::countr_zero(Mask);
4252 if (C2 > Leading && Leading > 0 && Trailing == ShAmt) {
4253 SDLoc DL(N);
4254 EVT VT = N.getValueType();
4255 Val = SDValue(CurDAG->getMachineNode(
4256 RISCV::SRAI, DL, VT, N0.getOperand(0),
4257 CurDAG->getTargetConstant(C2 - Leading, DL, VT)),
4258 0);
4259 Val = SDValue(CurDAG->getMachineNode(
4260 RISCV::SRLI, DL, VT, Val,
4261 CurDAG->getTargetConstant(Leading + ShAmt, DL, VT)),
4262 0);
4263 return true;
4264 }
4265 }
4266 }
4267 } else if (bool LeftShift = N.getOpcode() == ISD::SHL;
4268 (LeftShift || N.getOpcode() == ISD::SRL) &&
4269 isa<ConstantSDNode>(N.getOperand(1))) {
4270 SDValue N0 = N.getOperand(0);
4271 if (N0.getOpcode() == ISD::AND && N0.hasOneUse() &&
4273 uint64_t Mask = N0.getConstantOperandVal(1);
4274 if (isShiftedMask_64(Mask)) {
4275 unsigned C1 = N.getConstantOperandVal(1);
4276 unsigned XLen = Subtarget->getXLen();
4277 unsigned Leading = XLen - llvm::bit_width(Mask);
4278 unsigned Trailing = llvm::countr_zero(Mask);
4279 // Look for (shl (and X, Mask), C1) where Mask has 32 leading zeros and
4280 // C3 trailing zeros. If C1+C3==ShAmt we can use SRLIW+SHXADD.
4281 if (LeftShift && Leading == 32 && Trailing > 0 &&
4282 (Trailing + C1) == ShAmt) {
4283 SDLoc DL(N);
4284 EVT VT = N.getValueType();
4285 Val = SDValue(CurDAG->getMachineNode(
4286 RISCV::SRLIW, DL, VT, N0.getOperand(0),
4287 CurDAG->getTargetConstant(Trailing, DL, VT)),
4288 0);
4289 return true;
4290 }
4291 // Look for (srl (and X, Mask), C1) where Mask has 32 leading zeros and
4292 // C3 trailing zeros. If C3-C1==ShAmt we can use SRLIW+SHXADD.
4293 if (!LeftShift && Leading == 32 && Trailing > C1 &&
4294 (Trailing - C1) == ShAmt) {
4295 SDLoc DL(N);
4296 EVT VT = N.getValueType();
4297 Val = SDValue(CurDAG->getMachineNode(
4298 RISCV::SRLIW, DL, VT, N0.getOperand(0),
4299 CurDAG->getTargetConstant(Trailing, DL, VT)),
4300 0);
4301 return true;
4302 }
4303 }
4304 }
4305 }
4306
4307 return false;
4308}
4309
4310/// Look for various patterns that can be done with a SHL that can be folded
4311/// into a SHXADD_UW. \p ShAmt contains 1, 2, or 3 and is set based on which
4312/// SHXADD_UW we are trying to match.
4314 SDValue &Val) {
4315 if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1)) &&
4316 N.hasOneUse()) {
4317 SDValue N0 = N.getOperand(0);
4318 if (N0.getOpcode() == ISD::SHL && isa<ConstantSDNode>(N0.getOperand(1)) &&
4319 N0.hasOneUse()) {
4320 uint64_t Mask = N.getConstantOperandVal(1);
4321 unsigned C2 = N0.getConstantOperandVal(1);
4322
4323 Mask &= maskTrailingZeros<uint64_t>(C2);
4324
4325 // Look for (and (shl y, c2), c1) where c1 is a shifted mask with
4326 // 32-ShAmt leading zeros and c2 trailing zeros. We can use SLLI by
4327 // c2-ShAmt followed by SHXADD_UW with ShAmt for the X amount.
4328 if (isShiftedMask_64(Mask)) {
4329 unsigned Leading = llvm::countl_zero(Mask);
4330 unsigned Trailing = llvm::countr_zero(Mask);
4331 if (Leading == 32 - ShAmt && Trailing == C2 && Trailing > ShAmt) {
4332 SDLoc DL(N);
4333 EVT VT = N.getValueType();
4334 Val = SDValue(CurDAG->getMachineNode(
4335 RISCV::SLLI, DL, VT, N0.getOperand(0),
4336 CurDAG->getTargetConstant(C2 - ShAmt, DL, VT)),
4337 0);
4338 return true;
4339 }
4340 }
4341 }
4342 }
4343
4344 return false;
4345}
4346
4348 assert(N->getOpcode() == ISD::OR || N->getOpcode() == RISCVISD::OR_VL);
4349 if (N->getFlags().hasDisjoint())
4350 return true;
4351 return CurDAG->haveNoCommonBitsSet(N->getOperand(0), N->getOperand(1));
4352}
4353
4354bool RISCVDAGToDAGISel::selectImm64IfCheaper(int64_t Imm, int64_t OrigImm,
4355 SDValue N, SDValue &Val) {
4356 int OrigCost = RISCVMatInt::getIntMatCost(APInt(64, OrigImm), 64, *Subtarget,
4357 /*CompressionCost=*/true);
4358 int Cost = RISCVMatInt::getIntMatCost(APInt(64, Imm), 64, *Subtarget,
4359 /*CompressionCost=*/true);
4360 if (OrigCost <= Cost)
4361 return false;
4362
4363 Val = selectImm(CurDAG, SDLoc(N), N->getSimpleValueType(0), Imm, *Subtarget);
4364 return true;
4365}
4366
4368 if (!isa<ConstantSDNode>(N))
4369 return false;
4370 int64_t Imm = cast<ConstantSDNode>(N)->getSExtValue();
4371 if ((Imm >> 31) != 1)
4372 return false;
4373
4374 for (const SDNode *U : N->users()) {
4375 switch (U->getOpcode()) {
4376 case ISD::ADD:
4377 break;
4378 case ISD::OR:
4379 if (orDisjoint(U))
4380 break;
4381 return false;
4382 default:
4383 return false;
4384 }
4385 }
4386
4387 return selectImm64IfCheaper(0xffffffff00000000 | Imm, Imm, N, Val);
4388}
4389
4391 if (!isa<ConstantSDNode>(N))
4392 return false;
4393 int64_t Imm = cast<ConstantSDNode>(N)->getSExtValue();
4394 if (isInt<32>(Imm))
4395 return false;
4396 if (Imm == INT64_MIN)
4397 return false;
4398
4399 for (const SDNode *U : N->users()) {
4400 switch (U->getOpcode()) {
4401 case ISD::ADD:
4402 break;
4403 case RISCVISD::VMV_V_X_VL:
4404 if (!all_of(U->users(), [](const SDNode *V) {
4405 return V->getOpcode() == ISD::ADD ||
4406 V->getOpcode() == RISCVISD::ADD_VL;
4407 }))
4408 return false;
4409 break;
4410 default:
4411 return false;
4412 }
4413 }
4414
4415 return selectImm64IfCheaper(-Imm, Imm, N, Val);
4416}
4417
4419 if (!isa<ConstantSDNode>(N))
4420 return false;
4421 int64_t Imm = cast<ConstantSDNode>(N)->getSExtValue();
4422
4423 // For 32-bit signed constants, we can only substitute LUI+ADDI with LUI.
4424 if (isInt<32>(Imm) && ((Imm & 0xfff) != 0xfff || Imm == -1))
4425 return false;
4426
4427 // Abandon this transform if the constant is needed elsewhere.
4428 for (const SDNode *U : N->users()) {
4429 switch (U->getOpcode()) {
4430 case ISD::AND:
4431 case ISD::OR:
4432 case ISD::XOR:
4433 if (!(Subtarget->hasStdExtZbb() || Subtarget->hasStdExtZbkb()))
4434 return false;
4435 break;
4436 case RISCVISD::VMV_V_X_VL:
4437 if (!Subtarget->hasStdExtZvkb())
4438 return false;
4439 if (!all_of(U->users(), [](const SDNode *V) {
4440 return V->getOpcode() == ISD::AND ||
4441 V->getOpcode() == RISCVISD::AND_VL;
4442 }))
4443 return false;
4444 break;
4445 default:
4446 return false;
4447 }
4448 }
4449
4450 if (isInt<32>(Imm)) {
4451 Val =
4452 selectImm(CurDAG, SDLoc(N), N->getSimpleValueType(0), ~Imm, *Subtarget);
4453 return true;
4454 }
4455
4456 // For 64-bit constants, the instruction sequences get complex,
4457 // so we select inverted only if it's cheaper.
4458 return selectImm64IfCheaper(~Imm, Imm, N, Val);
4459}
4460
4461static bool vectorPseudoHasAllNBitUsers(SDNode *User, unsigned UserOpNo,
4462 unsigned Bits,
4463 const TargetInstrInfo *TII) {
4464 unsigned MCOpcode = RISCV::getRVVMCOpcode(User->getMachineOpcode());
4465
4466 if (!MCOpcode)
4467 return false;
4468
4469 const MCInstrDesc &MCID = TII->get(User->getMachineOpcode());
4470 const uint64_t TSFlags = MCID.TSFlags;
4471 if (!RISCVII::hasSEWOp(TSFlags))
4472 return false;
4473 assert(RISCVII::hasVLOp(TSFlags));
4474
4475 unsigned ChainOpIdx = User->getNumOperands() - 1;
4476 bool HasChainOp = User->getOperand(ChainOpIdx).getValueType() == MVT::Other;
4477 bool HasVecPolicyOp = RISCVII::hasVecPolicyOp(TSFlags);
4478 unsigned VLIdx = User->getNumOperands() - HasVecPolicyOp - HasChainOp - 2;
4479 const unsigned Log2SEW = User->getConstantOperandVal(VLIdx + 1);
4480
4481 if (UserOpNo == VLIdx)
4482 return false;
4483
4484 auto NumDemandedBits =
4485 RISCV::getVectorLowDemandedScalarBits(MCOpcode, Log2SEW);
4486 return NumDemandedBits && Bits >= *NumDemandedBits;
4487}
4488
4489// Return true if all users of this SDNode* only consume the lower \p Bits.
4490// This can be used to form W instructions for add/sub/mul/shl even when the
4491// root isn't a sext_inreg. This can allow the ADDW/SUBW/MULW/SLLIW to CSE if
4492// SimplifyDemandedBits has made it so some users see a sext_inreg and some
4493// don't. The sext_inreg+add/sub/mul/shl will get selected, but still leave
4494// the add/sub/mul/shl to become non-W instructions. By checking the users we
4495// may be able to use a W instruction and CSE with the other instruction if
4496// this has happened. We could try to detect that the CSE opportunity exists
4497// before doing this, but that would be more complicated.
4499 const unsigned Depth) const {
4500 assert((Node->getOpcode() == ISD::ADD || Node->getOpcode() == ISD::SUB ||
4501 Node->getOpcode() == ISD::MUL || Node->getOpcode() == ISD::SHL ||
4502 Node->getOpcode() == ISD::SRL || Node->getOpcode() == ISD::AND ||
4503 Node->getOpcode() == ISD::OR || Node->getOpcode() == ISD::XOR ||
4504 Node->getOpcode() == ISD::SIGN_EXTEND_INREG ||
4505 isa<ConstantSDNode>(Node) || Depth != 0) &&
4506 "Unexpected opcode");
4507
4509 return false;
4510
4511 // The PatFrags that call this may run before RISCVGenDAGISel.inc has checked
4512 // the VT. Ensure the type is scalar to avoid wasting time on vectors.
4513 if (Depth == 0 && !Node->getValueType(0).isScalarInteger())
4514 return false;
4515
4516 for (SDUse &Use : Node->uses()) {
4517 SDNode *User = Use.getUser();
4518 // Users of this node should have already been instruction selected
4519 if (!User->isMachineOpcode())
4520 return false;
4521
4522 // TODO: Add more opcodes?
4523 switch (User->getMachineOpcode()) {
4524 default:
4526 break;
4527 return false;
4528 case RISCV::ADDW:
4529 case RISCV::ADDIW:
4530 case RISCV::SUBW:
4531 case RISCV::MULW:
4532 case RISCV::SLLW:
4533 case RISCV::SLLIW:
4534 case RISCV::SRAW:
4535 case RISCV::SRAIW:
4536 case RISCV::SRLW:
4537 case RISCV::SRLIW:
4538 case RISCV::DIVW:
4539 case RISCV::DIVUW:
4540 case RISCV::REMW:
4541 case RISCV::REMUW:
4542 case RISCV::ROLW:
4543 case RISCV::RORW:
4544 case RISCV::RORIW:
4545 case RISCV::CLSW:
4546 case RISCV::CLZW:
4547 case RISCV::CTZW:
4548 case RISCV::CPOPW:
4549 case RISCV::SLLI_UW:
4550 case RISCV::ABSW:
4551 case RISCV::FMV_W_X:
4552 case RISCV::FCVT_H_W:
4553 case RISCV::FCVT_H_W_INX:
4554 case RISCV::FCVT_H_WU:
4555 case RISCV::FCVT_H_WU_INX:
4556 case RISCV::FCVT_S_W:
4557 case RISCV::FCVT_S_W_INX:
4558 case RISCV::FCVT_S_WU:
4559 case RISCV::FCVT_S_WU_INX:
4560 case RISCV::FCVT_D_W:
4561 case RISCV::FCVT_D_W_INX:
4562 case RISCV::FCVT_D_WU:
4563 case RISCV::FCVT_D_WU_INX:
4564 case RISCV::TH_REVW:
4565 case RISCV::TH_SRRIW:
4566 if (Bits >= 32)
4567 break;
4568 return false;
4569 case RISCV::SLL:
4570 case RISCV::SRA:
4571 case RISCV::SRL:
4572 case RISCV::ROL:
4573 case RISCV::ROR:
4574 case RISCV::BSET:
4575 case RISCV::BCLR:
4576 case RISCV::BINV:
4577 // Shift amount operands only use log2(Xlen) bits.
4578 if (Use.getOperandNo() == 1 && Bits >= Log2_32(Subtarget->getXLen()))
4579 break;
4580 return false;
4581 case RISCV::SLLI:
4582 // SLLI only uses the lower (XLen - ShAmt) bits.
4583 if (Bits >= Subtarget->getXLen() - User->getConstantOperandVal(1))
4584 break;
4585 return false;
4586 case RISCV::ANDI:
4587 if (Bits >= (unsigned)llvm::bit_width(User->getConstantOperandVal(1)))
4588 break;
4589 goto RecCheck;
4590 case RISCV::ORI: {
4591 uint64_t Imm = cast<ConstantSDNode>(User->getOperand(1))->getSExtValue();
4592 if (Bits >= (unsigned)llvm::bit_width<uint64_t>(~Imm))
4593 break;
4594 [[fallthrough]];
4595 }
4596 case RISCV::AND:
4597 case RISCV::OR:
4598 case RISCV::XOR:
4599 case RISCV::XORI:
4600 case RISCV::ANDN:
4601 case RISCV::ORN:
4602 case RISCV::XNOR:
4603 case RISCV::SH1ADD:
4604 case RISCV::SH2ADD:
4605 case RISCV::SH3ADD:
4606 RecCheck:
4607 if (hasAllNBitUsers(User, Bits, Depth + 1))
4608 break;
4609 return false;
4610 case RISCV::SRLI: {
4611 unsigned ShAmt = User->getConstantOperandVal(1);
4612 // If we are shifting right by less than Bits, and users don't demand any
4613 // bits that were shifted into [Bits-1:0], then we can consider this as an
4614 // N-Bit user.
4615 if (Bits > ShAmt && hasAllNBitUsers(User, Bits - ShAmt, Depth + 1))
4616 break;
4617 return false;
4618 }
4619 case RISCV::SEXT_B:
4620 case RISCV::PACKH:
4621 if (Bits >= 8)
4622 break;
4623 return false;
4624 case RISCV::SEXT_H:
4625 case RISCV::FMV_H_X:
4626 case RISCV::ZEXT_H_RV32:
4627 case RISCV::ZEXT_H_RV64:
4628 case RISCV::PACKW:
4629 if (Bits >= 16)
4630 break;
4631 return false;
4632 case RISCV::PACK:
4633 if (Bits >= (Subtarget->getXLen() / 2))
4634 break;
4635 return false;
4636 case RISCV::PPAIRE_H:
4637 // If only the lower 32-bits of the result are used, then only the
4638 // lower 16 bits of the inputs are used.
4639 if (Bits >= 16 && hasAllNBitUsers(User, 32, Depth + 1))
4640 break;
4641 return false;
4642 case RISCV::ADD_UW:
4643 case RISCV::SH1ADD_UW:
4644 case RISCV::SH2ADD_UW:
4645 case RISCV::SH3ADD_UW:
4646 // The first operand to add.uw/shXadd.uw is implicitly zero extended from
4647 // 32 bits.
4648 if (Use.getOperandNo() == 0 && Bits >= 32)
4649 break;
4650 return false;
4651 case RISCV::SB:
4652 if (Use.getOperandNo() == 0 && Bits >= 8)
4653 break;
4654 return false;
4655 case RISCV::SH:
4656 if (Use.getOperandNo() == 0 && Bits >= 16)
4657 break;
4658 return false;
4659 case RISCV::SW:
4660 if (Use.getOperandNo() == 0 && Bits >= 32)
4661 break;
4662 return false;
4663 case RISCV::TH_EXT:
4664 case RISCV::TH_EXTU: {
4665 unsigned Msb = User->getConstantOperandVal(1);
4666 unsigned Lsb = User->getConstantOperandVal(2);
4667 // Behavior of Msb < Lsb is not well documented.
4668 if (Msb >= Lsb && Bits > Msb)
4669 break;
4670 return false;
4671 }
4672 }
4673 }
4674
4675 return true;
4676}
4677
4678// Select a constant that can be represented as (sign_extend(imm5) << imm2).
4680 SDValue &Shl2) {
4681 auto *C = dyn_cast<ConstantSDNode>(N);
4682 if (!C)
4683 return false;
4684
4685 int64_t Offset = C->getSExtValue();
4686 for (unsigned Shift = 0; Shift < 4; Shift++) {
4687 if (isInt<5>(Offset >> Shift) && ((Offset % (1LL << Shift)) == 0)) {
4688 EVT VT = N->getValueType(0);
4689 Simm5 = CurDAG->getSignedTargetConstant(Offset >> Shift, SDLoc(N), VT);
4690 Shl2 = CurDAG->getTargetConstant(Shift, SDLoc(N), VT);
4691 return true;
4692 }
4693 }
4694
4695 return false;
4696}
4697
4698// Select VL as a 5 bit immediate or a value that will become a register. This
4699// allows us to choose between VSETIVLI or VSETVLI later.
4701 auto *C = dyn_cast<ConstantSDNode>(N);
4702 if (C && isUInt<5>(C->getZExtValue())) {
4703 VL = CurDAG->getTargetConstant(C->getZExtValue(), SDLoc(N),
4704 N->getValueType(0));
4705 } else if (C && C->isAllOnes()) {
4706 // Treat all ones as VLMax.
4707 VL = CurDAG->getSignedTargetConstant(RISCV::VLMaxSentinel, SDLoc(N),
4708 N->getValueType(0));
4709 } else if (isa<RegisterSDNode>(N) &&
4710 cast<RegisterSDNode>(N)->getReg() == RISCV::X0) {
4711 // All our VL operands use an operand that allows GPRNoX0 or an immediate
4712 // as the register class. Convert X0 to a special immediate to pass the
4713 // MachineVerifier. This is recognized specially by the vsetvli insertion
4714 // pass.
4715 VL = CurDAG->getSignedTargetConstant(RISCV::VLMaxSentinel, SDLoc(N),
4716 N->getValueType(0));
4717 } else {
4718 VL = N;
4719 }
4720
4721 return true;
4722}
4723
4725 if (N.getOpcode() == ISD::INSERT_SUBVECTOR) {
4726 if (!N.getOperand(0).isUndef())
4727 return SDValue();
4728 N = N.getOperand(1);
4729 }
4730 SDValue Splat = N;
4731 if ((Splat.getOpcode() != RISCVISD::VMV_V_X_VL &&
4732 Splat.getOpcode() != RISCVISD::VMV_S_X_VL) ||
4733 !Splat.getOperand(0).isUndef())
4734 return SDValue();
4735 assert(Splat.getNumOperands() == 3 && "Unexpected number of operands");
4736 return Splat;
4737}
4738
4741 if (!Splat)
4742 return false;
4743
4744 SplatVal = Splat.getOperand(1);
4745 return true;
4746}
4747
4749 SelectionDAG &DAG,
4750 const RISCVSubtarget &Subtarget,
4751 std::function<bool(int64_t)> ValidateImm,
4752 bool Decrement = false) {
4754 if (!Splat || !isa<ConstantSDNode>(Splat.getOperand(1)))
4755 return false;
4756
4757 const unsigned SplatEltSize = Splat.getScalarValueSizeInBits();
4758 assert(Subtarget.getXLenVT() == Splat.getOperand(1).getSimpleValueType() &&
4759 "Unexpected splat operand type");
4760
4761 // The semantics of RISCVISD::VMV_V_X_VL is that when the operand
4762 // type is wider than the resulting vector element type: an implicit
4763 // truncation first takes place. Therefore, perform a manual
4764 // truncation/sign-extension in order to ignore any truncated bits and catch
4765 // any zero-extended immediate.
4766 // For example, we wish to match (i8 -1) -> (XLenVT 255) as a simm5 by first
4767 // sign-extending to (XLenVT -1).
4768 APInt SplatConst = Splat.getConstantOperandAPInt(1).sextOrTrunc(SplatEltSize);
4769
4770 int64_t SplatImm = SplatConst.getSExtValue();
4771
4772 if (!ValidateImm(SplatImm))
4773 return false;
4774
4775 if (Decrement)
4776 SplatImm -= 1;
4777
4778 SplatVal =
4779 DAG.getSignedTargetConstant(SplatImm, SDLoc(N), Subtarget.getXLenVT());
4780 return true;
4781}
4782
4784 return selectVSplatImmHelper(N, SplatVal, *CurDAG, *Subtarget,
4785 [](int64_t Imm) { return isInt<5>(Imm); });
4786}
4787
4789 return selectVSplatImmHelper(
4790 N, SplatVal, *CurDAG, *Subtarget,
4791 [](int64_t Imm) { return Imm >= -15 && Imm <= 16; },
4792 /*Decrement=*/true);
4793}
4794
4796 return selectVSplatImmHelper(
4797 N, SplatVal, *CurDAG, *Subtarget,
4798 [](int64_t Imm) { return Imm >= -15 && Imm <= 16; },
4799 /*Decrement=*/false);
4800}
4801
4803 SDValue &SplatVal) {
4804 return selectVSplatImmHelper(
4805 N, SplatVal, *CurDAG, *Subtarget,
4806 [](int64_t Imm) { return Imm != 0 && Imm >= -15 && Imm <= 16; },
4807 /*Decrement=*/true);
4808}
4809
4811 SDValue &SplatVal) {
4812 return selectVSplatImmHelper(
4813 N, SplatVal, *CurDAG, *Subtarget,
4814 [Bits](int64_t Imm) { return isUIntN(Bits, Imm); });
4815}
4816
4819 return Splat && selectNegImm(Splat.getOperand(1), SplatVal);
4820}
4821
4823 auto IsExtOrTrunc = [](SDValue N) {
4824 switch (N->getOpcode()) {
4825 case ISD::SIGN_EXTEND:
4826 case ISD::ZERO_EXTEND:
4827 // There's no passthru on these _VL nodes so any VL/mask is ok, since any
4828 // inactive elements will be undef.
4829 case RISCVISD::TRUNCATE_VECTOR_VL:
4830 case RISCVISD::VSEXT_VL:
4831 case RISCVISD::VZEXT_VL:
4832 return true;
4833 default:
4834 return false;
4835 }
4836 };
4837
4838 // We can have multiple nested nodes, so unravel them all if needed.
4839 while (IsExtOrTrunc(N)) {
4840 if (!N.hasOneUse() || N.getScalarValueSizeInBits() < 8)
4841 return false;
4842 N = N->getOperand(0);
4843 }
4844
4845 return selectVSplat(N, SplatVal);
4846}
4847
4849 // Allow bitcasts from XLenVT -> FP.
4850 if (N.getOpcode() == ISD::BITCAST &&
4851 N.getOperand(0).getValueType() == Subtarget->getXLenVT()) {
4852 Imm = N.getOperand(0);
4853 return true;
4854 }
4855 // Allow moves from XLenVT to FP.
4856 if (N.getOpcode() == RISCVISD::FMV_H_X ||
4857 N.getOpcode() == RISCVISD::FMV_W_X_RV64) {
4858 Imm = N.getOperand(0);
4859 return true;
4860 }
4861
4862 // Otherwise, look for FP constants that can materialized with scalar int.
4864 if (!CFP)
4865 return false;
4866 const APFloat &APF = CFP->getValueAPF();
4867 // td can handle +0.0 already.
4868 if (APF.isPosZero())
4869 return false;
4870
4871 MVT VT = CFP->getSimpleValueType(0);
4872
4873 MVT XLenVT = Subtarget->getXLenVT();
4874 if (VT == MVT::f64 && !Subtarget->is64Bit()) {
4875 assert(APF.isNegZero() && "Unexpected constant.");
4876 return false;
4877 }
4878 SDLoc DL(N);
4879 Imm = selectImm(CurDAG, DL, XLenVT, APF.bitcastToAPInt().getSExtValue(),
4880 *Subtarget);
4881 return true;
4882}
4883
4885 SDValue &Imm) {
4886 if (auto *C = dyn_cast<ConstantSDNode>(N)) {
4887 int64_t ImmVal = SignExtend64(C->getSExtValue(), Width);
4888
4889 if (!isInt<5>(ImmVal))
4890 return false;
4891
4892 Imm = CurDAG->getSignedTargetConstant(ImmVal, SDLoc(N),
4893 Subtarget->getXLenVT());
4894 return true;
4895 }
4896
4897 return false;
4898}
4899
4900// Match XOR with a VMSET_VL operand. Return the other operand.
4902 if (N.getOpcode() != ISD::XOR)
4903 return false;
4904
4905 if (N.getOperand(0).getOpcode() == RISCVISD::VMSET_VL) {
4906 Res = N.getOperand(1);
4907 return true;
4908 }
4909
4910 if (N.getOperand(1).getOpcode() == RISCVISD::VMSET_VL) {
4911 Res = N.getOperand(0);
4912 return true;
4913 }
4914
4915 return false;
4916}
4917
4918// Match VMXOR_VL with a VMSET_VL operand. Making sure that that VL operand
4919// matches the parent's VL. Return the other operand of the VMXOR_VL.
4921 SDValue &Res) {
4922 if (N.getOpcode() != RISCVISD::VMXOR_VL)
4923 return false;
4924
4925 assert(Parent &&
4926 (Parent->getOpcode() == RISCVISD::VMAND_VL ||
4927 Parent->getOpcode() == RISCVISD::VMOR_VL ||
4928 Parent->getOpcode() == RISCVISD::VMXOR_VL) &&
4929 "Unexpected parent");
4930
4931 // The VL should match the parent.
4932 if (Parent->getOperand(2) != N->getOperand(2))
4933 return false;
4934
4935 if (N.getOperand(0).getOpcode() == RISCVISD::VMSET_VL) {
4936 Res = N.getOperand(1);
4937 return true;
4938 }
4939
4940 if (N.getOperand(1).getOpcode() == RISCVISD::VMSET_VL) {
4941 Res = N.getOperand(0);
4942 return true;
4943 }
4944
4945 return false;
4946}
4947
4948// Try to remove sext.w if the input is a W instruction or can be made into
4949// a W instruction cheaply.
4950bool RISCVDAGToDAGISel::doPeepholeSExtW(SDNode *N) {
4951 // Look for the sext.w pattern, addiw rd, rs1, 0.
4952 if (N->getMachineOpcode() != RISCV::ADDIW ||
4953 !isNullConstant(N->getOperand(1)))
4954 return false;
4955
4956 SDValue N0 = N->getOperand(0);
4957 if (!N0.isMachineOpcode())
4958 return false;
4959
4960 switch (N0.getMachineOpcode()) {
4961 default:
4962 break;
4963 case RISCV::ADD:
4964 case RISCV::ADDI:
4965 case RISCV::SUB:
4966 case RISCV::MUL:
4967 case RISCV::SLLI: {
4968 // Convert sext.w+add/sub/mul to their W instructions. This will create
4969 // a new independent instruction. This improves latency.
4970 unsigned Opc;
4971 switch (N0.getMachineOpcode()) {
4972 default:
4973 llvm_unreachable("Unexpected opcode!");
4974 case RISCV::ADD: Opc = RISCV::ADDW; break;
4975 case RISCV::ADDI: Opc = RISCV::ADDIW; break;
4976 case RISCV::SUB: Opc = RISCV::SUBW; break;
4977 case RISCV::MUL: Opc = RISCV::MULW; break;
4978 case RISCV::SLLI: Opc = RISCV::SLLIW; break;
4979 }
4980
4981 SDValue N00 = N0.getOperand(0);
4982 SDValue N01 = N0.getOperand(1);
4983
4984 // Shift amount needs to be uimm5.
4985 if (N0.getMachineOpcode() == RISCV::SLLI &&
4986 !isUInt<5>(cast<ConstantSDNode>(N01)->getSExtValue()))
4987 break;
4988
4989 SDNode *Result =
4990 CurDAG->getMachineNode(Opc, SDLoc(N), N->getValueType(0),
4991 N00, N01);
4992 ReplaceUses(N, Result);
4993 return true;
4994 }
4995 case RISCV::ADDW:
4996 case RISCV::ADDIW:
4997 case RISCV::SUBW:
4998 case RISCV::MULW:
4999 case RISCV::SLLIW:
5000 case RISCV::PACKW:
5001 case RISCV::TH_MULAW:
5002 case RISCV::TH_MULAH:
5003 case RISCV::TH_MULSW:
5004 case RISCV::TH_MULSH:
5005 if (N0.getValueType() == MVT::i32)
5006 break;
5007
5008 // Result is already sign extended just remove the sext.w.
5009 // NOTE: We only handle the nodes that are selected with hasAllWUsers.
5010 ReplaceUses(N, N0.getNode());
5011 return true;
5012 }
5013
5014 return false;
5015}
5016
5017static bool usesAllOnesMask(SDValue MaskOp) {
5018 const auto IsVMSet = [](unsigned Opc) {
5019 return Opc == RISCV::PseudoVMSET_M_B1 || Opc == RISCV::PseudoVMSET_M_B16 ||
5020 Opc == RISCV::PseudoVMSET_M_B2 || Opc == RISCV::PseudoVMSET_M_B32 ||
5021 Opc == RISCV::PseudoVMSET_M_B4 || Opc == RISCV::PseudoVMSET_M_B64 ||
5022 Opc == RISCV::PseudoVMSET_M_B8;
5023 };
5024
5025 // TODO: Check that the VMSET is the expected bitwidth? The pseudo has
5026 // undefined behaviour if it's the wrong bitwidth, so we could choose to
5027 // assume that it's all-ones? Same applies to its VL.
5028 return MaskOp->isMachineOpcode() && IsVMSet(MaskOp.getMachineOpcode());
5029}
5030
5031static bool isImplicitDef(SDValue V) {
5032 if (!V.isMachineOpcode())
5033 return false;
5034 if (V.getMachineOpcode() == TargetOpcode::REG_SEQUENCE) {
5035 for (unsigned I = 1; I < V.getNumOperands(); I += 2)
5036 if (!isImplicitDef(V.getOperand(I)))
5037 return false;
5038 return true;
5039 }
5040 return V.getMachineOpcode() == TargetOpcode::IMPLICIT_DEF;
5041}
5042
5043// Optimize masked RVV pseudo instructions with a known all-ones mask to their
5044// corresponding "unmasked" pseudo versions.
5045bool RISCVDAGToDAGISel::doPeepholeMaskedRVV(MachineSDNode *N) {
5046 const RISCV::RISCVMaskedPseudoInfo *I =
5047 RISCV::getMaskedPseudoInfo(N->getMachineOpcode());
5048 if (!I)
5049 return false;
5050
5051 unsigned MaskOpIdx = I->MaskOpIdx;
5052 if (!usesAllOnesMask(N->getOperand(MaskOpIdx)))
5053 return false;
5054
5055 // There are two classes of pseudos in the table - compares and
5056 // everything else. See the comment on RISCVMaskedPseudo for details.
5057 const unsigned Opc = I->UnmaskedPseudo;
5058 const MCInstrDesc &MCID = TII->get(Opc);
5059 const bool HasPassthru = RISCVII::isFirstDefTiedToFirstUse(MCID);
5060
5061 const MCInstrDesc &MaskedMCID = TII->get(N->getMachineOpcode());
5062 const bool MaskedHasPassthru = RISCVII::isFirstDefTiedToFirstUse(MaskedMCID);
5063
5064 assert((RISCVII::hasVecPolicyOp(MaskedMCID.TSFlags) ||
5066 "Unmasked pseudo has policy but masked pseudo doesn't?");
5067 assert(RISCVII::hasVecPolicyOp(MCID.TSFlags) == HasPassthru &&
5068 "Unexpected pseudo structure");
5069 assert(!(HasPassthru && !MaskedHasPassthru) &&
5070 "Unmasked pseudo has passthru but masked pseudo doesn't?");
5071
5073 // Skip the passthru operand at index 0 if the unmasked don't have one.
5074 bool ShouldSkip = !HasPassthru && MaskedHasPassthru;
5075 bool DropPolicy = !RISCVII::hasVecPolicyOp(MCID.TSFlags) &&
5076 RISCVII::hasVecPolicyOp(MaskedMCID.TSFlags);
5077 bool HasChainOp =
5078 N->getOperand(N->getNumOperands() - 1).getValueType() == MVT::Other;
5079 unsigned LastOpNum = N->getNumOperands() - 1 - HasChainOp;
5080 for (unsigned I = ShouldSkip, E = N->getNumOperands(); I != E; I++) {
5081 // Skip the mask
5082 SDValue Op = N->getOperand(I);
5083 if (I == MaskOpIdx)
5084 continue;
5085 if (DropPolicy && I == LastOpNum)
5086 continue;
5087 Ops.push_back(Op);
5088 }
5089
5090 MachineSDNode *Result =
5091 CurDAG->getMachineNode(Opc, SDLoc(N), N->getVTList(), Ops);
5092
5093 if (!N->memoperands_empty())
5094 CurDAG->setNodeMemRefs(Result, N->memoperands());
5095
5096 Result->setFlags(N->getFlags());
5097 ReplaceUses(N, Result);
5098
5099 return true;
5100}
5101
5102/// If our passthru is an implicit_def, use noreg instead. This side
5103/// steps issues with MachineCSE not being able to CSE expressions with
5104/// IMPLICIT_DEF operands while preserving the semantic intent. See
5105/// pr64282 for context. Note that this transform is the last one
5106/// performed at ISEL DAG to DAG.
5107bool RISCVDAGToDAGISel::doPeepholeNoRegPassThru() {
5108 bool MadeChange = false;
5109 SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end();
5110
5111 while (Position != CurDAG->allnodes_begin()) {
5112 SDNode *N = &*--Position;
5113 if (N->use_empty() || !N->isMachineOpcode())
5114 continue;
5115
5116 const unsigned Opc = N->getMachineOpcode();
5117 if (!RISCVVPseudosTable::getPseudoInfo(Opc) ||
5119 !isImplicitDef(N->getOperand(0)))
5120 continue;
5121
5123 Ops.push_back(CurDAG->getRegister(RISCV::NoRegister, N->getValueType(0)));
5124 for (unsigned I = 1, E = N->getNumOperands(); I != E; I++) {
5125 SDValue Op = N->getOperand(I);
5126 Ops.push_back(Op);
5127 }
5128
5129 MachineSDNode *Result =
5130 CurDAG->getMachineNode(Opc, SDLoc(N), N->getVTList(), Ops);
5131 Result->setFlags(N->getFlags());
5132 CurDAG->setNodeMemRefs(Result, cast<MachineSDNode>(N)->memoperands());
5133 ReplaceUses(N, Result);
5134 MadeChange = true;
5135 }
5136 return MadeChange;
5137}
5138
5139
5140// This pass converts a legalized DAG into a RISCV-specific DAG, ready
5141// for instruction scheduling.
5146
5150
5152
5157
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:970
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:627
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:339
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:342
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:428
#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:177
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.