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