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