LLVM 24.0.0git
RISCVISelLowering.cpp
Go to the documentation of this file.
1//===-- RISCVISelLowering.cpp - RISC-V DAG Lowering Implementation -------===//
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 the interfaces that RISC-V uses to lower LLVM code into a
10// selection DAG.
11//
12//===----------------------------------------------------------------------===//
13
14#include "RISCVISelLowering.h"
16#include "RISCV.h"
19#include "RISCVRegisterInfo.h"
21#include "RISCVSubtarget.h"
22#include "RISCVVectorUtils.h"
23#include "llvm/ADT/SmallSet.h"
25#include "llvm/ADT/Statistic.h"
41#include "llvm/IR/IRBuilder.h"
44#include "llvm/IR/IntrinsicsRISCV.h"
48#include "llvm/Support/Debug.h"
54#include <optional>
55
56using namespace llvm;
57
58#define DEBUG_TYPE "riscv-lower"
59
60STATISTIC(NumTailCalls, "Number of tail calls");
61
63 DEBUG_TYPE "-ext-max-web-size", cl::Hidden,
64 cl::desc("Give the maximum size (in number of nodes) of the web of "
65 "instructions that we will consider for VW expansion"),
66 cl::init(18));
67
68static cl::opt<bool>
69 AllowSplatInVW_W(DEBUG_TYPE "-form-vw-w-with-splat", cl::Hidden,
70 cl::desc("Allow the formation of VW_W operations (e.g., "
71 "VWADD_W) with splat constants"),
72 cl::init(false));
73
75 DEBUG_TYPE "-fp-repeated-divisors", cl::Hidden,
76 cl::desc("Set the minimum number of repetitions of a divisor to allow "
77 "transformation to multiplications by the reciprocal"),
78 cl::init(2));
79
80static cl::opt<int>
82 cl::desc("Give the maximum number of instructions that we will "
83 "use for creating a floating-point immediate value"),
84 cl::init(3));
85
86static cl::opt<bool>
87 ReassocShlAddiAdd("reassoc-shl-addi-add", cl::Hidden,
88 cl::desc("Swap add and addi in cases where the add may "
89 "be combined with a shift"),
90 cl::init(true));
91
93 "riscv-br-merging-base-cost", cl::init(2),
95 "Sets the cost threshold for when multiple conditionals will be merged "
96 "into one branch versus be split in multiple branches. Merging "
97 "conditionals saves branches at the cost of additional instructions. "
98 "This value sets the instruction cost limit, below which conditionals "
99 "will be merged, and above which conditionals will be split. Set to -1 "
100 "to never merge branches."),
101 cl::Hidden);
102
104 "riscv-br-merging-likely-bias", cl::init(0),
105 cl::desc(
106 "Increases 'riscv-br-merging-base-cost' in cases that it is "
107 "likely that all conditionals will be executed. For example for "
108 "merging the conditionals (a == b && c > d), if its known that "
109 "a == b is likely, then it is likely that if the conditionals are "
110 "split both sides will be executed, so it may be desirable to "
111 "increase the instruction cost threshold. Set to -1 to never merge "
112 "likely branches."),
113 cl::Hidden);
114
116 "riscv-br-merging-unlikely-bias", cl::init(-1),
117 cl::desc(
118 "Decreases 'riscv-br-merging-base-cost' in cases that it is unlikely "
119 "that all conditionals will be executed. For example for merging "
120 "the conditionals (a == b && c > d), if its known that a == b is "
121 "unlikely, then it is unlikely that if the conditionals are split "
122 "both sides will be executed, so it may be desirable to decrease "
123 "the instruction cost threshold. Set to -1 to never merge unlikely "
124 "branches."),
125 cl::Hidden);
126
127// TODO: Support more ops
134
136 const RISCVSubtarget &STI)
137 : TargetLowering(TM, STI), Subtarget(STI) {
138
139 RISCVABI::ABI ABI = Subtarget.getTargetABI();
140 // Note: Hard-float ABIs that don't match the F/D extensions are already
141 // rejected/ by RISCVABI::computeTargetABI() during subtarget construction.
142 assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialised target ABI");
143
144 switch (ABI) {
145 default:
146 reportFatalUsageError("Don't know how to lower this ABI");
155 break;
156 }
157
158 MVT XLenVT = Subtarget.getXLenVT();
159
160 // Set up the register classes.
161 addRegisterClass(XLenVT, &RISCV::GPRRegClass);
162
163 if (Subtarget.hasStdExtZfhmin())
164 addRegisterClass(MVT::f16, &RISCV::FPR16RegClass);
165 if (Subtarget.hasStdExtZfbfmin() || Subtarget.hasVendorXAndesBFHCvt())
166 addRegisterClass(MVT::bf16, &RISCV::FPR16RegClass);
167 if (Subtarget.hasStdExtF())
168 addRegisterClass(MVT::f32, &RISCV::FPR32RegClass);
169 if (Subtarget.hasStdExtD())
170 addRegisterClass(MVT::f64, &RISCV::FPR64RegClass);
171 if (Subtarget.hasStdExtZhinxmin())
172 addRegisterClass(MVT::f16, &RISCV::GPRF16RegClass);
173 if (Subtarget.hasStdExtZfinx())
174 addRegisterClass(MVT::f32, &RISCV::GPRF32RegClass);
175 if (Subtarget.hasStdExtZdinx()) {
176 if (Subtarget.is64Bit())
177 addRegisterClass(MVT::f64, &RISCV::GPRRegClass);
178 else
179 addRegisterClass(MVT::f64, &RISCV::GPRPairRegClass);
180 }
181
182 static const MVT::SimpleValueType BoolVecVTs[] = {
183 MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1,
184 MVT::nxv16i1, MVT::nxv32i1, MVT::nxv64i1};
185 static const MVT::SimpleValueType IntVecVTs[] = {
186 MVT::nxv1i8, MVT::nxv2i8, MVT::nxv4i8, MVT::nxv8i8, MVT::nxv16i8,
187 MVT::nxv32i8, MVT::nxv64i8, MVT::nxv1i16, MVT::nxv2i16, MVT::nxv4i16,
188 MVT::nxv8i16, MVT::nxv16i16, MVT::nxv32i16, MVT::nxv1i32, MVT::nxv2i32,
189 MVT::nxv4i32, MVT::nxv8i32, MVT::nxv16i32, MVT::nxv1i64, MVT::nxv2i64,
190 MVT::nxv4i64, MVT::nxv8i64};
191 static const MVT::SimpleValueType F16VecVTs[] = {
192 MVT::nxv1f16, MVT::nxv2f16, MVT::nxv4f16,
193 MVT::nxv8f16, MVT::nxv16f16, MVT::nxv32f16};
194 static const MVT::SimpleValueType BF16VecVTs[] = {
195 MVT::nxv1bf16, MVT::nxv2bf16, MVT::nxv4bf16,
196 MVT::nxv8bf16, MVT::nxv16bf16, MVT::nxv32bf16};
197 static const MVT::SimpleValueType F32VecVTs[] = {
198 MVT::nxv1f32, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv8f32, MVT::nxv16f32};
199 static const MVT::SimpleValueType F64VecVTs[] = {
200 MVT::nxv1f64, MVT::nxv2f64, MVT::nxv4f64, MVT::nxv8f64};
201 static const MVT::SimpleValueType VecTupleVTs[] = {
202 MVT::riscv_nxv1i8x2, MVT::riscv_nxv1i8x3, MVT::riscv_nxv1i8x4,
203 MVT::riscv_nxv1i8x5, MVT::riscv_nxv1i8x6, MVT::riscv_nxv1i8x7,
204 MVT::riscv_nxv1i8x8, MVT::riscv_nxv2i8x2, MVT::riscv_nxv2i8x3,
205 MVT::riscv_nxv2i8x4, MVT::riscv_nxv2i8x5, MVT::riscv_nxv2i8x6,
206 MVT::riscv_nxv2i8x7, MVT::riscv_nxv2i8x8, MVT::riscv_nxv4i8x2,
207 MVT::riscv_nxv4i8x3, MVT::riscv_nxv4i8x4, MVT::riscv_nxv4i8x5,
208 MVT::riscv_nxv4i8x6, MVT::riscv_nxv4i8x7, MVT::riscv_nxv4i8x8,
209 MVT::riscv_nxv8i8x2, MVT::riscv_nxv8i8x3, MVT::riscv_nxv8i8x4,
210 MVT::riscv_nxv8i8x5, MVT::riscv_nxv8i8x6, MVT::riscv_nxv8i8x7,
211 MVT::riscv_nxv8i8x8, MVT::riscv_nxv16i8x2, MVT::riscv_nxv16i8x3,
212 MVT::riscv_nxv16i8x4, MVT::riscv_nxv32i8x2};
213
214 if (Subtarget.hasVInstructions()) {
215 auto addRegClassForRVV = [this](MVT VT) {
216 // Disable the smallest fractional LMUL types if ELEN is less than
217 // RVVBitsPerBlock.
218 unsigned MinElts = RISCV::RVVBitsPerBlock / Subtarget.getELen();
219 if (VT.getVectorMinNumElements() < MinElts)
220 return;
221
222 unsigned Size = VT.getSizeInBits().getKnownMinValue();
223 const TargetRegisterClass *RC;
225 RC = &RISCV::VRRegClass;
226 else if (Size == 2 * RISCV::RVVBitsPerBlock)
227 RC = &RISCV::VRM2RegClass;
228 else if (Size == 4 * RISCV::RVVBitsPerBlock)
229 RC = &RISCV::VRM4RegClass;
230 else if (Size == 8 * RISCV::RVVBitsPerBlock)
231 RC = &RISCV::VRM8RegClass;
232 else
233 llvm_unreachable("Unexpected size");
234
235 addRegisterClass(VT, RC);
236 };
237
238 for (MVT VT : BoolVecVTs)
239 addRegClassForRVV(VT);
240 for (MVT VT : IntVecVTs) {
241 if (VT.getVectorElementType() == MVT::i64 &&
242 !Subtarget.hasVInstructionsI64())
243 continue;
244 addRegClassForRVV(VT);
245 }
246
247 if (Subtarget.hasVInstructionsF16Minimal() ||
248 Subtarget.hasVendorXAndesVPackFPH())
249 for (MVT VT : F16VecVTs)
250 addRegClassForRVV(VT);
251
252 if (Subtarget.hasVInstructionsBF16Minimal() ||
253 Subtarget.hasVendorXAndesVBFHCvt())
254 for (MVT VT : BF16VecVTs)
255 addRegClassForRVV(VT);
256
257 if (Subtarget.hasVInstructionsF32())
258 for (MVT VT : F32VecVTs)
259 addRegClassForRVV(VT);
260
261 if (Subtarget.hasVInstructionsF64())
262 for (MVT VT : F64VecVTs)
263 addRegClassForRVV(VT);
264
265 if (Subtarget.useRVVForFixedLengthVectors()) {
266 auto addRegClassForFixedVectors = [this](MVT VT) {
267 MVT ContainerVT = getContainerForFixedLengthVector(VT);
268 unsigned RCID = getRegClassIDForVecVT(ContainerVT);
269 const RISCVRegisterInfo &TRI = *Subtarget.getRegisterInfo();
270 addRegisterClass(VT, TRI.getRegClass(RCID));
271 };
273 if (useRVVForFixedLengthVectorVT(VT))
274 addRegClassForFixedVectors(VT);
275
277 if (useRVVForFixedLengthVectorVT(VT))
278 addRegClassForFixedVectors(VT);
279 }
280
281 addRegisterClass(MVT::riscv_nxv1i8x2, &RISCV::VRN2M1RegClass);
282 addRegisterClass(MVT::riscv_nxv1i8x3, &RISCV::VRN3M1RegClass);
283 addRegisterClass(MVT::riscv_nxv1i8x4, &RISCV::VRN4M1RegClass);
284 addRegisterClass(MVT::riscv_nxv1i8x5, &RISCV::VRN5M1RegClass);
285 addRegisterClass(MVT::riscv_nxv1i8x6, &RISCV::VRN6M1RegClass);
286 addRegisterClass(MVT::riscv_nxv1i8x7, &RISCV::VRN7M1RegClass);
287 addRegisterClass(MVT::riscv_nxv1i8x8, &RISCV::VRN8M1RegClass);
288 addRegisterClass(MVT::riscv_nxv2i8x2, &RISCV::VRN2M1RegClass);
289 addRegisterClass(MVT::riscv_nxv2i8x3, &RISCV::VRN3M1RegClass);
290 addRegisterClass(MVT::riscv_nxv2i8x4, &RISCV::VRN4M1RegClass);
291 addRegisterClass(MVT::riscv_nxv2i8x5, &RISCV::VRN5M1RegClass);
292 addRegisterClass(MVT::riscv_nxv2i8x6, &RISCV::VRN6M1RegClass);
293 addRegisterClass(MVT::riscv_nxv2i8x7, &RISCV::VRN7M1RegClass);
294 addRegisterClass(MVT::riscv_nxv2i8x8, &RISCV::VRN8M1RegClass);
295 addRegisterClass(MVT::riscv_nxv4i8x2, &RISCV::VRN2M1RegClass);
296 addRegisterClass(MVT::riscv_nxv4i8x3, &RISCV::VRN3M1RegClass);
297 addRegisterClass(MVT::riscv_nxv4i8x4, &RISCV::VRN4M1RegClass);
298 addRegisterClass(MVT::riscv_nxv4i8x5, &RISCV::VRN5M1RegClass);
299 addRegisterClass(MVT::riscv_nxv4i8x6, &RISCV::VRN6M1RegClass);
300 addRegisterClass(MVT::riscv_nxv4i8x7, &RISCV::VRN7M1RegClass);
301 addRegisterClass(MVT::riscv_nxv4i8x8, &RISCV::VRN8M1RegClass);
302 addRegisterClass(MVT::riscv_nxv8i8x2, &RISCV::VRN2M1RegClass);
303 addRegisterClass(MVT::riscv_nxv8i8x3, &RISCV::VRN3M1RegClass);
304 addRegisterClass(MVT::riscv_nxv8i8x4, &RISCV::VRN4M1RegClass);
305 addRegisterClass(MVT::riscv_nxv8i8x5, &RISCV::VRN5M1RegClass);
306 addRegisterClass(MVT::riscv_nxv8i8x6, &RISCV::VRN6M1RegClass);
307 addRegisterClass(MVT::riscv_nxv8i8x7, &RISCV::VRN7M1RegClass);
308 addRegisterClass(MVT::riscv_nxv8i8x8, &RISCV::VRN8M1RegClass);
309 addRegisterClass(MVT::riscv_nxv16i8x2, &RISCV::VRN2M2RegClass);
310 addRegisterClass(MVT::riscv_nxv16i8x3, &RISCV::VRN3M2RegClass);
311 addRegisterClass(MVT::riscv_nxv16i8x4, &RISCV::VRN4M2RegClass);
312 addRegisterClass(MVT::riscv_nxv32i8x2, &RISCV::VRN2M4RegClass);
313 }
314
315 // fixed vector is stored in GPRs for P extension packed operations
316 if (Subtarget.hasStdExtP()) {
317 if (Subtarget.is64Bit()) {
318 addRegisterClass(MVT::v2i32, &RISCV::GPRRegClass);
319 addRegisterClass(MVT::v4i16, &RISCV::GPRRegClass);
320 addRegisterClass(MVT::v8i8, &RISCV::GPRRegClass);
321 } else {
322 addRegisterClass(MVT::v2i16, &RISCV::GPRRegClass);
323 addRegisterClass(MVT::v4i8, &RISCV::GPRRegClass);
324
325 addRegisterClass(MVT::v2i32, &RISCV::GPRPairRegClass);
326 addRegisterClass(MVT::v4i16, &RISCV::GPRPairRegClass);
327 addRegisterClass(MVT::v8i8, &RISCV::GPRPairRegClass);
328 }
329 }
330
331 // Compute derived properties from the register classes.
333
335
337 MVT::i1, Promote);
338 // DAGCombiner can call isLoadExtLegal for types that aren't legal.
340 MVT::i1, Promote);
341
342 // TODO: add all necessary setOperationAction calls.
344
349
354 if (!(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
357 }
358
360
363
364 if (!Subtarget.hasVendorXTHeadBb() && !Subtarget.hasVendorXqcibm() &&
365 !Subtarget.hasVendorXAndesPerf())
367
369
370 if (!Subtarget.hasStdExtZbb() && !Subtarget.hasVendorXTHeadBb() &&
371 !Subtarget.hasVendorXqcibm() && !Subtarget.hasVendorXAndesPerf() &&
372 !(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit()))
373 setOperationAction(ISD::SIGN_EXTEND_INREG, {MVT::i8, MVT::i16}, Expand);
374
375 if (Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit()) {
378 }
379
380 if (Subtarget.is64Bit()) {
382
385 MVT::i32, Custom);
388 } else if (Subtarget.hasStdExtP()) {
389 // Custom legalize i64 ADD/SUB/SHL/SRL/SRA for RV32+P.
392 }
393 if (!Subtarget.hasStdExtZmmul()) {
395 } else if (Subtarget.is64Bit()) {
398 } else {
400 }
401
402 if (!Subtarget.hasStdExtM()) {
404 Expand);
405 } else if (Subtarget.is64Bit()) {
407 {MVT::i8, MVT::i16, MVT::i32}, Custom);
408 }
409
411
412 // On RV32, the P extension has a WMUL(U) instruction we can use for
413 // (S/U)MUL_LOHI.
414 // FIXME: Does P imply Zmmul?
415 if (!Subtarget.hasStdExtP() || !Subtarget.hasStdExtZmmul() ||
416 Subtarget.is64Bit())
418
420 Custom);
421
422 if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) {
423 if (Subtarget.is64Bit())
425 } else if (Subtarget.hasVendorXTHeadBb()) {
426 if (Subtarget.is64Bit())
429 } else if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit()) {
431 } else {
433 }
434
435 if (Subtarget.hasStdExtP())
437
439 Subtarget.hasREV8Like() ? Legal : Expand);
440
441 if (Subtarget.hasREVLike()) {
443 } else {
444 // Zbkb can use rev8+brev8 to implement bitreverse.
446 Subtarget.hasStdExtZbkb() ? Custom : Expand);
447 if (Subtarget.hasStdExtZbkb())
449 }
450
451 if (Subtarget.hasStdExtZbb() ||
452 (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
454 Legal);
455 }
456
457 if (Subtarget.hasCTZLike()) {
458 if (Subtarget.is64Bit())
460 } else {
462 }
463
464 if (!Subtarget.hasCPOPLike()) {
465 // TODO: These should be set to LibCall, but this currently breaks
466 // the Linux kernel build. See #101786. Lacks i128 tests, too.
467 if (Subtarget.is64Bit())
469 else
472 }
473
474 if (Subtarget.hasCLZLike()) {
475 // We need the custom lowering to make sure that the resulting sequence
476 // for the 32bit case is efficient on 64bit targets.
477 // Use default promotion for i32 without Zbb.
478 if (Subtarget.is64Bit() &&
479 (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtP()))
481 } else {
482 if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit())
485 }
486
487 if (Subtarget.hasStdExtP()) {
489 if (Subtarget.is64Bit())
491 }
492
493 if (Subtarget.hasStdExtP() ||
494 (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
496 if (Subtarget.is64Bit())
498 } else if (Subtarget.hasShortForwardBranchIALU()) {
499 // We can use PseudoCCSUB to implement ABS.
501 } else if (Subtarget.is64Bit()) {
503 }
504
505 if (!Subtarget.useMIPSCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov())
507
508 if ((Subtarget.hasStdExtP() || Subtarget.hasVendorXqcia()) &&
509 !Subtarget.is64Bit()) {
511 MVT::i32, Legal);
512 } else if (Subtarget.hasStdExtP() && Subtarget.is64Bit()) {
514 MVT::i32, Custom);
515 } else if (!Subtarget.hasStdExtZbb() && Subtarget.is64Bit()) {
517 MVT::i32, Custom);
518 }
519
520 if ((Subtarget.hasStdExtP() || Subtarget.hasVendorXqcia()) &&
521 !Subtarget.is64Bit()) {
522 // FIXME: Support i32 on RV64+P by inserting into a v2i32 vector, doing
523 // pssha.w/psshl.w and extracting.
526 }
527
528 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit()) {
529 // FIXME: Support i32 on RV64+P by inserting into a v2i32 vector, doing
530 // paadd.w, paaddu.w and extracting.
532 }
533
534 if (Subtarget.hasStdExtZbkc()) {
536 if (Subtarget.hasStdExtZbc())
538 } else if (Subtarget.hasStdExtZvbc() && Subtarget.is64Bit()) {
539 // FIXME: Support i32 on RV32 by zexting from XLEN to i64 and extracting
540 // half of the result (low for CLMUL, high for CLMULH).
541 // TODO: Zvbc32e allows us to do a lot more here.
543 }
544
545 static const unsigned FPLegalNodeTypes[] = {
553
554 static const ISD::CondCode FPCCToExpand[] = {
558
559 static const unsigned FPOpToExpand[] = {ISD::FSIN, ISD::FCOS, ISD::FSINCOS,
560 ISD::FPOW};
561 static const unsigned FPOpToLibCall[] = {ISD::FREM};
562
563 static const unsigned FPRndMode[] = {
566
567 static const unsigned ZfhminZfbfminPromoteOps[] = {
578
579 if (Subtarget.hasStdExtP()) {
580 static const MVT P32VecVTs[] = {MVT::v2i16, MVT::v4i8};
581 static const MVT P64VecVTs[] = {MVT::v2i32, MVT::v4i16, MVT::v8i8};
582 ArrayRef<MVT> VTs;
583 if (Subtarget.is64Bit()) {
584 VTs = P64VecVTs;
585 // There's no instruction for vector shamt in P extension so we unroll to
586 // scalar instructions. Vector VTs that are 32-bit are widened to 64-bit
587 // vector, e.g. v2i16 -> v4i16, before getting unrolled, so we need custom
588 // widen for those operations that will be unrolled.
590 {MVT::v2i16, MVT::v4i8}, Custom);
591 setOperationAction(ISD::INTRINSIC_WO_CHAIN, {MVT::v2i16, MVT::v4i8},
592 Custom);
593 // Operand legalization queries the action using the illegal subvector.
594 setOperationAction(ISD::INSERT_SUBVECTOR, {MVT::v2i16, MVT::v4i8},
595 Custom);
596 } else {
597 VTs = P32VecVTs;
598 }
599 // By default everything must be expanded.
600 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op)
602
603 for (MVT VT : VTs) {
605 setTruncStoreAction(VT, OtherVT, Expand);
607 OtherVT, Expand);
608 }
609 }
610
622 for (MVT VT : VTs) {
623 if (VT != MVT::v2i32)
625 if (VT.getVectorElementType() != MVT::i8) {
628 }
629 }
637 Custom);
639 Legal);
645 Expand);
647
648 if (!Subtarget.is64Bit())
649 setOperationAction(ISD::BUILD_VECTOR, {MVT::v2i16, MVT::v4i8}, Custom);
650
651 // P extension vector comparisons produce all 1s for true, all 0s for false
653
654 if (!Subtarget.is64Bit()) {
655 // By default everything must be expanded.
656 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op)
657 setOperationAction(Op, P64VecVTs, Expand);
658
659 for (MVT VT : P64VecVTs) {
661 setTruncStoreAction(VT, OtherVT, Expand);
663 OtherVT, Expand);
664 }
665 }
666
671 setOperationAction({ISD::AND, ISD::OR, ISD::XOR}, {MVT::v4i16, MVT::v8i8},
672 Custom);
675 Legal);
680 P64VecVTs, Legal);
682 {MVT::v4i16, MVT::v8i8}, Legal);
684 setOperationAction(ISD::SSHLSAT, {MVT::v2i32, MVT::v4i16}, Custom);
685 setOperationAction(ISD::BSWAP, MVT::v4i16, Legal);
686 setOperationAction(ISD::BITREVERSE, {MVT::v4i16, MVT::v8i8}, Legal);
693 {MVT::v4i16, MVT::v8i8}, Custom);
694 setOperationAction(ISD::CONCAT_VECTORS, {MVT::v4i16, MVT::v8i8}, Legal);
695 setOperationAction(ISD::EXTRACT_SUBVECTOR, {MVT::v2i16, MVT::v4i8},
696 Legal);
697 setOperationAction({ISD::SELECT, ISD::VSELECT}, {MVT::v4i16, MVT::v8i8},
698 Custom);
700 {MVT::v4i16, MVT::v8i8}, Custom);
705 {MVT::v4i16, MVT::v2i32}, Legal);
706 setOperationAction(ISD::TRUNCATE, {MVT::v4i8, MVT::v2i16}, Legal);
710 P64VecVTs, Expand);
712 // Operation legalization queries the action using the result type.
713 setOperationAction(ISD::INSERT_SUBVECTOR, {MVT::v4i16, MVT::v8i8},
714 Custom);
715 } else {
716 setOperationAction(ISD::MUL, P64VecVTs, Legal);
717 setOperationAction({ISD::MULHS, ISD::MULHU}, {MVT::v2i32, MVT::v4i16},
718 Legal);
721 {MVT::v4i16, MVT::v2i32}, Legal);
722 setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, {MVT::v4i16, MVT::v2i32},
723 Custom);
724 setOperationAction(ISD::TRUNCATE, {MVT::v4i8, MVT::v2i16}, Custom);
725 }
726 // LegalizeVectorOps uses result VT, LegalizeDAG uses ExtVT.
729 {MVT::v2i8, MVT::v4i8, MVT::v2i16, MVT::v4i16, MVT::v2i32}, Legal);
730 }
731
732 if (Subtarget.hasStdExtZfbfmin()) {
739 setOperationAction(ZfhminZfbfminPromoteOps, MVT::bf16, Promote);
746 }
747
748 if (Subtarget.hasStdExtZfhminOrZhinxmin()) {
749 if (Subtarget.hasStdExtZfhmin())
751 if (Subtarget.hasStdExtZfhOrZhinx()) {
752 setOperationAction(FPLegalNodeTypes, MVT::f16, Legal);
753 setOperationAction(FPRndMode, MVT::f16,
754 Subtarget.hasStdExtZfa() ? Legal : Custom);
757 Subtarget.hasStdExtZfa() ? Legal : Custom);
758 if (Subtarget.hasStdExtZfa())
760 } else {
761 setOperationAction(ZfhminZfbfminPromoteOps, MVT::f16, Promote);
766 setOperationAction(Op, MVT::f16, Custom);
772 }
773
774 if (!Subtarget.hasStdExtD()) {
775 // FIXME: handle f16 fma when f64 is not legal. Using an f32 fma
776 // instruction runs into double rounding issues, so this is wrong.
777 // Normally we'd use an f64 fma, but without the D extension the f64 type
778 // is not legal. This should probably be a libcall.
779 AddPromotedToType(ISD::FMA, MVT::f16, MVT::f32);
780 AddPromotedToType(ISD::STRICT_FMA, MVT::f16, MVT::f32);
781 }
782
784
787 setCondCodeAction(FPCCToExpand, MVT::f16, Expand);
791
793 ISD::FNEARBYINT, MVT::f16,
794 Subtarget.hasStdExtZfh() && Subtarget.hasStdExtZfa() ? Legal : Promote);
799 MVT::f16, Promote);
800
801 // FIXME: Need to promote f16 STRICT_* to f32 libcalls, but we don't have
802 // complete support for all operations in LegalizeDAG.
807 MVT::f16, Promote);
808
809 // We need to custom promote this.
810 if (Subtarget.is64Bit())
812 }
813
814 if (Subtarget.hasStdExtFOrZfinx()) {
815 if (Subtarget.hasStdExtF())
817 setOperationAction(FPLegalNodeTypes, MVT::f32, Legal);
818 setOperationAction(FPRndMode, MVT::f32,
819 Subtarget.hasStdExtZfa() ? Legal : Custom);
820 setCondCodeAction(FPCCToExpand, MVT::f32, Expand);
824 setOperationAction(FPOpToExpand, MVT::f32, Expand);
825 setOperationAction(FPOpToLibCall, MVT::f32, LibCall);
826 setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);
827 setTruncStoreAction(MVT::f32, MVT::f16, Expand);
828 setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::bf16, Expand);
829 setTruncStoreAction(MVT::f32, MVT::bf16, Expand);
833 Subtarget.isSoftFPABI() ? LibCall : Custom);
838
839 if (Subtarget.hasStdExtZfa()) {
843 } else {
845 }
846 }
847
848 if (Subtarget.hasStdExtFOrZfinx() && Subtarget.is64Bit())
850
851 if (Subtarget.hasStdExtDOrZdinx()) {
852 if (Subtarget.hasStdExtD())
854 setOperationAction(FPLegalNodeTypes, MVT::f64, Legal);
855
856 if (!Subtarget.is64Bit())
858
859 if (Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
860 !Subtarget.is64Bit()) {
863 }
864
865 if (Subtarget.hasStdExtZfa()) {
867 setOperationAction(FPRndMode, MVT::f64, Legal);
870 } else {
871 if (Subtarget.is64Bit())
872 setOperationAction(FPRndMode, MVT::f64, Custom);
873
875 }
876
879 setCondCodeAction(FPCCToExpand, MVT::f64, Expand);
883 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
884 setTruncStoreAction(MVT::f64, MVT::f32, Expand);
885 setOperationAction(FPOpToExpand, MVT::f64, Expand);
886 setOperationAction(FPOpToLibCall, MVT::f64, LibCall);
887 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);
888 setTruncStoreAction(MVT::f64, MVT::f16, Expand);
889 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::bf16, Expand);
890 setTruncStoreAction(MVT::f64, MVT::bf16, Expand);
894 Subtarget.isSoftFPABI() ? LibCall : Custom);
899 }
900
901 if (Subtarget.is64Bit()) {
904 MVT::i32, Custom);
906 } else if (Subtarget.hasStdExtZfhminOrZhinxmin()) {
907 // i64 is not a legal type on RV32, so these are custom expanded in
908 // ReplaceNodeResults: f16 sources are converted to i32 and extended, other
909 // FP sources fall back to the default libcall expansion.
912 MVT::i64, Custom);
913 }
914
915 if (Subtarget.hasStdExtFOrZfinx()) {
917 Custom);
918
919 // f16/bf16 require custom handling.
921 Custom);
923 Custom);
924
933 }
934
937 XLenVT, Custom);
938
940
941 if (Subtarget.is64Bit())
943
944 // TODO: On M-mode only targets, the cycle[h]/time[h] CSR may not be present.
945 // Unfortunately this can't be determined just from the ISA naming string.
947 Subtarget.is64Bit() ? Legal : Custom);
949 Subtarget.is64Bit() ? Legal : Custom);
950
951 if (Subtarget.is64Bit()) {
954 }
955
958 if (Subtarget.is64Bit())
960
961 if (Subtarget.hasVendorXMIPSCBOP())
963 else
965
966 if (Subtarget.hasStdExtZalrsc()) {
967 setMaxAtomicSizeInBitsSupported(Subtarget.getXLen());
968 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
970 else
972 } else if (Subtarget.hasForcedAtomics()) {
973 setMaxAtomicSizeInBitsSupported(Subtarget.getXLen());
974 } else {
976 }
977
979
981
982 if (getTargetMachine().getTargetTriple().isOSLinux()) {
983 // Custom lowering of llvm.clear_cache.
985 }
986
987 if (Subtarget.hasVInstructions()) {
989
991
992 // RVV intrinsics may have illegal operands.
993 // We also need to custom legalize vmv.x.s.
996 {MVT::i8, MVT::i16}, Custom);
997 if (Subtarget.is64Bit())
999 MVT::i32, Custom);
1000 else
1002 MVT::i64, Custom);
1003
1005 MVT::Other, Custom);
1006
1007 static const unsigned IntegerVPOps[] = {
1008 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
1009 ISD::VP_UREM, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
1010 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
1011 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
1012 ISD::VP_MERGE,
1013 ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
1014 ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_POISON};
1015
1016 static const unsigned FloatingPointVPOps[] = {
1017 ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
1018 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
1019 ISD::VP_REDUCE_FMINIMUM, ISD::VP_REDUCE_FMAXIMUM};
1020
1021 static const unsigned IntegerVecReduceOps[] = {
1025
1026 static const unsigned FloatingPointVecReduceOps[] = {
1029
1030 static const unsigned FloatingPointLibCallOps[] = {
1033
1034 if (!Subtarget.is64Bit()) {
1035 // We must custom-lower certain vXi64 operations on RV32 due to the vector
1036 // element type being illegal.
1038 MVT::i64, Custom);
1039
1040 setOperationAction(IntegerVecReduceOps, MVT::i64, Custom);
1041
1042 setOperationAction({ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
1043 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
1044 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
1045 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
1046 MVT::i64, Custom);
1047 }
1048
1049 for (MVT VT : BoolVecVTs) {
1050 if (!isTypeLegal(VT))
1051 continue;
1052
1054
1055 // Mask VTs are custom-expanded into a series of standard nodes
1059 VT, Custom);
1060
1062 Custom);
1063
1066 Expand);
1067 setOperationAction(ISD::VP_MERGE, VT, Custom);
1068
1070 ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_POISON},
1071 VT, Custom);
1072
1075 Custom);
1076
1078 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1079 Custom);
1080
1081 // RVV has native int->float & float->int conversions where the
1082 // element type sizes are within one power-of-two of each other. Any
1083 // wider distances between type sizes have to be lowered as sequences
1084 // which progressively narrow the gap in stages.
1089 VT, Custom);
1091 Custom);
1092
1093 // Expand all extending loads to types larger than this, and truncating
1094 // stores from types larger than this.
1096 setTruncStoreAction(VT, OtherVT, Expand);
1098 OtherVT, Expand);
1099 }
1100
1103 {2, 3, 4, 5, 6, 7, 8}, VT, Custom);
1104
1106
1107 setOperationAction(ISD::EXPERIMENTAL_VP_SPLICE, VT, Custom);
1108 setOperationAction(ISD::EXPERIMENTAL_VP_REVERSE, VT, Custom);
1109
1112 MVT::getVectorVT(MVT::i8, VT.getVectorElementCount()));
1113 }
1114
1115 for (MVT VT : IntVecVTs) {
1116 if (!isTypeLegal(VT))
1117 continue;
1118
1121
1122 // Vectors implement MULHS/MULHU.
1124
1125 // nxvXi64 MULHS/MULHU requires the V extension instead of Zve64*.
1126 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
1128
1130 Legal);
1131
1132 if (Subtarget.hasStdExtZvabd()) {
1135 } else {
1137 }
1138
1139 // Custom-lower extensions and truncations from/to mask types.
1141 VT, Custom);
1142
1143 // RVV has native int->float & float->int conversions where the
1144 // element type sizes are within one power-of-two of each other. Any
1145 // wider distances between type sizes have to be lowered as sequences
1146 // which progressively narrow the gap in stages.
1151 VT, Custom);
1153 Custom);
1157 VT, Legal);
1158
1159 // Integer VTs are lowered as a series of "RISCVISD::TRUNCATE_VECTOR_VL"
1160 // nodes which truncate by one power of two at a time.
1163 Custom);
1164
1165 // Custom-lower insert/extract operations to simplify patterns.
1167 Custom);
1168
1169 // Custom-lower reduction operations to set up the corresponding custom
1170 // nodes' operands.
1171 setOperationAction(IntegerVecReduceOps, VT, Custom);
1172
1173 setOperationAction(IntegerVPOps, VT, Custom);
1174
1176
1178 VT, Custom);
1179
1181 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1182 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1183 VT, Custom);
1184 setOperationAction(ISD::VP_LOAD_FF, VT, Custom);
1185
1188 VT, Custom);
1189
1192
1194
1196 setTruncStoreAction(VT, OtherVT, Expand);
1198 OtherVT, Expand);
1199 }
1200
1203 {2, 3, 4, 5, 6, 7, 8}, VT, Custom);
1204
1206 VT, Custom);
1207
1208 if (Subtarget.hasStdExtZvkb()) {
1210 } else {
1213 }
1214
1215 if (Subtarget.hasStdExtZvbb()) {
1217 } else {
1220
1221 // Lower CTLZ_ZERO_POISON and CTTZ_ZERO_POISON if element of VT in the
1222 // range of f32.
1223 EVT FloatVT = MVT::getVectorVT(MVT::f32, VT.getVectorElementCount());
1224 if (isTypeLegal(FloatVT)) {
1227 Custom);
1228 }
1229 }
1230
1231 if (VT.getVectorElementType() == MVT::i64) {
1232 if (Subtarget.hasStdExtZvbc())
1234 } else {
1235 if (Subtarget.hasStdExtZvbc32e()) {
1237 } else if (Subtarget.hasStdExtZvbc()) {
1238 // Promote to i64 if the lmul is small enough.
1239 // FIXME: Split if necessary to widen.
1240 // FIXME: Promote clmulh directly without legalizing to clmul first.
1241 MVT I64VecVT = MVT::getVectorVT(MVT::i64, VT.getVectorElementCount());
1242 if (isTypeLegal(I64VecVT))
1244 }
1245 }
1246
1250 VT, Legal);
1251 }
1252
1253 for (MVT VT : VecTupleVTs) {
1254 if (!isTypeLegal(VT))
1255 continue;
1256
1258 }
1259
1260 // Expand various CCs to best match the RVV ISA, which natively supports UNE
1261 // but no other unordered comparisons, and supports all ordered comparisons
1262 // except ONE. Additionally, we expand GT,OGT,GE,OGE for optimization
1263 // purposes; they are expanded to their swapped-operand CCs (LT,OLT,LE,OLE),
1264 // and we pattern-match those back to the "original", swapping operands once
1265 // more. This way we catch both operations and both "vf" and "fv" forms with
1266 // fewer patterns.
1267 static const ISD::CondCode VFPCCToExpand[] = {
1271 };
1272
1273 // TODO: support more ops.
1274 static const unsigned ZvfhminZvfbfminPromoteOps[] = {
1279 ISD::FADD,
1280 ISD::FSUB,
1281 ISD::FMUL,
1282 ISD::FMA,
1283 ISD::FDIV,
1284 ISD::FSQRT,
1285 ISD::FCEIL,
1290 ISD::FRINT,
1293 ISD::SETCC,
1308
1309 // TODO: Make more of these ops legal.
1310 static const unsigned ZvfbfaPromoteOps[] = {ISD::FDIV,
1311 ISD::FSQRT,
1312 ISD::FCEIL,
1317 ISD::FRINT,
1326
1327 // TODO: support more vp ops.
1328 static const unsigned ZvfhminZvfbfminPromoteVPOps[] = {
1329 ISD::VP_REDUCE_FMIN,
1330 ISD::VP_REDUCE_FMAX,
1331 ISD::VP_REDUCE_FMINIMUM,
1332 ISD::VP_REDUCE_FMAXIMUM};
1333
1334 // Sets common operation actions on RVV floating-point vector types.
1335 const auto SetCommonVFPActions = [&](MVT VT) {
1337 // RVV has native FP_ROUND & FP_EXTEND conversions where the element type
1338 // sizes are within one power-of-two of each other. Therefore conversions
1339 // between vXf16 and vXf64 must be lowered as sequences which convert via
1340 // vXf32.
1344 // Custom-lower insert/extract operations to simplify patterns.
1346 Custom);
1347 // Expand various condition codes (explained above).
1348 setCondCodeAction(VFPCCToExpand, VT, Expand);
1349
1352 Legal);
1354
1358 VT, Custom);
1359
1360 setOperationAction(FloatingPointVecReduceOps, VT, Custom);
1361
1362 // Expand FP operations that need libcalls.
1363 setOperationAction(FloatingPointLibCallOps, VT, Expand);
1364
1366
1368
1370
1372 VT, Custom);
1373
1375 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1376 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1377 VT, Custom);
1378 setOperationAction(ISD::VP_LOAD_FF, VT, Custom);
1379
1382
1385 VT, Custom);
1386
1389 {2, 3, 4, 5, 6, 7, 8}, VT, Custom);
1390
1393 VT, Custom);
1394 setOperationAction(ISD::EXPERIMENTAL_VP_SPLICE, VT, Custom);
1395 setOperationAction(ISD::EXPERIMENTAL_VP_REVERSE, VT, Custom);
1396
1397 setOperationAction(FloatingPointVPOps, VT, Custom);
1398
1400 Custom);
1403 VT, Legal);
1408 VT, Custom);
1409
1411 };
1412
1413 // Sets common extload/truncstore actions on RVV floating-point vector
1414 // types.
1415 const auto SetCommonVFPExtLoadTruncStoreActions =
1416 [&](MVT VT, ArrayRef<MVT::SimpleValueType> SmallerVTs) {
1417 for (auto SmallVT : SmallerVTs) {
1418 setTruncStoreAction(VT, SmallVT, Expand);
1419 setLoadExtAction(ISD::EXTLOAD, VT, SmallVT, Expand);
1420 }
1421 };
1422
1423 // Sets common actions for f16 and bf16 for when there's only
1424 // zvfhmin/zvfbfmin and we need to promote to f32 for most operations.
1425 const auto SetCommonPromoteToF32Actions = [&](MVT VT) {
1428 Custom);
1431 setOperationAction({ISD::VP_MERGE, ISD::SELECT}, VT,
1432 Custom);
1438 VT, Custom);
1441 {2, 3, 4, 5, 6, 7, 8}, VT, Custom);
1442 setOperationAction(ISD::EXPERIMENTAL_VP_SPLICE, VT, Custom);
1443 setOperationAction(ISD::EXPERIMENTAL_VP_REVERSE, VT, Custom);
1444 MVT EltVT = VT.getVectorElementType();
1445 if (isTypeLegal(EltVT))
1447 VT, Custom);
1448 else
1451 ISD::MGATHER, ISD::MSCATTER, ISD::VP_LOAD,
1452 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1453 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1454 ISD::VP_SCATTER},
1455 VT, Custom);
1456 setOperationAction(ISD::VP_LOAD_FF, VT, Custom);
1457
1461
1462 // Expand FP operations that need libcalls.
1463 setOperationAction(FloatingPointLibCallOps, VT, Expand);
1464
1466
1467 // Custom split nxv32[b]f16 since nxv32[b]f32 is not legal.
1468 if (getLMUL(VT) == RISCVVType::LMUL_8) {
1469 setOperationAction(ZvfhminZvfbfminPromoteOps, VT, Custom);
1470 setOperationAction(ZvfhminZvfbfminPromoteVPOps, VT, Custom);
1471 } else {
1472 MVT F32VecVT = MVT::getVectorVT(MVT::f32, VT.getVectorElementCount());
1473 setOperationPromotedToType(ZvfhminZvfbfminPromoteOps, VT, F32VecVT);
1474 setOperationPromotedToType(ZvfhminZvfbfminPromoteVPOps, VT, F32VecVT);
1475 }
1476 };
1477
1478 // Sets common actions for zvfbfa, some of instructions are supported
1479 // natively so that we don't need to promote them.
1480 const auto SetZvfbfaActions = [&](MVT VT) {
1483 Custom);
1486 setOperationAction({ISD::VP_MERGE, ISD::SELECT}, VT,
1487 Custom);
1494 VT, Custom);
1497 {2, 3, 4, 5, 6, 7, 8}, VT, Custom);
1500 Legal);
1503 setOperationAction(ISD::EXPERIMENTAL_VP_SPLICE, VT, Custom);
1504 setOperationAction(ISD::EXPERIMENTAL_VP_REVERSE, VT, Custom);
1505
1510 VT, Legal);
1511 setCondCodeAction(VFPCCToExpand, VT, Expand);
1512
1514 ISD::MGATHER, ISD::MSCATTER, ISD::VP_LOAD,
1515 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1516 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1517 ISD::VP_SCATTER},
1518 VT, Custom);
1519 setOperationAction(ISD::VP_LOAD_FF, VT, Custom);
1520
1521 // Expand FP operations that need libcalls.
1522 setOperationAction(FloatingPointLibCallOps, VT, Expand);
1523
1525
1526 // Custom split nxv32[b]f16 since nxv32[b]f32 is not legal.
1527 if (getLMUL(VT) == RISCVVType::LMUL_8) {
1528 setOperationAction(ZvfbfaPromoteOps, VT, Custom);
1529 setOperationAction(ZvfhminZvfbfminPromoteVPOps, VT, Custom);
1530 } else {
1531 MVT F32VecVT = MVT::getVectorVT(MVT::f32, VT.getVectorElementCount());
1532 setOperationPromotedToType(ZvfbfaPromoteOps, VT, F32VecVT);
1533 setOperationPromotedToType(ZvfhminZvfbfminPromoteVPOps, VT, F32VecVT);
1534 }
1535 };
1536
1537 if (Subtarget.hasVInstructionsF16()) {
1538 for (MVT VT : F16VecVTs) {
1539 if (!isTypeLegal(VT))
1540 continue;
1541 SetCommonVFPActions(VT);
1542 }
1543 } else if (Subtarget.hasVInstructionsF16Minimal()) {
1544 for (MVT VT : F16VecVTs) {
1545 if (!isTypeLegal(VT))
1546 continue;
1547 SetCommonPromoteToF32Actions(VT);
1548 }
1549 }
1550
1551 if (Subtarget.hasVInstructionsBF16()) {
1552 for (MVT VT : BF16VecVTs) {
1553 if (!isTypeLegal(VT))
1554 continue;
1555 SetZvfbfaActions(VT);
1556 }
1557 } else if (Subtarget.hasVInstructionsBF16Minimal()) {
1558 for (MVT VT : BF16VecVTs) {
1559 if (!isTypeLegal(VT))
1560 continue;
1561 SetCommonPromoteToF32Actions(VT);
1562 }
1563 }
1564
1565 if (Subtarget.hasStdExtZvfofp8min()) {
1566 for (MVT VT : BF16VecVTs) {
1567 if (!isTypeLegal(VT))
1568 continue;
1570 }
1571 }
1572
1573 if (Subtarget.hasVInstructionsF32()) {
1574 for (MVT VT : F32VecVTs) {
1575 if (!isTypeLegal(VT))
1576 continue;
1577 SetCommonVFPActions(VT);
1578 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1579 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1580 }
1581 }
1582
1583 if (Subtarget.hasVInstructionsF64()) {
1584 for (MVT VT : F64VecVTs) {
1585 if (!isTypeLegal(VT))
1586 continue;
1587 SetCommonVFPActions(VT);
1588 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1589 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1590 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1591 }
1592 }
1593
1594 if (Subtarget.useRVVForFixedLengthVectors()) {
1596 if (!useRVVForFixedLengthVectorVT(VT))
1597 continue;
1598
1599 // By default everything must be expanded.
1600 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op)
1603 setTruncStoreAction(VT, OtherVT, Expand);
1605 OtherVT, Expand);
1606 }
1607
1608 // Custom lower fixed vector undefs to scalable vector undefs to avoid
1609 // expansion to a build_vector of 0s.
1611
1612 // We use EXTRACT_SUBVECTOR as a "cast" from scalable to fixed.
1614 Custom);
1615
1618 Custom);
1619
1622 {2, 3, 4, 5, 6, 7, 8}, VT, Custom);
1623
1625 VT, Custom);
1626
1628
1630
1632
1634
1637 Custom);
1638
1640
1643 Custom);
1644
1646 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1647 Custom);
1648
1650 {
1659 },
1660 VT, Custom);
1662 Custom);
1663
1665
1666 // Operations below are different for between masks and other vectors.
1667 if (VT.getVectorElementType() == MVT::i1) {
1669
1670 setOperationAction(ISD::VP_MERGE, VT, Custom);
1671
1672 setOperationAction(ISD::EXPERIMENTAL_VP_SPLICE, VT, Custom);
1673 setOperationAction(ISD::EXPERIMENTAL_VP_REVERSE, VT, Custom);
1674
1676 Custom);
1677 continue;
1678 }
1679
1680 // Make SPLAT_VECTOR Legal so DAGCombine will convert splat vectors to
1681 // it before type legalization for i64 vectors on RV32. It will then be
1682 // type legalized to SPLAT_VECTOR_PARTS which we need to Custom handle.
1683 // FIXME: Use SPLAT_VECTOR for all types? DAGCombine probably needs
1684 // improvements first.
1685 if (!Subtarget.is64Bit() && VT.getVectorElementType() == MVT::i64) {
1688
1689 // Lower BUILD_VECTOR with i64 type to VID on RV32 if possible.
1691 }
1692
1695
1696 setOperationAction({ISD::VP_LOAD, ISD::VP_STORE,
1697 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1698 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1699 ISD::VP_SCATTER},
1700 VT, Custom);
1701 setOperationAction(ISD::VP_LOAD_FF, VT, Custom);
1702
1706 VT, Custom);
1707
1710
1712
1713 // vXi64 MULHS/MULHU requires the V extension instead of Zve64*.
1714 if (VT.getVectorElementType() != MVT::i64 || Subtarget.hasStdExtV())
1716
1720 VT, Custom);
1721
1723
1726
1727 // Custom-lower reduction operations to set up the corresponding custom
1728 // nodes' operands.
1732 VT, Custom);
1733
1734 setOperationAction(IntegerVPOps, VT, Custom);
1735
1736 if (Subtarget.hasStdExtZvkb())
1738
1739 if (Subtarget.hasStdExtZvbb()) {
1742 VT, Custom);
1743 } else {
1744 // Lower CTLZ_ZERO_POISON and CTTZ_ZERO_POISON if element of VT in the
1745 // range of f32.
1746 EVT FloatVT = MVT::getVectorVT(MVT::f32, VT.getVectorElementCount());
1747 if (isTypeLegal(FloatVT))
1750 Custom);
1751 }
1752
1753 if (VT.getVectorElementType() == MVT::i64) {
1754 if (Subtarget.hasStdExtZvbc())
1756 } else {
1757 if (Subtarget.hasStdExtZvbc32e()) {
1759 } else if (Subtarget.hasStdExtZvbc()) {
1760 // Promote to i64 as is done for scalable vectors.
1761 MVT I64VecVT =
1763 if (I64VecVT.isValid() && useRVVForFixedLengthVectorVT(I64VecVT))
1765 }
1766 }
1767
1771 VT, Custom);
1772 }
1773
1775 // There are no extending loads or truncating stores.
1776 for (MVT InnerVT : MVT::fp_fixedlen_vector_valuetypes()) {
1777 setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Expand);
1778 setTruncStoreAction(VT, InnerVT, Expand);
1779 }
1780
1781 if (!useRVVForFixedLengthVectorVT(VT))
1782 continue;
1783
1784 // By default everything must be expanded.
1785 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op)
1787
1788 // Custom lower fixed vector undefs to scalable vector undefs to avoid
1789 // expansion to a build_vector of 0s.
1791
1796 VT, Custom);
1797 setOperationAction(ISD::EXPERIMENTAL_VP_SPLICE, VT, Custom);
1798 setOperationAction(ISD::EXPERIMENTAL_VP_REVERSE, VT, Custom);
1799
1802 {2, 3, 4, 5, 6, 7, 8}, VT, Custom);
1803
1806 VT, Custom);
1807 setOperationAction({ISD::VP_LOAD, ISD::VP_STORE, ISD::VP_GATHER,
1808 ISD::VP_SCATTER, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1809 ISD::EXPERIMENTAL_VP_STRIDED_STORE},
1810 VT, Custom);
1811 setOperationAction(ISD::VP_LOAD_FF, VT, Custom);
1812
1815 Custom);
1816
1818
1819 if (VT.getVectorElementType() == MVT::f16 &&
1820 !Subtarget.hasVInstructionsF16()) {
1822 {ISD::VP_MERGE, ISD::VSELECT, ISD::SELECT}, VT,
1823 Custom);
1826 if (Subtarget.hasStdExtZfhmin()) {
1828 } else {
1829 // We need to custom legalize f16 build vectors if Zfhmin isn't
1830 // available.
1832 }
1836 MVT F32VecVT = MVT::getVectorVT(MVT::f32, VT.getVectorElementCount());
1837 // Don't promote f16 vector operations to f32 if f32 vector type is
1838 // not legal.
1839 // Custom lower maximum LMUL case to split to 2 half LMUL operations.
1840 // TODO: Support more operations.
1841 if (!isTypeLegal(F32VecVT)) {
1845 VT, Custom);
1847 continue;
1848 }
1849 setOperationPromotedToType(ZvfhminZvfbfminPromoteOps, VT, F32VecVT);
1850 setOperationPromotedToType(ZvfhminZvfbfminPromoteVPOps, VT, F32VecVT);
1851 continue;
1852 }
1853
1854 if (VT.getVectorElementType() == MVT::bf16) {
1857 if (Subtarget.hasStdExtZvfofp8min())
1859 if (Subtarget.hasStdExtZfbfmin()) {
1861 } else {
1862 // We need to custom legalize bf16 build vectors if Zfbfmin isn't
1863 // available.
1865 }
1866 if (Subtarget.hasVInstructionsBF16()) {
1868 setCondCodeAction(VFPCCToExpand, VT, Expand);
1869 }
1871 {ISD::VP_MERGE, ISD::VSELECT, ISD::SELECT}, VT,
1872 Custom);
1873 MVT F32VecVT = MVT::getVectorVT(MVT::f32, VT.getVectorElementCount());
1874 // Don't promote bf16 vector operations to f32 if f32 vector type is
1875 // not legal.
1876 // Custom lower maximum LMUL case to split to 2 half LMUL operations.
1877 // TODO: Support more operations.
1878 if (!isTypeLegal(F32VecVT)) {
1882 VT, Custom);
1884 continue;
1885 }
1886
1887 if (Subtarget.hasVInstructionsBF16())
1888 setOperationPromotedToType(ZvfbfaPromoteOps, VT, F32VecVT);
1889 else
1890 setOperationPromotedToType(ZvfhminZvfbfminPromoteOps, VT, F32VecVT);
1891 setOperationPromotedToType(ZvfhminZvfbfminPromoteVPOps, VT, F32VecVT);
1892 continue;
1893 }
1894
1896 Custom);
1897
1903 VT, Custom);
1904
1909 VT, Custom);
1910
1911 setCondCodeAction(VFPCCToExpand, VT, Expand);
1912
1915
1916 setOperationAction(FloatingPointVecReduceOps, VT, Custom);
1917
1918 setOperationAction(FloatingPointVPOps, VT, Custom);
1919
1926 VT, Custom);
1927 }
1928
1929 // Custom-legalize bitcasts from fixed-length vectors to scalar types.
1930 setOperationAction(ISD::BITCAST, {MVT::i8, MVT::i16, MVT::i32}, Custom);
1931 if (Subtarget.is64Bit())
1933 if (Subtarget.hasStdExtZfhminOrZhinxmin())
1935 if (Subtarget.hasStdExtZfbfmin())
1937 if (Subtarget.hasStdExtFOrZfinx())
1939 if (Subtarget.hasStdExtDOrZdinx())
1941 }
1942 }
1943
1944 if (Subtarget.hasStdExtZaamo())
1946
1947 if (Subtarget.hasForcedAtomics()) {
1948 // Force __sync libcalls to be emitted for atomic rmw/cas operations.
1954 XLenVT, LibCall);
1955 }
1956
1957 if (Subtarget.hasVendorXTHeadMemIdx()) {
1958 for (unsigned im : {ISD::PRE_INC, ISD::POST_INC}) {
1959 setIndexedLoadAction(im, MVT::i8, Legal);
1960 setIndexedStoreAction(im, MVT::i8, Legal);
1961 setIndexedLoadAction(im, MVT::i16, Legal);
1962 setIndexedStoreAction(im, MVT::i16, Legal);
1963 setIndexedLoadAction(im, MVT::i32, Legal);
1964 setIndexedStoreAction(im, MVT::i32, Legal);
1965
1966 if (Subtarget.is64Bit()) {
1967 setIndexedLoadAction(im, MVT::i64, Legal);
1968 setIndexedStoreAction(im, MVT::i64, Legal);
1969 }
1970 }
1971 }
1972
1973 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
1977
1981 }
1982
1983 // zve32x is broken for partial_reduce_umla, but let's not make it worse.
1984 if (Subtarget.hasStdExtZvdot4a8i() && Subtarget.getELen() >= 64) {
1985 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
1988 setPartialReduceMLAAction(MLAOps, MVT::nxv1i32, MVT::nxv4i8, Custom);
1989 setPartialReduceMLAAction(MLAOps, MVT::nxv2i32, MVT::nxv8i8, Custom);
1990 setPartialReduceMLAAction(MLAOps, MVT::nxv4i32, MVT::nxv16i8, Custom);
1991 setPartialReduceMLAAction(MLAOps, MVT::nxv8i32, MVT::nxv32i8, Custom);
1992 setPartialReduceMLAAction(MLAOps, MVT::nxv16i32, MVT::nxv64i8, Custom);
1993
1994 // An i64 accumulator is handled by performing an i32 vdot4a* and widening
1995 // the result to i64 (see lowerPARTIAL_REDUCE_MLA).
1996 setPartialReduceMLAAction(MLAOps, MVT::nxv1i64, MVT::nxv8i8, Custom);
1997 setPartialReduceMLAAction(MLAOps, MVT::nxv2i64, MVT::nxv16i8, Custom);
1998 setPartialReduceMLAAction(MLAOps, MVT::nxv4i64, MVT::nxv32i8, Custom);
1999 setPartialReduceMLAAction(MLAOps, MVT::nxv8i64, MVT::nxv64i8, Custom);
2000
2001 if (Subtarget.useRVVForFixedLengthVectors()) {
2003 if ((VT.getVectorElementType() != MVT::i32 &&
2004 VT.getVectorElementType() != MVT::i64) ||
2005 !useRVVForFixedLengthVectorVT(VT))
2006 continue;
2007 ElementCount EC = VT.getVectorElementCount();
2008 unsigned Scale = VT.getVectorElementType() == MVT::i64 ? 8 : 4;
2009 MVT ArgVT = MVT::getVectorVT(MVT::i8, EC * Scale);
2010 setPartialReduceMLAAction(MLAOps, VT, ArgVT, Custom);
2011 }
2012 }
2013 }
2014
2015 // Customize load and store operation for bf16 if zfh isn't enabled.
2016 if (Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh()) {
2017 setOperationAction(ISD::LOAD, MVT::bf16, Custom);
2019 }
2020
2021 // Function alignments.
2022 const Align FunctionAlignment(Subtarget.hasStdExtZca() ? 2 : 4);
2023 setMinFunctionAlignment(FunctionAlignment);
2024 // Set preferred alignments.
2025 setPrefFunctionAlignment(Subtarget.getPrefFunctionAlignment());
2026 setPrefLoopAlignment(Subtarget.getPrefLoopAlignment());
2027
2031 ISD::SRA});
2033
2034 if (Subtarget.hasStdExtFOrZfinx())
2036
2037 // Allow scalar min/max to be combined with vector reductions.
2038 if (Subtarget.hasVInstructions())
2040 if (Subtarget.hasVInstructions() || Subtarget.hasStdExtP())
2042
2043 if ((Subtarget.hasStdExtZbs() && Subtarget.is64Bit()) ||
2044 Subtarget.hasVInstructions() || Subtarget.hasStdExtP())
2046
2047 if (Subtarget.hasStdExtZbkb())
2049
2050 if (Subtarget.hasStdExtFOrZfinx())
2053 if (Subtarget.hasVInstructions())
2058 ISD::MLOAD,
2059 ISD::VP_GATHER,
2060 ISD::VP_SCATTER,
2061 ISD::SRL,
2062 ISD::SHL,
2063 ISD::STORE,
2067 ISD::VP_STORE,
2068 ISD::EXPERIMENTAL_VP_REVERSE,
2069 ISD::SDIV,
2070 ISD::UDIV,
2071 ISD::SREM,
2072 ISD::UREM,
2074 ISD::ABS,
2076 ISD::CTPOP,
2078 ISD::FMA,
2082
2083 if (Subtarget.hasStdExtZvzip())
2085
2086 if (Subtarget.hasVendorXTHeadMemPair())
2088 if (Subtarget.useRVVForFixedLengthVectors() || Subtarget.hasStdExtP())
2090
2091 setMaxDivRemBitWidthSupported(Subtarget.is64Bit() ? 128 : 64);
2092
2093 setMaxLargeFPConvertBitWidthSupported(Subtarget.is64Bit() ? 128 : 64);
2094
2095 setJumpIsExpensive(Subtarget.isJumpExpensive());
2096
2097 // Disable strict node mutation.
2098 IsStrictFPEnabled = true;
2099 EnableExtLdPromotion = true;
2100
2101 // Let the subtarget decide if a predictable select is more expensive than the
2102 // corresponding branch. This information is used in CGP/SelectOpt to decide
2103 // when to convert selects into branches.
2104 PredictableSelectIsExpensive = Subtarget.predictableSelectIsExpensive();
2105
2106 MaxStoresPerMemsetOptSize = Subtarget.getMaxStoresPerMemset(/*OptSize=*/true);
2107 MaxStoresPerMemset = Subtarget.getMaxStoresPerMemset(/*OptSize=*/false);
2108
2109 MaxGluedStoresPerMemcpy = Subtarget.getMaxGluedStoresPerMemcpy();
2110 MaxStoresPerMemcpyOptSize = Subtarget.getMaxStoresPerMemcpy(/*OptSize=*/true);
2111 MaxStoresPerMemcpy = Subtarget.getMaxStoresPerMemcpy(/*OptSize=*/false);
2112
2114 Subtarget.getMaxStoresPerMemmove(/*OptSize=*/true);
2115 MaxStoresPerMemmove = Subtarget.getMaxStoresPerMemmove(/*OptSize=*/false);
2116
2117 MaxLoadsPerMemcmpOptSize = Subtarget.getMaxLoadsPerMemcmp(/*OptSize=*/true);
2118 MaxLoadsPerMemcmp = Subtarget.getMaxLoadsPerMemcmp(/*OptSize=*/false);
2119}
2120
2123 if (Subtarget.is64Bit() && Subtarget.hasStdExtP())
2124 if (VT == MVT::v2i16 || VT == MVT::v4i8)
2125 return TypeWidenVector;
2126
2128}
2129
2131 LLVMContext &Context,
2132 EVT VT) const {
2133 if (!VT.isVector())
2134 return getPointerTy(DL);
2135 if (Subtarget.hasVInstructions() &&
2136 (VT.isScalableVector() || Subtarget.useRVVForFixedLengthVectors()))
2137 return EVT::getVectorVT(Context, MVT::i1, VT.getVectorElementCount());
2139}
2140
2143 const Value *LHS,
2144 const Value *RHS,
2145 const Function *F) const {
2146 if (F->hasOptSize())
2148
2149 // Merging conditions eliminates a branch, so the budget we are willing to
2150 // spend eagerly computing the RHS condition should scale with how expensive a
2151 // mispredicted branch is. A branch only costs the full penalty when actually
2152 // mispredicted, so scale it down by an assumed misprediction rate (~25%).
2153 int BaseCost = Subtarget.getMispredictionPenalty() / 4;
2154 if (BrMergingBaseCostThresh.getNumOccurrences() > 1)
2155 BaseCost = BrMergingBaseCostThresh;
2156
2157 return {BaseCost, BrMergingLikelyBias, BrMergingUnlikelyBias};
2158}
2159
2161 return Subtarget.getXLenVT();
2162}
2163
2164bool RISCVTargetLowering::isProfitableToFoldVScaleAdd(SDValue N) const {
2165 return N.hasOneUse();
2166}
2167
2168// Return false if we can lower get_vector_length to a vsetvli intrinsic.
2169bool RISCVTargetLowering::shouldExpandGetVectorLength(EVT TripCountVT,
2170 unsigned VF,
2171 bool IsScalable) const {
2172 if (!Subtarget.hasVInstructions())
2173 return true;
2174
2175 if (!IsScalable)
2176 return true;
2177
2178 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.getXLenVT())
2179 return true;
2180
2181 // Don't allow VF=1 if those types are't legal.
2182 if (VF < RISCV::RVVBitsPerBlock / Subtarget.getELen())
2183 return true;
2184
2185 // VLEN=32 support is incomplete.
2186 if (Subtarget.getRealMinVLen() < RISCV::RVVBitsPerBlock)
2187 return true;
2188
2189 // The maximum VF is for the smallest element width with LMUL=8.
2190 // VF must be a power of 2.
2191 unsigned MaxVF = RISCV::RVVBytesPerBlock * 8;
2192 return VF > MaxVF || !isPowerOf2_32(VF);
2193}
2194
2197 MachineFunction &MF, unsigned Intrinsic) const {
2198 IntrinsicInfo Info;
2199 auto &DL = I.getDataLayout();
2200
2201 auto SetRVVLoadStoreInfo = [&](unsigned PtrOp, bool IsStore,
2202 bool IsUnitStrided, bool UsePtrVal = false) {
2203 Info.opc = IsStore ? ISD::INTRINSIC_VOID : ISD::INTRINSIC_W_CHAIN;
2204 // We can't use ptrVal if the intrinsic can access memory before the
2205 // pointer. This means we can't use it for strided or indexed intrinsics.
2206 if (UsePtrVal)
2207 Info.ptrVal = I.getArgOperand(PtrOp);
2208 else
2209 Info.fallbackAddressSpace =
2210 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
2211 Type *MemTy;
2212 if (IsStore) {
2213 // Store value is the first operand.
2214 MemTy = I.getArgOperand(0)->getType();
2215 } else {
2216 // Use return type. If it's segment load, return type is a struct.
2217 MemTy = I.getType();
2218 if (MemTy->isStructTy())
2219 MemTy = MemTy->getStructElementType(0);
2220 }
2221 if (!IsUnitStrided)
2222 MemTy = MemTy->getScalarType();
2223
2224 Info.memVT = getValueType(DL, MemTy);
2225 if (MemTy->isTargetExtTy()) {
2226 // RISC-V vector tuple type's alignment type should be its element type.
2227 if (cast<TargetExtType>(MemTy)->getName() == "riscv.vector.tuple")
2228 MemTy = Type::getIntNTy(
2229 MemTy->getContext(),
2230 1 << cast<ConstantInt>(I.getArgOperand(I.arg_size() - 1))
2231 ->getZExtValue());
2232 Info.align = DL.getABITypeAlign(MemTy);
2233 } else {
2234 Info.align = Align(DL.getTypeStoreSize(MemTy->getScalarType()));
2235 }
2236 Info.size = MemoryLocation::UnknownSize;
2237 Info.flags |=
2239 Infos.push_back(Info);
2240 };
2241
2242 if (I.hasMetadata(LLVMContext::MD_nontemporal))
2244
2246 switch (Intrinsic) {
2247 default:
2248 return;
2249 case Intrinsic::riscv_masked_atomicrmw_xchg:
2250 case Intrinsic::riscv_masked_atomicrmw_add:
2251 case Intrinsic::riscv_masked_atomicrmw_sub:
2252 case Intrinsic::riscv_masked_atomicrmw_nand:
2253 case Intrinsic::riscv_masked_atomicrmw_max:
2254 case Intrinsic::riscv_masked_atomicrmw_min:
2255 case Intrinsic::riscv_masked_atomicrmw_umax:
2256 case Intrinsic::riscv_masked_atomicrmw_umin:
2257 case Intrinsic::riscv_masked_cmpxchg:
2258 // riscv_masked_{atomicrmw_*,cmpxchg} intrinsics represent an emulated
2259 // narrow atomic operation. These will be expanded to an LR/SC loop that
2260 // reads/writes to/from an aligned 4 byte location. And, or, shift, etc.
2261 // will be used to modify the appropriate part of the 4 byte data and
2262 // preserve the rest.
2263 Info.opc = ISD::INTRINSIC_W_CHAIN;
2264 Info.memVT = MVT::i32;
2265 Info.ptrVal = I.getArgOperand(0);
2266 Info.offset = 0;
2267 Info.align = Align(4);
2270 Infos.push_back(Info);
2271 return;
2272 case Intrinsic::riscv_seg2_load_mask:
2273 case Intrinsic::riscv_seg3_load_mask:
2274 case Intrinsic::riscv_seg4_load_mask:
2275 case Intrinsic::riscv_seg5_load_mask:
2276 case Intrinsic::riscv_seg6_load_mask:
2277 case Intrinsic::riscv_seg7_load_mask:
2278 case Intrinsic::riscv_seg8_load_mask:
2279 case Intrinsic::riscv_sseg2_load_mask:
2280 case Intrinsic::riscv_sseg3_load_mask:
2281 case Intrinsic::riscv_sseg4_load_mask:
2282 case Intrinsic::riscv_sseg5_load_mask:
2283 case Intrinsic::riscv_sseg6_load_mask:
2284 case Intrinsic::riscv_sseg7_load_mask:
2285 case Intrinsic::riscv_sseg8_load_mask:
2286 SetRVVLoadStoreInfo(/*PtrOp*/ 0, /*IsStore*/ false,
2287 /*IsUnitStrided*/ false, /*UsePtrVal*/ true);
2288 return;
2289 case Intrinsic::riscv_seg2_store_mask:
2290 case Intrinsic::riscv_seg3_store_mask:
2291 case Intrinsic::riscv_seg4_store_mask:
2292 case Intrinsic::riscv_seg5_store_mask:
2293 case Intrinsic::riscv_seg6_store_mask:
2294 case Intrinsic::riscv_seg7_store_mask:
2295 case Intrinsic::riscv_seg8_store_mask:
2296 // Operands are (vec, ..., vec, ptr, mask, vl)
2297 SetRVVLoadStoreInfo(/*PtrOp*/ I.arg_size() - 3,
2298 /*IsStore*/ true,
2299 /*IsUnitStrided*/ false, /*UsePtrVal*/ true);
2300 return;
2301 case Intrinsic::riscv_sseg2_store_mask:
2302 case Intrinsic::riscv_sseg3_store_mask:
2303 case Intrinsic::riscv_sseg4_store_mask:
2304 case Intrinsic::riscv_sseg5_store_mask:
2305 case Intrinsic::riscv_sseg6_store_mask:
2306 case Intrinsic::riscv_sseg7_store_mask:
2307 case Intrinsic::riscv_sseg8_store_mask:
2308 // Operands are (vec, ..., vec, ptr, offset, mask, vl)
2309 SetRVVLoadStoreInfo(/*PtrOp*/ I.arg_size() - 4,
2310 /*IsStore*/ true,
2311 /*IsUnitStrided*/ false, /*UsePtrVal*/ true);
2312 return;
2313 case Intrinsic::riscv_vlm:
2314 SetRVVLoadStoreInfo(/*PtrOp*/ 0,
2315 /*IsStore*/ false,
2316 /*IsUnitStrided*/ true,
2317 /*UsePtrVal*/ true);
2318 return;
2319 case Intrinsic::riscv_vle:
2320 case Intrinsic::riscv_vle_mask:
2321 case Intrinsic::riscv_vleff:
2322 case Intrinsic::riscv_vleff_mask:
2323 SetRVVLoadStoreInfo(/*PtrOp*/ 1,
2324 /*IsStore*/ false,
2325 /*IsUnitStrided*/ true,
2326 /*UsePtrVal*/ true);
2327 return;
2328 case Intrinsic::riscv_vsm:
2329 case Intrinsic::riscv_vse:
2330 case Intrinsic::riscv_vse_mask:
2331 SetRVVLoadStoreInfo(/*PtrOp*/ 1,
2332 /*IsStore*/ true,
2333 /*IsUnitStrided*/ true,
2334 /*UsePtrVal*/ true);
2335 return;
2336 case Intrinsic::riscv_vlse:
2337 case Intrinsic::riscv_vlse_mask:
2338 case Intrinsic::riscv_vloxei:
2339 case Intrinsic::riscv_vloxei_mask:
2340 case Intrinsic::riscv_vluxei:
2341 case Intrinsic::riscv_vluxei_mask:
2342 SetRVVLoadStoreInfo(/*PtrOp*/ 1,
2343 /*IsStore*/ false,
2344 /*IsUnitStrided*/ false);
2345 return;
2346 case Intrinsic::riscv_vsse:
2347 case Intrinsic::riscv_vsse_mask:
2348 case Intrinsic::riscv_vsoxei:
2349 case Intrinsic::riscv_vsoxei_mask:
2350 case Intrinsic::riscv_vsuxei:
2351 case Intrinsic::riscv_vsuxei_mask:
2352 SetRVVLoadStoreInfo(/*PtrOp*/ 1,
2353 /*IsStore*/ true,
2354 /*IsUnitStrided*/ false);
2355 return;
2356 case Intrinsic::riscv_vlseg2:
2357 case Intrinsic::riscv_vlseg3:
2358 case Intrinsic::riscv_vlseg4:
2359 case Intrinsic::riscv_vlseg5:
2360 case Intrinsic::riscv_vlseg6:
2361 case Intrinsic::riscv_vlseg7:
2362 case Intrinsic::riscv_vlseg8:
2363 case Intrinsic::riscv_vlseg2ff:
2364 case Intrinsic::riscv_vlseg3ff:
2365 case Intrinsic::riscv_vlseg4ff:
2366 case Intrinsic::riscv_vlseg5ff:
2367 case Intrinsic::riscv_vlseg6ff:
2368 case Intrinsic::riscv_vlseg7ff:
2369 case Intrinsic::riscv_vlseg8ff:
2370 SetRVVLoadStoreInfo(/*PtrOp*/ I.arg_size() - 3,
2371 /*IsStore*/ false,
2372 /*IsUnitStrided*/ false, /*UsePtrVal*/ true);
2373 return;
2374 case Intrinsic::riscv_vlseg2_mask:
2375 case Intrinsic::riscv_vlseg3_mask:
2376 case Intrinsic::riscv_vlseg4_mask:
2377 case Intrinsic::riscv_vlseg5_mask:
2378 case Intrinsic::riscv_vlseg6_mask:
2379 case Intrinsic::riscv_vlseg7_mask:
2380 case Intrinsic::riscv_vlseg8_mask:
2381 case Intrinsic::riscv_vlseg2ff_mask:
2382 case Intrinsic::riscv_vlseg3ff_mask:
2383 case Intrinsic::riscv_vlseg4ff_mask:
2384 case Intrinsic::riscv_vlseg5ff_mask:
2385 case Intrinsic::riscv_vlseg6ff_mask:
2386 case Intrinsic::riscv_vlseg7ff_mask:
2387 case Intrinsic::riscv_vlseg8ff_mask:
2388 SetRVVLoadStoreInfo(/*PtrOp*/ I.arg_size() - 5,
2389 /*IsStore*/ false,
2390 /*IsUnitStrided*/ false, /*UsePtrVal*/ true);
2391 return;
2392 case Intrinsic::riscv_vlsseg2:
2393 case Intrinsic::riscv_vlsseg3:
2394 case Intrinsic::riscv_vlsseg4:
2395 case Intrinsic::riscv_vlsseg5:
2396 case Intrinsic::riscv_vlsseg6:
2397 case Intrinsic::riscv_vlsseg7:
2398 case Intrinsic::riscv_vlsseg8:
2399 case Intrinsic::riscv_vloxseg2:
2400 case Intrinsic::riscv_vloxseg3:
2401 case Intrinsic::riscv_vloxseg4:
2402 case Intrinsic::riscv_vloxseg5:
2403 case Intrinsic::riscv_vloxseg6:
2404 case Intrinsic::riscv_vloxseg7:
2405 case Intrinsic::riscv_vloxseg8:
2406 case Intrinsic::riscv_vluxseg2:
2407 case Intrinsic::riscv_vluxseg3:
2408 case Intrinsic::riscv_vluxseg4:
2409 case Intrinsic::riscv_vluxseg5:
2410 case Intrinsic::riscv_vluxseg6:
2411 case Intrinsic::riscv_vluxseg7:
2412 case Intrinsic::riscv_vluxseg8:
2413 SetRVVLoadStoreInfo(/*PtrOp*/ I.arg_size() - 4,
2414 /*IsStore*/ false,
2415 /*IsUnitStrided*/ false);
2416 return;
2417 case Intrinsic::riscv_vlsseg2_mask:
2418 case Intrinsic::riscv_vlsseg3_mask:
2419 case Intrinsic::riscv_vlsseg4_mask:
2420 case Intrinsic::riscv_vlsseg5_mask:
2421 case Intrinsic::riscv_vlsseg6_mask:
2422 case Intrinsic::riscv_vlsseg7_mask:
2423 case Intrinsic::riscv_vlsseg8_mask:
2424 case Intrinsic::riscv_vloxseg2_mask:
2425 case Intrinsic::riscv_vloxseg3_mask:
2426 case Intrinsic::riscv_vloxseg4_mask:
2427 case Intrinsic::riscv_vloxseg5_mask:
2428 case Intrinsic::riscv_vloxseg6_mask:
2429 case Intrinsic::riscv_vloxseg7_mask:
2430 case Intrinsic::riscv_vloxseg8_mask:
2431 case Intrinsic::riscv_vluxseg2_mask:
2432 case Intrinsic::riscv_vluxseg3_mask:
2433 case Intrinsic::riscv_vluxseg4_mask:
2434 case Intrinsic::riscv_vluxseg5_mask:
2435 case Intrinsic::riscv_vluxseg6_mask:
2436 case Intrinsic::riscv_vluxseg7_mask:
2437 case Intrinsic::riscv_vluxseg8_mask:
2438 SetRVVLoadStoreInfo(/*PtrOp*/ I.arg_size() - 6,
2439 /*IsStore*/ false,
2440 /*IsUnitStrided*/ false);
2441 return;
2442 case Intrinsic::riscv_vsseg2:
2443 case Intrinsic::riscv_vsseg3:
2444 case Intrinsic::riscv_vsseg4:
2445 case Intrinsic::riscv_vsseg5:
2446 case Intrinsic::riscv_vsseg6:
2447 case Intrinsic::riscv_vsseg7:
2448 case Intrinsic::riscv_vsseg8:
2449 SetRVVLoadStoreInfo(/*PtrOp*/ I.arg_size() - 3,
2450 /*IsStore*/ true,
2451 /*IsUnitStrided*/ false);
2452 return;
2453 case Intrinsic::riscv_vsseg2_mask:
2454 case Intrinsic::riscv_vsseg3_mask:
2455 case Intrinsic::riscv_vsseg4_mask:
2456 case Intrinsic::riscv_vsseg5_mask:
2457 case Intrinsic::riscv_vsseg6_mask:
2458 case Intrinsic::riscv_vsseg7_mask:
2459 case Intrinsic::riscv_vsseg8_mask:
2460 SetRVVLoadStoreInfo(/*PtrOp*/ I.arg_size() - 4,
2461 /*IsStore*/ true,
2462 /*IsUnitStrided*/ false);
2463 return;
2464 case Intrinsic::riscv_vssseg2:
2465 case Intrinsic::riscv_vssseg3:
2466 case Intrinsic::riscv_vssseg4:
2467 case Intrinsic::riscv_vssseg5:
2468 case Intrinsic::riscv_vssseg6:
2469 case Intrinsic::riscv_vssseg7:
2470 case Intrinsic::riscv_vssseg8:
2471 case Intrinsic::riscv_vsoxseg2:
2472 case Intrinsic::riscv_vsoxseg3:
2473 case Intrinsic::riscv_vsoxseg4:
2474 case Intrinsic::riscv_vsoxseg5:
2475 case Intrinsic::riscv_vsoxseg6:
2476 case Intrinsic::riscv_vsoxseg7:
2477 case Intrinsic::riscv_vsoxseg8:
2478 case Intrinsic::riscv_vsuxseg2:
2479 case Intrinsic::riscv_vsuxseg3:
2480 case Intrinsic::riscv_vsuxseg4:
2481 case Intrinsic::riscv_vsuxseg5:
2482 case Intrinsic::riscv_vsuxseg6:
2483 case Intrinsic::riscv_vsuxseg7:
2484 case Intrinsic::riscv_vsuxseg8:
2485 SetRVVLoadStoreInfo(/*PtrOp*/ I.arg_size() - 4,
2486 /*IsStore*/ true,
2487 /*IsUnitStrided*/ false);
2488 return;
2489 case Intrinsic::riscv_vssseg2_mask:
2490 case Intrinsic::riscv_vssseg3_mask:
2491 case Intrinsic::riscv_vssseg4_mask:
2492 case Intrinsic::riscv_vssseg5_mask:
2493 case Intrinsic::riscv_vssseg6_mask:
2494 case Intrinsic::riscv_vssseg7_mask:
2495 case Intrinsic::riscv_vssseg8_mask:
2496 case Intrinsic::riscv_vsoxseg2_mask:
2497 case Intrinsic::riscv_vsoxseg3_mask:
2498 case Intrinsic::riscv_vsoxseg4_mask:
2499 case Intrinsic::riscv_vsoxseg5_mask:
2500 case Intrinsic::riscv_vsoxseg6_mask:
2501 case Intrinsic::riscv_vsoxseg7_mask:
2502 case Intrinsic::riscv_vsoxseg8_mask:
2503 case Intrinsic::riscv_vsuxseg2_mask:
2504 case Intrinsic::riscv_vsuxseg3_mask:
2505 case Intrinsic::riscv_vsuxseg4_mask:
2506 case Intrinsic::riscv_vsuxseg5_mask:
2507 case Intrinsic::riscv_vsuxseg6_mask:
2508 case Intrinsic::riscv_vsuxseg7_mask:
2509 case Intrinsic::riscv_vsuxseg8_mask:
2510 SetRVVLoadStoreInfo(/*PtrOp*/ I.arg_size() - 5,
2511 /*IsStore*/ true,
2512 /*IsUnitStrided*/ false);
2513 return;
2514 case Intrinsic::riscv_sf_vlte8:
2515 case Intrinsic::riscv_sf_vlte16:
2516 case Intrinsic::riscv_sf_vlte32:
2517 case Intrinsic::riscv_sf_vlte64:
2518 Info.opc = ISD::INTRINSIC_VOID;
2519 Info.ptrVal = I.getArgOperand(1);
2520 switch (Intrinsic) {
2521 case Intrinsic::riscv_sf_vlte8:
2522 Info.memVT = MVT::i8;
2523 Info.align = Align(1);
2524 break;
2525 case Intrinsic::riscv_sf_vlte16:
2526 Info.memVT = MVT::i16;
2527 Info.align = Align(2);
2528 break;
2529 case Intrinsic::riscv_sf_vlte32:
2530 Info.memVT = MVT::i32;
2531 Info.align = Align(4);
2532 break;
2533 case Intrinsic::riscv_sf_vlte64:
2534 Info.memVT = MVT::i64;
2535 Info.align = Align(8);
2536 break;
2537 }
2538 Info.size = MemoryLocation::UnknownSize;
2539 Info.flags |= MachineMemOperand::MOLoad;
2540 Infos.push_back(Info);
2541 return;
2542 case Intrinsic::riscv_sf_vste8:
2543 case Intrinsic::riscv_sf_vste16:
2544 case Intrinsic::riscv_sf_vste32:
2545 case Intrinsic::riscv_sf_vste64:
2546 Info.opc = ISD::INTRINSIC_VOID;
2547 Info.ptrVal = I.getArgOperand(1);
2548 switch (Intrinsic) {
2549 case Intrinsic::riscv_sf_vste8:
2550 Info.memVT = MVT::i8;
2551 Info.align = Align(1);
2552 break;
2553 case Intrinsic::riscv_sf_vste16:
2554 Info.memVT = MVT::i16;
2555 Info.align = Align(2);
2556 break;
2557 case Intrinsic::riscv_sf_vste32:
2558 Info.memVT = MVT::i32;
2559 Info.align = Align(4);
2560 break;
2561 case Intrinsic::riscv_sf_vste64:
2562 Info.memVT = MVT::i64;
2563 Info.align = Align(8);
2564 break;
2565 }
2566 Info.size = MemoryLocation::UnknownSize;
2567 Info.flags |= MachineMemOperand::MOStore;
2568 Infos.push_back(Info);
2569 return;
2570 }
2571}
2572
2574 const AddrMode &AM, Type *Ty,
2575 unsigned AS,
2576 Instruction *I) const {
2577 // No global is ever allowed as a base.
2578 if (AM.BaseGV)
2579 return false;
2580
2581 // None of our addressing modes allows a scalable offset
2582 if (AM.ScalableOffset)
2583 return false;
2584
2585 // RVV instructions only support register addressing.
2586 if (Subtarget.hasVInstructions() && isa<VectorType>(Ty))
2587 return AM.HasBaseReg && AM.Scale == 0 && !AM.BaseOffs;
2588
2589 // The Xqcilo extension provides load/store instructions with a 26-bit signed
2590 // offset.
2591 if (Subtarget.hasVendorXqcilo()) {
2592 if (!isInt<26>(AM.BaseOffs))
2593 return false;
2594 } else if (!isInt<12>(AM.BaseOffs)) {
2595 // Otherwise require a 12-bit signed offset.
2596 return false;
2597 }
2598
2599 switch (AM.Scale) {
2600 case 0: // "r+i" or just "i", depending on HasBaseReg.
2601 break;
2602 case 1:
2603 if (!AM.HasBaseReg) // allow "r+i".
2604 break;
2605 return false; // disallow "r+r" or "r+r+i".
2606 default:
2607 return false;
2608 }
2609
2610 return true;
2611}
2612
2614 return isInt<12>(Imm);
2615}
2616
2618 // The Xqcilia extension provides add-immediate instructions with a 26-bit
2619 // signed immediate.
2620 if (Subtarget.hasVendorXqcilia())
2621 return isInt<26>(Imm);
2622 return isInt<12>(Imm);
2623}
2624
2625// On RV32, 64-bit integers are split into their high and low parts and held
2626// in two different registers, so the trunc is free since the low register can
2627// just be used.
2628// FIXME: Should we consider i64->i32 free on RV64 to match the EVT version of
2629// isTruncateFree?
2631 if (Subtarget.is64Bit() || !SrcTy->isIntegerTy() || !DstTy->isIntegerTy())
2632 return false;
2633 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
2634 unsigned DestBits = DstTy->getPrimitiveSizeInBits();
2635 return (SrcBits == 64 && DestBits == 32);
2636}
2637
2639 // We consider i64->i32 free on RV64 since we have good selection of W
2640 // instructions that make promoting operations back to i64 free in many cases.
2641 if (SrcVT.isVector() || DstVT.isVector() || !SrcVT.isInteger() ||
2642 !DstVT.isInteger())
2643 return false;
2644 unsigned SrcBits = SrcVT.getSizeInBits();
2645 unsigned DestBits = DstVT.getSizeInBits();
2646 return (SrcBits == 64 && DestBits == 32);
2647}
2648
2650 EVT SrcVT = Val.getValueType();
2651 // free truncate from vnsrl and vnsra
2652 if (Subtarget.hasVInstructions() &&
2653 (Val.getOpcode() == ISD::SRL || Val.getOpcode() == ISD::SRA) &&
2654 SrcVT.isVector() && VT2.isVector()) {
2655 unsigned SrcBits = SrcVT.getVectorElementType().getSizeInBits();
2656 unsigned DestBits = VT2.getVectorElementType().getSizeInBits();
2657 if (SrcBits == DestBits * 2) {
2658 return true;
2659 }
2660 }
2661 return TargetLowering::isTruncateFree(Val, VT2);
2662}
2663
2665 // Zexts are free if they can be combined with a load.
2666 // Don't advertise i32->i64 zextload as being free for RV64. It interacts
2667 // poorly with type legalization of compares preferring sext.
2668 if (auto *LD = dyn_cast<LoadSDNode>(Val)) {
2669 EVT MemVT = LD->getMemoryVT();
2670 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
2671 (LD->getExtensionType() == ISD::NON_EXTLOAD ||
2672 LD->getExtensionType() == ISD::ZEXTLOAD))
2673 return true;
2674 }
2675
2676 return TargetLowering::isZExtFree(Val, VT2);
2677}
2678
2680 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
2681}
2682
2684 return Subtarget.is64Bit() && CI->getType()->isIntegerTy(32);
2685}
2686
2688 return Subtarget.hasCTZLike();
2689}
2690
2692 return Subtarget.hasCLZLike();
2693}
2694
2696 const Instruction &AndI) const {
2697 // We expect to be able to match a bit extraction instruction if the Zbs
2698 // extension is supported and the mask is a power of two. However, we
2699 // conservatively return false if the mask would fit in an ANDI instruction,
2700 // on the basis that it's possible the sinking+duplication of the AND in
2701 // CodeGenPrepare triggered by this hook wouldn't decrease the instruction
2702 // count and would increase code size (e.g. ANDI+BNEZ => BEXTI+BNEZ).
2703 if (!Subtarget.hasBEXTILike())
2704 return false;
2706 if (!Mask)
2707 return false;
2708 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2709}
2710
2712 EVT VT = Y.getValueType();
2713
2714 if (VT.isVector())
2715 return false;
2716
2717 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2718 (!isa<ConstantSDNode>(Y) || cast<ConstantSDNode>(Y)->isOpaque());
2719}
2720
2722 EVT VT = Y.getValueType();
2723
2724 if (!VT.isVector())
2725 return hasAndNotCompare(Y);
2726
2727 // vmandn.mm
2728 if (VT.getVectorElementType() == MVT::i1)
2729 return Subtarget.hasVInstructions();
2730
2731 return Subtarget.hasStdExtZvkb();
2732}
2733
2735 // Zbs provides BEXT[_I], which can be used with SEQZ/SNEZ as a bit test.
2736 if (Subtarget.hasStdExtZbs())
2737 return X.getValueType().isScalarInteger();
2738 auto *C = dyn_cast<ConstantSDNode>(Y);
2739 // XTheadBs provides th.tst (similar to bexti), if Y is a constant
2740 if (Subtarget.hasVendorXTHeadBs())
2741 return C != nullptr;
2742 // We can use ANDI+SEQZ/SNEZ as a bit test. Y contains the bit position.
2743 return C && C->getAPIntValue().ule(10);
2744}
2745
2747 unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X,
2748 SDValue Y) const {
2749 if (SelectOpcode != ISD::VSELECT)
2750 return false;
2751
2752 // Only enable for rvv.
2753 if (!VT.isVector() || !Subtarget.hasVInstructions())
2754 return false;
2755
2756 if (VT.isFixedLengthVector() && !isTypeLegal(VT))
2757 return false;
2758
2759 return true;
2760}
2761
2763 Type *Ty) const {
2764 assert(Ty->isIntegerTy());
2765
2766 unsigned BitSize = Ty->getIntegerBitWidth();
2767 if (BitSize > Subtarget.getXLen())
2768 return false;
2769
2770 // Fast path, assume 32-bit immediates are cheap.
2771 int64_t Val = Imm.getSExtValue();
2772 if (isInt<32>(Val))
2773 return true;
2774
2775 // A constant pool entry may be more aligned than the load we're trying to
2776 // replace. If we don't support unaligned scalar mem, prefer the constant
2777 // pool.
2778 // TODO: Can the caller pass down the alignment?
2779 if (!Subtarget.enableUnalignedScalarMem())
2780 return true;
2781
2782 // Prefer to keep the load if it would require many instructions.
2783 // This uses the same threshold we use for constant pools but doesn't
2784 // check useConstantPoolForLargeInts.
2785 // TODO: Should we keep the load only when we're definitely going to emit a
2786 // constant pool?
2787
2789 return Seq.size() <= Subtarget.getMaxBuildIntsCost();
2790}
2791
2795 unsigned OldShiftOpcode, unsigned NewShiftOpcode,
2796 SelectionDAG &DAG) const {
2797 // One interesting pattern that we'd want to form is 'bit extract':
2798 // ((1 >> Y) & 1) ==/!= 0
2799 // But we also need to be careful not to try to reverse that fold.
2800
2801 // Is this '((1 >> Y) & 1)'?
2802 if (XC && OldShiftOpcode == ISD::SRL && XC->isOne())
2803 return false; // Keep the 'bit extract' pattern.
2804
2805 // Will this be '((1 >> Y) & 1)' after the transform?
2806 if (NewShiftOpcode == ISD::SRL && CC->isOne())
2807 return true; // Do form the 'bit extract' pattern.
2808
2809 // If 'X' is a constant, and we transform, then we will immediately
2810 // try to undo the fold, thus causing endless combine loop.
2811 // So only do the transform if X is not a constant. This matches the default
2812 // implementation of this function.
2813 return !XC;
2814}
2815
2817 unsigned Opc = VecOp.getOpcode();
2818
2819 // Assume target opcodes can't be scalarized.
2820 // TODO - do we have any exceptions?
2821 if (Opc >= ISD::BUILTIN_OP_END || !isBinOp(Opc))
2822 return false;
2823
2824 // If the vector op is not supported, try to convert to scalar.
2825 EVT VecVT = VecOp.getValueType();
2827 return true;
2828
2829 // If the vector op is supported, but the scalar op is not, the transform may
2830 // not be worthwhile.
2831 // Permit a vector binary operation can be converted to scalar binary
2832 // operation which is custom lowered with illegal type.
2833 EVT ScalarVT = VecVT.getScalarType();
2834 return isOperationLegalOrCustomOrPromote(Opc, ScalarVT) ||
2835 isOperationCustom(Opc, ScalarVT);
2836}
2837
2839 const GlobalAddressSDNode *GA) const {
2840 // In order to maximise the opportunity for common subexpression elimination,
2841 // keep a separate ADD node for the global address offset instead of folding
2842 // it in the global address node. Later peephole optimisations may choose to
2843 // fold it back in when profitable.
2844 return false;
2845}
2846
2847// Returns 0-31 if the fli instruction is available for the type and this is
2848// legal FP immediate for the type. Returns -1 otherwise.
2850 if (!Subtarget.hasStdExtZfa())
2851 return -1;
2852
2853 bool IsSupportedVT = false;
2854 if (VT == MVT::f16) {
2855 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2856 } else if (VT == MVT::f32) {
2857 IsSupportedVT = true;
2858 } else if (VT == MVT::f64) {
2859 assert(Subtarget.hasStdExtD() && "Expect D extension");
2860 IsSupportedVT = true;
2861 }
2862
2863 if (!IsSupportedVT)
2864 return -1;
2865
2867}
2868
2870 bool ForCodeSize) const {
2871 bool IsLegalVT = false;
2872 if (VT == MVT::f16)
2873 IsLegalVT = Subtarget.hasStdExtZfhminOrZhinxmin();
2874 else if (VT == MVT::f32)
2875 IsLegalVT = Subtarget.hasStdExtFOrZfinx();
2876 else if (VT == MVT::f64)
2877 IsLegalVT = Subtarget.hasStdExtDOrZdinx();
2878 else if (VT == MVT::bf16)
2879 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2880
2881 if (!IsLegalVT)
2882 return false;
2883
2884 if (getLegalZfaFPImm(Imm, VT) >= 0)
2885 return true;
2886
2887 // Some constants can be produced by fli+fneg.
2888 if (Imm.isNegative() && getLegalZfaFPImm(-Imm, VT) >= 0)
2889 return true;
2890
2891 // Cannot create a 64 bit floating-point immediate value for rv32.
2892 if (Subtarget.getXLen() < VT.getScalarSizeInBits()) {
2893 // td can handle +0.0 or -0.0 already.
2894 // -0.0 can be created by fmv + fneg.
2895 return Imm.isZero();
2896 }
2897
2898 // Special case: fmv + fneg
2899 if (Imm.isNegZero())
2900 return true;
2901
2902 // Building an integer and then converting requires a fmv at the end of
2903 // the integer sequence. The fmv is not required for Zfinx.
2904 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2905 const int Cost =
2906 FmvCost + RISCVMatInt::getIntMatCost(Imm.bitcastToAPInt(),
2907 Subtarget.getXLen(), Subtarget);
2908 return Cost <= FPImmCost;
2909}
2910
2911// TODO: This is very conservative.
2914 unsigned Index) const {
2915 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit() &&
2916 (ResVT == MVT::v4i8 || ResVT == MVT::v2i16)) {
2917 if ((Index % ResVT.getVectorNumElements()) == 0)
2920 }
2921
2922 if (!Subtarget.hasVInstructions())
2924
2927
2928 // Extracts from index 0 are just subreg extracts.
2929 if (Index == 0)
2931
2932 // Only support extracting a fixed from a fixed vector for now.
2933 if (ResVT.isScalableVector() || SrcVT.isScalableVector())
2935
2936 EVT EltVT = ResVT.getVectorElementType();
2937 assert(EltVT == SrcVT.getVectorElementType() && "Should hold for node");
2938
2939 // The smallest type we can slide is i8.
2940 if (EltVT == MVT::i1)
2942
2943 unsigned ResElts = ResVT.getVectorNumElements();
2944 unsigned SrcElts = SrcVT.getVectorNumElements();
2945
2946 unsigned MinVLen = Subtarget.getRealMinVLen();
2947 unsigned MinVLMAX = MinVLen / EltVT.getSizeInBits();
2948
2949 // If we're extracting only data from the first VLEN bits of the source
2950 // then we can always do this with an m1 vslidedown.vx. Restricting the
2951 // Index ensures we can use a vslidedown.vi.
2952 // TODO: We can generalize this when the exact VLEN is known.
2953 if (Index + ResElts <= MinVLMAX && Index < 31)
2955
2956 // Convervatively only handle extracting half of a vector.
2957 // TODO: We can do arbitrary slidedowns, but for now only support extracting
2958 // the upper half of a vector until we have more test coverage.
2959 // TODO: For sizes which aren't multiples of VLEN sizes, this may not be
2960 // a cheap extract. However, this case is important in practice for
2961 // shuffled extracts of longer vectors. How resolve?
2962 if ((ResElts * 2) == SrcElts && Index == ResElts)
2965}
2966
2968 CallingConv::ID CC,
2969 EVT VT) const {
2970 // Use f32 to pass f16 if it is legal and Zfh/Zfhmin is not enabled.
2971 // We might still end up using a GPR but that will be decided based on ABI.
2972 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2973 !Subtarget.hasStdExtZfhminOrZhinxmin())
2974 return MVT::f32;
2975
2976 return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
2977}
2978
2979unsigned
2981 std::optional<MVT> RegisterVT) const {
2982 // Pair inline assembly operand
2983 if (VT == (Subtarget.is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2984 *RegisterVT == MVT::Untyped)
2985 return 1;
2986
2987 return TargetLowering::getNumRegisters(Context, VT, RegisterVT);
2988}
2989
2991 CallingConv::ID CC,
2992 EVT VT) const {
2993 // Use f32 to pass f16 if it is legal and Zfh/Zfhmin is not enabled.
2994 // We might still end up using a GPR but that will be decided based on ABI.
2995 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2996 !Subtarget.hasStdExtZfhminOrZhinxmin())
2997 return 1;
2998
2999 return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);
3000}
3001
3002// Changes the condition code and swaps operands if necessary, so the SetCC
3003// operation matches one of the comparisons supported directly by branches
3004// in the RISC-V ISA. May adjust compares to favor compare with 0 over compare
3005// with 1/-1.
3007 ISD::CondCode &CC, SelectionDAG &DAG,
3008 const RISCVSubtarget &Subtarget) {
3009 // If this is a single bit test that can't be handled by ANDI, shift the
3010 // bit to be tested to the MSB and perform a signed compare with 0.
3011 if (isIntEqualitySetCC(CC) && isNullConstant(RHS) &&
3012 LHS.getOpcode() == ISD::AND && LHS.hasOneUse() &&
3013 isa<ConstantSDNode>(LHS.getOperand(1)) &&
3014 // XAndesPerf supports branch on test bit.
3015 !Subtarget.hasVendorXAndesPerf()) {
3016 uint64_t Mask = LHS.getConstantOperandVal(1);
3017 if ((isPowerOf2_64(Mask) || isMask_64(Mask)) && !isInt<12>(Mask)) {
3018 unsigned ShAmt = 0;
3019 if (isPowerOf2_64(Mask)) {
3020 CC = CC == ISD::SETEQ ? ISD::SETGE : ISD::SETLT;
3021 ShAmt = LHS.getValueSizeInBits() - 1 - Log2_64(Mask);
3022 } else {
3023 ShAmt = LHS.getValueSizeInBits() - llvm::bit_width(Mask);
3024 }
3025
3026 LHS = LHS.getOperand(0);
3027 if (ShAmt != 0)
3028 LHS = DAG.getNode(ISD::SHL, DL, LHS.getValueType(), LHS,
3029 DAG.getConstant(ShAmt, DL, LHS.getValueType()));
3030 return;
3031 }
3032 }
3033
3034 if (auto *RHSC = dyn_cast<ConstantSDNode>(RHS)) {
3035 int64_t C = RHSC->getSExtValue();
3036 switch (CC) {
3037 default: break;
3038 case ISD::SETGT:
3039 // Convert X > -1 to X >= 0.
3040 if (C == -1) {
3041 RHS = DAG.getConstant(0, DL, RHS.getValueType());
3042 CC = ISD::SETGE;
3043 return;
3044 }
3045 if ((Subtarget.hasVendorXqcicm() || Subtarget.hasVendorXqcicli()) &&
3046 C != INT64_MAX && isInt<5>(C + 1)) {
3047 // We have a conditional move instruction for SETGE but not SETGT.
3048 // Convert X > C to X >= C + 1, if (C + 1) is a 5-bit signed immediate.
3049 RHS = DAG.getSignedConstant(C + 1, DL, RHS.getValueType());
3050 CC = ISD::SETGE;
3051 return;
3052 }
3053 if (Subtarget.hasVendorXqcibi() && C != INT64_MAX && isInt<16>(C + 1)) {
3054 // We have a branch immediate instruction for SETGE but not SETGT.
3055 // Convert X > C to X >= C + 1, if (C + 1) is a 16-bit signed immediate.
3056 RHS = DAG.getSignedConstant(C + 1, DL, RHS.getValueType());
3057 CC = ISD::SETGE;
3058 return;
3059 }
3060 break;
3061 case ISD::SETLT:
3062 // Convert X < 1 to 0 >= X.
3063 if (C == 1) {
3064 RHS = LHS;
3065 LHS = DAG.getConstant(0, DL, RHS.getValueType());
3066 CC = ISD::SETGE;
3067 return;
3068 }
3069 break;
3070 case ISD::SETUGT:
3071 if ((Subtarget.hasVendorXqcicm() || Subtarget.hasVendorXqcicli()) &&
3072 C != INT64_MAX && isUInt<5>(C + 1)) {
3073 // We have a conditional move instruction for SETUGE but not SETUGT.
3074 // Convert X > C to X >= C + 1, if (C + 1) is a 5-bit signed immediate.
3075 RHS = DAG.getConstant(C + 1, DL, RHS.getValueType());
3076 CC = ISD::SETUGE;
3077 return;
3078 }
3079 if (Subtarget.hasVendorXqcibi() && C != INT64_MAX && isUInt<16>(C + 1)) {
3080 // We have a branch immediate instruction for SETUGE but not SETUGT.
3081 // Convert X > C to X >= C + 1, if (C + 1) is a 16-bit unsigned
3082 // immediate.
3083 RHS = DAG.getConstant(C + 1, DL, RHS.getValueType());
3084 CC = ISD::SETUGE;
3085 return;
3086 }
3087 break;
3088 }
3089 }
3090
3091 switch (CC) {
3092 default:
3093 break;
3094 case ISD::SETGT:
3095 case ISD::SETLE:
3096 case ISD::SETUGT:
3097 case ISD::SETULE:
3099 std::swap(LHS, RHS);
3100 break;
3101 }
3102}
3103
3105 if (VT.isRISCVVectorTuple()) {
3106 if (VT.SimpleTy >= MVT::riscv_nxv1i8x2 &&
3107 VT.SimpleTy <= MVT::riscv_nxv1i8x8)
3108 return RISCVVType::LMUL_F8;
3109 if (VT.SimpleTy >= MVT::riscv_nxv2i8x2 &&
3110 VT.SimpleTy <= MVT::riscv_nxv2i8x8)
3111 return RISCVVType::LMUL_F4;
3112 if (VT.SimpleTy >= MVT::riscv_nxv4i8x2 &&
3113 VT.SimpleTy <= MVT::riscv_nxv4i8x8)
3114 return RISCVVType::LMUL_F2;
3115 if (VT.SimpleTy >= MVT::riscv_nxv8i8x2 &&
3116 VT.SimpleTy <= MVT::riscv_nxv8i8x8)
3117 return RISCVVType::LMUL_1;
3118 if (VT.SimpleTy >= MVT::riscv_nxv16i8x2 &&
3119 VT.SimpleTy <= MVT::riscv_nxv16i8x4)
3120 return RISCVVType::LMUL_2;
3121 if (VT.SimpleTy == MVT::riscv_nxv32i8x2)
3122 return RISCVVType::LMUL_4;
3123 llvm_unreachable("Invalid vector tuple type LMUL.");
3124 }
3125
3126 assert(VT.isScalableVector() && "Expecting a scalable vector type");
3127 unsigned KnownSize = VT.getSizeInBits().getKnownMinValue();
3128 if (VT.getVectorElementType() == MVT::i1)
3129 KnownSize *= 8;
3130
3131 switch (KnownSize) {
3132 default:
3133 llvm_unreachable("Invalid LMUL.");
3134 case 8:
3135 return RISCVVType::LMUL_F8;
3136 case 16:
3137 return RISCVVType::LMUL_F4;
3138 case 32:
3139 return RISCVVType::LMUL_F2;
3140 case 64:
3141 return RISCVVType::LMUL_1;
3142 case 128:
3143 return RISCVVType::LMUL_2;
3144 case 256:
3145 return RISCVVType::LMUL_4;
3146 case 512:
3147 return RISCVVType::LMUL_8;
3148 }
3149}
3150
3152 switch (LMul) {
3153 default:
3154 llvm_unreachable("Invalid LMUL.");
3158 case RISCVVType::LMUL_1:
3159 return RISCV::VRRegClassID;
3160 case RISCVVType::LMUL_2:
3161 return RISCV::VRM2RegClassID;
3162 case RISCVVType::LMUL_4:
3163 return RISCV::VRM4RegClassID;
3164 case RISCVVType::LMUL_8:
3165 return RISCV::VRM8RegClassID;
3166 }
3167}
3168
3169unsigned RISCVTargetLowering::getSubregIndexByMVT(MVT VT, unsigned Index) {
3170 RISCVVType::VLMUL LMUL = getLMUL(VT);
3171 if (LMUL == RISCVVType::LMUL_F8 || LMUL == RISCVVType::LMUL_F4 ||
3172 LMUL == RISCVVType::LMUL_F2 || LMUL == RISCVVType::LMUL_1) {
3173 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
3174 "Unexpected subreg numbering");
3175 return RISCV::sub_vrm1_0 + Index;
3176 }
3177 if (LMUL == RISCVVType::LMUL_2) {
3178 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
3179 "Unexpected subreg numbering");
3180 return RISCV::sub_vrm2_0 + Index;
3181 }
3182 if (LMUL == RISCVVType::LMUL_4) {
3183 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
3184 "Unexpected subreg numbering");
3185 return RISCV::sub_vrm4_0 + Index;
3186 }
3187 llvm_unreachable("Invalid vector type.");
3188}
3189
3191 if (VT.isRISCVVectorTuple()) {
3192 unsigned NF = VT.getRISCVVectorTupleNumFields();
3193 unsigned RegsPerField =
3194 std::max(1U, (unsigned)VT.getSizeInBits().getKnownMinValue() /
3195 (NF * RISCV::RVVBitsPerBlock));
3196 switch (RegsPerField) {
3197 case 1:
3198 if (NF == 2)
3199 return RISCV::VRN2M1RegClassID;
3200 if (NF == 3)
3201 return RISCV::VRN3M1RegClassID;
3202 if (NF == 4)
3203 return RISCV::VRN4M1RegClassID;
3204 if (NF == 5)
3205 return RISCV::VRN5M1RegClassID;
3206 if (NF == 6)
3207 return RISCV::VRN6M1RegClassID;
3208 if (NF == 7)
3209 return RISCV::VRN7M1RegClassID;
3210 if (NF == 8)
3211 return RISCV::VRN8M1RegClassID;
3212 break;
3213 case 2:
3214 if (NF == 2)
3215 return RISCV::VRN2M2RegClassID;
3216 if (NF == 3)
3217 return RISCV::VRN3M2RegClassID;
3218 if (NF == 4)
3219 return RISCV::VRN4M2RegClassID;
3220 break;
3221 case 4:
3222 assert(NF == 2);
3223 return RISCV::VRN2M4RegClassID;
3224 default:
3225 break;
3226 }
3227 llvm_unreachable("Invalid vector tuple type RegClass.");
3228 }
3229
3230 if (VT.getVectorElementType() == MVT::i1)
3231 return RISCV::VRRegClassID;
3232 return getRegClassIDForLMUL(getLMUL(VT));
3233}
3234
3235// Attempt to decompose a subvector insert/extract between VecVT and
3236// SubVecVT via subregister indices. Returns the subregister index that
3237// can perform the subvector insert/extract with the given element index, as
3238// well as the index corresponding to any leftover subvectors that must be
3239// further inserted/extracted within the register class for SubVecVT.
3240std::pair<unsigned, unsigned>
3242 MVT VecVT, MVT SubVecVT, unsigned InsertExtractIdx,
3243 const RISCVRegisterInfo *TRI) {
3244 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
3245 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
3246 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
3247 "Register classes not ordered");
3248 unsigned VecRegClassID = getRegClassIDForVecVT(VecVT);
3249 unsigned SubRegClassID = getRegClassIDForVecVT(SubVecVT);
3250
3251 // If VecVT is a vector tuple type, either it's the tuple type with same
3252 // RegClass with SubVecVT or SubVecVT is a actually a subvector of the VecVT.
3253 if (VecVT.isRISCVVectorTuple()) {
3254 if (VecRegClassID == SubRegClassID)
3255 return {RISCV::NoSubRegister, 0};
3256
3257 assert(SubVecVT.isScalableVector() &&
3258 "Only allow scalable vector subvector.");
3259 assert(getLMUL(VecVT) == getLMUL(SubVecVT) &&
3260 "Invalid vector tuple insert/extract for vector and subvector with "
3261 "different LMUL.");
3262 return {getSubregIndexByMVT(VecVT, InsertExtractIdx), 0};
3263 }
3264
3265 // Try to compose a subregister index that takes us from the incoming
3266 // LMUL>1 register class down to the outgoing one. At each step we half
3267 // the LMUL:
3268 // nxv16i32@12 -> nxv2i32: sub_vrm4_1_then_sub_vrm2_1_then_sub_vrm1_0
3269 // Note that this is not guaranteed to find a subregister index, such as
3270 // when we are extracting from one VR type to another.
3271 unsigned SubRegIdx = RISCV::NoSubRegister;
3272 for (const unsigned RCID :
3273 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
3274 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
3275 VecVT = VecVT.getHalfNumVectorElementsVT();
3276 bool IsHi =
3277 InsertExtractIdx >= VecVT.getVectorElementCount().getKnownMinValue();
3278 SubRegIdx = TRI->composeSubRegIndices(SubRegIdx,
3279 getSubregIndexByMVT(VecVT, IsHi));
3280 if (IsHi)
3281 InsertExtractIdx -= VecVT.getVectorElementCount().getKnownMinValue();
3282 }
3283 return {SubRegIdx, InsertExtractIdx};
3284}
3285
3286// Permit combining of mask vectors as BUILD_VECTOR never expands to scalar
3287// stores for those types.
3288bool RISCVTargetLowering::mergeStoresAfterLegalization(EVT VT) const {
3289 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit() &&
3290 (VT == MVT::i32 || VT == MVT::v2i16 || VT == MVT::v4i8))
3291 return false;
3292
3293 return !Subtarget.useRVVForFixedLengthVectors() ||
3294 VT.isFixedLengthVectorOf(MVT::i1);
3295}
3296
3298 if (!ScalarTy.isSimple())
3299 return false;
3300 switch (ScalarTy.getSimpleVT().SimpleTy) {
3301 case MVT::iPTR:
3302 return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() : true;
3303 case MVT::i8:
3304 case MVT::i16:
3305 case MVT::i32:
3306 return Subtarget.hasVInstructions();
3307 case MVT::i64:
3308 return Subtarget.hasVInstructionsI64();
3309 case MVT::f16:
3310 return Subtarget.hasVInstructionsF16Minimal();
3311 case MVT::bf16:
3312 return Subtarget.hasVInstructionsBF16Minimal();
3313 case MVT::f32:
3314 return Subtarget.hasVInstructionsF32();
3315 case MVT::f64:
3316 return Subtarget.hasVInstructionsF64();
3317 default:
3318 return false;
3319 }
3320}
3321
3322
3324 return NumRepeatedDivisors;
3325}
3326
3328 assert((Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN ||
3329 Op.getOpcode() == ISD::INTRINSIC_W_CHAIN) &&
3330 "Unexpected opcode");
3331 bool HasChain = Op.getOpcode() == ISD::INTRINSIC_W_CHAIN;
3332 unsigned IntNo = Op.getConstantOperandVal(HasChain ? 1 : 0);
3334 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
3335 if (!II)
3336 return SDValue();
3337 return Op.getOperand(II->VLOperand + 1 + HasChain);
3338}
3339
3341 const RISCVSubtarget &Subtarget) {
3342 assert(VT.isFixedLengthVector() && "Expected a fixed length vector type!");
3343 if (!Subtarget.useRVVForFixedLengthVectors())
3344 return false;
3345
3346 // We only support a set of vector types with a consistent maximum fixed size
3347 // across all supported vector element types to avoid legalization issues.
3348 // Therefore -- since the largest is v1024i8/v512i16/etc -- the largest
3349 // fixed-length vector type we support is 1024 bytes.
3350 if (VT.getVectorNumElements() > 1024 || VT.getFixedSizeInBits() > 1024 * 8)
3351 return false;
3352
3353 unsigned MinVLen = Subtarget.getRealMinVLen();
3354
3355 MVT EltVT = VT.getVectorElementType();
3356
3357 // Don't use RVV for vectors we cannot scalarize if required.
3358 switch (EltVT.SimpleTy) {
3359 // i1 is supported but has different rules.
3360 default:
3361 return false;
3362 case MVT::i1:
3363 // Masks can only use a single register.
3364 if (VT.getVectorNumElements() > MinVLen)
3365 return false;
3366 MinVLen /= 8;
3367 break;
3368 case MVT::i8:
3369 case MVT::i16:
3370 case MVT::i32:
3371 break;
3372 case MVT::i64:
3373 if (!Subtarget.hasVInstructionsI64())
3374 return false;
3375 break;
3376 case MVT::f16:
3377 if (!Subtarget.hasVInstructionsF16Minimal())
3378 return false;
3379 break;
3380 case MVT::bf16:
3381 if (!Subtarget.hasVInstructionsBF16Minimal())
3382 return false;
3383 break;
3384 case MVT::f32:
3385 if (!Subtarget.hasVInstructionsF32())
3386 return false;
3387 break;
3388 case MVT::f64:
3389 if (!Subtarget.hasVInstructionsF64())
3390 return false;
3391 break;
3392 }
3393
3394 // Reject elements larger than ELEN.
3395 if (EltVT.getSizeInBits() > Subtarget.getELen())
3396 return false;
3397
3398 unsigned LMul = divideCeil(VT.getSizeInBits(), MinVLen);
3399 // Don't use RVV for types that don't fit.
3400 if (LMul > 8)
3401 return false;
3402
3403 // TODO: Perhaps an artificial restriction, but worth having whilst getting
3404 // the base fixed length RVV support in place.
3405 if (!VT.isPow2VectorType())
3406 return false;
3407
3408 return true;
3409}
3410
3411bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(MVT VT) const {
3412 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
3413}
3414
3415// Return the largest legal scalable vector type that matches VT's element type.
3417 const RISCVSubtarget &Subtarget) {
3418 // This may be called before legal types are setup.
3419 assert(((VT.isFixedLengthVector() &&
3420 Subtarget.getTargetLowering()->isTypeLegal(VT)) ||
3421 useRVVForFixedLengthVectorVT(VT, Subtarget)) &&
3422 "Expected legal fixed length vector!");
3423
3424 unsigned MinVLen = Subtarget.getRealMinVLen();
3425 unsigned MaxELen = Subtarget.getELen();
3426
3427 MVT EltVT = VT.getVectorElementType();
3428 switch (EltVT.SimpleTy) {
3429 default:
3430 llvm_unreachable("unexpected element type for RVV container");
3431 case MVT::i1:
3432 case MVT::i8:
3433 case MVT::i16:
3434 case MVT::i32:
3435 case MVT::i64:
3436 case MVT::bf16:
3437 case MVT::f16:
3438 case MVT::f32:
3439 case MVT::f64: {
3440 // We prefer to use LMUL=1 for VLEN sized types. Use fractional lmuls for
3441 // narrower types. The smallest fractional LMUL we support is 8/ELEN. Within
3442 // each fractional LMUL we support SEW between 8 and LMUL*ELEN.
3443 unsigned NumElts =
3445 NumElts = std::max(NumElts, RISCV::RVVBitsPerBlock / MaxELen);
3446 assert(isPowerOf2_32(NumElts) && "Expected power of 2 NumElts");
3447 return MVT::getScalableVectorVT(EltVT, NumElts);
3448 }
3449 }
3450}
3451
3453 return ::getContainerForFixedLengthVector(VT, getSubtarget());
3454}
3455
3456// Grow V to consume an entire RVV register.
3458 const RISCVSubtarget &Subtarget) {
3459 assert(VT.isScalableVector() &&
3460 "Expected to convert into a scalable vector!");
3461 assert(V.getValueType().isFixedLengthVector() &&
3462 "Expected a fixed length vector operand!");
3463 SDLoc DL(V);
3464 return DAG.getInsertSubvector(DL, DAG.getUNDEF(VT), V, 0);
3465}
3466
3467// Shrink V so it's just big enough to maintain a VT's worth of data.
3469 const RISCVSubtarget &Subtarget) {
3471 "Expected to convert into a fixed length vector!");
3472 assert(V.getValueType().isScalableVector() &&
3473 "Expected a scalable vector operand!");
3474 SDLoc DL(V);
3475 return DAG.getExtractSubvector(DL, VT, V, 0);
3476}
3477
3478/// Return the type of the mask type suitable for masking the provided
3479/// vector type. This is simply an i1 element type vector of the same
3480/// (possibly scalable) length.
3481static MVT getMaskTypeFor(MVT VecVT) {
3482 assert(VecVT.isVector());
3484 return MVT::getVectorVT(MVT::i1, EC);
3485}
3486
3487/// Creates an all ones mask suitable for masking a vector of type VecTy with
3488/// vector length VL. .
3489static SDValue getAllOnesMask(MVT VecVT, SDValue VL, const SDLoc &DL,
3490 SelectionDAG &DAG) {
3491 MVT MaskVT = getMaskTypeFor(VecVT);
3492 return DAG.getNode(RISCVISD::VMSET_VL, DL, MaskVT, VL);
3493}
3494
3495static std::pair<SDValue, SDValue>
3497 const RISCVSubtarget &Subtarget) {
3498 assert(VecVT.isScalableVector() && "Expecting a scalable vector");
3499 SDValue VL = DAG.getRegister(RISCV::X0, Subtarget.getXLenVT());
3500 SDValue Mask = getAllOnesMask(VecVT, VL, DL, DAG);
3501 return {Mask, VL};
3502}
3503
3504static std::pair<SDValue, SDValue>
3505getDefaultVLOps(uint64_t NumElts, MVT ContainerVT, const SDLoc &DL,
3506 SelectionDAG &DAG, const RISCVSubtarget &Subtarget) {
3507 assert(ContainerVT.isScalableVector() && "Expecting scalable container type");
3508 SDValue VL = DAG.getConstant(NumElts, DL, Subtarget.getXLenVT());
3509 SDValue Mask = getAllOnesMask(ContainerVT, VL, DL, DAG);
3510 return {Mask, VL};
3511}
3512
3513// Gets the two common "VL" operands: an all-ones mask and the vector length.
3514// VecVT is a vector type, either fixed-length or scalable, and ContainerVT is
3515// the vector type that the fixed-length vector is contained in. Otherwise if
3516// VecVT is scalable, then ContainerVT should be the same as VecVT.
3517static std::pair<SDValue, SDValue>
3518getDefaultVLOps(MVT VecVT, MVT ContainerVT, const SDLoc &DL, SelectionDAG &DAG,
3519 const RISCVSubtarget &Subtarget) {
3520 if (VecVT.isFixedLengthVector())
3521 return getDefaultVLOps(VecVT.getVectorNumElements(), ContainerVT, DL, DAG,
3522 Subtarget);
3523 assert(ContainerVT.isScalableVector() && "Expecting scalable container type");
3524 return getDefaultScalableVLOps(ContainerVT, DL, DAG, Subtarget);
3525}
3526
3528 SelectionDAG &DAG) const {
3529 assert(VecVT.isScalableVector() && "Expected scalable vector");
3530 return DAG.getElementCount(DL, Subtarget.getXLenVT(),
3531 VecVT.getVectorElementCount());
3532}
3533
3534std::pair<unsigned, unsigned>
3536 const RISCVSubtarget &Subtarget) {
3537 assert(VecVT.isScalableVector() && "Expected scalable vector");
3538
3539 unsigned EltSize = VecVT.getScalarSizeInBits();
3540 unsigned MinSize = VecVT.getSizeInBits().getKnownMinValue();
3541
3542 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
3543 unsigned MaxVLMAX =
3544 RISCVTargetLowering::computeVLMAX(VectorBitsMax, EltSize, MinSize);
3545
3546 unsigned VectorBitsMin = Subtarget.getRealMinVLen();
3547 unsigned MinVLMAX =
3548 RISCVTargetLowering::computeVLMAX(VectorBitsMin, EltSize, MinSize);
3549
3550 return std::make_pair(MinVLMAX, MaxVLMAX);
3551}
3552
3553// The state of RVV BUILD_VECTOR and VECTOR_SHUFFLE lowering is that very few
3554// of either is (currently) supported. This can get us into an infinite loop
3555// where we try to lower a BUILD_VECTOR as a VECTOR_SHUFFLE as a BUILD_VECTOR
3556// as a ..., etc.
3557// Until either (or both) of these can reliably lower any node, reporting that
3558// we don't want to expand BUILD_VECTORs via VECTOR_SHUFFLEs at least breaks
3559// the infinite loop. Note that this lowers BUILD_VECTOR through the stack,
3560// which is not desirable.
3562 EVT VT, unsigned DefinedValues) const {
3563 return false;
3564}
3565
3567 // TODO: Here assume reciprocal throughput is 1 for LMUL_1, it is
3568 // implementation-defined.
3569 if (!VT.isVector())
3571 unsigned DLenFactor = Subtarget.getDLenFactor();
3572 unsigned Cost;
3573 if (VT.isScalableVector()) {
3574 unsigned LMul;
3575 bool Fractional;
3576 std::tie(LMul, Fractional) =
3578 if (Fractional)
3579 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
3580 else
3581 Cost = (LMul * DLenFactor);
3582 } else {
3583 Cost = divideCeil(VT.getSizeInBits(), Subtarget.getRealMinVLen() / DLenFactor);
3584 }
3585 return Cost;
3586}
3587
3588
3589/// Return the cost of a vrgather.vv instruction for the type VT. vrgather.vv
3590/// may be quadratic in the number of vreg implied by LMUL, and is assumed to
3591/// be by default. VRGatherCostModel reflects available options. Note that
3592/// operand (index and possibly mask) are handled separately.
3594 auto LMULCost = getLMULCost(VT);
3595 bool Log2CostModel =
3596 Subtarget.getVRGatherCostModel() == llvm::RISCVSubtarget::NLog2N;
3597 if (Log2CostModel && LMULCost.isValid()) {
3598 unsigned Log = Log2_64(LMULCost.getValue());
3599 if (Log > 0)
3600 return LMULCost * Log;
3601 }
3602 return LMULCost * LMULCost;
3603}
3604
3605/// Return the cost of a vrgather.vi (or vx) instruction for the type VT.
3606/// vrgather.vi/vx may be linear in the number of vregs implied by LMUL,
3607/// or may track the vrgather.vv cost. It is implementation-dependent.
3611
3612/// Return the cost of a vslidedown.vx or vslideup.vx instruction
3613/// for the type VT. (This does not cover the vslide1up or vslide1down
3614/// variants.) Slides may be linear in the number of vregs implied by LMUL,
3615/// or may track the vrgather.vv cost. It is implementation-dependent.
3619
3620/// Return the cost of a vslidedown.vi or vslideup.vi instruction
3621/// for the type VT. (This does not cover the vslide1up or vslide1down
3622/// variants.) Slides may be linear in the number of vregs implied by LMUL,
3623/// or may track the vrgather.vv cost. It is implementation-dependent.
3627
3629 const RISCVSubtarget &Subtarget) {
3630 // f16 conversions are promoted to f32 when Zfh/Zhinx are not supported.
3631 // bf16 conversions are always promoted to f32.
3632 if ((Op.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx()) ||
3633 Op.getValueType() == MVT::bf16) {
3634 bool IsStrict = Op->isStrictFPOpcode();
3635
3636 SDLoc DL(Op);
3637 if (IsStrict) {
3638 SDValue Val = DAG.getNode(Op.getOpcode(), DL, {MVT::f32, MVT::Other},
3639 {Op.getOperand(0), Op.getOperand(1)});
3640 return DAG.getNode(ISD::STRICT_FP_ROUND, DL,
3641 {Op.getValueType(), MVT::Other},
3642 {Val.getValue(1), Val.getValue(0),
3643 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)});
3644 }
3645 return DAG.getNode(
3646 ISD::FP_ROUND, DL, Op.getValueType(),
3647 DAG.getNode(Op.getOpcode(), DL, MVT::f32, Op.getOperand(0)),
3648 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
3649 }
3650
3651 // Other operations are legal.
3652 return Op;
3653}
3654
3656 const RISCVSubtarget &Subtarget) {
3657 // RISC-V FP-to-int conversions saturate to the destination register size, but
3658 // don't produce 0 for nan. We can use a conversion instruction and fix the
3659 // nan case with a compare and a select.
3660 SDValue Src = Op.getOperand(0);
3661
3662 MVT DstVT = Op.getSimpleValueType();
3663 EVT SatVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
3664
3665 bool IsSigned = Op.getOpcode() == ISD::FP_TO_SINT_SAT;
3666
3667 if (!DstVT.isVector()) {
3668 // For bf16 or for f16 in absence of Zfh, promote to f32, then saturate
3669 // the result.
3670 if ((Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx()) ||
3671 Src.getValueType() == MVT::bf16) {
3672 Src = DAG.getNode(ISD::FP_EXTEND, SDLoc(Op), MVT::f32, Src);
3673 }
3674
3675 unsigned Opc;
3676 if (SatVT == DstVT)
3677 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
3678 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
3679 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
3680 else
3681 return SDValue();
3682 // FIXME: Support other SatVTs by clamping before or after the conversion.
3683
3684 SDLoc DL(Op);
3685 SDValue FpToInt = DAG.getNode(
3686 Opc, DL, DstVT, Src,
3688
3689 if (Opc == RISCVISD::FCVT_WU_RV64)
3690 FpToInt = DAG.getZeroExtendInReg(FpToInt, DL, MVT::i32);
3691
3692 SDValue ZeroInt = DAG.getConstant(0, DL, DstVT);
3693 return DAG.getSelectCC(DL, Src, Src, ZeroInt, FpToInt,
3695 }
3696
3697 // Vectors.
3698
3699 MVT DstEltVT = DstVT.getVectorElementType();
3700 MVT SrcVT = Src.getSimpleValueType();
3701 MVT SrcEltVT = SrcVT.getVectorElementType();
3702 unsigned SrcEltSize = SrcEltVT.getSizeInBits();
3703 unsigned DstEltSize = DstEltVT.getSizeInBits();
3704
3705 // Only handle saturating to the destination type.
3706 if (SatVT != DstEltVT)
3707 return SDValue();
3708
3709 MVT DstContainerVT = DstVT;
3710 MVT SrcContainerVT = SrcVT;
3711 if (DstVT.isFixedLengthVector()) {
3712 DstContainerVT = getContainerForFixedLengthVector(DstVT, Subtarget);
3713 SrcContainerVT = getContainerForFixedLengthVector(SrcVT, Subtarget);
3714 assert(DstContainerVT.getVectorElementCount() ==
3715 SrcContainerVT.getVectorElementCount() &&
3716 "Expected same element count");
3717 Src = convertToScalableVector(SrcContainerVT, Src, DAG, Subtarget);
3718 }
3719
3720 SDLoc DL(Op);
3721
3722 auto [Mask, VL] = getDefaultVLOps(DstVT, DstContainerVT, DL, DAG, Subtarget);
3723
3724 SDValue IsNan = DAG.getNode(RISCVISD::SETCC_VL, DL, Mask.getValueType(),
3725 {Src, Src, DAG.getCondCode(ISD::SETNE),
3726 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
3727
3728 // Need to widen by more than 1 step, promote the FP type, then do a widening
3729 // convert.
3730 if (DstEltSize > (2 * SrcEltSize)) {
3731 assert(SrcContainerVT.getVectorElementType() == MVT::f16 && "Unexpected VT!");
3732 MVT InterVT = SrcContainerVT.changeVectorElementType(MVT::f32);
3733 Src = DAG.getNode(RISCVISD::FP_EXTEND_VL, DL, InterVT, Src, Mask, VL);
3734 }
3735
3736 MVT CvtContainerVT = DstContainerVT;
3737 MVT CvtEltVT = DstEltVT;
3738 if (SrcEltSize > (2 * DstEltSize)) {
3739 CvtEltVT = MVT::getIntegerVT(SrcEltVT.getSizeInBits() / 2);
3740 CvtContainerVT = CvtContainerVT.changeVectorElementType(CvtEltVT);
3741 }
3742
3743 unsigned RVVOpc =
3744 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
3745 SDValue Res = DAG.getNode(RVVOpc, DL, CvtContainerVT, Src, Mask, VL);
3746
3747 while (CvtContainerVT != DstContainerVT) {
3748 CvtEltVT = MVT::getIntegerVT(CvtEltVT.getSizeInBits() / 2);
3749 CvtContainerVT = CvtContainerVT.changeVectorElementType(CvtEltVT);
3750 // Rounding mode here is arbitrary since we aren't shifting out any bits.
3751 unsigned ClipOpc = IsSigned ? RISCVISD::TRUNCATE_VECTOR_VL_SSAT
3752 : RISCVISD::TRUNCATE_VECTOR_VL_USAT;
3753 Res = DAG.getNode(ClipOpc, DL, CvtContainerVT, Res, Mask, VL);
3754 }
3755
3756 SDValue SplatZero = DAG.getNode(
3757 RISCVISD::VMV_V_X_VL, DL, DstContainerVT, DAG.getUNDEF(DstContainerVT),
3758 DAG.getConstant(0, DL, Subtarget.getXLenVT()), VL);
3759 Res = DAG.getNode(RISCVISD::VMERGE_VL, DL, DstContainerVT, IsNan, SplatZero,
3760 Res, DAG.getUNDEF(DstContainerVT), VL);
3761
3762 if (DstVT.isFixedLengthVector())
3763 Res = convertFromScalableVector(DstVT, Res, DAG, Subtarget);
3764
3765 return Res;
3766}
3767
3769 const RISCVSubtarget &Subtarget) {
3770 bool IsStrict = Op->isStrictFPOpcode();
3771 SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
3772
3773 // f16 conversions are promoted to f32 when Zfh/Zhinx is not enabled.
3774 // bf16 conversions are always promoted to f32.
3775 if ((SrcVal.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx()) ||
3776 SrcVal.getValueType() == MVT::bf16) {
3777 SDLoc DL(Op);
3778 if (IsStrict) {
3779 SDValue Ext =
3780 DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {MVT::f32, MVT::Other},
3781 {Op.getOperand(0), SrcVal});
3782 return DAG.getNode(Op.getOpcode(), DL, {Op.getValueType(), MVT::Other},
3783 {Ext.getValue(1), Ext.getValue(0)});
3784 }
3785 return DAG.getNode(Op.getOpcode(), DL, Op.getValueType(),
3786 DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, SrcVal));
3787 }
3788
3789 // Other operations are legal.
3790 return Op;
3791}
3792
3794 switch (Opc) {
3795 case ISD::FROUNDEVEN:
3797 return RISCVFPRndMode::RNE;
3798 case ISD::FTRUNC:
3799 case ISD::STRICT_FTRUNC:
3800 return RISCVFPRndMode::RTZ;
3801 case ISD::FFLOOR:
3802 case ISD::STRICT_FFLOOR:
3803 return RISCVFPRndMode::RDN;
3804 case ISD::FCEIL:
3805 case ISD::STRICT_FCEIL:
3806 return RISCVFPRndMode::RUP;
3807 case ISD::FROUND:
3808 case ISD::LROUND:
3809 case ISD::LLROUND:
3810 case ISD::STRICT_FROUND:
3811 case ISD::STRICT_LROUND:
3813 return RISCVFPRndMode::RMM;
3814 case ISD::FRINT:
3815 case ISD::LRINT:
3816 case ISD::LLRINT:
3817 case ISD::STRICT_FRINT:
3818 case ISD::STRICT_LRINT:
3819 case ISD::STRICT_LLRINT:
3820 return RISCVFPRndMode::DYN;
3821 }
3822
3824}
3825
3826// Expand vector FTRUNC, FCEIL, FFLOOR and FROUND by converting to
3827// the integer domain and back. Taking care to avoid converting values that are
3828// nan or already correct.
3829static SDValue
3831 const RISCVSubtarget &Subtarget) {
3832 MVT VT = Op.getSimpleValueType();
3833 assert(VT.isVector() && "Unexpected type");
3834
3835 SDLoc DL(Op);
3836
3837 SDValue Src = Op.getOperand(0);
3838
3839 // Freeze the source since we are increasing the number of uses.
3840 Src = DAG.getFreeze(Src);
3841
3842 MVT ContainerVT = VT;
3843 if (VT.isFixedLengthVector()) {
3844 ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
3845 Src = convertToScalableVector(ContainerVT, Src, DAG, Subtarget);
3846 }
3847
3848 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
3849
3850 // We do the conversion on the absolute value and fix the sign at the end.
3851 SDValue Abs = DAG.getNode(RISCVISD::FABS_VL, DL, ContainerVT, Src, Mask, VL);
3852
3853 // Determine the largest integer that can be represented exactly. This and
3854 // values larger than it don't have any fractional bits so don't need to
3855 // be converted.
3856 const fltSemantics &FltSem = ContainerVT.getFltSemantics();
3857 unsigned Precision = APFloat::semanticsPrecision(FltSem);
3858 APFloat MaxVal = APFloat(FltSem);
3859 MaxVal.convertFromAPInt(APInt::getOneBitSet(Precision, Precision - 1),
3860 /*IsSigned*/ false, APFloat::rmNearestTiesToEven);
3861 SDValue MaxValNode =
3862 DAG.getConstantFP(MaxVal, DL, ContainerVT.getVectorElementType());
3863 SDValue MaxValSplat = DAG.getNode(RISCVISD::VFMV_V_F_VL, DL, ContainerVT,
3864 DAG.getUNDEF(ContainerVT), MaxValNode, VL);
3865
3866 // If abs(Src) was larger than MaxVal or nan, keep it.
3867 MVT SetccVT = MVT::getVectorVT(MVT::i1, ContainerVT.getVectorElementCount());
3868 Mask =
3869 DAG.getNode(RISCVISD::SETCC_VL, DL, SetccVT,
3870 {Abs, MaxValSplat, DAG.getCondCode(ISD::SETOLT),
3871 Mask, Mask, VL});
3872
3873 // Truncate to integer and convert back to FP.
3874 MVT IntVT = ContainerVT.changeVectorElementTypeToInteger();
3875 MVT XLenVT = Subtarget.getXLenVT();
3876 SDValue Truncated;
3877
3878 switch (Op.getOpcode()) {
3879 default:
3880 llvm_unreachable("Unexpected opcode");
3881 case ISD::FRINT:
3882 case ISD::FCEIL:
3883 case ISD::FFLOOR:
3884 case ISD::FROUND:
3885 case ISD::FROUNDEVEN: {
3888 Truncated = DAG.getNode(RISCVISD::VFCVT_RM_X_F_VL, DL, IntVT, Src, Mask,
3889 DAG.getTargetConstant(FRM, DL, XLenVT), VL);
3890 break;
3891 }
3892 case ISD::FTRUNC:
3893 Truncated = DAG.getNode(RISCVISD::VFCVT_RTZ_X_F_VL, DL, IntVT, Src,
3894 Mask, VL);
3895 break;
3896 case ISD::FNEARBYINT:
3897 Truncated = DAG.getNode(RISCVISD::VFROUND_NOEXCEPT_VL, DL, ContainerVT, Src,
3898 Mask, VL);
3899 break;
3900 }
3901
3902 // VFROUND_NOEXCEPT_VL includes SINT_TO_FP_VL.
3903 if (Truncated.getOpcode() != RISCVISD::VFROUND_NOEXCEPT_VL)
3904 Truncated = DAG.getNode(RISCVISD::SINT_TO_FP_VL, DL, ContainerVT, Truncated,
3905 Mask, VL);
3906
3907 // Restore the original sign so that -0.0 is preserved.
3908 Truncated = DAG.getNode(RISCVISD::FCOPYSIGN_VL, DL, ContainerVT, Truncated,
3909 Src, Src, Mask, VL);
3910
3911 if (!VT.isFixedLengthVector())
3912 return Truncated;
3913
3914 return convertFromScalableVector(VT, Truncated, DAG, Subtarget);
3915}
3916
3917// Expand vector STRICT_FTRUNC, STRICT_FCEIL, STRICT_FFLOOR, STRICT_FROUND
3918// STRICT_FROUNDEVEN and STRICT_FNEARBYINT by converting sNan of the source to
3919// qNan and converting the new source to integer and back to FP.
3920static SDValue
3922 const RISCVSubtarget &Subtarget) {
3923 SDLoc DL(Op);
3924 MVT VT = Op.getSimpleValueType();
3925 SDValue Chain = Op.getOperand(0);
3926 SDValue Src = Op.getOperand(1);
3927
3928 MVT ContainerVT = VT;
3929 if (VT.isFixedLengthVector()) {
3930 ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
3931 Src = convertToScalableVector(ContainerVT, Src, DAG, Subtarget);
3932 }
3933
3934 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
3935
3936 // Freeze the source since we are increasing the number of uses.
3937 Src = DAG.getFreeze(Src);
3938
3939 // Convert sNan to qNan by executing x + x for all unordered element x in Src.
3940 MVT MaskVT = Mask.getSimpleValueType();
3941 SDValue Unorder = DAG.getNode(RISCVISD::STRICT_FSETCC_VL, DL,
3942 DAG.getVTList(MaskVT, MVT::Other),
3943 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3944 DAG.getUNDEF(MaskVT), Mask, VL});
3945 Chain = Unorder.getValue(1);
3946 Src = DAG.getNode(RISCVISD::STRICT_FADD_VL, DL,
3947 DAG.getVTList(ContainerVT, MVT::Other),
3948 {Chain, Src, Src, Src, Unorder, VL});
3949 Chain = Src.getValue(1);
3950
3951 // We do the conversion on the absolute value and fix the sign at the end.
3952 SDValue Abs = DAG.getNode(RISCVISD::FABS_VL, DL, ContainerVT, Src, Mask, VL);
3953
3954 // Determine the largest integer that can be represented exactly. This and
3955 // values larger than it don't have any fractional bits so don't need to
3956 // be converted.
3957 const fltSemantics &FltSem = ContainerVT.getFltSemantics();
3958 unsigned Precision = APFloat::semanticsPrecision(FltSem);
3959 APFloat MaxVal = APFloat(FltSem);
3960 MaxVal.convertFromAPInt(APInt::getOneBitSet(Precision, Precision - 1),
3961 /*IsSigned*/ false, APFloat::rmNearestTiesToEven);
3962 SDValue MaxValNode =
3963 DAG.getConstantFP(MaxVal, DL, ContainerVT.getVectorElementType());
3964 SDValue MaxValSplat = DAG.getNode(RISCVISD::VFMV_V_F_VL, DL, ContainerVT,
3965 DAG.getUNDEF(ContainerVT), MaxValNode, VL);
3966
3967 // If abs(Src) was larger than MaxVal or nan, keep it.
3968 Mask = DAG.getNode(
3969 RISCVISD::SETCC_VL, DL, MaskVT,
3970 {Abs, MaxValSplat, DAG.getCondCode(ISD::SETOLT), Mask, Mask, VL});
3971
3972 // Truncate to integer and convert back to FP.
3973 MVT IntVT = ContainerVT.changeVectorElementTypeToInteger();
3974 MVT XLenVT = Subtarget.getXLenVT();
3975 SDValue Truncated;
3976
3977 switch (Op.getOpcode()) {
3978 default:
3979 llvm_unreachable("Unexpected opcode");
3980 case ISD::STRICT_FCEIL:
3981 case ISD::STRICT_FFLOOR:
3982 case ISD::STRICT_FROUND:
3986 Truncated = DAG.getNode(
3987 RISCVISD::STRICT_VFCVT_RM_X_F_VL, DL, DAG.getVTList(IntVT, MVT::Other),
3988 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3989 break;
3990 }
3991 case ISD::STRICT_FTRUNC:
3992 Truncated =
3993 DAG.getNode(RISCVISD::STRICT_VFCVT_RTZ_X_F_VL, DL,
3994 DAG.getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3995 break;
3997 Truncated = DAG.getNode(RISCVISD::STRICT_VFROUND_NOEXCEPT_VL, DL,
3998 DAG.getVTList(ContainerVT, MVT::Other), Chain, Src,
3999 Mask, VL);
4000 break;
4001 }
4002 Chain = Truncated.getValue(1);
4003
4004 // VFROUND_NOEXCEPT_VL includes SINT_TO_FP_VL.
4005 if (Op.getOpcode() != ISD::STRICT_FNEARBYINT) {
4006 Truncated = DAG.getNode(RISCVISD::STRICT_SINT_TO_FP_VL, DL,
4007 DAG.getVTList(ContainerVT, MVT::Other), Chain,
4008 Truncated, Mask, VL);
4009 Chain = Truncated.getValue(1);
4010 }
4011
4012 // Restore the original sign so that -0.0 is preserved.
4013 Truncated = DAG.getNode(RISCVISD::FCOPYSIGN_VL, DL, ContainerVT, Truncated,
4014 Src, Src, Mask, VL);
4015
4016 if (VT.isFixedLengthVector())
4017 Truncated = convertFromScalableVector(VT, Truncated, DAG, Subtarget);
4018 return DAG.getMergeValues({Truncated, Chain}, DL);
4019}
4020
4021static SDValue
4023 const RISCVSubtarget &Subtarget) {
4024 MVT VT = Op.getSimpleValueType();
4025 if (VT.isVector())
4026 return lowerVectorFTRUNC_FCEIL_FFLOOR_FROUND(Op, DAG, Subtarget);
4027
4028 if (DAG.shouldOptForSize())
4029 return SDValue();
4030
4031 SDLoc DL(Op);
4032 SDValue Src = Op.getOperand(0);
4033
4034 // Create an integer the size of the mantissa with the MSB set. This and all
4035 // values larger than it don't have any fractional bits so don't need to be
4036 // converted.
4037 const fltSemantics &FltSem = VT.getFltSemantics();
4038 unsigned Precision = APFloat::semanticsPrecision(FltSem);
4039 APFloat MaxVal = APFloat(FltSem);
4040 MaxVal.convertFromAPInt(APInt::getOneBitSet(Precision, Precision - 1),
4041 /*IsSigned*/ false, APFloat::rmNearestTiesToEven);
4042 SDValue MaxValNode = DAG.getConstantFP(MaxVal, DL, VT);
4043
4045 return DAG.getNode(RISCVISD::FROUND, DL, VT, Src, MaxValNode,
4046 DAG.getTargetConstant(FRM, DL, Subtarget.getXLenVT()));
4047}
4048
4049// Expand vector [L]LRINT and [L]LROUND by converting to the integer domain.
4051 const RISCVSubtarget &Subtarget) {
4052 SDLoc DL(Op);
4053 MVT DstVT = Op.getSimpleValueType();
4054 SDValue Src = Op.getOperand(0);
4055 MVT SrcVT = Src.getSimpleValueType();
4056 assert(SrcVT.isVector() && DstVT.isVector() &&
4057 !(SrcVT.isFixedLengthVector() ^ DstVT.isFixedLengthVector()) &&
4058 "Unexpected type");
4059
4060 MVT DstContainerVT = DstVT;
4061 MVT SrcContainerVT = SrcVT;
4062
4063 if (DstVT.isFixedLengthVector()) {
4064 DstContainerVT = getContainerForFixedLengthVector(DstVT, Subtarget);
4065 SrcContainerVT = getContainerForFixedLengthVector(SrcVT, Subtarget);
4066 Src = convertToScalableVector(SrcContainerVT, Src, DAG, Subtarget);
4067 }
4068
4069 auto [Mask, VL] = getDefaultVLOps(SrcVT, SrcContainerVT, DL, DAG, Subtarget);
4070
4071 // [b]f16 -> f32
4072 MVT SrcElemType = SrcVT.getVectorElementType();
4073 if (SrcElemType == MVT::f16 || SrcElemType == MVT::bf16) {
4074 MVT F32VT = SrcContainerVT.changeVectorElementType(MVT::f32);
4075 Src = DAG.getNode(RISCVISD::FP_EXTEND_VL, DL, F32VT, Src, Mask, VL);
4076 }
4077
4078 SDValue Res =
4079 DAG.getNode(RISCVISD::VFCVT_RM_X_F_VL, DL, DstContainerVT, Src, Mask,
4080 DAG.getTargetConstant(matchRoundingOp(Op.getOpcode()), DL,
4081 Subtarget.getXLenVT()),
4082 VL);
4083
4084 if (!DstVT.isFixedLengthVector())
4085 return Res;
4086
4087 return convertFromScalableVector(DstVT, Res, DAG, Subtarget);
4088}
4089
4090static SDValue
4092 const SDLoc &DL, EVT VT, SDValue Passthru, SDValue Op,
4093 SDValue Offset, SDValue Mask, SDValue VL,
4095 if (Passthru.isUndef())
4097 SDValue PolicyOp = DAG.getTargetConstant(Policy, DL, Subtarget.getXLenVT());
4098 SDValue Ops[] = {Passthru, Op, Offset, Mask, VL, PolicyOp};
4099 return DAG.getNode(RISCVISD::VSLIDEDOWN_VL, DL, VT, Ops);
4100}
4101
4102static SDValue
4103getVSlideup(SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const SDLoc &DL,
4104 EVT VT, SDValue Passthru, SDValue Op, SDValue Offset, SDValue Mask,
4105 SDValue VL,
4107 if (Passthru.isUndef())
4109 SDValue PolicyOp = DAG.getTargetConstant(Policy, DL, Subtarget.getXLenVT());
4110 SDValue Ops[] = {Passthru, Op, Offset, Mask, VL, PolicyOp};
4111 return DAG.getNode(RISCVISD::VSLIDEUP_VL, DL, VT, Ops);
4112}
4113
4117 int64_t Addend;
4118};
4119
4120static std::optional<APInt> getExactInteger(const APFloat &APF,
4122 // We will use a SINT_TO_FP to materialize this constant so we should use a
4123 // signed APSInt here.
4124 APSInt ValInt(BitWidth, /*IsUnsigned*/ false);
4125 // We use an arbitrary rounding mode here. If a floating-point is an exact
4126 // integer (e.g., 1.0), the rounding mode does not affect the output value. If
4127 // the rounding mode changes the output value, then it is not an exact
4128 // integer.
4130 bool IsExact;
4131 // If it is out of signed integer range, it will return an invalid operation.
4132 // If it is not an exact integer, IsExact is false.
4133 if ((APF.convertToInteger(ValInt, ArbitraryRM, &IsExact) ==
4135 !IsExact)
4136 return std::nullopt;
4137 return ValInt.extractBits(BitWidth, 0);
4138}
4139
4140// Try to match an arithmetic-sequence BUILD_VECTOR [X,X+S,X+2*S,...,X+(N-1)*S]
4141// to the (non-zero) step S and start value X. This can be then lowered as the
4142// RVV sequence (VID * S) + X, for example.
4143// The step S is represented as an integer numerator divided by a positive
4144// denominator. Note that the implementation currently only identifies
4145// sequences in which either the numerator is +/- 1 or the denominator is 1. It
4146// cannot detect 2/3, for example.
4147// Note that this method will also match potentially unappealing index
4148// sequences, like <i32 0, i32 50939494>, however it is left to the caller to
4149// determine whether this is worth generating code for.
4150//
4151// EltSizeInBits is the size of the type that the sequence will be calculated
4152// in, i.e. SEW for build_vectors or XLEN for address calculations.
4153static std::optional<VIDSequence> isSimpleVIDSequence(SDValue Op,
4154 unsigned EltSizeInBits) {
4155 assert(Op.getOpcode() == ISD::BUILD_VECTOR && "Unexpected BUILD_VECTOR");
4157 return std::nullopt;
4158 bool IsInteger = Op.getValueType().isInteger();
4159
4160 std::optional<unsigned> SeqStepDenom;
4161 std::optional<APInt> SeqStepNum;
4162 std::optional<APInt> SeqAddend;
4163 std::optional<std::pair<APInt, unsigned>> PrevElt;
4164 assert(EltSizeInBits >= Op.getValueType().getScalarSizeInBits());
4165
4166 // First extract the ops into a list of constant integer values. This may not
4167 // be possible for floats if they're not all representable as integers.
4168 SmallVector<std::optional<APInt>> Elts(Op.getNumOperands());
4169 const unsigned OpSize = Op.getScalarValueSizeInBits();
4170 for (auto [Idx, Elt] : enumerate(Op->op_values())) {
4171 if (Elt.isUndef()) {
4172 Elts[Idx] = std::nullopt;
4173 continue;
4174 }
4175 if (IsInteger) {
4176 Elts[Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
4177 } else {
4178 auto ExactInteger =
4179 getExactInteger(cast<ConstantFPSDNode>(Elt)->getValueAPF(), OpSize);
4180 if (!ExactInteger)
4181 return std::nullopt;
4182 Elts[Idx] = *ExactInteger;
4183 }
4184 }
4185
4186 for (auto [Idx, Elt] : enumerate(Elts)) {
4187 // Assume undef elements match the sequence; we just have to be careful
4188 // when interpolating across them.
4189 if (!Elt)
4190 continue;
4191
4192 if (PrevElt) {
4193 // Calculate the step since the last non-undef element, and ensure
4194 // it's consistent across the entire sequence.
4195 unsigned IdxDiff = Idx - PrevElt->second;
4196 APInt ValDiff = *Elt - PrevElt->first;
4197
4198 // A zero-value value difference means that we're somewhere in the middle
4199 // of a fractional step, e.g. <0,0,0*,0,1,1,1,1>. Wait until we notice a
4200 // step change before evaluating the sequence.
4201 if (ValDiff == 0)
4202 continue;
4203
4204 int64_t Remainder = ValDiff.srem(IdxDiff);
4205 // Normalize the step if it's greater than 1.
4206 if (Remainder != ValDiff.getSExtValue()) {
4207 // The difference must cleanly divide the element span.
4208 if (Remainder != 0)
4209 return std::nullopt;
4210 ValDiff = ValDiff.sdiv(IdxDiff);
4211 IdxDiff = 1;
4212 }
4213
4214 if (!SeqStepNum)
4215 SeqStepNum = ValDiff;
4216 else if (ValDiff != SeqStepNum)
4217 return std::nullopt;
4218
4219 if (!SeqStepDenom)
4220 SeqStepDenom = IdxDiff;
4221 else if (IdxDiff != *SeqStepDenom)
4222 return std::nullopt;
4223 }
4224
4225 // Record this non-undef element for later.
4226 if (!PrevElt || PrevElt->first != *Elt)
4227 PrevElt = std::make_pair(*Elt, Idx);
4228 }
4229
4230 // We need to have logged a step for this to count as a legal index sequence.
4231 if (!SeqStepNum || !SeqStepDenom)
4232 return std::nullopt;
4233
4234 // Loop back through the sequence and validate elements we might have skipped
4235 // while waiting for a valid step. While doing this, log any sequence addend.
4236 for (auto [Idx, Elt] : enumerate(Elts)) {
4237 if (!Elt)
4238 continue;
4239 APInt ExpectedVal =
4240 (APInt(EltSizeInBits, Idx, /*isSigned=*/false, /*implicitTrunc=*/true) *
4241 *SeqStepNum)
4242 .sdiv(*SeqStepDenom);
4243
4244 APInt Addend = *Elt - ExpectedVal;
4245 if (!SeqAddend)
4246 SeqAddend = Addend;
4247 else if (Addend != SeqAddend)
4248 return std::nullopt;
4249 }
4250
4251 assert(SeqAddend && "Must have an addend if we have a step");
4252
4253 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
4254 SeqAddend->getSExtValue()};
4255}
4256
4257// Match a splatted value (SPLAT_VECTOR/BUILD_VECTOR) of an EXTRACT_VECTOR_ELT
4258// and lower it as a VRGATHER_VX_VL from the source vector.
4259static SDValue matchSplatAsGather(SDValue SplatVal, MVT VT, const SDLoc &DL,
4260 SelectionDAG &DAG,
4261 const RISCVSubtarget &Subtarget) {
4262 if (SplatVal.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
4263 return SDValue();
4264 SDValue Src = SplatVal.getOperand(0);
4265 // Don't perform this optimization for i1 vectors, or if the element types are
4266 // different
4267 // FIXME: Support i1 vectors, maybe by promoting to i8?
4268 MVT EltTy = VT.getVectorElementType();
4269 if (EltTy == MVT::i1 ||
4270 !DAG.getTargetLoweringInfo().isTypeLegal(Src.getValueType()))
4271 return SDValue();
4272 MVT SrcVT = Src.getSimpleValueType();
4273 if (EltTy != SrcVT.getVectorElementType())
4274 return SDValue();
4275 SDValue Idx = SplatVal.getOperand(1);
4276 // The index must be a legal type.
4277 if (Idx.getValueType() != Subtarget.getXLenVT())
4278 return SDValue();
4279
4280 // Check that we know Idx lies within VT
4281 if (!TypeSize::isKnownLE(SrcVT.getSizeInBits(), VT.getSizeInBits())) {
4282 auto *CIdx = dyn_cast<ConstantSDNode>(Idx);
4283 if (!CIdx || CIdx->getZExtValue() >= VT.getVectorMinNumElements())
4284 return SDValue();
4285 }
4286
4287 // Convert fixed length vectors to scalable
4288 MVT ContainerVT = VT;
4289 if (VT.isFixedLengthVector())
4290 ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
4291
4292 MVT SrcContainerVT = SrcVT;
4293 if (SrcVT.isFixedLengthVector()) {
4294 SrcContainerVT = getContainerForFixedLengthVector(SrcVT, Subtarget);
4295 Src = convertToScalableVector(SrcContainerVT, Src, DAG, Subtarget);
4296 }
4297
4298 // Put Vec in a VT sized vector
4299 if (SrcContainerVT.getVectorMinNumElements() <
4300 ContainerVT.getVectorMinNumElements())
4301 Src = DAG.getInsertSubvector(DL, DAG.getUNDEF(ContainerVT), Src, 0);
4302 else
4303 Src = DAG.getExtractSubvector(DL, ContainerVT, Src, 0);
4304
4305 // We checked that Idx fits inside VT earlier
4306 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
4307 SDValue Gather = DAG.getNode(RISCVISD::VRGATHER_VX_VL, DL, ContainerVT, Src,
4308 Idx, DAG.getUNDEF(ContainerVT), Mask, VL);
4309 if (VT.isFixedLengthVector())
4310 Gather = convertFromScalableVector(VT, Gather, DAG, Subtarget);
4311 return Gather;
4312}
4313
4315 const RISCVSubtarget &Subtarget) {
4316 MVT VT = Op.getSimpleValueType();
4317 assert(VT.isFixedLengthVector() && "Unexpected vector!");
4318
4319 MVT ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
4320
4321 SDLoc DL(Op);
4322 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
4323
4324 if (auto SimpleVID = isSimpleVIDSequence(Op, Op.getScalarValueSizeInBits())) {
4325 int64_t StepNumerator = SimpleVID->StepNumerator;
4326 unsigned StepDenominator = SimpleVID->StepDenominator;
4327 int64_t Addend = SimpleVID->Addend;
4328
4329 assert(StepNumerator != 0 && "Invalid step");
4330 bool Negate = false;
4331 int64_t SplatStepVal = StepNumerator;
4332 unsigned StepOpcode = ISD::MUL;
4333 // Exclude INT64_MIN to avoid passing it to std::abs. We won't optimize it
4334 // anyway as the shift of 63 won't fit in uimm5.
4335 if (StepNumerator != 1 && StepNumerator != INT64_MIN &&
4336 isPowerOf2_64(std::abs(StepNumerator))) {
4337 Negate = StepNumerator < 0;
4338 StepOpcode = ISD::SHL;
4339 SplatStepVal = Log2_64(std::abs(StepNumerator));
4340 }
4341
4342 // Only emit VIDs with suitably-small steps. We use imm5 as a threshold
4343 // since it's the immediate value many RVV instructions accept. There is
4344 // no vmul.vi instruction so ensure multiply constant can fit in a
4345 // single addi instruction. For the addend, we allow up to 32 bits..
4346 if (((StepOpcode == ISD::MUL && isInt<12>(SplatStepVal)) ||
4347 (StepOpcode == ISD::SHL && isUInt<5>(SplatStepVal))) &&
4348 isPowerOf2_32(StepDenominator) &&
4349 (SplatStepVal >= 0 || StepDenominator == 1) && isInt<32>(Addend)) {
4350 MVT VIDVT =
4352 MVT VIDContainerVT = getContainerForFixedLengthVector(VIDVT, Subtarget);
4353 SDValue VID = DAG.getNode(RISCVISD::VID_VL, DL, VIDContainerVT, Mask, VL);
4354 // Convert right out of the scalable type so we can use standard ISD
4355 // nodes for the rest of the computation. If we used scalable types with
4356 // these, we'd lose the fixed-length vector info and generate worse
4357 // vsetvli code.
4358 VID = convertFromScalableVector(VIDVT, VID, DAG, Subtarget);
4359 if ((StepOpcode == ISD::MUL && SplatStepVal != 1) ||
4360 (StepOpcode == ISD::SHL && SplatStepVal != 0)) {
4361 SDValue SplatStep = DAG.getSignedConstant(SplatStepVal, DL, VIDVT);
4362 VID = DAG.getNode(StepOpcode, DL, VIDVT, VID, SplatStep);
4363 }
4364 if (StepDenominator != 1) {
4365 SDValue SplatStep =
4366 DAG.getConstant(Log2_64(StepDenominator), DL, VIDVT);
4367 VID = DAG.getNode(ISD::SRL, DL, VIDVT, VID, SplatStep);
4368 }
4369 if (Addend != 0 || Negate) {
4370 SDValue SplatAddend = DAG.getSignedConstant(Addend, DL, VIDVT);
4371 VID = DAG.getNode(Negate ? ISD::SUB : ISD::ADD, DL, VIDVT, SplatAddend,
4372 VID);
4373 }
4374 if (VT.isFloatingPoint()) {
4375 // TODO: Use vfwcvt to reduce register pressure.
4376 VID = DAG.getNode(ISD::SINT_TO_FP, DL, VT, VID);
4377 }
4378 return VID;
4379 }
4380 }
4381
4382 return SDValue();
4383}
4384
4385/// Try and optimize BUILD_VECTORs with "dominant values" - these are values
4386/// which constitute a large proportion of the elements. In such cases we can
4387/// splat a vector with the dominant element and make up the shortfall with
4388/// INSERT_VECTOR_ELTs. Returns SDValue if not profitable.
4389/// Note that this includes vectors of 2 elements by association. The
4390/// upper-most element is the "dominant" one, allowing us to use a splat to
4391/// "insert" the upper element, and an insert of the lower element at position
4392/// 0, which improves codegen.
4394 const RISCVSubtarget &Subtarget) {
4395 MVT VT = Op.getSimpleValueType();
4396 assert(VT.isFixedLengthVector() && "Unexpected vector!");
4397
4398 MVT ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
4399
4400 SDLoc DL(Op);
4401 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
4402
4403 MVT XLenVT = Subtarget.getXLenVT();
4404 unsigned NumElts = Op.getNumOperands();
4405
4406 SDValue DominantValue;
4407 unsigned MostCommonCount = 0;
4408 DenseMap<SDValue, unsigned> ValueCounts;
4409 unsigned NumUndefElts =
4410 count_if(Op->op_values(), [](const SDValue &V) { return V.isUndef(); });
4411
4412 // Track the number of scalar loads we know we'd be inserting, estimated as
4413 // any non-zero floating-point constant. Other kinds of element are either
4414 // already in registers or are materialized on demand. The threshold at which
4415 // a vector load is more desirable than several scalar materializion and
4416 // vector-insertion instructions is not known.
4417 unsigned NumScalarLoads = 0;
4418
4419 for (SDValue V : Op->op_values()) {
4420 if (V.isUndef())
4421 continue;
4422
4423 unsigned &Count = ValueCounts[V];
4424 if (0 == Count)
4425 if (auto *CFP = dyn_cast<ConstantFPSDNode>(V))
4426 NumScalarLoads += !CFP->isPosZero();
4427
4428 // Is this value dominant? In case of a tie, prefer the highest element as
4429 // it's cheaper to insert near the beginning of a vector than it is at the
4430 // end.
4431 if (++Count >= MostCommonCount) {
4432 DominantValue = V;
4433 MostCommonCount = Count;
4434 }
4435 }
4436
4437 assert(DominantValue && "Not expecting an all-undef BUILD_VECTOR");
4438 unsigned NumDefElts = NumElts - NumUndefElts;
4439 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
4440
4441 // Don't perform this optimization when optimizing for size, since
4442 // materializing elements and inserting them tends to cause code bloat.
4443 if (!DAG.shouldOptForSize() && NumScalarLoads < NumElts &&
4444 (NumElts != 2 || ISD::isBuildVectorOfConstantSDNodes(Op.getNode())) &&
4445 ((MostCommonCount > DominantValueCountThreshold) ||
4446 (ValueCounts.size() <= Log2_32(NumDefElts)))) {
4447 // Start by splatting the most common element.
4448 SDValue Vec = DAG.getSplatBuildVector(VT, DL, DominantValue);
4449
4450 DenseSet<SDValue> Processed{DominantValue};
4451
4452 // We can handle an insert into the last element (of a splat) via
4453 // v(f)slide1down. This is slightly better than the vslideup insert
4454 // lowering as it avoids the need for a vector group temporary. It
4455 // is also better than using vmerge.vx as it avoids the need to
4456 // materialize the mask in a vector register.
4457 if (SDValue LastOp = Op->getOperand(Op->getNumOperands() - 1);
4458 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
4459 LastOp != DominantValue) {
4460 Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget);
4461 auto OpCode =
4462 VT.isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL;
4463 if (!VT.isFloatingPoint())
4464 LastOp = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, LastOp);
4465 Vec = DAG.getNode(OpCode, DL, ContainerVT, DAG.getUNDEF(ContainerVT), Vec,
4466 LastOp, Mask, VL);
4467 Vec = convertFromScalableVector(VT, Vec, DAG, Subtarget);
4468 Processed.insert(LastOp);
4469 }
4470
4471 MVT SelMaskTy = VT.changeVectorElementType(MVT::i1);
4472 for (const auto &OpIdx : enumerate(Op->ops())) {
4473 const SDValue &V = OpIdx.value();
4474 if (V.isUndef() || !Processed.insert(V).second)
4475 continue;
4476 if (ValueCounts[V] == 1) {
4477 Vec = DAG.getInsertVectorElt(DL, Vec, V, OpIdx.index());
4478 } else {
4479 // Blend in all instances of this value using a VSELECT, using a
4480 // mask where each bit signals whether that element is the one
4481 // we're after.
4483 transform(Op->op_values(), std::back_inserter(Ops), [&](SDValue V1) {
4484 return DAG.getConstant(V == V1, DL, XLenVT);
4485 });
4486 Vec = DAG.getNode(ISD::VSELECT, DL, VT,
4487 DAG.getBuildVector(SelMaskTy, DL, Ops),
4488 DAG.getSplatBuildVector(VT, DL, V), Vec);
4489 }
4490 }
4491
4492 return Vec;
4493 }
4494
4495 return SDValue();
4496}
4497
4499 const RISCVSubtarget &Subtarget) {
4500 MVT VT = Op.getSimpleValueType();
4501 assert(VT.isFixedLengthVector() && "Unexpected vector!");
4502
4503 MVT ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
4504
4505 SDLoc DL(Op);
4506 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
4507
4508 MVT XLenVT = Subtarget.getXLenVT();
4509 unsigned NumElts = Op.getNumOperands();
4510
4511 if (VT.getVectorElementType() == MVT::i1) {
4512 if (ISD::isBuildVectorAllZeros(Op.getNode())) {
4513 SDValue VMClr = DAG.getNode(RISCVISD::VMCLR_VL, DL, ContainerVT, VL);
4514 return convertFromScalableVector(VT, VMClr, DAG, Subtarget);
4515 }
4516
4517 if (ISD::isBuildVectorAllOnes(Op.getNode())) {
4518 SDValue VMSet = DAG.getNode(RISCVISD::VMSET_VL, DL, ContainerVT, VL);
4519 return convertFromScalableVector(VT, VMSet, DAG, Subtarget);
4520 }
4521
4522 // Lower constant mask BUILD_VECTORs via an integer vector type, in
4523 // scalar integer chunks whose bit-width depends on the number of mask
4524 // bits and XLEN.
4525 // First, determine the most appropriate scalar integer type to use. This
4526 // is at most XLenVT, but may be shrunk to a smaller vector element type
4527 // according to the size of the final vector - use i8 chunks rather than
4528 // XLenVT if we're producing a v8i1. This results in more consistent
4529 // codegen across RV32 and RV64.
4530 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.getXLen());
4531 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.getELen());
4532 // If we have to use more than one INSERT_VECTOR_ELT then this
4533 // optimization is likely to increase code size; avoid performing it in
4534 // such a case. We can use a load from a constant pool in this case.
4535 if (DAG.shouldOptForSize() && NumElts > NumViaIntegerBits)
4536 return SDValue();
4537 // Now we can create our integer vector type. Note that it may be larger
4538 // than the resulting mask type: v4i1 would use v1i8 as its integer type.
4539 unsigned IntegerViaVecElts = divideCeil(NumElts, NumViaIntegerBits);
4540 MVT IntegerViaVecVT =
4541 MVT::getVectorVT(MVT::getIntegerVT(NumViaIntegerBits),
4542 IntegerViaVecElts);
4543
4544 uint64_t Bits = 0;
4545 unsigned BitPos = 0, IntegerEltIdx = 0;
4546 SmallVector<SDValue, 8> Elts(IntegerViaVecElts);
4547
4548 for (unsigned I = 0; I < NumElts;) {
4549 SDValue V = Op.getOperand(I);
4550 bool BitValue = !V.isUndef() && V->getAsZExtVal();
4551 Bits |= ((uint64_t)BitValue << BitPos);
4552 ++BitPos;
4553 ++I;
4554
4555 // Once we accumulate enough bits to fill our scalar type or process the
4556 // last element, insert into our vector and clear our accumulated data.
4557 if (I % NumViaIntegerBits == 0 || I == NumElts) {
4558 if (NumViaIntegerBits <= 32)
4559 Bits = SignExtend64<32>(Bits);
4560 SDValue Elt = DAG.getSignedConstant(Bits, DL, XLenVT);
4561 Elts[IntegerEltIdx] = Elt;
4562 Bits = 0;
4563 BitPos = 0;
4564 IntegerEltIdx++;
4565 }
4566 }
4567
4568 SDValue Vec = DAG.getBuildVector(IntegerViaVecVT, DL, Elts);
4569
4570 if (NumElts < NumViaIntegerBits) {
4571 // If we're producing a smaller vector than our minimum legal integer
4572 // type, bitcast to the equivalent (known-legal) mask type, and extract
4573 // our final mask.
4574 assert(IntegerViaVecVT == MVT::v1i8 && "Unexpected mask vector type");
4575 Vec = DAG.getBitcast(MVT::v8i1, Vec);
4576 Vec = DAG.getExtractSubvector(DL, VT, Vec, 0);
4577 } else {
4578 // Else we must have produced an integer type with the same size as the
4579 // mask type; bitcast for the final result.
4580 assert(VT.getSizeInBits() == IntegerViaVecVT.getSizeInBits());
4581 Vec = DAG.getBitcast(VT, Vec);
4582 }
4583
4584 return Vec;
4585 }
4586
4588 unsigned Opc = VT.isFloatingPoint() ? RISCVISD::VFMV_V_F_VL
4589 : RISCVISD::VMV_V_X_VL;
4590 if (!VT.isFloatingPoint())
4591 Splat = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, Splat);
4592 Splat =
4593 DAG.getNode(Opc, DL, ContainerVT, DAG.getUNDEF(ContainerVT), Splat, VL);
4594 return convertFromScalableVector(VT, Splat, DAG, Subtarget);
4595 }
4596
4597 // Try and match index sequences, which we can lower to the vid instruction
4598 // with optional modifications. An all-undef vector is matched by
4599 // getSplatValue, above.
4600 if (SDValue Res = lowerBuildVectorViaVID(Op, DAG, Subtarget))
4601 return Res;
4602
4603 // For very small build_vectors, use a single scalar insert of a constant.
4604 // TODO: Base this on constant rematerialization cost, not size.
4605 const unsigned EltBitSize = VT.getScalarSizeInBits();
4606 if (VT.getSizeInBits() <= 32 &&
4608 MVT ViaIntVT = MVT::getIntegerVT(VT.getSizeInBits());
4609 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
4610 "Unexpected sequence type");
4611 // If we can use the original VL with the modified element type, this
4612 // means we only have a VTYPE toggle, not a VL toggle. TODO: Should this
4613 // be moved into InsertVSETVLI?
4614 unsigned ViaVecLen =
4615 (Subtarget.getRealMinVLen() >= VT.getSizeInBits() * NumElts) ? NumElts : 1;
4616 MVT ViaVecVT = MVT::getVectorVT(ViaIntVT, ViaVecLen);
4617
4618 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
4619 uint64_t SplatValue = 0;
4620 // Construct the amalgamated value at this larger vector type.
4621 for (const auto &OpIdx : enumerate(Op->op_values())) {
4622 const auto &SeqV = OpIdx.value();
4623 if (!SeqV.isUndef())
4624 SplatValue |=
4625 ((SeqV->getAsZExtVal() & EltMask) << (OpIdx.index() * EltBitSize));
4626 }
4627
4628 // On RV64, sign-extend from 32 to 64 bits where possible in order to
4629 // achieve better constant materializion.
4630 // On RV32, we need to sign-extend to use getSignedConstant.
4631 if (ViaIntVT == MVT::i32)
4632 SplatValue = SignExtend64<32>(SplatValue);
4633
4634 SDValue Vec = DAG.getInsertVectorElt(
4635 DL, DAG.getUNDEF(ViaVecVT),
4636 DAG.getSignedConstant(SplatValue, DL, XLenVT), 0);
4637 if (ViaVecLen != 1)
4638 Vec = DAG.getExtractSubvector(DL, MVT::getVectorVT(ViaIntVT, 1), Vec, 0);
4639 return DAG.getBitcast(VT, Vec);
4640 }
4641
4642
4643 // Attempt to detect "hidden" splats, which only reveal themselves as splats
4644 // when re-interpreted as a vector with a larger element type. For example,
4645 // v4i16 = build_vector i16 0, i16 1, i16 0, i16 1
4646 // could be instead splat as
4647 // v2i32 = build_vector i32 0x00010000, i32 0x00010000
4648 // TODO: This optimization could also work on non-constant splats, but it
4649 // would require bit-manipulation instructions to construct the splat value.
4650 SmallVector<SDValue> Sequence;
4651 const auto *BV = cast<BuildVectorSDNode>(Op);
4652 if (VT.isInteger() && EltBitSize < Subtarget.getELen() &&
4654 BV->getRepeatedSequence(Sequence) &&
4655 (Sequence.size() * EltBitSize) <= Subtarget.getELen()) {
4656 unsigned SeqLen = Sequence.size();
4657 MVT ViaIntVT = MVT::getIntegerVT(EltBitSize * SeqLen);
4658 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
4659 ViaIntVT == MVT::i64) &&
4660 "Unexpected sequence type");
4661
4662 // If we can use the original VL with the modified element type, this
4663 // means we only have a VTYPE toggle, not a VL toggle. TODO: Should this
4664 // be moved into InsertVSETVLI?
4665 const unsigned RequiredVL = NumElts / SeqLen;
4666 const unsigned ViaVecLen =
4667 (Subtarget.getRealMinVLen() >= ViaIntVT.getSizeInBits() * NumElts) ?
4668 NumElts : RequiredVL;
4669 MVT ViaVecVT = MVT::getVectorVT(ViaIntVT, ViaVecLen);
4670
4671 unsigned EltIdx = 0;
4672 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
4673 uint64_t SplatValue = 0;
4674 // Construct the amalgamated value which can be splatted as this larger
4675 // vector type.
4676 for (const auto &SeqV : Sequence) {
4677 if (!SeqV.isUndef())
4678 SplatValue |=
4679 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
4680 EltIdx++;
4681 }
4682
4683 // On RV64, sign-extend from 32 to 64 bits where possible in order to
4684 // achieve better constant materializion.
4685 // On RV32, we need to sign-extend to use getSignedConstant.
4686 if (ViaIntVT == MVT::i32)
4687 SplatValue = SignExtend64<32>(SplatValue);
4688
4689 // Since we can't introduce illegal i64 types at this stage, we can only
4690 // perform an i64 splat on RV32 if it is its own sign-extended value. That
4691 // way we can use RVV instructions to splat.
4692 assert((ViaIntVT.bitsLE(XLenVT) ||
4693 (!Subtarget.is64Bit() && ViaIntVT == MVT::i64)) &&
4694 "Unexpected bitcast sequence");
4695 if (ViaIntVT.bitsLE(XLenVT) || isInt<32>(SplatValue)) {
4696 SDValue ViaVL =
4697 DAG.getConstant(ViaVecVT.getVectorNumElements(), DL, XLenVT);
4698 MVT ViaContainerVT =
4699 getContainerForFixedLengthVector(ViaVecVT, Subtarget);
4700 SDValue Splat =
4701 DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ViaContainerVT,
4702 DAG.getUNDEF(ViaContainerVT),
4703 DAG.getSignedConstant(SplatValue, DL, XLenVT), ViaVL);
4704 Splat = convertFromScalableVector(ViaVecVT, Splat, DAG, Subtarget);
4705 if (ViaVecLen != RequiredVL)
4707 DL, MVT::getVectorVT(ViaIntVT, RequiredVL), Splat, 0);
4708 return DAG.getBitcast(VT, Splat);
4709 }
4710 }
4711
4712 // If the number of signbits allows, see if we can lower as a <N x i8>.
4713 // Our main goal here is to reduce LMUL (and thus work) required to
4714 // build the constant, but we will also narrow if the resulting
4715 // narrow vector is known to materialize cheaply.
4716 // TODO: We really should be costing the smaller vector. There are
4717 // profitable cases this misses.
4718 if (EltBitSize > 8 && VT.isInteger() &&
4719 (NumElts <= 4 || VT.getSizeInBits() > Subtarget.getRealMinVLen()) &&
4720 DAG.ComputeMaxSignificantBits(Op) <= 8) {
4721 SDValue Source = DAG.getBuildVector(VT.changeVectorElementType(MVT::i8),
4722 DL, Op->ops());
4723 Source = convertToScalableVector(ContainerVT.changeVectorElementType(MVT::i8),
4724 Source, DAG, Subtarget);
4725 SDValue Res = DAG.getNode(RISCVISD::VSEXT_VL, DL, ContainerVT, Source, Mask, VL);
4726 return convertFromScalableVector(VT, Res, DAG, Subtarget);
4727 }
4728
4729 if (SDValue Res = lowerBuildVectorViaDominantValues(Op, DAG, Subtarget))
4730 return Res;
4731
4732 // For constant vectors, use generic constant pool lowering. Otherwise,
4733 // we'd have to materialize constants in GPRs just to move them into the
4734 // vector.
4735 return SDValue();
4736}
4737
4738static unsigned getPACKOpcode(unsigned DestBW,
4739 const RISCVSubtarget &Subtarget) {
4740 switch (DestBW) {
4741 default:
4742 llvm_unreachable("Unsupported pack size");
4743 case 16:
4744 return RISCV::PACKH;
4745 case 32:
4746 return Subtarget.is64Bit() ? RISCV::PACKW : RISCV::PACK;
4747 case 64:
4748 assert(Subtarget.is64Bit());
4749 return RISCV::PACK;
4750 }
4751}
4752
4753/// Double the element size of the build vector to reduce the number
4754/// of vslide1down in the build vector chain. In the worst case, this
4755/// trades three scalar operations for 1 vector operation. Scalar
4756/// operations are generally lower latency, and for out-of-order cores
4757/// we also benefit from additional parallelism.
4759 const RISCVSubtarget &Subtarget) {
4760 SDLoc DL(Op);
4761 MVT VT = Op.getSimpleValueType();
4762 assert(VT.isFixedLengthVector() && "Unexpected vector!");
4763 MVT ElemVT = VT.getVectorElementType();
4764 if (!ElemVT.isInteger())
4765 return SDValue();
4766
4767 // TODO: Relax these architectural restrictions, possibly with costing
4768 // of the actual instructions required.
4769 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4770 return SDValue();
4771
4772 unsigned NumElts = VT.getVectorNumElements();
4773 unsigned ElemSizeInBits = ElemVT.getSizeInBits();
4774 if (ElemSizeInBits >= std::min(Subtarget.getELen(), Subtarget.getXLen()) ||
4775 NumElts % 2 != 0)
4776 return SDValue();
4777
4778 // Produce [B,A] packed into a type twice as wide. Note that all
4779 // scalars are XLenVT, possibly masked (see below).
4780 MVT XLenVT = Subtarget.getXLenVT();
4781 SDValue Mask = DAG.getConstant(
4782 APInt::getLowBitsSet(XLenVT.getSizeInBits(), ElemSizeInBits), DL, XLenVT);
4783 auto pack = [&](SDValue A, SDValue B) {
4784 // Bias the scheduling of the inserted operations to near the
4785 // definition of the element - this tends to reduce register
4786 // pressure overall.
4787 SDLoc ElemDL(B);
4788 if (Subtarget.hasStdExtZbkb())
4789 // Note that we're relying on the high bits of the result being
4790 // don't care. For PACKW, the result is *sign* extended.
4791 return SDValue(
4792 DAG.getMachineNode(getPACKOpcode(ElemSizeInBits * 2, Subtarget),
4793 ElemDL, XLenVT, A, B),
4794 0);
4795
4796 A = DAG.getNode(ISD::AND, SDLoc(A), XLenVT, A, Mask);
4797 B = DAG.getNode(ISD::AND, SDLoc(B), XLenVT, B, Mask);
4798 SDValue ShtAmt = DAG.getConstant(ElemSizeInBits, ElemDL, XLenVT);
4799 return DAG.getNode(ISD::OR, ElemDL, XLenVT, A,
4800 DAG.getNode(ISD::SHL, ElemDL, XLenVT, B, ShtAmt),
4802 };
4803
4804 SmallVector<SDValue> NewOperands;
4805 NewOperands.reserve(NumElts / 2);
4806 for (unsigned i = 0; i < VT.getVectorNumElements(); i += 2)
4807 NewOperands.push_back(pack(Op.getOperand(i), Op.getOperand(i + 1)));
4808 assert(NumElts == NewOperands.size() * 2);
4809 MVT WideVT = MVT::getIntegerVT(ElemSizeInBits * 2);
4810 MVT WideVecVT = MVT::getVectorVT(WideVT, NumElts / 2);
4811 return DAG.getNode(ISD::BITCAST, DL, VT,
4812 DAG.getBuildVector(WideVecVT, DL, NewOperands));
4813}
4814
4816 const RISCVSubtarget &Subtarget) {
4817 MVT VT = Op.getSimpleValueType();
4818 assert(VT.isFixedLengthVector() && "Unexpected vector!");
4819
4820 MVT EltVT = VT.getVectorElementType();
4821 MVT XLenVT = Subtarget.getXLenVT();
4822
4823 SDLoc DL(Op);
4824
4825 if (!Subtarget.is64Bit() && Subtarget.hasStdExtP()) {
4826 if (VT == MVT::v2i16) {
4827 SDValue Lo = DAG.getBitcast(
4828 MVT::v2i16,
4829 DAG.getAnyExtOrTrunc(Op->getOperand(0), DL, MVT::i32));
4830 SDValue Hi = DAG.getBitcast(
4831 MVT::v2i16,
4832 DAG.getAnyExtOrTrunc(Op->getOperand(1), DL, MVT::i32));
4833 return DAG.getNode(RISCVISD::PPAIRE, DL, MVT::v2i16, Lo, Hi);
4834 }
4835
4836 if (VT == MVT::v4i8) {
4837 // <4 x i8> BUILD_VECTOR a, b, c, d -> PACK(PPACK.DH pair(a, c), pair(b,
4838 // d))
4839 SDValue Val0 =
4840 DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(0));
4841 SDValue Val1 =
4842 DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(1));
4843 SDValue Val2 =
4844 DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(2));
4845 SDValue Val3 =
4846 DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(3));
4847 SDValue Concat1 =
4848 DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i8, Val0, Val2);
4849 SDValue Concat2 =
4850 DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i8, Val1, Val3);
4851 SDValue PPairE =
4852 DAG.getNode(RISCVISD::PPAIRE, DL, MVT::v8i8, Concat1, Concat2);
4853
4854 SDValue Lo = DAG.getExtractSubvector(DL, MVT::v4i8, PPairE, 0);
4855 SDValue Hi = DAG.getExtractSubvector(DL, MVT::v4i8, PPairE, 4);
4856
4857 return DAG.getBitcast(MVT::v4i8,
4858 DAG.getNode(RISCVISD::PPAIRE, DL, MVT::v2i16,
4859 DAG.getBitcast(MVT::v2i16, Lo),
4860 DAG.getBitcast(MVT::v2i16, Hi)));
4861 }
4862
4863 llvm_unreachable("Unexpected RV32 P BUILD_VECTOR type");
4864 }
4865
4866 // Proper support for f16 requires Zvfh. bf16 always requires special
4867 // handling. We need to cast the scalar to integer and create an integer
4868 // build_vector.
4869 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
4870 (EltVT == MVT::bf16 && !Subtarget.hasVInstructionsBF16())) {
4871 MVT IVT = VT.changeVectorElementType(MVT::i16);
4872 SmallVector<SDValue, 16> NewOps(Op.getNumOperands());
4873 for (const auto &[I, U] : enumerate(Op->ops())) {
4874 SDValue Elem = U.get();
4875 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4876 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4877 // Called by LegalizeDAG, we need to use XLenVT operations since we
4878 // can't create illegal types.
4879 if (auto *C = dyn_cast<ConstantFPSDNode>(Elem)) {
4880 // Manually constant fold so the integer build_vector can be lowered
4881 // better. Waiting for DAGCombine will be too late.
4882 APInt V =
4883 C->getValueAPF().bitcastToAPInt().sext(XLenVT.getSizeInBits());
4884 NewOps[I] = DAG.getConstant(V, DL, XLenVT);
4885 } else {
4886 NewOps[I] = DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, XLenVT, Elem);
4887 }
4888 } else {
4889 // Called by scalar type legalizer, we can use i16.
4890 NewOps[I] = DAG.getBitcast(MVT::i16, Op.getOperand(I));
4891 }
4892 }
4893 SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, DL, IVT, NewOps);
4894 return DAG.getBitcast(VT, Res);
4895 }
4896
4897 if (ISD::isBuildVectorOfConstantSDNodes(Op.getNode()) ||
4899 return lowerBuildVectorOfConstants(Op, DAG, Subtarget);
4900
4901 MVT ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
4902
4903 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
4904
4905 if (VT.getVectorElementType() == MVT::i1) {
4906 // A BUILD_VECTOR can be lowered as a SETCC. For each fixed-length mask
4907 // vector type, we have a legal equivalently-sized i8 type, so we can use
4908 // that.
4909 MVT WideVecVT = VT.changeVectorElementType(MVT::i8);
4910 SDValue VecZero = DAG.getConstant(0, DL, WideVecVT);
4911
4912 SDValue WideVec;
4914 // For a splat, perform a scalar truncate before creating the wider
4915 // vector.
4916 Splat = DAG.getNode(ISD::AND, DL, Splat.getValueType(), Splat,
4917 DAG.getConstant(1, DL, Splat.getValueType()));
4918 WideVec = DAG.getSplatBuildVector(WideVecVT, DL, Splat);
4919 } else {
4920 SmallVector<SDValue, 8> Ops(Op->op_values());
4921 WideVec = DAG.getBuildVector(WideVecVT, DL, Ops);
4922 SDValue VecOne = DAG.getConstant(1, DL, WideVecVT);
4923 WideVec = DAG.getNode(ISD::AND, DL, WideVecVT, WideVec, VecOne);
4924 }
4925
4926 return DAG.getSetCC(DL, VT, WideVec, VecZero, ISD::SETNE);
4927 }
4928
4930 if (auto Gather = matchSplatAsGather(Splat, VT, DL, DAG, Subtarget))
4931 return Gather;
4932
4933 if (!VT.isFloatingPoint())
4934 Splat = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, Splat);
4935
4936 // Prefer vmv.s.x/vfmv.s.f if legal to reduce work and register
4937 // pressure at high LMUL.
4938 bool IsScalar = all_of(Op->ops().drop_front(),
4939 [](const SDUse &U) { return U.get().isUndef(); });
4940 unsigned Opc =
4941 VT.isFloatingPoint()
4942 ? (IsScalar ? RISCVISD::VFMV_S_F_VL : RISCVISD::VFMV_V_F_VL)
4943 : (IsScalar ? RISCVISD::VMV_S_X_VL : RISCVISD::VMV_V_X_VL);
4944 Splat =
4945 DAG.getNode(Opc, DL, ContainerVT, DAG.getUNDEF(ContainerVT), Splat, VL);
4946 return convertFromScalableVector(VT, Splat, DAG, Subtarget);
4947 }
4948
4949 if (SDValue Res = lowerBuildVectorViaDominantValues(Op, DAG, Subtarget))
4950 return Res;
4951
4952 // If we're compiling for an exact VLEN value, we can split our work per
4953 // register in the register group.
4954 if (const auto VLen = Subtarget.getRealVLen();
4955 VLen && VT.getSizeInBits().getKnownMinValue() > *VLen) {
4956 MVT ElemVT = VT.getVectorElementType();
4957 unsigned ElemsPerVReg = *VLen / ElemVT.getFixedSizeInBits();
4958 EVT ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
4959 MVT OneRegVT = MVT::getVectorVT(ElemVT, ElemsPerVReg);
4960 MVT M1VT = getContainerForFixedLengthVector(OneRegVT, Subtarget);
4961 assert(M1VT == RISCVTargetLowering::getM1VT(M1VT));
4962
4963 // The following semantically builds up a fixed length concat_vector
4964 // of the component build_vectors. We eagerly lower to scalable and
4965 // insert_subvector here to avoid DAG combining it back to a large
4966 // build_vector.
4967 SmallVector<SDValue> BuildVectorOps(Op->ops());
4968 unsigned NumOpElts = M1VT.getVectorMinNumElements();
4969 SDValue Vec = DAG.getUNDEF(ContainerVT);
4970 for (unsigned i = 0; i < VT.getVectorNumElements(); i += ElemsPerVReg) {
4971 auto OneVRegOfOps = ArrayRef(BuildVectorOps).slice(i, ElemsPerVReg);
4972 SDValue SubBV =
4973 DAG.getNode(ISD::BUILD_VECTOR, DL, OneRegVT, OneVRegOfOps);
4974 SubBV = convertToScalableVector(M1VT, SubBV, DAG, Subtarget);
4975 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4976 Vec = DAG.getInsertSubvector(DL, Vec, SubBV, InsertIdx);
4977 }
4978 return convertFromScalableVector(VT, Vec, DAG, Subtarget);
4979 }
4980
4981 // If we're about to resort to vslide1down (or stack usage), pack our
4982 // elements into the widest scalar type we can. This will force a VL/VTYPE
4983 // toggle, but reduces the critical path, the number of vslide1down ops
4984 // required, and possibly enables scalar folds of the values.
4985 if (SDValue Res = lowerBuildVectorViaPacking(Op, DAG, Subtarget))
4986 return Res;
4987
4988 // For m1 vectors, if we have non-undef values in both halves of our vector,
4989 // split the vector into low and high halves, build them separately, then
4990 // use a vselect to combine them. For long vectors, this cuts the critical
4991 // path of the vslide1down sequence in half, and gives us an opportunity
4992 // to special case each half independently. Note that we don't change the
4993 // length of the sub-vectors here, so if both fallback to the generic
4994 // vslide1down path, we should be able to fold the vselect into the final
4995 // vslidedown (for the undef tail) for the first half w/ masking.
4996 unsigned NumElts = VT.getVectorNumElements();
4997 unsigned NumUndefElts =
4998 count_if(Op->op_values(), [](const SDValue &V) { return V.isUndef(); });
4999 unsigned NumDefElts = NumElts - NumUndefElts;
5000 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
5001 ContainerVT.bitsLE(RISCVTargetLowering::getM1VT(ContainerVT))) {
5002 SmallVector<SDValue> SubVecAOps, SubVecBOps;
5003 SmallVector<SDValue> MaskVals;
5004 SDValue UndefElem = DAG.getUNDEF(Op->getOperand(0)->getValueType(0));
5005 SubVecAOps.reserve(NumElts);
5006 SubVecBOps.reserve(NumElts);
5007 for (const auto &[Idx, U] : enumerate(Op->ops())) {
5008 SDValue Elem = U.get();
5009 if (Idx < NumElts / 2) {
5010 SubVecAOps.push_back(Elem);
5011 SubVecBOps.push_back(UndefElem);
5012 } else {
5013 SubVecAOps.push_back(UndefElem);
5014 SubVecBOps.push_back(Elem);
5015 }
5016 bool SelectMaskVal = (Idx < NumElts / 2);
5017 MaskVals.push_back(DAG.getConstant(SelectMaskVal, DL, XLenVT));
5018 }
5019 assert(SubVecAOps.size() == NumElts && SubVecBOps.size() == NumElts &&
5020 MaskVals.size() == NumElts);
5021
5022 SDValue SubVecA = DAG.getBuildVector(VT, DL, SubVecAOps);
5023 SDValue SubVecB = DAG.getBuildVector(VT, DL, SubVecBOps);
5024 MVT MaskVT = MVT::getVectorVT(MVT::i1, NumElts);
5025 SDValue SelectMask = DAG.getBuildVector(MaskVT, DL, MaskVals);
5026 return DAG.getNode(ISD::VSELECT, DL, VT, SelectMask, SubVecA, SubVecB);
5027 }
5028
5029 // Cap the cost at a value linear to the number of elements in the vector.
5030 // The default lowering is to use the stack. The vector store + scalar loads
5031 // is linear in VL. However, at high lmuls vslide1down and vslidedown end up
5032 // being (at least) linear in LMUL. As a result, using the vslidedown
5033 // lowering for every element ends up being VL*LMUL..
5034 // TODO: Should we be directly costing the stack alternative? Doing so might
5035 // give us a more accurate upper bound.
5036 InstructionCost LinearBudget = VT.getVectorNumElements() * 2;
5037
5038 // TODO: unify with TTI getSlideCost.
5039 InstructionCost PerSlideCost = 1;
5040 switch (RISCVTargetLowering::getLMUL(ContainerVT)) {
5041 default: break;
5042 case RISCVVType::LMUL_2:
5043 PerSlideCost = 2;
5044 break;
5045 case RISCVVType::LMUL_4:
5046 PerSlideCost = 4;
5047 break;
5048 case RISCVVType::LMUL_8:
5049 PerSlideCost = 8;
5050 break;
5051 }
5052
5053 // TODO: Should we be using the build instseq then cost + evaluate scheme
5054 // we use for integer constants here?
5055 unsigned UndefCount = 0;
5056 for (const SDValue &V : Op->ops()) {
5057 if (V.isUndef()) {
5058 UndefCount++;
5059 continue;
5060 }
5061 if (UndefCount) {
5062 LinearBudget -= PerSlideCost;
5063 UndefCount = 0;
5064 }
5065 LinearBudget -= PerSlideCost;
5066 }
5067 if (UndefCount) {
5068 LinearBudget -= PerSlideCost;
5069 }
5070
5071 if (LinearBudget < 0)
5072 return SDValue();
5073
5074 assert((!VT.isFloatingPoint() ||
5075 VT.getVectorElementType().getSizeInBits() <= Subtarget.getFLen()) &&
5076 "Illegal type which will result in reserved encoding");
5077
5078 const unsigned Policy = RISCVVType::TAIL_AGNOSTIC | RISCVVType::MASK_AGNOSTIC;
5079
5080 // General case: splat the first operand and slide other operands down one
5081 // by one to form a vector. Alternatively, if every operand is an
5082 // extraction from element 0 of a vector, we use that vector from the last
5083 // extraction as the start value and slide up instead of slide down. Such that
5084 // (1) we can avoid the initial splat (2) we can turn those vslide1up into
5085 // vslideup of 1 later and eliminate the vector to scalar movement, which is
5086 // something we cannot do with vslide1down/vslidedown.
5087 // Of course, using vslide1up/vslideup might increase the register pressure,
5088 // and that's why we conservatively limit to cases where every operand is an
5089 // extraction from the first element.
5090 SmallVector<SDValue> Operands(Op->op_begin(), Op->op_end());
5091 SDValue EVec;
5092 bool SlideUp = false;
5093 auto getVSlide = [&](EVT ContainerVT, SDValue Passthru, SDValue Vec,
5094 SDValue Offset, SDValue Mask, SDValue VL) -> SDValue {
5095 if (SlideUp)
5096 return getVSlideup(DAG, Subtarget, DL, ContainerVT, Passthru, Vec, Offset,
5097 Mask, VL, Policy);
5098 return getVSlidedown(DAG, Subtarget, DL, ContainerVT, Passthru, Vec, Offset,
5099 Mask, VL, Policy);
5100 };
5101
5102 // The reason we don't use all_of here is because we're also capturing EVec
5103 // from the last non-undef operand. If the std::execution_policy of the
5104 // underlying std::all_of is anything but std::sequenced_policy we might
5105 // capture the wrong EVec.
5106 for (SDValue V : Operands) {
5107 using namespace SDPatternMatch;
5108 SlideUp = V.isUndef() || sd_match(V, m_ExtractElt(m_Value(EVec), m_Zero()));
5109 if (!SlideUp)
5110 break;
5111 }
5112
5113 // Do not slideup if the element type of EVec is different.
5114 if (SlideUp) {
5115 MVT EVecEltVT = EVec.getSimpleValueType().getVectorElementType();
5116 MVT ContainerEltVT = ContainerVT.getVectorElementType();
5117 if (EVecEltVT != ContainerEltVT)
5118 SlideUp = false;
5119 }
5120
5121 if (SlideUp) {
5122 MVT EVecContainerVT = EVec.getSimpleValueType();
5123 // Make sure the original vector has scalable vector type.
5124 if (EVecContainerVT.isFixedLengthVector()) {
5125 EVecContainerVT =
5126 getContainerForFixedLengthVector(EVecContainerVT, Subtarget);
5127 EVec = convertToScalableVector(EVecContainerVT, EVec, DAG, Subtarget);
5128 }
5129
5130 // Adapt EVec's type into ContainerVT.
5131 if (EVecContainerVT.getVectorMinNumElements() <
5132 ContainerVT.getVectorMinNumElements())
5133 EVec = DAG.getInsertSubvector(DL, DAG.getUNDEF(ContainerVT), EVec, 0);
5134 else
5135 EVec = DAG.getExtractSubvector(DL, ContainerVT, EVec, 0);
5136
5137 // Reverse the elements as we're going to slide up from the last element.
5138 std::reverse(Operands.begin(), Operands.end());
5139 }
5140
5141 SDValue Vec;
5142 UndefCount = 0;
5143 for (SDValue V : Operands) {
5144 if (V.isUndef()) {
5145 UndefCount++;
5146 continue;
5147 }
5148
5149 // Start our sequence with either a TA splat or extract source in the
5150 // hopes that hardware is able to recognize there's no dependency on the
5151 // prior value of our temporary register.
5152 if (!Vec) {
5153 if (SlideUp) {
5154 Vec = EVec;
5155 } else {
5156 Vec = DAG.getSplatVector(VT, DL, V);
5157 Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget);
5158 }
5159
5160 UndefCount = 0;
5161 continue;
5162 }
5163
5164 if (UndefCount) {
5165 const SDValue Offset = DAG.getConstant(UndefCount, DL, Subtarget.getXLenVT());
5166 Vec = getVSlide(ContainerVT, DAG.getUNDEF(ContainerVT), Vec, Offset, Mask,
5167 VL);
5168 UndefCount = 0;
5169 }
5170
5171 unsigned Opcode;
5172 if (VT.isFloatingPoint())
5173 Opcode = SlideUp ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VFSLIDE1DOWN_VL;
5174 else
5175 Opcode = SlideUp ? RISCVISD::VSLIDE1UP_VL : RISCVISD::VSLIDE1DOWN_VL;
5176
5177 if (!VT.isFloatingPoint())
5178 V = DAG.getNode(ISD::ANY_EXTEND, DL, Subtarget.getXLenVT(), V);
5179 Vec = DAG.getNode(Opcode, DL, ContainerVT, DAG.getUNDEF(ContainerVT), Vec,
5180 V, Mask, VL);
5181 }
5182 if (UndefCount) {
5183 const SDValue Offset = DAG.getConstant(UndefCount, DL, Subtarget.getXLenVT());
5184 Vec = getVSlide(ContainerVT, DAG.getUNDEF(ContainerVT), Vec, Offset, Mask,
5185 VL);
5186 }
5187 return convertFromScalableVector(VT, Vec, DAG, Subtarget);
5188}
5189
5190static SDValue splatPartsI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru,
5192 SelectionDAG &DAG) {
5193 if (!Passthru)
5194 Passthru = DAG.getUNDEF(VT);
5196 int32_t LoC = cast<ConstantSDNode>(Lo)->getSExtValue();
5197 int32_t HiC = cast<ConstantSDNode>(Hi)->getSExtValue();
5198 // If Hi constant is all the same sign bit as Lo, lower this as a custom
5199 // node in order to try and match RVV vector/scalar instructions.
5200 if ((LoC >> 31) == HiC)
5201 return DAG.getNode(RISCVISD::VMV_V_X_VL, DL, VT, Passthru, Lo, VL);
5202
5203 // Use vmv.v.x with EEW=32. Use either a vsetivli or vsetvli to change
5204 // VL. This can temporarily increase VL if VL less than VLMAX.
5205 if (LoC == HiC) {
5206 SDValue NewVL;
5207 if (isa<ConstantSDNode>(VL) && isUInt<4>(VL->getAsZExtVal()))
5208 NewVL = DAG.getNode(ISD::ADD, DL, VL.getValueType(), VL, VL);
5209 else
5210 NewVL = DAG.getRegister(RISCV::X0, MVT::i32);
5211 MVT InterVT =
5212 MVT::getVectorVT(MVT::i32, VT.getVectorElementCount() * 2);
5213 auto InterVec = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, InterVT,
5214 DAG.getUNDEF(InterVT), Lo, NewVL);
5215 return DAG.getNode(ISD::BITCAST, DL, VT, InterVec);
5216 }
5217 }
5218
5219 // Detect cases where Hi is (SRA Lo, 31) which means Hi is Lo sign extended.
5220 if (Hi.getOpcode() == ISD::SRA && Hi.getOperand(0) == Lo &&
5221 isa<ConstantSDNode>(Hi.getOperand(1)) &&
5222 Hi.getConstantOperandVal(1) == 31)
5223 return DAG.getNode(RISCVISD::VMV_V_X_VL, DL, VT, Passthru, Lo, VL);
5224
5225 // If the hi bits of the splat are undefined, then it's fine to just splat Lo
5226 // even if it might be sign extended.
5227 if (Hi.isUndef())
5228 return DAG.getNode(RISCVISD::VMV_V_X_VL, DL, VT, Passthru, Lo, VL);
5229
5230 // Fall back to a stack store and stride x0 vector load.
5231 return DAG.getNode(RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL, DL, VT, Passthru, Lo,
5232 Hi, VL);
5233}
5234
5235// Called by type legalization to handle splat of i64 on RV32.
5236// FIXME: We can optimize this when the type has sign or zero bits in one
5237// of the halves.
5238static SDValue splatSplitI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru,
5239 SDValue Scalar, SDValue VL,
5240 SelectionDAG &DAG) {
5241 assert(Scalar.getValueType() == MVT::i64 && "Unexpected VT!");
5242 SDValue Lo, Hi;
5243 std::tie(Lo, Hi) = DAG.SplitScalar(Scalar, DL, MVT::i32, MVT::i32);
5244 return splatPartsI64WithVL(DL, VT, Passthru, Lo, Hi, VL, DAG);
5245}
5246
5247// This function lowers a splat of a scalar operand Splat with the vector
5248// length VL. It ensures the final sequence is type legal, which is useful when
5249// lowering a splat after type legalization.
5250static SDValue lowerScalarSplat(SDValue Passthru, SDValue Scalar, SDValue VL,
5251 MVT VT, const SDLoc &DL, SelectionDAG &DAG,
5252 const RISCVSubtarget &Subtarget) {
5253 bool HasPassthru = Passthru && !Passthru.isUndef();
5254 if (!HasPassthru && !Passthru)
5255 Passthru = DAG.getUNDEF(VT);
5256
5257 MVT EltVT = VT.getVectorElementType();
5258 MVT XLenVT = Subtarget.getXLenVT();
5259
5260 if (VT.isFloatingPoint()) {
5261 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
5262 (EltVT == MVT::bf16 && !Subtarget.hasVInstructionsBF16())) {
5263 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
5264 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
5265 Scalar = DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, XLenVT, Scalar);
5266 else
5267 Scalar = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Scalar);
5268 MVT IVT = VT.changeVectorElementType(MVT::i16);
5269 Passthru = DAG.getNode(ISD::BITCAST, DL, IVT, Passthru);
5270 SDValue Splat =
5271 lowerScalarSplat(Passthru, Scalar, VL, IVT, DL, DAG, Subtarget);
5272 return DAG.getNode(ISD::BITCAST, DL, VT, Splat);
5273 }
5274 return DAG.getNode(RISCVISD::VFMV_V_F_VL, DL, VT, Passthru, Scalar, VL);
5275 }
5276
5277 // Simplest case is that the operand needs to be promoted to XLenVT.
5278 if (Scalar.getValueType().bitsLE(XLenVT)) {
5279 // If the operand is a constant, sign extend to increase our chances
5280 // of being able to use a .vi instruction. ANY_EXTEND would become a
5281 // a zero extend and the simm5 check in isel would fail.
5282 // FIXME: Should we ignore the upper bits in isel instead?
5283 unsigned ExtOpc =
5285 Scalar = DAG.getNode(ExtOpc, DL, XLenVT, Scalar);
5286 return DAG.getNode(RISCVISD::VMV_V_X_VL, DL, VT, Passthru, Scalar, VL);
5287 }
5288
5289 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
5290 "Unexpected scalar for splat lowering!");
5291
5292 if (isOneConstant(VL) && isNullConstant(Scalar))
5293 return DAG.getNode(RISCVISD::VMV_S_X_VL, DL, VT, Passthru,
5294 DAG.getConstant(0, DL, XLenVT), VL);
5295
5296 // Otherwise use the more complicated splatting algorithm.
5297 return splatSplitI64WithVL(DL, VT, Passthru, Scalar, VL, DAG);
5298}
5299
5300// This function lowers an insert of a scalar operand Scalar into lane
5301// 0 of the vector regardless of the value of VL. The contents of the
5302// remaining lanes of the result vector are unspecified. VL is assumed
5303// to be non-zero.
5305 const SDLoc &DL, SelectionDAG &DAG,
5306 const RISCVSubtarget &Subtarget) {
5307 assert(VT.isScalableVector() && "Expect VT is scalable vector type.");
5308
5309 const MVT XLenVT = Subtarget.getXLenVT();
5310 SDValue Passthru = DAG.getUNDEF(VT);
5311
5312 if (Scalar.getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
5313 isNullConstant(Scalar.getOperand(1))) {
5314 SDValue ExtractedVal = Scalar.getOperand(0);
5315 // The element types must be the same.
5316 if (ExtractedVal.getValueType().getVectorElementType() ==
5317 VT.getVectorElementType()) {
5318 MVT ExtractedVT = ExtractedVal.getSimpleValueType();
5319 MVT ExtractedContainerVT = ExtractedVT;
5320 if (ExtractedContainerVT.isFixedLengthVector()) {
5321 ExtractedContainerVT =
5322 getContainerForFixedLengthVector(ExtractedContainerVT, Subtarget);
5323 ExtractedVal = convertToScalableVector(ExtractedContainerVT,
5324 ExtractedVal, DAG, Subtarget);
5325 }
5326 if (ExtractedContainerVT.bitsLE(VT))
5327 return DAG.getInsertSubvector(DL, Passthru, ExtractedVal, 0);
5328 return DAG.getExtractSubvector(DL, VT, ExtractedVal, 0);
5329 }
5330 }
5331
5332 if (VT.isFloatingPoint())
5333 return DAG.getNode(RISCVISD::VFMV_S_F_VL, DL, VT, DAG.getUNDEF(VT), Scalar,
5334 VL);
5335
5336 // Avoid the tricky legalization cases by falling back to using the
5337 // splat code which already handles it gracefully.
5338 if (!Scalar.getValueType().bitsLE(XLenVT))
5339 return lowerScalarSplat(DAG.getUNDEF(VT), Scalar,
5340 DAG.getConstant(1, DL, XLenVT),
5341 VT, DL, DAG, Subtarget);
5342
5343 // If the operand is a constant, sign extend to increase our chances
5344 // of being able to use a .vi instruction. ANY_EXTEND would become a
5345 // a zero extend and the simm5 check in isel would fail.
5346 // FIXME: Should we ignore the upper bits in isel instead?
5347 unsigned ExtOpc =
5349 Scalar = DAG.getNode(ExtOpc, DL, XLenVT, Scalar);
5350 return DAG.getNode(RISCVISD::VMV_S_X_VL, DL, VT, DAG.getUNDEF(VT), Scalar,
5351 VL);
5352}
5353
5354/// If concat_vector(V1,V2) could be folded away to some existing
5355/// vector source, return it. Note that the source may be larger
5356/// than the requested concat_vector (i.e. a extract_subvector
5357/// might be required.)
5359 EVT VT = V1.getValueType();
5360 assert(VT == V2.getValueType() && "argument types must match");
5361 // Both input must be extracts.
5362 if (V1.getOpcode() != ISD::EXTRACT_SUBVECTOR ||
5364 return SDValue();
5365
5366 // Extracting from the same source.
5367 SDValue Src = V1.getOperand(0);
5368 if (Src != V2.getOperand(0) ||
5369 VT.isScalableVector() != Src.getValueType().isScalableVector())
5370 return SDValue();
5371
5372 // The extracts must extract the two halves of the source.
5373 if (V1.getConstantOperandVal(1) != 0 ||
5375 return SDValue();
5376
5377 return Src;
5378}
5379
5380// Can this shuffle be performed on exactly one (possibly larger) input?
5382
5383 if (V2.isUndef())
5384 return V1;
5385
5386 unsigned NumElts = VT.getVectorNumElements();
5387 // Src needs to have twice the number of elements.
5388 // TODO: Update shuffle lowering to add the extract subvector
5389 if (SDValue Src = foldConcatVector(V1, V2);
5390 Src && Src.getValueType().getVectorNumElements() == (NumElts * 2))
5391 return Src;
5392
5393 return SDValue();
5394}
5395
5396static unsigned getLMULOctuple(MVT ContainerVT) {
5397 assert(ContainerVT.isScalableVector() && "Expected scalable vector type");
5398 unsigned MinSize = ContainerVT.getSizeInBits().getKnownMinValue();
5399 assert(isPowerOf2_32(MinSize) && MinSize >= 8 && MinSize <= 512 &&
5400 "Unexpected LMUL");
5401 return MinSize / (RISCV::RVVBitsPerBlock / 8);
5402}
5403
5404static bool
5406 MVT ContainerVT = VT;
5407 if (VT.isFixedLengthVector())
5408 ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
5409 return RISCVTargetLowering::getLMUL(ContainerVT) != RISCVVType::LMUL_8;
5410}
5411
5412static bool
5414 MVT ContainerVT = VT;
5415 if (VT.isFixedLengthVector()) {
5416 // VT is the interleaved result type, but lowerZvzipVZIP maps each
5417 // half-sized input to a scalable container before doubling that container
5418 // for the result. Mirror that order here because the minimum scalable
5419 // container size means mapping VT directly is not necessarily equivalent.
5420 // For example, interleaving two <2 x i32> inputs at VLEN=128 requires an
5421 // m2 result container, while mapping the <4 x i32> result directly yields
5422 // m1.
5424 VT.getHalfNumVectorElementsVT(), Subtarget);
5425 ContainerVT = ContainerVT.getDoubleNumVectorElementsVT();
5426 }
5427 unsigned EltBits = VT.getScalarSizeInBits();
5428 unsigned LMULOctuple = getLMULOctuple(ContainerVT);
5429 // Perform 2 * SEW <= LMUL * min(ELEN, VLEN) check.
5430 return EltBits * 16 <= LMULOctuple * std::min(Subtarget.getELen(),
5431 Subtarget.getRealMinVLen());
5432}
5433
5434/// Is this shuffle interleaving contiguous elements from one vector into the
5435/// even elements and contiguous elements from another vector into the odd
5436/// elements. \p EvenSrc will contain the element that should be in the first
5437/// even element. \p OddSrc will contain the element that should be in the first
5438/// odd element. These can be the first element in a source or the element half
5439/// way through the source.
5440static bool isInterleaveShuffle(ArrayRef<int> Mask, MVT VT, int &EvenSrc,
5441 int &OddSrc, const RISCVSubtarget &Subtarget) {
5442 // We need to be able to widen elements to the next larger integer type or
5443 // use the vzip instruction at e64.
5444 if (VT.getScalarSizeInBits() >= Subtarget.getELen()) {
5445 if (!Subtarget.hasStdExtZvzip())
5446 return false;
5447 if (!isLegalVTForZvzipInterleavedOperand(VT, Subtarget))
5448 return false;
5449 }
5450
5451 int Size = Mask.size();
5452 int NumElts = VT.getVectorNumElements();
5453 assert(Size == (int)NumElts && "Unexpected mask size");
5454
5455 SmallVector<unsigned, 2> StartIndexes;
5456 if (!ShuffleVectorInst::isInterleaveMask(Mask, 2, Size * 2, StartIndexes))
5457 return false;
5458
5459 EvenSrc = StartIndexes[0];
5460 OddSrc = StartIndexes[1];
5461
5462 // One source should be low half of first vector.
5463 if (EvenSrc != 0 && OddSrc != 0)
5464 return false;
5465
5466 // Subvectors will be subtracted from either at the start of the two input
5467 // vectors, or at the start and middle of the first vector if it's an unary
5468 // interleave.
5469 // In both cases, HalfNumElts will be extracted.
5470 // We need to ensure that the extract indices are 0 or HalfNumElts otherwise
5471 // we'll create an illegal extract_subvector.
5472 // FIXME: We could support other values using a slidedown first.
5473 int HalfNumElts = NumElts / 2;
5474 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
5475}
5476
5477/// Is this mask representing a masked combination of two slides?
5479 std::array<std::pair<int, int>, 2> &SrcInfo) {
5480 if (!llvm::isMaskedSlidePair(Mask, Mask.size(), SrcInfo))
5481 return false;
5482
5483 // Avoid matching vselect idioms
5484 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
5485 return false;
5486 // Prefer vslideup as the second instruction, and identity
5487 // only as the initial instruction.
5488 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
5489 SrcInfo[1].second == 0)
5490 std::swap(SrcInfo[0], SrcInfo[1]);
5491 assert(SrcInfo[0].first != -1 && "Must find one slide");
5492 return true;
5493}
5494
5495// Exactly matches the semantics of a previously existing custom matcher
5496// to allow migration to new matcher without changing output.
5497static bool isElementRotate(const std::array<std::pair<int, int>, 2> &SrcInfo,
5498 unsigned NumElts) {
5499 if (SrcInfo[1].first == -1)
5500 return true;
5501 return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
5502 SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
5503}
5504
5505// Lower a deinterleave shuffle to SRL and TRUNC. Factor must be
5506// 2, 4, 8 and the integer type Factor-times larger than VT's
5507// element type must be a legal element type.
5508// [a, p, b, q, c, r, d, s] -> [a, b, c, d] (Factor=2, Index=0)
5509// -> [p, q, r, s] (Factor=2, Index=1)
5511 SDValue Src, unsigned Factor,
5512 unsigned Index, SelectionDAG &DAG) {
5513 unsigned EltBits = VT.getScalarSizeInBits();
5514 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
5515 MVT WideSrcVT = MVT::getVectorVT(MVT::getIntegerVT(EltBits * Factor),
5516 SrcEC.divideCoefficientBy(Factor));
5517 MVT ResVT = MVT::getVectorVT(MVT::getIntegerVT(EltBits),
5518 SrcEC.divideCoefficientBy(Factor));
5519 Src = DAG.getBitcast(WideSrcVT, Src);
5520
5521 unsigned Shift = Index * EltBits;
5522 SDValue Res = DAG.getNode(ISD::SRL, DL, WideSrcVT, Src,
5523 DAG.getConstant(Shift, DL, WideSrcVT));
5524 Res = DAG.getNode(ISD::TRUNCATE, DL, ResVT, Res);
5526 Res = DAG.getBitcast(CastVT, Res);
5527 return DAG.getInsertSubvector(DL, DAG.getUNDEF(VT), Res, 0);
5528}
5529
5530/// Match a single source shuffle which is an identity except that some
5531/// particular element is repeated. This can be lowered as a masked
5532/// vrgather.vi/vx. Note that the two source form of this is handled
5533/// by the recursive splitting logic and doesn't need special handling.
5535 const RISCVSubtarget &Subtarget,
5536 SelectionDAG &DAG) {
5537
5538 SDLoc DL(SVN);
5539 MVT VT = SVN->getSimpleValueType(0);
5540 SDValue V1 = SVN->getOperand(0);
5541 assert(SVN->getOperand(1).isUndef());
5542 ArrayRef<int> Mask = SVN->getMask();
5543 const unsigned NumElts = VT.getVectorNumElements();
5544 MVT XLenVT = Subtarget.getXLenVT();
5545
5546 std::optional<int> SplatIdx;
5547 for (auto [I, M] : enumerate(Mask)) {
5548 if (M == -1 || I == (unsigned)M)
5549 continue;
5550 if (SplatIdx && *SplatIdx != M)
5551 return SDValue();
5552 SplatIdx = M;
5553 }
5554
5555 if (!SplatIdx)
5556 return SDValue();
5557
5558 SmallVector<SDValue> MaskVals;
5559 for (int MaskIndex : Mask) {
5560 bool SelectMaskVal = MaskIndex == *SplatIdx;
5561 MaskVals.push_back(DAG.getConstant(SelectMaskVal, DL, XLenVT));
5562 }
5563 assert(MaskVals.size() == NumElts && "Unexpected select-like shuffle");
5564 MVT MaskVT = MVT::getVectorVT(MVT::i1, NumElts);
5565 SDValue SelectMask = DAG.getBuildVector(MaskVT, DL, MaskVals);
5566 SDValue Splat = DAG.getVectorShuffle(VT, DL, V1, DAG.getUNDEF(VT),
5567 SmallVector<int>(NumElts, *SplatIdx));
5568 return DAG.getNode(ISD::VSELECT, DL, VT, SelectMask, Splat, V1);
5569}
5570
5571// Lower the following shuffle to vslidedown.
5572// a)
5573// t49: v8i8 = extract_subvector t13, Constant:i64<0>
5574// t109: v8i8 = extract_subvector t13, Constant:i64<8>
5575// t108: v8i8 = vector_shuffle<1,2,3,4,5,6,7,8> t49, t106
5576// b)
5577// t69: v16i16 = extract_subvector t68, Constant:i64<0>
5578// t23: v8i16 = extract_subvector t69, Constant:i64<0>
5579// t29: v4i16 = extract_subvector t23, Constant:i64<4>
5580// t26: v8i16 = extract_subvector t69, Constant:i64<8>
5581// t30: v4i16 = extract_subvector t26, Constant:i64<0>
5582// t54: v4i16 = vector_shuffle<1,2,3,4> t29, t30
5584 SDValue V1, SDValue V2,
5585 ArrayRef<int> Mask,
5586 const RISCVSubtarget &Subtarget,
5587 SelectionDAG &DAG) {
5588 auto findNonEXTRACT_SUBVECTORParent =
5589 [](SDValue Parent) -> std::pair<SDValue, uint64_t> {
5590 uint64_t Offset = 0;
5591 while (Parent.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
5592 // EXTRACT_SUBVECTOR can be used to extract a fixed-width vector from
5593 // a scalable vector. But we don't want to match the case.
5594 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
5595 Offset += Parent.getConstantOperandVal(1);
5596 Parent = Parent.getOperand(0);
5597 }
5598 return std::make_pair(Parent, Offset);
5599 };
5600
5601 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
5602 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
5603
5604 // Extracting from the same source.
5605 SDValue Src = V1Src;
5606 if (Src != V2Src)
5607 return SDValue();
5608
5609 // Rebuild mask because Src may be from multiple EXTRACT_SUBVECTORs.
5610 SmallVector<int, 16> NewMask(Mask);
5611 for (size_t i = 0; i != NewMask.size(); ++i) {
5612 if (NewMask[i] == -1)
5613 continue;
5614
5615 if (static_cast<size_t>(NewMask[i]) < NewMask.size()) {
5616 NewMask[i] = NewMask[i] + V1IndexOffset;
5617 } else {
5618 // Minus NewMask.size() is needed. Otherwise, the b case would be
5619 // <5,6,7,12> instead of <5,6,7,8>.
5620 NewMask[i] = NewMask[i] - NewMask.size() + V2IndexOffset;
5621 }
5622 }
5623
5624 // First index must be known and non-zero. It will be used as the slidedown
5625 // amount.
5626 if (NewMask[0] <= 0)
5627 return SDValue();
5628
5629 // NewMask is also continuous.
5630 for (unsigned i = 1; i != NewMask.size(); ++i)
5631 if (NewMask[i - 1] + 1 != NewMask[i])
5632 return SDValue();
5633
5634 MVT XLenVT = Subtarget.getXLenVT();
5635 MVT SrcVT = Src.getSimpleValueType();
5636 MVT ContainerVT = getContainerForFixedLengthVector(SrcVT, Subtarget);
5637 auto [TrueMask, VL] = getDefaultVLOps(SrcVT, ContainerVT, DL, DAG, Subtarget);
5638 SDValue Slidedown =
5639 getVSlidedown(DAG, Subtarget, DL, ContainerVT, DAG.getUNDEF(ContainerVT),
5640 convertToScalableVector(ContainerVT, Src, DAG, Subtarget),
5641 DAG.getConstant(NewMask[0], DL, XLenVT), TrueMask, VL);
5642 return DAG.getExtractSubvector(
5643 DL, VT, convertFromScalableVector(SrcVT, Slidedown, DAG, Subtarget), 0);
5644}
5645
5646// Because vslideup leaves the destination elements at the start intact, we can
5647// use it to perform shuffles that insert subvectors:
5648//
5649// vector_shuffle v8:v8i8, v9:v8i8, <0, 1, 2, 3, 8, 9, 10, 11>
5650// ->
5651// vsetvli zero, 8, e8, mf2, ta, ma
5652// vslideup.vi v8, v9, 4
5653//
5654// vector_shuffle v8:v8i8, v9:v8i8 <0, 1, 8, 9, 10, 5, 6, 7>
5655// ->
5656// vsetvli zero, 5, e8, mf2, tu, ma
5657// vslideup.v1 v8, v9, 2
5659 SDValue V1, SDValue V2,
5660 ArrayRef<int> Mask,
5661 const RISCVSubtarget &Subtarget,
5662 SelectionDAG &DAG) {
5663 unsigned NumElts = VT.getVectorNumElements();
5664 int NumSubElts, Index;
5665 if (!ShuffleVectorInst::isInsertSubvectorMask(Mask, NumElts, NumSubElts,
5666 Index))
5667 return SDValue();
5668
5669 bool OpsSwapped = Mask[Index] < (int)NumElts;
5670 SDValue InPlace = OpsSwapped ? V2 : V1;
5671 SDValue ToInsert = OpsSwapped ? V1 : V2;
5672
5673 MVT XLenVT = Subtarget.getXLenVT();
5674 MVT ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
5675 auto TrueMask = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).first;
5676 // We slide up by the index that the subvector is being inserted at, and set
5677 // VL to the index + the number of elements being inserted.
5678 unsigned Policy =
5680 // If the we're adding a suffix to the in place vector, i.e. inserting right
5681 // up to the very end of it, then we don't actually care about the tail.
5682 if (NumSubElts + Index >= (int)NumElts)
5683 Policy |= RISCVVType::TAIL_AGNOSTIC;
5684
5685 InPlace = convertToScalableVector(ContainerVT, InPlace, DAG, Subtarget);
5686 ToInsert = convertToScalableVector(ContainerVT, ToInsert, DAG, Subtarget);
5687 SDValue VL = DAG.getConstant(NumSubElts + Index, DL, XLenVT);
5688
5689 SDValue Res;
5690 // If we're inserting into the lowest elements, use a tail undisturbed
5691 // vmv.v.v.
5692 if (Index == 0)
5693 Res = DAG.getNode(RISCVISD::VMV_V_V_VL, DL, ContainerVT, InPlace, ToInsert,
5694 VL);
5695 else
5696 Res = getVSlideup(DAG, Subtarget, DL, ContainerVT, InPlace, ToInsert,
5697 DAG.getConstant(Index, DL, XLenVT), TrueMask, VL, Policy);
5698 return convertFromScalableVector(VT, Res, DAG, Subtarget);
5699}
5700
5701// A shuffle of shuffles where the final data only is drawn from 2 input ops
5702// can be compressed into a single shuffle
5704 const RISCVSubtarget &Subtarget,
5705 SelectionDAG &DAG) {
5706 SDValue V1 = SVN->getOperand(0);
5707 SDValue V2 = SVN->getOperand(1);
5708
5709 if (V1.getOpcode() != ISD::VECTOR_SHUFFLE ||
5711 return SDValue();
5712
5713 if (!V1.hasOneUse() || !V2.hasOneUse())
5714 return SDValue();
5715
5716 ArrayRef<int> Mask = SVN->getMask();
5717 ArrayRef<int> V1Mask = cast<ShuffleVectorSDNode>(V1.getNode())->getMask();
5718 ArrayRef<int> V2Mask = cast<ShuffleVectorSDNode>(V2.getNode())->getMask();
5719 unsigned NumElts = Mask.size();
5720 SmallVector<int> NewMask(NumElts, -1);
5721 for (unsigned Idx : seq<unsigned>(NumElts)) {
5722 int Lane = Mask[Idx];
5723 // Don't assign if poison
5724 if (Lane == -1)
5725 continue;
5726 int OrigLane;
5727 bool SecondOp = false;
5728 if ((unsigned)Lane < NumElts) {
5729 OrigLane = V1Mask[Lane];
5730 } else {
5731 OrigLane = V2Mask[Lane - NumElts];
5732 SecondOp = true;
5733 }
5734 if (OrigLane == -1)
5735 continue;
5736 // Don't handle if shuffling from a second operand
5737 if ((unsigned)OrigLane >= NumElts)
5738 return SDValue();
5739 if (SecondOp)
5740 OrigLane += NumElts;
5741 NewMask[Idx] = OrigLane;
5742 }
5743
5744 EVT VT = SVN->getValueType(0);
5745 SDLoc DL(SVN);
5746
5747 return DAG.getVectorShuffle(VT, DL, V1->getOperand(0), V2->getOperand(0),
5748 NewMask);
5749}
5750
5751/// Match v(f)slide1up/down idioms. These operations involve sliding
5752/// N-1 elements to make room for an inserted scalar at one end.
5754 SDValue V1, SDValue V2,
5755 ArrayRef<int> Mask,
5756 const RISCVSubtarget &Subtarget,
5757 SelectionDAG &DAG) {
5758 bool OpsSwapped = false;
5759 if (!isa<BuildVectorSDNode>(V1)) {
5760 if (!isa<BuildVectorSDNode>(V2))
5761 return SDValue();
5762 std::swap(V1, V2);
5763 OpsSwapped = true;
5764 }
5765 SDValue Splat = cast<BuildVectorSDNode>(V1)->getSplatValue();
5766 if (!Splat)
5767 return SDValue();
5768
5769 // Return true if the mask could describe a slide of Mask.size() - 1
5770 // elements from concat_vector(V1, V2)[Base:] to [Offset:].
5771 auto isSlideMask = [](ArrayRef<int> Mask, unsigned Base, int Offset) {
5772 const unsigned S = (Offset > 0) ? 0 : -Offset;
5773 const unsigned E = Mask.size() - ((Offset > 0) ? Offset : 0);
5774 for (unsigned i = S; i != E; ++i)
5775 if (Mask[i] >= 0 && (unsigned)Mask[i] != Base + i + Offset)
5776 return false;
5777 return true;
5778 };
5779
5780 const unsigned NumElts = VT.getVectorNumElements();
5781 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
5782 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
5783 return SDValue();
5784
5785 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
5786 // Inserted lane must come from splat, undef scalar is legal but not profitable.
5787 if (InsertIdx < 0 || InsertIdx / NumElts != (unsigned)OpsSwapped)
5788 return SDValue();
5789
5790 MVT ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
5791 auto [TrueMask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
5792
5793 // zvfhmin and zvfbfmin don't have vfslide1{down,up}.vf so use fmv.x.h +
5794 // vslide1{down,up}.vx instead.
5795 if ((VT.getVectorElementType() == MVT::bf16 &&
5796 !Subtarget.hasVInstructionsBF16()) ||
5797 (VT.getVectorElementType() == MVT::f16 &&
5798 !Subtarget.hasVInstructionsF16())) {
5799 MVT IntVT = ContainerVT.changeVectorElementTypeToInteger();
5800 Splat =
5801 DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, Subtarget.getXLenVT(), Splat);
5802 V2 = DAG.getBitcast(
5803 IntVT, convertToScalableVector(ContainerVT, V2, DAG, Subtarget));
5804 SDValue Vec = DAG.getNode(
5805 IsVSlidedown ? RISCVISD::VSLIDE1DOWN_VL : RISCVISD::VSLIDE1UP_VL, DL,
5806 IntVT, DAG.getUNDEF(IntVT), V2, Splat, TrueMask, VL);
5807 Vec = DAG.getBitcast(ContainerVT, Vec);
5808 return convertFromScalableVector(VT, Vec, DAG, Subtarget);
5809 }
5810
5811 auto OpCode = IsVSlidedown ?
5812 (VT.isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL) :
5813 (VT.isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VSLIDE1UP_VL);
5814 if (!VT.isFloatingPoint())
5815 Splat = DAG.getNode(ISD::ANY_EXTEND, DL, Subtarget.getXLenVT(), Splat);
5816 auto Vec = DAG.getNode(OpCode, DL, ContainerVT,
5817 DAG.getUNDEF(ContainerVT),
5818 convertToScalableVector(ContainerVT, V2, DAG, Subtarget),
5819 Splat, TrueMask, VL);
5820 return convertFromScalableVector(VT, Vec, DAG, Subtarget);
5821}
5822
5823/// Match a mask which "spreads" the leading elements of a vector evenly
5824/// across the result. Factor is the spread amount, and Index is the
5825/// offset applied. (on success, Index < Factor) This is the inverse
5826/// of a deinterleave with the same Factor and Index. This is analogous
5827/// to an interleave, except that all but one lane is undef.
5829 unsigned &Index) {
5830 SmallVector<bool> LaneIsUndef(Factor, true);
5831 for (unsigned i = 0; i < Mask.size(); i++)
5832 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
5833
5834 bool Found = false;
5835 for (unsigned i = 0; i < Factor; i++) {
5836 if (LaneIsUndef[i])
5837 continue;
5838 if (Found)
5839 return false;
5840 Index = i;
5841 Found = true;
5842 }
5843 if (!Found)
5844 return false;
5845
5846 for (unsigned i = 0; i < Mask.size() / Factor; i++) {
5847 unsigned j = i * Factor + Index;
5848 if (Mask[j] != -1 && (unsigned)Mask[j] != i)
5849 return false;
5850 }
5851 return true;
5852}
5853
5854static SDValue lowerZvzipVPAIR(unsigned Opc, SDValue Op0, SDValue Op1,
5855 const SDLoc &DL, SelectionDAG &DAG,
5856 const RISCVSubtarget &Subtarget) {
5857 assert(RISCVISD::VPAIRE_VL == Opc || RISCVISD::VPAIRO_VL == Opc);
5859
5860 MVT VT = Op0.getSimpleValueType();
5862 Op0 = DAG.getBitcast(IntVT, Op0);
5863 Op1 = DAG.getBitcast(IntVT, Op1);
5864
5865 MVT ContainerVT = IntVT;
5866 if (VT.isFixedLengthVector()) {
5867 ContainerVT = getContainerForFixedLengthVector(IntVT, Subtarget);
5868 Op0 = convertToScalableVector(ContainerVT, Op0, DAG, Subtarget);
5869 Op1 = convertToScalableVector(ContainerVT, Op1, DAG, Subtarget);
5870 }
5871
5872 MVT InnerVT = ContainerVT;
5873 auto [Mask, VL] = getDefaultVLOps(IntVT, InnerVT, DL, DAG, Subtarget);
5874
5875 SDValue Passthru = DAG.getUNDEF(InnerVT);
5876 SDValue Res = DAG.getNode(Opc, DL, InnerVT, Op0, Op1, Passthru, Mask, VL);
5877 if (IntVT.isFixedLengthVector())
5878 Res = convertFromScalableVector(IntVT, Res, DAG, Subtarget);
5879 Res = DAG.getBitcast(VT, Res);
5880 return Res;
5881}
5882
5884 SelectionDAG &DAG,
5885 const RISCVSubtarget &Subtarget) {
5887 MVT VT = Op0.getSimpleValueType();
5889 Op0 = DAG.getBitcast(IntVT, Op0);
5890 Op1 = DAG.getBitcast(IntVT, Op1);
5891 MVT ContainerVT = IntVT;
5892 if (VT.isFixedLengthVector()) {
5893 ContainerVT = getContainerForFixedLengthVector(IntVT, Subtarget);
5894 Op0 = convertToScalableVector(ContainerVT, Op0, DAG, Subtarget);
5895 Op1 = convertToScalableVector(ContainerVT, Op1, DAG, Subtarget);
5896 }
5897 MVT ResVT = ContainerVT.getDoubleNumVectorElementsVT();
5898 MVT ResIntVT = IntVT.getDoubleNumVectorElementsVT();
5899 auto [Mask, VL] = getDefaultVLOps(ResIntVT, ResVT, DL, DAG, Subtarget);
5900 SDValue Passthru = DAG.getUNDEF(ResVT);
5901 SDValue Res =
5902 DAG.getNode(RISCVISD::VZIP_VL, DL, ResVT, Op0, Op1, Passthru, Mask, VL);
5903 if (IntVT.isFixedLengthVector())
5905 DAG, Subtarget);
5906 Res = DAG.getBitcast(VT.getDoubleNumVectorElementsVT(), Res);
5907 return Res;
5908}
5909
5910static SDValue lowerZvzipVUNZIP(unsigned Opc, SDValue Op, const SDLoc &DL,
5911 SelectionDAG &DAG,
5912 const RISCVSubtarget &Subtarget) {
5913 assert(Opc == RISCVISD::VUNZIPE_VL || Opc == RISCVISD::VUNZIPO_VL);
5914 MVT VT = Op.getSimpleValueType();
5916
5918 Op = DAG.getBitcast(IntVT, Op);
5919 MVT ContainerVT = IntVT;
5920 if (VT.isFixedLengthVector()) {
5921 ContainerVT = getContainerForFixedLengthVector(IntVT, Subtarget);
5922 // Ensure that halving the source container produces a legal result type.
5923 // In particular, E64 has no fractional LMUL types, and some Zve profiles
5924 // do not legalize the smallest fractional LMUL type.
5925 if (ContainerVT.getVectorMinNumElements() == 1 ||
5926 !Subtarget.getTargetLowering()->isTypeLegal(
5927 ContainerVT.getHalfNumVectorElementsVT()))
5928 ContainerVT = ContainerVT.getDoubleNumVectorElementsVT();
5929 Op = convertToScalableVector(ContainerVT, Op, DAG, Subtarget);
5930 }
5931
5932 MVT ResVT = ContainerVT.getHalfNumVectorElementsVT();
5933 MVT HalfVT = VT.getHalfNumVectorElementsVT();
5934 MVT HalfIntVT = IntVT.getHalfNumVectorElementsVT();
5935 SDValue VL = getDefaultVLOps(HalfIntVT, ResVT, DL, DAG, Subtarget).second;
5936 SDValue Passthru = DAG.getUNDEF(ResVT);
5937 SDValue Res = DAG.getNode(Opc, DL, ResVT, Op, Passthru, VL);
5938 if (HalfIntVT.isFixedLengthVector())
5939 Res = convertFromScalableVector(HalfIntVT, Res, DAG, Subtarget);
5940 Res = DAG.getBitcast(HalfVT, Res);
5941 return Res;
5942}
5943
5944// Given a vector a, b, c, d return a vector Factor times longer
5945// with Factor-1 undef's between elements. Ex:
5946// a, undef, b, undef, c, undef, d, undef (Factor=2, Index=0)
5947// undef, a, undef, b, undef, c, undef, d (Factor=2, Index=1)
5948static SDValue getWideningSpread(SDValue V, unsigned Factor, unsigned Index,
5949 const SDLoc &DL, SelectionDAG &DAG) {
5950
5951 MVT VT = V.getSimpleValueType();
5952 unsigned EltBits = VT.getScalarSizeInBits();
5954 V = DAG.getBitcast(VT.changeTypeToInteger(), V);
5955
5956 MVT WideVT = MVT::getVectorVT(MVT::getIntegerVT(EltBits * Factor), EC);
5957
5958 SDValue Result = DAG.getNode(ISD::ZERO_EXTEND, DL, WideVT, V);
5959 // TODO: On rv32, the constant becomes a splat_vector_parts which does not
5960 // allow the SHL to fold away if Index is 0.
5961 if (Index != 0)
5962 Result = DAG.getNode(ISD::SHL, DL, WideVT, Result,
5963 DAG.getConstant(EltBits * Index, DL, WideVT));
5964 // Make sure to use original element type
5965 MVT ResultVT = MVT::getVectorVT(VT.getVectorElementType(), EC * Factor);
5966 return DAG.getBitcast(ResultVT, Result);
5967}
5968
5969// Given two input vectors of <[vscale x ]n x ty>, use vwaddu.vv and vwmaccu.vx
5970// to create an interleaved vector of <[vscale x] n*2 x ty>.
5971// This requires that the size of ty is less than the subtarget's maximum ELEN.
5973 const SDLoc &DL, SelectionDAG &DAG,
5974 const RISCVSubtarget &Subtarget) {
5975
5976 // FIXME: Not only does this optimize the code, it fixes some correctness
5977 // issues because MIR does not have freeze.
5978 if (EvenV.isUndef())
5979 return getWideningSpread(OddV, 2, 1, DL, DAG);
5980 if (OddV.isUndef())
5981 return getWideningSpread(EvenV, 2, 0, DL, DAG);
5982
5983 MVT VecVT = EvenV.getSimpleValueType();
5984 MVT VecContainerVT = VecVT; // <vscale x n x ty>
5985 // Convert fixed vectors to scalable if needed
5986 if (VecContainerVT.isFixedLengthVector()) {
5987 VecContainerVT = getContainerForFixedLengthVector(VecVT, Subtarget);
5988 EvenV = convertToScalableVector(VecContainerVT, EvenV, DAG, Subtarget);
5989 OddV = convertToScalableVector(VecContainerVT, OddV, DAG, Subtarget);
5990 }
5991
5992 assert(VecVT.getScalarSizeInBits() < Subtarget.getELen());
5993
5994 // We're working with a vector of the same size as the resulting
5995 // interleaved vector, but with half the number of elements and
5996 // twice the SEW (Hence the restriction on not using the maximum
5997 // ELEN)
5998 MVT WideVT =
6000 VecVT.getVectorElementCount());
6001 MVT WideContainerVT = WideVT; // <vscale x n x ty*2>
6002 if (WideContainerVT.isFixedLengthVector())
6003 WideContainerVT = getContainerForFixedLengthVector(WideVT, Subtarget);
6004
6005 // Bitcast the input vectors to integers in case they are FP
6006 VecContainerVT = VecContainerVT.changeTypeToInteger();
6007 EvenV = DAG.getBitcast(VecContainerVT, EvenV);
6008 OddV = DAG.getBitcast(VecContainerVT, OddV);
6009
6010 auto [Mask, VL] = getDefaultVLOps(VecVT, VecContainerVT, DL, DAG, Subtarget);
6011 SDValue Passthru = DAG.getUNDEF(WideContainerVT);
6012
6013 SDValue Interleaved;
6014 if (Subtarget.hasStdExtZvbb()) {
6015 // Interleaved = (OddV << VecVT.getScalarSizeInBits()) + EvenV.
6016 SDValue OffsetVec =
6017 DAG.getConstant(VecVT.getScalarSizeInBits(), DL, VecContainerVT);
6018 Interleaved = DAG.getNode(RISCVISD::VWSLL_VL, DL, WideContainerVT, OddV,
6019 OffsetVec, Passthru, Mask, VL);
6020 Interleaved = DAG.getNode(RISCVISD::VWADDU_W_VL, DL, WideContainerVT,
6021 Interleaved, EvenV, Passthru, Mask, VL);
6022 } else {
6023 // FIXME: We should freeze the odd vector here. We already handled the case
6024 // of provably undef/poison above.
6025
6026 // Widen EvenV and OddV with 0s and add one copy of OddV to EvenV with
6027 // vwaddu.vv
6028 Interleaved = DAG.getNode(RISCVISD::VWADDU_VL, DL, WideContainerVT, EvenV,
6029 OddV, Passthru, Mask, VL);
6030
6031 // Then get OddV * by 2^(VecVT.getScalarSizeInBits() - 1)
6032 SDValue AllOnesVec = DAG.getSplatVector(
6033 VecContainerVT, DL, DAG.getAllOnesConstant(DL, Subtarget.getXLenVT()));
6034 SDValue OddsMul = DAG.getNode(RISCVISD::VWMULU_VL, DL, WideContainerVT,
6035 OddV, AllOnesVec, Passthru, Mask, VL);
6036
6037 // Add the two together so we get
6038 // (OddV * 0xff...ff) + (OddV + EvenV)
6039 // = (OddV * 0x100...00) + EvenV
6040 // = (OddV << VecVT.getScalarSizeInBits()) + EvenV
6041 // Note the ADD_VL and VLMULU_VL should get selected as vwmaccu.vx
6042 Interleaved = DAG.getNode(RISCVISD::ADD_VL, DL, WideContainerVT,
6043 Interleaved, OddsMul, Passthru, Mask, VL);
6044 }
6045
6046 // Bitcast from <vscale x n * ty*2> to <vscale x 2*n x ty>
6047 MVT ResultContainerVT = MVT::getVectorVT(
6048 VecVT.getVectorElementType(), // Make sure to use original type
6049 VecContainerVT.getVectorElementCount() * 2);
6050 Interleaved = DAG.getBitcast(ResultContainerVT, Interleaved);
6051
6052 // Convert back to a fixed vector if needed
6053 MVT ResultVT = MVT::getVectorVT(VecVT.getVectorElementType(),
6054 VecVT.getVectorElementCount() * 2);
6055 if (ResultVT.isFixedLengthVector())
6056 Interleaved =
6057 convertFromScalableVector(ResultVT, Interleaved, DAG, Subtarget);
6058
6059 return Interleaved;
6060}
6061
6062// If we have a vector of bits that we want to reverse, we can use a vbrev on a
6063// larger element type, e.g. v32i1 can be reversed with a v1i32 bitreverse.
6065 SelectionDAG &DAG,
6066 const RISCVSubtarget &Subtarget) {
6067 SDLoc DL(SVN);
6068 MVT VT = SVN->getSimpleValueType(0);
6069 SDValue V = SVN->getOperand(0);
6070 unsigned NumElts = VT.getVectorNumElements();
6071
6072 assert(VT.getVectorElementType() == MVT::i1);
6073
6075 SVN->getMask().size()) ||
6076 !SVN->getOperand(1).isUndef())
6077 return SDValue();
6078
6079 unsigned ViaEltSize = std::max((uint64_t)8, PowerOf2Ceil(NumElts));
6080 EVT ViaVT = EVT::getVectorVT(
6081 *DAG.getContext(), EVT::getIntegerVT(*DAG.getContext(), ViaEltSize), 1);
6082 EVT ViaBitVT =
6083 EVT::getVectorVT(*DAG.getContext(), MVT::i1, ViaVT.getScalarSizeInBits());
6084
6085 // If we don't have zvbb or the larger element type > ELEN, the operation will
6086 // be illegal.
6088 ViaVT) ||
6089 !Subtarget.getTargetLowering()->isTypeLegal(ViaBitVT))
6090 return SDValue();
6091
6092 // If the bit vector doesn't fit exactly into the larger element type, we need
6093 // to insert it into the larger vector and then shift up the reversed bits
6094 // afterwards to get rid of the gap introduced.
6095 if (ViaEltSize > NumElts)
6096 V = DAG.getInsertSubvector(DL, DAG.getUNDEF(ViaBitVT), V, 0);
6097
6098 SDValue Res =
6099 DAG.getNode(ISD::BITREVERSE, DL, ViaVT, DAG.getBitcast(ViaVT, V));
6100
6101 // Shift up the reversed bits if the vector didn't exactly fit into the larger
6102 // element type.
6103 if (ViaEltSize > NumElts)
6104 Res = DAG.getNode(ISD::SRL, DL, ViaVT, Res,
6105 DAG.getConstant(ViaEltSize - NumElts, DL, ViaVT));
6106
6107 Res = DAG.getBitcast(ViaBitVT, Res);
6108
6109 if (ViaEltSize > NumElts)
6110 Res = DAG.getExtractSubvector(DL, VT, Res, 0);
6111 return Res;
6112}
6113
6115 const RISCVSubtarget &Subtarget,
6116 MVT &RotateVT, unsigned &RotateAmt) {
6117 unsigned NumElts = VT.getVectorNumElements();
6118 unsigned EltSizeInBits = VT.getScalarSizeInBits();
6119 unsigned NumSubElts;
6120 if (!ShuffleVectorInst::isBitRotateMask(Mask, EltSizeInBits, 2,
6121 NumElts, NumSubElts, RotateAmt))
6122 return false;
6123 RotateVT = MVT::getVectorVT(MVT::getIntegerVT(EltSizeInBits * NumSubElts),
6124 NumElts / NumSubElts);
6125
6126 // We might have a RotateVT that isn't legal, e.g. v4i64 on zve32x.
6127 return Subtarget.getTargetLowering()->isTypeLegal(RotateVT);
6128}
6129
6130// Given a shuffle mask like <3, 0, 1, 2, 7, 4, 5, 6> for v8i8, we can
6131// reinterpret it as a v2i32 and rotate it right by 8 instead. We can lower this
6132// as a vror.vi if we have Zvkb, or otherwise as a vsll, vsrl and vor.
6134 SelectionDAG &DAG,
6135 const RISCVSubtarget &Subtarget) {
6136 SDLoc DL(SVN);
6137
6138 EVT VT = SVN->getValueType(0);
6139 unsigned RotateAmt;
6140 MVT RotateVT;
6141 if (!isLegalBitRotate(SVN->getMask(), VT, Subtarget, RotateVT, RotateAmt))
6142 return SDValue();
6143
6144 SDValue Op = DAG.getBitcast(RotateVT, SVN->getOperand(0));
6145
6146 SDValue Rotate;
6147 // A rotate of an i16 by 8 bits either direction is equivalent to a byteswap,
6148 // so canonicalize to vrev8.
6149 if (RotateVT.getScalarType() == MVT::i16 && RotateAmt == 8)
6150 Rotate = DAG.getNode(ISD::BSWAP, DL, RotateVT, Op);
6151 else
6152 Rotate = DAG.getNode(ISD::ROTL, DL, RotateVT, Op,
6153 DAG.getConstant(RotateAmt, DL, RotateVT));
6154
6155 return DAG.getBitcast(VT, Rotate);
6156}
6157
6158// If compiling with an exactly known VLEN, see if we can split a
6159// shuffle on m2 or larger into a small number of m1 sized shuffles
6160// which write each destination registers exactly once.
6162 SelectionDAG &DAG,
6163 const RISCVSubtarget &Subtarget) {
6164 SDLoc DL(SVN);
6165 MVT VT = SVN->getSimpleValueType(0);
6166 SDValue V1 = SVN->getOperand(0);
6167 SDValue V2 = SVN->getOperand(1);
6168 ArrayRef<int> Mask = SVN->getMask();
6169
6170 // If we don't know exact data layout, not much we can do. If this
6171 // is already m1 or smaller, no point in splitting further.
6172 const auto VLen = Subtarget.getRealVLen();
6173 if (!VLen || VT.getSizeInBits().getFixedValue() <= *VLen)
6174 return SDValue();
6175
6176 // Avoid picking up bitrotate patterns which we have a linear-in-lmul
6177 // expansion for.
6178 unsigned RotateAmt;
6179 MVT RotateVT;
6180 if (isLegalBitRotate(Mask, VT, Subtarget, RotateVT, RotateAmt))
6181 return SDValue();
6182
6183 MVT ElemVT = VT.getVectorElementType();
6184 unsigned ElemsPerVReg = *VLen / ElemVT.getFixedSizeInBits();
6185
6186 EVT ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
6187 MVT OneRegVT = MVT::getVectorVT(ElemVT, ElemsPerVReg);
6188 MVT M1VT = getContainerForFixedLengthVector(OneRegVT, Subtarget);
6189 assert(M1VT == RISCVTargetLowering::getM1VT(M1VT));
6190 unsigned NumOpElts = M1VT.getVectorMinNumElements();
6191 unsigned NumElts = ContainerVT.getVectorMinNumElements();
6192 unsigned NumOfSrcRegs = NumElts / NumOpElts;
6193 unsigned NumOfDestRegs = NumElts / NumOpElts;
6194 // The following semantically builds up a fixed length concat_vector
6195 // of the component shuffle_vectors. We eagerly lower to scalable here
6196 // to avoid DAG combining it back to a large shuffle_vector again.
6197 V1 = convertToScalableVector(ContainerVT, V1, DAG, Subtarget);
6198 V2 = convertToScalableVector(ContainerVT, V2, DAG, Subtarget);
6200 Operands;
6202 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
6203 [&]() { Operands.emplace_back(); },
6204 [&](ArrayRef<int> SrcSubMask, unsigned SrcVecIdx, unsigned DstVecIdx) {
6205 Operands.emplace_back().emplace_back(SrcVecIdx, UINT_MAX,
6206 SmallVector<int>(SrcSubMask));
6207 },
6208 [&](ArrayRef<int> SrcSubMask, unsigned Idx1, unsigned Idx2, bool NewReg) {
6209 if (NewReg)
6210 Operands.emplace_back();
6211 Operands.back().emplace_back(Idx1, Idx2, SmallVector<int>(SrcSubMask));
6212 });
6213 assert(Operands.size() == NumOfDestRegs && "Whole vector must be processed");
6214 // Note: check that we do not emit too many shuffles here to prevent code
6215 // size explosion.
6216 // TODO: investigate, if it can be improved by extra analysis of the masks to
6217 // check if the code is more profitable.
6218 unsigned NumShuffles = std::accumulate(
6219 Operands.begin(), Operands.end(), 0u,
6220 [&](unsigned N,
6221 ArrayRef<std::tuple<unsigned, unsigned, SmallVector<int>>> Data) {
6222 if (Data.empty())
6223 return N;
6224 N += Data.size();
6225 for (const auto &P : Data) {
6226 unsigned Idx2 = std::get<1>(P);
6227 ArrayRef<int> Mask = std::get<2>(P);
6228 if (Idx2 != UINT_MAX)
6229 ++N;
6230 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
6231 --N;
6232 }
6233 return N;
6234 });
6235 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
6236 (NumOfDestRegs <= 2 && NumShuffles >= 4))
6237 return SDValue();
6238 auto ExtractValue = [&, &DAG = DAG](SDValue SrcVec, unsigned ExtractIdx) {
6239 SDValue SubVec = DAG.getExtractSubvector(DL, M1VT, SrcVec, ExtractIdx);
6240 SubVec = convertFromScalableVector(OneRegVT, SubVec, DAG, Subtarget);
6241 return SubVec;
6242 };
6243 auto PerformShuffle = [&, &DAG = DAG](SDValue SubVec1, SDValue SubVec2,
6245 SDValue SubVec = DAG.getVectorShuffle(OneRegVT, DL, SubVec1, SubVec2, Mask);
6246 return SubVec;
6247 };
6248 SDValue Vec = DAG.getUNDEF(ContainerVT);
6249 for (auto [I, Data] : enumerate(Operands)) {
6250 if (Data.empty())
6251 continue;
6253 for (unsigned I : seq<unsigned>(Data.size())) {
6254 const auto &[Idx1, Idx2, _] = Data[I];
6255 // If the shuffle contains permutation of odd number of elements,
6256 // Idx1 might be used already in the first iteration.
6257 //
6258 // Idx1 = shuffle Idx1, Idx2
6259 // Idx1 = shuffle Idx1, Idx3
6260 SDValue &V = Values.try_emplace(Idx1).first->getSecond();
6261 if (!V)
6262 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
6263 (Idx1 % NumOfSrcRegs) * NumOpElts);
6264 if (Idx2 != UINT_MAX) {
6265 SDValue &V = Values.try_emplace(Idx2).first->getSecond();
6266 if (!V)
6267 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
6268 (Idx2 % NumOfSrcRegs) * NumOpElts);
6269 }
6270 }
6271 SDValue V;
6272 for (const auto &[Idx1, Idx2, Mask] : Data) {
6273 SDValue V1 = Values.at(Idx1);
6274 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.at(Idx2);
6275 V = PerformShuffle(V1, V2, Mask);
6276 Values[Idx1] = V;
6277 }
6278
6279 unsigned InsertIdx = I * NumOpElts;
6280 V = convertToScalableVector(M1VT, V, DAG, Subtarget);
6281 Vec = DAG.getInsertSubvector(DL, Vec, V, InsertIdx);
6282 }
6283 return convertFromScalableVector(VT, Vec, DAG, Subtarget);
6284}
6285
6286// Matches a subset of compress masks with a contiguous prefix of output
6287// elements. This could be extended to allow gaps by deciding which
6288// source elements to spuriously demand.
6290 int Last = -1;
6291 bool SawUndef = false;
6292 for (const auto &[Idx, M] : enumerate(Mask)) {
6293 if (M == -1) {
6294 SawUndef = true;
6295 continue;
6296 }
6297 if (SawUndef)
6298 return false;
6299 if (Idx > (unsigned)M)
6300 return false;
6301 if (M <= Last)
6302 return false;
6303 Last = M;
6304 }
6305 return true;
6306}
6307
6308/// Given a shuffle where the indices are disjoint between the two sources,
6309/// e.g.:
6310///
6311/// t2:v4i8 = vector_shuffle t0:v4i8, t1:v4i8, <2, 7, 1, 4>
6312///
6313/// Merge the two sources into one and do a single source shuffle:
6314///
6315/// t2:v4i8 = vselect t1:v4i8, t0:v4i8, <0, 1, 0, 1>
6316/// t3:v4i8 = vector_shuffle t2:v4i8, undef, <2, 3, 1, 0>
6317///
6318/// A vselect will either be merged into a masked instruction or be lowered as a
6319/// vmerge.vvm, which is cheaper than a vrgather.vv.
6321 SelectionDAG &DAG,
6322 const RISCVSubtarget &Subtarget) {
6323 MVT VT = SVN->getSimpleValueType(0);
6324 MVT XLenVT = Subtarget.getXLenVT();
6325 SDLoc DL(SVN);
6326
6327 const ArrayRef<int> Mask = SVN->getMask();
6328
6329 // Work out which source each lane will come from.
6330 SmallVector<int, 16> Srcs(Mask.size(), -1);
6331
6332 for (int Idx : Mask) {
6333 if (Idx == -1)
6334 continue;
6335 unsigned SrcIdx = Idx % Mask.size();
6336 int Src = (uint32_t)Idx < Mask.size() ? 0 : 1;
6337 if (Srcs[SrcIdx] == -1)
6338 // Mark this source as using this lane.
6339 Srcs[SrcIdx] = Src;
6340 else if (Srcs[SrcIdx] != Src)
6341 // The other source is using this lane: not disjoint.
6342 return SDValue();
6343 }
6344
6345 SmallVector<SDValue> SelectMaskVals;
6346 for (int Lane : Srcs) {
6347 if (Lane == -1)
6348 SelectMaskVals.push_back(DAG.getUNDEF(XLenVT));
6349 else
6350 SelectMaskVals.push_back(DAG.getConstant(Lane ? 0 : 1, DL, XLenVT));
6351 }
6352 MVT MaskVT = VT.changeVectorElementType(MVT::i1);
6353 SDValue SelectMask = DAG.getBuildVector(MaskVT, DL, SelectMaskVals);
6354 SDValue Select = DAG.getNode(ISD::VSELECT, DL, VT, SelectMask,
6355 SVN->getOperand(0), SVN->getOperand(1));
6356
6357 // Move all indices relative to the first source.
6358 SmallVector<int> NewMask(Mask.size());
6359 for (unsigned I = 0; I < Mask.size(); I++) {
6360 if (Mask[I] == -1)
6361 NewMask[I] = -1;
6362 else
6363 NewMask[I] = Mask[I] % Mask.size();
6364 }
6365
6366 return DAG.getVectorShuffle(VT, DL, Select, DAG.getUNDEF(VT), NewMask);
6367}
6368
6369/// Is this mask local (i.e. elements only move within their local span), and
6370/// repeating (that is, the same rearrangement is being done within each span)?
6371static bool isLocalRepeatingShuffle(ArrayRef<int> Mask, int Span) {
6372 // Require a prefix from the original mask until the consumer code
6373 // is adjusted to rewrite the mask instead of just taking a prefix.
6374 for (auto [I, M] : enumerate(Mask)) {
6375 if (M == -1)
6376 continue;
6377 if ((M / Span) != (int)(I / Span))
6378 return false;
6379 int SpanIdx = I % Span;
6380 int Expected = M % Span;
6381 if (Mask[SpanIdx] != Expected)
6382 return false;
6383 }
6384 return true;
6385}
6386
6387/// Is this mask only using elements from the first span of the input?
6388static bool isLowSourceShuffle(ArrayRef<int> Mask, int Span) {
6389 return all_of(Mask, [&](const auto &Idx) { return Idx == -1 || Idx < Span; });
6390}
6391
6392/// Return true for a mask which performs an arbitrary shuffle within the first
6393/// span, and then repeats that same result across all remaining spans. Note
6394/// that this doesn't check if all the inputs come from a single span!
6395static bool isSpanSplatShuffle(ArrayRef<int> Mask, int Span) {
6396 // Require a prefix from the original mask until the consumer code
6397 // is adjusted to rewrite the mask instead of just taking a prefix.
6398 for (auto [I, M] : enumerate(Mask)) {
6399 if (M == -1)
6400 continue;
6401 int SpanIdx = I % Span;
6402 if (Mask[SpanIdx] != M)
6403 return false;
6404 }
6405 return true;
6406}
6407
6408/// Try to widen element type to get a new mask value for a better permutation
6409/// sequence. This doesn't try to inspect the widened mask for profitability;
6410/// we speculate the widened form is equal or better. This has the effect of
6411/// reducing mask constant sizes - allowing cheaper materialization sequences
6412/// - and index sequence sizes - reducing register pressure and materialization
6413/// cost, at the cost of (possibly) an extra VTYPE toggle.
6415 SDLoc DL(Op);
6416 MVT VT = Op.getSimpleValueType();
6417 MVT ScalarVT = VT.getVectorElementType();
6418 unsigned ElementSize = ScalarVT.getFixedSizeInBits();
6419 SDValue V0 = Op.getOperand(0);
6420 SDValue V1 = Op.getOperand(1);
6421 ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Op)->getMask();
6422
6423 // Avoid wasted work leading to isTypeLegal check failing below
6424 if (ElementSize > 32)
6425 return SDValue();
6426
6427 SmallVector<int, 8> NewMask;
6428 if (!widenShuffleMaskElts(Mask, NewMask))
6429 return SDValue();
6430
6431 MVT NewEltVT = VT.isFloatingPoint() ? MVT::getFloatingPointVT(ElementSize * 2)
6432 : MVT::getIntegerVT(ElementSize * 2);
6433 MVT NewVT = MVT::getVectorVT(NewEltVT, VT.getVectorNumElements() / 2);
6434 if (!DAG.getTargetLoweringInfo().isTypeLegal(NewVT))
6435 return SDValue();
6436 V0 = DAG.getBitcast(NewVT, V0);
6437 V1 = DAG.getBitcast(NewVT, V1);
6438 return DAG.getBitcast(VT, DAG.getVectorShuffle(NewVT, DL, V0, V1, NewMask));
6439}
6440
6441// Match an interleave shuffle that forms a P-extension packed zip:
6442// <a0, b0, a1, b1, ...> -> zip*p/wzip*p
6444 const RISCVSubtarget &Subtarget,
6445 SelectionDAG &DAG) {
6446 SDValue V1 = SVN->getOperand(0);
6447 SDValue V2 = SVN->getOperand(1);
6448 SDLoc DL(SVN);
6449 MVT VT = SVN->getSimpleValueType(0);
6450 unsigned NumElts = VT.getVectorNumElements();
6451 ArrayRef<int> Mask = SVN->getMask();
6452
6453 if (VT != MVT::v8i8 && VT != MVT::v4i16)
6454 return SDValue();
6455
6456 SmallVector<unsigned, 2> StartIndexes;
6457 if (!V2.isUndef() &&
6458 ShuffleVectorInst::isInterleaveMask(Mask, 2, NumElts * 2, StartIndexes)) {
6459 unsigned EvenSrc = StartIndexes[0];
6460 unsigned OddSrc = StartIndexes[1];
6461 if (EvenSrc == 0 && OddSrc == NumElts) {
6462 if (Subtarget.is64Bit())
6463 return DAG.getNode(RISCVISD::PZIP, DL, VT, V1, V2);
6464 EVT HalfVT = VT.getHalfNumVectorElementsVT();
6465 V1 = DAG.getExtractSubvector(DL, HalfVT, V1, 0);
6466 V2 = DAG.getExtractSubvector(DL, HalfVT, V2, 0);
6467 return DAG.getNode(RISCVISD::PWZIP, DL, VT, V1, V2);
6468 }
6469 if (EvenSrc == NumElts && OddSrc == 0) {
6470 if (Subtarget.is64Bit())
6471 return DAG.getNode(RISCVISD::PZIP, DL, VT, V2, V1);
6472 EVT HalfVT = VT.getHalfNumVectorElementsVT();
6473 V1 = DAG.getExtractSubvector(DL, HalfVT, V1, 0);
6474 V2 = DAG.getExtractSubvector(DL, HalfVT, V2, 0);
6475 return DAG.getNode(RISCVISD::PWZIP, DL, VT, V2, V1);
6476 }
6477 }
6478
6479 return SDValue();
6480}
6481
6482// Match a deinterleave shuffle that forms a P-extension packed unzip:
6483// <a0, a2, ..., b0, b2, ...> -> unzip*p
6484// <a1, a3, ..., b1, b3, ...> -> unzip*hp
6486 SelectionDAG &DAG, bool IsRV64) {
6487 MVT VT = SVN->getSimpleValueType(0);
6488 if (!IsRV64 || (VT != MVT::v8i8 && VT != MVT::v4i16))
6489 return SDValue();
6490
6491 SDValue V1 = SVN->getOperand(0);
6492 SDValue V2 = SVN->getOperand(1);
6493 SDLoc DL(SVN);
6494 ArrayRef<int> Mask = SVN->getMask();
6495
6496 unsigned Index = 0;
6498 return SDValue();
6499
6500 unsigned Opc = Index == 0 ? RISCVISD::PUNZIPE : RISCVISD::PUNZIPO;
6501 return DAG.getNode(Opc, DL, VT, V1, V2);
6502}
6503
6504// Match a slide by one element with a scalar inserted at either end:
6505// <b0, a0, ..., aN-2> -> slide1up
6506// <a1, ..., aN-1, b0> -> slide1down
6508 const RISCVSubtarget &Subtarget,
6509 SelectionDAG &DAG) {
6510 MVT VT = SVN->getSimpleValueType(0);
6511 if (VT != MVT::v4i8 && VT != MVT::v8i8 && VT != MVT::v2i16 &&
6512 VT != MVT::v4i16 && VT != MVT::v2i32)
6513 return SDValue();
6514 if (!Subtarget.is64Bit() && VT == MVT::v2i32)
6515 return SDValue();
6516
6517 unsigned NumElts = VT.getVectorNumElements();
6518 ArrayRef<int> Mask = SVN->getMask();
6519 unsigned ActiveElts = NumElts;
6520 if (Subtarget.is64Bit() &&
6521 all_of(Mask.drop_front(NumElts / 2), [](int M) { return M < 0; }))
6522 ActiveElts /= 2;
6523
6524 ArrayRef<int> ActiveMask = Mask.take_front(ActiveElts);
6525 bool SlideUp = ActiveMask[0] == (int)NumElts &&
6526 all_of(enumerate(ActiveMask.drop_front()), [](const auto &M) {
6527 return M.value() == (int)M.index();
6528 });
6529 bool SlideDown = ActiveMask.back() == (int)NumElts &&
6530 all_of(enumerate(ActiveMask.drop_back()), [](const auto &M) {
6531 return M.value() == (int)M.index() + 1;
6532 });
6533 if (!SlideUp && !SlideDown)
6534 return SDValue();
6535
6536 SDValue V1 = SVN->getOperand(0);
6537 SDValue V2 = SVN->getOperand(1);
6538 SDLoc DL(SVN);
6539 unsigned EltBits = VT.getScalarSizeInBits();
6540 unsigned SlideBits = ActiveElts * EltBits;
6541 MVT XLenVT = Subtarget.getXLenVT();
6542 SDValue Scalar = DAG.getExtractVectorElt(DL, XLenVT, V2, 0);
6543
6544 // A two-element slide is exactly a packed pair operation.
6545 if (ActiveElts == 2) {
6546 SDValue ScalarVec = DAG.getBitcast(VT, Scalar);
6547 return DAG.getNode(SlideUp ? RISCVISD::PPAIRE : RISCVISD::PPAIROE, DL, VT,
6548 SlideUp ? ScalarVec : V1, SlideUp ? V1 : ScalarVec);
6549 }
6550
6551 // Lower a full-register slide to the funnel shift instruction that
6552 // implements it.
6553 if (SlideBits == Subtarget.getXLen()) {
6554 SDValue Bits = DAG.getBitcast(XLenVT, V1);
6555 SDValue Shamt = DAG.getConstant(EltBits, DL, XLenVT);
6556 if (SlideUp) {
6557 Scalar = DAG.getNode(ISD::SHL, DL, XLenVT, Scalar,
6558 DAG.getConstant(SlideBits - EltBits, DL, XLenVT));
6559 Bits = DAG.getNode(ISD::FSHL, DL, XLenVT, Bits, Scalar, Shamt);
6560 } else {
6561 Bits = DAG.getNode(ISD::FSHR, DL, XLenVT, Scalar, Bits, Shamt);
6562 }
6563 return DAG.getBitcast(VT, Bits);
6564 }
6565
6566 // A 32-bit packed slide on RV64 is carried in the low word of a GPR. Expand
6567 // it using XLEN operations or packed pair instructions.
6568 if (Subtarget.is64Bit()) {
6569 assert(SlideBits == 32 && "Unexpected RV64 packed slide width");
6570 SDValue Shamt = DAG.getConstant(EltBits, DL, MVT::i64);
6571 SDValue Bits = DAG.getBitcast(MVT::i64, V1);
6572 if (SlideUp) {
6573 Scalar = DAG.getNode(ISD::SHL, DL, MVT::i64, Scalar,
6574 DAG.getConstant(64 - EltBits, DL, MVT::i64));
6575 Bits = DAG.getNode(ISD::FSHL, DL, MVT::i64, Bits, Scalar, Shamt);
6576 } else {
6577 SDValue Pair = DAG.getNode(RISCVISD::PPAIRE, DL, MVT::v2i32,
6578 DAG.getBitcast(MVT::v2i32, V1),
6579 DAG.getBitcast(MVT::v2i32, Scalar));
6580 Bits = DAG.getNode(ISD::SRL, DL, MVT::i64, DAG.getBitcast(MVT::i64, Pair),
6581 Shamt);
6582 }
6583 return DAG.getBitcast(VT, Bits);
6584 }
6585
6586 // RV32 represents 64-bit packed values as two GPRs. Form each shifted half
6587 // directly so the slide uses two XLEN funnel shifts.
6588 assert(SlideBits == 64 && "Unexpected RV32 packed slide width");
6589 auto [LoVec, HiVec] = DAG.SplitVector(V1, DL);
6590 MVT HalfVT = LoVec.getSimpleValueType();
6591 SDValue Lo = DAG.getBitcast(MVT::i32, LoVec);
6592 SDValue Hi = DAG.getBitcast(MVT::i32, HiVec);
6593 SDValue Shamt = DAG.getConstant(EltBits, DL, MVT::i32);
6594 SDValue NewLo;
6595 SDValue NewHi;
6596 if (SlideUp) {
6597 SDValue Insert = DAG.getNode(ISD::SHL, DL, MVT::i32, Scalar,
6598 DAG.getConstant(32 - EltBits, DL, MVT::i32));
6599 NewLo = DAG.getNode(ISD::FSHL, DL, MVT::i32, Lo, Insert, Shamt);
6600 NewHi = DAG.getNode(ISD::FSHL, DL, MVT::i32, Hi, Lo, Shamt);
6601 } else {
6602 NewLo = DAG.getNode(ISD::FSHR, DL, MVT::i32, Hi, Lo, Shamt);
6603 NewHi = DAG.getNode(ISD::FSHR, DL, MVT::i32, Scalar, Hi, Shamt);
6604 }
6605 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, DAG.getBitcast(HalfVT, NewLo),
6606 DAG.getBitcast(HalfVT, NewHi));
6607}
6608
6609// Match the packed zero-extend shuffle mask <0, N, 2, N+2, ...>: even result
6610// lanes keep operand 0's even lanes and odd result lanes come from operand 1.
6611// The odd lanes may select any element of operand 1, which is looser than a
6612// strict pair-even mask; DAGCombiner::XformToShuffleWithZero forms exactly this
6613// from a packed zero-extend `and`, leaving each zeroed lane at its own
6614// position, and lowerVECTOR_SHUFFLEAsPPair then forms the PPAIRE. Undef lanes
6615// always match.
6617 unsigned NumElts = Mask.size();
6618 if (NumElts % 2 != 0)
6619 return false;
6620 for (unsigned I = 0; I != NumElts / 2; ++I)
6621 if ((Mask[2 * I] >= 0 && Mask[2 * I] != (int)(2 * I)) ||
6622 (Mask[2 * I + 1] >= 0 && Mask[2 * I + 1] < (int)NumElts))
6623 return false;
6624 return true;
6625}
6626
6627// Match a legalized deinterleave shuffle on two RV32 vector halves and lower
6628// it to an RV32 P narrowing shift on the concatenated source.
6629static SDValue
6631 const RISCVSubtarget &Subtarget,
6632 SelectionDAG &DAG) {
6633 MVT VT = SVN->getSimpleValueType(0);
6634 if (VT != MVT::v4i8)
6635 return SDValue();
6636
6637 SDValue V1 = SVN->getOperand(0);
6638 SDValue V2 = SVN->getOperand(1);
6639 SDLoc DL(SVN);
6640 unsigned NumElts = VT.getVectorNumElements();
6641
6642 SDValue Src = foldConcatVector(V1, V2);
6643 if (!Src) {
6644 MVT SrcVT = VT == MVT::v4i8 ? MVT::v8i8 : MVT::v4i16;
6645 Src = DAG.getNode(ISD::CONCAT_VECTORS, DL, SrcVT, V1, V2);
6646 }
6647
6648 // The source vector should be twice the size.
6649 if (Src.getValueType().getVectorNumElements() != 2 * NumElts)
6650 return SDValue();
6651
6652 unsigned Index = 0;
6654 return SDValue();
6655
6656 unsigned EltBits = VT.getVectorElementType().getSizeInBits();
6657 return DAG.getNode(RISCVISD::PNSRL, DL, VT, Src,
6658 DAG.getConstant(Index * EltBits, DL, MVT::i32));
6659}
6660
6661// Match a strided-interleave shuffle that forms a P-extension packed pair:
6662// <a0, b0, a2, b2, ...> -> ppaire.*
6663// <a0, b1, a2, b3, ...> -> ppaireo.*
6664// <a1, b0, a3, b2, ...> -> ppairoe.*
6665// <a1, b1, a3, b3, ...> -> ppairo.*
6667 SelectionDAG &DAG) {
6668 MVT VT = SVN->getSimpleValueType(0);
6669 if (VT != MVT::v4i8 && VT != MVT::v8i8 && VT != MVT::v2i16 &&
6670 VT != MVT::v4i16)
6671 return SDValue();
6672
6673 SDValue V1 = SVN->getOperand(0);
6674 SDValue V2 = SVN->getOperand(1);
6675 SDLoc DL(SVN);
6676 unsigned NumElts = VT.getVectorNumElements();
6677 ArrayRef<int> Mask = SVN->getMask();
6678
6679 // A splat operand's lanes are all equal, so a lane selecting from it matches
6680 // any of its positions. This covers the zero operand XformToShuffleWithZero
6681 // forms for a packed zero-extend, which keeps each zeroed lane at its own
6682 // position rather than the strided one.
6683 bool V1IsSplat = DAG.isSplatValue(V1);
6684 bool V2IsSplat = DAG.isSplatValue(V2);
6685
6686 // Walk the mask once, tracking the operand feeding the destination's even
6687 // lanes (index 0) and the operand feeding its odd lanes (index 1) — either
6688 // may turn out to be V1 or V2 — along with whether each pulls the even or
6689 // odd element out of its pair. All even (resp. odd) lanes must agree on
6690 // both the operand and the parity used; a splat operand's lanes are all
6691 // equal so it never constrains the parity.
6692 SDValue Src[2];
6693 std::optional<bool> Parity[2];
6694 for (unsigned I = 0; I != NumElts; ++I) {
6695 int M = Mask[I];
6696 if (M < 0)
6697 continue;
6698 unsigned Lane = I % 2;
6699 bool FromV1 = (unsigned)M < NumElts;
6700 SDValue Cand = FromV1 ? V1 : V2;
6701 unsigned Local = (unsigned)M % NumElts;
6702 if (!Src[Lane])
6703 Src[Lane] = Cand;
6704 else if (Src[Lane] != Cand)
6705 return SDValue();
6706
6707 // Splats don't constrain parity.
6708 if (FromV1 ? V1IsSplat : V2IsSplat)
6709 continue;
6710
6711 // The index must be from the even/odd element of its pair.
6712 if (Local / 2 != I / 2)
6713 return SDValue();
6714
6715 bool P = Local % 2;
6716 if (!Parity[Lane])
6717 Parity[Lane] = P;
6718 else if (*Parity[Lane] != P)
6719 return SDValue();
6720 }
6721
6722 // Make sure we have a source for both lanes.
6723 if (!Src[0] || !Src[1])
6724 return SDValue();
6725
6726 bool EvenIsOdd = Parity[0].value_or(false);
6727 bool OddIsOdd = Parity[1].value_or(false);
6728 unsigned Opc;
6729 if (!EvenIsOdd && !OddIsOdd)
6730 Opc = RISCVISD::PPAIRE;
6731 else if (EvenIsOdd && OddIsOdd)
6732 Opc = RISCVISD::PPAIRO;
6733 else if (!EvenIsOdd && OddIsOdd)
6734 Opc = RISCVISD::PPAIREO;
6735 else
6736 Opc = RISCVISD::PPAIROE;
6737
6738 return DAG.getNode(Opc, DL, VT, Src[0], Src[1]);
6739}
6740
6741SDValue RISCVTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
6742 SelectionDAG &DAG) const {
6743 SDValue V1 = Op.getOperand(0);
6744 SDValue V2 = Op.getOperand(1);
6745 SDLoc DL(Op);
6746 MVT XLenVT = Subtarget.getXLenVT();
6747 MVT VT = Op.getSimpleValueType();
6748 unsigned NumElts = VT.getVectorNumElements();
6749 ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op.getNode());
6750
6751 // Select RVP-specific packed shuffles before falling back to the generic
6752 // fixed/scalable-vector lowering below.
6753 if (Subtarget.hasStdExtP() && !Subtarget.hasVInstructions()) {
6754 ArrayRef<int> Mask = SVN->getMask();
6755
6756 // Select an element reverse shuffle to VECTOR_REVERSE. The tablegen
6757 // patterns select rev8/rev16/ppairoe.* from VECTOR_REVERSE.
6758 // Reverse of the low L lanes, higher lanes poison. L == NumElts is a plain
6759 // reverse; L == NumElts/2 is a widened RV64 v4i8/v2i16 reverse.
6760 auto IsLowReverse = [&](unsigned L) {
6761 return V2.isUndef() &&
6762 ShuffleVectorInst::isReverseMask(Mask.take_front(L), L) &&
6763 all_of(Mask.drop_front(L), [](int M) { return M < 0; });
6764 };
6765 if (IsLowReverse(NumElts))
6766 return DAG.getNode(ISD::VECTOR_REVERSE, DL, VT, V1);
6767 if (Subtarget.is64Bit() && VT == MVT::v4i16 && IsLowReverse(/*L=*/2))
6768 return DAG.getNode(RISCVISD::PPAIROE_H, DL, VT, V1, V1);
6769 // Widened: reversing sends the low-half lanes to the top half, so shift
6770 // them back down by half the register. Only the 64-bit packed types are
6771 // legal here, so the register is XLen (i64).
6772 if (Subtarget.is64Bit() && VT.getSizeInBits() == 64 &&
6773 IsLowReverse(NumElts / 2)) {
6774 SDValue Rev = DAG.getBitcast(
6775 MVT::i64, DAG.getNode(ISD::VECTOR_REVERSE, DL, VT, V1));
6776 SDValue Srl =
6777 DAG.getNode(ISD::SRL, DL, MVT::i64, Rev,
6778 DAG.getConstant(VT.getSizeInBits() / 2, DL, MVT::i64));
6779 return DAG.getBitcast(VT, Srl);
6780 }
6781
6782 if (SDValue V = lowerVECTOR_SHUFFLEAsPSlide1(SVN, Subtarget, DAG))
6783 return V;
6784 if (SDValue V = lowerVECTOR_SHUFFLEAsPUnzip(SVN, DAG, Subtarget.is64Bit()))
6785 return V;
6786 if (SDValue V = lowerVECTOR_SHUFFLEAsPZip(SVN, Subtarget, DAG))
6787 return V;
6788 if (SDValue V =
6789 lowerVECTOR_SHUFFLEAsRV32PNarrowingShift(SVN, Subtarget, DAG))
6790 return V;
6791 if (SDValue V = lowerVECTOR_SHUFFLEAsPPair(SVN, DAG))
6792 return V;
6793 return SDValue();
6794 }
6795
6796 if (VT.getVectorElementType() == MVT::i1) {
6797 // Lower to a vror.vi of a larger element type if possible before we promote
6798 // i1s to i8s.
6799 if (SDValue V = lowerVECTOR_SHUFFLEAsRotate(SVN, DAG, Subtarget))
6800 return V;
6801 if (SDValue V = lowerBitreverseShuffle(SVN, DAG, Subtarget))
6802 return V;
6803
6804 // Promote i1 shuffle to i8 shuffle.
6805 MVT WidenVT = MVT::getVectorVT(MVT::i8, VT.getVectorElementCount());
6806 V1 = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenVT, V1);
6807 V2 = V2.isUndef() ? DAG.getUNDEF(WidenVT)
6808 : DAG.getNode(ISD::ZERO_EXTEND, DL, WidenVT, V2);
6809 SDValue Shuffled = DAG.getVectorShuffle(WidenVT, DL, V1, V2, SVN->getMask());
6810 return DAG.getSetCC(DL, VT, Shuffled, DAG.getConstant(0, DL, WidenVT),
6811 ISD::SETNE);
6812 }
6813
6814 MVT ContainerVT = getContainerForFixedLengthVector(VT);
6815
6816 // Store the return value in a single variable instead of structured bindings
6817 // so that we can pass it to GetSlide below, which cannot capture structured
6818 // bindings until C++20.
6819 auto TrueMaskVL = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
6820 auto [TrueMask, VL] = TrueMaskVL;
6821
6822 if (SVN->isSplat()) {
6823 const int Lane = SVN->getSplatIndex();
6824 if (Lane >= 0) {
6825 MVT SVT = VT.getVectorElementType();
6826
6827 // Turn splatted vector load into a strided load with an X0 stride.
6828 SDValue V = V1;
6829 // Peek through CONCAT_VECTORS as VectorCombine can concat a vector
6830 // with undef.
6831 // FIXME: Peek through INSERT_SUBVECTOR, EXTRACT_SUBVECTOR, bitcasts?
6832 int Offset = Lane;
6833 if (V.getOpcode() == ISD::CONCAT_VECTORS) {
6834 int OpElements =
6835 V.getOperand(0).getSimpleValueType().getVectorNumElements();
6836 V = V.getOperand(Offset / OpElements);
6837 Offset %= OpElements;
6838 }
6839
6840 // We need to ensure the load isn't atomic or volatile.
6841 if (ISD::isNormalLoad(V.getNode()) && cast<LoadSDNode>(V)->isSimple()) {
6842 auto *Ld = cast<LoadSDNode>(V);
6843 Offset *= SVT.getStoreSize();
6844 SDValue NewAddr = DAG.getMemBasePlusOffset(
6845 Ld->getBasePtr(), TypeSize::getFixed(Offset), DL);
6846
6847 // If this is SEW=64 on RV32, use a strided load with a stride of x0.
6848 if (SVT.isInteger() && SVT.bitsGT(XLenVT)) {
6849 SDVTList VTs = DAG.getVTList({ContainerVT, MVT::Other});
6850 SDValue IntID =
6851 DAG.getTargetConstant(Intrinsic::riscv_vlse, DL, XLenVT);
6852 SDValue Ops[] = {Ld->getChain(),
6853 IntID,
6854 DAG.getUNDEF(ContainerVT),
6855 NewAddr,
6856 DAG.getRegister(RISCV::X0, XLenVT),
6857 VL};
6858 SDValue NewLoad = DAG.getMemIntrinsicNode(
6859 ISD::INTRINSIC_W_CHAIN, DL, VTs, Ops, SVT,
6861 Ld->getMemOperand(), Offset, SVT.getStoreSize()));
6862 DAG.makeEquivalentMemoryOrdering(Ld, NewLoad);
6863 return convertFromScalableVector(VT, NewLoad, DAG, Subtarget);
6864 }
6865
6866 MVT SplatVT = ContainerVT;
6867
6868 // f16 with zvfhmin and bf16 need to use an integer scalar load.
6869 if (SVT == MVT::bf16 ||
6870 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
6871 SVT = MVT::i16;
6872 SplatVT = ContainerVT.changeVectorElementType(SVT);
6873 }
6874
6875 // Otherwise use a scalar load and splat. This will give the best
6876 // opportunity to fold a splat into the operation. ISel can turn it into
6877 // the x0 strided load if we aren't able to fold away the select.
6878 if (SVT.isFloatingPoint())
6879 V = DAG.getLoad(SVT, DL, Ld->getChain(), NewAddr,
6880 Ld->getPointerInfo().getWithOffset(Offset),
6881 Ld->getBaseAlign(), Ld->getMemOperand()->getFlags());
6882 else
6883 V = DAG.getExtLoad(ISD::EXTLOAD, DL, XLenVT, Ld->getChain(), NewAddr,
6884 Ld->getPointerInfo().getWithOffset(Offset), SVT,
6885 Ld->getBaseAlign(),
6886 Ld->getMemOperand()->getFlags());
6888
6889 unsigned Opc = SplatVT.isFloatingPoint() ? RISCVISD::VFMV_V_F_VL
6890 : RISCVISD::VMV_V_X_VL;
6891 SDValue Splat =
6892 DAG.getNode(Opc, DL, SplatVT, DAG.getUNDEF(ContainerVT), V, VL);
6893 Splat = DAG.getBitcast(ContainerVT, Splat);
6894 return convertFromScalableVector(VT, Splat, DAG, Subtarget);
6895 }
6896
6897 V1 = convertToScalableVector(ContainerVT, V1, DAG, Subtarget);
6898 assert(Lane < (int)NumElts && "Unexpected lane!");
6899 SDValue Gather = DAG.getNode(RISCVISD::VRGATHER_VX_VL, DL, ContainerVT,
6900 V1, DAG.getConstant(Lane, DL, XLenVT),
6901 DAG.getUNDEF(ContainerVT), TrueMask, VL);
6902 return convertFromScalableVector(VT, Gather, DAG, Subtarget);
6903 }
6904 }
6905
6906 // For exact VLEN m2 or greater, try to split to m1 operations if we
6907 // can split cleanly.
6908 if (SDValue V = lowerShuffleViaVRegSplitting(SVN, DAG, Subtarget))
6909 return V;
6910
6911 ArrayRef<int> Mask = SVN->getMask();
6912
6913 if (SDValue V =
6914 lowerVECTOR_SHUFFLEAsVSlide1(DL, VT, V1, V2, Mask, Subtarget, DAG))
6915 return V;
6916
6917 if (SDValue V =
6918 lowerVECTOR_SHUFFLEAsVSlidedown(DL, VT, V1, V2, Mask, Subtarget, DAG))
6919 return V;
6920
6921 // A bitrotate will be one instruction on Zvkb, so try to lower to it first if
6922 // available.
6923 if (Subtarget.hasStdExtZvkb())
6924 if (SDValue V = lowerVECTOR_SHUFFLEAsRotate(SVN, DAG, Subtarget))
6925 return V;
6926
6927 if (ShuffleVectorInst::isReverseMask(Mask, NumElts) && V2.isUndef() &&
6928 NumElts != 2)
6929 return DAG.getNode(ISD::VECTOR_REVERSE, DL, VT, V1);
6930
6931 // Try using vunzip{e,o} from Zvzip to lower deinterleave2.
6932 unsigned Index = 0;
6933 if (Subtarget.hasStdExtZvzip() &&
6935 1 < count_if(Mask, [](int Idx) { return Idx != -1; })) {
6936 bool UsesBothSources =
6937 1 < count_if(Mask,
6938 [&Mask](int Idx) { return Idx < (int)Mask.size(); }) &&
6939 1 < count_if(Mask,
6940 [&Mask](int Idx) { return Idx >= (int)Mask.size(); });
6941
6942 unsigned Opc = Index == 0 ? RISCVISD::VUNZIPE_VL : RISCVISD::VUNZIPO_VL;
6943 if (isLegalVTForZvzipDeinterleavedOperand(VT, Subtarget)) {
6944 MVT NewVT = VT.getDoubleNumVectorElementsVT();
6945 if (isTypeLegal(NewVT)) {
6946 SDValue Op;
6947 if (V2.isUndef()) {
6948 Op = DAG.getNode(ISD::CONCAT_VECTORS, DL, NewVT, V1, V2);
6949 } else if (auto VLEN = Subtarget.getRealVLen();
6950 VLEN && VT.getSizeInBits().getKnownMinValue() % *VLEN == 0) {
6951 Op = DAG.getNode(ISD::CONCAT_VECTORS, DL, NewVT, V1, V2);
6952 } else if (SDValue Src = foldConcatVector(V1, V2)) {
6953 Op = DAG.getExtractSubvector(DL, NewVT, Src, 0);
6954 }
6955 if (Op)
6956 return lowerZvzipVUNZIP(Opc, Op, DL, DAG, Subtarget);
6957 }
6958 }
6959
6960 MVT HalfVT = VT.getHalfNumVectorElementsVT();
6961 if (UsesBothSources &&
6962 isLegalVTForZvzipDeinterleavedOperand(HalfVT, Subtarget) &&
6963 V1.getSimpleValueType().getVectorMinNumElements() >= 2 &&
6965 SDValue Lo = lowerZvzipVUNZIP(Opc, V1, DL, DAG, Subtarget);
6966 SDValue Hi = lowerZvzipVUNZIP(Opc, V2, DL, DAG, Subtarget);
6967 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi);
6968 }
6969 }
6970
6971 // If this is a deinterleave(2,4,8) and we can widen the vector, then we can
6972 // use shift and truncate to perform the shuffle.
6973 // TODO: For Factor=6, we can perform the first step of the deinterleave via
6974 // shift-and-trunc reducing total cost for everything except an mf8 result.
6975 // TODO: For Factor=4,8, we can do the same when the ratio isn't high enough
6976 // to do the entire operation.
6977 if (VT.getScalarSizeInBits() < Subtarget.getELen()) {
6978 const unsigned MaxFactor = Subtarget.getELen() / VT.getScalarSizeInBits();
6979 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6980 for (unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
6981 unsigned Index = 0;
6982 if (ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, Factor, Index) &&
6983 1 < count_if(Mask, [](int Idx) { return Idx != -1; })) {
6984 if (SDValue Src = getSingleShuffleSrc(VT, V1, V2))
6985 return getDeinterleaveShiftAndTrunc(DL, VT, Src, Factor, Index, DAG);
6986 if (1 < count_if(Mask,
6987 [&Mask](int Idx) { return Idx < (int)Mask.size(); }) &&
6988 1 < count_if(Mask, [&Mask](int Idx) {
6989 return Idx >= (int)Mask.size();
6990 })) {
6991 // Narrow each source and concatenate them.
6992 // FIXME: For small LMUL it is better to concatenate first.
6993 MVT EltVT = VT.getVectorElementType();
6994 auto EltCnt = VT.getVectorElementCount();
6995 MVT SubVT =
6996 MVT::getVectorVT(EltVT, EltCnt.divideCoefficientBy(Factor));
6997
6998 SDValue Lo =
6999 getDeinterleaveShiftAndTrunc(DL, SubVT, V1, Factor, Index, DAG);
7000 SDValue Hi =
7001 getDeinterleaveShiftAndTrunc(DL, SubVT, V2, Factor, Index, DAG);
7002
7003 SDValue Concat =
7006 if (Factor == 2)
7007 return Concat;
7008
7009 SDValue Vec = DAG.getUNDEF(VT);
7010 return DAG.getInsertSubvector(DL, Vec, Concat, 0);
7011 }
7012 }
7013 }
7014 }
7015
7016 if (SDValue V =
7017 lowerVECTOR_SHUFFLEAsVSlideup(DL, VT, V1, V2, Mask, Subtarget, DAG))
7018 return V;
7019
7020 // Detect an interleave shuffle and lower to
7021 // (vmaccu.vx (vwaddu.vx lohalf(V1), lohalf(V2)), lohalf(V2), (2^eltbits - 1))
7022 int EvenSrc, OddSrc;
7023 if (isInterleaveShuffle(Mask, VT, EvenSrc, OddSrc, Subtarget) &&
7024 !(NumElts == 2 &&
7026 // Extract the halves of the vectors.
7027 MVT HalfVT = VT.getHalfNumVectorElementsVT();
7028
7029 // Recognize if one half is actually undef; the matching above will
7030 // otherwise reuse the even stream for the undef one. This improves
7031 // spread(2) shuffles.
7032 bool LaneIsUndef[2] = { true, true};
7033 for (const auto &[Idx, M] : enumerate(Mask))
7034 LaneIsUndef[Idx % 2] &= (M == -1);
7035
7036 int Size = Mask.size();
7037 SDValue EvenV, OddV;
7038 if (LaneIsUndef[0]) {
7039 EvenV = DAG.getUNDEF(HalfVT);
7040 } else {
7041 assert(EvenSrc >= 0 && "Undef source?");
7042 EvenV = (EvenSrc / Size) == 0 ? V1 : V2;
7043 EvenV = DAG.getExtractSubvector(DL, HalfVT, EvenV, EvenSrc % Size);
7044 }
7045
7046 if (LaneIsUndef[1]) {
7047 OddV = DAG.getUNDEF(HalfVT);
7048 } else {
7049 assert(OddSrc >= 0 && "Undef source?");
7050 OddV = (OddSrc / Size) == 0 ? V1 : V2;
7051 OddV = DAG.getExtractSubvector(DL, HalfVT, OddV, OddSrc % Size);
7052 }
7053
7054 // Prefer vzip if available.
7055 // TODO: Extend to matching vzip if EvenSrc and OddSrc allow.
7056 if (Subtarget.hasStdExtZvzip() &&
7058 return lowerZvzipVZIP(EvenV, OddV, DL, DAG, Subtarget);
7059 return getWideningInterleave(EvenV, OddV, DL, DAG, Subtarget);
7060 }
7061
7062 // Recognize a pattern which can handled via a pair of vslideup/vslidedown
7063 // instructions (in any combination) with masking on the second instruction.
7064 // Also handles masked slides into an identity source, and single slides
7065 // without masking. Avoid matching bit rotates (which are not also element
7066 // rotates) as slide pairs. This is a performance heuristic, not a
7067 // functional check.
7068 std::array<std::pair<int, int>, 2> SrcInfo;
7069 unsigned RotateAmt;
7070 MVT RotateVT;
7071 if (::isMaskedSlidePair(Mask, SrcInfo) &&
7072 (isElementRotate(SrcInfo, NumElts) ||
7073 !isLegalBitRotate(Mask, VT, Subtarget, RotateVT, RotateAmt))) {
7074 SDValue Sources[2];
7075 auto GetSourceFor = [&](const std::pair<int, int> &Info) {
7076 int SrcIdx = Info.first;
7077 assert(SrcIdx == 0 || SrcIdx == 1);
7078 SDValue &Src = Sources[SrcIdx];
7079 if (!Src) {
7080 SDValue SrcV = SrcIdx == 0 ? V1 : V2;
7081 Src = convertToScalableVector(ContainerVT, SrcV, DAG, Subtarget);
7082 }
7083 return Src;
7084 };
7085 auto GetSlide = [&](const std::pair<int, int> &Src, SDValue Mask,
7086 SDValue Passthru) {
7087 auto [TrueMask, VL] = TrueMaskVL;
7088 SDValue SrcV = GetSourceFor(Src);
7089 int SlideAmt = Src.second;
7090 if (SlideAmt == 0) {
7091 // Should never be second operation
7092 assert(Mask == TrueMask);
7093 return SrcV;
7094 }
7095 if (SlideAmt < 0)
7096 return getVSlidedown(DAG, Subtarget, DL, ContainerVT, Passthru, SrcV,
7097 DAG.getConstant(-SlideAmt, DL, XLenVT), Mask, VL,
7099 return getVSlideup(DAG, Subtarget, DL, ContainerVT, Passthru, SrcV,
7100 DAG.getConstant(SlideAmt, DL, XLenVT), Mask, VL,
7102 };
7103
7104 if (SrcInfo[1].first == -1) {
7105 SDValue Res = DAG.getUNDEF(ContainerVT);
7106 Res = GetSlide(SrcInfo[0], TrueMask, Res);
7107 return convertFromScalableVector(VT, Res, DAG, Subtarget);
7108 }
7109
7110 if (Subtarget.hasStdExtZvzip()) {
7111 bool TryWiden = false;
7112 unsigned Factor;
7113 if (isPairEven(SrcInfo, Mask, Factor)) {
7114 if (Factor == 1) {
7115 SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
7116 SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
7117 return lowerZvzipVPAIR(RISCVISD::VPAIRE_VL, Src1, Src2, DL, DAG,
7118 Subtarget);
7119 }
7120 TryWiden = true;
7121 }
7122 if (isPairOdd(SrcInfo, Mask, Factor)) {
7123 if (Factor == 1) {
7124 SDValue Src1 = SrcInfo[1].first == 0 ? V1 : V2;
7125 SDValue Src2 = SrcInfo[0].first == 0 ? V1 : V2;
7126 return lowerZvzipVPAIR(RISCVISD::VPAIRO_VL, Src1, Src2, DL, DAG,
7127 Subtarget);
7128 }
7129 TryWiden = true;
7130 }
7131 // If we found a widening oppurtunity which would let us form a
7132 // pair-even or pair-odd, use the generic code to widen the shuffle
7133 // and recurse through this logic.
7134 if (TryWiden)
7135 if (SDValue V = tryWidenMaskForShuffle(Op, DAG))
7136 return V;
7137 }
7138
7139 // Build the mask. Note that vslideup unconditionally preserves elements
7140 // below the slide amount in the destination, and thus those elements are
7141 // undefined in the mask. If the mask ends up all true (or undef), it
7142 // will be folded away by general logic.
7143 SmallVector<SDValue> MaskVals;
7144 for (const auto &[Idx, M] : enumerate(Mask)) {
7145 if (M < 0 ||
7146 (SrcInfo[1].second > 0 && Idx < (unsigned)SrcInfo[1].second)) {
7147 MaskVals.push_back(DAG.getUNDEF(XLenVT));
7148 continue;
7149 }
7150 int Src = M >= (int)NumElts;
7151 int Diff = (int)Idx - (M % NumElts);
7152 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
7153 assert(C ^ (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
7154 "Must match exactly one of the two slides");
7155 MaskVals.push_back(DAG.getConstant(C, DL, XLenVT));
7156 }
7157 assert(MaskVals.size() == NumElts && "Unexpected select-like shuffle");
7158 MVT MaskVT = MVT::getVectorVT(MVT::i1, NumElts);
7159 SDValue SelectMask = convertToScalableVector(
7160 ContainerVT.changeVectorElementType(MVT::i1),
7161 DAG.getBuildVector(MaskVT, DL, MaskVals), DAG, Subtarget);
7162
7163 SDValue Res = DAG.getUNDEF(ContainerVT);
7164 Res = GetSlide(SrcInfo[0], TrueMask, Res);
7165 Res = GetSlide(SrcInfo[1], SelectMask, Res);
7166 return convertFromScalableVector(VT, Res, DAG, Subtarget);
7167 }
7168
7169 // Handle any remaining single source shuffles
7170 assert(!V1.isUndef() && "Unexpected shuffle canonicalization");
7171 if (V2.isUndef()) {
7172 // We might be able to express the shuffle as a bitrotate. But even if we
7173 // don't have Zvkb and have to expand, the expanded sequence of approx. 2
7174 // shifts and a vor will have a higher throughput than a vrgather.
7175 if (SDValue V = lowerVECTOR_SHUFFLEAsRotate(SVN, DAG, Subtarget))
7176 return V;
7177
7178 if (SDValue V = lowerVECTOR_SHUFFLEAsVRGatherVX(SVN, Subtarget, DAG))
7179 return V;
7180
7181 // Match a spread(4,8) which can be done via extend and shift. Spread(2)
7182 // is fully covered in interleave(2) above, so it is ignored here.
7183 if (VT.getScalarSizeInBits() < Subtarget.getELen()) {
7184 unsigned MaxFactor = Subtarget.getELen() / VT.getScalarSizeInBits();
7185 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
7186 for (unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
7187 unsigned Index;
7188 if (RISCVTargetLowering::isSpreadMask(Mask, Factor, Index)) {
7189 MVT NarrowVT =
7190 MVT::getVectorVT(VT.getVectorElementType(), NumElts / Factor);
7191 SDValue Src = DAG.getExtractSubvector(DL, NarrowVT, V1, 0);
7192 return getWideningSpread(Src, Factor, Index, DL, DAG);
7193 }
7194 }
7195 }
7196
7197 // If only a prefix of the source elements influence a prefix of the
7198 // destination elements, try to see if we can reduce the required LMUL
7199 unsigned MinVLen = Subtarget.getRealMinVLen();
7200 unsigned MinVLMAX = MinVLen / VT.getScalarSizeInBits();
7201 if (NumElts > MinVLMAX) {
7202 unsigned MaxIdx = 0;
7203 for (auto [I, M] : enumerate(Mask)) {
7204 if (M == -1)
7205 continue;
7206 MaxIdx = std::max({(unsigned)I, (unsigned)M, MaxIdx});
7207 }
7208 unsigned NewNumElts =
7209 std::max((uint64_t)MinVLMAX, PowerOf2Ceil(MaxIdx + 1));
7210 if (NewNumElts != NumElts) {
7211 MVT NewVT = MVT::getVectorVT(VT.getVectorElementType(), NewNumElts);
7212 V1 = DAG.getExtractSubvector(DL, NewVT, V1, 0);
7213 SDValue Res = DAG.getVectorShuffle(NewVT, DL, V1, DAG.getUNDEF(NewVT),
7214 Mask.take_front(NewNumElts));
7215 return DAG.getInsertSubvector(DL, DAG.getUNDEF(VT), Res, 0);
7216 }
7217 }
7218
7219 // Before hitting generic lowering fallbacks, try to widen the mask
7220 // to a wider SEW.
7221 if (SDValue V = tryWidenMaskForShuffle(Op, DAG))
7222 return V;
7223
7224 // Can we generate a vcompress instead of a vrgather? These scale better
7225 // at high LMUL, at the cost of not being able to fold a following select
7226 // into them. The mask constants are also smaller than the index vector
7227 // constants, and thus easier to materialize.
7228 if (isCompressMask(Mask)) {
7229 SmallVector<SDValue> MaskVals(NumElts,
7230 DAG.getConstant(false, DL, XLenVT));
7231 for (auto Idx : Mask) {
7232 if (Idx == -1)
7233 break;
7234 assert(Idx >= 0 && (unsigned)Idx < NumElts);
7235 MaskVals[Idx] = DAG.getConstant(true, DL, XLenVT);
7236 }
7237 MVT MaskVT = MVT::getVectorVT(MVT::i1, NumElts);
7238 SDValue CompressMask = DAG.getBuildVector(MaskVT, DL, MaskVals);
7239 return DAG.getNode(ISD::VECTOR_COMPRESS, DL, VT, V1, CompressMask,
7240 DAG.getUNDEF(VT));
7241 }
7242
7243 if (VT.getScalarSizeInBits() == 8 &&
7244 any_of(Mask, [&](const auto &Idx) { return Idx > 255; })) {
7245 // On such a vector we're unable to use i8 as the index type.
7246 // FIXME: We could promote the index to i16 and use vrgatherei16, but that
7247 // may involve vector splitting if we're already at LMUL=8, or our
7248 // user-supplied maximum fixed-length LMUL.
7249 return SDValue();
7250 }
7251
7252 // Base case for the two operand recursion below - handle the worst case
7253 // single source shuffle.
7254 unsigned GatherVVOpc = RISCVISD::VRGATHER_VV_VL;
7255 MVT IndexVT = VT.changeTypeToInteger();
7256 // Since we can't introduce illegal index types at this stage, use i16 and
7257 // vrgatherei16 if the corresponding index type for plain vrgather is greater
7258 // than XLenVT.
7259 if (IndexVT.getScalarType().bitsGT(XLenVT)) {
7260 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
7261 IndexVT = IndexVT.changeVectorElementType(MVT::i16);
7262 }
7263
7264 // If the mask allows, we can do all the index computation in 16 bits. This
7265 // requires less work and less register pressure at high LMUL, and creates
7266 // smaller constants which may be cheaper to materialize.
7267 if (IndexVT.getScalarType().bitsGT(MVT::i16) && isUInt<16>(NumElts - 1) &&
7268 (IndexVT.getSizeInBits() / Subtarget.getRealMinVLen()) > 1) {
7269 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
7270 IndexVT = IndexVT.changeVectorElementType(MVT::i16);
7271 }
7272
7273 MVT IndexContainerVT =
7274 ContainerVT.changeVectorElementType(IndexVT.getScalarType());
7275
7276 V1 = convertToScalableVector(ContainerVT, V1, DAG, Subtarget);
7277 SmallVector<SDValue> GatherIndicesLHS;
7278 for (int MaskIndex : Mask) {
7279 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
7280 GatherIndicesLHS.push_back(IsLHSIndex
7281 ? DAG.getConstant(MaskIndex, DL, XLenVT)
7282 : DAG.getUNDEF(XLenVT));
7283 }
7284 SDValue LHSIndices = DAG.getBuildVector(IndexVT, DL, GatherIndicesLHS);
7285 LHSIndices =
7286 convertToScalableVector(IndexContainerVT, LHSIndices, DAG, Subtarget);
7287 // At m1 and less, there's no point trying any of the high LMUL splitting
7288 // techniques. TODO: Should we reconsider this for DLEN < VLEN?
7289 if (NumElts <= MinVLMAX) {
7290 SDValue Gather = DAG.getNode(GatherVVOpc, DL, ContainerVT, V1, LHSIndices,
7291 DAG.getUNDEF(ContainerVT), TrueMask, VL);
7292 return convertFromScalableVector(VT, Gather, DAG, Subtarget);
7293 }
7294
7295 const MVT M1VT = RISCVTargetLowering::getM1VT(ContainerVT);
7296 EVT SubIndexVT = M1VT.changeVectorElementType(IndexVT.getScalarType());
7297 auto [InnerTrueMask, InnerVL] =
7298 getDefaultScalableVLOps(M1VT, DL, DAG, Subtarget);
7299 int N =
7300 ContainerVT.getVectorMinNumElements() / M1VT.getVectorMinNumElements();
7301 assert(isPowerOf2_32(N) && N <= 8);
7302
7303 // If we have a locally repeating mask, then we can reuse the first
7304 // register in the index register group for all registers within the
7305 // source register group. TODO: This generalizes to m2, and m4.
7306 if (isLocalRepeatingShuffle(Mask, MinVLMAX)) {
7307 SDValue SubIndex = DAG.getExtractSubvector(DL, SubIndexVT, LHSIndices, 0);
7308 SDValue Gather = DAG.getUNDEF(ContainerVT);
7309 for (int i = 0; i < N; i++) {
7310 unsigned SubIdx = M1VT.getVectorMinNumElements() * i;
7311 SDValue SubV1 = DAG.getExtractSubvector(DL, M1VT, V1, SubIdx);
7312 SDValue SubVec =
7313 DAG.getNode(GatherVVOpc, DL, M1VT, SubV1, SubIndex,
7314 DAG.getUNDEF(M1VT), InnerTrueMask, InnerVL);
7315 Gather = DAG.getInsertSubvector(DL, Gather, SubVec, SubIdx);
7316 }
7317 return convertFromScalableVector(VT, Gather, DAG, Subtarget);
7318 }
7319
7320 // If we have a shuffle which only uses the first register in our source
7321 // register group, and repeats the same index across all spans, we can
7322 // use a single vrgather (and possibly some register moves).
7323 // TODO: This can be generalized for m2 or m4, or for any shuffle for
7324 // which we can do a linear number of shuffles to form an m1 which
7325 // contains all the output elements.
7326 if (isLowSourceShuffle(Mask, MinVLMAX) &&
7327 isSpanSplatShuffle(Mask, MinVLMAX)) {
7328 SDValue SubV1 = DAG.getExtractSubvector(DL, M1VT, V1, 0);
7329 SDValue SubIndex = DAG.getExtractSubvector(DL, SubIndexVT, LHSIndices, 0);
7330 SDValue SubVec = DAG.getNode(GatherVVOpc, DL, M1VT, SubV1, SubIndex,
7331 DAG.getUNDEF(M1VT), InnerTrueMask, InnerVL);
7332 SDValue Gather = DAG.getUNDEF(ContainerVT);
7333 for (int i = 0; i < N; i++)
7334 Gather = DAG.getInsertSubvector(DL, Gather, SubVec,
7335 M1VT.getVectorMinNumElements() * i);
7336 return convertFromScalableVector(VT, Gather, DAG, Subtarget);
7337 }
7338
7339 // If we have a shuffle which only uses the first register in our
7340 // source register group, we can do a linear number of m1 vrgathers
7341 // reusing the same source register (but with different indices)
7342 // TODO: This can be generalized for m2 or m4, or for any shuffle
7343 // for which we can do a vslidedown followed by this expansion.
7344 if (isLowSourceShuffle(Mask, MinVLMAX)) {
7345 SDValue SlideAmt =
7346 DAG.getElementCount(DL, XLenVT, M1VT.getVectorElementCount());
7347 SDValue SubV1 = DAG.getExtractSubvector(DL, M1VT, V1, 0);
7348 SDValue Gather = DAG.getUNDEF(ContainerVT);
7349 for (int i = 0; i < N; i++) {
7350 if (i != 0)
7351 LHSIndices = getVSlidedown(DAG, Subtarget, DL, IndexContainerVT,
7352 DAG.getUNDEF(IndexContainerVT), LHSIndices,
7353 SlideAmt, TrueMask, VL);
7354 SDValue SubIndex =
7355 DAG.getExtractSubvector(DL, SubIndexVT, LHSIndices, 0);
7356 SDValue SubVec =
7357 DAG.getNode(GatherVVOpc, DL, M1VT, SubV1, SubIndex,
7358 DAG.getUNDEF(M1VT), InnerTrueMask, InnerVL);
7359 Gather = DAG.getInsertSubvector(DL, Gather, SubVec,
7360 M1VT.getVectorMinNumElements() * i);
7361 }
7362 return convertFromScalableVector(VT, Gather, DAG, Subtarget);
7363 }
7364
7365 // Fallback to generic vrgather if we can't find anything better.
7366 // On many machines, this will be O(LMUL^2)
7367 SDValue Gather = DAG.getNode(GatherVVOpc, DL, ContainerVT, V1, LHSIndices,
7368 DAG.getUNDEF(ContainerVT), TrueMask, VL);
7369 return convertFromScalableVector(VT, Gather, DAG, Subtarget);
7370 }
7371
7372 // As a backup, shuffles can be lowered via a vrgather instruction, possibly
7373 // merged with a second vrgather.
7374 SmallVector<int> ShuffleMaskLHS, ShuffleMaskRHS;
7375
7376 // Now construct the mask that will be used by the blended vrgather operation.
7377 // Construct the appropriate indices into each vector.
7378 for (int MaskIndex : Mask) {
7379 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
7380 ShuffleMaskLHS.push_back(IsLHSOrUndefIndex && MaskIndex >= 0
7381 ? MaskIndex : -1);
7382 ShuffleMaskRHS.push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
7383 }
7384
7385 // If the mask indices are disjoint between the two sources, we can lower it
7386 // as a vselect + a single source vrgather.vv. Don't do this if we think the
7387 // operands may end up being lowered to something cheaper than a vrgather.vv.
7388 if (!DAG.isSplatValue(V2) && !DAG.isSplatValue(V1) &&
7389 !ShuffleVectorSDNode::isSplatMask(ShuffleMaskLHS) &&
7390 !ShuffleVectorSDNode::isSplatMask(ShuffleMaskRHS) &&
7391 !ShuffleVectorInst::isIdentityMask(ShuffleMaskLHS, NumElts) &&
7392 !ShuffleVectorInst::isIdentityMask(ShuffleMaskRHS, NumElts))
7393 if (SDValue V = lowerDisjointIndicesShuffle(SVN, DAG, Subtarget))
7394 return V;
7395
7396 // Before hitting generic lowering fallbacks, try to widen the mask
7397 // to a wider SEW.
7398 if (SDValue V = tryWidenMaskForShuffle(Op, DAG))
7399 return V;
7400
7401 // Try to pick a profitable operand order.
7402 bool SwapOps = DAG.isSplatValue(V2) && !DAG.isSplatValue(V1);
7403 SwapOps = SwapOps ^ ShuffleVectorInst::isIdentityMask(ShuffleMaskRHS, NumElts);
7404
7405 // Recursively invoke lowering for each operand if we had two
7406 // independent single source shuffles, and then combine the result via a
7407 // vselect. Note that the vselect will likely be folded back into the
7408 // second permute (vrgather, or other) by the post-isel combine.
7409 V1 = DAG.getVectorShuffle(VT, DL, V1, DAG.getUNDEF(VT), ShuffleMaskLHS);
7410 V2 = DAG.getVectorShuffle(VT, DL, V2, DAG.getUNDEF(VT), ShuffleMaskRHS);
7411
7412 SmallVector<SDValue> MaskVals;
7413 for (int MaskIndex : Mask) {
7414 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
7415 MaskVals.push_back(DAG.getConstant(SelectMaskVal, DL, XLenVT));
7416 }
7417
7418 assert(MaskVals.size() == NumElts && "Unexpected select-like shuffle");
7419 MVT MaskVT = MVT::getVectorVT(MVT::i1, NumElts);
7420 SDValue SelectMask = DAG.getBuildVector(MaskVT, DL, MaskVals);
7421
7422 if (SwapOps)
7423 return DAG.getNode(ISD::VSELECT, DL, VT, SelectMask, V1, V2);
7424 return DAG.getNode(ISD::VSELECT, DL, VT, SelectMask, V2, V1);
7425}
7426
7428 EVT VT) const {
7429 // Enable DAGCombiner::XformToShuffleWithZero to rewrite a packed zero-extend
7430 // `and` into shuffle(src, zero, ...), which lowerVECTOR_SHUFFLE turns into
7431 // RISCVISD::PPAIRE. Accept the packed byte/halfword views that lowering
7432 // handles; the 32-bit views are illegal on RV64 but reachable before type
7433 // legalization widens them to the legal 64-bit view.
7434 if (!Subtarget.hasStdExtP() || !VT.isSimple())
7435 return false;
7436 MVT SVT = VT.getSimpleVT();
7437 return (SVT == MVT::v4i8 || SVT == MVT::v8i8 || SVT == MVT::v4i16) &&
7439}
7440
7442 // Only support legal VTs for other shuffles for now.
7443 if (!isTypeLegal(VT) || !Subtarget.hasVInstructions())
7444 return false;
7445
7446 // Support splats for any type. These should type legalize well.
7448 return true;
7449
7450 const unsigned NumElts = M.size();
7451 MVT SVT = VT.getSimpleVT();
7452
7453 // Not for i1 vectors.
7454 if (SVT.getScalarType() == MVT::i1)
7455 return false;
7456
7457 std::array<std::pair<int, int>, 2> SrcInfo;
7458 int Dummy1, Dummy2;
7459 return ShuffleVectorInst::isReverseMask(M, NumElts) ||
7460 (::isMaskedSlidePair(M, SrcInfo) &&
7461 isElementRotate(SrcInfo, NumElts)) ||
7462 isInterleaveShuffle(M, SVT, Dummy1, Dummy2, Subtarget);
7463}
7464
7465// Lower CTLZ_ZERO_POISON or CTTZ_ZERO_POISON by converting to FP and extracting
7466// the exponent.
7467SDValue
7468RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_POISON(SDValue Op,
7469 SelectionDAG &DAG) const {
7470 MVT VT = Op.getSimpleValueType();
7471 unsigned EltSize = VT.getScalarSizeInBits();
7472 SDValue Src = Op.getOperand(0);
7473 SDLoc DL(Op);
7474 MVT ContainerVT = VT;
7475
7476 // We choose FP type that can represent the value if possible. Otherwise, we
7477 // use rounding to zero conversion for correct exponent of the result.
7478 // TODO: Use f16 for i8 when possible?
7479 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 : MVT::f32;
7480 if (!isTypeLegal(MVT::getVectorVT(FloatEltVT, VT.getVectorElementCount())))
7481 FloatEltVT = MVT::f32;
7482 MVT FloatVT = MVT::getVectorVT(FloatEltVT, VT.getVectorElementCount());
7483
7484 // Legal types should have been checked in the RISCVTargetLowering
7485 // constructor.
7486 // TODO: Splitting may make sense in some cases.
7487 assert(DAG.getTargetLoweringInfo().isTypeLegal(FloatVT) &&
7488 "Expected legal float type!");
7489
7490 // For CTTZ_ZERO_POISON, we need to extract the lowest set bit using X & -X.
7491 // The trailing zero count is equal to log2 of this single bit value.
7492 if (Op.getOpcode() == ISD::CTTZ_ZERO_POISON) {
7493 SDValue Neg = DAG.getNegative(Src, DL, VT);
7494 Src = DAG.getNode(ISD::AND, DL, VT, Src, Neg);
7495 }
7496
7497 // We have a legal FP type, convert to it.
7498 SDValue FloatVal;
7499 if (FloatVT.bitsGT(VT)) {
7500 FloatVal = DAG.getNode(ISD::UINT_TO_FP, DL, FloatVT, Src);
7501 } else {
7502 // Use RTZ to avoid rounding influencing exponent of FloatVal.
7503 if (VT.isFixedLengthVector()) {
7504 ContainerVT = getContainerForFixedLengthVector(VT);
7505 Src = convertToScalableVector(ContainerVT, Src, DAG, Subtarget);
7506 }
7507 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
7508 SDValue RTZRM =
7509 DAG.getTargetConstant(RISCVFPRndMode::RTZ, DL, Subtarget.getXLenVT());
7510 MVT ContainerFloatVT =
7511 MVT::getVectorVT(FloatEltVT, ContainerVT.getVectorElementCount());
7512 FloatVal = DAG.getNode(RISCVISD::VFCVT_RM_F_XU_VL, DL, ContainerFloatVT,
7513 Src, Mask, RTZRM, VL);
7514 if (VT.isFixedLengthVector())
7515 FloatVal = convertFromScalableVector(FloatVT, FloatVal, DAG, Subtarget);
7516 }
7517 // Bitcast to integer and shift the exponent to the LSB.
7518 EVT IntVT = FloatVT.changeVectorElementTypeToInteger();
7519 SDValue Bitcast = DAG.getBitcast(IntVT, FloatVal);
7520 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
7521
7522 // Restore back to original type. Truncation after SRL is to generate vnsrl.
7523 SDValue Exp = DAG.getNode(ISD::SRL, DL, IntVT, Bitcast,
7524 DAG.getConstant(ShiftAmt, DL, IntVT));
7525 if (IntVT.bitsLT(VT))
7526 Exp = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, Exp);
7527 else if (IntVT.bitsGT(VT))
7528 Exp = DAG.getNode(ISD::TRUNCATE, DL, VT, Exp);
7529
7530 // The exponent contains log2 of the value in biased form.
7531 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
7532 // For trailing zeros, we just need to subtract the bias.
7533 if (Op.getOpcode() == ISD::CTTZ_ZERO_POISON)
7534 return DAG.getNode(ISD::SUB, DL, VT, Exp,
7535 DAG.getConstant(ExponentBias, DL, VT));
7536
7537 // For leading zeros, we need to remove the bias and convert from log2 to
7538 // leading zeros. We can do this by subtracting from (Bias + (EltSize - 1)).
7539 unsigned Adjust = ExponentBias + (EltSize - 1);
7540 SDValue Res =
7541 DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(Adjust, DL, VT), Exp);
7542
7543 // The above result with zero input equals to Adjust which is greater than
7544 // EltSize. Hence, we can do min(Res, EltSize) for CTLZ.
7545 if (Op.getOpcode() == ISD::CTLZ)
7546 Res = DAG.getNode(ISD::UMIN, DL, VT, Res, DAG.getConstant(EltSize, DL, VT));
7547
7548 return Res;
7549}
7550
7551SDValue RISCVTargetLowering::lowerVPCttzElements(SDValue Op,
7552 SelectionDAG &DAG) const {
7553 SDLoc DL(Op);
7554 MVT XLenVT = Subtarget.getXLenVT();
7555 SDValue Source = Op->getOperand(0);
7556 MVT SrcVT = Source.getSimpleValueType();
7557 SDValue Mask = Op->getOperand(1);
7558 SDValue EVL = Op->getOperand(2);
7559
7560 if (SrcVT.isFixedLengthVector()) {
7561 MVT ContainerVT = getContainerForFixedLengthVector(SrcVT);
7562 Source = convertToScalableVector(ContainerVT, Source, DAG, Subtarget);
7563 Mask = convertToScalableVector(getMaskTypeFor(ContainerVT), Mask, DAG,
7564 Subtarget);
7565 SrcVT = ContainerVT;
7566 }
7567
7568 // Convert to boolean vector.
7569 if (SrcVT.getScalarType() != MVT::i1) {
7570 SDValue AllZero = DAG.getConstant(0, DL, SrcVT);
7571 SrcVT = MVT::getVectorVT(MVT::i1, SrcVT.getVectorElementCount());
7572 Source = DAG.getNode(RISCVISD::SETCC_VL, DL, SrcVT,
7573 {Source, AllZero, DAG.getCondCode(ISD::SETNE),
7574 DAG.getUNDEF(SrcVT), Mask, EVL});
7575 }
7576
7577 SDValue Res = DAG.getNode(RISCVISD::VFIRST_VL, DL, XLenVT, Source, Mask, EVL);
7578 if (Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_POISON)
7579 // In this case, we can interpret poison as -1, so nothing to do further.
7580 return Res;
7581
7582 // Convert -1 to VL.
7583 SDValue SetCC =
7584 DAG.getSetCC(DL, XLenVT, Res, DAG.getConstant(0, DL, XLenVT), ISD::SETLT);
7585 Res = DAG.getSelect(DL, XLenVT, SetCC, EVL, Res);
7586 return DAG.getNode(ISD::TRUNCATE, DL, Op.getValueType(), Res);
7587}
7588
7589// While RVV has alignment restrictions, we should always be able to load as a
7590// legal equivalently-sized byte-typed vector instead. This method is
7591// responsible for re-expressing a ISD::LOAD via a correctly-aligned type. If
7592// the load is already correctly-aligned, it returns SDValue().
7593SDValue RISCVTargetLowering::expandUnalignedRVVLoad(SDValue Op,
7594 SelectionDAG &DAG) const {
7595 auto *Load = cast<LoadSDNode>(Op);
7596 assert(Load && Load->getMemoryVT().isVector() && "Expected vector load");
7597
7599 Load->getMemoryVT(),
7600 *Load->getMemOperand()))
7601 return SDValue();
7602
7603 SDLoc DL(Op);
7604 MVT VT = Op.getSimpleValueType();
7605 unsigned EltSizeBits = VT.getScalarSizeInBits();
7606 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
7607 "Unexpected unaligned RVV load type");
7608 MVT NewVT =
7609 MVT::getVectorVT(MVT::i8, VT.getVectorElementCount() * (EltSizeBits / 8));
7610 assert(NewVT.isValid() &&
7611 "Expecting equally-sized RVV vector types to be legal");
7612 SDValue L = DAG.getLoad(NewVT, DL, Load->getChain(), Load->getBasePtr(),
7613 Load->getPointerInfo(), Load->getBaseAlign(),
7614 Load->getMemOperand()->getFlags());
7615 return DAG.getMergeValues({DAG.getBitcast(VT, L), L.getValue(1)}, DL);
7616}
7617
7618// While RVV has alignment restrictions, we should always be able to store as a
7619// legal equivalently-sized byte-typed vector instead. This method is
7620// responsible for re-expressing a ISD::STORE via a correctly-aligned type. It
7621// returns SDValue() if the store is already correctly aligned.
7622SDValue RISCVTargetLowering::expandUnalignedRVVStore(SDValue Op,
7623 SelectionDAG &DAG) const {
7624 auto *Store = cast<StoreSDNode>(Op);
7625 assert(Store && Store->getValue().getValueType().isVector() &&
7626 "Expected vector store");
7627
7629 Store->getMemoryVT(),
7630 *Store->getMemOperand()))
7631 return SDValue();
7632
7633 SDLoc DL(Op);
7634 SDValue StoredVal = Store->getValue();
7635 MVT VT = StoredVal.getSimpleValueType();
7636 unsigned EltSizeBits = VT.getScalarSizeInBits();
7637 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
7638 "Unexpected unaligned RVV store type");
7639 MVT NewVT =
7640 MVT::getVectorVT(MVT::i8, VT.getVectorElementCount() * (EltSizeBits / 8));
7641 assert(NewVT.isValid() &&
7642 "Expecting equally-sized RVV vector types to be legal");
7643 StoredVal = DAG.getBitcast(NewVT, StoredVal);
7644 return DAG.getStore(Store->getChain(), DL, StoredVal, Store->getBasePtr(),
7645 Store->getPointerInfo(), Store->getBaseAlign(),
7646 Store->getMemOperand()->getFlags());
7647}
7648
7649// While RVV has alignment restrictions, we should always be able to load as a
7650// legal equivalently-sized byte-typed vector instead. This method is
7651// responsible for re-expressing a ISD::VP_LOAD via a correctly-aligned type. If
7652// the load is already correctly-aligned, it returns SDValue().
7653SDValue RISCVTargetLowering::expandUnalignedVPLoad(SDValue Op,
7654 SelectionDAG &DAG) const {
7655 auto *Load = cast<VPLoadSDNode>(Op);
7656 assert(Load && Load->getMemoryVT().isVector() && "Expected vector load");
7657
7659 Load->getMemoryVT(),
7660 *Load->getMemOperand()))
7661 return SDValue();
7662
7663 SDValue Mask = Load->getMask();
7664
7665 // FIXME: Handled masked loads somehow.
7667 return SDValue();
7668
7669 SDLoc DL(Op);
7670 MVT VT = Op.getSimpleValueType();
7671 unsigned EltSizeBits = VT.getScalarSizeInBits();
7672 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
7673 "Unexpected unaligned RVV load type");
7674 MVT NewVT =
7675 MVT::getVectorVT(MVT::i8, VT.getVectorElementCount() * (EltSizeBits / 8));
7676 assert(NewVT.isValid() &&
7677 "Expecting equally-sized RVV vector types to be legal");
7678
7679 SDValue VL = Load->getVectorLength();
7680 VL = DAG.getNode(ISD::MUL, DL, VL.getValueType(), VL,
7681 DAG.getConstant((EltSizeBits / 8), DL, VL.getValueType()));
7682
7683 MVT MaskVT = MVT::getVectorVT(MVT::i1, NewVT.getVectorElementCount());
7684 SDValue L = DAG.getLoadVP(NewVT, DL, Load->getChain(), Load->getBasePtr(),
7685 DAG.getAllOnesConstant(DL, MaskVT), VL,
7686 Load->getPointerInfo(), Load->getBaseAlign(),
7687 Load->getMemOperand()->getFlags(), AAMDNodes());
7688 return DAG.getMergeValues({DAG.getBitcast(VT, L), L.getValue(1)}, DL);
7689}
7690
7691// While RVV has alignment restrictions, we should always be able to store as a
7692// legal equivalently-sized byte-typed vector instead. This method is
7693// responsible for re-expressing a ISD::VP STORE via a correctly-aligned type.
7694// It returns SDValue() if the store is already correctly aligned.
7695SDValue RISCVTargetLowering::expandUnalignedVPStore(SDValue Op,
7696 SelectionDAG &DAG) const {
7697 auto *Store = cast<VPStoreSDNode>(Op);
7698 assert(Store && Store->getValue().getValueType().isVector() &&
7699 "Expected vector store");
7700
7702 Store->getMemoryVT(),
7703 *Store->getMemOperand()))
7704 return SDValue();
7705
7706 SDValue Mask = Store->getMask();
7707
7708 // FIXME: Handled masked stores somehow.
7710 return SDValue();
7711
7712 SDLoc DL(Op);
7713 SDValue StoredVal = Store->getValue();
7714 MVT VT = StoredVal.getSimpleValueType();
7715 unsigned EltSizeBits = VT.getScalarSizeInBits();
7716 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
7717 "Unexpected unaligned RVV store type");
7718 MVT NewVT =
7719 MVT::getVectorVT(MVT::i8, VT.getVectorElementCount() * (EltSizeBits / 8));
7720 assert(NewVT.isValid() &&
7721 "Expecting equally-sized RVV vector types to be legal");
7722
7723 SDValue VL = Store->getVectorLength();
7724 VL = DAG.getNode(ISD::MUL, DL, VL.getValueType(), VL,
7725 DAG.getConstant((EltSizeBits / 8), DL, VL.getValueType()));
7726
7727 StoredVal = DAG.getBitcast(NewVT, StoredVal);
7728
7729 LocationSize Size = LocationSize::precise(NewVT.getStoreSize());
7731 MachineMemOperand *MMO = MF.getMachineMemOperand(
7732 Store->getPointerInfo(), Store->getMemOperand()->getFlags(), Size,
7733 Store->getBaseAlign());
7734
7735 MVT MaskVT = MVT::getVectorVT(MVT::i1, NewVT.getVectorElementCount());
7736 return DAG.getStoreVP(Store->getChain(), DL, StoredVal, Store->getBasePtr(),
7737 DAG.getPOISON(Store->getBasePtr().getValueType()),
7738 DAG.getAllOnesConstant(DL, MaskVT), VL, NewVT, MMO,
7740}
7741
7743 const RISCVSubtarget &Subtarget) {
7744 assert(Op.getValueType() == MVT::i64 && "Unexpected VT");
7745
7746 int64_t Imm = cast<ConstantSDNode>(Op)->getSExtValue();
7747
7748 // All simm32 constants should be handled by isel.
7749 // NOTE: The getMaxBuildIntsCost call below should return a value >= 2 making
7750 // this check redundant, but small immediates are common so this check
7751 // should have better compile time.
7752 if (isInt<32>(Imm))
7753 return Op;
7754
7755 // We only need to cost the immediate, if constant pool lowering is enabled.
7756 if (!Subtarget.useConstantPoolForLargeInts())
7757 return Op;
7758
7760 if (Seq.size() <= Subtarget.getMaxBuildIntsCost())
7761 return Op;
7762
7763 // Optimizations below are disabled for opt size. If we're optimizing for
7764 // size, use a constant pool.
7765 if (DAG.shouldOptForSize())
7766 return SDValue();
7767
7768 // Special case. See if we can build the constant as (ADD (SLLI X, C), X) do
7769 // that if it will avoid a constant pool.
7770 // It will require an extra temporary register though.
7771 // If we have Zba we can use (ADD_UW X, (SLLI X, 32)) to handle cases where
7772 // low and high 32 bits are the same and bit 31 and 63 are set.
7773 unsigned ShiftAmt, AddOpc;
7774 RISCVMatInt::InstSeq SeqLo =
7775 RISCVMatInt::generateTwoRegInstSeq(Imm, Subtarget, ShiftAmt, AddOpc);
7776 if (!SeqLo.empty() && (SeqLo.size() + 2) <= Subtarget.getMaxBuildIntsCost())
7777 return Op;
7778
7779 return SDValue();
7780}
7781
7782SDValue RISCVTargetLowering::lowerConstantFP(SDValue Op,
7783 SelectionDAG &DAG) const {
7784 MVT VT = Op.getSimpleValueType();
7785 const APFloat &Imm = cast<ConstantFPSDNode>(Op)->getValueAPF();
7786
7787 // Can this constant be selected by a Zfa FLI instruction?
7788 bool Negate = false;
7789 int Index = getLegalZfaFPImm(Imm, VT);
7790
7791 // If the constant is negative, try negating.
7792 if (Index < 0 && Imm.isNegative()) {
7793 Index = getLegalZfaFPImm(-Imm, VT);
7794 Negate = true;
7795 }
7796
7797 // If we couldn't find a FLI lowering, fall back to generic code.
7798 if (Index < 0)
7799 return SDValue();
7800
7801 // Emit an FLI+FNEG. We use a custom node to hide from constant folding.
7802 SDLoc DL(Op);
7803 SDValue Const =
7804 DAG.getNode(RISCVISD::FLI, DL, VT,
7805 DAG.getTargetConstant(Index, DL, Subtarget.getXLenVT()));
7806 if (!Negate)
7807 return Const;
7808
7809 return DAG.getNode(ISD::FNEG, DL, VT, Const);
7810}
7811
7813 SelectionDAG &DAG) {
7814
7815 unsigned IsData = Op.getConstantOperandVal(4);
7816
7817 // mips-p8700 we support data prefetch for now.
7818 if (Subtarget.hasVendorXMIPSCBOP() && !IsData)
7819 return Op.getOperand(0);
7820 return Op;
7821}
7822
7824 const RISCVSubtarget &Subtarget) {
7825 SDLoc dl(Op);
7826 AtomicOrdering FenceOrdering =
7827 static_cast<AtomicOrdering>(Op.getConstantOperandVal(1));
7828 SyncScope::ID FenceSSID =
7829 static_cast<SyncScope::ID>(Op.getConstantOperandVal(2));
7830
7831 if (Subtarget.hasStdExtZtso()) {
7832 // The only fence that needs an instruction is a sequentially-consistent
7833 // cross-thread fence.
7834 if (FenceOrdering == AtomicOrdering::SequentiallyConsistent &&
7835 FenceSSID == SyncScope::System)
7836 return Op;
7837
7838 // MEMBARRIER is a compiler barrier; it codegens to a no-op.
7839 return DAG.getNode(ISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0));
7840 }
7841
7842 // singlethread fences only synchronize with signal handlers on the same
7843 // thread and thus only need to preserve instruction order, not actually
7844 // enforce memory ordering.
7845 if (FenceSSID == SyncScope::SingleThread)
7846 // MEMBARRIER is a compiler barrier; it codegens to a no-op.
7847 return DAG.getNode(ISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0));
7848
7849 return Op;
7850}
7851
7852SDValue RISCVTargetLowering::LowerIS_FPCLASS(SDValue Op,
7853 SelectionDAG &DAG) const {
7854 SDLoc DL(Op);
7855 MVT VT = Op.getSimpleValueType();
7856 MVT XLenVT = Subtarget.getXLenVT();
7857 unsigned Check = Op.getConstantOperandVal(1);
7858 unsigned TDCMask = 0;
7859 if (Check & fcSNan)
7860 TDCMask |= RISCV::FPMASK_Signaling_NaN;
7861 if (Check & fcQNan)
7862 TDCMask |= RISCV::FPMASK_Quiet_NaN;
7863 if (Check & fcPosInf)
7865 if (Check & fcNegInf)
7867 if (Check & fcPosNormal)
7869 if (Check & fcNegNormal)
7871 if (Check & fcPosSubnormal)
7873 if (Check & fcNegSubnormal)
7875 if (Check & fcPosZero)
7876 TDCMask |= RISCV::FPMASK_Positive_Zero;
7877 if (Check & fcNegZero)
7878 TDCMask |= RISCV::FPMASK_Negative_Zero;
7879
7880 bool IsOneBitMask = isPowerOf2_32(TDCMask);
7881
7882 SDValue TDCMaskV = DAG.getConstant(TDCMask, DL, XLenVT);
7883
7884 if (VT.isVector()) {
7885 SDValue Op0 = Op.getOperand(0);
7886 MVT VT0 = Op.getOperand(0).getSimpleValueType();
7887
7888 if (VT.isScalableVector()) {
7889 MVT DstVT = VT0.changeVectorElementTypeToInteger();
7890 auto [Mask, VL] = getDefaultScalableVLOps(VT0, DL, DAG, Subtarget);
7891 SDValue FPCLASS = DAG.getNode(RISCVISD::FCLASS_VL, DL, DstVT, Op0, Mask,
7892 VL, Op->getFlags());
7893 if (IsOneBitMask)
7894 return DAG.getSetCC(DL, VT, FPCLASS,
7895 DAG.getConstant(TDCMask, DL, DstVT),
7897 SDValue AND = DAG.getNode(ISD::AND, DL, DstVT, FPCLASS,
7898 DAG.getConstant(TDCMask, DL, DstVT));
7899 return DAG.getSetCC(DL, VT, AND, DAG.getConstant(0, DL, DstVT),
7900 ISD::SETNE);
7901 }
7902
7903 MVT ContainerVT0 = getContainerForFixedLengthVector(VT0);
7904 MVT ContainerVT = getContainerForFixedLengthVector(VT);
7905 MVT ContainerDstVT = ContainerVT0.changeVectorElementTypeToInteger();
7906 auto [Mask, VL] = getDefaultVLOps(VT0, ContainerVT0, DL, DAG, Subtarget);
7907 Op0 = convertToScalableVector(ContainerVT0, Op0, DAG, Subtarget);
7908
7909 SDValue FPCLASS = DAG.getNode(RISCVISD::FCLASS_VL, DL, ContainerDstVT, Op0,
7910 Mask, VL, Op->getFlags());
7911
7912 TDCMaskV = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerDstVT,
7913 DAG.getUNDEF(ContainerDstVT), TDCMaskV, VL);
7914 if (IsOneBitMask) {
7915 SDValue VMSEQ =
7916 DAG.getNode(RISCVISD::SETCC_VL, DL, ContainerVT,
7917 {FPCLASS, TDCMaskV, DAG.getCondCode(ISD::SETEQ),
7918 DAG.getUNDEF(ContainerVT), Mask, VL});
7919 return convertFromScalableVector(VT, VMSEQ, DAG, Subtarget);
7920 }
7921 SDValue AND = DAG.getNode(RISCVISD::AND_VL, DL, ContainerDstVT, FPCLASS,
7922 TDCMaskV, DAG.getUNDEF(ContainerDstVT), Mask, VL);
7923
7924 SDValue SplatZero = DAG.getConstant(0, DL, XLenVT);
7925 SplatZero = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerDstVT,
7926 DAG.getUNDEF(ContainerDstVT), SplatZero, VL);
7927
7928 SDValue VMSNE = DAG.getNode(RISCVISD::SETCC_VL, DL, ContainerVT,
7929 {AND, SplatZero, DAG.getCondCode(ISD::SETNE),
7930 DAG.getUNDEF(ContainerVT), Mask, VL});
7931 return convertFromScalableVector(VT, VMSNE, DAG, Subtarget);
7932 }
7933
7934 SDValue FCLASS = DAG.getNode(RISCVISD::FCLASS, DL, XLenVT, Op.getOperand(0));
7935 SDValue AND = DAG.getNode(ISD::AND, DL, XLenVT, FCLASS, TDCMaskV);
7936 SDValue Res = DAG.getSetCC(DL, XLenVT, AND, DAG.getConstant(0, DL, XLenVT),
7938 return DAG.getNode(ISD::TRUNCATE, DL, VT, Res);
7939}
7940
7941// Lower fmaximum and fminimum. Unlike our fmax and fmin instructions, these
7942// operations propagate nans.
7944 const RISCVSubtarget &Subtarget) {
7945 SDLoc DL(Op);
7946 MVT VT = Op.getSimpleValueType();
7947
7948 SDValue X = Op.getOperand(0);
7949 SDValue Y = Op.getOperand(1);
7950
7951 if (!VT.isVector()) {
7952 MVT XLenVT = Subtarget.getXLenVT();
7953
7954 // If X is a nan, replace Y with X. If Y is a nan, replace X with Y. This
7955 // ensures that when one input is a nan, the other will also be a nan
7956 // allowing the nan to propagate. If both inputs are nan, this will swap the
7957 // inputs which is harmless.
7958
7959 SDValue NewY = Y;
7960 if (!Op->getFlags().hasNoNaNs() && !DAG.isKnownNeverNaN(X)) {
7961 SDValue XIsNonNan = DAG.getSetCC(DL, XLenVT, X, X, ISD::SETOEQ);
7962 NewY = DAG.getSelect(DL, VT, XIsNonNan, Y, X);
7963 }
7964
7965 SDValue NewX = X;
7966 if (!Op->getFlags().hasNoNaNs() && !DAG.isKnownNeverNaN(Y)) {
7967 SDValue YIsNonNan = DAG.getSetCC(DL, XLenVT, Y, Y, ISD::SETOEQ);
7968 NewX = DAG.getSelect(DL, VT, YIsNonNan, X, Y);
7969 }
7970
7971 unsigned Opc =
7972 Op.getOpcode() == ISD::FMAXIMUM ? RISCVISD::FMAX : RISCVISD::FMIN;
7973 return DAG.getNode(Opc, DL, VT, NewX, NewY);
7974 }
7975
7976 // Check no NaNs before converting to fixed vector scalable.
7977 bool XIsNeverNan = Op->getFlags().hasNoNaNs() || DAG.isKnownNeverNaN(X);
7978 bool YIsNeverNan = Op->getFlags().hasNoNaNs() || DAG.isKnownNeverNaN(Y);
7979
7980 MVT ContainerVT = VT;
7981 if (VT.isFixedLengthVector()) {
7982 ContainerVT = getContainerForFixedLengthVector(VT, Subtarget);
7983 X = convertToScalableVector(ContainerVT, X, DAG, Subtarget);
7984 Y = convertToScalableVector(ContainerVT, Y, DAG, Subtarget);
7985 }
7986
7987 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
7988
7989 SDValue NewY = Y;
7990 if (!XIsNeverNan) {
7991 SDValue XIsNonNan = DAG.getNode(RISCVISD::SETCC_VL, DL, Mask.getValueType(),
7992 {X, X, DAG.getCondCode(ISD::SETOEQ),
7993 DAG.getUNDEF(ContainerVT), Mask, VL});
7994 NewY = DAG.getNode(RISCVISD::VMERGE_VL, DL, ContainerVT, XIsNonNan, Y, X,
7995 DAG.getUNDEF(ContainerVT), VL);
7996 }
7997
7998 SDValue NewX = X;
7999 if (!YIsNeverNan) {
8000 SDValue YIsNonNan = DAG.getNode(RISCVISD::SETCC_VL, DL, Mask.getValueType(),
8001 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
8002 DAG.getUNDEF(ContainerVT), Mask, VL});
8003 NewX = DAG.getNode(RISCVISD::VMERGE_VL, DL, ContainerVT, YIsNonNan, X, Y,
8004 DAG.getUNDEF(ContainerVT), VL);
8005 }
8006
8007 unsigned Opc =
8008 Op.getOpcode() == ISD::FMAXIMUM ? RISCVISD::VFMAX_VL : RISCVISD::VFMIN_VL;
8009 SDValue Res = DAG.getNode(Opc, DL, ContainerVT, NewX, NewY,
8010 DAG.getUNDEF(ContainerVT), Mask, VL);
8011 if (VT.isFixedLengthVector())
8012 Res = convertFromScalableVector(VT, Res, DAG, Subtarget);
8013 return Res;
8014}
8015
8017 const RISCVSubtarget &Subtarget) {
8018 bool IsFABS = Op.getOpcode() == ISD::FABS;
8019 assert((IsFABS || Op.getOpcode() == ISD::FNEG) &&
8020 "Wrong opcode for lowering FABS or FNEG.");
8021
8022 MVT XLenVT = Subtarget.getXLenVT();
8023 MVT VT = Op.getSimpleValueType();
8024 assert((VT == MVT::f16 || VT == MVT::bf16) && "Unexpected type");
8025
8026 SDLoc DL(Op);
8027 SDValue Fmv =
8028 DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, XLenVT, Op.getOperand(0));
8029
8030 APInt Mask = IsFABS ? APInt::getSignedMaxValue(16) : APInt::getSignMask(16);
8031 Mask = Mask.sext(Subtarget.getXLen());
8032
8033 unsigned LogicOpc = IsFABS ? ISD::AND : ISD::XOR;
8034 SDValue Logic =
8035 DAG.getNode(LogicOpc, DL, XLenVT, Fmv, DAG.getConstant(Mask, DL, XLenVT));
8036 return DAG.getNode(RISCVISD::FMV_H_X, DL, VT, Logic);
8037}
8038
8040 const RISCVSubtarget &Subtarget) {
8041 assert(Op.getOpcode() == ISD::FCOPYSIGN && "Unexpected opcode");
8042
8043 MVT XLenVT = Subtarget.getXLenVT();
8044 MVT VT = Op.getSimpleValueType();
8045 assert((VT == MVT::f16 || VT == MVT::bf16) && "Unexpected type");
8046
8047 SDValue Mag = Op.getOperand(0);
8048 SDValue Sign = Op.getOperand(1);
8049
8050 SDLoc DL(Op);
8051
8052 // Get sign bit into an integer value.
8053 unsigned SignSize = Sign.getValueSizeInBits();
8054 SDValue SignAsInt = [&]() {
8055 if (SignSize == Subtarget.getXLen())
8056 return DAG.getNode(ISD::BITCAST, DL, XLenVT, Sign);
8057 switch (SignSize) {
8058 case 16:
8059 return DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, XLenVT, Sign);
8060 case 32:
8061 return DAG.getNode(RISCVISD::FMV_X_ANYEXTW_RV64, DL, XLenVT, Sign);
8062 case 64: {
8063 assert(XLenVT == MVT::i32 && "Unexpected type");
8064 // Copy the upper word to integer.
8065 SignSize = 32;
8066 return DAG.getNode(RISCVISD::SplitF64, DL, {MVT::i32, MVT::i32}, Sign)
8067 .getValue(1);
8068 }
8069 default:
8070 llvm_unreachable("Unexpected sign size");
8071 }
8072 }();
8073
8074 // Get the signbit at the right position for MagAsInt.
8075 if (int ShiftAmount = (int)SignSize - (int)Mag.getValueSizeInBits())
8076 SignAsInt = DAG.getNode(ShiftAmount > 0 ? ISD::SRL : ISD::SHL, DL, XLenVT,
8077 SignAsInt,
8078 DAG.getConstant(std::abs(ShiftAmount), DL, XLenVT));
8079
8080 // Mask the sign bit and any bits above it. The extra bits will be dropped
8081 // when we convert back to FP.
8082 SDValue SignMask = DAG.getConstant(
8083 APInt::getSignMask(16).sext(Subtarget.getXLen()), DL, XLenVT);
8084 SDValue SignBit = DAG.getNode(ISD::AND, DL, XLenVT, SignAsInt, SignMask);
8085
8086 // Transform Mag value to integer, and clear the sign bit.
8087 SDValue MagAsInt = DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, XLenVT, Mag);
8088 SDValue ClearSignMask = DAG.getConstant(
8089 APInt::getSignedMaxValue(16).sext(Subtarget.getXLen()), DL, XLenVT);
8090 SDValue ClearedSign =
8091 DAG.getNode(ISD::AND, DL, XLenVT, MagAsInt, ClearSignMask);
8092
8093 SDValue CopiedSign = DAG.getNode(ISD::OR, DL, XLenVT, ClearedSign, SignBit,
8095
8096 return DAG.getNode(RISCVISD::FMV_H_X, DL, VT, CopiedSign);
8097}
8098
8099/// Get a RISC-V target specified VL op for a given SDNode.
8100static unsigned getRISCVVLOp(SDValue Op) {
8101#define OP_CASE(NODE) \
8102 case ISD::NODE: \
8103 return RISCVISD::NODE##_VL;
8104#define VP_CASE(NODE) \
8105 case ISD::VP_##NODE: \
8106 return RISCVISD::NODE##_VL;
8107 // clang-format off
8108 switch (Op.getOpcode()) {
8109 default:
8110 llvm_unreachable("don't have RISC-V specified VL op for this SDNode");
8111 OP_CASE(ADD)
8112 OP_CASE(SUB)
8113 OP_CASE(MUL)
8114 OP_CASE(MULHS)
8115 OP_CASE(MULHU)
8116 OP_CASE(SDIV)
8117 OP_CASE(SREM)
8118 OP_CASE(UDIV)
8119 OP_CASE(UREM)
8120 OP_CASE(SHL)
8121 OP_CASE(SRA)
8122 OP_CASE(SRL)
8123 OP_CASE(ROTL)
8124 OP_CASE(ROTR)
8125 OP_CASE(BSWAP)
8126 OP_CASE(CTTZ)
8127 OP_CASE(CTLZ)
8128 OP_CASE(CTPOP)
8129 OP_CASE(BITREVERSE)
8130 OP_CASE(CLMUL)
8131 OP_CASE(CLMULH)
8132 OP_CASE(SADDSAT)
8133 OP_CASE(UADDSAT)
8134 OP_CASE(SSUBSAT)
8135 OP_CASE(USUBSAT)
8136 OP_CASE(AVGFLOORS)
8137 OP_CASE(AVGFLOORU)
8138 OP_CASE(AVGCEILS)
8139 OP_CASE(AVGCEILU)
8140 OP_CASE(FADD)
8141 OP_CASE(FSUB)
8142 OP_CASE(FMUL)
8143 OP_CASE(FDIV)
8144 OP_CASE(FNEG)
8145 OP_CASE(FABS)
8146 OP_CASE(FCOPYSIGN)
8147 OP_CASE(FSQRT)
8148 OP_CASE(SMIN)
8149 OP_CASE(SMAX)
8150 OP_CASE(UMIN)
8151 OP_CASE(UMAX)
8152 OP_CASE(ABDS)
8153 OP_CASE(ABDU)
8154 OP_CASE(STRICT_FADD)
8155 OP_CASE(STRICT_FSUB)
8156 OP_CASE(STRICT_FMUL)
8157 OP_CASE(STRICT_FDIV)
8158 OP_CASE(STRICT_FSQRT)
8159 VP_CASE(SDIV) // VP_SDIV
8160 VP_CASE(SREM) // VP_SREM
8161 VP_CASE(UDIV) // VP_UDIV
8162 VP_CASE(UREM) // VP_UREM
8164 return RISCVISD::CTLZ_VL;
8166 return RISCVISD::CTTZ_VL;
8167 case ISD::FMA:
8168 return RISCVISD::VFMADD_VL;
8169 case ISD::STRICT_FMA:
8170 return RISCVISD::STRICT_VFMADD_VL;
8171 case ISD::AND:
8172 if (Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8173 return RISCVISD::VMAND_VL;
8174 return RISCVISD::AND_VL;
8175 case ISD::OR:
8176 if (Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8177 return RISCVISD::VMOR_VL;
8178 return RISCVISD::OR_VL;
8179 case ISD::XOR:
8180 if (Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8181 return RISCVISD::VMXOR_VL;
8182 return RISCVISD::XOR_VL;
8183 case ISD::ANY_EXTEND:
8184 case ISD::ZERO_EXTEND:
8185 return RISCVISD::VZEXT_VL;
8186 case ISD::SIGN_EXTEND:
8187 return RISCVISD::VSEXT_VL;
8188 case ISD::SETCC:
8189 return RISCVISD::SETCC_VL;
8190 case ISD::VSELECT:
8191 return RISCVISD::VMERGE_VL;
8192 case ISD::VP_MERGE:
8193 return RISCVISD::VMERGE_VL;
8194 case ISD::FMINNUM:
8195 case ISD::FMINIMUMNUM:
8196 return RISCVISD::VFMIN_VL;
8197 case ISD::FMAXNUM:
8198 case ISD::FMAXIMUMNUM:
8199 return RISCVISD::VFMAX_VL;
8200 case ISD::LRINT:
8201 case ISD::LLRINT:
8202 return RISCVISD::VFCVT_RM_X_F_VL;
8203 case ISD::MASKED_UDIV:
8204 return RISCVISD::UDIV_VL;
8205 case ISD::MASKED_UREM:
8206 return RISCVISD::UREM_VL;
8207 case ISD::MASKED_SDIV:
8208 return RISCVISD::SDIV_VL;
8209 case ISD::MASKED_SREM:
8210 return RISCVISD::SREM_VL;
8211 }
8212 // clang-format on
8213#undef OP_CASE
8214#undef VP_CASE
8215}
8216
8218 const RISCVSubtarget &Subtarget,
8219 const TargetLowering &TLI) {
8220 MVT OpVT = Op.getSimpleValueType();
8221 if (!OpVT.isVector())
8222 return false;
8223 MVT EltVT = OpVT.getVectorElementType();
8224 if (!(EltVT == MVT::f16 && Subtarget.hasVInstructionsF16Minimal() &&
8225 !Subtarget.hasVInstructionsF16()) &&
8226 !(EltVT == MVT::bf16 && Subtarget.hasVInstructionsBF16Minimal() &&
8227 (!Subtarget.hasVInstructionsBF16() ||
8228 !llvm::is_contained(ZvfbfaOps, Op.getOpcode()))))
8229 return false;
8230 // Need to split when the same width f32 vector type isn't legal.
8231 return !TLI.isTypeLegal(
8232 MVT::getVectorVT(MVT::f32, OpVT.getVectorElementCount()));
8233}
8234
8236 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(Op.getValueType());
8237 SDLoc DL(Op);
8238
8239 SmallVector<SDValue, 4> LoOperands(Op.getNumOperands());
8240 SmallVector<SDValue, 4> HiOperands(Op.getNumOperands());
8241
8242 for (unsigned j = 0; j != Op.getNumOperands(); ++j) {
8243 if (!Op.getOperand(j).getValueType().isVector()) {
8244 LoOperands[j] = Op.getOperand(j);
8245 HiOperands[j] = Op.getOperand(j);
8246 continue;
8247 }
8248 std::tie(LoOperands[j], HiOperands[j]) =
8249 DAG.SplitVector(Op.getOperand(j), DL);
8250 }
8251
8252 SDValue LoRes =
8253 DAG.getNode(Op.getOpcode(), DL, LoVT, LoOperands, Op->getFlags());
8254 SDValue HiRes =
8255 DAG.getNode(Op.getOpcode(), DL, HiVT, HiOperands, Op->getFlags());
8256
8257 return DAG.getNode(ISD::CONCAT_VECTORS, DL, Op.getValueType(), LoRes, HiRes);
8258}
8259
8261 bool IsVP) {
8262 SDLoc DL(Op);
8263
8264 if (IsVP) {
8265 auto [Lo, Hi] = DAG.SplitVector(Op.getOperand(1), DL);
8266 auto [MaskLo, MaskHi] = DAG.SplitVector(Op.getOperand(2), DL);
8267 auto [EVLLo, EVLHi] =
8268 DAG.SplitEVL(Op.getOperand(3), Op.getOperand(1).getValueType(), DL);
8269
8270 SDValue ResLo =
8271 DAG.getNode(Op.getOpcode(), DL, Op.getValueType(),
8272 {Op.getOperand(0), Lo, MaskLo, EVLLo}, Op->getFlags());
8273 return DAG.getNode(Op.getOpcode(), DL, Op.getValueType(),
8274 {ResLo, Hi, MaskHi, EVLHi}, Op->getFlags());
8275 }
8276
8277 unsigned Opcode = Op.getOpcode();
8278 unsigned OpNo = Opcode == ISD::VECREDUCE_SEQ_FADD ? 1 : 0;
8279
8280 auto [Lo, Hi] = DAG.SplitVector(Op.getOperand(OpNo), DL);
8281 if (Opcode == ISD::VECREDUCE_SEQ_FADD) {
8282 SDValue ResLo = DAG.getNode(Op.getOpcode(), DL, Op.getValueType(),
8283 Op.getOperand(0), Lo, Op->getFlags());
8284 return DAG.getNode(Op.getOpcode(), DL, Op.getValueType(), ResLo, Hi,
8285 Op->getFlags());
8286 }
8287
8288 SDValue ResLo =
8289 DAG.getNode(Op.getOpcode(), DL, Op.getValueType(), Lo, Op->getFlags());
8290 SDValue ResHi =
8291 DAG.getNode(Op.getOpcode(), DL, Op.getValueType(), Hi, Op->getFlags());
8292 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Op.getOpcode());
8293 return DAG.getNode(BaseOpc, DL, Op.getValueType(), ResLo, ResHi,
8294 Op->getFlags());
8295}
8296
8298
8299 assert(Op->isStrictFPOpcode());
8300
8301 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(Op->getValueType(0));
8302
8303 SDVTList LoVTs = DAG.getVTList(LoVT, Op->getValueType(1));
8304 SDVTList HiVTs = DAG.getVTList(HiVT, Op->getValueType(1));
8305
8306 SDLoc DL(Op);
8307
8308 SmallVector<SDValue, 4> LoOperands(Op.getNumOperands());
8309 SmallVector<SDValue, 4> HiOperands(Op.getNumOperands());
8310
8311 for (unsigned j = 0; j != Op.getNumOperands(); ++j) {
8312 if (!Op.getOperand(j).getValueType().isVector()) {
8313 LoOperands[j] = Op.getOperand(j);
8314 HiOperands[j] = Op.getOperand(j);
8315 continue;
8316 }
8317 std::tie(LoOperands[j], HiOperands[j]) =
8318 DAG.SplitVector(Op.getOperand(j), DL);
8319 }
8320
8321 SDValue LoRes =
8322 DAG.getNode(Op.getOpcode(), DL, LoVTs, LoOperands, Op->getFlags());
8323 HiOperands[0] = LoRes.getValue(1);
8324 SDValue HiRes =
8325 DAG.getNode(Op.getOpcode(), DL, HiVTs, HiOperands, Op->getFlags());
8326
8327 SDValue V = DAG.getNode(ISD::CONCAT_VECTORS, DL, Op->getValueType(0),
8328 LoRes.getValue(0), HiRes.getValue(0));
8329 return DAG.getMergeValues({V, HiRes.getValue(1)}, DL);
8330}
8331
8332SDValue
8333RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Load(SDValue Op,
8334 SelectionDAG &DAG) const {
8335 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
8336 "Unexpected bfloat16 load lowering");
8337
8338 SDLoc DL(Op);
8339 LoadSDNode *LD = cast<LoadSDNode>(Op.getNode());
8340 EVT MemVT = LD->getMemoryVT();
8341 SDValue Load = DAG.getExtLoad(
8342 ISD::ZEXTLOAD, DL, Subtarget.getXLenVT(), LD->getChain(),
8343 LD->getBasePtr(),
8345 LD->getMemOperand());
8346 // Using mask to make bf16 nan-boxing valid when we don't have flh
8347 // instruction. -65536 would be treat as a small number and thus it can be
8348 // directly used lui to get the constant.
8349 SDValue mask = DAG.getSignedConstant(-65536, DL, Subtarget.getXLenVT());
8350 SDValue OrSixteenOne =
8351 DAG.getNode(ISD::OR, DL, Load.getValueType(), {Load, mask});
8352 SDValue ConvertedResult =
8353 DAG.getNode(RISCVISD::NDS_FMV_BF16_X, DL, MVT::bf16, OrSixteenOne);
8354 return DAG.getMergeValues({ConvertedResult, Load.getValue(1)}, DL);
8355}
8356
8357SDValue
8358RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Store(SDValue Op,
8359 SelectionDAG &DAG) const {
8360 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
8361 "Unexpected bfloat16 store lowering");
8362
8363 StoreSDNode *ST = cast<StoreSDNode>(Op.getNode());
8364 SDLoc DL(Op);
8365 SDValue FMV = DAG.getNode(RISCVISD::NDS_FMV_X_ANYEXTBF16, DL,
8366 Subtarget.getXLenVT(), ST->getValue());
8367 return DAG.getTruncStore(
8368 ST->getChain(), DL, FMV, ST->getBasePtr(),
8369 EVT::getIntegerVT(*DAG.getContext(), ST->getMemoryVT().getSizeInBits()),
8370 ST->getMemOperand());
8371}
8372
8374 const RISCVSubtarget &Subtarget);
8375
8377 const RISCVSubtarget &Subtarget);
8378
8380 SelectionDAG &DAG) const {
8381 switch (Op.getOpcode()) {
8382 default:
8384 "Unimplemented RISCVTargetLowering::LowerOperation Case");
8385 case ISD::PREFETCH:
8386 return LowerPREFETCH(Op, Subtarget, DAG);
8387 case ISD::ATOMIC_FENCE:
8388 return LowerATOMIC_FENCE(Op, DAG, Subtarget);
8389 case ISD::GlobalAddress:
8390 return lowerGlobalAddress(Op, DAG);
8391 case ISD::BlockAddress:
8392 return lowerBlockAddress(Op, DAG);
8393 case ISD::ConstantPool:
8394 return lowerConstantPool(Op, DAG);
8395 case ISD::JumpTable:
8396 return lowerJumpTable(Op, DAG);
8398 return lowerGlobalTLSAddress(Op, DAG);
8399 case ISD::Constant:
8400 return lowerConstant(Op, DAG, Subtarget);
8401 case ISD::ConstantFP:
8402 return lowerConstantFP(Op, DAG);
8403 case ISD::SELECT:
8404 return lowerSELECT(Op, DAG);
8405 case ISD::BRCOND:
8406 return lowerBRCOND(Op, DAG);
8407 case ISD::VASTART:
8408 return lowerVASTART(Op, DAG);
8409 case ISD::FRAMEADDR:
8410 return lowerFRAMEADDR(Op, DAG);
8411 case ISD::RETURNADDR:
8412 return lowerRETURNADDR(Op, DAG);
8413 case ISD::SHL_PARTS:
8414 return lowerShiftLeftParts(Op, DAG);
8415 case ISD::SRA_PARTS:
8416 return lowerShiftRightParts(Op, DAG, true);
8417 case ISD::SRL_PARTS:
8418 return lowerShiftRightParts(Op, DAG, false);
8419 case ISD::ROTL:
8420 case ISD::ROTR:
8421 if (Op.getValueType().isFixedLengthVector()) {
8422 assert(Subtarget.hasStdExtZvkb());
8423 return lowerToScalableOp(Op, DAG);
8424 }
8425 assert(Subtarget.hasVendorXTHeadBb() &&
8426 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
8427 "Unexpected custom legalization");
8428 // XTHeadBb only supports rotate by constant.
8429 if (!isa<ConstantSDNode>(Op.getOperand(1)))
8430 return SDValue();
8431 return Op;
8432 case ISD::BITCAST: {
8433 SDLoc DL(Op);
8434 EVT VT = Op.getValueType();
8435 SDValue Op0 = Op.getOperand(0);
8436 EVT Op0VT = Op0.getValueType();
8437 MVT XLenVT = Subtarget.getXLenVT();
8438 if (Op0VT == MVT::i16 &&
8439 ((VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
8440 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
8441 SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, Op0);
8442 return DAG.getNode(RISCVISD::FMV_H_X, DL, VT, NewOp0);
8443 }
8444 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.is64Bit() &&
8445 Subtarget.hasStdExtFOrZfinx()) {
8446 SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op0);
8447 return DAG.getNode(RISCVISD::FMV_W_X_RV64, DL, MVT::f32, NewOp0);
8448 }
8449 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit() &&
8450 Subtarget.hasStdExtDOrZdinx()) {
8451 SDValue Lo, Hi;
8452 std::tie(Lo, Hi) = DAG.SplitScalar(Op0, DL, MVT::i32, MVT::i32);
8453 return DAG.getNode(RISCVISD::BuildPairF64, DL, MVT::f64, Lo, Hi);
8454 }
8455
8456 if (Subtarget.hasStdExtP() && VT.isSimple() && Op0VT.isSimple()) {
8457 if (VT.getSimpleVT() == Subtarget.getXLenVT() &&
8458 Subtarget.isPExtPackedType(Op0VT.getSimpleVT()))
8459 return Op;
8460 if (Op0VT.getSimpleVT() == Subtarget.getXLenVT() &&
8461 Subtarget.isPExtPackedType(VT.getSimpleVT()))
8462 return Op;
8463 }
8464
8465 // Consider other scalar<->scalar casts as legal if the types are legal.
8466 // Otherwise expand them.
8467 if (!VT.isVector() && !Op0VT.isVector()) {
8468 if (isTypeLegal(VT) && isTypeLegal(Op0VT))
8469 return Op;
8470 return SDValue();
8471 }
8472
8473 assert(!VT.isScalableVector() && !Op0VT.isScalableVector() &&
8474 "Unexpected types");
8475
8476 if (VT.isFixedLengthVector()) {
8477 // We can handle fixed length vector bitcasts with a simple replacement
8478 // in isel.
8479 if (Op0VT.isFixedLengthVector())
8480 return Op;
8481 // When bitcasting from scalar to fixed-length vector, insert the scalar
8482 // into a one-element vector of the result type, and perform a vector
8483 // bitcast.
8484 if (!Op0VT.isVector()) {
8485 EVT BVT = EVT::getVectorVT(*DAG.getContext(), Op0VT, 1);
8486 if (!isTypeLegal(BVT))
8487 return SDValue();
8488 return DAG.getBitcast(
8489 VT, DAG.getInsertVectorElt(DL, DAG.getUNDEF(BVT), Op0, 0));
8490 }
8491 return SDValue();
8492 }
8493 // Custom-legalize bitcasts from fixed-length vector types to scalar types
8494 // thus: bitcast the vector to a one-element vector type whose element type
8495 // is the same as the result type, and extract the first element.
8496 if (!VT.isVector() && Op0VT.isFixedLengthVector()) {
8497 EVT BVT = EVT::getVectorVT(*DAG.getContext(), VT, 1);
8498 if (!isTypeLegal(BVT))
8499 return SDValue();
8500 SDValue BVec = DAG.getBitcast(BVT, Op0);
8501 return DAG.getExtractVectorElt(DL, VT, BVec, 0);
8502 }
8503 return SDValue();
8504 }
8506 return LowerINTRINSIC_WO_CHAIN(Op, DAG);
8508 return LowerINTRINSIC_W_CHAIN(Op, DAG);
8510 return LowerINTRINSIC_VOID(Op, DAG);
8511 case ISD::IS_FPCLASS:
8512 return LowerIS_FPCLASS(Op, DAG);
8513 case ISD::BITREVERSE: {
8514 MVT VT = Op.getSimpleValueType();
8515 if (VT.isFixedLengthVector()) {
8516 assert(Subtarget.hasStdExtZvbb());
8517 return lowerToScalableOp(Op, DAG);
8518 }
8519 SDLoc DL(Op);
8520 assert(Subtarget.hasStdExtZbkb() && "Unexpected custom legalization");
8521 assert(Op.getOpcode() == ISD::BITREVERSE && "Unexpected opcode");
8522 // Expand bitreverse to a bswap(rev8) followed by brev8.
8523 SDValue BSwap = DAG.getNode(ISD::BSWAP, DL, VT, Op.getOperand(0));
8524 return DAG.getNode(RISCVISD::BREV8, DL, VT, BSwap);
8525 }
8526 case ISD::TRUNCATE:
8529 // Only custom-lower vector truncates
8530 if (!Op.getSimpleValueType().isVector())
8531 return Op;
8532 return lowerVectorTrunc(Op, DAG);
8533 case ISD::ANY_EXTEND:
8534 case ISD::ZERO_EXTEND:
8535 if (Op.getOperand(0).getValueType().isVector() &&
8536 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
8537 return lowerVectorMaskExt(Op, DAG, /*ExtVal*/ 1);
8538 if (Op.getValueType().isScalableVector())
8539 return Op;
8540 return lowerToScalableOp(Op, DAG);
8541 case ISD::SIGN_EXTEND:
8542 if (Op.getOperand(0).getValueType().isVector() &&
8543 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
8544 return lowerVectorMaskExt(Op, DAG, /*ExtVal*/ -1);
8545 if (Op.getValueType().isScalableVector())
8546 return Op;
8547 return lowerToScalableOp(Op, DAG);
8549 return lowerSPLAT_VECTOR_PARTS(Op, DAG);
8551 return lowerINSERT_VECTOR_ELT(Op, DAG);
8553 return lowerEXTRACT_VECTOR_ELT(Op, DAG);
8554 case ISD::SCALAR_TO_VECTOR: {
8555 MVT VT = Op.getSimpleValueType();
8556 SDLoc DL(Op);
8557 SDValue Scalar = Op.getOperand(0);
8558 if (VT.getVectorElementType() == MVT::i1) {
8559 MVT WideVT = VT.changeVectorElementType(MVT::i8);
8560 SDValue V = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, WideVT, Scalar);
8561 return DAG.getNode(ISD::TRUNCATE, DL, VT, V);
8562 }
8563 MVT ContainerVT = VT;
8564 if (VT.isFixedLengthVector())
8565 ContainerVT = getContainerForFixedLengthVector(VT);
8566 SDValue VL = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).second;
8567
8568 SDValue V;
8569 if (VT.isFloatingPoint()) {
8570 V = DAG.getNode(RISCVISD::VFMV_S_F_VL, DL, ContainerVT,
8571 DAG.getUNDEF(ContainerVT), Scalar, VL);
8572 } else {
8573 Scalar = DAG.getNode(ISD::ANY_EXTEND, DL, Subtarget.getXLenVT(), Scalar);
8574 V = DAG.getNode(RISCVISD::VMV_S_X_VL, DL, ContainerVT,
8575 DAG.getUNDEF(ContainerVT), Scalar, VL);
8576 }
8577 if (VT.isFixedLengthVector())
8578 V = convertFromScalableVector(VT, V, DAG, Subtarget);
8579 return V;
8580 }
8581 case ISD::VSCALE: {
8582 MVT XLenVT = Subtarget.getXLenVT();
8583 MVT VT = Op.getSimpleValueType();
8584 SDLoc DL(Op);
8585 SDValue Res = DAG.getNode(RISCVISD::READ_VLENB, DL, XLenVT);
8586 // We define our scalable vector types for lmul=1 to use a 64 bit known
8587 // minimum size. e.g. <vscale x 2 x i32>. VLENB is in bytes so we calculate
8588 // vscale as VLENB / 8.
8589 static_assert(RISCV::RVVBitsPerBlock == 64, "Unexpected bits per block!");
8590 if (Subtarget.getRealMinVLen() < RISCV::RVVBitsPerBlock)
8591 reportFatalInternalError("Support for VLEN==32 is incomplete.");
8592 // We assume VLENB is a multiple of 8. We manually choose the best shift
8593 // here because SimplifyDemandedBits isn't always able to simplify it.
8594 uint64_t Val = Op.getConstantOperandVal(0);
8595 if (isPowerOf2_64(Val)) {
8596 uint64_t Log2 = Log2_64(Val);
8597 if (Log2 < 3) {
8598 SDNodeFlags Flags;
8599 Flags.setExact(true);
8600 Res = DAG.getNode(ISD::SRL, DL, XLenVT, Res,
8601 DAG.getConstant(3 - Log2, DL, XLenVT), Flags);
8602 } else if (Log2 > 3) {
8603 Res = DAG.getNode(ISD::SHL, DL, XLenVT, Res,
8604 DAG.getConstant(Log2 - 3, DL, XLenVT));
8605 }
8606 } else if ((Val % 8) == 0) {
8607 // If the multiplier is a multiple of 8, scale it down to avoid needing
8608 // to shift the VLENB value.
8609 Res = DAG.getNode(ISD::MUL, DL, XLenVT, Res,
8610 DAG.getConstant(Val / 8, DL, XLenVT));
8611 } else {
8612 SDNodeFlags Flags;
8613 Flags.setExact(true);
8614 SDValue VScale = DAG.getNode(ISD::SRL, DL, XLenVT, Res,
8615 DAG.getConstant(3, DL, XLenVT), Flags);
8616 Res = DAG.getNode(ISD::MUL, DL, XLenVT, VScale,
8617 DAG.getConstant(Val, DL, XLenVT));
8618 }
8619 return DAG.getNode(ISD::TRUNCATE, DL, VT, Res);
8620 }
8621 case ISD::FPOWI: {
8622 // Custom promote f16 powi with illegal i32 integer type on RV64. Once
8623 // promoted this will be legalized into a libcall by LegalizeIntegerTypes.
8624 if (Op.getValueType() == MVT::f16 && Subtarget.is64Bit() &&
8625 Op.getOperand(1).getValueType() == MVT::i32) {
8626 SDLoc DL(Op);
8627 SDValue Op0 = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Op.getOperand(0));
8628 SDValue Powi =
8629 DAG.getNode(ISD::FPOWI, DL, MVT::f32, Op0, Op.getOperand(1));
8630 return DAG.getNode(ISD::FP_ROUND, DL, MVT::f16, Powi,
8631 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
8632 }
8633 return SDValue();
8634 }
8635 case ISD::FMAXIMUM:
8636 case ISD::FMINIMUM:
8637 if (isPromotedOpNeedingSplit(Op, Subtarget, *this))
8638 return SplitVectorOp(Op, DAG);
8639 return lowerFMAXIMUM_FMINIMUM(Op, DAG, Subtarget);
8640 case ISD::FP_EXTEND:
8641 case ISD::FP_ROUND:
8642 return lowerVectorFPExtendOrRound(Op, DAG);
8645 return lowerStrictFPExtendOrRoundLike(Op, DAG);
8646 case ISD::SINT_TO_FP:
8647 case ISD::UINT_TO_FP:
8648 // An i1-to-fp conversion is equivalent to selecting between 1.0/-1.0 and
8649 // 0.0 for unsigned/signed conversion, respectively. This avoids extending
8650 // the mask before converting it.
8651 if (Op.getValueType().isVector() &&
8652 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1) {
8653 SDLoc DL(Op);
8654 EVT VT = Op.getValueType();
8655 SDValue Zero = DAG.getConstantFP(0.0, DL, VT);
8656 double TrueVal = Op.getOpcode() == ISD::UINT_TO_FP ? 1.0 : -1.0;
8657 SDValue True = DAG.getConstantFP(TrueVal, DL, VT);
8658 return DAG.getNode(ISD::VSELECT, DL, VT, Op.getOperand(0), True, Zero);
8659 }
8660 // Fall back to zvfbfmin for bf16 case if source type is wider than 8 bits.
8661 if (SDValue Op1 = Op.getOperand(0);
8662 Op.getValueType().isVector() &&
8663 ((Op.getValueType().getScalarType() == MVT::f16 &&
8664 (Subtarget.hasVInstructionsF16Minimal() &&
8665 !Subtarget.hasVInstructionsF16())) ||
8666 (Op.getValueType().getScalarType() == MVT::bf16 &&
8667 (Subtarget.hasVInstructionsBF16Minimal() &&
8668 (!Subtarget.hasVInstructionsBF16() ||
8669 Op1.getValueType().getScalarSizeInBits() > 8))))) {
8670 MVT NVT =
8671 MVT::getVectorVT(MVT::f32, Op.getValueType().getVectorElementCount());
8672 if (!isTypeLegal(NVT))
8673 return SplitVectorOp(Op, DAG);
8674 // int -> f32
8675 SDLoc DL(Op);
8676 SDValue NC = DAG.getNode(Op.getOpcode(), DL, NVT, Op->ops());
8677 // f32 -> [b]f16
8678 return DAG.getNode(ISD::FP_ROUND, DL, Op.getValueType(), NC,
8679 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
8680 }
8681 [[fallthrough]];
8682 case ISD::FP_TO_SINT:
8683 case ISD::FP_TO_UINT:
8684 // Fall back to zvfbfmin for bf16 case if destination type is wider than 8
8685 // bits.
8686 if (SDValue Op1 = Op.getOperand(0);
8687 Op1.getValueType().isVector() &&
8688 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8689 (Subtarget.hasVInstructionsF16Minimal() &&
8690 !Subtarget.hasVInstructionsF16())) ||
8691 (Op1.getValueType().getScalarType() == MVT::bf16 &&
8692 (Subtarget.hasVInstructionsBF16Minimal() &&
8693 (!Subtarget.hasVInstructionsBF16() ||
8694 Op.getValueType().getScalarSizeInBits() > 8))))) {
8695 MVT NVT = MVT::getVectorVT(MVT::f32,
8696 Op1.getValueType().getVectorElementCount());
8697 if (!isTypeLegal(NVT))
8698 return SplitVectorOp(Op, DAG);
8699 // [b]f16 -> f32
8700 SDLoc DL(Op);
8701 SDValue WidenVec = DAG.getNode(ISD::FP_EXTEND, DL, NVT, Op1);
8702 // f32 -> int
8703 return DAG.getNode(Op.getOpcode(), DL, Op.getValueType(), WidenVec);
8704 }
8705 [[fallthrough]];
8710 // RVV can only do fp<->int conversions to types half/double the size as
8711 // the source. We custom-lower any conversions that do two hops into
8712 // sequences.
8713 MVT VT = Op.getSimpleValueType();
8714 if (VT.isScalarInteger())
8715 return lowerFP_TO_INT(Op, DAG, Subtarget);
8716 bool IsStrict = Op->isStrictFPOpcode();
8717 SDValue Src = Op.getOperand(0 + IsStrict);
8718 MVT SrcVT = Src.getSimpleValueType();
8719 if (SrcVT.isScalarInteger())
8720 return lowerINT_TO_FP(Op, DAG, Subtarget);
8721 if (!VT.isVector())
8722 return Op;
8723 SDLoc DL(Op);
8724 MVT EltVT = VT.getVectorElementType();
8725 MVT SrcEltVT = SrcVT.getVectorElementType();
8726 unsigned EltSize = EltVT.getSizeInBits();
8727 unsigned SrcEltSize = SrcEltVT.getSizeInBits();
8728 assert(isPowerOf2_32(EltSize) && isPowerOf2_32(SrcEltSize) &&
8729 "Unexpected vector element types");
8730
8731 bool IsInt2FP = SrcEltVT.isInteger();
8732 // Widening conversions
8733 if (EltSize > (2 * SrcEltSize)) {
8734 if (IsInt2FP) {
8735 // Do a regular integer sign/zero extension then convert to float.
8736 MVT IVecVT = MVT::getVectorVT(MVT::getIntegerVT(EltSize / 2),
8738 unsigned ExtOpcode = (Op.getOpcode() == ISD::UINT_TO_FP ||
8739 Op.getOpcode() == ISD::STRICT_UINT_TO_FP)
8742 SDValue Ext = DAG.getNode(ExtOpcode, DL, IVecVT, Src);
8743 if (IsStrict)
8744 return DAG.getNode(Op.getOpcode(), DL, Op->getVTList(),
8745 Op.getOperand(0), Ext);
8746 return DAG.getNode(Op.getOpcode(), DL, VT, Ext);
8747 }
8748 // FP2Int
8749 assert((SrcEltVT == MVT::f16 || SrcEltVT == MVT::bf16) &&
8750 "Unexpected FP_TO_[US]INT lowering");
8751 // Do one doubling fp_extend then complete the operation by converting
8752 // to int.
8753 MVT InterimFVT = MVT::getVectorVT(MVT::f32, VT.getVectorElementCount());
8754 if (IsStrict) {
8755 auto [FExt, Chain] =
8756 DAG.getStrictFPExtendOrRound(Src, Op.getOperand(0), DL, InterimFVT);
8757 return DAG.getNode(Op.getOpcode(), DL, Op->getVTList(), Chain, FExt);
8758 }
8759 SDValue FExt = DAG.getFPExtendOrRound(Src, DL, InterimFVT);
8760 return DAG.getNode(Op.getOpcode(), DL, VT, FExt);
8761 }
8762
8763 // Narrowing conversions
8764 if (SrcEltSize > (2 * EltSize)) {
8765 if (IsInt2FP) {
8766 // One narrowing int_to_fp, then an fp_round.
8767 assert((EltVT == MVT::f16 || EltVT == MVT::bf16) &&
8768 "Unexpected [US]_TO_FP lowering");
8769 MVT InterimFVT = MVT::getVectorVT(MVT::f32, VT.getVectorElementCount());
8770 if (IsStrict) {
8771 SDValue Int2FP = DAG.getNode(Op.getOpcode(), DL,
8772 DAG.getVTList(InterimFVT, MVT::Other),
8773 Op.getOperand(0), Src);
8774 SDValue Chain = Int2FP.getValue(1);
8775 return DAG.getStrictFPExtendOrRound(Int2FP, Chain, DL, VT).first;
8776 }
8777 SDValue Int2FP = DAG.getNode(Op.getOpcode(), DL, InterimFVT, Src);
8778 return DAG.getFPExtendOrRound(Int2FP, DL, VT);
8779 }
8780 // FP2Int
8781 // One narrowing fp_to_int, then truncate the integer. If the float isn't
8782 // representable by the integer, the result is poison.
8783 MVT IVecVT = MVT::getVectorVT(MVT::getIntegerVT(SrcEltSize / 2),
8785 if (IsStrict) {
8786 SDValue FP2Int =
8787 DAG.getNode(Op.getOpcode(), DL, DAG.getVTList(IVecVT, MVT::Other),
8788 Op.getOperand(0), Src);
8789 SDValue Res = DAG.getNode(ISD::TRUNCATE, DL, VT, FP2Int);
8790 return DAG.getMergeValues({Res, FP2Int.getValue(1)}, DL);
8791 }
8792 SDValue FP2Int = DAG.getNode(Op.getOpcode(), DL, IVecVT, Src);
8793 if (EltSize == 1)
8794 // The integer should be 0 or 1/-1, so compare the integer result to 0.
8795 return DAG.getSetCC(DL, VT, DAG.getConstant(0, DL, IVecVT), FP2Int,
8796 ISD::SETNE);
8797 return DAG.getNode(ISD::TRUNCATE, DL, VT, FP2Int);
8798 }
8799
8800 // Scalable vectors can exit here. Patterns will handle equally-sized
8801 // conversions halving/doubling ones.
8802 if (!VT.isFixedLengthVector())
8803 return Op;
8804
8805 // For fixed-length vectors we lower to a custom "VL" node.
8806 unsigned RVVOpc = 0;
8807 switch (Op.getOpcode()) {
8808 default:
8809 llvm_unreachable("Impossible opcode");
8810 case ISD::FP_TO_SINT:
8811 RVVOpc = RISCVISD::VFCVT_RTZ_X_F_VL;
8812 break;
8813 case ISD::FP_TO_UINT:
8814 RVVOpc = RISCVISD::VFCVT_RTZ_XU_F_VL;
8815 break;
8816 case ISD::SINT_TO_FP:
8817 RVVOpc = RISCVISD::SINT_TO_FP_VL;
8818 break;
8819 case ISD::UINT_TO_FP:
8820 RVVOpc = RISCVISD::UINT_TO_FP_VL;
8821 break;
8823 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_X_F_VL;
8824 break;
8826 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_XU_F_VL;
8827 break;
8829 RVVOpc = RISCVISD::STRICT_SINT_TO_FP_VL;
8830 break;
8832 RVVOpc = RISCVISD::STRICT_UINT_TO_FP_VL;
8833 break;
8834 }
8835
8836 MVT ContainerVT = getContainerForFixedLengthVector(VT);
8837 MVT SrcContainerVT = getContainerForFixedLengthVector(SrcVT);
8838 assert(ContainerVT.getVectorElementCount() == SrcContainerVT.getVectorElementCount() &&
8839 "Expected same element count");
8840
8841 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
8842
8843 Src = convertToScalableVector(SrcContainerVT, Src, DAG, Subtarget);
8844 if (IsStrict) {
8845 Src = DAG.getNode(RVVOpc, DL, DAG.getVTList(ContainerVT, MVT::Other),
8846 Op.getOperand(0), Src, Mask, VL);
8847 SDValue SubVec = convertFromScalableVector(VT, Src, DAG, Subtarget);
8848 return DAG.getMergeValues({SubVec, Src.getValue(1)}, DL);
8849 }
8850 Src = DAG.getNode(RVVOpc, DL, ContainerVT, Src, Mask, VL);
8851 return convertFromScalableVector(VT, Src, DAG, Subtarget);
8852 }
8855 return lowerFP_TO_INT_SAT(Op, DAG, Subtarget);
8856 case ISD::FP_TO_BF16: {
8857 // Custom lower to ensure the libcall return is passed in an FPR on hard
8858 // float ABIs.
8859 assert(!Subtarget.isSoftFPABI() && "Unexpected custom legalization");
8860 SDLoc DL(Op);
8861 MakeLibCallOptions CallOptions;
8862 RTLIB::Libcall LC =
8863 RTLIB::getFPROUND(Op.getOperand(0).getValueType(), MVT::bf16);
8864 SDValue Res =
8865 makeLibCall(DAG, LC, MVT::f32, Op.getOperand(0), CallOptions, DL).first;
8866 if (Subtarget.is64Bit())
8867 return DAG.getNode(RISCVISD::FMV_X_ANYEXTW_RV64, DL, MVT::i64, Res);
8868 return DAG.getBitcast(MVT::i32, Res);
8869 }
8870 case ISD::BF16_TO_FP: {
8871 assert(Subtarget.hasStdExtFOrZfinx() && "Unexpected custom legalization");
8872 MVT VT = Op.getSimpleValueType();
8873 SDLoc DL(Op);
8874 Op = DAG.getNode(
8875 ISD::SHL, DL, Op.getOperand(0).getValueType(), Op.getOperand(0),
8876 DAG.getShiftAmountConstant(16, Op.getOperand(0).getValueType(), DL));
8877 SDValue Res = Subtarget.is64Bit()
8878 ? DAG.getNode(RISCVISD::FMV_W_X_RV64, DL, MVT::f32, Op)
8879 : DAG.getBitcast(MVT::f32, Op);
8880 // fp_extend if the target VT is bigger than f32.
8881 if (VT != MVT::f32)
8882 return DAG.getNode(ISD::FP_EXTEND, DL, VT, Res);
8883 return Res;
8884 }
8886 case ISD::FP_TO_FP16: {
8887 // Custom lower to ensure the libcall return is passed in an FPR on hard
8888 // float ABIs.
8889 assert(Subtarget.hasStdExtFOrZfinx() && "Unexpected custom legalisation");
8890 SDLoc DL(Op);
8891 MakeLibCallOptions CallOptions;
8892 bool IsStrict = Op->isStrictFPOpcode();
8893 SDValue Op0 = IsStrict ? Op.getOperand(1) : Op.getOperand(0);
8894 SDValue Chain = IsStrict ? Op.getOperand(0) : SDValue();
8895 RTLIB::Libcall LC = RTLIB::getFPROUND(Op0.getValueType(), MVT::f16);
8896 SDValue Res;
8897 std::tie(Res, Chain) =
8898 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions, DL, Chain);
8899 if (Subtarget.is64Bit())
8900 return DAG.getNode(RISCVISD::FMV_X_ANYEXTW_RV64, DL, MVT::i64, Res);
8901 SDValue Result = DAG.getBitcast(MVT::i32, IsStrict ? Res.getValue(0) : Res);
8902 if (IsStrict)
8903 return DAG.getMergeValues({Result, Chain}, DL);
8904 return Result;
8905 }
8907 case ISD::FP16_TO_FP: {
8908 // Custom lower to ensure the libcall argument is passed in an FPR on hard
8909 // float ABIs.
8910 assert(Subtarget.hasStdExtFOrZfinx() && "Unexpected custom legalisation");
8911 SDLoc DL(Op);
8912 MakeLibCallOptions CallOptions;
8913 bool IsStrict = Op->isStrictFPOpcode();
8914 SDValue Op0 = IsStrict ? Op.getOperand(1) : Op.getOperand(0);
8915 SDValue Chain = IsStrict ? Op.getOperand(0) : SDValue();
8916 SDValue Arg = Subtarget.is64Bit()
8917 ? DAG.getNode(RISCVISD::FMV_W_X_RV64, DL, MVT::f32, Op0)
8918 : DAG.getBitcast(MVT::f32, Op0);
8919 SDValue Res;
8920 std::tie(Res, Chain) = makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
8921 CallOptions, DL, Chain);
8922 if (IsStrict)
8923 return DAG.getMergeValues({Res, Chain}, DL);
8924 return Res;
8925 }
8926 case ISD::FTRUNC:
8927 case ISD::FCEIL:
8928 case ISD::FFLOOR:
8929 case ISD::FNEARBYINT:
8930 case ISD::FRINT:
8931 case ISD::FROUND:
8932 case ISD::FROUNDEVEN:
8933 if (isPromotedOpNeedingSplit(Op, Subtarget, *this))
8934 return SplitVectorOp(Op, DAG);
8935 return lowerFTRUNC_FCEIL_FFLOOR_FROUND(Op, DAG, Subtarget);
8936 case ISD::FCANONICALIZE: {
8937 MVT VT = Op.getSimpleValueType();
8938 assert(VT.isFixedLengthVector() && "Unexpected type");
8939 SDLoc DL(Op);
8940 MVT ContainerVT = getContainerForFixedLengthVector(VT);
8941 SDValue Src =
8942 convertToScalableVector(ContainerVT, Op.getOperand(0), DAG, Subtarget);
8943 SDValue Res = DAG.getNode(ISD::FCANONICALIZE, DL, ContainerVT, Src);
8944 return convertFromScalableVector(VT, Res, DAG, Subtarget);
8945 }
8946 case ISD::LRINT:
8947 case ISD::LLRINT:
8948 case ISD::LROUND:
8949 case ISD::LLROUND: {
8950 if (Op.getValueType().isVector())
8951 return lowerVectorXRINT_XROUND(Op, DAG, Subtarget);
8952 assert(Op.getOperand(0).getValueType() == MVT::f16 &&
8953 "Unexpected custom legalisation");
8954 SDLoc DL(Op);
8955 SDValue Ext = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Op.getOperand(0));
8956 return DAG.getNode(Op.getOpcode(), DL, Op.getValueType(), Ext);
8957 }
8958 case ISD::STRICT_LRINT:
8959 case ISD::STRICT_LLRINT:
8960 case ISD::STRICT_LROUND:
8961 case ISD::STRICT_LLROUND: {
8962 assert(Op.getOperand(1).getValueType() == MVT::f16 &&
8963 "Unexpected custom legalisation");
8964 SDLoc DL(Op);
8965 SDValue Ext = DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {MVT::f32, MVT::Other},
8966 {Op.getOperand(0), Op.getOperand(1)});
8967 return DAG.getNode(Op.getOpcode(), DL, {Op.getValueType(), MVT::Other},
8968 {Ext.getValue(1), Ext.getValue(0)});
8969 }
8970 case ISD::VECREDUCE_ADD:
8975 return lowerVECREDUCE(Op, DAG);
8976 case ISD::VECREDUCE_AND:
8977 case ISD::VECREDUCE_OR:
8978 case ISD::VECREDUCE_XOR:
8979 if (Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
8980 return lowerVectorMaskVecReduction(Op, DAG, /*IsVP*/ false);
8981 return lowerVECREDUCE(Op, DAG);
8983 if (isPromotedOpNeedingSplit(Op.getOperand(1), Subtarget, *this))
8984 return SplitVectorReductionOp(Op, DAG, /*IsVP*/ false);
8985 return lowerFPVECREDUCE(Op, DAG);
8991 if (isPromotedOpNeedingSplit(Op.getOperand(0), Subtarget, *this))
8992 return SplitVectorReductionOp(Op, DAG, /*IsVP*/ false);
8993 return lowerFPVECREDUCE(Op, DAG);
8994 case ISD::VP_REDUCE_ADD:
8995 case ISD::VP_REDUCE_UMAX:
8996 case ISD::VP_REDUCE_SMAX:
8997 case ISD::VP_REDUCE_UMIN:
8998 case ISD::VP_REDUCE_SMIN:
8999 case ISD::VP_REDUCE_FADD:
9000 case ISD::VP_REDUCE_SEQ_FADD:
9001 case ISD::VP_REDUCE_FMIN:
9002 case ISD::VP_REDUCE_FMAX:
9003 case ISD::VP_REDUCE_FMINIMUM:
9004 case ISD::VP_REDUCE_FMAXIMUM:
9005 if (isPromotedOpNeedingSplit(Op.getOperand(1), Subtarget, *this))
9006 return SplitVectorReductionOp(Op, DAG, /*IsVP*/ true);
9007 return lowerVPREDUCE(Op, DAG);
9008 case ISD::VP_REDUCE_AND:
9009 case ISD::VP_REDUCE_OR:
9010 case ISD::VP_REDUCE_XOR:
9011 if (Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
9012 return lowerVectorMaskVecReduction(Op, DAG, /*IsVP*/ true);
9013 return lowerVPREDUCE(Op, DAG);
9014 case ISD::VP_CTTZ_ELTS:
9015 case ISD::VP_CTTZ_ELTS_ZERO_POISON:
9016 return lowerVPCttzElements(Op, DAG);
9017 case ISD::UNDEF:
9018 case ISD::POISON: {
9019 MVT ContainerVT = getContainerForFixedLengthVector(Op.getSimpleValueType());
9020 SDValue Passthru = Op.getOpcode() == ISD::POISON
9021 ? DAG.getPOISON(ContainerVT)
9022 : DAG.getUNDEF(ContainerVT);
9023 return convertFromScalableVector(Op.getSimpleValueType(), Passthru, DAG,
9024 Subtarget);
9025 }
9027 return lowerINSERT_SUBVECTOR(Op, DAG);
9029 return lowerEXTRACT_SUBVECTOR(Op, DAG);
9031 return lowerVECTOR_DEINTERLEAVE(Op, DAG);
9033 return lowerVECTOR_INTERLEAVE(Op, DAG);
9034 case ISD::STEP_VECTOR:
9035 return lowerSTEP_VECTOR(Op, DAG);
9037 return lowerVECTOR_REVERSE(Op, DAG);
9040 return lowerVECTOR_SPLICE(Op, DAG);
9041 case ISD::BUILD_VECTOR: {
9042 MVT VT = Op.getSimpleValueType();
9043 MVT EltVT = VT.getVectorElementType();
9044 if (!Subtarget.is64Bit() && EltVT == MVT::i64)
9045 return lowerBuildVectorViaVID(Op, DAG, Subtarget);
9046 return lowerBUILD_VECTOR(Op, DAG, Subtarget);
9047 }
9048 case ISD::SPLAT_VECTOR: {
9049 MVT VT = Op.getSimpleValueType();
9050 MVT EltVT = VT.getVectorElementType();
9051 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
9052 EltVT == MVT::bf16) {
9053 SDLoc DL(Op);
9054 SDValue Elt;
9055 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
9056 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
9057 Elt = DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, Subtarget.getXLenVT(),
9058 Op.getOperand(0));
9059 else
9060 Elt = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Op.getOperand(0));
9061 MVT IVT = VT.changeVectorElementType(MVT::i16);
9062 return DAG.getNode(ISD::BITCAST, DL, VT,
9063 DAG.getNode(ISD::SPLAT_VECTOR, DL, IVT, Elt));
9064 }
9065
9066 if (EltVT == MVT::i1)
9067 return lowerVectorMaskSplat(Op, DAG);
9068 return SDValue();
9069 }
9071 return lowerVECTOR_SHUFFLE(Op, DAG);
9072 case ISD::CONCAT_VECTORS: {
9073 // Split CONCAT_VECTORS into a series of INSERT_SUBVECTOR nodes. This is
9074 // better than going through the stack, as the default expansion does.
9075 SDLoc DL(Op);
9076 MVT VT = Op.getSimpleValueType();
9077 MVT ContainerVT = VT;
9078 if (VT.isFixedLengthVector())
9079 ContainerVT = ::getContainerForFixedLengthVector(VT, Subtarget);
9080
9081 // Recursively split concat_vectors with more than 2 operands:
9082 //
9083 // concat_vector op1, op2, op3, op4
9084 // ->
9085 // concat_vector (concat_vector op1, op2), (concat_vector op3, op4)
9086 //
9087 // This reduces the length of the chain of vslideups and allows us to
9088 // perform the vslideups at a smaller LMUL, limited to MF2.
9089 if (Op.getNumOperands() > 2 &&
9090 ContainerVT.bitsGE(RISCVTargetLowering::getM1VT(ContainerVT))) {
9091 MVT HalfVT = VT.getHalfNumVectorElementsVT();
9092 assert(isPowerOf2_32(Op.getNumOperands()));
9093 size_t HalfNumOps = Op.getNumOperands() / 2;
9094 SDValue Lo = DAG.getNode(ISD::CONCAT_VECTORS, DL, HalfVT,
9095 Op->ops().take_front(HalfNumOps));
9096 SDValue Hi = DAG.getNode(ISD::CONCAT_VECTORS, DL, HalfVT,
9097 Op->ops().drop_front(HalfNumOps));
9098 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi);
9099 }
9100
9101 unsigned NumOpElts =
9102 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
9103 SDValue Vec = DAG.getUNDEF(VT);
9104 for (const auto &OpIdx : enumerate(Op->ops())) {
9105 SDValue SubVec = OpIdx.value();
9106 // Don't insert undef subvectors.
9107 if (SubVec.isUndef())
9108 continue;
9109 Vec = DAG.getInsertSubvector(DL, Vec, SubVec, OpIdx.index() * NumOpElts);
9110 }
9111 return Vec;
9112 }
9113 case ISD::LOAD: {
9114 auto *Load = cast<LoadSDNode>(Op);
9115 EVT VT = Load->getValueType(0);
9116 if (VT == MVT::f64) {
9117 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
9118 !Subtarget.is64Bit() && "Unexpected custom legalisation");
9119
9120 // Replace a double precision load with two i32 loads and a BuildPairF64.
9121 SDLoc DL(Op);
9122 SDValue BasePtr = Load->getBasePtr();
9123 SDValue Chain = Load->getChain();
9124
9125 SDValue Lo =
9126 DAG.getLoad(MVT::i32, DL, Chain, BasePtr, Load->getPointerInfo(),
9127 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
9128 BasePtr = DAG.getObjectPtrOffset(DL, BasePtr, TypeSize::getFixed(4));
9129 SDValue Hi = DAG.getLoad(
9130 MVT::i32, DL, Chain, BasePtr, Load->getPointerInfo().getWithOffset(4),
9131 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
9132 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo.getValue(1),
9133 Hi.getValue(1));
9134
9135 // For big-endian, swap the order of Lo and Hi.
9136 if (!Subtarget.isLittleEndian())
9137 std::swap(Lo, Hi);
9138
9139 SDValue Pair = DAG.getNode(RISCVISD::BuildPairF64, DL, MVT::f64, Lo, Hi);
9140 return DAG.getMergeValues({Pair, Chain}, DL);
9141 }
9142
9143 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit() &&
9144 (VT == MVT::v2i32 || VT == MVT::v4i16 || VT == MVT::v8i8)) {
9145 assert(!Subtarget.is64Bit() && "Unexpected custom legalisation");
9146
9147 // Determine the half-size type
9148 MVT HalfVT;
9149 if (VT == MVT::v2i32)
9150 HalfVT = MVT::i32;
9151 else if (VT == MVT::v4i16)
9152 HalfVT = MVT::v2i16;
9153 else // VT == MVT::v8i8
9154 HalfVT = MVT::v4i8;
9155
9156 SDLoc DL(Op);
9157 SDValue BasePtr = Load->getBasePtr();
9158 SDValue Chain = Load->getChain();
9159
9160 // Create two loads for the lower and upper halves
9161 SDValue Lo =
9162 DAG.getLoad(HalfVT, DL, Chain, BasePtr, Load->getPointerInfo(),
9163 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
9164 unsigned HalfSize = HalfVT.getStoreSize();
9165 BasePtr =
9166 DAG.getObjectPtrOffset(DL, BasePtr, TypeSize::getFixed(HalfSize));
9167 SDValue Hi =
9168 DAG.getLoad(HalfVT, DL, Chain, BasePtr,
9169 Load->getPointerInfo().getWithOffset(HalfSize),
9170 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
9171 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo.getValue(1),
9172 Hi.getValue(1));
9173
9174 // Combine the two halves into the result vector
9175 SDValue Result;
9176 if (VT == MVT::v2i32) {
9177 // For v2i32, build vector from two i32 scalars
9178 Result = DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
9179 } else {
9180 // For v4i16 and v8i8, use CONCAT_VECTORS
9181 Result = DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi);
9182 }
9183
9184 return DAG.getMergeValues({Result, Chain}, DL);
9185 }
9186
9187 if (VT == MVT::bf16)
9188 return lowerXAndesBfHCvtBFloat16Load(Op, DAG);
9189
9190 // Handle normal vector tuple load.
9191 if (VT.isRISCVVectorTuple()) {
9192 SDLoc DL(Op);
9193 MVT XLenVT = Subtarget.getXLenVT();
9194 unsigned NF = VT.getRISCVVectorTupleNumFields();
9195 unsigned Sz = VT.getSizeInBits().getKnownMinValue();
9196 unsigned NumElts = Sz / (NF * 8);
9197 int Log2LMUL = Log2_64(NumElts) - 3;
9198
9199 auto Flag = SDNodeFlags();
9200 Flag.setNoUnsignedWrap(true);
9201 SDValue Ret = DAG.getUNDEF(VT);
9202 SDValue BasePtr = Load->getBasePtr();
9203 SDValue VROffset = DAG.getNode(RISCVISD::READ_VLENB, DL, XLenVT);
9204 VROffset =
9205 DAG.getNode(ISD::SHL, DL, XLenVT, VROffset,
9206 DAG.getConstant(std::max(Log2LMUL, 0), DL, XLenVT));
9207 SmallVector<SDValue, 8> OutChains;
9208
9209 // Load NF vector registers and combine them to a vector tuple.
9210 for (unsigned i = 0; i < NF; ++i) {
9211 SDValue LoadVal = DAG.getLoad(
9212 MVT::getScalableVectorVT(MVT::i8, NumElts), DL, Load->getChain(),
9213 BasePtr, MachinePointerInfo(Load->getAddressSpace()), Align(8));
9214 OutChains.push_back(LoadVal.getValue(1));
9215 Ret = DAG.getNode(RISCVISD::TUPLE_INSERT, DL, VT, Ret, LoadVal,
9216 DAG.getTargetConstant(i, DL, MVT::i32));
9217 BasePtr = DAG.getNode(ISD::ADD, DL, XLenVT, BasePtr, VROffset, Flag);
9218 }
9219 return DAG.getMergeValues(
9220 {Ret, DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains)}, DL);
9221 }
9222
9223 if (auto V = expandUnalignedRVVLoad(Op, DAG))
9224 return V;
9225 if (Op.getValueType().isFixedLengthVector())
9226 return lowerFixedLengthVectorLoadToRVV(Op, DAG);
9227 return Op;
9228 }
9229 case ISD::STORE: {
9230 auto *Store = cast<StoreSDNode>(Op);
9231 SDValue StoredVal = Store->getValue();
9232 EVT VT = StoredVal.getValueType();
9233
9234 if (VT == MVT::f64) {
9235 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
9236 !Subtarget.is64Bit() && "Unexpected custom legalisation");
9237
9238 // Replace a double precision store with a SplitF64 and i32 stores.
9239 SDValue DL(Op);
9240 SDValue BasePtr = Store->getBasePtr();
9241 SDValue Chain = Store->getChain();
9242 SDValue Split = DAG.getNode(RISCVISD::SplitF64, DL,
9243 DAG.getVTList(MVT::i32, MVT::i32), StoredVal);
9244
9245 SDValue Lo = Split.getValue(0);
9246 SDValue Hi = Split.getValue(1);
9247
9248 // For big-endian, swap the order of Lo and Hi before storing.
9249 if (!Subtarget.isLittleEndian())
9250 std::swap(Lo, Hi);
9251
9252 SDValue LoStore = DAG.getStore(
9253 Chain, DL, Lo, BasePtr, Store->getPointerInfo(),
9254 Store->getBaseAlign(), Store->getMemOperand()->getFlags());
9255 BasePtr = DAG.getObjectPtrOffset(DL, BasePtr, TypeSize::getFixed(4));
9256 SDValue HiStore = DAG.getStore(
9257 Chain, DL, Hi, BasePtr, Store->getPointerInfo().getWithOffset(4),
9258 Store->getBaseAlign(), Store->getMemOperand()->getFlags());
9259 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, LoStore, HiStore);
9260 }
9261 if (VT == MVT::i64) {
9262 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
9263 "Unexpected custom legalisation");
9264 if (Store->isTruncatingStore())
9265 return SDValue();
9266
9267 if (Store->getAlign() < Subtarget.getZilsdAlign())
9268 return SDValue();
9269
9270 SDLoc DL(Op);
9271 SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, StoredVal,
9272 DAG.getTargetConstant(0, DL, MVT::i32));
9273 SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, StoredVal,
9274 DAG.getTargetConstant(1, DL, MVT::i32));
9275
9276 return DAG.getMemIntrinsicNode(
9277 RISCVISD::SD_RV32, DL, DAG.getVTList(MVT::Other),
9278 {Store->getChain(), Lo, Hi, Store->getBasePtr()}, MVT::i64,
9279 Store->getMemOperand());
9280 }
9281
9282 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit() &&
9283 (VT == MVT::v2i32 || VT == MVT::v4i16 || VT == MVT::v8i8)) {
9284 assert(!Subtarget.is64Bit() && "Unexpected custom legalisation");
9285
9286 auto *Store = cast<StoreSDNode>(Op);
9287 SDValue Val = Store->getValue();
9288
9289 // Determine the half-size type
9290 MVT HalfVT;
9291 if (VT == MVT::v2i32)
9292 HalfVT = MVT::i32;
9293 else if (VT == MVT::v4i16)
9294 HalfVT = MVT::v2i16;
9295 else // VT == MVT::v8i8
9296 HalfVT = MVT::v4i8;
9297
9298 SDLoc DL(Op);
9299 SDValue BasePtr = Store->getBasePtr();
9300 SDValue Chain = Store->getChain();
9301
9302 // Extract the two halves from the vector
9303 SDValue Lo, Hi;
9304 if (VT == MVT::v2i32) {
9305 // For v2i32, extract two i32 scalars
9306 Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Val,
9307 DAG.getVectorIdxConstant(0, DL));
9308 Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Val,
9309 DAG.getVectorIdxConstant(1, DL));
9310 } else {
9311 // For v4i16 and v8i8, extract two vector halves
9312 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HalfVT, Val,
9313 DAG.getVectorIdxConstant(0, DL));
9314 unsigned HalfNumElts = HalfVT.getVectorNumElements();
9315 Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HalfVT, Val,
9316 DAG.getVectorIdxConstant(HalfNumElts, DL));
9317 }
9318
9319 // Create two stores for the lower and upper halves
9320 SDValue LoStore = DAG.getStore(
9321 Chain, DL, Lo, BasePtr, Store->getPointerInfo(),
9322 Store->getBaseAlign(), Store->getMemOperand()->getFlags());
9323 unsigned HalfSize = HalfVT.getStoreSize();
9324 BasePtr =
9325 DAG.getObjectPtrOffset(DL, BasePtr, TypeSize::getFixed(HalfSize));
9326 SDValue HiStore = DAG.getStore(
9327 Chain, DL, Hi, BasePtr,
9328 Store->getPointerInfo().getWithOffset(HalfSize),
9329 Store->getBaseAlign(), Store->getMemOperand()->getFlags());
9330
9331 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, LoStore, HiStore);
9332 }
9333
9334 if (VT == MVT::bf16)
9335 return lowerXAndesBfHCvtBFloat16Store(Op, DAG);
9336
9337 // Handle normal vector tuple store.
9338 if (VT.isRISCVVectorTuple()) {
9339 SDLoc DL(Op);
9340 MVT XLenVT = Subtarget.getXLenVT();
9341 unsigned NF = VT.getRISCVVectorTupleNumFields();
9342 unsigned Sz = VT.getSizeInBits().getKnownMinValue();
9343 unsigned NumElts = Sz / (NF * 8);
9344 int Log2LMUL = Log2_64(NumElts) - 3;
9345
9346 auto Flag = SDNodeFlags();
9347 Flag.setNoUnsignedWrap(true);
9348 SDValue Ret;
9349 SDValue Chain = Store->getChain();
9350 SDValue BasePtr = Store->getBasePtr();
9351 SDValue VROffset = DAG.getNode(RISCVISD::READ_VLENB, DL, XLenVT);
9352 VROffset =
9353 DAG.getNode(ISD::SHL, DL, XLenVT, VROffset,
9354 DAG.getConstant(std::max(Log2LMUL, 0), DL, XLenVT));
9355
9356 // Extract subregisters in a vector tuple and store them individually.
9357 for (unsigned i = 0; i < NF; ++i) {
9358 auto Extract =
9359 DAG.getNode(RISCVISD::TUPLE_EXTRACT, DL,
9360 MVT::getScalableVectorVT(MVT::i8, NumElts), StoredVal,
9361 DAG.getTargetConstant(i, DL, MVT::i32));
9362 Ret = DAG.getStore(Chain, DL, Extract, BasePtr,
9363 MachinePointerInfo(Store->getAddressSpace()),
9364 Store->getBaseAlign(),
9365 Store->getMemOperand()->getFlags());
9366 Chain = Ret.getValue(0);
9367 BasePtr = DAG.getNode(ISD::ADD, DL, XLenVT, BasePtr, VROffset, Flag);
9368 }
9369 return Ret;
9370 }
9371
9372 if (auto V = expandUnalignedRVVStore(Op, DAG))
9373 return V;
9374 if (Op.getOperand(1).getValueType().isFixedLengthVector())
9375 return lowerFixedLengthVectorStoreToRVV(Op, DAG);
9376 return Op;
9377 }
9378 case ISD::VP_LOAD:
9379 if (SDValue V = expandUnalignedVPLoad(Op, DAG))
9380 return V;
9381 [[fallthrough]];
9382 case ISD::MLOAD:
9383 return lowerMaskedLoad(Op, DAG);
9384 case ISD::VP_LOAD_FF:
9385 return lowerLoadFF(Op, DAG);
9386 case ISD::VP_STORE:
9387 if (SDValue V = expandUnalignedVPStore(Op, DAG))
9388 return V;
9389 [[fallthrough]];
9390 case ISD::MSTORE:
9391 return lowerMaskedStore(Op, DAG);
9393 return lowerVectorCompress(Op, DAG);
9394 case ISD::SELECT_CC: {
9395 // This occurs because we custom legalize SETGT and SETUGT for setcc. That
9396 // causes LegalizeDAG to think we need to custom legalize select_cc. Expand
9397 // into separate SETCC+SELECT just like LegalizeDAG.
9398 SDValue Tmp1 = Op.getOperand(0);
9399 SDValue Tmp2 = Op.getOperand(1);
9400 SDValue True = Op.getOperand(2);
9401 SDValue False = Op.getOperand(3);
9402 EVT VT = Op.getValueType();
9403 SDValue CC = Op.getOperand(4);
9404 EVT CmpVT = Tmp1.getValueType();
9405 EVT CCVT =
9406 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), CmpVT);
9407 SDLoc DL(Op);
9408 SDValue Cond =
9409 DAG.getNode(ISD::SETCC, DL, CCVT, Tmp1, Tmp2, CC, Op->getFlags());
9410 return DAG.getSelect(DL, VT, Cond, True, False);
9411 }
9412 case ISD::SETCC: {
9413 MVT OpVT = Op.getOperand(0).getSimpleValueType();
9414 if (OpVT.isScalarInteger()) {
9415 MVT VT = Op.getSimpleValueType();
9416 SDValue LHS = Op.getOperand(0);
9417 SDValue RHS = Op.getOperand(1);
9418 ISD::CondCode CCVal = cast<CondCodeSDNode>(Op.getOperand(2))->get();
9419 assert((CCVal == ISD::SETGT || CCVal == ISD::SETUGT) &&
9420 "Unexpected CondCode");
9421
9422 SDLoc DL(Op);
9423
9424 // If the RHS is a constant in the range [-2049, 0) or (0, 2046], we can
9425 // convert this to the equivalent of (set(u)ge X, C+1) by using
9426 // (xori (slti(u) X, C+1), 1). This avoids materializing a small constant
9427 // in a register.
9428 if (isa<ConstantSDNode>(RHS)) {
9429 int64_t Imm = cast<ConstantSDNode>(RHS)->getSExtValue();
9430 if (Imm != 0 && isInt<12>((uint64_t)Imm + 1)) {
9431 // If this is an unsigned compare and the constant is -1, incrementing
9432 // the constant would change behavior. The result should be false.
9433 if (CCVal == ISD::SETUGT && Imm == -1)
9434 return DAG.getConstant(0, DL, VT);
9435 // Using getSetCCSwappedOperands will convert SET(U)GT->SET(U)LT.
9436 CCVal = ISD::getSetCCSwappedOperands(CCVal);
9437 SDValue SetCC = DAG.getSetCC(
9438 DL, VT, LHS, DAG.getSignedConstant(Imm + 1, DL, OpVT), CCVal);
9439 return DAG.getLogicalNOT(DL, SetCC, VT);
9440 }
9441 // Lower (setugt X, 2047) as (setne (srl X, 11), 0).
9442 if (CCVal == ISD::SETUGT && Imm == 2047) {
9443 SDValue Shift = DAG.getNode(ISD::SRL, DL, OpVT, LHS,
9444 DAG.getShiftAmountConstant(11, OpVT, DL));
9445 return DAG.getSetCC(DL, VT, Shift, DAG.getConstant(0, DL, OpVT),
9446 ISD::SETNE);
9447 }
9448 }
9449
9450 // Not a constant we could handle, swap the operands and condition code to
9451 // SETLT/SETULT.
9452 CCVal = ISD::getSetCCSwappedOperands(CCVal);
9453 return DAG.getSetCC(DL, VT, RHS, LHS, CCVal);
9454 }
9455
9456 MVT VT = Op.getSimpleValueType();
9457 if (Subtarget.hasStdExtP() && VT.isFixedLengthVector()) {
9458 ISD::CondCode CCVal = cast<CondCodeSDNode>(Op.getOperand(2))->get();
9459 SDValue LHS = Op.getOperand(0);
9460 SDValue RHS = Op.getOperand(1);
9461 SDLoc DL(Op);
9462 if (CCVal == ISD::SETNE) {
9463 // Convert setne X, 0 to setult 0, X.
9464 if (ISD::isConstantSplatVectorAllZeros(RHS.getNode())) {
9465 return DAG.getSetCC(DL, VT, RHS, LHS, ISD::SETULT);
9466 }
9467
9468 // Not a constant we could handle, convert to SETEQ+Invert
9469 SDValue SetCC = DAG.getSetCC(DL, VT, LHS, RHS, ISD::SETEQ);
9470 return DAG.getLogicalNOT(DL, SetCC, VT);
9471 }
9472
9473 if (CCVal == ISD::SETGT) {
9474 if (ISD::isConstantSplatVectorAllOnes(RHS.getNode())) {
9475 SDValue SetCC =
9476 DAG.getSetCC(DL, VT, LHS, DAG.getConstant(0, DL, VT), ISD::SETLT);
9477 return DAG.getLogicalNOT(DL, SetCC, VT);
9478 }
9479
9480 // Not a constant we could handle, swap the operands and condition code
9481 // to SETLT.
9482 CCVal = ISD::getSetCCSwappedOperands(CCVal);
9483 return DAG.getSetCC(DL, VT, RHS, LHS, CCVal);
9484 }
9485
9486 return SDValue();
9487 }
9488
9489 if (isPromotedOpNeedingSplit(Op.getOperand(0), Subtarget, *this))
9490 return SplitVectorOp(Op, DAG);
9491
9492 return lowerToScalableOp(Op, DAG);
9493 }
9494 case ISD::ADD:
9495 case ISD::SUB:
9496 case ISD::SDIV:
9497 case ISD::SREM:
9498 case ISD::UDIV:
9499 case ISD::UREM:
9500 case ISD::BSWAP:
9501 case ISD::CTPOP:
9502 return lowerToScalableOp(Op, DAG);
9503 case ISD::VSELECT: {
9504 EVT VT = Op.getValueType();
9505 // Split 64-bit vector VSELECT on RV32 with P extension for v4i16 and v8i8
9506 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit() &&
9507 (VT == MVT::v4i16 || VT == MVT::v8i8)) {
9508 SDLoc DL(Op);
9509 SDValue Mask = Op.getOperand(0);
9510 SDValue TrueVal = Op.getOperand(1);
9511 SDValue FalseVal = Op.getOperand(2);
9512
9513 // Split all three operands into two halves
9514 auto [MaskLo, MaskHi] = DAG.SplitVector(Mask, DL);
9515 auto [TrueLo, TrueHi] = DAG.SplitVector(TrueVal, DL);
9516 auto [FalseLo, FalseHi] = DAG.SplitVector(FalseVal, DL);
9517
9518 // Perform VSELECT on each half
9519 SDValue ResLo = DAG.getNode(ISD::VSELECT, DL, TrueLo.getValueType(),
9520 MaskLo, TrueLo, FalseLo);
9521 SDValue ResHi = DAG.getNode(ISD::VSELECT, DL, TrueHi.getValueType(),
9522 MaskHi, TrueHi, FalseHi);
9523
9524 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, ResLo, ResHi);
9525 }
9526 return lowerToScalableOp(Op, DAG);
9527 }
9528 case ISD::AND:
9529 case ISD::OR:
9530 case ISD::XOR:
9531 case ISD::MUL:
9532 case ISD::MULHS:
9533 case ISD::MULHU: {
9534 EVT VT = Op.getValueType();
9535 unsigned Opc = Op.getOpcode();
9536 // Split 64-bit vector AND/OR/XOR/MUL/MULHS/MULHU on RV32 with P extension
9537 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit() &&
9538 (VT == MVT::v4i16 || VT == MVT::v8i8)) {
9539 SDLoc DL(Op);
9540 SDValue LHS = Op.getOperand(0);
9541 SDValue RHS = Op.getOperand(1);
9542
9543 // Determine the half-size type
9544 MVT HalfVT = (VT == MVT::v4i16) ? MVT::v2i16 : MVT::v4i8;
9545
9546 // Extract the two halves from LHS
9547 auto [LHSLo, LHSHi] = DAG.SplitVector(LHS, DL, HalfVT, HalfVT);
9548
9549 // Extract the two halves from RHS
9550 auto [RHSLo, RHSHi] = DAG.SplitVector(RHS, DL, HalfVT, HalfVT);
9551
9552 // Perform the operation on each half
9553 SDValue ResLo = DAG.getNode(Opc, DL, HalfVT, LHSLo, RHSLo);
9554 SDValue ResHi = DAG.getNode(Opc, DL, HalfVT, LHSHi, RHSHi);
9555
9556 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, ResLo, ResHi);
9557 }
9558 // Lower v4i8/v2i16 MUL/MULHS/MULHU via widening multiply + srl + truncate.
9559 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit() &&
9560 (Opc == ISD::MUL || Opc == ISD::MULHS || Opc == ISD::MULHU) &&
9561 (VT == MVT::v4i8 || VT == MVT::v2i16)) {
9562 assert((VT == MVT::v4i8 || Opc == ISD::MUL) &&
9563 "Unexpected custom legalisation");
9564 SDLoc DL(Op);
9565 MVT WideVT = (VT == MVT::v4i8) ? MVT::v4i16 : MVT::v2i32;
9566 unsigned WMulOpc =
9567 (Opc == ISD::MULHU) ? RISCVISD::PWMULU : RISCVISD::PWMUL;
9568 SDValue Res =
9569 DAG.getNode(WMulOpc, DL, WideVT, Op.getOperand(0), Op.getOperand(1));
9570 if (Opc != ISD::MUL) {
9571 unsigned EltBits = VT.getVectorElementType().getSizeInBits();
9572 Res = DAG.getNode(ISD::SRL, DL, WideVT, Res,
9573 DAG.getConstant(EltBits, DL, WideVT));
9574 }
9575 return DAG.getNode(ISD::TRUNCATE, DL, VT, Res);
9576 }
9577 // Lower v8i8 MULHS/MULHU on RV64 via a pair of widening byte multiplies
9578 // (picking out the even/odd result lanes) recombined with PPAIRO.
9579 if (Subtarget.hasStdExtP() && Subtarget.is64Bit() && VT == MVT::v8i8 &&
9580 Opc != ISD::MUL) {
9581 SDLoc DL(Op);
9582 SDValue LHS = Op.getOperand(0);
9583 SDValue RHS = Op.getOperand(1);
9584 unsigned LoOpc = Opc == ISD::MULHU ? RISCVISD::PMULU_HALVES_00
9585 : RISCVISD::PMUL_HALVES_00;
9586 unsigned HiOpc = Opc == ISD::MULHU ? RISCVISD::PMULU_HALVES_11
9587 : RISCVISD::PMUL_HALVES_11;
9588 SDValue Lo = DAG.getNode(LoOpc, DL, MVT::v4i16, LHS, RHS);
9589 SDValue Hi = DAG.getNode(HiOpc, DL, MVT::v4i16, LHS, RHS);
9590 return DAG.getNode(RISCVISD::PPAIRO, DL, VT, DAG.getBitcast(VT, Lo),
9591 DAG.getBitcast(VT, Hi));
9592 }
9593 return lowerToScalableOp(Op, DAG);
9594 }
9596 EVT VT = Op.getValueType();
9597 assert(Subtarget.hasStdExtP() && Subtarget.is64Bit() &&
9598 (VT == MVT::v2i32 || VT == MVT::v4i16) &&
9599 "Unexpected custom legalisation");
9601 Op.getOperand(0));
9602 }
9603 case ISD::SHL:
9604 case ISD::SRL:
9605 case ISD::SRA:
9606 case ISD::SSHLSAT:
9607 if (Op.getSimpleValueType().isFixedLengthVector()) {
9608 if (Subtarget.hasStdExtP()) {
9609 SDValue ShAmtVec = Op.getOperand(1);
9610 SDValue SplatVal;
9611 if (ShAmtVec.getOpcode() == ISD::SPLAT_VECTOR)
9612 SplatVal = ShAmtVec.getOperand(0);
9613 else if (ShAmtVec.getOpcode() == ISD::BUILD_VECTOR)
9614 SplatVal = cast<BuildVectorSDNode>(ShAmtVec)->getSplatValue();
9615
9616 if (!SplatVal)
9617 return SDValue();
9618
9619 unsigned Opc;
9620 switch (Op.getOpcode()) {
9621 default:
9622 llvm_unreachable("Unexpected opcode");
9623 case ISD::SHL:
9624 Opc = RISCVISD::PSLL;
9625 break;
9626 case ISD::SRL:
9627 Opc = RISCVISD::PSRL;
9628 break;
9629 case ISD::SRA:
9630 Opc = RISCVISD::PSRA;
9631 break;
9632 case ISD::SSHLSAT:
9633 Opc = RISCVISD::PSSHA;
9634 break;
9635 }
9636 return DAG.getNode(Opc, SDLoc(Op), Op.getValueType(), Op.getOperand(0),
9637 SplatVal);
9638 }
9639 return lowerToScalableOp(Op, DAG);
9640 }
9641 assert(Op.getOpcode() != ISD::SSHLSAT);
9642 // This can be called for an i32 shift amount that needs to be promoted.
9643 assert(Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() &&
9644 "Unexpected custom legalisation");
9645 return SDValue();
9646 case ISD::MASKED_UDIV:
9647 case ISD::MASKED_SDIV:
9648 case ISD::MASKED_UREM:
9649 case ISD::MASKED_SREM: {
9650 SDLoc DL(Op);
9651 MVT VT = Op.getSimpleValueType();
9652 MVT ContainerVT = getContainerForFixedLengthVector(VT);
9653 SDValue VL = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).second;
9654 SDValue Res = DAG.getNode(
9655 getRISCVVLOp(Op), DL, ContainerVT,
9656 convertToScalableVector(ContainerVT, Op.getOperand(0), DAG, Subtarget),
9657 convertToScalableVector(ContainerVT, Op.getOperand(1), DAG, Subtarget),
9658 DAG.getUNDEF(ContainerVT),
9659 convertToScalableVector(getMaskTypeFor(ContainerVT), Op.getOperand(2),
9660 DAG, Subtarget),
9661 VL);
9662 return convertFromScalableVector(VT, Res, DAG, Subtarget);
9663 }
9664 case ISD::FABS:
9665 case ISD::FNEG:
9666 if (Op.getValueType() == MVT::f16 || Op.getValueType() == MVT::bf16)
9667 return lowerFABSorFNEG(Op, DAG, Subtarget);
9668 [[fallthrough]];
9669 case ISD::FADD:
9670 case ISD::FSUB:
9671 case ISD::FMUL:
9672 case ISD::FDIV:
9673 case ISD::FSQRT:
9674 case ISD::FMA:
9675 case ISD::FMINNUM:
9676 case ISD::FMAXNUM:
9677 case ISD::FMINIMUMNUM:
9678 case ISD::FMAXIMUMNUM:
9679 if (isPromotedOpNeedingSplit(Op, Subtarget, *this))
9680 return SplitVectorOp(Op, DAG);
9681 [[fallthrough]];
9682 case ISD::AVGFLOORS:
9683 case ISD::AVGFLOORU:
9684 case ISD::AVGCEILS:
9685 case ISD::AVGCEILU:
9686 case ISD::SMIN:
9687 case ISD::SMAX:
9688 case ISD::UMIN:
9689 case ISD::UMAX:
9690 case ISD::UADDSAT:
9691 case ISD::USUBSAT:
9692 case ISD::SADDSAT:
9693 case ISD::SSUBSAT:
9694 return lowerToScalableOp(Op, DAG);
9695 case ISD::ABDS:
9696 case ISD::ABDU: {
9697 EVT VT = Op->getValueType(0);
9698 if (Subtarget.hasStdExtZvabd() && VT.isVector())
9699 return lowerToScalableOp(Op, DAG);
9700
9701 SDLoc dl(Op);
9702 SDValue LHS = DAG.getFreeze(Op->getOperand(0));
9703 SDValue RHS = DAG.getFreeze(Op->getOperand(1));
9704 bool IsSigned = Op->getOpcode() == ISD::ABDS;
9705
9706 // abds(lhs, rhs) -> sub(smax(lhs,rhs), smin(lhs,rhs))
9707 // abdu(lhs, rhs) -> sub(umax(lhs,rhs), umin(lhs,rhs))
9708 unsigned MaxOpc = IsSigned ? ISD::SMAX : ISD::UMAX;
9709 unsigned MinOpc = IsSigned ? ISD::SMIN : ISD::UMIN;
9710 SDValue Max = DAG.getNode(MaxOpc, dl, VT, LHS, RHS);
9711 SDValue Min = DAG.getNode(MinOpc, dl, VT, LHS, RHS);
9712 return DAG.getNode(ISD::SUB, dl, VT, Max, Min);
9713 }
9714 case ISD::ABS:
9716 return lowerABS(Op, DAG);
9717 case ISD::CTLZ:
9719 case ISD::CTTZ:
9721 if (Subtarget.hasStdExtZvbb())
9722 return lowerToScalableOp(Op, DAG);
9723 assert(Op.getOpcode() != ISD::CTTZ);
9724 return lowerCTLZ_CTTZ_ZERO_POISON(Op, DAG);
9725 case ISD::CLMUL:
9726 case ISD::CLMULH: {
9727 SDLoc DL(Op);
9728 MVT VT = Op.getSimpleValueType();
9729 MVT XLenVT = Subtarget.getXLenVT();
9730
9731 if (!VT.isVector()) {
9732 // The op needs to be performed in a vector register.
9733 assert(Subtarget.hasStdExtZvbc() && Subtarget.is64Bit() && VT == XLenVT &&
9734 "Unexpected custom legalisation");
9735 // We can't implicitly use vector registers with noimplicitfloat.
9737 Attribute::NoImplicitFloat))
9738 return SDValue();
9739 MVT VecVT = MVT::getScalableVectorVT(VT, 1);
9740 SDValue VL = DAG.getConstant(1, DL, XLenVT);
9741 SDValue Op0 =
9742 lowerScalarInsert(Op.getOperand(0), VL, VecVT, DL, DAG, Subtarget);
9743 SDValue Op1 =
9744 lowerScalarInsert(Op.getOperand(1), VL, VecVT, DL, DAG, Subtarget);
9745 SDValue Res = DAG.getNode(Op.getOpcode(), DL, VecVT, Op0, Op1);
9746 return DAG.getNode(RISCVISD::VMV_X_S, DL, XLenVT, Res);
9747 }
9748
9749 // If the scalable vector version of this op is Legal, convert to scalable.
9750 if (VT.isFixedLengthVector() &&
9751 (VT.getVectorElementType() == MVT::i64 || Subtarget.hasStdExtZvbc32e()))
9752 return lowerToScalableOp(Op, DAG);
9753
9754 assert(Op.getOpcode() == ISD::CLMUL && Subtarget.hasStdExtZvbc() &&
9755 "Unexpected custom legalisation");
9756 // Promote to i64 vector.
9757 MVT I64VecVT = VT.changeVectorElementType(MVT::i64);
9758 SDValue Op0 = DAG.getNode(ISD::ZERO_EXTEND, DL, I64VecVT, Op.getOperand(0));
9759 SDValue Op1 = DAG.getNode(ISD::ZERO_EXTEND, DL, I64VecVT, Op.getOperand(1));
9760 SDValue CLMUL = DAG.getNode(ISD::CLMUL, DL, I64VecVT, Op0, Op1);
9761 return DAG.getNode(ISD::TRUNCATE, DL, VT, CLMUL);
9762 }
9763 case ISD::FCOPYSIGN:
9764 if (Op.getValueType() == MVT::f16 || Op.getValueType() == MVT::bf16)
9765 return lowerFCOPYSIGN(Op, DAG, Subtarget);
9766 if (isPromotedOpNeedingSplit(Op, Subtarget, *this))
9767 return SplitVectorOp(Op, DAG);
9768 return lowerToScalableOp(Op, DAG);
9769 case ISD::STRICT_FADD:
9770 case ISD::STRICT_FSUB:
9771 case ISD::STRICT_FMUL:
9772 case ISD::STRICT_FDIV:
9773 case ISD::STRICT_FSQRT:
9774 case ISD::STRICT_FMA:
9775 if (isPromotedOpNeedingSplit(Op, Subtarget, *this))
9776 return SplitStrictFPVectorOp(Op, DAG);
9777 return lowerToScalableOp(Op, DAG);
9778 case ISD::STRICT_FSETCC:
9780 return lowerVectorStrictFSetcc(Op, DAG);
9781 case ISD::STRICT_FCEIL:
9782 case ISD::STRICT_FRINT:
9783 case ISD::STRICT_FFLOOR:
9784 case ISD::STRICT_FTRUNC:
9786 case ISD::STRICT_FROUND:
9788 return lowerVectorStrictFTRUNC_FCEIL_FFLOOR_FROUND(Op, DAG, Subtarget);
9789 case ISD::MGATHER:
9790 case ISD::VP_GATHER:
9791 return lowerMaskedGather(Op, DAG);
9792 case ISD::MSCATTER:
9793 case ISD::VP_SCATTER:
9794 return lowerMaskedScatter(Op, DAG);
9795 case ISD::GET_ROUNDING:
9796 return lowerGET_ROUNDING(Op, DAG);
9797 case ISD::SET_ROUNDING:
9798 return lowerSET_ROUNDING(Op, DAG);
9799 case ISD::GET_FPENV:
9800 return lowerGET_FPENV(Op, DAG);
9801 case ISD::SET_FPENV:
9802 return lowerSET_FPENV(Op, DAG);
9803 case ISD::RESET_FPENV:
9804 return lowerRESET_FPENV(Op, DAG);
9805 case ISD::GET_FPMODE:
9806 return lowerGET_FPMODE(Op, DAG);
9807 case ISD::SET_FPMODE:
9808 return lowerSET_FPMODE(Op, DAG);
9809 case ISD::RESET_FPMODE:
9810 return lowerRESET_FPMODE(Op, DAG);
9811 case ISD::EH_DWARF_CFA:
9812 return lowerEH_DWARF_CFA(Op, DAG);
9813 case ISD::VP_MERGE:
9814 if (Op.getSimpleValueType().getVectorElementType() == MVT::i1)
9815 return lowerVPMergeMask(Op, DAG);
9816 [[fallthrough]];
9817 case ISD::VP_SDIV:
9818 case ISD::VP_UDIV:
9819 case ISD::VP_SREM:
9820 case ISD::VP_UREM:
9821 return lowerVPOp(Op, DAG);
9822 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
9823 return lowerVPStridedLoad(Op, DAG);
9824 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
9825 return lowerVPStridedStore(Op, DAG);
9826 case ISD::EXPERIMENTAL_VP_SPLICE:
9827 return lowerVPSpliceExperimental(Op, DAG);
9828 case ISD::EXPERIMENTAL_VP_REVERSE:
9829 return lowerVPReverseExperimental(Op, DAG);
9830 case ISD::CLEAR_CACHE: {
9831 assert(getTargetMachine().getTargetTriple().isOSLinux() &&
9832 "llvm.clear_cache only needs custom lower on Linux targets");
9833 SDLoc DL(Op);
9834 SDValue Flags = DAG.getConstant(0, DL, Subtarget.getXLenVT());
9835 return emitFlushICache(DAG, Op.getOperand(0), Op.getOperand(1),
9836 Op.getOperand(2), Flags, DL);
9837 }
9839 return lowerDYNAMIC_STACKALLOC(Op, DAG);
9841 return lowerINIT_TRAMPOLINE(Op, DAG);
9843 return lowerADJUST_TRAMPOLINE(Op, DAG);
9847 return lowerPARTIAL_REDUCE_MLA(Op, DAG);
9848 case ISD::CTTZ_ELTS:
9850 return lowerCttzElts(Op, DAG, Subtarget);
9852 return lowerCONVERT_FROM_ARBITRARY_FP(Op, DAG, Subtarget);
9853 }
9854}
9855
9856SDValue RISCVTargetLowering::emitFlushICache(SelectionDAG &DAG, SDValue InChain,
9857 SDValue Start, SDValue End,
9858 SDValue Flags, SDLoc DL) const {
9859 MakeLibCallOptions CallOptions;
9860 std::pair<SDValue, SDValue> CallResult =
9861 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
9862 {Start, End, Flags}, CallOptions, DL, InChain);
9863
9864 // This function returns void so only the out chain matters.
9865 return CallResult.second;
9866}
9867
9868SDValue RISCVTargetLowering::lowerINIT_TRAMPOLINE(SDValue Op,
9869 SelectionDAG &DAG) const {
9870 if (!Subtarget.is64Bit())
9871 llvm::reportFatalUsageError("Trampolines only implemented for RV64");
9872
9873 // Create an MCCodeEmitter to encode instructions.
9874 TargetLoweringObjectFile *TLO = getTargetMachine().getObjFileLowering();
9875 assert(TLO);
9876 MCContext &MCCtx = TLO->getContext();
9877
9878 std::unique_ptr<MCCodeEmitter> CodeEmitter(
9879 createRISCVMCCodeEmitter(*getTargetMachine().getMCInstrInfo(), MCCtx));
9880
9881 SDValue Root = Op.getOperand(0);
9882 SDValue Trmp = Op.getOperand(1); // trampoline
9883 SDLoc dl(Op);
9884
9885 const Value *TrmpAddr = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
9886
9887 // We store in the trampoline buffer the following instructions and data.
9888 // Offset:
9889 // 0: auipc t2, 0
9890 // 4: ld t0, 24(t2)
9891 // 8: ld t2, 16(t2)
9892 // 12: jalr t0
9893 // 16: <StaticChainOffset>
9894 // 24: <FunctionAddressOffset>
9895 // 32:
9896 // Offset with branch control flow protection enabled:
9897 // 0: lpad <imm20>
9898 // 4: auipc t3, 0
9899 // 8: ld t2, 28(t3)
9900 // 12: ld t3, 20(t3)
9901 // 16: jalr t2
9902 // 20: <StaticChainOffset>
9903 // 28: <FunctionAddressOffset>
9904 // 36:
9905
9906 const MachineFunction &MF = DAG.getMachineFunction();
9907 const bool HasCFBranch =
9908 MF.getInfo<RISCVMachineFunctionInfo>()->hasCFProtectionBranch();
9909 const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
9910 const unsigned StaticChainOffset = StaticChainIdx * 4;
9911 const unsigned FunctionAddressOffset = StaticChainOffset + 8;
9912
9913 const MCSubtargetInfo &STI = getTargetMachine().getMCSubtargetInfo();
9914 auto GetEncoding = [&](const MCInst &MC) {
9917 CodeEmitter->encodeInstruction(MC, CB, Fixups, STI);
9918 uint32_t Encoding = support::endian::read32le(CB.data());
9919 return Encoding;
9920 };
9921
9922 SmallVector<SDValue> OutChains;
9923
9924 SmallVector<uint32_t> Encodings;
9925 if (!HasCFBranch) {
9926 Encodings.append(
9927 {// auipc t2, 0
9928 // Loads the current PC into t2.
9929 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
9930 // ld t0, 24(t2)
9931 // Loads the function address into t0. Note that we are using offsets
9932 // pc-relative to the first instruction of the trampoline.
9933 GetEncoding(MCInstBuilder(RISCV::LD)
9934 .addReg(RISCV::X5)
9935 .addReg(RISCV::X7)
9936 .addImm(FunctionAddressOffset)),
9937 // ld t2, 16(t2)
9938 // Load the value of the static chain.
9939 GetEncoding(MCInstBuilder(RISCV::LD)
9940 .addReg(RISCV::X7)
9941 .addReg(RISCV::X7)
9942 .addImm(StaticChainOffset)),
9943 // jalr t0
9944 // Jump to the function.
9945 GetEncoding(MCInstBuilder(RISCV::JALR)
9946 .addReg(RISCV::X0)
9947 .addReg(RISCV::X5)
9948 .addImm(0))});
9949 } else {
9950 Encodings.append(
9951 {// auipc x0, <imm20> (lpad <imm20>)
9952 // Landing pad.
9953 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X0).addImm(0)),
9954 // auipc t3, 0
9955 // Loads the current PC into t3.
9956 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X28).addImm(0)),
9957 // ld t2, (FunctionAddressOffset - 4)(t3)
9958 // Loads the function address into t2. Note that we are using offsets
9959 // pc-relative to the SECOND instruction of the trampoline.
9960 GetEncoding(MCInstBuilder(RISCV::LD)
9961 .addReg(RISCV::X7)
9962 .addReg(RISCV::X28)
9963 .addImm(FunctionAddressOffset - 4)),
9964 // ld t3, (StaticChainOffset - 4)(t3)
9965 // Load the value of the static chain.
9966 GetEncoding(MCInstBuilder(RISCV::LD)
9967 .addReg(RISCV::X28)
9968 .addReg(RISCV::X28)
9969 .addImm(StaticChainOffset - 4)),
9970 // jalr t2
9971 // Software-guarded jump to the function.
9972 GetEncoding(MCInstBuilder(RISCV::JALR)
9973 .addReg(RISCV::X0)
9974 .addReg(RISCV::X7)
9975 .addImm(0))});
9976 }
9977
9978 // Store encoded instructions.
9979 for (auto [Idx, Encoding] : llvm::enumerate(Encodings)) {
9980 SDValue Addr = Idx > 0 ? DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp,
9981 DAG.getConstant(Idx * 4, dl, MVT::i64))
9982 : Trmp;
9983 OutChains.push_back(DAG.getTruncStore(
9984 Root, dl, DAG.getConstant(Encoding, dl, MVT::i64), Addr,
9985 MachinePointerInfo(TrmpAddr, Idx * 4), MVT::i32));
9986 }
9987
9988 // Now store the variable part of the trampoline.
9989 SDValue FunctionAddress = Op.getOperand(2);
9990 SDValue StaticChain = Op.getOperand(3);
9991
9992 // Store the given static chain and function pointer in the trampoline buffer.
9993 struct OffsetValuePair {
9994 const unsigned Offset;
9995 const SDValue Value;
9996 SDValue Addr = SDValue(); // Used to cache the address.
9997 } OffsetValues[] = {
9998 {StaticChainOffset, StaticChain},
9999 {FunctionAddressOffset, FunctionAddress},
10000 };
10001 for (auto &OffsetValue : OffsetValues) {
10002 SDValue Addr =
10003 DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp,
10004 DAG.getConstant(OffsetValue.Offset, dl, MVT::i64));
10005 OffsetValue.Addr = Addr;
10006 OutChains.push_back(
10007 DAG.getStore(Root, dl, OffsetValue.Value, Addr,
10008 MachinePointerInfo(TrmpAddr, OffsetValue.Offset)));
10009 }
10010
10011 assert(OutChains.size() == StaticChainIdx + 2 &&
10012 "Size of OutChains mismatch");
10013 SDValue StoreToken = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
10014
10015 // The end of instructions of trampoline is the same as the static chain
10016 // address that we computed earlier.
10017 SDValue EndOfTrmp = OffsetValues[0].Addr;
10018
10019 // Call clear cache on the trampoline instructions.
10020 SDValue Chain = DAG.getNode(ISD::CLEAR_CACHE, dl, MVT::Other, StoreToken,
10021 Trmp, EndOfTrmp);
10022
10023 return Chain;
10024}
10025
10026SDValue RISCVTargetLowering::lowerADJUST_TRAMPOLINE(SDValue Op,
10027 SelectionDAG &DAG) const {
10028 if (!Subtarget.is64Bit())
10029 llvm::reportFatalUsageError("Trampolines only implemented for RV64");
10030
10031 return Op.getOperand(0);
10032}
10033
10034SDValue RISCVTargetLowering::lowerPARTIAL_REDUCE_MLA(SDValue Op,
10035 SelectionDAG &DAG) const {
10036 // Currently, only the vdot4a and vdot4au case (from zvdot4a8i) should be
10037 // legal.
10038 // TODO: There are many other sub-cases we could potentially lower, are
10039 // any of them worthwhile? Ex: via vredsum, vwredsum, vwwmaccu, etc..
10040 SDLoc DL(Op);
10041 MVT VT = Op.getSimpleValueType();
10042 SDValue Accum = Op.getOperand(0);
10043 SDValue A = Op.getOperand(1);
10044 SDValue B = Op.getOperand(2);
10045 MVT ArgVT = A.getSimpleValueType();
10046 assert(ArgVT == B.getSimpleValueType() &&
10047 ArgVT.getVectorElementType() == MVT::i8);
10048 (void)ArgVT;
10049
10050 // vdot4a* only produces an i32 result. For an i64 accumulator, perform the
10051 // dot product into a fresh i32 accumulator (each result is the sum of four
10052 // i8 products, which cannot overflow i32), reduce those i32 partial sums
10053 // down to the accumulator's element count while still in i32 (a sum of eight
10054 // i8 products still cannot overflow i32), and only then extend to i64 and add
10055 // to the accumulator.
10056 if (VT.getVectorElementType() == MVT::i64) {
10057 assert(Accum.getSimpleValueType() == VT);
10058 // vdot4a* reduces each group of four i8 lanes into one i32 lane, so the
10059 // intermediate i32 result has 1/4 the element count of the i8 inputs.
10060 MVT DotVT = MVT::getVectorVT(
10061 MVT::i32, ArgVT.getVectorElementCount().divideCoefficientBy(4));
10062 SDValue Dot = DAG.getNode(Op.getOpcode(), DL, DotVT,
10063 {DAG.getConstant(0, DL, DotVT), A, B});
10064 // The reduced i32 sums are signed for SMLA/SUMLA and unsigned for UMLA.
10065 unsigned ExtOpc = Op.getOpcode() == ISD::PARTIAL_REDUCE_UMLA
10068
10069 MVT NarrowVT = VT.changeVectorElementType(MVT::i32);
10070 if (VT.isScalableVector() &&
10072 .second) {
10073 // When the accumulator is a single vector (LMUL 1), the i32 subvectors
10074 // are a fractional LMUL, so extracting the high subvector would need a
10075 // vslidedown. Widen the i32 sums to i64 first instead; the i64
10076 // subvectors are then register-aligned and the reduction is a plain add.
10077 MVT WideVT = DotVT.changeVectorElementType(MVT::i64);
10078 SDValue Wide = DAG.getNode(ExtOpc, DL, WideVT, Dot);
10079 unsigned Stride = VT.getVectorMinNumElements();
10080 SDValue Sum = DAG.getExtractSubvector(DL, VT, Wide, 0);
10081 for (unsigned I = 1, E = WideVT.getVectorMinNumElements() / Stride;
10082 I != E; ++I)
10083 Sum = DAG.getNode(ISD::ADD, DL, VT, Sum,
10084 DAG.getExtractSubvector(DL, VT, Wide, I * Stride));
10085 return DAG.getNode(ISD::ADD, DL, VT, Accum, Sum);
10086 }
10087
10088 // Add the i32 partial sums down to the accumulator's element count by
10089 // extracting and summing the subvectors (still in i32 to avoid a wider
10090 // extend), then extend once to i64 and accumulate.
10091 unsigned Stride = NarrowVT.getVectorMinNumElements();
10092 SDValue Sum = DAG.getExtractSubvector(DL, NarrowVT, Dot, 0);
10093 for (unsigned I = 1, E = DotVT.getVectorMinNumElements() / Stride; I != E;
10094 ++I)
10095 Sum = DAG.getNode(ISD::ADD, DL, NarrowVT, Sum,
10096 DAG.getExtractSubvector(DL, NarrowVT, Dot, I * Stride));
10097 return DAG.getNode(ISD::ADD, DL, VT, Accum,
10098 DAG.getNode(ExtOpc, DL, VT, Sum));
10099 }
10100
10101 assert(Accum.getSimpleValueType() == VT &&
10102 VT.getVectorElementType() == MVT::i32);
10103
10104 // The zvdot4a8i pseudos are defined with sources and destination both
10105 // being i32. This cast is needed for correctness to avoid incorrect
10106 // .vx matching of i8 splats.
10107 A = DAG.getBitcast(VT, A);
10108 B = DAG.getBitcast(VT, B);
10109
10110 MVT ContainerVT = VT;
10111 if (VT.isFixedLengthVector()) {
10112 ContainerVT = getContainerForFixedLengthVector(VT);
10113 Accum = convertToScalableVector(ContainerVT, Accum, DAG, Subtarget);
10114 A = convertToScalableVector(ContainerVT, A, DAG, Subtarget);
10115 B = convertToScalableVector(ContainerVT, B, DAG, Subtarget);
10116 }
10117
10118 unsigned Opc;
10119 switch (Op.getOpcode()) {
10121 Opc = RISCVISD::VDOT4A_VL;
10122 break;
10124 Opc = RISCVISD::VDOT4AU_VL;
10125 break;
10127 Opc = RISCVISD::VDOT4ASU_VL;
10128 break;
10129 default:
10130 llvm_unreachable("Unexpected opcode");
10131 }
10132 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
10133 SDValue Res = DAG.getNode(Opc, DL, ContainerVT, {A, B, Accum, Mask, VL});
10134 if (VT.isFixedLengthVector())
10135 Res = convertFromScalableVector(VT, Res, DAG, Subtarget);
10136 return Res;
10137}
10138
10140 SelectionDAG &DAG, unsigned Flags) {
10141 return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);
10142}
10143
10145 SelectionDAG &DAG, unsigned Flags) {
10146 return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(),
10147 Flags);
10148}
10149
10151 SelectionDAG &DAG, unsigned Flags) {
10152 return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(),
10153 N->getOffset(), Flags);
10154}
10155
10157 SelectionDAG &DAG, unsigned Flags) {
10158 return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags);
10159}
10160
10162 EVT Ty, SelectionDAG &DAG) {
10164 SDValue CPAddr = DAG.getTargetConstantPool(CPV, Ty, Align(8));
10165 SDValue LC = DAG.getNode(RISCVISD::LLA, DL, Ty, CPAddr);
10166 return DAG.getLoad(
10167 Ty, DL, DAG.getEntryNode(), LC,
10169}
10170
10172 EVT Ty, SelectionDAG &DAG) {
10174 RISCVConstantPoolValue::Create(*DAG.getContext(), N->getSymbol());
10175 SDValue CPAddr = DAG.getTargetConstantPool(CPV, Ty, Align(8));
10176 SDValue LC = DAG.getNode(RISCVISD::LLA, DL, Ty, CPAddr);
10177 return DAG.getLoad(
10178 Ty, DL, DAG.getEntryNode(), LC,
10180}
10181
10182template <class NodeTy>
10183SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
10184 bool IsLocal, bool IsExternWeak) const {
10185 SDLoc DL(N);
10186 EVT Ty = getPointerTy(DAG.getDataLayout());
10187
10188 // When HWASAN is used and tagging of global variables is enabled
10189 // they should be accessed via the GOT, since the tagged address of a global
10190 // is incompatible with existing code models. This also applies to non-pic
10191 // mode.
10192 if (isPositionIndependent() || Subtarget.allowTaggedGlobals()) {
10193 SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
10194 if (IsLocal && !Subtarget.allowTaggedGlobals())
10195 // Use PC-relative addressing to access the symbol. This generates the
10196 // pattern (PseudoLLA sym), which expands to (addi (auipc %pcrel_hi(sym))
10197 // %pcrel_lo(auipc)).
10198 return DAG.getNode(RISCVISD::LLA, DL, Ty, Addr);
10199
10200 // Use PC-relative addressing to access the GOT for this symbol, then load
10201 // the address from the GOT. This generates the pattern (PseudoLGA sym),
10202 // which expands to (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(auipc))).
10203 SDValue Load =
10204 SDValue(DAG.getMachineNode(RISCV::PseudoLGA, DL, Ty, Addr), 0);
10206 MachineMemOperand *MemOp = MF.getMachineMemOperand(
10210 LLT(Ty.getSimpleVT()), Align(Ty.getFixedSizeInBits() / 8));
10211 DAG.setNodeMemRefs(cast<MachineSDNode>(Load.getNode()), {MemOp});
10212 return Load;
10213 }
10214
10215 switch (getTargetMachine().getCodeModel()) {
10216 default:
10217 reportFatalUsageError("Unsupported code model for lowering");
10218 case CodeModel::Small: {
10219 // Generate a sequence for accessing addresses within the first 2 GiB of
10220 // address space.
10221 if (Subtarget.hasVendorXqcili()) {
10222 // Use QC.E.LI to generate the address, as this is easier to relax than
10223 // LUI/ADDI.
10224 SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
10225 return DAG.getNode(RISCVISD::QC_E_LI, DL, Ty, Addr);
10226 }
10227
10228 // This generates the pattern (addi (lui %hi(sym)) %lo(sym)).
10229 SDValue AddrHi = getTargetNode(N, DL, Ty, DAG, RISCVII::MO_HI);
10230 SDValue AddrLo = getTargetNode(N, DL, Ty, DAG, RISCVII::MO_LO);
10231 SDValue MNHi = DAG.getNode(RISCVISD::HI, DL, Ty, AddrHi);
10232 return DAG.getNode(RISCVISD::ADD_LO, DL, Ty, MNHi, AddrLo);
10233 }
10234 case CodeModel::Medium: {
10235 SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
10236 if (IsExternWeak) {
10237 // An extern weak symbol may be undefined, i.e. have value 0, which may
10238 // not be within 2GiB of PC, so use GOT-indirect addressing to access the
10239 // symbol. This generates the pattern (PseudoLGA sym), which expands to
10240 // (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(auipc))).
10241 SDValue Load =
10242 SDValue(DAG.getMachineNode(RISCV::PseudoLGA, DL, Ty, Addr), 0);
10244 MachineMemOperand *MemOp = MF.getMachineMemOperand(
10248 LLT(Ty.getSimpleVT()), Align(Ty.getFixedSizeInBits() / 8));
10249 DAG.setNodeMemRefs(cast<MachineSDNode>(Load.getNode()), {MemOp});
10250 return Load;
10251 }
10252
10253 // Generate a sequence for accessing addresses within any 2GiB range within
10254 // the address space. This generates the pattern (PseudoLLA sym), which
10255 // expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
10256 return DAG.getNode(RISCVISD::LLA, DL, Ty, Addr);
10257 }
10258 case CodeModel::Large: {
10259 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N))
10260 return getLargeGlobalAddress(G, DL, Ty, DAG);
10261
10262 // Using pc-relative mode for other node type.
10263 SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
10264 return DAG.getNode(RISCVISD::LLA, DL, Ty, Addr);
10265 }
10266 }
10267}
10268
10269SDValue RISCVTargetLowering::lowerGlobalAddress(SDValue Op,
10270 SelectionDAG &DAG) const {
10271 GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
10272 assert(N->getOffset() == 0 && "unexpected offset in global node");
10273 const GlobalValue *GV = N->getGlobal();
10274 bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV);
10275 return getAddr(N, DAG, IsLocal, GV->hasExternalWeakLinkage());
10276}
10277
10278SDValue RISCVTargetLowering::lowerBlockAddress(SDValue Op,
10279 SelectionDAG &DAG) const {
10280 BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op);
10281
10282 return getAddr(N, DAG);
10283}
10284
10285SDValue RISCVTargetLowering::lowerConstantPool(SDValue Op,
10286 SelectionDAG &DAG) const {
10287 ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
10288
10289 return getAddr(N, DAG);
10290}
10291
10292SDValue RISCVTargetLowering::lowerJumpTable(SDValue Op,
10293 SelectionDAG &DAG) const {
10294 JumpTableSDNode *N = cast<JumpTableSDNode>(Op);
10295
10296 return getAddr(N, DAG);
10297}
10298
10299SDValue RISCVTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N,
10300 SelectionDAG &DAG,
10301 bool UseGOT) const {
10302 SDLoc DL(N);
10303 EVT Ty = getPointerTy(DAG.getDataLayout());
10304 const GlobalValue *GV = N->getGlobal();
10305 MVT XLenVT = Subtarget.getXLenVT();
10306
10307 if (UseGOT) {
10308 // Use PC-relative addressing to access the GOT for this TLS symbol, then
10309 // load the address from the GOT and add the thread pointer. This generates
10310 // the pattern (PseudoLA_TLS_IE sym), which expands to
10311 // (ld (auipc %tls_ie_pcrel_hi(sym)) %pcrel_lo(auipc)).
10312 SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, Ty, 0, 0);
10313 SDValue Load =
10314 SDValue(DAG.getMachineNode(RISCV::PseudoLA_TLS_IE, DL, Ty, Addr), 0);
10316 MachineMemOperand *MemOp = MF.getMachineMemOperand(
10320 LLT(Ty.getSimpleVT()), Align(Ty.getFixedSizeInBits() / 8));
10321 DAG.setNodeMemRefs(cast<MachineSDNode>(Load.getNode()), {MemOp});
10322
10323 // Add the thread pointer.
10324 SDValue TPReg = DAG.getRegister(RISCV::X4, XLenVT);
10325 return DAG.getNode(ISD::ADD, DL, Ty, Load, TPReg);
10326 }
10327
10328 // Generate a sequence for accessing the address relative to the thread
10329 // pointer, with the appropriate adjustment for the thread pointer offset.
10330 // This generates the pattern
10331 // (add (add_tprel (lui %tprel_hi(sym)) tp %tprel_add(sym)) %tprel_lo(sym))
10332 SDValue AddrHi =
10334 SDValue AddrAdd =
10336 SDValue AddrLo =
10338
10339 SDValue MNHi = DAG.getNode(RISCVISD::HI, DL, Ty, AddrHi);
10340 SDValue TPReg = DAG.getRegister(RISCV::X4, XLenVT);
10341 SDValue MNAdd =
10342 DAG.getNode(RISCVISD::ADD_TPREL, DL, Ty, MNHi, TPReg, AddrAdd);
10343 return DAG.getNode(RISCVISD::ADD_LO, DL, Ty, MNAdd, AddrLo);
10344}
10345
10346SDValue RISCVTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N,
10347 SelectionDAG &DAG) const {
10348 SDLoc DL(N);
10349 EVT Ty = getPointerTy(DAG.getDataLayout());
10350 IntegerType *CallTy = Type::getIntNTy(*DAG.getContext(), Ty.getSizeInBits());
10351 const GlobalValue *GV = N->getGlobal();
10352
10353 // Use a PC-relative addressing mode to access the global dynamic GOT address.
10354 // This generates the pattern (PseudoLA_TLS_GD sym), which expands to
10355 // (addi (auipc %tls_gd_pcrel_hi(sym)) %pcrel_lo(auipc)).
10356 SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, Ty, 0, 0);
10357 SDValue Load =
10358 SDValue(DAG.getMachineNode(RISCV::PseudoLA_TLS_GD, DL, Ty, Addr), 0);
10359
10360 // Prepare argument list to generate call.
10362 Args.emplace_back(Load, CallTy);
10363
10364 // Setup call to __tls_get_addr.
10365 TargetLowering::CallLoweringInfo CLI(DAG);
10366 CLI.setDebugLoc(DL)
10367 .setChain(DAG.getEntryNode())
10368 .setLibCallee(CallingConv::C, CallTy,
10369 DAG.getExternalSymbol("__tls_get_addr", Ty),
10370 std::move(Args));
10371
10372 return LowerCallTo(CLI).first;
10373}
10374
10375SDValue RISCVTargetLowering::getTLSDescAddr(GlobalAddressSDNode *N,
10376 SelectionDAG &DAG) const {
10377 SDLoc DL(N);
10378 EVT Ty = getPointerTy(DAG.getDataLayout());
10379 const GlobalValue *GV = N->getGlobal();
10380
10381 // Use a PC-relative addressing mode to access the global dynamic GOT address.
10382 // This generates the pattern (PseudoLA_TLSDESC sym), which expands to
10383 //
10384 // auipc tX, %tlsdesc_hi(symbol) // R_RISCV_TLSDESC_HI20(symbol)
10385 // lw tY, tX, %tlsdesc_load_lo(label) // R_RISCV_TLSDESC_LOAD_LO12(label)
10386 // addi a0, tX, %tlsdesc_add_lo(label) // R_RISCV_TLSDESC_ADD_LO12(label)
10387 // jalr t0, tY // R_RISCV_TLSDESC_CALL(label)
10388 SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, Ty, 0, 0);
10389 return SDValue(DAG.getMachineNode(RISCV::PseudoLA_TLSDESC, DL, Ty, Addr), 0);
10390}
10391
10392SDValue RISCVTargetLowering::lowerGlobalTLSAddress(SDValue Op,
10393 SelectionDAG &DAG) const {
10394 GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
10395 assert(N->getOffset() == 0 && "unexpected offset in global node");
10396
10397 if (DAG.getTarget().useEmulatedTLS())
10398 return LowerToTLSEmulatedModel(N, DAG);
10399
10401
10404 reportFatalUsageError("In GHC calling convention TLS is not supported");
10405
10406 SDValue Addr;
10407 switch (Model) {
10409 Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/false);
10410 break;
10412 Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/true);
10413 break;
10416 Addr = DAG.getTarget().useTLSDESC() ? getTLSDescAddr(N, DAG)
10417 : getDynamicTLSAddr(N, DAG);
10418 break;
10419 }
10420
10421 return Addr;
10422}
10423
10424// Return true if Val is equal to (setcc LHS, RHS, CC).
10425// Return false if Val is the inverse of (setcc LHS, RHS, CC).
10426// Otherwise, return std::nullopt.
10427static std::optional<bool> matchSetCC(SDValue LHS, SDValue RHS,
10428 ISD::CondCode CC, SDValue Val) {
10429 assert(Val->getOpcode() == ISD::SETCC);
10430 SDValue LHS2 = Val.getOperand(0);
10431 SDValue RHS2 = Val.getOperand(1);
10432 ISD::CondCode CC2 = cast<CondCodeSDNode>(Val.getOperand(2))->get();
10433
10434 if (LHS == LHS2 && RHS == RHS2) {
10435 if (CC == CC2)
10436 return true;
10437 if (CC == ISD::getSetCCInverse(CC2, LHS2.getValueType()))
10438 return false;
10439 } else if (LHS == RHS2 && RHS == LHS2) {
10441 if (CC == CC2)
10442 return true;
10443 if (CC == ISD::getSetCCInverse(CC2, LHS2.getValueType()))
10444 return false;
10445 }
10446
10447 return std::nullopt;
10448}
10449
10451 return isa<ConstantSDNode>(V) && V->getAsAPIntVal().isSignedIntN(12);
10452}
10453
10455 const RISCVSubtarget &Subtarget) {
10456 SDValue CondV = N->getOperand(0);
10457 SDValue TrueV = N->getOperand(1);
10458 SDValue FalseV = N->getOperand(2);
10459 MVT VT = N->getSimpleValueType(0);
10460 SDLoc DL(N);
10461
10462 if (!Subtarget.hasConditionalMoveFusion()) {
10463 // (select c, -1, y) -> -c | y
10464 if (isAllOnesConstant(TrueV)) {
10465 SDValue Neg = DAG.getNegative(CondV, DL, VT);
10466 return DAG.getNode(ISD::OR, DL, VT, Neg, DAG.getFreeze(FalseV));
10467 }
10468 // (select c, y, -1) -> (c-1) | y
10469 if (isAllOnesConstant(FalseV)) {
10470 SDValue Neg = DAG.getNode(ISD::ADD, DL, VT, CondV,
10471 DAG.getAllOnesConstant(DL, VT));
10472 return DAG.getNode(ISD::OR, DL, VT, Neg, DAG.getFreeze(TrueV));
10473 }
10474
10475 const bool HasZicond = VT.isScalarInteger() && Subtarget.hasStdExtZicond();
10476
10477 // (select c, 0, y) -> (c-1) & y
10478 if (isNullConstant(TrueV) && (!HasZicond || isSimm12Constant(FalseV))) {
10479 SDValue Neg =
10480 DAG.getNode(ISD::ADD, DL, VT, CondV, DAG.getAllOnesConstant(DL, VT));
10481 return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(FalseV));
10482 }
10483 if (isNullConstant(FalseV)) {
10484 if (auto *TrueC = dyn_cast<ConstantSDNode>(TrueV)) {
10485 // (select c, y, 0) -> (c * (y - 1)) + c
10486 int64_t MulImm = TrueC->getSExtValue();
10487 if (MulImm != INT64_MIN && isInt<12>(MulImm - 1) &&
10488 Subtarget.hasVendorXqciac())
10489 return DAG.getNode(RISCVISD::QC_MULIADD, DL, VT, CondV, CondV,
10490 DAG.getSignedTargetConstant(MulImm - 1, DL, VT));
10491
10492 // (select c, (1 << ShAmount), 0) -> c << ShAmount
10493 uint64_t TrueVal = TrueC->getZExtValue();
10494 if (isPowerOf2_64(TrueVal))
10495 return DAG.getNode(
10496 ISD::SHL, DL, VT, CondV,
10497 DAG.getShiftAmountConstant(Log2_64(TrueVal), VT, DL));
10498
10499 // (select c, (1 << ShAmount) + 1, 0) -> (c << ShAmount) + c
10500 uint64_t TrueM1 = TrueVal - 1;
10501 if (isPowerOf2_64(TrueM1)) {
10502 unsigned ShAmount = Log2_64(TrueM1);
10503 if (Subtarget.hasShlAdd(ShAmount))
10504 return DAG.getNode(RISCVISD::SHL_ADD, DL, VT, CondV,
10505 DAG.getTargetConstant(ShAmount, DL, VT), CondV);
10506 }
10507 }
10508 // (select c, y, 0) -> -c & y
10509 if (!HasZicond || isSimm12Constant(TrueV)) {
10510 SDValue Neg = DAG.getNegative(CondV, DL, VT);
10511 return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(TrueV));
10512 }
10513 }
10514 }
10515
10516 // select c, ~x, x --> xor -c, x
10517 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
10518 const APInt &TrueVal = TrueV->getAsAPIntVal();
10519 const APInt &FalseVal = FalseV->getAsAPIntVal();
10520 if (~TrueVal == FalseVal) {
10521 SDValue Neg = DAG.getNegative(CondV, DL, VT);
10522 return DAG.getNode(ISD::XOR, DL, VT, Neg, FalseV);
10523 }
10524 }
10525
10526 // Try to fold (select (setcc lhs, rhs, cc), truev, falsev) into bitwise ops
10527 // when both truev and falsev are also setcc.
10528 if (CondV.getOpcode() == ISD::SETCC && TrueV.getOpcode() == ISD::SETCC &&
10529 FalseV.getOpcode() == ISD::SETCC) {
10530 SDValue LHS = CondV.getOperand(0);
10531 SDValue RHS = CondV.getOperand(1);
10532 ISD::CondCode CC = cast<CondCodeSDNode>(CondV.getOperand(2))->get();
10533
10534 // (select x, x, y) -> x | y
10535 // (select !x, x, y) -> x & y
10536 if (std::optional<bool> MatchResult = matchSetCC(LHS, RHS, CC, TrueV)) {
10537 return DAG.getNode(*MatchResult ? ISD::OR : ISD::AND, DL, VT, TrueV,
10538 DAG.getFreeze(FalseV));
10539 }
10540 // (select x, y, x) -> x & y
10541 // (select !x, y, x) -> x | y
10542 if (std::optional<bool> MatchResult = matchSetCC(LHS, RHS, CC, FalseV)) {
10543 return DAG.getNode(*MatchResult ? ISD::AND : ISD::OR, DL, VT,
10544 DAG.getFreeze(TrueV), FalseV);
10545 }
10546 }
10547
10548 return SDValue();
10549}
10550
10551// Transform `binOp (select cond, x, c0), c1` where `c0` and `c1` are constants
10552// into `select cond, binOp(x, c1), binOp(c0, c1)` if profitable.
10553// For now we only consider transformation profitable if `binOp(c0, c1)` ends up
10554// being `0` or `-1`. In such cases we can replace `select` with `and`.
10555// TODO: Should we also do this if `binOp(c0, c1)` is cheaper to materialize
10556// than `c0`?
10557static SDValue
10559 const RISCVSubtarget &Subtarget) {
10560 if (Subtarget.hasShortForwardBranchIALU())
10561 return SDValue();
10562
10563 unsigned SelOpNo = 0;
10564 SDValue Sel = BO->getOperand(0);
10565 if (Sel.getOpcode() != ISD::SELECT || !Sel.hasOneUse()) {
10566 SelOpNo = 1;
10567 Sel = BO->getOperand(1);
10568 }
10569
10570 if (Sel.getOpcode() != ISD::SELECT || !Sel.hasOneUse())
10571 return SDValue();
10572
10573 unsigned ConstSelOpNo = 1;
10574 unsigned OtherSelOpNo = 2;
10575 if (!isa<ConstantSDNode>(Sel->getOperand(ConstSelOpNo))) {
10576 ConstSelOpNo = 2;
10577 OtherSelOpNo = 1;
10578 }
10579 SDValue ConstSelOp = Sel->getOperand(ConstSelOpNo);
10580 ConstantSDNode *ConstSelOpNode = dyn_cast<ConstantSDNode>(ConstSelOp);
10581 if (!ConstSelOpNode || ConstSelOpNode->isOpaque())
10582 return SDValue();
10583
10584 SDValue ConstBinOp = BO->getOperand(SelOpNo ^ 1);
10585 ConstantSDNode *ConstBinOpNode = dyn_cast<ConstantSDNode>(ConstBinOp);
10586 if (!ConstBinOpNode || ConstBinOpNode->isOpaque())
10587 return SDValue();
10588
10589 SDLoc DL(Sel);
10590 EVT VT = BO->getValueType(0);
10591
10592 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
10593 if (SelOpNo == 1)
10594 std::swap(NewConstOps[0], NewConstOps[1]);
10595
10596 SDValue NewConstOp =
10597 DAG.FoldConstantArithmetic(BO->getOpcode(), DL, VT, NewConstOps);
10598 if (!NewConstOp)
10599 return SDValue();
10600
10601 const APInt &NewConstAPInt = NewConstOp->getAsAPIntVal();
10602 if (!NewConstAPInt.isZero() && !NewConstAPInt.isAllOnes())
10603 return SDValue();
10604
10605 SDValue OtherSelOp = Sel->getOperand(OtherSelOpNo);
10606 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
10607 if (SelOpNo == 1)
10608 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
10609 SDValue NewNonConstOp = DAG.getNode(BO->getOpcode(), DL, VT, NewNonConstOps);
10610
10611 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
10612 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
10613 return DAG.getSelect(DL, VT, Sel.getOperand(0), NewT, NewF);
10614}
10615
10616SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
10617 SDValue CondV = Op.getOperand(0);
10618 SDValue TrueV = Op.getOperand(1);
10619 SDValue FalseV = Op.getOperand(2);
10620 SDLoc DL(Op);
10621 MVT VT = Op.getSimpleValueType();
10622 MVT XLenVT = Subtarget.getXLenVT();
10623
10624 // Handle P extension packed types by bitcasting to an integer of
10625 // matching width and reusing the scalar selection mechanism.
10626 // Reachable cases:
10627 // RV32: v4i8/v2i16 -> select on i32
10628 // RV32: v8i8/v4i16 -> select on i64 (legalizes to two i32 selects)
10629 // RV64: v8i8/v4i16/v2i32 -> select on i64
10630 if (Subtarget.isPExtPackedType(VT)) {
10631 MVT IntVT = MVT::getIntegerVT(VT.getSizeInBits());
10632 SDValue TrueVInt = DAG.getBitcast(IntVT, TrueV);
10633 SDValue FalseVInt = DAG.getBitcast(IntVT, FalseV);
10634 SDValue ResultInt =
10635 DAG.getNode(ISD::SELECT, DL, IntVT, CondV, TrueVInt, FalseVInt);
10636 return DAG.getBitcast(VT, ResultInt);
10637 }
10638
10639 // Lower vector SELECTs to VSELECTs by splatting the condition.
10640 if (VT.isVector()) {
10641 MVT SplatCondVT = VT.changeVectorElementType(MVT::i1);
10642 SDValue CondSplat = DAG.getSplat(SplatCondVT, DL, CondV);
10643 return DAG.getNode(ISD::VSELECT, DL, VT, CondSplat, TrueV, FalseV);
10644 }
10645
10646 // Try some other optimizations before falling back to generic lowering.
10647 if (SDValue V = lowerSelectToBinOp(Op.getNode(), DAG, Subtarget))
10648 return V;
10649
10650 // When there is no cost for GPR <-> FPR, we can use zicond select for
10651 // floating value when CondV is int type
10652 bool FPinGPR = Subtarget.hasStdExtZfinx();
10653
10654 // We can handle FGPR without spliting into hi/lo parts
10655 bool FitsInGPR = TypeSize::isKnownLE(VT.getSizeInBits(),
10656 Subtarget.getXLenVT().getSizeInBits());
10657
10658 bool UseZicondForFPSel = Subtarget.hasStdExtZicond() && FPinGPR &&
10659 VT.isFloatingPoint() && FitsInGPR;
10660
10661 if (UseZicondForFPSel) {
10662
10663 auto CastToInt = [&](SDValue V) -> SDValue {
10664 // Treat +0.0 as int 0 to enable single 'czero' instruction generation.
10665 if (isNullFPConstant(V))
10666 return DAG.getConstant(0, DL, XLenVT);
10667
10668 if (VT == MVT::f16)
10669 return DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, XLenVT, V);
10670
10671 if (VT == MVT::f32 && Subtarget.is64Bit())
10672 return DAG.getNode(RISCVISD::FMV_X_ANYEXTW_RV64, DL, XLenVT, V);
10673
10674 return DAG.getBitcast(XLenVT, V);
10675 };
10676
10677 SDValue TrueVInt = CastToInt(TrueV);
10678 SDValue FalseVInt = CastToInt(FalseV);
10679
10680 // Emit integer SELECT (lowers to Zicond)
10681 SDValue ResultInt =
10682 DAG.getNode(ISD::SELECT, DL, XLenVT, CondV, TrueVInt, FalseVInt);
10683
10684 // Convert back to floating VT
10685 if (VT == MVT::f32 && Subtarget.is64Bit())
10686 return DAG.getNode(RISCVISD::FMV_W_X_RV64, DL, VT, ResultInt);
10687
10688 if (VT == MVT::f16)
10689 return DAG.getNode(RISCVISD::FMV_H_X, DL, VT, ResultInt);
10690
10691 return DAG.getBitcast(VT, ResultInt);
10692 }
10693
10694 // When Zicond is present, emit CZERO_EQZ and CZERO_NEZ
10695 // nodes to implement the SELECT. Performing the lowering here allows for
10696 // greater control over when CZERO_{EQZ/NEZ} are used vs another branchless
10697 // sequence or RISCVISD::SELECT_CC node (branch-based select).
10698 if (Subtarget.hasStdExtZicond() && VT.isScalarInteger()) {
10699
10700 // (select c, t, 0) -> (czero_eqz t, c)
10701 if (isNullConstant(FalseV))
10702 return DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV);
10703 // (select c, 0, f) -> (czero_nez f, c)
10704 if (isNullConstant(TrueV))
10705 return DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV);
10706
10707 // Check to see if a given operation is a 'NOT', if so return the negated
10708 // operand
10709 auto getNotOperand = [](const SDValue &Op) -> std::optional<const SDValue> {
10710 using namespace llvm::SDPatternMatch;
10711 SDValue Xor;
10712 if (sd_match(Op, m_OneUse(m_Not(m_Value(Xor))))) {
10713 return Xor;
10714 }
10715 return std::nullopt;
10716 };
10717 // (select c, (and f, x), f) -> (or (and f, x), (czero_nez f, c))
10718 // (select c, (and f, ~x), f) -> (andn f, (czero_eqz x, c))
10719 if (TrueV.getOpcode() == ISD::AND &&
10720 (TrueV.getOperand(0) == FalseV || TrueV.getOperand(1) == FalseV)) {
10721 auto NotOperand = (TrueV.getOperand(0) == FalseV)
10722 ? getNotOperand(TrueV.getOperand(1))
10723 : getNotOperand(TrueV.getOperand(0));
10724 if (NotOperand) {
10725 SDValue CMOV =
10726 DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, *NotOperand, CondV);
10727 SDValue NOT = DAG.getNOT(DL, CMOV, VT);
10728 return DAG.getNode(ISD::AND, DL, VT, FalseV, NOT);
10729 }
10730 return DAG.getNode(
10731 ISD::OR, DL, VT, TrueV,
10732 DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV));
10733 }
10734
10735 // (select c, t, (and t, x)) -> (or (czero_eqz t, c), (and t, x))
10736 // (select c, t, (and t, ~x)) -> (andn t, (czero_nez x, c))
10737 if (FalseV.getOpcode() == ISD::AND &&
10738 (FalseV.getOperand(0) == TrueV || FalseV.getOperand(1) == TrueV)) {
10739 auto NotOperand = (FalseV.getOperand(0) == TrueV)
10740 ? getNotOperand(FalseV.getOperand(1))
10741 : getNotOperand(FalseV.getOperand(0));
10742 if (NotOperand) {
10743 SDValue CMOV =
10744 DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, *NotOperand, CondV);
10745 SDValue NOT = DAG.getNOT(DL, CMOV, VT);
10746 return DAG.getNode(ISD::AND, DL, VT, TrueV, NOT);
10747 }
10748 return DAG.getNode(
10749 ISD::OR, DL, VT, FalseV,
10750 DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV));
10751 }
10752
10753 // (select c, c1, c2) -> (add (czero_nez c2 - c1, c), c1)
10754 // (select c, c1, c2) -> (add (czero_eqz c1 - c2, c), c2)
10755 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
10756 const APInt &TrueVal = TrueV->getAsAPIntVal();
10757 const APInt &FalseVal = FalseV->getAsAPIntVal();
10758
10759 // Prefer these over Zicond to avoid materializing an immediate:
10760 // (select (x < 0), y, z) -> x >> (XLEN - 1) & (y - z) + z
10761 // (select (x > -1), z, y) -> x >> (XLEN - 1) & (y - z) + z
10762 if (CondV.getOpcode() == ISD::SETCC &&
10763 CondV.getOperand(0).getValueType() == VT && CondV.hasOneUse()) {
10764 ISD::CondCode CCVal = cast<CondCodeSDNode>(CondV.getOperand(2))->get();
10765 if ((CCVal == ISD::SETLT && isNullConstant(CondV.getOperand(1))) ||
10766 (CCVal == ISD::SETGT && isAllOnesConstant(CondV.getOperand(1)))) {
10767 int64_t TrueImm = TrueVal.getSExtValue();
10768 int64_t FalseImm = FalseVal.getSExtValue();
10769 if (CCVal == ISD::SETGT)
10770 std::swap(TrueImm, FalseImm);
10771 if (isInt<12>(TrueImm) && isInt<12>(FalseImm) &&
10772 isInt<12>(TrueImm - FalseImm)) {
10773 SDValue SRA =
10774 DAG.getNode(ISD::SRA, DL, VT, CondV.getOperand(0),
10775 DAG.getConstant(Subtarget.getXLen() - 1, DL, VT));
10776 SDValue AND =
10777 DAG.getNode(ISD::AND, DL, VT, SRA,
10778 DAG.getSignedConstant(TrueImm - FalseImm, DL, VT));
10779 return DAG.getNode(ISD::ADD, DL, VT, AND,
10780 DAG.getSignedConstant(FalseImm, DL, VT));
10781 }
10782 }
10783 }
10784
10785 // Use SLLI/ADDI (and possible XORI) to avoid having to materialize
10786 // a constant in register
10787 if ((TrueVal - FalseVal).isPowerOf2() && FalseVal.isSignedIntN(12)) {
10788 SDValue Log2 = DAG.getConstant((TrueVal - FalseVal).logBase2(), DL, VT);
10789 SDValue BitDiff = DAG.getNode(ISD::SHL, DL, VT, CondV, Log2);
10790 return DAG.getNode(ISD::ADD, DL, VT, BitDiff, FalseV);
10791 }
10792 if ((FalseVal - TrueVal).isPowerOf2() && TrueVal.isSignedIntN(12)) {
10793 SDValue Log2 = DAG.getConstant((FalseVal - TrueVal).logBase2(), DL, VT);
10794 CondV = DAG.getLogicalNOT(DL, CondV, CondV.getValueType());
10795 SDValue BitDiff = DAG.getNode(ISD::SHL, DL, VT, CondV, Log2);
10796 return DAG.getNode(ISD::ADD, DL, VT, BitDiff, TrueV);
10797 }
10798
10799 // If we can't use ADDI, it might still be profitable to use SLLI/ADD or
10800 // SLLI/SUB. We need to materialize a large constant for the czero+add
10801 // sequence below anyway. Using SLLI avoids materializing the delta.
10802 // Don't do this if the condition is an equality comparison since czero
10803 // allows us to fold part of the compare.
10804 if ((TrueVal - FalseVal).isPowerOf2() &&
10805 !(CondV.getOpcode() == ISD::SETCC &&
10807 cast<CondCodeSDNode>(CondV.getOperand(2))->get()))) {
10808 SDValue Log2 = DAG.getConstant((TrueVal - FalseVal).logBase2(), DL, VT);
10809 SDValue BitDiff = DAG.getNode(ISD::SHL, DL, VT, CondV, Log2);
10810 return DAG.getNode(ISD::ADD, DL, VT, FalseV, BitDiff);
10811 }
10812 if ((FalseVal - TrueVal).isPowerOf2() && !FalseVal.isSignedIntN(12) &&
10813 !(CondV.getOpcode() == ISD::SETCC &&
10815 cast<CondCodeSDNode>(CondV.getOperand(2))->get()))) {
10816 SDValue Log2 = DAG.getConstant((FalseVal - TrueVal).logBase2(), DL, VT);
10817 SDValue BitDiff = DAG.getNode(ISD::SHL, DL, VT, CondV, Log2);
10818 return DAG.getNode(ISD::SUB, DL, VT, FalseV, BitDiff);
10819 }
10820
10821 auto getCost = [&](const APInt &Delta, const APInt &Addend) {
10822 const int DeltaCost = RISCVMatInt::getIntMatCost(
10823 Delta, Subtarget.getXLen(), Subtarget, /*CompressionCost=*/true);
10824 // Does the addend fold into an ADDI
10825 if (Addend.isSignedIntN(12))
10826 return DeltaCost;
10827 const int AddendCost = RISCVMatInt::getIntMatCost(
10828 Addend, Subtarget.getXLen(), Subtarget, /*CompressionCost=*/true);
10829 return AddendCost + DeltaCost;
10830 };
10831 bool IsCZERO_NEZ = getCost(FalseVal - TrueVal, TrueVal) <=
10832 getCost(TrueVal - FalseVal, FalseVal);
10833 SDValue LHSVal = DAG.getConstant(
10834 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal, DL, VT);
10835 SDValue CMOV =
10836 DAG.getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
10837 DL, VT, LHSVal, CondV);
10838 return DAG.getNode(ISD::ADD, DL, VT, CMOV, IsCZERO_NEZ ? TrueV : FalseV);
10839 }
10840
10841 // (select c, c1, t) -> (add (czero_nez t - c1, c), c1)
10842 // (select c, t, c1) -> (add (czero_eqz t - c1, c), c1)
10843 if (isa<ConstantSDNode>(TrueV) != isa<ConstantSDNode>(FalseV)) {
10844 bool IsCZERO_NEZ = isa<ConstantSDNode>(TrueV);
10845 SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
10846 SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
10847 int64_t RawConstVal = cast<ConstantSDNode>(ConstVal)->getSExtValue();
10848 // Efficient only if the constant and its negation fit into `ADDI`
10849 // Prefer Add/Sub over Xor since can be compressed for small immediates
10850 if (isInt<12>(RawConstVal)) {
10851 // Fall back to XORI if Const == -0x800 since we don't have SUBI.
10852 unsigned SubOpc = (RawConstVal == -0x800) ? ISD::XOR : ISD::SUB;
10853 unsigned AddOpc = (RawConstVal == -0x800) ? ISD::XOR : ISD::ADD;
10854 SDValue SubOp = DAG.getNode(SubOpc, DL, VT, RegV, ConstVal);
10855 SDValue CZERO =
10856 DAG.getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
10857 DL, VT, SubOp, CondV);
10858 return DAG.getNode(AddOpc, DL, VT, CZERO, ConstVal);
10859 }
10860 }
10861
10862 // Unless we have the short forward branch optimization, or we are
10863 // optimizing for size.
10864 if (!Subtarget.hasConditionalMoveFusion() && !DAG.shouldOptForSize()) {
10865 using namespace llvm::SDPatternMatch;
10866
10867 // (select c, x, -x) -> (sub (czero_eqz x, c), (czero_nez x, c))
10868 if (sd_match(FalseV, m_Neg(m_Specific(TrueV)))) {
10869 TrueV = DAG.getFreeze(TrueV);
10870 return DAG.getNode(
10871 ISD::SUB, DL, VT,
10872 DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV),
10873 DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, TrueV, CondV));
10874 }
10875 // (select c, -x, x) -> (sub (czero_nez x, c), (czero_eqz x, c))
10876 if (sd_match(TrueV, m_Neg(m_Specific(FalseV)))) {
10877 FalseV = DAG.getFreeze(FalseV);
10878 return DAG.getNode(
10879 ISD::SUB, DL, VT,
10880 DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV),
10881 DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, FalseV, CondV));
10882 }
10883
10884 // (select c, t, f) -> (or (czero_eqz t, c), (czero_nez f, c))
10885 return DAG.getNode(
10886 ISD::OR, DL, VT,
10887 DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV),
10888 DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV, CondV),
10890 }
10891 }
10892
10893 if (Op.hasOneUse()) {
10894 unsigned UseOpc = Op->user_begin()->getOpcode();
10895 if (isBinOp(UseOpc) && DAG.isSafeToSpeculativelyExecute(UseOpc)) {
10896 SDNode *BinOp = *Op->user_begin();
10897 if (SDValue NewSel = foldBinOpIntoSelectIfProfitable(*Op->user_begin(),
10898 DAG, Subtarget)) {
10899 DAG.ReplaceAllUsesWith(BinOp, &NewSel);
10900 // Opcode check is necessary because foldBinOpIntoSelectIfProfitable
10901 // may return a constant node and cause crash in lowerSELECT.
10902 if (NewSel.getOpcode() == ISD::SELECT)
10903 return lowerSELECT(NewSel, DAG);
10904 return NewSel;
10905 }
10906 }
10907 }
10908
10909 // (select cc, 1.0, 0.0) -> (sint_to_fp (zext cc))
10910 // (select cc, 0.0, 1.0) -> (sint_to_fp (zext (xor cc, 1)))
10911 const ConstantFPSDNode *FPTV = dyn_cast<ConstantFPSDNode>(TrueV);
10912 const ConstantFPSDNode *FPFV = dyn_cast<ConstantFPSDNode>(FalseV);
10913 if (FPTV && FPFV) {
10914 if (FPTV->isOne() && FPFV->isPosZero())
10915 return DAG.getNode(ISD::SINT_TO_FP, DL, VT, CondV);
10916 if (FPTV->isPosZero() && FPFV->isOne()) {
10917 SDValue XOR = DAG.getNode(ISD::XOR, DL, XLenVT, CondV,
10918 DAG.getConstant(1, DL, XLenVT));
10919 return DAG.getNode(ISD::SINT_TO_FP, DL, VT, XOR);
10920 }
10921 }
10922
10923 // If the condition is not an integer SETCC which operates on XLenVT, we need
10924 // to emit a RISCVISD::SELECT_CC comparing the condition to zero. i.e.:
10925 // (select condv, truev, falsev)
10926 // -> (riscvisd::select_cc condv, zero, setne, truev, falsev)
10927 if (CondV.getOpcode() != ISD::SETCC ||
10928 CondV.getOperand(0).getSimpleValueType() != XLenVT) {
10929 SDValue Zero = DAG.getConstant(0, DL, XLenVT);
10930 SDValue SetNE = DAG.getCondCode(ISD::SETNE);
10931
10932 SDValue Ops[] = {CondV, Zero, SetNE, TrueV, FalseV};
10933
10934 return DAG.getNode(RISCVISD::SELECT_CC, DL, VT, Ops);
10935 }
10936
10937 // If the CondV is the output of a SETCC node which operates on XLenVT inputs,
10938 // then merge the SETCC node into the lowered RISCVISD::SELECT_CC to take
10939 // advantage of the integer compare+branch instructions. i.e.:
10940 // (select (setcc lhs, rhs, cc), truev, falsev)
10941 // -> (riscvisd::select_cc lhs, rhs, cc, truev, falsev)
10942 SDValue LHS = CondV.getOperand(0);
10943 SDValue RHS = CondV.getOperand(1);
10944 ISD::CondCode CCVal = cast<CondCodeSDNode>(CondV.getOperand(2))->get();
10945
10946 // Special case for a select of 2 constants that have a difference of 1.
10947 // Normally this is done by DAGCombine, but if the select is introduced by
10948 // type legalization or op legalization, we miss it. Restricting to SETLT
10949 // case for now because that is what signed saturating add/sub need.
10950 // FIXME: We don't need the condition to be SETLT or even a SETCC,
10951 // but we would probably want to swap the true/false values if the condition
10952 // is SETGE/SETLE to avoid an XORI.
10953 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
10954 CCVal == ISD::SETLT) {
10955 const APInt &TrueVal = TrueV->getAsAPIntVal();
10956 const APInt &FalseVal = FalseV->getAsAPIntVal();
10957 if (TrueVal - 1 == FalseVal)
10958 return DAG.getNode(ISD::ADD, DL, VT, CondV, FalseV);
10959 if (TrueVal + 1 == FalseVal)
10960 return DAG.getNode(ISD::SUB, DL, VT, FalseV, CondV);
10961 }
10962
10963 translateSetCCForBranch(DL, LHS, RHS, CCVal, DAG, Subtarget);
10964 // 1 < x ? x : 1 -> 0 < x ? x : 1
10965 if (isOneConstant(LHS) && (CCVal == ISD::SETLT || CCVal == ISD::SETULT) &&
10966 RHS == TrueV && LHS == FalseV) {
10967 LHS = DAG.getConstant(0, DL, VT);
10968 // 0 <u x is the same as x != 0.
10969 if (CCVal == ISD::SETULT) {
10970 std::swap(LHS, RHS);
10971 CCVal = ISD::SETNE;
10972 }
10973 }
10974
10975 // x <s -1 ? x : -1 -> x <s 0 ? x : -1
10976 if (isAllOnesConstant(RHS) && CCVal == ISD::SETLT && LHS == TrueV &&
10977 RHS == FalseV) {
10978 RHS = DAG.getConstant(0, DL, VT);
10979 }
10980
10981 SDValue TargetCC = DAG.getCondCode(CCVal);
10982
10983 if (isa<ConstantSDNode>(TrueV) && !isa<ConstantSDNode>(FalseV)) {
10984 // (select (setcc lhs, rhs, CC), constant, falsev)
10985 // -> (select (setcc lhs, rhs, InverseCC), falsev, constant)
10986 std::swap(TrueV, FalseV);
10987 TargetCC = DAG.getCondCode(ISD::getSetCCInverse(CCVal, LHS.getValueType()));
10988 }
10989
10990 SDValue Ops[] = {LHS, RHS, TargetCC, TrueV, FalseV};
10991 return DAG.getNode(RISCVISD::SELECT_CC, DL, VT, Ops);
10992}
10993
10994SDValue RISCVTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
10995 SDValue CondV = Op.getOperand(1);
10996 SDLoc DL(Op);
10997 MVT XLenVT = Subtarget.getXLenVT();
10998
10999 if (CondV.getOpcode() == ISD::SETCC &&
11000 CondV.getOperand(0).getValueType() == XLenVT) {
11001 SDValue LHS = CondV.getOperand(0);
11002 SDValue RHS = CondV.getOperand(1);
11003 ISD::CondCode CCVal = cast<CondCodeSDNode>(CondV.getOperand(2))->get();
11004
11005 translateSetCCForBranch(DL, LHS, RHS, CCVal, DAG, Subtarget);
11006
11007 SDValue TargetCC = DAG.getCondCode(CCVal);
11008 return DAG.getNode(RISCVISD::BR_CC, DL, Op.getValueType(), Op.getOperand(0),
11009 LHS, RHS, TargetCC, Op.getOperand(2));
11010 }
11011
11012 return DAG.getNode(RISCVISD::BR_CC, DL, Op.getValueType(), Op.getOperand(0),
11013 CondV, DAG.getConstant(0, DL, XLenVT),
11014 DAG.getCondCode(ISD::SETNE), Op.getOperand(2));
11015}
11016
11017SDValue RISCVTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const {
11019 RISCVMachineFunctionInfo *FuncInfo = MF.getInfo<RISCVMachineFunctionInfo>();
11020
11021 SDLoc DL(Op);
11022 SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(),
11024
11025 // vastart just stores the address of the VarArgsFrameIndex slot into the
11026 // memory location argument.
11027 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
11028 return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1),
11029 MachinePointerInfo(SV));
11030}
11031
11032SDValue RISCVTargetLowering::lowerFRAMEADDR(SDValue Op,
11033 SelectionDAG &DAG) const {
11034 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
11036 MachineFrameInfo &MFI = MF.getFrameInfo();
11037 MFI.setFrameAddressIsTaken(true);
11038 Register FrameReg = RI.getFrameRegister(MF);
11039 int XLenInBytes = Subtarget.getXLen() / 8;
11040
11041 EVT VT = Op.getValueType();
11042 SDLoc DL(Op);
11043 SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), DL, FrameReg, VT);
11044 unsigned Depth = Op.getConstantOperandVal(0);
11045 while (Depth--) {
11046 int Offset = -(XLenInBytes * 2);
11047 SDValue Ptr = DAG.getNode(
11048 ISD::ADD, DL, VT, FrameAddr,
11050 FrameAddr =
11051 DAG.getLoad(VT, DL, DAG.getEntryNode(), Ptr, MachinePointerInfo());
11052 }
11053 return FrameAddr;
11054}
11055
11056SDValue RISCVTargetLowering::lowerRETURNADDR(SDValue Op,
11057 SelectionDAG &DAG) const {
11058 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
11060 MachineFrameInfo &MFI = MF.getFrameInfo();
11061 MFI.setReturnAddressIsTaken(true);
11062 MVT XLenVT = Subtarget.getXLenVT();
11063 int XLenInBytes = Subtarget.getXLen() / 8;
11064
11065 EVT VT = Op.getValueType();
11066 SDLoc DL(Op);
11067 unsigned Depth = Op.getConstantOperandVal(0);
11068 if (Depth) {
11069 int Off = -XLenInBytes;
11070 SDValue FrameAddr = lowerFRAMEADDR(Op, DAG);
11071 SDValue Offset = DAG.getSignedConstant(Off, DL, VT);
11072 return DAG.getLoad(VT, DL, DAG.getEntryNode(),
11073 DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset),
11074 MachinePointerInfo());
11075 }
11076
11077 // Return the value of the return address register, marking it an implicit
11078 // live-in.
11079 Register Reg = MF.addLiveIn(RI.getRARegister(), getRegClassFor(XLenVT));
11080 return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, XLenVT);
11081}
11082
11083SDValue RISCVTargetLowering::lowerShiftLeftParts(SDValue Op,
11084 SelectionDAG &DAG) const {
11085 SDLoc DL(Op);
11086 SDValue Lo = Op.getOperand(0);
11087 SDValue Hi = Op.getOperand(1);
11088 SDValue Shamt = Op.getOperand(2);
11089 EVT VT = Lo.getValueType();
11090 unsigned XLen = Subtarget.getXLen();
11091
11092 // With P extension, use SLX (FSHL) for the high part.
11093 if (Subtarget.hasStdExtP()) {
11094 // HiRes = fshl(Hi, Lo, Shamt) - correct when Shamt < XLen
11095 SDValue HiRes = DAG.getNode(ISD::FSHL, DL, VT, Hi, Lo, Shamt);
11096 // LoRes = Lo << Shamt - correct Lo when Shamt < XLen,
11097 // Mask shift amount to avoid UB when Shamt >= XLen.
11098 SDValue ShamtMasked =
11099 DAG.getNode(ISD::AND, DL, VT, Shamt, DAG.getConstant(XLen - 1, DL, VT));
11100 SDValue LoRes = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMasked);
11101
11102 // Create a mask that is -1 when Shamt >= XLen, 0 otherwise.
11103 // FIXME: We should use a select and let LowerSelect make the
11104 // optimizations.
11105 SDValue ShAmtExt =
11106 DAG.getNode(ISD::SHL, DL, VT, Shamt,
11107 DAG.getConstant(XLen - Log2_32(XLen) - 1, DL, VT));
11108 SDValue Mask = DAG.getNode(ISD::SRA, DL, VT, ShAmtExt,
11109 DAG.getConstant(XLen - 1, DL, VT));
11110
11111 // When Shamt >= XLen: HiRes = LoRes, LoRes = 0
11112 // HiRes = (HiRes & ~Mask) | (LoRes & Mask)
11113 SDValue HiMasked =
11114 DAG.getNode(ISD::AND, DL, VT, HiRes, DAG.getNOT(DL, Mask, VT));
11115 SDValue LoMasked = DAG.getNode(ISD::AND, DL, VT, LoRes, Mask);
11116 HiRes =
11117 DAG.getNode(ISD::OR, DL, VT, HiMasked, LoMasked, SDNodeFlags::Disjoint);
11118
11119 // LoRes = LoRes & ~Mask (clear when Shamt >= XLen)
11120 LoRes = DAG.getNode(ISD::AND, DL, VT, LoRes, DAG.getNOT(DL, Mask, VT));
11121
11122 return DAG.getMergeValues({LoRes, HiRes}, DL);
11123 }
11124
11125 // if Shamt-XLEN < 0: // Shamt < XLEN
11126 // Lo = Lo << Shamt
11127 // Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (XLEN-1 - Shamt))
11128 // else:
11129 // Lo = 0
11130 // Hi = Lo << (Shamt-XLEN)
11131
11132 SDValue Zero = DAG.getConstant(0, DL, VT);
11133 SDValue One = DAG.getConstant(1, DL, VT);
11134 SDValue MinusXLen = DAG.getSignedConstant(-(int)XLen, DL, VT);
11135 SDValue XLenMinus1 = DAG.getConstant(XLen - 1, DL, VT);
11136 SDValue ShamtMinusXLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusXLen);
11137 SDValue XLenMinus1Shamt = DAG.getNode(ISD::SUB, DL, VT, XLenMinus1, Shamt);
11138
11139 SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt);
11140 SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, One);
11141 SDValue ShiftRightLo =
11142 DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, XLenMinus1Shamt);
11143 SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt);
11144 SDValue HiTrue = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo);
11145 SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusXLen);
11146
11147 SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusXLen, Zero, ISD::SETLT);
11148
11149 Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, Zero);
11150 Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse);
11151
11152 SDValue Parts[2] = {Lo, Hi};
11153 return DAG.getMergeValues(Parts, DL);
11154}
11155
11156SDValue RISCVTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG,
11157 bool IsSRA) const {
11158 SDLoc DL(Op);
11159 SDValue Lo = Op.getOperand(0);
11160 SDValue Hi = Op.getOperand(1);
11161 SDValue Shamt = Op.getOperand(2);
11162 EVT VT = Lo.getValueType();
11163
11164 // With P extension, use NSRL/NSRA for RV32 or FSHR (SRX) for RV64.
11165 if (Subtarget.hasStdExtP()) {
11166 unsigned XLen = Subtarget.getXLen();
11167
11168 SDValue LoRes;
11169 if (Subtarget.is64Bit()) {
11170 // On RV64, use FSHR (SRX instruction) for the low part. We will need
11171 // to fix this later if ShAmt >= 64.
11172 LoRes = DAG.getNode(ISD::FSHR, DL, VT, Hi, Lo, Shamt);
11173 } else {
11174 // On RV32, use NSRL/NSRA for the low part.
11175 // NSRL/NSRA read 6 bits of shift amount, so they handle Shamt >= 32
11176 // correctly.
11177 LoRes = DAG.getNode(IsSRA ? RISCVISD::NSRA : RISCVISD::NSRL, DL, VT, Lo,
11178 Hi, Shamt);
11179 }
11180
11181 // Mask shift amount to avoid UB when Shamt >= XLen.
11182 SDValue ShamtMasked =
11183 DAG.getNode(ISD::AND, DL, VT, Shamt, DAG.getConstant(XLen - 1, DL, VT));
11184 SDValue HiRes =
11185 DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, DL, VT, Hi, ShamtMasked);
11186
11187 // Create a mask that is -1 when Shamt >= XLen, 0 otherwise.
11188 // FIXME: We should use a select and let LowerSelect make the
11189 // optimizations.
11190 SDValue ShAmtExt =
11191 DAG.getNode(ISD::SHL, DL, VT, Shamt,
11192 DAG.getConstant(XLen - Log2_32(XLen) - 1, DL, VT));
11193 SDValue Mask = DAG.getNode(ISD::SRA, DL, VT, ShAmtExt,
11194 DAG.getConstant(XLen - 1, DL, VT));
11195
11196 if (Subtarget.is64Bit()) {
11197 // On RV64, FSHR masks shift amount to 63. We need to replace LoRes
11198 // with HiRes when Shamt >= 64.
11199 // LoRes = (LoRes & ~Mask) | (HiRes & Mask)
11200 SDValue LoMasked =
11201 DAG.getNode(ISD::AND, DL, VT, LoRes, DAG.getNOT(DL, Mask, VT));
11202 SDValue HiMasked = DAG.getNode(ISD::AND, DL, VT, HiRes, Mask);
11203 LoRes = DAG.getNode(ISD::OR, DL, VT, LoMasked, HiMasked,
11205 }
11206
11207 // If ShAmt >= XLen, we need to replace HiRes with 0 or sign bits.
11208 if (IsSRA) {
11209 // sra hi, hi, (mask & (XLen-1)) - shifts by XLen-1 when shamt >= XLen
11210 SDValue MaskAmt = DAG.getNode(ISD::AND, DL, VT, Mask,
11211 DAG.getConstant(XLen - 1, DL, VT));
11212 HiRes = DAG.getNode(ISD::SRA, DL, VT, HiRes, MaskAmt);
11213 } else {
11214 // andn hi, hi, mask - clears hi when shamt >= XLen
11215 HiRes = DAG.getNode(ISD::AND, DL, VT, HiRes, DAG.getNOT(DL, Mask, VT));
11216 }
11217
11218 return DAG.getMergeValues({LoRes, HiRes}, DL);
11219 }
11220
11221 // SRA expansion:
11222 // if Shamt-XLEN < 0: // Shamt < XLEN
11223 // Lo = (Lo >>u Shamt) | ((Hi << 1) << (XLEN-1 - ShAmt))
11224 // Hi = Hi >>s Shamt
11225 // else:
11226 // Lo = Hi >>s (Shamt-XLEN);
11227 // Hi = Hi >>s (XLEN-1)
11228 //
11229 // SRL expansion:
11230 // if Shamt-XLEN < 0: // Shamt < XLEN
11231 // Lo = (Lo >>u Shamt) | ((Hi << 1) << (XLEN-1 - ShAmt))
11232 // Hi = Hi >>u Shamt
11233 // else:
11234 // Lo = Hi >>u (Shamt-XLEN);
11235 // Hi = 0;
11236
11237 unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL;
11238
11239 SDValue Zero = DAG.getConstant(0, DL, VT);
11240 SDValue One = DAG.getConstant(1, DL, VT);
11241 SDValue MinusXLen = DAG.getSignedConstant(-(int)Subtarget.getXLen(), DL, VT);
11242 SDValue XLenMinus1 = DAG.getConstant(Subtarget.getXLen() - 1, DL, VT);
11243 SDValue ShamtMinusXLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusXLen);
11244 SDValue XLenMinus1Shamt = DAG.getNode(ISD::SUB, DL, VT, XLenMinus1, Shamt);
11245
11246 SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt);
11247 SDValue ShiftLeftHi1 = DAG.getNode(ISD::SHL, DL, VT, Hi, One);
11248 SDValue ShiftLeftHi =
11249 DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, XLenMinus1Shamt);
11250 SDValue LoTrue = DAG.getNode(ISD::OR, DL, VT, ShiftRightLo, ShiftLeftHi);
11251 SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt);
11252 SDValue LoFalse = DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusXLen);
11253 SDValue HiFalse =
11254 IsSRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, XLenMinus1) : Zero;
11255
11256 SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusXLen, Zero, ISD::SETLT);
11257
11258 Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, LoFalse);
11259 Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse);
11260
11261 SDValue Parts[2] = {Lo, Hi};
11262 return DAG.getMergeValues(Parts, DL);
11263}
11264
11265// Lower splats of i1 types to SETCC. For each mask vector type, we have a
11266// legal equivalently-sized i8 type, so we can use that as a go-between.
11267SDValue RISCVTargetLowering::lowerVectorMaskSplat(SDValue Op,
11268 SelectionDAG &DAG) const {
11269 SDLoc DL(Op);
11270 MVT VT = Op.getSimpleValueType();
11271 SDValue SplatVal = Op.getOperand(0);
11272 // All-zeros or all-ones splats are handled specially.
11273 if (ISD::isConstantSplatVectorAllOnes(Op.getNode())) {
11274 SDValue VL = getDefaultScalableVLOps(VT, DL, DAG, Subtarget).second;
11275 return DAG.getNode(RISCVISD::VMSET_VL, DL, VT, VL);
11276 }
11277 if (ISD::isConstantSplatVectorAllZeros(Op.getNode())) {
11278 SDValue VL = getDefaultScalableVLOps(VT, DL, DAG, Subtarget).second;
11279 return DAG.getNode(RISCVISD::VMCLR_VL, DL, VT, VL);
11280 }
11281 MVT InterVT = VT.changeVectorElementType(MVT::i8);
11282 SplatVal = DAG.getNode(ISD::AND, DL, SplatVal.getValueType(), SplatVal,
11283 DAG.getConstant(1, DL, SplatVal.getValueType()));
11284 SDValue LHS = DAG.getSplatVector(InterVT, DL, SplatVal);
11285 SDValue Zero = DAG.getConstant(0, DL, InterVT);
11286 return DAG.getSetCC(DL, VT, LHS, Zero, ISD::SETNE);
11287}
11288
11289// Custom-lower a SPLAT_VECTOR_PARTS where XLEN<SEW, as the SEW element type is
11290// illegal (currently only vXi64 RV32).
11291// FIXME: We could also catch non-constant sign-extended i32 values and lower
11292// them to VMV_V_X_VL.
11293SDValue RISCVTargetLowering::lowerSPLAT_VECTOR_PARTS(SDValue Op,
11294 SelectionDAG &DAG) const {
11295 SDLoc DL(Op);
11296 MVT VecVT = Op.getSimpleValueType();
11297 assert(!Subtarget.is64Bit() && VecVT.getVectorElementType() == MVT::i64 &&
11298 "Unexpected SPLAT_VECTOR_PARTS lowering");
11299
11300 assert(Op.getNumOperands() == 2 && "Unexpected number of operands!");
11301 SDValue Lo = Op.getOperand(0);
11302 SDValue Hi = Op.getOperand(1);
11303
11304 MVT ContainerVT = VecVT;
11305 if (VecVT.isFixedLengthVector())
11306 ContainerVT = getContainerForFixedLengthVector(VecVT);
11307
11308 auto VL = getDefaultVLOps(VecVT, ContainerVT, DL, DAG, Subtarget).second;
11309
11310 SDValue Res =
11311 splatPartsI64WithVL(DL, ContainerVT, SDValue(), Lo, Hi, VL, DAG);
11312
11313 if (VecVT.isFixedLengthVector())
11314 Res = convertFromScalableVector(VecVT, Res, DAG, Subtarget);
11315
11316 return Res;
11317}
11318
11319// Custom-lower extensions from mask vectors by using a vselect either with 1
11320// for zero/any-extension or -1 for sign-extension:
11321// (vXiN = (s|z)ext vXi1:vmask) -> (vXiN = vselect vmask, (-1 or 1), 0)
11322// Note that any-extension is lowered identically to zero-extension.
11323SDValue RISCVTargetLowering::lowerVectorMaskExt(SDValue Op, SelectionDAG &DAG,
11324 int64_t ExtTrueVal) const {
11325 SDLoc DL(Op);
11326 MVT VecVT = Op.getSimpleValueType();
11327 SDValue Src = Op.getOperand(0);
11328 // Only custom-lower extensions from mask types
11329 assert(Src.getValueType().isVector() &&
11330 Src.getValueType().getVectorElementType() == MVT::i1);
11331
11332 if (VecVT.isScalableVector()) {
11333 SDValue SplatZero = DAG.getConstant(0, DL, VecVT);
11334 SDValue SplatTrueVal = DAG.getSignedConstant(ExtTrueVal, DL, VecVT);
11335 if (Src.getOpcode() == ISD::XOR &&
11336 ISD::isConstantSplatVectorAllOnes(Src.getOperand(1).getNode()))
11337 return DAG.getNode(ISD::VSELECT, DL, VecVT, Src.getOperand(0), SplatZero,
11338 SplatTrueVal);
11339 return DAG.getNode(ISD::VSELECT, DL, VecVT, Src, SplatTrueVal, SplatZero);
11340 }
11341
11342 MVT ContainerVT = getContainerForFixedLengthVector(VecVT);
11343 MVT I1ContainerVT =
11344 MVT::getVectorVT(MVT::i1, ContainerVT.getVectorElementCount());
11345
11346 SDValue CC = convertToScalableVector(I1ContainerVT, Src, DAG, Subtarget);
11347
11348 SDValue VL = getDefaultVLOps(VecVT, ContainerVT, DL, DAG, Subtarget).second;
11349
11350 MVT XLenVT = Subtarget.getXLenVT();
11351 SDValue SplatZero = DAG.getConstant(0, DL, XLenVT);
11352 SDValue SplatTrueVal = DAG.getSignedConstant(ExtTrueVal, DL, XLenVT);
11353
11354 if (Src.getOpcode() == ISD::EXTRACT_SUBVECTOR) {
11355 SDValue Xor = Src.getOperand(0);
11356 if (Xor.getOpcode() == RISCVISD::VMXOR_VL) {
11357 SDValue ScalableOnes = Xor.getOperand(1);
11358 if (ScalableOnes.getOpcode() == ISD::INSERT_SUBVECTOR &&
11359 ScalableOnes.getOperand(0).isUndef() &&
11361 ScalableOnes.getOperand(1).getNode())) {
11362 CC = Xor.getOperand(0);
11363 std::swap(SplatZero, SplatTrueVal);
11364 }
11365 }
11366 }
11367
11368 SplatZero = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerVT,
11369 DAG.getUNDEF(ContainerVT), SplatZero, VL);
11370 SplatTrueVal = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerVT,
11371 DAG.getUNDEF(ContainerVT), SplatTrueVal, VL);
11372 SDValue Select =
11373 DAG.getNode(RISCVISD::VMERGE_VL, DL, ContainerVT, CC, SplatTrueVal,
11374 SplatZero, DAG.getUNDEF(ContainerVT), VL);
11375
11376 return convertFromScalableVector(VecVT, Select, DAG, Subtarget);
11377}
11378
11379// Custom-lower truncations from vectors to mask vectors by using a mask and a
11380// setcc operation:
11381// (vXi1 = trunc vXiN vec) -> (vXi1 = setcc (and vec, 1), 0, ne)
11382SDValue RISCVTargetLowering::lowerVectorMaskTrunc(SDValue Op,
11383 SelectionDAG &DAG) const {
11384 SDLoc DL(Op);
11385 EVT MaskVT = Op.getValueType();
11386 // Only expect to custom-lower truncations to mask types
11387 assert(MaskVT.isVectorOf(MVT::i1) &&
11388 "Unexpected type for vector mask lowering");
11389 SDValue Src = Op.getOperand(0);
11390 MVT VecVT = Src.getSimpleValueType();
11391 // If this is a fixed vector, we need to convert it to a scalable vector.
11392 MVT ContainerVT = VecVT;
11393
11394 if (VecVT.isFixedLengthVector()) {
11395 ContainerVT = getContainerForFixedLengthVector(VecVT);
11396 Src = convertToScalableVector(ContainerVT, Src, DAG, Subtarget);
11397 }
11398
11399 auto [Mask, VL] = getDefaultVLOps(VecVT, ContainerVT, DL, DAG, Subtarget);
11400
11401 SDValue SplatOne = DAG.getConstant(1, DL, Subtarget.getXLenVT());
11402 SDValue SplatZero = DAG.getConstant(0, DL, Subtarget.getXLenVT());
11403
11404 SplatOne = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerVT,
11405 DAG.getUNDEF(ContainerVT), SplatOne, VL);
11406 SplatZero = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerVT,
11407 DAG.getUNDEF(ContainerVT), SplatZero, VL);
11408
11409 MVT MaskContainerVT = ContainerVT.changeVectorElementType(MVT::i1);
11410 SDValue Trunc = DAG.getNode(RISCVISD::AND_VL, DL, ContainerVT, Src, SplatOne,
11411 DAG.getUNDEF(ContainerVT), Mask, VL);
11412 Trunc = DAG.getNode(RISCVISD::SETCC_VL, DL, MaskContainerVT,
11413 {Trunc, SplatZero, DAG.getCondCode(ISD::SETNE),
11414 DAG.getUNDEF(MaskContainerVT), Mask, VL});
11415 if (MaskVT.isFixedLengthVector())
11416 Trunc = convertFromScalableVector(MaskVT, Trunc, DAG, Subtarget);
11417 return Trunc;
11418}
11419
11420SDValue RISCVTargetLowering::lowerVectorTrunc(SDValue Op,
11421 SelectionDAG &DAG) const {
11422 unsigned Opc = Op.getOpcode();
11423 SDLoc DL(Op);
11424
11425 MVT VT = Op.getSimpleValueType();
11426 // Only custom-lower vector truncates
11427 assert(VT.isVector() && "Unexpected type for vector truncate lowering");
11428
11429 // Truncates to mask types are handled differently
11430 if (VT.getVectorElementType() == MVT::i1)
11431 return lowerVectorMaskTrunc(Op, DAG);
11432
11433 // RVV only has truncates which operate from SEW*2->SEW, so lower arbitrary
11434 // truncates as a series of "RISCVISD::TRUNCATE_VECTOR_VL" nodes which
11435 // truncate by one power of two at a time.
11436 MVT DstEltVT = VT.getVectorElementType();
11437
11438 SDValue Src = Op.getOperand(0);
11439 MVT SrcVT = Src.getSimpleValueType();
11440 MVT SrcEltVT = SrcVT.getVectorElementType();
11441
11442 assert(DstEltVT.bitsLT(SrcEltVT) && isPowerOf2_64(DstEltVT.getSizeInBits()) &&
11443 isPowerOf2_64(SrcEltVT.getSizeInBits()) &&
11444 "Unexpected vector truncate lowering");
11445
11446 MVT ContainerVT = SrcVT;
11447 if (SrcVT.isFixedLengthVector()) {
11448 ContainerVT = getContainerForFixedLengthVector(SrcVT);
11449 Src = convertToScalableVector(ContainerVT, Src, DAG, Subtarget);
11450 }
11451
11452 SDValue Result = Src;
11453 auto [Mask, VL] = getDefaultVLOps(SrcVT, ContainerVT, DL, DAG, Subtarget);
11454
11455 unsigned NewOpc;
11457 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
11458 else if (Opc == ISD::TRUNCATE_USAT_U)
11459 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
11460 else
11461 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL;
11462
11463 do {
11464 SrcEltVT = MVT::getIntegerVT(SrcEltVT.getSizeInBits() / 2);
11465 MVT ResultVT = ContainerVT.changeVectorElementType(SrcEltVT);
11466 Result = DAG.getNode(NewOpc, DL, ResultVT, Result, Mask, VL);
11467 } while (SrcEltVT != DstEltVT);
11468
11469 if (SrcVT.isFixedLengthVector())
11470 Result = convertFromScalableVector(VT, Result, DAG, Subtarget);
11471
11472 return Result;
11473}
11474
11475SDValue
11476RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(SDValue Op,
11477 SelectionDAG &DAG) const {
11478 SDLoc DL(Op);
11479 SDValue Chain = Op.getOperand(0);
11480 SDValue Src = Op.getOperand(1);
11481 MVT VT = Op.getSimpleValueType();
11482 MVT SrcVT = Src.getSimpleValueType();
11483 MVT ContainerVT = VT;
11484 if (VT.isFixedLengthVector()) {
11485 MVT SrcContainerVT = getContainerForFixedLengthVector(SrcVT);
11486 ContainerVT =
11487 SrcContainerVT.changeVectorElementType(VT.getVectorElementType());
11488 Src = convertToScalableVector(SrcContainerVT, Src, DAG, Subtarget);
11489 }
11490
11491 auto [Mask, VL] = getDefaultVLOps(SrcVT, ContainerVT, DL, DAG, Subtarget);
11492
11493 // RVV can only widen/truncate fp to types double/half the size as the source.
11494 if ((VT.getVectorElementType() == MVT::f64 &&
11495 (SrcVT.getVectorElementType() == MVT::f16 ||
11496 SrcVT.getVectorElementType() == MVT::bf16)) ||
11497 ((VT.getVectorElementType() == MVT::f16 ||
11498 VT.getVectorElementType() == MVT::bf16) &&
11499 SrcVT.getVectorElementType() == MVT::f64)) {
11500 // For double rounding, the intermediate rounding should be round-to-odd.
11501 unsigned InterConvOpc = Op.getOpcode() == ISD::STRICT_FP_EXTEND
11502 ? RISCVISD::STRICT_FP_EXTEND_VL
11503 : RISCVISD::STRICT_VFNCVT_ROD_VL;
11504 MVT InterVT = ContainerVT.changeVectorElementType(MVT::f32);
11505 Src = DAG.getNode(InterConvOpc, DL, DAG.getVTList(InterVT, MVT::Other),
11506 Chain, Src, Mask, VL);
11507 Chain = Src.getValue(1);
11508 }
11509
11510 unsigned ConvOpc = Op.getOpcode() == ISD::STRICT_FP_EXTEND
11511 ? RISCVISD::STRICT_FP_EXTEND_VL
11512 : RISCVISD::STRICT_FP_ROUND_VL;
11513 SDValue Res = DAG.getNode(ConvOpc, DL, DAG.getVTList(ContainerVT, MVT::Other),
11514 Chain, Src, Mask, VL);
11515 if (VT.isFixedLengthVector()) {
11516 // StrictFP operations have two result values. Their lowered result should
11517 // have same result count.
11518 SDValue SubVec = convertFromScalableVector(VT, Res, DAG, Subtarget);
11519 Res = DAG.getMergeValues({SubVec, Res.getValue(1)}, DL);
11520 }
11521 return Res;
11522}
11523
11524SDValue
11525RISCVTargetLowering::lowerVectorFPExtendOrRound(SDValue Op,
11526 SelectionDAG &DAG) const {
11527 bool IsExtend = Op.getOpcode() == ISD::FP_EXTEND;
11528 // RVV can only do truncate fp to types half the size as the source. We
11529 // custom-lower f64->f16 rounds via RVV's round-to-odd float
11530 // conversion instruction.
11531 SDLoc DL(Op);
11532 MVT VT = Op.getSimpleValueType();
11533
11534 assert(VT.isVector() && "Unexpected type for vector truncate lowering");
11535
11536 SDValue Src = Op.getOperand(0);
11537 MVT SrcVT = Src.getSimpleValueType();
11538
11539 bool IsDirectExtend =
11540 IsExtend && (VT.getVectorElementType() != MVT::f64 ||
11541 (SrcVT.getVectorElementType() != MVT::f16 &&
11542 SrcVT.getVectorElementType() != MVT::bf16));
11543 bool IsDirectTrunc = !IsExtend && ((VT.getVectorElementType() != MVT::f16 &&
11544 VT.getVectorElementType() != MVT::bf16) ||
11545 SrcVT.getVectorElementType() != MVT::f64);
11546
11547 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
11548
11549 // We have regular SD node patterns for direct non-VL extends.
11550 if (VT.isScalableVector() && IsDirectConv)
11551 return Op;
11552
11553 // Prepare any fixed-length vector operands.
11554 MVT ContainerVT = VT;
11555 if (VT.isFixedLengthVector()) {
11556 MVT SrcContainerVT = getContainerForFixedLengthVector(SrcVT);
11557 ContainerVT =
11558 SrcContainerVT.changeVectorElementType(VT.getVectorElementType());
11559 Src = convertToScalableVector(SrcContainerVT, Src, DAG, Subtarget);
11560 }
11561
11562 auto [Mask, VL] = getDefaultVLOps(SrcVT, ContainerVT, DL, DAG, Subtarget);
11563
11564 unsigned ConvOpc = IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::FP_ROUND_VL;
11565
11566 if (IsDirectConv) {
11567 Src = DAG.getNode(ConvOpc, DL, ContainerVT, Src, Mask, VL);
11568 if (VT.isFixedLengthVector())
11569 Src = convertFromScalableVector(VT, Src, DAG, Subtarget);
11570 return Src;
11571 }
11572
11573 unsigned InterConvOpc =
11574 IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::VFNCVT_ROD_VL;
11575
11576 MVT InterVT = ContainerVT.changeVectorElementType(MVT::f32);
11577 SDValue IntermediateConv =
11578 DAG.getNode(InterConvOpc, DL, InterVT, Src, Mask, VL);
11579 SDValue Result =
11580 DAG.getNode(ConvOpc, DL, ContainerVT, IntermediateConv, Mask, VL);
11581 if (VT.isFixedLengthVector())
11582 return convertFromScalableVector(VT, Result, DAG, Subtarget);
11583 return Result;
11584}
11585
11586// Given a scalable vector type and an index into it, returns the type for the
11587// smallest subvector that the index fits in. This can be used to reduce LMUL
11588// for operations like vslidedown.
11589//
11590// E.g. With Zvl128b, index 3 in a nxv4i32 fits within the first nxv2i32.
11591static std::optional<MVT>
11592getSmallestVTForIndex(MVT VecVT, unsigned MaxIdx, SDLoc DL, SelectionDAG &DAG,
11593 const RISCVSubtarget &Subtarget) {
11594 assert(VecVT.isScalableVector());
11595 const unsigned EltSize = VecVT.getScalarSizeInBits();
11596 const unsigned VectorBitsMin = Subtarget.getRealMinVLen();
11597 const unsigned MinVLMAX = VectorBitsMin / EltSize;
11598 MVT SmallerVT;
11599 if (MaxIdx < MinVLMAX)
11600 SmallerVT = RISCVTargetLowering::getM1VT(VecVT);
11601 else if (MaxIdx < MinVLMAX * 2)
11602 SmallerVT =
11604 else if (MaxIdx < MinVLMAX * 4)
11605 SmallerVT = RISCVTargetLowering::getM1VT(VecVT)
11608 if (!SmallerVT.isValid() || !VecVT.bitsGT(SmallerVT))
11609 return std::nullopt;
11610 return SmallerVT;
11611}
11612
11613// Custom-legalize INSERT_VECTOR_ELT so that the value is inserted into the
11614// first position of a vector, and that vector is slid up to the insert index.
11615// By limiting the active vector length to index+1 and merging with the
11616// original vector (with an undisturbed tail policy for elements >= VL), we
11617// achieve the desired result of leaving all elements untouched except the one
11618// at VL-1, which is replaced with the desired value.
11619SDValue RISCVTargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op,
11620 SelectionDAG &DAG) const {
11621 SDLoc DL(Op);
11622 MVT VecVT = Op.getSimpleValueType();
11623 MVT XLenVT = Subtarget.getXLenVT();
11624 SDValue Vec = Op.getOperand(0);
11625 SDValue Val = Op.getOperand(1);
11626 MVT ValVT = Val.getSimpleValueType();
11627 SDValue Idx = Op.getOperand(2);
11628
11629 if (VecVT.getVectorElementType() == MVT::i1) {
11630 // FIXME: For now we just promote to an i8 vector and insert into that,
11631 // but this is probably not optimal.
11632 MVT WideVT = MVT::getVectorVT(MVT::i8, VecVT.getVectorElementCount());
11633 Vec = DAG.getNode(ISD::ZERO_EXTEND, DL, WideVT, Vec);
11634 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, WideVT, Vec, Val, Idx);
11635 return DAG.getNode(ISD::TRUNCATE, DL, VecVT, Vec);
11636 }
11637
11638 if ((ValVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
11639 (ValVT == MVT::bf16 && !Subtarget.hasVInstructionsBF16())) {
11640 // If we don't have vfmv.s.f for f16/bf16, use fmv.x.h first.
11641 MVT IntVT = VecVT.changeTypeToInteger();
11642 SDValue IntInsert = DAG.getNode(
11643 ISD::INSERT_VECTOR_ELT, DL, IntVT, DAG.getBitcast(IntVT, Vec),
11644 DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, XLenVT, Val), Idx);
11645 return DAG.getBitcast(VecVT, IntInsert);
11646 }
11647
11648 if (Subtarget.hasStdExtP() && VecVT.isFixedLengthVector()) {
11649 auto *IdxC = dyn_cast<ConstantSDNode>(Idx);
11650 if (!IdxC)
11651 return SDValue();
11652
11653 unsigned IdxVal = IdxC->getZExtValue();
11654 unsigned NumElts = VecVT.getVectorNumElements();
11655 MVT EltVT = VecVT.getVectorElementType();
11656
11657 if (!Subtarget.is64Bit() && (VecVT == MVT::v4i16 || VecVT == MVT::v8i8)) {
11658 unsigned HalfNumElts = NumElts / 2;
11659 auto [Lo, Hi] = DAG.SplitVector(Vec, DL);
11660 MVT HalfVT = Lo.getSimpleValueType();
11661 if (IdxVal < HalfNumElts) {
11662 SDValue NewLo =
11663 DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, HalfVT, Lo, Val, Idx);
11664 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VecVT, NewLo, Hi);
11665 }
11666 SDValue NewHi =
11667 DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, HalfVT, Hi, Val,
11668 DAG.getVectorIdxConstant(IdxVal - HalfNumElts, DL));
11669 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VecVT, Lo, NewHi);
11670 }
11671
11672 Vec = DAG.getBitcast(XLenVT, Vec);
11673 SDValue ExtVal = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, Val);
11674
11675 // For 2-element vectors, BUILD_VECTOR is more efficient since it only needs
11676 // at most 2 instructions.
11677 if (NumElts == 2) {
11678 unsigned EltBits = EltVT.getSizeInBits();
11679 SDValue Elt0, Elt1;
11680 if (IdxVal == 0) {
11681 Elt0 = ExtVal;
11682 Elt1 = DAG.getNode(ISD::SRL, DL, XLenVT, Vec,
11683 DAG.getConstant(EltBits, DL, XLenVT));
11684 } else {
11685 Elt0 = Vec;
11686 Elt1 = ExtVal;
11687 }
11688 return DAG.getNode(ISD::BUILD_VECTOR, DL, VecVT, Elt0, Elt1);
11689 }
11690
11691 // For 4/8-element vectors, use MVM(or MERGE) instruction which does bitwise
11692 // select: rd = (~mask & rd) | (mask & rs1).
11693 // This generates: slli + lui/li + mvm
11694 if (NumElts == 4 || NumElts == 8) {
11695 unsigned EltBits = EltVT.getSizeInBits();
11696 unsigned ShiftAmt = IdxVal * EltBits;
11697 uint64_t PosMask = ((1ULL << EltBits) - 1) << ShiftAmt;
11698
11699 SDValue ShiftedVal = DAG.getNode(ISD::SHL, DL, XLenVT, ExtVal,
11700 DAG.getConstant(ShiftAmt, DL, XLenVT));
11701 SDValue Mask = DAG.getConstant(PosMask, DL, XLenVT);
11702 SDValue Result =
11703 DAG.getNode(RISCVISD::MERGE, DL, XLenVT, Mask, Vec, ShiftedVal);
11704 return DAG.getBitcast(VecVT, Result);
11705 }
11706
11707 return SDValue();
11708 }
11709
11710 MVT ContainerVT = VecVT;
11711 // If the operand is a fixed-length vector, convert to a scalable one.
11712 if (VecVT.isFixedLengthVector()) {
11713 ContainerVT = getContainerForFixedLengthVector(VecVT);
11714 Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget);
11715 }
11716
11717 // If we know the index we're going to insert at, we can shrink Vec so that
11718 // we're performing the scalar inserts and slideup on a smaller LMUL.
11719 SDValue OrigVec = Vec;
11720 std::optional<unsigned> AlignedIdx;
11721 if (auto *IdxC = dyn_cast<ConstantSDNode>(Idx)) {
11722 const unsigned OrigIdx = IdxC->getZExtValue();
11723 // Do we know an upper bound on LMUL?
11724 if (auto ShrunkVT = getSmallestVTForIndex(ContainerVT, OrigIdx,
11725 DL, DAG, Subtarget)) {
11726 ContainerVT = *ShrunkVT;
11727 AlignedIdx = 0;
11728 }
11729
11730 // If we're compiling for an exact VLEN value, we can always perform
11731 // the insert in m1 as we can determine the register corresponding to
11732 // the index in the register group.
11733 const MVT M1VT = RISCVTargetLowering::getM1VT(ContainerVT);
11734 if (auto VLEN = Subtarget.getRealVLen(); VLEN && ContainerVT.bitsGT(M1VT)) {
11735 EVT ElemVT = VecVT.getVectorElementType();
11736 unsigned ElemsPerVReg = *VLEN / ElemVT.getFixedSizeInBits();
11737 unsigned RemIdx = OrigIdx % ElemsPerVReg;
11738 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
11739 AlignedIdx = SubRegIdx * M1VT.getVectorElementCount().getKnownMinValue();
11740 Idx = DAG.getVectorIdxConstant(RemIdx, DL);
11741 ContainerVT = M1VT;
11742 }
11743
11744 if (AlignedIdx)
11745 Vec = DAG.getExtractSubvector(DL, ContainerVT, Vec, *AlignedIdx);
11746 }
11747
11748 bool IsLegalInsert = Subtarget.is64Bit() || Val.getValueType() != MVT::i64;
11749 // Even i64-element vectors on RV32 can be lowered without scalar
11750 // legalization if the most-significant 32 bits of the value are not affected
11751 // by the sign-extension of the lower 32 bits. This applies to i32 constants
11752 // and sign_extend of i32 values.
11753 if (!IsLegalInsert) {
11754 if (isa<ConstantSDNode>(Val)) {
11755 const auto *CVal = cast<ConstantSDNode>(Val);
11756 if (isInt<32>(CVal->getSExtValue())) {
11757 IsLegalInsert = true;
11758 Val = DAG.getSignedConstant(CVal->getSExtValue(), DL, MVT::i32);
11759 }
11760 } else if (Val.getOpcode() == ISD::SIGN_EXTEND &&
11761 Val.getOperand(0).getValueType() == MVT::i32) {
11762 IsLegalInsert = true;
11763 Val = Val.getOperand(0);
11764 }
11765 }
11766
11767 auto [Mask, VL] = getDefaultVLOps(VecVT, ContainerVT, DL, DAG, Subtarget);
11768
11769 SDValue ValInVec;
11770
11771 if (IsLegalInsert) {
11772 unsigned Opc =
11773 VecVT.isFloatingPoint() ? RISCVISD::VFMV_S_F_VL : RISCVISD::VMV_S_X_VL;
11774 if (isNullConstant(Idx)) {
11775 if (!VecVT.isFloatingPoint())
11776 Val = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, Val);
11777 Vec = DAG.getNode(Opc, DL, ContainerVT, Vec, Val, VL);
11778
11779 if (AlignedIdx)
11780 Vec = DAG.getInsertSubvector(DL, OrigVec, Vec, *AlignedIdx);
11781 if (!VecVT.isFixedLengthVector())
11782 return Vec;
11783 return convertFromScalableVector(VecVT, Vec, DAG, Subtarget);
11784 }
11785
11786 ValInVec = lowerScalarInsert(Val, VL, ContainerVT, DL, DAG, Subtarget);
11787 } else {
11788 // On RV32, i64-element vectors must be specially handled to place the
11789 // value at element 0, by using two vslide1down instructions in sequence on
11790 // the i32 split lo/hi value. Use an equivalently-sized i32 vector for
11791 // this.
11792 SDValue ValLo, ValHi;
11793 std::tie(ValLo, ValHi) = DAG.SplitScalar(Val, DL, MVT::i32, MVT::i32);
11794 MVT I32ContainerVT =
11795 MVT::getVectorVT(MVT::i32, ContainerVT.getVectorElementCount() * 2);
11796 SDValue I32Mask =
11797 getDefaultScalableVLOps(I32ContainerVT, DL, DAG, Subtarget).first;
11798 // Limit the active VL to two.
11799 SDValue InsertI64VL = DAG.getConstant(2, DL, XLenVT);
11800 // If the Idx is 0 we can insert directly into the vector.
11801 if (isNullConstant(Idx)) {
11802 // First slide in the lo value, then the hi in above it. We use slide1down
11803 // to avoid the register group overlap constraint of vslide1up.
11804 ValInVec = DAG.getNode(RISCVISD::VSLIDE1DOWN_VL, DL, I32ContainerVT,
11805 Vec, Vec, ValLo, I32Mask, InsertI64VL);
11806 // If the source vector is undef don't pass along the tail elements from
11807 // the previous slide1down.
11808 SDValue Tail = Vec.isUndef() ? Vec : ValInVec;
11809 ValInVec = DAG.getNode(RISCVISD::VSLIDE1DOWN_VL, DL, I32ContainerVT,
11810 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
11811 // Bitcast back to the right container type.
11812 ValInVec = DAG.getBitcast(ContainerVT, ValInVec);
11813
11814 if (AlignedIdx)
11815 ValInVec = DAG.getInsertSubvector(DL, OrigVec, ValInVec, *AlignedIdx);
11816 if (!VecVT.isFixedLengthVector())
11817 return ValInVec;
11818 return convertFromScalableVector(VecVT, ValInVec, DAG, Subtarget);
11819 }
11820
11821 // First slide in the lo value, then the hi in above it. We use slide1down
11822 // to avoid the register group overlap constraint of vslide1up.
11823 ValInVec = DAG.getNode(RISCVISD::VSLIDE1DOWN_VL, DL, I32ContainerVT,
11824 DAG.getUNDEF(I32ContainerVT),
11825 DAG.getUNDEF(I32ContainerVT), ValLo,
11826 I32Mask, InsertI64VL);
11827 ValInVec = DAG.getNode(RISCVISD::VSLIDE1DOWN_VL, DL, I32ContainerVT,
11828 DAG.getUNDEF(I32ContainerVT), ValInVec, ValHi,
11829 I32Mask, InsertI64VL);
11830 // Bitcast back to the right container type.
11831 ValInVec = DAG.getBitcast(ContainerVT, ValInVec);
11832 }
11833
11834 // Now that the value is in a vector, slide it into position.
11835 SDValue InsertVL =
11836 DAG.getNode(ISD::ADD, DL, XLenVT, Idx, DAG.getConstant(1, DL, XLenVT));
11837
11838 // Use tail agnostic policy if Idx is the last index of Vec.
11840 if (VecVT.isFixedLengthVector() && isa<ConstantSDNode>(Idx) &&
11841 Idx->getAsZExtVal() + 1 == VecVT.getVectorNumElements())
11843 SDValue Slideup = getVSlideup(DAG, Subtarget, DL, ContainerVT, Vec, ValInVec,
11844 Idx, Mask, InsertVL, Policy);
11845
11846 if (AlignedIdx)
11847 Slideup = DAG.getInsertSubvector(DL, OrigVec, Slideup, *AlignedIdx);
11848 if (!VecVT.isFixedLengthVector())
11849 return Slideup;
11850 return convertFromScalableVector(VecVT, Slideup, DAG, Subtarget);
11851}
11852
11853// Custom-lower EXTRACT_VECTOR_ELT operations to slide the vector down, then
11854// extract the first element: (extractelt (slidedown vec, idx), 0). For integer
11855// types this is done using VMV_X_S to allow us to glean information about the
11856// sign bits of the result.
11857SDValue RISCVTargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op,
11858 SelectionDAG &DAG) const {
11859 SDLoc DL(Op);
11860 SDValue Idx = Op.getOperand(1);
11861 SDValue Vec = Op.getOperand(0);
11862 EVT EltVT = Op.getValueType();
11863 MVT VecVT = Vec.getSimpleValueType();
11864 MVT XLenVT = Subtarget.getXLenVT();
11865
11866 if (VecVT.getVectorElementType() == MVT::i1) {
11867 // Use vfirst.m to extract the first bit.
11868 if (isNullConstant(Idx)) {
11869 MVT ContainerVT = VecVT;
11870 if (VecVT.isFixedLengthVector()) {
11871 ContainerVT = getContainerForFixedLengthVector(VecVT);
11872 Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget);
11873 }
11874 auto [Mask, VL] = getDefaultVLOps(VecVT, ContainerVT, DL, DAG, Subtarget);
11875 SDValue Vfirst =
11876 DAG.getNode(RISCVISD::VFIRST_VL, DL, XLenVT, Vec, Mask, VL);
11877 SDValue Res = DAG.getSetCC(DL, XLenVT, Vfirst,
11878 DAG.getConstant(0, DL, XLenVT), ISD::SETEQ);
11879 return DAG.getNode(ISD::TRUNCATE, DL, EltVT, Res);
11880 }
11881 if (VecVT.isFixedLengthVector()) {
11882 unsigned NumElts = VecVT.getVectorNumElements();
11883 if (NumElts >= 8) {
11884 MVT WideEltVT;
11885 unsigned WidenVecLen;
11886 SDValue ExtractElementIdx;
11887 SDValue ExtractBitIdx;
11888 unsigned MaxEEW = Subtarget.getELen();
11889 MVT LargestEltVT = MVT::getIntegerVT(
11890 std::min(MaxEEW, unsigned(XLenVT.getSizeInBits())));
11891 if (NumElts <= LargestEltVT.getSizeInBits()) {
11892 assert(isPowerOf2_32(NumElts) &&
11893 "the number of elements should be power of 2");
11894 WideEltVT = MVT::getIntegerVT(NumElts);
11895 WidenVecLen = 1;
11896 ExtractElementIdx = DAG.getConstant(0, DL, XLenVT);
11897 ExtractBitIdx = Idx;
11898 } else {
11899 WideEltVT = LargestEltVT;
11900 WidenVecLen = NumElts / WideEltVT.getSizeInBits();
11901 // extract element index = index / element width
11902 ExtractElementIdx = DAG.getNode(
11903 ISD::SRL, DL, XLenVT, Idx,
11904 DAG.getConstant(Log2_64(WideEltVT.getSizeInBits()), DL, XLenVT));
11905 // mask bit index = index % element width
11906 ExtractBitIdx = DAG.getNode(
11907 ISD::AND, DL, XLenVT, Idx,
11908 DAG.getConstant(WideEltVT.getSizeInBits() - 1, DL, XLenVT));
11909 }
11910 MVT WideVT = MVT::getVectorVT(WideEltVT, WidenVecLen);
11911 Vec = DAG.getNode(ISD::BITCAST, DL, WideVT, Vec);
11912 SDValue ExtractElt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, XLenVT,
11913 Vec, ExtractElementIdx);
11914 // Extract the bit from GPR.
11915 SDValue ShiftRight =
11916 DAG.getNode(ISD::SRL, DL, XLenVT, ExtractElt, ExtractBitIdx);
11917 SDValue Res = DAG.getNode(ISD::AND, DL, XLenVT, ShiftRight,
11918 DAG.getConstant(1, DL, XLenVT));
11919 return DAG.getNode(ISD::TRUNCATE, DL, EltVT, Res);
11920 }
11921 }
11922 // Otherwise, promote to an i8 vector and extract from that.
11923 MVT WideVT = MVT::getVectorVT(MVT::i8, VecVT.getVectorElementCount());
11924 Vec = DAG.getNode(ISD::ZERO_EXTEND, DL, WideVT, Vec);
11925 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, Vec, Idx);
11926 }
11927
11928 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
11929 (EltVT == MVT::bf16 && !Subtarget.hasVInstructionsBF16())) {
11930 // If we don't have vfmv.f.s for f16/bf16, extract to a gpr then use fmv.h.x
11931 MVT IntVT = VecVT.changeTypeToInteger();
11932 SDValue IntVec = DAG.getBitcast(IntVT, Vec);
11933 SDValue IntExtract =
11934 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, XLenVT, IntVec, Idx);
11935 return DAG.getNode(RISCVISD::FMV_H_X, DL, EltVT, IntExtract);
11936 }
11937
11938 if (Subtarget.hasStdExtP() && VecVT.isFixedLengthVector()) {
11939 if (VecVT != MVT::v4i16 && VecVT != MVT::v2i16 && VecVT != MVT::v8i8 &&
11940 VecVT != MVT::v4i8 && VecVT != MVT::v2i32)
11941 return SDValue();
11942
11943 if (!Subtarget.is64Bit() && (VecVT == MVT::v4i16 || VecVT == MVT::v8i8)) {
11944 auto *IdxC = dyn_cast<ConstantSDNode>(Idx);
11945 if (!IdxC)
11946 return SDValue();
11947 unsigned IdxVal = IdxC->getZExtValue();
11948 unsigned HalfNumElts = VecVT.getVectorNumElements() / 2;
11949 auto [Lo, Hi] = DAG.SplitVector(Vec, DL);
11950 if (IdxVal < HalfNumElts)
11951 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, Lo, Idx);
11952 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, Hi,
11953 DAG.getVectorIdxConstant(IdxVal - HalfNumElts, DL));
11954 }
11955
11956 SDValue Extracted = DAG.getBitcast(XLenVT, Vec);
11957 unsigned ElemWidth = VecVT.getVectorElementType().getSizeInBits();
11958 SDValue Shamt = DAG.getNode(ISD::MUL, DL, XLenVT, Idx,
11959 DAG.getConstant(ElemWidth, DL, XLenVT));
11960 return DAG.getNode(ISD::SRL, DL, XLenVT, Extracted, Shamt);
11961 }
11962
11963 // If this is a fixed vector, we need to convert it to a scalable vector.
11964 MVT ContainerVT = VecVT;
11965 if (VecVT.isFixedLengthVector()) {
11966 ContainerVT = getContainerForFixedLengthVector(VecVT);
11967 Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget);
11968 }
11969
11970 // If we're compiling for an exact VLEN value and we have a known
11971 // constant index, we can always perform the extract in m1 (or
11972 // smaller) as we can determine the register corresponding to
11973 // the index in the register group.
11974 const auto VLen = Subtarget.getRealVLen();
11975 if (auto *IdxC = dyn_cast<ConstantSDNode>(Idx);
11976 IdxC && VLen && VecVT.getSizeInBits().getKnownMinValue() > *VLen) {
11977 MVT M1VT = RISCVTargetLowering::getM1VT(ContainerVT);
11978 unsigned OrigIdx = IdxC->getZExtValue();
11979 EVT ElemVT = VecVT.getVectorElementType();
11980 unsigned ElemsPerVReg = *VLen / ElemVT.getFixedSizeInBits();
11981 unsigned RemIdx = OrigIdx % ElemsPerVReg;
11982 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
11983 unsigned ExtractIdx =
11984 SubRegIdx * M1VT.getVectorElementCount().getKnownMinValue();
11985 Vec = DAG.getExtractSubvector(DL, M1VT, Vec, ExtractIdx);
11986 Idx = DAG.getVectorIdxConstant(RemIdx, DL);
11987 ContainerVT = M1VT;
11988 }
11989
11990 // Reduce the LMUL of our slidedown and vmv.x.s to the smallest LMUL which
11991 // contains our index.
11992 std::optional<uint64_t> MaxIdx;
11993 if (VecVT.isFixedLengthVector())
11994 MaxIdx = VecVT.getVectorNumElements() - 1;
11995 if (auto *IdxC = dyn_cast<ConstantSDNode>(Idx))
11996 MaxIdx = IdxC->getZExtValue();
11997 if (MaxIdx) {
11998 if (auto SmallerVT =
11999 getSmallestVTForIndex(ContainerVT, *MaxIdx, DL, DAG, Subtarget)) {
12000 ContainerVT = *SmallerVT;
12001 Vec = DAG.getExtractSubvector(DL, ContainerVT, Vec, 0);
12002 }
12003 }
12004
12005 // If after narrowing, the required slide is still greater than LMUL2,
12006 // fallback to generic expansion and go through the stack. This is done
12007 // for a subtle reason: extracting *all* elements out of a vector is
12008 // widely expected to be linear in vector size, but because vslidedown
12009 // is linear in LMUL, performing N extracts using vslidedown becomes
12010 // O(n^2) / (VLEN/ETYPE) work. On the surface, going through the stack
12011 // seems to have the same problem (the store is linear in LMUL), but the
12012 // generic expansion *memoizes* the store, and thus for many extracts of
12013 // the same vector we end up with one store and a bunch of loads.
12014 // TODO: We don't have the same code for insert_vector_elt because we
12015 // have BUILD_VECTOR and handle the degenerate case there. Should we
12016 // consider adding an inverse BUILD_VECTOR node?
12017 MVT LMUL2VT =
12019 if (ContainerVT.bitsGT(LMUL2VT) && VecVT.isFixedLengthVector())
12020 return SDValue();
12021
12022 // If the index is 0, the vector is already in the right position.
12023 if (!isNullConstant(Idx)) {
12024 // Use a VL of 1 to avoid processing more elements than we need.
12025 auto [Mask, VL] = getDefaultVLOps(1, ContainerVT, DL, DAG, Subtarget);
12026 Vec = getVSlidedown(DAG, Subtarget, DL, ContainerVT,
12027 DAG.getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
12028 }
12029
12030 if (!EltVT.isInteger()) {
12031 // Floating-point extracts are handled in TableGen.
12032 return DAG.getExtractVectorElt(DL, EltVT, Vec, 0);
12033 }
12034
12035 SDValue Elt0 = DAG.getNode(RISCVISD::VMV_X_S, DL, XLenVT, Vec);
12036 return DAG.getNode(ISD::TRUNCATE, DL, EltVT, Elt0);
12037}
12038
12039// Some RVV intrinsics may claim that they want an integer operand to be
12040// promoted or expanded.
12042 const RISCVSubtarget &Subtarget) {
12043 assert((Op.getOpcode() == ISD::INTRINSIC_VOID ||
12044 Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN ||
12045 Op.getOpcode() == ISD::INTRINSIC_W_CHAIN) &&
12046 "Unexpected opcode");
12047
12048 if (!Subtarget.hasVInstructions())
12049 return SDValue();
12050
12051 bool HasChain = Op.getOpcode() == ISD::INTRINSIC_VOID ||
12052 Op.getOpcode() == ISD::INTRINSIC_W_CHAIN;
12053 unsigned IntNo = Op.getConstantOperandVal(HasChain ? 1 : 0);
12054
12055 SDLoc DL(Op);
12056
12058 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
12059 if (!II || !II->hasScalarOperand())
12060 return SDValue();
12061
12062 unsigned SplatOp = II->ScalarOperand + 1 + HasChain;
12063 assert(SplatOp < Op.getNumOperands());
12064
12066 SDValue &ScalarOp = Operands[SplatOp];
12067 MVT OpVT = ScalarOp.getSimpleValueType();
12068 MVT XLenVT = Subtarget.getXLenVT();
12069
12070 // If this isn't a scalar, or its type is XLenVT we're done.
12071 if (!OpVT.isScalarInteger() || OpVT == XLenVT)
12072 return SDValue();
12073
12074 // Simplest case is that the operand needs to be promoted to XLenVT.
12075 if (OpVT.bitsLT(XLenVT)) {
12076 // If the operand is a constant, sign extend to increase our chances
12077 // of being able to use a .vi instruction. ANY_EXTEND would become a
12078 // a zero extend and the simm5 check in isel would fail.
12079 // FIXME: Should we ignore the upper bits in isel instead?
12080 unsigned ExtOpc =
12082 ScalarOp = DAG.getNode(ExtOpc, DL, XLenVT, ScalarOp);
12083 return DAG.getNode(Op->getOpcode(), DL, Op->getVTList(), Operands);
12084 }
12085
12086 // Use the previous operand to get the vXi64 VT. The result might be a mask
12087 // VT for compares. Using the previous operand assumes that the previous
12088 // operand will never have a smaller element size than a scalar operand and
12089 // that a widening operation never uses SEW=64.
12090 // NOTE: If this fails the below assert, we can probably just find the
12091 // element count from any operand or result and use it to construct the VT.
12092 assert(II->ScalarOperand > 0 && "Unexpected splat operand!");
12093 MVT VT = Op.getOperand(SplatOp - 1).getSimpleValueType();
12094
12095 // The more complex case is when the scalar is larger than XLenVT.
12096 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
12097 VT.getVectorElementType() == MVT::i64 && "Unexpected VTs!");
12098
12099 // If this is a sign-extended 32-bit value, we can truncate it and rely on the
12100 // instruction to sign-extend since SEW>XLEN.
12101 if (DAG.ComputeNumSignBits(ScalarOp) > 32) {
12102 ScalarOp = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, ScalarOp);
12103 return DAG.getNode(Op->getOpcode(), DL, Op->getVTList(), Operands);
12104 }
12105
12106 switch (IntNo) {
12107 case Intrinsic::riscv_vslide1up:
12108 case Intrinsic::riscv_vslide1down:
12109 case Intrinsic::riscv_vslide1up_mask:
12110 case Intrinsic::riscv_vslide1down_mask: {
12111 // We need to special case these when the scalar is larger than XLen.
12112 unsigned NumOps = Op.getNumOperands();
12113 bool IsMasked = NumOps == 7;
12114
12115 // Convert the vector source to the equivalent nxvXi32 vector.
12116 MVT I32VT = MVT::getVectorVT(MVT::i32, VT.getVectorElementCount() * 2);
12117 SDValue Vec = DAG.getBitcast(I32VT, Operands[2]);
12118 SDValue ScalarLo, ScalarHi;
12119 std::tie(ScalarLo, ScalarHi) =
12120 DAG.SplitScalar(ScalarOp, DL, MVT::i32, MVT::i32);
12121
12122 // Double the VL since we halved SEW.
12123 SDValue AVL = getVLOperand(Op);
12124 SDValue I32VL;
12125
12126 // Optimize for constant AVL
12127 if (isa<ConstantSDNode>(AVL)) {
12128 const auto [MinVLMAX, MaxVLMAX] =
12130
12131 uint64_t AVLInt = AVL->getAsZExtVal();
12132 if (AVLInt <= MinVLMAX) {
12133 I32VL = DAG.getConstant(2 * AVLInt, DL, XLenVT);
12134 } else if (AVLInt >= 2 * MaxVLMAX) {
12135 // Just set vl to VLMAX in this situation
12136 I32VL = DAG.getRegister(RISCV::X0, XLenVT);
12137 } else {
12138 // For AVL between (MinVLMAX, 2 * MaxVLMAX), the actual working vl
12139 // is related to the hardware implementation.
12140 // So let the following code handle
12141 }
12142 }
12143 if (!I32VL) {
12145 SDValue LMUL = DAG.getConstant(Lmul, DL, XLenVT);
12146 unsigned Sew = RISCVVType::encodeSEW(VT.getScalarSizeInBits());
12147 SDValue SEW = DAG.getConstant(Sew, DL, XLenVT);
12148 SDValue SETVL =
12149 DAG.getTargetConstant(Intrinsic::riscv_vsetvli, DL, MVT::i32);
12150 // Using vsetvli instruction to get actually used length which related to
12151 // the hardware implementation
12152 SDValue VL = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, XLenVT, SETVL, AVL,
12153 SEW, LMUL);
12154 I32VL =
12155 DAG.getNode(ISD::SHL, DL, XLenVT, VL, DAG.getConstant(1, DL, XLenVT));
12156 }
12157
12158 SDValue I32Mask = getAllOnesMask(I32VT, I32VL, DL, DAG);
12159
12160 // Shift the two scalar parts in using SEW=32 slide1up/slide1down
12161 // instructions.
12162 SDValue Passthru;
12163 if (IsMasked)
12164 Passthru = DAG.getUNDEF(I32VT);
12165 else
12166 Passthru = DAG.getBitcast(I32VT, Operands[1]);
12167
12168 if (IntNo == Intrinsic::riscv_vslide1up ||
12169 IntNo == Intrinsic::riscv_vslide1up_mask) {
12170 Vec = DAG.getNode(RISCVISD::VSLIDE1UP_VL, DL, I32VT, Passthru, Vec,
12171 ScalarHi, I32Mask, I32VL);
12172 Vec = DAG.getNode(RISCVISD::VSLIDE1UP_VL, DL, I32VT, Passthru, Vec,
12173 ScalarLo, I32Mask, I32VL);
12174 } else {
12175 Vec = DAG.getNode(RISCVISD::VSLIDE1DOWN_VL, DL, I32VT, Passthru, Vec,
12176 ScalarLo, I32Mask, I32VL);
12177 Vec = DAG.getNode(RISCVISD::VSLIDE1DOWN_VL, DL, I32VT, Passthru, Vec,
12178 ScalarHi, I32Mask, I32VL);
12179 }
12180
12181 // Convert back to nxvXi64.
12182 Vec = DAG.getBitcast(VT, Vec);
12183
12184 if (!IsMasked)
12185 return Vec;
12186 // Apply mask after the operation.
12187 SDValue Mask = Operands[NumOps - 3];
12188 SDValue MaskedOff = Operands[1];
12189 // Assume Policy operand is the last operand.
12190 uint64_t Policy = Operands[NumOps - 1]->getAsZExtVal();
12191 // We don't need to select maskedoff if it's undef.
12192 if (MaskedOff.isUndef())
12193 return Vec;
12194 // TAMU
12195 if (Policy == RISCVVType::TAIL_AGNOSTIC)
12196 return DAG.getNode(RISCVISD::VMERGE_VL, DL, VT, Mask, Vec, MaskedOff,
12197 DAG.getUNDEF(VT), AVL);
12198 // TUMA or TUMU: Currently we always emit tumu policy regardless of tuma.
12199 // It's fine because vmerge does not care mask policy.
12200 return DAG.getNode(RISCVISD::VMERGE_VL, DL, VT, Mask, Vec, MaskedOff,
12201 MaskedOff, AVL);
12202 }
12203 }
12204
12205 // We need to convert the scalar to a splat vector.
12206 SDValue VL = getVLOperand(Op);
12207 assert(VL.getValueType() == XLenVT);
12208 ScalarOp = splatSplitI64WithVL(DL, VT, SDValue(), ScalarOp, VL, DAG);
12209 return DAG.getNode(Op->getOpcode(), DL, Op->getVTList(), Operands);
12210}
12211
12212// Lower the llvm.get.vector.length intrinsic to vsetvli. We only support
12213// scalable vector llvm.get.vector.length for now.
12214//
12215// We need to convert from a scalable VF to a vsetvli with VLMax equal to
12216// (vscale * VF). The vscale and VF are independent of element width. We use
12217// SEW=8 for the vsetvli because it is the only element width that supports all
12218// fractional LMULs. The LMUL is chosen so that with SEW=8 the VLMax is
12219// (vscale * VF). Where vscale is defined as VLEN/RVVBitsPerBlock. The
12220// InsertVSETVLI pass can fix up the vtype of the vsetvli if a different
12221// SEW and LMUL are better for the surrounding vector instructions.
12223 const RISCVSubtarget &Subtarget) {
12224 MVT XLenVT = Subtarget.getXLenVT();
12225
12226 // The smallest LMUL is only valid for the smallest element width.
12227 const unsigned ElementWidth = 8;
12228
12229 // Determine the VF that corresponds to LMUL 1 for ElementWidth.
12230 unsigned LMul1VF = RISCV::RVVBitsPerBlock / ElementWidth;
12231 // We don't support VF==1 with ELEN==32.
12232 [[maybe_unused]] unsigned MinVF =
12233 RISCV::RVVBitsPerBlock / Subtarget.getELen();
12234
12235 [[maybe_unused]] unsigned VF = N->getConstantOperandVal(2);
12236 assert(VF >= MinVF && VF <= (LMul1VF * 8) && isPowerOf2_32(VF) &&
12237 "Unexpected VF");
12238
12239 bool Fractional = VF < LMul1VF;
12240 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
12241 unsigned VLMUL = (unsigned)RISCVVType::encodeLMUL(LMulVal, Fractional);
12242 unsigned VSEW = RISCVVType::encodeSEW(ElementWidth);
12243
12244 SDLoc DL(N);
12245
12246 SDValue LMul = DAG.getTargetConstant(VLMUL, DL, XLenVT);
12247 SDValue Sew = DAG.getTargetConstant(VSEW, DL, XLenVT);
12248
12249 SDValue AVL = DAG.getNode(ISD::ZERO_EXTEND, DL, XLenVT, N->getOperand(1));
12250
12251 SDValue ID = DAG.getTargetConstant(Intrinsic::riscv_vsetvli, DL, XLenVT);
12252 SDValue Res =
12253 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, XLenVT, ID, AVL, Sew, LMul);
12254 return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), Res);
12255}
12256
12258 const RISCVSubtarget &Subtarget) {
12259 SDValue Op0 = Op.getOperand(0);
12260 MVT OpVT = Op0.getSimpleValueType();
12261 MVT ContainerVT = OpVT;
12262 if (OpVT.isFixedLengthVector()) {
12263 ContainerVT = getContainerForFixedLengthVector(OpVT, Subtarget);
12264 Op0 = convertToScalableVector(ContainerVT, Op0, DAG, Subtarget);
12265 }
12266 MVT XLenVT = Subtarget.getXLenVT();
12267 SDLoc DL(Op);
12268 auto [Mask, VL] = getDefaultVLOps(OpVT, ContainerVT, DL, DAG, Subtarget);
12269 SDValue Res = DAG.getNode(RISCVISD::VFIRST_VL, DL, XLenVT, Op0, Mask, VL);
12270 if (Op.getOpcode() == ISD::CTTZ_ELTS_ZERO_POISON)
12271 return Res;
12272
12273 // Convert -1 to VL.
12274 SDValue Setcc =
12275 DAG.getSetCC(DL, XLenVT, Res, DAG.getConstant(0, DL, XLenVT), ISD::SETLT);
12276 VL = DAG.getElementCount(DL, XLenVT, OpVT.getVectorElementCount());
12277 return DAG.getSelect(DL, XLenVT, Setcc, VL, Res);
12278}
12279
12281 const RISCVSubtarget &Subtarget) {
12283 const uint64_t SemEnum = Op->getConstantOperandVal(1);
12284 const auto Sem = static_cast<APFloatBase::Semantics>(SemEnum);
12285
12286 if (Sem != APFloatBase::S_Float8E5M2)
12287 return SDValue();
12288
12289 SDValue Src = Op.getOperand(0);
12290 EVT SrcEVT = Src.getValueType();
12291 if (!SrcEVT.isSimple() || SrcEVT.getVectorElementType() != MVT::i8)
12292 return SDValue();
12293 MVT SrcVT = SrcEVT.getSimpleVT();
12294 MVT DstVT = Op.getSimpleValueType();
12295 assert(DstVT.getVectorElementType() == MVT::bf16);
12296 SDLoc DL(Op);
12297
12298 MVT SrcContainerVT = SrcVT;
12299 MVT DstContainerVT = DstVT;
12300 if (SrcVT.isFixedLengthVector()) {
12301 SrcContainerVT = getContainerForFixedLengthVector(SrcVT, Subtarget);
12302 Src = convertToScalableVector(SrcContainerVT, Src, DAG, Subtarget);
12303 DstContainerVT = getContainerForFixedLengthVector(DstVT, Subtarget);
12304 }
12305 SDValue VL =
12306 getDefaultVLOps(SrcVT, SrcContainerVT, DL, DAG, Subtarget).second;
12307
12308 SDValue Ops[] = {DAG.getTargetConstant(Intrinsic::riscv_vfwcvt_f_f_v_alt, DL,
12309 Subtarget.getXLenVT()),
12310 DAG.getPOISON(DstContainerVT), // Passthru
12311 Src, VL};
12312 SDValue NewVal =
12313 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, DstContainerVT, Ops);
12314 if (SrcVT.isFixedLengthVector())
12315 NewVal = convertFromScalableVector(DstVT, NewVal, DAG, Subtarget);
12316 return NewVal;
12317}
12318
12319static inline void promoteVCIXScalar(SDValue Op,
12321 SelectionDAG &DAG) {
12322 const RISCVSubtarget &Subtarget =
12324
12325 bool HasChain = Op.getOpcode() == ISD::INTRINSIC_VOID ||
12326 Op.getOpcode() == ISD::INTRINSIC_W_CHAIN;
12327 unsigned IntNo = Op.getConstantOperandVal(HasChain ? 1 : 0);
12328 SDLoc DL(Op);
12329
12331 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
12332 if (!II || !II->hasScalarOperand())
12333 return;
12334
12335 unsigned SplatOp = II->ScalarOperand + 1;
12336 assert(SplatOp < Op.getNumOperands());
12337
12338 SDValue &ScalarOp = Operands[SplatOp];
12339 MVT OpVT = ScalarOp.getSimpleValueType();
12340 MVT XLenVT = Subtarget.getXLenVT();
12341
12342 // The code below is partially copied from lowerVectorIntrinsicScalars.
12343 // If this isn't a scalar, or its type is XLenVT we're done.
12344 if (!OpVT.isScalarInteger() || OpVT == XLenVT)
12345 return;
12346
12347 // Manually emit promote operation for scalar operation.
12348 if (OpVT.bitsLT(XLenVT)) {
12349 unsigned ExtOpc =
12351 ScalarOp = DAG.getNode(ExtOpc, DL, XLenVT, ScalarOp);
12352 }
12353}
12354
12355static void processVCIXOperands(SDValue OrigOp,
12357 SelectionDAG &DAG) {
12358 promoteVCIXScalar(OrigOp, Operands, DAG);
12359 const RISCVSubtarget &Subtarget =
12361 for (SDValue &V : Operands) {
12362 EVT ValType = V.getValueType();
12363 if (ValType.isVector() && ValType.isFloatingPoint()) {
12364 MVT InterimIVT =
12365 MVT::getVectorVT(MVT::getIntegerVT(ValType.getScalarSizeInBits()),
12366 ValType.getVectorElementCount());
12367 V = DAG.getBitcast(InterimIVT, V);
12368 }
12369 if (ValType.isFixedLengthVector()) {
12370 MVT OpContainerVT =
12371 getContainerForFixedLengthVector(V.getSimpleValueType(), Subtarget);
12372 V = convertToScalableVector(OpContainerVT, V, DAG, Subtarget);
12373 }
12374 }
12375}
12376
12377// LMUL * VLEN should be greater than or equal to EGS * SEW
12378static inline bool isValidEGW(int EGS, EVT VT,
12379 const RISCVSubtarget &Subtarget) {
12380 return (Subtarget.getRealMinVLen() *
12382 EGS * VT.getScalarSizeInBits();
12383}
12384
12385static unsigned getRVPShiftOpcode(Intrinsic::ID IntNo) {
12386 switch (IntNo) {
12387 default:
12389 "Unexpected RISC-V packed saturating and rounding shift intrinsic");
12390 case Intrinsic::riscv_psll:
12391 return RISCVISD::PSLL;
12392 case Intrinsic::riscv_psrl:
12393 return RISCVISD::PSRL;
12394 case Intrinsic::riscv_psra:
12395 return RISCVISD::PSRA;
12396 case Intrinsic::riscv_pssha:
12397 return RISCVISD::PSSHA;
12398 case Intrinsic::riscv_psshar:
12399 return RISCVISD::PSSHAR;
12400 case Intrinsic::riscv_psshl:
12401 return RISCVISD::PSSHL;
12402 case Intrinsic::riscv_psshlr:
12403 return RISCVISD::PSSHLR;
12404 }
12405}
12406
12408 switch (IntNo) {
12409 default:
12410 llvm_unreachable("Unexpected RISC-V packed narrowing shift intrinsic");
12411 case Intrinsic::riscv_pnsrl:
12412 return RISCVISD::PNSRL;
12413 case Intrinsic::riscv_pnsra:
12414 return RISCVISD::PNSRA;
12415 case Intrinsic::riscv_pnsrar:
12416 return RISCVISD::PNSRAR;
12417 }
12418}
12419
12421 const RISCVSubtarget &Subtarget) {
12422 MVT VT = Src.getSimpleValueType();
12423 MVT PPairVT =
12425 VT.getVectorNumElements() * 2);
12426 Src = DAG.getBitcast(PPairVT, Src);
12427 SDValue Zero = DAG.getNode(ISD::SPLAT_VECTOR, DL, PPairVT,
12428 DAG.getConstant(0, DL, Subtarget.getXLenVT()));
12429 SDValue Res = DAG.getNode(RISCVISD::PPAIRE, DL, PPairVT, Src, Zero);
12430 return DAG.getBitcast(VT, Res);
12431}
12432
12433static unsigned getRVPMulHighOpcode(unsigned IntNo) {
12434 switch (IntNo) {
12435 default:
12436 llvm_unreachable("Unexpected RISC-V packed multiply high intrinsic");
12437 case Intrinsic::riscv_pmulhr:
12438 return RISCVISD::MULHR;
12439 case Intrinsic::riscv_pmulhru:
12440 return RISCVISD::MULHRU;
12441 case Intrinsic::riscv_pmulhsu:
12442 return RISCVISD::MULHSU;
12443 case Intrinsic::riscv_pmulhrsu:
12444 return RISCVISD::MULHRSU;
12445 }
12446}
12447
12448static unsigned getRVScalarMulHighOpcode(unsigned IntNo) {
12449 switch (IntNo) {
12450 default:
12451 llvm_unreachable("Unexpected RISC-V scalar multiply high intrinsic");
12452 case Intrinsic::riscv_mulhr_i32:
12453 return RISCVISD::MULHR;
12454 case Intrinsic::riscv_mulhru_u32:
12455 return RISCVISD::MULHRU;
12456 case Intrinsic::riscv_mulhsu_i32:
12457 return RISCVISD::MULHSU;
12458 case Intrinsic::riscv_mulhrsu_i32:
12459 return RISCVISD::MULHRSU;
12460 }
12461}
12462
12463static unsigned getRVPMulHighAccumulateOpcode(unsigned IntNo) {
12464 switch (IntNo) {
12465 default:
12467 "Unexpected RISC-V packed multiply high accumulate intrinsic");
12468 case Intrinsic::riscv_pmhacc:
12469 return RISCVISD::MHACC;
12470 case Intrinsic::riscv_pmhracc:
12471 return RISCVISD::MHRACC;
12472 case Intrinsic::riscv_pmhaccu:
12473 return RISCVISD::MHACCU;
12474 case Intrinsic::riscv_pmhraccu:
12475 return RISCVISD::MHRACCU;
12476 case Intrinsic::riscv_pmhaccsu:
12477 return RISCVISD::MHACCSU;
12478 case Intrinsic::riscv_pmhraccsu:
12479 return RISCVISD::MHRACCSU;
12480 }
12481}
12482
12483/// Return the multiply high accumulate node for \p IntNo.
12484static unsigned getRVPMulHighAccumulateByHalvesOpcode(unsigned IntNo) {
12485 switch (IntNo) {
12486 default:
12487 llvm_unreachable("Unexpected RISC-V packed multiply high accumulate by "
12488 "halves intrinsic");
12489 case Intrinsic::riscv_pmhacc_b0:
12490 return RISCVISD::MHACC_H_B0;
12491 case Intrinsic::riscv_pmhacc_b1:
12492 return RISCVISD::MHACC_H_B1;
12493 case Intrinsic::riscv_pmhaccsu_b0:
12494 return RISCVISD::MHACCSU_H_B0;
12495 case Intrinsic::riscv_pmhaccsu_b1:
12496 return RISCVISD::MHACCSU_H_B1;
12497 case Intrinsic::riscv_pmhacc_h0:
12498 return RISCVISD::MHACC_W_H0;
12499 case Intrinsic::riscv_pmhacc_h1:
12500 return RISCVISD::MHACC_W_H1;
12501 case Intrinsic::riscv_pmhaccsu_h0:
12502 return RISCVISD::MHACCSU_W_H0;
12503 case Intrinsic::riscv_pmhaccsu_h1:
12504 return RISCVISD::MHACCSU_W_H1;
12505 }
12506}
12507
12508/// Return the multiply-high-parts node for a multiply-high-parts intrinsic.
12509/// The scalar spelling maps to the same node; its product is the first
12510/// element.
12511static unsigned getRVPMulHighPartsOpcode(unsigned IntNo) {
12512 switch (IntNo) {
12513 default:
12514 llvm_unreachable("Unexpected RISC-V multiply-high-parts intrinsic");
12515 case Intrinsic::riscv_pmulh_b0:
12516 return RISCVISD::PMULH_H_B0;
12517 case Intrinsic::riscv_pmulh_b1:
12518 return RISCVISD::PMULH_H_B1;
12519 case Intrinsic::riscv_pmulhsu_b0:
12520 return RISCVISD::PMULHSU_H_B0;
12521 case Intrinsic::riscv_pmulhsu_b1:
12522 return RISCVISD::PMULHSU_H_B1;
12523 }
12524}
12525
12526/// Return the word multiply-high-parts node for a word multiply-high-parts
12527/// intrinsic. The scalar spelling maps to the same node; its product is the
12528/// first element.
12529static unsigned getRVPMulHighPartsWOpcode(unsigned IntNo) {
12530 switch (IntNo) {
12531 default:
12532 llvm_unreachable("Unexpected RISC-V word multiply-high-parts intrinsic");
12533 case Intrinsic::riscv_pmulh_h0:
12534 case Intrinsic::riscv_mulh_h0:
12535 return RISCVISD::PMULH_W_H0;
12536 case Intrinsic::riscv_pmulh_h1:
12537 case Intrinsic::riscv_mulh_h1:
12538 return RISCVISD::PMULH_W_H1;
12539 case Intrinsic::riscv_pmulhsu_h0:
12540 case Intrinsic::riscv_mulhsu_h0:
12541 return RISCVISD::PMULHSU_W_H0;
12542 case Intrinsic::riscv_pmulhsu_h1:
12543 case Intrinsic::riscv_mulhsu_h1:
12544 return RISCVISD::PMULHSU_W_H1;
12545 }
12546}
12547
12548/// Return the scalar halfword multiply-high-parts node for \p IntNo (RV32
12549/// mulh.h0/h1). The packed word spelling maps to the same node; its product
12550/// is the first element.
12551static unsigned getRVPScalarMulHighPartsOpcode(unsigned IntNo) {
12552 switch (IntNo) {
12553 default:
12554 llvm_unreachable("Unexpected RISC-V scalar multiply-high-parts intrinsic");
12555 case Intrinsic::riscv_pmulh_h0:
12556 case Intrinsic::riscv_mulh_h0:
12557 return RISCVISD::MULH_H0;
12558 case Intrinsic::riscv_pmulh_h1:
12559 case Intrinsic::riscv_mulh_h1:
12560 return RISCVISD::MULH_H1;
12561 case Intrinsic::riscv_pmulhsu_h0:
12562 case Intrinsic::riscv_mulhsu_h0:
12563 return RISCVISD::MULHSU_H0;
12564 case Intrinsic::riscv_pmulhsu_h1:
12565 case Intrinsic::riscv_mulhsu_h1:
12566 return RISCVISD::MULHSU_H1;
12567 }
12568}
12569
12571 switch (IntNo) {
12572 default:
12573 llvm_unreachable("Unexpected RISC-V packed Q-format accumulate intrinsic");
12574 case Intrinsic::riscv_mqacc_00:
12575 case Intrinsic::riscv_pmqacc_h00:
12576 return RISCVISD::MQACC_00;
12577 case Intrinsic::riscv_mqacc_01:
12578 case Intrinsic::riscv_pmqacc_h01:
12579 return RISCVISD::MQACC_01;
12580 case Intrinsic::riscv_mqacc_11:
12581 case Intrinsic::riscv_pmqacc_h11:
12582 return RISCVISD::MQACC_11;
12583 case Intrinsic::riscv_mqracc_00:
12584 case Intrinsic::riscv_pmqracc_h00:
12585 return RISCVISD::MQRACC_00;
12586 case Intrinsic::riscv_mqracc_01:
12587 case Intrinsic::riscv_pmqracc_h01:
12588 return RISCVISD::MQRACC_01;
12589 case Intrinsic::riscv_mqracc_11:
12590 case Intrinsic::riscv_pmqracc_h11:
12591 return RISCVISD::MQRACC_11;
12592 }
12593}
12594
12596 switch (IntNo) {
12597 default:
12598 llvm_unreachable("Unexpected RISC-V packed Q-format accumulate intrinsic");
12599 case Intrinsic::riscv_mqacc_00:
12600 case Intrinsic::riscv_pmqacc_h00:
12601 return RISCVISD::PMQACC_W_H00;
12602 case Intrinsic::riscv_mqacc_01:
12603 case Intrinsic::riscv_pmqacc_h01:
12604 return RISCVISD::PMQACC_W_H01;
12605 case Intrinsic::riscv_mqacc_11:
12606 case Intrinsic::riscv_pmqacc_h11:
12607 return RISCVISD::PMQACC_W_H11;
12608 case Intrinsic::riscv_mqracc_00:
12609 case Intrinsic::riscv_pmqracc_h00:
12610 return RISCVISD::PMQRACC_W_H00;
12611 case Intrinsic::riscv_mqracc_01:
12612 case Intrinsic::riscv_pmqracc_h01:
12613 return RISCVISD::PMQRACC_W_H01;
12614 case Intrinsic::riscv_mqracc_11:
12615 case Intrinsic::riscv_pmqracc_h11:
12616 return RISCVISD::PMQRACC_W_H11;
12617 }
12618}
12619
12620static unsigned getRVPHorizontalMulOpcode(unsigned IntNo) {
12621 switch (IntNo) {
12622 default:
12623 llvm_unreachable("Unexpected RISC-V packed horizontal multiply intrinsic");
12624 case Intrinsic::riscv_pm4add:
12625 return RISCVISD::PM4ADD;
12626 case Intrinsic::riscv_pm2add:
12627 return RISCVISD::PM2ADD;
12628 case Intrinsic::riscv_pm2add_x:
12629 return RISCVISD::PM2ADD_X;
12630 case Intrinsic::riscv_pm4addu:
12631 return RISCVISD::PM4ADDU;
12632 case Intrinsic::riscv_pm2addu:
12633 return RISCVISD::PM2ADDU;
12634 case Intrinsic::riscv_pmq2add:
12635 return RISCVISD::PMQ2ADD;
12636 case Intrinsic::riscv_pmqr2add:
12637 return RISCVISD::PMQR2ADD;
12638 case Intrinsic::riscv_pm2sadd:
12639 return RISCVISD::PM2SADD;
12640 case Intrinsic::riscv_pm2sadd_x:
12641 return RISCVISD::PM2SADD_X;
12642 case Intrinsic::riscv_pm2sub:
12643 return RISCVISD::PM2SUB;
12644 case Intrinsic::riscv_pm2sub_x:
12645 return RISCVISD::PM2SUB_X;
12646 case Intrinsic::riscv_pm4addsu:
12647 return RISCVISD::PM4ADDSU;
12648 case Intrinsic::riscv_pm2addsu:
12649 return RISCVISD::PM2ADDSU;
12650 }
12651}
12652
12653static SDValue lowerRV32HorizontalMul64(unsigned IntNo, SDValue Rs1,
12654 SDValue Rs2, const SDLoc &DL,
12655 SelectionDAG &DAG) {
12656 auto Extract = [&](SDValue V, unsigned Idx) {
12657 return DAG.getExtractVectorElt(DL, MVT::i32, V, Idx);
12658 };
12659
12660 if (Rs1.getSimpleValueType() == MVT::v4i16) {
12661 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL);
12662 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
12663 unsigned MulOpc, AccOpc;
12664 switch (IntNo) {
12665 default:
12666 llvm_unreachable("Unexpected RV32 horizontal multiply intrinsic");
12667 case Intrinsic::riscv_pm4add:
12668 MulOpc = RISCVISD::PM2WADD;
12669 AccOpc = RISCVISD::PM2WADDA;
12670 break;
12671 case Intrinsic::riscv_pm4addu:
12672 MulOpc = RISCVISD::PM2WADDU;
12673 AccOpc = RISCVISD::PM2WADDAU;
12674 break;
12675 case Intrinsic::riscv_pm4addsu:
12676 MulOpc = RISCVISD::PM2WADDSU;
12677 AccOpc = RISCVISD::PM2WADDASU;
12678 break;
12679 }
12680 SDValue Acc = DAG.getNode(MulOpc, DL, MVT::v2i32, Rs1Lo, Rs2Lo);
12681 Acc = DAG.getNode(AccOpc, DL, MVT::v2i32, Acc, Rs1Hi, Rs2Hi);
12682 return DAG.getBitcast(MVT::i64, Acc);
12683 }
12684
12685 assert(Rs1.getSimpleValueType() == MVT::v2i32 &&
12686 "Unexpected RV32 horizontal multiply source type");
12687 SDValue Rs1Lo = Extract(Rs1, 0);
12688 SDValue Rs1Hi = Extract(Rs1, 1);
12689 SDValue Rs2Lo = Extract(Rs2, 0);
12690 SDValue Rs2Hi = Extract(Rs2, 1);
12691
12692 if (IntNo == Intrinsic::riscv_pmq2add || IntNo == Intrinsic::riscv_pmqr2add) {
12693 unsigned AccOpc = IntNo == Intrinsic::riscv_pmq2add ? RISCVISD::MQWACC
12694 : RISCVISD::MQRWACC;
12695 SDVTList VTs = DAG.getVTList(MVT::i32, MVT::i32);
12696 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
12697 SDValue Acc = DAG.getNode(AccOpc, DL, VTs, {Zero, Zero, Rs1Lo, Rs2Lo});
12698 Acc = DAG.getNode(AccOpc, DL, VTs, {Acc, Acc.getValue(1), Rs1Hi, Rs2Hi});
12699 return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Acc, Acc.getValue(1));
12700 }
12701
12702 unsigned MulOpc = ISD::SMUL_LOHI;
12703 if (IntNo == Intrinsic::riscv_pm2addu)
12704 MulOpc = ISD::UMUL_LOHI;
12705 else if (IntNo == Intrinsic::riscv_pm2addsu)
12706 MulOpc = RISCVISD::WMULSU;
12707 bool IsSub =
12708 IntNo == Intrinsic::riscv_pm2sub || IntNo == Intrinsic::riscv_pm2sub_x;
12709 if (IntNo == Intrinsic::riscv_pm2add_x || IntNo == Intrinsic::riscv_pm2sub_x)
12710 std::swap(Rs2Lo, Rs2Hi);
12711
12712 SDVTList VTs = DAG.getVTList(MVT::i32, MVT::i32);
12713 SDValue LoMul = DAG.getNode(MulOpc, DL, VTs, Rs1Lo, Rs2Lo);
12714 SDValue HiMul = DAG.getNode(MulOpc, DL, VTs, Rs1Hi, Rs2Hi);
12715 unsigned Opc = IsSub ? RISCVISD::SUBD : RISCVISD::ADDD;
12716 SDValue Res = DAG.getNode(Opc, DL, VTs, LoMul, LoMul.getValue(1), HiMul,
12717 HiMul.getValue(1));
12718 return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Res, Res.getValue(1));
12719}
12720
12721/// Return the packed multiply-halves node for a multiply-parts intrinsic. The
12722/// scalar spelling maps to the same node; its product is the first element.
12723static unsigned getRVPMulHalvesOpcode(unsigned IntNo) {
12724 switch (IntNo) {
12725 default:
12726 llvm_unreachable("Unexpected RISC-V multiply-parts intrinsic");
12727 case Intrinsic::riscv_pmul_00:
12728 case Intrinsic::riscv_mul_00:
12729 return RISCVISD::PMUL_HALVES_00;
12730 case Intrinsic::riscv_pmul_01:
12731 case Intrinsic::riscv_mul_01:
12732 return RISCVISD::PMUL_HALVES_01;
12733 case Intrinsic::riscv_pmul_11:
12734 case Intrinsic::riscv_mul_11:
12735 return RISCVISD::PMUL_HALVES_11;
12736 case Intrinsic::riscv_pmulu_00:
12737 case Intrinsic::riscv_mulu_00:
12738 return RISCVISD::PMULU_HALVES_00;
12739 case Intrinsic::riscv_pmulu_01:
12740 case Intrinsic::riscv_mulu_01:
12741 return RISCVISD::PMULU_HALVES_01;
12742 case Intrinsic::riscv_pmulu_11:
12743 case Intrinsic::riscv_mulu_11:
12744 return RISCVISD::PMULU_HALVES_11;
12745 case Intrinsic::riscv_pmulsu_00:
12746 case Intrinsic::riscv_mulsu_00:
12747 return RISCVISD::PMULSU_HALVES_00;
12748 case Intrinsic::riscv_pmulsu_11:
12749 case Intrinsic::riscv_mulsu_11:
12750 return RISCVISD::PMULSU_HALVES_11;
12751 }
12752}
12753
12754/// Return the scalar multiply-parts intrinsic computing the first product of
12755/// packed intrinsic \p IntNo.
12757 switch (IntNo) {
12758 default:
12759 llvm_unreachable("Unexpected RISC-V packed multiply-parts intrinsic");
12760 case Intrinsic::riscv_pmul_00:
12761 return Intrinsic::riscv_mul_00;
12762 case Intrinsic::riscv_pmul_01:
12763 return Intrinsic::riscv_mul_01;
12764 case Intrinsic::riscv_pmul_11:
12765 return Intrinsic::riscv_mul_11;
12766 case Intrinsic::riscv_pmulu_00:
12767 return Intrinsic::riscv_mulu_00;
12768 case Intrinsic::riscv_pmulu_01:
12769 return Intrinsic::riscv_mulu_01;
12770 case Intrinsic::riscv_pmulu_11:
12771 return Intrinsic::riscv_mulu_11;
12772 case Intrinsic::riscv_pmulsu_00:
12773 return Intrinsic::riscv_mulsu_00;
12774 case Intrinsic::riscv_pmulsu_11:
12775 return Intrinsic::riscv_mulsu_11;
12776 }
12777}
12778
12779/// Return the accumulate form of multiply-parts intrinsic \p IntNo, or
12780/// Intrinsic::not_intrinsic if there is none.
12782 switch (IntNo) {
12783 default:
12785 case Intrinsic::riscv_mul_00:
12786 return Intrinsic::riscv_macc_00;
12787 case Intrinsic::riscv_pmul_00:
12788 return Intrinsic::riscv_pmacc_00;
12789 case Intrinsic::riscv_mul_01:
12790 return Intrinsic::riscv_macc_01;
12791 case Intrinsic::riscv_pmul_01:
12792 return Intrinsic::riscv_pmacc_01;
12793 case Intrinsic::riscv_mul_11:
12794 return Intrinsic::riscv_macc_11;
12795 case Intrinsic::riscv_pmul_11:
12796 return Intrinsic::riscv_pmacc_11;
12797 case Intrinsic::riscv_mulu_00:
12798 return Intrinsic::riscv_maccu_00;
12799 case Intrinsic::riscv_pmulu_00:
12800 return Intrinsic::riscv_pmaccu_00;
12801 case Intrinsic::riscv_mulu_01:
12802 return Intrinsic::riscv_maccu_01;
12803 case Intrinsic::riscv_pmulu_01:
12804 return Intrinsic::riscv_pmaccu_01;
12805 case Intrinsic::riscv_mulu_11:
12806 return Intrinsic::riscv_maccu_11;
12807 case Intrinsic::riscv_pmulu_11:
12808 return Intrinsic::riscv_pmaccu_11;
12809 case Intrinsic::riscv_mulsu_00:
12810 return Intrinsic::riscv_maccsu_00;
12811 case Intrinsic::riscv_pmulsu_00:
12812 return Intrinsic::riscv_pmaccsu_00;
12813 case Intrinsic::riscv_mulsu_11:
12814 return Intrinsic::riscv_maccsu_11;
12815 case Intrinsic::riscv_pmulsu_11:
12816 return Intrinsic::riscv_pmaccsu_11;
12817 }
12818}
12819
12820/// Return the multiply-parts accumulate node for \p IntNo.
12821static unsigned getRVPMulAccHalvesOpcode(unsigned IntNo) {
12822 switch (IntNo) {
12823 default:
12824 llvm_unreachable("Unexpected RISC-V multiply-parts accumulate intrinsic");
12825 case Intrinsic::riscv_pmacc_00:
12826 case Intrinsic::riscv_macc_00:
12827 return RISCVISD::PMACC_HALVES_00;
12828 case Intrinsic::riscv_pmacc_01:
12829 case Intrinsic::riscv_macc_01:
12830 return RISCVISD::PMACC_HALVES_01;
12831 case Intrinsic::riscv_pmacc_11:
12832 case Intrinsic::riscv_macc_11:
12833 return RISCVISD::PMACC_HALVES_11;
12834 case Intrinsic::riscv_pmaccu_00:
12835 case Intrinsic::riscv_maccu_00:
12836 return RISCVISD::PMACCU_HALVES_00;
12837 case Intrinsic::riscv_pmaccu_01:
12838 case Intrinsic::riscv_maccu_01:
12839 return RISCVISD::PMACCU_HALVES_01;
12840 case Intrinsic::riscv_pmaccu_11:
12841 case Intrinsic::riscv_maccu_11:
12842 return RISCVISD::PMACCU_HALVES_11;
12843 case Intrinsic::riscv_pmaccsu_00:
12844 case Intrinsic::riscv_maccsu_00:
12845 return RISCVISD::PMACCSU_HALVES_00;
12846 case Intrinsic::riscv_pmaccsu_11:
12847 case Intrinsic::riscv_maccsu_11:
12848 return RISCVISD::PMACCSU_HALVES_11;
12849 }
12850}
12851
12852/// Return {opcode, rs1 lane, rs2 lane} for the word form of \p IntNo.
12853static std::tuple<unsigned, unsigned, unsigned>
12855 switch (IntNo) {
12856 default:
12857 llvm_unreachable("Unexpected RISC-V multiply-parts intrinsic");
12858 case Intrinsic::riscv_mul_00:
12859 return {ISD::SMUL_LOHI, 0, 0};
12860 case Intrinsic::riscv_mul_01:
12861 return {ISD::SMUL_LOHI, 0, 1};
12862 case Intrinsic::riscv_mul_11:
12863 return {ISD::SMUL_LOHI, 1, 1};
12864 case Intrinsic::riscv_mulu_00:
12865 return {ISD::UMUL_LOHI, 0, 0};
12866 case Intrinsic::riscv_mulu_01:
12867 return {ISD::UMUL_LOHI, 0, 1};
12868 case Intrinsic::riscv_mulu_11:
12869 return {ISD::UMUL_LOHI, 1, 1};
12870 case Intrinsic::riscv_mulsu_00:
12871 return {RISCVISD::WMULSU, 0, 0};
12872 case Intrinsic::riscv_mulsu_11:
12873 return {RISCVISD::WMULSU, 1, 1};
12874 }
12875}
12876
12877/// Return {opcode, rs1 lane, rs2 lane} for the word form of accumulate
12878/// intrinsic \p IntNo.
12879static std::tuple<unsigned, unsigned, unsigned>
12881 switch (IntNo) {
12882 default:
12883 llvm_unreachable("Unexpected RISC-V multiply-parts accumulate intrinsic");
12884 case Intrinsic::riscv_macc_00:
12885 return {RISCVISD::WMACC, 0, 0};
12886 case Intrinsic::riscv_macc_01:
12887 return {RISCVISD::WMACC, 0, 1};
12888 case Intrinsic::riscv_macc_11:
12889 return {RISCVISD::WMACC, 1, 1};
12890 case Intrinsic::riscv_maccu_00:
12891 return {RISCVISD::WMACCU, 0, 0};
12892 case Intrinsic::riscv_maccu_01:
12893 return {RISCVISD::WMACCU, 0, 1};
12894 case Intrinsic::riscv_maccu_11:
12895 return {RISCVISD::WMACCU, 1, 1};
12896 case Intrinsic::riscv_maccsu_00:
12897 return {RISCVISD::WMACCSU, 0, 0};
12898 case Intrinsic::riscv_maccsu_11:
12899 return {RISCVISD::WMACCSU, 1, 1};
12900 }
12901}
12902
12903SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
12904 SelectionDAG &DAG) const {
12905 unsigned IntNo = Op.getConstantOperandVal(0);
12906 SDLoc DL(Op);
12907 MVT XLenVT = Subtarget.getXLenVT();
12908
12909 switch (IntNo) {
12910 default:
12911 break; // Don't custom lower most intrinsics.
12912 case Intrinsic::riscv_tuple_insert: {
12913 SDValue Vec = Op.getOperand(1);
12914 SDValue SubVec = Op.getOperand(2);
12915 SDValue Index = Op.getOperand(3);
12916
12917 return DAG.getNode(RISCVISD::TUPLE_INSERT, DL, Op.getValueType(), Vec,
12918 SubVec, Index);
12919 }
12920 case Intrinsic::riscv_tuple_extract: {
12921 SDValue Vec = Op.getOperand(1);
12922 SDValue Index = Op.getOperand(2);
12923
12924 return DAG.getNode(RISCVISD::TUPLE_EXTRACT, DL, Op.getValueType(), Vec,
12925 Index);
12926 }
12927 case Intrinsic::thread_pointer: {
12928 EVT PtrVT = getPointerTy(DAG.getDataLayout());
12929 return DAG.getRegister(RISCV::X4, PtrVT);
12930 }
12931 case Intrinsic::riscv_pmul_00:
12932 case Intrinsic::riscv_pmul_01:
12933 case Intrinsic::riscv_pmul_11:
12934 case Intrinsic::riscv_pmulu_00:
12935 case Intrinsic::riscv_pmulu_01:
12936 case Intrinsic::riscv_pmulu_11:
12937 case Intrinsic::riscv_pmulsu_00:
12938 case Intrinsic::riscv_pmulsu_11: {
12939 MVT VT = Op.getSimpleValueType();
12940 SDValue Rs1 = Op.getOperand(1);
12941 SDValue Rs2 = Op.getOperand(2);
12942 unsigned Opc = getRVPMulHalvesOpcode(IntNo);
12943 if (!Subtarget.isPExtPackedDoubleType(VT))
12944 return DAG.getNode(Opc, DL, VT, Rs1, Rs2);
12945
12946 // On RV32 a 64-bit result lives in a GPR pair; compute each half with the
12947 // 32-bit form of the same product.
12948 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL);
12949 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
12950 if (VT == MVT::v2i32) {
12951 // Each half is a single product, described by the scalar intrinsic.
12953 DL, MVT::i32);
12954 SDValue Lo =
12955 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32, Id, Rs1Lo, Rs2Lo);
12956 SDValue Hi =
12957 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32, Id, Rs1Hi, Rs2Hi);
12958 return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
12959 }
12960 MVT HalfVT = VT.getHalfNumVectorElementsVT();
12961 SDValue Lo = DAG.getNode(Opc, DL, HalfVT, Rs1Lo, Rs2Lo);
12962 SDValue Hi = DAG.getNode(Opc, DL, HalfVT, Rs1Hi, Rs2Hi);
12963 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi);
12964 }
12965 case Intrinsic::riscv_pmacc_00:
12966 case Intrinsic::riscv_pmacc_01:
12967 case Intrinsic::riscv_pmacc_11:
12968 case Intrinsic::riscv_pmaccu_00:
12969 case Intrinsic::riscv_pmaccu_01:
12970 case Intrinsic::riscv_pmaccu_11:
12971 case Intrinsic::riscv_pmaccsu_00:
12972 case Intrinsic::riscv_pmaccsu_11:
12973 case Intrinsic::riscv_macc_00:
12974 case Intrinsic::riscv_macc_01:
12975 case Intrinsic::riscv_macc_11:
12976 case Intrinsic::riscv_maccu_00:
12977 case Intrinsic::riscv_maccu_01:
12978 case Intrinsic::riscv_maccu_11:
12979 case Intrinsic::riscv_maccsu_00:
12980 case Intrinsic::riscv_maccsu_11: {
12981 MVT VT = Op.getSimpleValueType();
12982 SDValue Rd = Op.getOperand(1);
12983 SDValue Rs1 = Op.getOperand(2);
12984 SDValue Rs2 = Op.getOperand(3);
12985 unsigned Opc = getRVPMulAccHalvesOpcode(IntNo);
12986 if (VT != MVT::v2i32 || !Subtarget.isPExtPackedDoubleType(VT))
12987 return DAG.getNode(Opc, DL, VT, Rd, Rs1, Rs2);
12988
12989 // On RV32 a 64-bit result lives in a GPR pair; accumulate each half with
12990 // the 32-bit form of the same product.
12991 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL);
12992 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
12993 SDValue Lo =
12994 DAG.getNode(Opc, DL, MVT::i32,
12995 DAG.getExtractVectorElt(DL, MVT::i32, Rd, 0), Rs1Lo, Rs2Lo);
12996 SDValue Hi =
12997 DAG.getNode(Opc, DL, MVT::i32,
12998 DAG.getExtractVectorElt(DL, MVT::i32, Rd, 1), Rs1Hi, Rs2Hi);
12999 return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
13000 }
13001 case Intrinsic::riscv_pas:
13002 case Intrinsic::riscv_psa:
13003 case Intrinsic::riscv_psas:
13004 case Intrinsic::riscv_pssa:
13005 case Intrinsic::riscv_paas:
13006 case Intrinsic::riscv_pasa: {
13007 // v2i32 has no paired instruction on RV32; split into a pair of i32 ops
13008 // with cross-lane operands. The exchange shape is: even result uses
13009 // (S1[0], S2[1]); odd result uses (S1[1], S2[0]).
13010 if (Subtarget.is64Bit() || Op.getSimpleValueType() != MVT::v2i32)
13011 break;
13012
13013 unsigned EvenOpc, OddOpc;
13014 switch (IntNo) {
13015 case Intrinsic::riscv_pas:
13016 EvenOpc = ISD::SUB;
13017 OddOpc = ISD::ADD;
13018 break;
13019 case Intrinsic::riscv_psa:
13020 EvenOpc = ISD::ADD;
13021 OddOpc = ISD::SUB;
13022 break;
13023 case Intrinsic::riscv_psas:
13024 EvenOpc = ISD::SSUBSAT;
13025 OddOpc = ISD::SADDSAT;
13026 break;
13027 case Intrinsic::riscv_pssa:
13028 EvenOpc = ISD::SADDSAT;
13029 OddOpc = ISD::SSUBSAT;
13030 break;
13031 case Intrinsic::riscv_paas:
13032 EvenOpc = RISCVISD::ASUB;
13033 OddOpc = ISD::AVGFLOORS;
13034 break;
13035 case Intrinsic::riscv_pasa:
13036 EvenOpc = ISD::AVGFLOORS;
13037 OddOpc = RISCVISD::ASUB;
13038 break;
13039 default:
13040 llvm_unreachable("Unexpected exchanged add/sub intrinsic");
13041 }
13042
13043 SDValue S1 = Op.getOperand(1);
13044 SDValue S2 = Op.getOperand(2);
13045 SDValue S1Even = DAG.getExtractVectorElt(DL, MVT::i32, S1, 0);
13046 SDValue S1Odd = DAG.getExtractVectorElt(DL, MVT::i32, S1, 1);
13047 SDValue S2Even = DAG.getExtractVectorElt(DL, MVT::i32, S2, 0);
13048 SDValue S2Odd = DAG.getExtractVectorElt(DL, MVT::i32, S2, 1);
13049
13050 SDValue REven = DAG.getNode(EvenOpc, DL, MVT::i32, S1Even, S2Odd);
13051 SDValue ROdd = DAG.getNode(OddOpc, DL, MVT::i32, S1Odd, S2Even);
13052 return DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v2i32, REven, ROdd);
13053 }
13054 case Intrinsic::riscv_orc_b:
13055 case Intrinsic::riscv_brev8:
13056 case Intrinsic::riscv_sha256sig0:
13057 case Intrinsic::riscv_sha256sig1:
13058 case Intrinsic::riscv_sha256sum0:
13059 case Intrinsic::riscv_sha256sum1:
13060 case Intrinsic::riscv_sm3p0:
13061 case Intrinsic::riscv_sm3p1: {
13062 unsigned Opc;
13063 switch (IntNo) {
13064 case Intrinsic::riscv_orc_b: Opc = RISCVISD::ORC_B; break;
13065 case Intrinsic::riscv_brev8: Opc = RISCVISD::BREV8; break;
13066 case Intrinsic::riscv_sha256sig0: Opc = RISCVISD::SHA256SIG0; break;
13067 case Intrinsic::riscv_sha256sig1: Opc = RISCVISD::SHA256SIG1; break;
13068 case Intrinsic::riscv_sha256sum0: Opc = RISCVISD::SHA256SUM0; break;
13069 case Intrinsic::riscv_sha256sum1: Opc = RISCVISD::SHA256SUM1; break;
13070 case Intrinsic::riscv_sm3p0: Opc = RISCVISD::SM3P0; break;
13071 case Intrinsic::riscv_sm3p1: Opc = RISCVISD::SM3P1; break;
13072 }
13073
13074 return DAG.getNode(Opc, DL, XLenVT, Op.getOperand(1));
13075 }
13076 case Intrinsic::riscv_sm4ks:
13077 case Intrinsic::riscv_sm4ed: {
13078 unsigned Opc =
13079 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
13080
13081 return DAG.getNode(Opc, DL, XLenVT, Op.getOperand(1), Op.getOperand(2),
13082 Op.getOperand(3));
13083 }
13084 case Intrinsic::riscv_zip:
13085 case Intrinsic::riscv_unzip: {
13086 unsigned Opc =
13087 IntNo == Intrinsic::riscv_zip ? RISCVISD::ZIP : RISCVISD::UNZIP;
13088 return DAG.getNode(Opc, DL, XLenVT, Op.getOperand(1));
13089 }
13090 case Intrinsic::riscv_mopr:
13091 return DAG.getNode(RISCVISD::MOP_R, DL, XLenVT, Op.getOperand(1),
13092 Op.getOperand(2));
13093
13094 case Intrinsic::riscv_moprr: {
13095 return DAG.getNode(RISCVISD::MOP_RR, DL, XLenVT, Op.getOperand(1),
13096 Op.getOperand(2), Op.getOperand(3));
13097 }
13098 case Intrinsic::riscv_clmulh:
13099 case Intrinsic::riscv_clmulr: {
13100 unsigned Opc = IntNo == Intrinsic::riscv_clmulh ? ISD::CLMULH : ISD::CLMULR;
13101 return DAG.getNode(Opc, DL, XLenVT, Op.getOperand(1), Op.getOperand(2));
13102 }
13103 case Intrinsic::riscv_paadd:
13104 case Intrinsic::riscv_paaddu:
13105 case Intrinsic::riscv_pasub:
13106 case Intrinsic::riscv_pasubu:
13107 case Intrinsic::riscv_pabd:
13108 case Intrinsic::riscv_pabdu:
13109 case Intrinsic::riscv_psabs: {
13110 unsigned Opc;
13111 switch (IntNo) {
13112 case Intrinsic::riscv_paadd:
13114 break;
13115 case Intrinsic::riscv_paaddu:
13117 break;
13118 case Intrinsic::riscv_pasub:
13119 Opc = RISCVISD::ASUB;
13120 break;
13121 case Intrinsic::riscv_pasubu:
13122 Opc = RISCVISD::ASUBU;
13123 break;
13124 case Intrinsic::riscv_pabd:
13125 Opc = ISD::ABDS;
13126 break;
13127 case Intrinsic::riscv_pabdu:
13128 Opc = ISD::ABDU;
13129 break;
13130 case Intrinsic::riscv_psabs:
13131 Opc = RISCVISD::PSABS;
13132 break;
13133 }
13134
13135 if (IntNo == Intrinsic::riscv_psabs)
13136 return DAG.getNode(Opc, DL, Op.getValueType(), Op.getOperand(1));
13137
13138 return DAG.getNode(Opc, DL, Op.getValueType(), Op.getOperand(1),
13139 Op.getOperand(2));
13140 }
13141 case Intrinsic::riscv_pnclipp:
13142 case Intrinsic::riscv_pnclipup: {
13143 bool IsSigned = IntNo == Intrinsic::riscv_pnclipp;
13144 EVT VT = Op.getValueType();
13145 SDValue Rs1 = Op.getOperand(1);
13146 SDValue Rs2 = Op.getOperand(2);
13147 if (Subtarget.is64Bit()) {
13148 if (VT == MVT::v2i32 && !Rs1.getValueType().isVector()) {
13149 unsigned WOpc = IsSigned ? RISCVISD::PNCLIPP_W : RISCVISD::PNCLIPUP_W;
13150 return DAG.getNode(WOpc, DL, VT, Rs1, Rs2);
13151 }
13152 unsigned Opc = IsSigned ? RISCVISD::PNCLIPP : RISCVISD::PNCLIPUP;
13153 return DAG.getNode(Opc, DL, VT, Rs1, Rs2);
13154 }
13155
13156 MVT XLenVT = Subtarget.getXLenVT();
13157 SDValue Shift = DAG.getTargetConstant(0, DL, XLenVT);
13158 if (VT == MVT::v4i8) {
13159 unsigned ClipOpc = IsSigned ? RISCVISD::PNCLIP : RISCVISD::PNCLIPU;
13160 SDValue Pair = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16, Rs1, Rs2);
13161 return DAG.getNode(ClipOpc, DL, VT, Pair, Shift);
13162 }
13163 if (VT == MVT::v2i16) {
13164 unsigned ClipOpc = IsSigned ? RISCVISD::PNCLIP : RISCVISD::PNCLIPU;
13165 SDValue Pair = DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v2i32, Rs1, Rs2);
13166 return DAG.getNode(ClipOpc, DL, VT, Pair, Shift);
13167 }
13168 if (VT == MVT::v2i32) {
13169 unsigned ClipOpc = IsSigned ? RISCVISD::NCLIP : RISCVISD::NCLIPU;
13170 auto [Rs1Lo, Rs1Hi] = DAG.SplitScalar(Rs1, DL, XLenVT, XLenVT);
13171 auto [Rs2Lo, Rs2Hi] = DAG.SplitScalar(Rs2, DL, XLenVT, XLenVT);
13172 SDValue Lo = DAG.getNode(ClipOpc, DL, XLenVT, Rs1Lo, Rs1Hi, Shift);
13173 SDValue Hi = DAG.getNode(ClipOpc, DL, XLenVT, Rs2Lo, Rs2Hi, Shift);
13174 return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
13175 }
13176 if (VT == MVT::v8i8 || VT == MVT::v4i16) {
13177 unsigned ClipOpc = IsSigned ? RISCVISD::PNCLIP : RISCVISD::PNCLIPU;
13178 MVT HalfVT = VT == MVT::v8i8 ? MVT::v4i8 : MVT::v2i16;
13179 SDValue Lo = DAG.getNode(ClipOpc, DL, HalfVT, Rs1, Shift);
13180 SDValue Hi = DAG.getNode(ClipOpc, DL, HalfVT, Rs2, Shift);
13181 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi);
13182 }
13183
13184 llvm_unreachable("unexpected VT for pnclipp/pnclipup on RV32");
13185 }
13186 case Intrinsic::riscv_mqacc_00:
13187 case Intrinsic::riscv_mqacc_01:
13188 case Intrinsic::riscv_mqacc_11:
13189 case Intrinsic::riscv_mqracc_00:
13190 case Intrinsic::riscv_mqracc_01:
13191 case Intrinsic::riscv_mqracc_11:
13192 case Intrinsic::riscv_pmqacc_h00:
13193 case Intrinsic::riscv_pmqacc_h01:
13194 case Intrinsic::riscv_pmqacc_h11:
13195 case Intrinsic::riscv_pmqracc_h00:
13196 case Intrinsic::riscv_pmqracc_h01:
13197 case Intrinsic::riscv_pmqracc_h11: {
13198 EVT VT = Op.getValueType();
13199 SDValue Rd = Op.getOperand(1);
13200 SDValue Rs1 = Op.getOperand(2);
13201 SDValue Rs2 = Op.getOperand(3);
13202 MVT XLenVT = Subtarget.getXLenVT();
13203
13204 if (VT == MVT::v2i32 && Rs1.getSimpleValueType() == MVT::v4i16) {
13205 if (Subtarget.is64Bit()) {
13206 unsigned Opc = getRVPQFormatAccOpcode(IntNo);
13207 return DAG.getNode(Opc, DL, VT, Rd, Rs1, Rs2);
13208 }
13209
13210 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL);
13211 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
13212 SDValue RdLo = DAG.getExtractVectorElt(DL, XLenVT, Rd, 0);
13213 SDValue RdHi = DAG.getExtractVectorElt(DL, XLenVT, Rd, 1);
13214 unsigned ScalarOpc = getRVPQFormatAccScalarOpcode(IntNo);
13215 SDValue Lo = DAG.getNode(ScalarOpc, DL, XLenVT, RdLo, Rs1Lo, Rs2Lo);
13216 SDValue Hi = DAG.getNode(ScalarOpc, DL, XLenVT, RdHi, Rs1Hi, Rs2Hi);
13217 return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
13218 }
13219
13220 if (VT == XLenVT) {
13221 unsigned Opc = getRVPQFormatAccScalarOpcode(IntNo);
13222 return DAG.getNode(Opc, DL, XLenVT, Rd, Rs1, Rs2);
13223 }
13224
13225 return SDValue();
13226 }
13227 case Intrinsic::riscv_pmulq:
13228 case Intrinsic::riscv_pmulqr: {
13229 unsigned Opc;
13230 switch (IntNo) {
13231 case Intrinsic::riscv_pmulq:
13232 Opc = RISCVISD::MULQ;
13233 break;
13234 case Intrinsic::riscv_pmulqr:
13235 Opc = RISCVISD::MULQR;
13236 break;
13237 }
13238
13239 EVT VT = Op.getValueType();
13240 SDValue Rs1 = Op.getOperand(1);
13241 SDValue Rs2 = Op.getOperand(2);
13242
13243 // On RV32 the 64-bit packed vectors (v2i32, v4i16) have no single Q-format
13244 // multiply instruction. Split v4i16 into two v2i16 halves (each lowered to
13245 // a single pmulq.h/pmulqr.h via the existing patterns), and v2i32 into two
13246 // scalar mulq/mulqr (matched by the RV32 PatGprGpr patterns).
13247 if (!Subtarget.is64Bit()) {
13248 if (VT == MVT::v2i32) {
13249 MVT XLenVT = Subtarget.getXLenVT();
13250 SDValue Lo1 = DAG.getExtractVectorElt(DL, XLenVT, Rs1, 0);
13251 SDValue Lo2 = DAG.getExtractVectorElt(DL, XLenVT, Rs2, 0);
13252 SDValue Hi1 = DAG.getExtractVectorElt(DL, XLenVT, Rs1, 1);
13253 SDValue Hi2 = DAG.getExtractVectorElt(DL, XLenVT, Rs2, 1);
13254 SDValue LoRes = DAG.getNode(Opc, DL, XLenVT, Lo1, Lo2);
13255 SDValue HiRes = DAG.getNode(Opc, DL, XLenVT, Hi1, Hi2);
13256 return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, LoRes, HiRes);
13257 }
13258 if (VT == MVT::v4i16) {
13259 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL);
13260 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
13261 SDValue LoRes = DAG.getNode(Opc, DL, MVT::v2i16, Rs1Lo, Rs2Lo);
13262 SDValue HiRes = DAG.getNode(Opc, DL, MVT::v2i16, Rs1Hi, Rs2Hi);
13263 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, LoRes, HiRes);
13264 }
13265 }
13266
13267 return DAG.getNode(Opc, DL, VT, Rs1, Rs2);
13268 }
13269 case Intrinsic::riscv_psll:
13270 case Intrinsic::riscv_psrl:
13271 case Intrinsic::riscv_psra:
13272 case Intrinsic::riscv_pssha:
13273 case Intrinsic::riscv_psshar:
13274 case Intrinsic::riscv_psshl:
13275 case Intrinsic::riscv_psshlr: {
13276 SDValue ShAmt = Op.getOperand(2);
13277 ShAmt = DAG.getAnyExtOrTrunc(ShAmt, DL, XLenVT);
13278 return DAG.getNode(getRVPShiftOpcode(IntNo), DL, Op.getValueType(),
13279 Op.getOperand(1), ShAmt);
13280 }
13281 case Intrinsic::riscv_pwsll:
13282 case Intrinsic::riscv_pwsla: {
13283 MVT VT = Op.getSimpleValueType();
13284 SDValue Src = Op.getOperand(1);
13285 MVT SrcVT = Src.getSimpleValueType();
13286 if (!((VT == MVT::v4i16 && SrcVT == MVT::v4i8) ||
13287 (VT == MVT::v2i32 && SrcVT == MVT::v2i16)))
13288 reportFatalUsageError("unsupported packed widening shift intrinsic");
13289
13290 SDValue ShAmt = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, Op.getOperand(2));
13291 bool IsSigned = IntNo == Intrinsic::riscv_pwsla;
13292 if (!Subtarget.is64Bit()) {
13293 unsigned Opc = IsSigned ? RISCVISD::PWSLA : RISCVISD::PWSLL;
13294 return DAG.getNode(Opc, DL, VT, Src, ShAmt);
13295 }
13296
13297 unsigned ExtOpc = IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
13298 SDValue Wide = DAG.getNode(ExtOpc, DL, VT, Src);
13299 return DAG.getNode(RISCVISD::PSLL, DL, VT, Wide, ShAmt);
13300 }
13301 case Intrinsic::riscv_pnsrl:
13302 case Intrinsic::riscv_pnsra:
13303 case Intrinsic::riscv_pnsrar: {
13304 MVT VT = Op.getSimpleValueType();
13305 MVT SrcVT = Op.getOperand(1).getSimpleValueType();
13306 if (!((VT == MVT::v4i8 && SrcVT == MVT::v4i16) ||
13307 (VT == MVT::v2i16 && SrcVT == MVT::v2i32)))
13308 reportFatalUsageError("unsupported packed narrowing shift intrinsic");
13309
13310 SDValue ShAmt = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, Op.getOperand(2));
13311 return DAG.getNode(getRVPNarrowingShiftOpcode(IntNo), DL, VT,
13312 Op.getOperand(1), ShAmt);
13313 }
13314 case Intrinsic::riscv_psati:
13315 case Intrinsic::riscv_pusati: {
13316 bool IsSigned = IntNo == Intrinsic::riscv_psati;
13317 unsigned Opc = IsSigned ? RISCVISD::SATI : RISCVISD::USATI;
13318 // psati's width counts the sign bit, RISCVISD::SATI's immediate does not.
13319 unsigned Width = Op.getConstantOperandVal(2) - (IsSigned ? 1 : 0);
13320 return DAG.getNode(Opc, DL, Op.getValueType(), Op.getOperand(1),
13321 DAG.getTargetConstant(Width, DL, XLenVT));
13322 }
13323 case Intrinsic::riscv_psext_b:
13324 case Intrinsic::riscv_psext_h: {
13325 EVT VT = Op.getValueType();
13326 if (!VT.isSimple() || !Subtarget.isPExtPackedType(VT.getSimpleVT()))
13327 reportFatalUsageError("unsupported llvm.riscv.psext intrinsic");
13328
13329 MVT SimpleVT = VT.getSimpleVT();
13330 unsigned SrcEltBits = IntNo == Intrinsic::riscv_psext_b ? 8 : 16;
13331 if (SrcEltBits >= SimpleVT.getScalarSizeInBits())
13332 reportFatalUsageError("unsupported llvm.riscv.psext intrinsic");
13333
13334 MVT ExtVT = MVT::getVectorVT(MVT::getIntegerVT(SrcEltBits),
13335 SimpleVT.getVectorElementCount());
13336 return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, SimpleVT, Op.getOperand(1),
13337 DAG.getValueType(ExtVT));
13338 }
13339 case Intrinsic::riscv_pzext_b:
13340 case Intrinsic::riscv_pzext_h: {
13341 EVT VT = Op.getValueType();
13342 if (!VT.isSimple() || !Subtarget.isPExtPackedType(VT.getSimpleVT()))
13343 reportFatalUsageError("unsupported llvm.riscv.pzext intrinsic");
13344
13345 MVT SimpleVT = VT.getSimpleVT();
13346 unsigned SrcEltBits = IntNo == Intrinsic::riscv_pzext_b ? 8 : 16;
13347 if (SimpleVT.getScalarSizeInBits() != SrcEltBits * 2)
13348 reportFatalUsageError("unsupported llvm.riscv.pzext intrinsic");
13349
13350 return lowerPZExt(Op.getOperand(1), DL, DAG, Subtarget);
13351 }
13352 case Intrinsic::riscv_pabdsumu:
13353 case Intrinsic::riscv_pabdsumau: {
13354 // On RV32 an i32-result absolute difference sum over a 64-bit (GPRPair)
13355 // source has no paired instruction. Split into two v4i8 halves: reduce the
13356 // low half (folding in rd when accumulating), then accumulate the high half
13357 // into that partial sum.
13358 SDValue Rs1 = Op.getOperand(Op.getNumOperands() - 2);
13359 SDValue Rs2 = Op.getOperand(Op.getNumOperands() - 1);
13360 if (Subtarget.is64Bit() || Rs1.getSimpleValueType() != MVT::v8i8)
13361 return SDValue();
13362 bool IsAcc = IntNo == Intrinsic::riscv_pabdsumau;
13363 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL);
13364 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
13365 SDValue AbdsumuId =
13366 DAG.getTargetConstant(Intrinsic::riscv_pabdsumu, DL, MVT::i32);
13367 SDValue AbdsumauId =
13368 DAG.getTargetConstant(Intrinsic::riscv_pabdsumau, DL, MVT::i32);
13369 SDValue Lo = IsAcc ? DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
13370 AbdsumauId, Op.getOperand(1), Rs1Lo, Rs2Lo)
13371 : DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
13372 AbdsumuId, Rs1Lo, Rs2Lo);
13373 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32, AbdsumauId, Lo,
13374 Rs1Hi, Rs2Hi);
13375 }
13376 case Intrinsic::riscv_pmulhr:
13377 case Intrinsic::riscv_pmulhru:
13378 case Intrinsic::riscv_pmulhsu:
13379 case Intrinsic::riscv_pmulhrsu: {
13380 EVT VT = Op.getValueType();
13381 unsigned Opc = getRVPMulHighOpcode(IntNo);
13382
13383 // RV32 has no single instruction for 64-bit packed multiply high. Split
13384 // v4i16 into two v2i16 packed operations, and split v2i32 into scalar i32
13385 // operations so isel can use MULH*.
13386 if (!Subtarget.is64Bit() && VT == MVT::v4i16) {
13387 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Op.getOperand(1), DL);
13388 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Op.getOperand(2), DL);
13389 SDValue Lo = DAG.getNode(Opc, DL, MVT::v2i16, Rs1Lo, Rs2Lo);
13390 SDValue Hi = DAG.getNode(Opc, DL, MVT::v2i16, Rs1Hi, Rs2Hi);
13391 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi);
13392 }
13393
13394 if (!Subtarget.is64Bit() && VT == MVT::v2i32) {
13395 auto Extract = [&](SDValue V, unsigned Idx) {
13396 return DAG.getExtractVectorElt(DL, MVT::i32, V, Idx);
13397 };
13398 SDValue Rs1 = Op.getOperand(1);
13399 SDValue Rs2 = Op.getOperand(2);
13400 SDValue Lo =
13401 DAG.getNode(Opc, DL, MVT::i32, Extract(Rs1, 0), Extract(Rs2, 0));
13402 SDValue Hi =
13403 DAG.getNode(Opc, DL, MVT::i32, Extract(Rs1, 1), Extract(Rs2, 1));
13404 return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
13405 }
13406
13407 return DAG.getNode(Opc, DL, VT, Op.getOperand(1), Op.getOperand(2));
13408 }
13409 case Intrinsic::riscv_mulhr_i32:
13410 case Intrinsic::riscv_mulhru_u32:
13411 case Intrinsic::riscv_mulhsu_i32:
13412 case Intrinsic::riscv_mulhrsu_i32: {
13413 // RV32 maps the non-rounding forms onto the M extension and the rounding
13414 // forms onto the scalar P instructions. RV64 goes via ReplaceNodeResults.
13415 unsigned Opc = getRVScalarMulHighOpcode(IntNo);
13416 return DAG.getNode(Opc, DL, MVT::i32, Op.getOperand(1), Op.getOperand(2));
13417 }
13418 case Intrinsic::riscv_pmhacc:
13419 case Intrinsic::riscv_pmhracc:
13420 case Intrinsic::riscv_pmhaccu:
13421 case Intrinsic::riscv_pmhraccu:
13422 case Intrinsic::riscv_pmhaccsu:
13423 case Intrinsic::riscv_pmhraccsu: {
13424 EVT VT = Op.getValueType();
13425 unsigned MulOpc = getRVPMulHighAccumulateOpcode(IntNo);
13426 SDValue Rd = Op.getOperand(1);
13427 SDValue Rs1 = Op.getOperand(2);
13428 SDValue Rs2 = Op.getOperand(3);
13429
13430 // RV32 has no single instruction for 64-bit packed multiply high
13431 // accumulate. Split v4i16 into two v2i16 packed operations, and split
13432 // v2i32 into scalar i32 operations.
13433 if (!Subtarget.is64Bit() && VT == MVT::v4i16) {
13434 auto [RdLo, RdHi] = DAG.SplitVector(Rd, DL);
13435 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL);
13436 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
13437 SDValue Lo = DAG.getNode(MulOpc, DL, MVT::v2i16, RdLo, Rs1Lo, Rs2Lo);
13438 SDValue Hi = DAG.getNode(MulOpc, DL, MVT::v2i16, RdHi, Rs1Hi, Rs2Hi);
13439 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi);
13440 }
13441
13442 if (!Subtarget.is64Bit() && VT == MVT::v2i32) {
13443 auto Extract = [&](SDValue V, unsigned Idx) {
13444 return DAG.getExtractVectorElt(DL, MVT::i32, V, Idx);
13445 };
13446 SDValue Lo = DAG.getNode(MulOpc, DL, MVT::i32, Extract(Rd, 0),
13447 Extract(Rs1, 0), Extract(Rs2, 0));
13448 SDValue Hi = DAG.getNode(MulOpc, DL, MVT::i32, Extract(Rd, 1),
13449 Extract(Rs1, 1), Extract(Rs2, 1));
13450 return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
13451 }
13452
13453 return DAG.getNode(MulOpc, DL, VT, Rd, Rs1, Rs2);
13454 }
13455 case Intrinsic::riscv_pmhacc_b0:
13456 case Intrinsic::riscv_pmhacc_b1:
13457 case Intrinsic::riscv_pmhaccsu_b0:
13458 case Intrinsic::riscv_pmhaccsu_b1: {
13459 EVT VT = Op.getValueType();
13461 SDValue Rd = Op.getOperand(1);
13462 SDValue Rs1 = Op.getOperand(2);
13463 SDValue Rs2 = Op.getOperand(3);
13464
13465 // RV32: split v4i16 into two v2i16 operations
13466 if (!Subtarget.is64Bit() && VT == MVT::v4i16) {
13467 auto [RdLo, RdHi] = DAG.SplitVector(Rd, DL);
13468 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL);
13469 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
13470 SDValue Lo = DAG.getNode(Opc, DL, MVT::v2i16, RdLo, Rs1Lo, Rs2Lo);
13471 SDValue Hi = DAG.getNode(Opc, DL, MVT::v2i16, RdHi, Rs1Hi, Rs2Hi);
13472 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi);
13473 }
13474
13475 return DAG.getNode(Opc, DL, VT, Rd, Rs1, Rs2);
13476 }
13477 case Intrinsic::riscv_pmhacc_h0:
13478 case Intrinsic::riscv_pmhacc_h1:
13479 case Intrinsic::riscv_pmhaccsu_h0:
13480 case Intrinsic::riscv_pmhaccsu_h1: {
13481 EVT VT = Op.getValueType();
13483 SDValue Rd = Op.getOperand(1);
13484 SDValue Rs1 = Op.getOperand(2);
13485 SDValue Rs2 = Op.getOperand(3);
13486
13487 // RV32 has no 64-bit packed form: split into two scalar operations, each
13488 // accumulating one word of the result.
13489 if (!Subtarget.is64Bit() && VT == MVT::v2i32) {
13490 auto Extract = [&](SDValue V, unsigned Idx) {
13491 return DAG.getExtractVectorElt(DL, MVT::i32, V, Idx);
13492 };
13493 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
13494 SDValue Lo = DAG.getNode(Opc, DL, MVT::i32, Extract(Rd, 0),
13495 Extract(Rs1, 0), Rs2Lo);
13496 SDValue Hi = DAG.getNode(Opc, DL, MVT::i32, Extract(Rd, 1),
13497 Extract(Rs1, 1), Rs2Hi);
13498 return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
13499 }
13500
13501 return DAG.getNode(Opc, DL, VT, Rd, Rs1, Rs2);
13502 }
13503 case Intrinsic::riscv_pmulh_b0:
13504 case Intrinsic::riscv_pmulh_b1:
13505 case Intrinsic::riscv_pmulhsu_b0:
13506 case Intrinsic::riscv_pmulhsu_b1: {
13507 EVT VT = Op.getValueType();
13508 SDValue Rs1 = Op.getOperand(1);
13509 SDValue Rs2 = Op.getOperand(2);
13510 unsigned Opc = getRVPMulHighPartsOpcode(IntNo);
13511
13512 // RV32 has no single instruction for a 64-bit packed multiply-high parts.
13513 // Split v4i16 into two v2i16 packed operations.
13514 if (!Subtarget.is64Bit() && VT == MVT::v4i16) {
13515 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL);
13516 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
13517 SDValue Lo = DAG.getNode(Opc, DL, MVT::v2i16, Rs1Lo, Rs2Lo);
13518 SDValue Hi = DAG.getNode(Opc, DL, MVT::v2i16, Rs1Hi, Rs2Hi);
13519 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi);
13520 }
13521
13522 return DAG.getNode(Opc, DL, VT, Rs1, Rs2);
13523 }
13524 case Intrinsic::riscv_pmulh_h0:
13525 case Intrinsic::riscv_pmulh_h1:
13526 case Intrinsic::riscv_pmulhsu_h0:
13527 case Intrinsic::riscv_pmulhsu_h1: {
13528 EVT VT = Op.getValueType();
13529 SDValue Rs1 = Op.getOperand(1);
13530 SDValue Rs2 = Op.getOperand(2);
13531 unsigned Opc = getRVPMulHighPartsWOpcode(IntNo);
13532
13533 // RV32 has no single instruction for a 64-bit packed word multiply-high
13534 // parts. Split v2i32 into two scalar operations, one per result word.
13535 if (!Subtarget.is64Bit() && VT == MVT::v2i32) {
13536 auto Extract = [&](SDValue V, unsigned Idx) {
13537 return DAG.getExtractVectorElt(DL, MVT::i32, V, Idx);
13538 };
13539 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
13540 unsigned SOpc = getRVPScalarMulHighPartsOpcode(IntNo);
13541 SDValue Lo = DAG.getNode(SOpc, DL, MVT::i32, Extract(Rs1, 0), Rs2Lo);
13542 SDValue Hi = DAG.getNode(SOpc, DL, MVT::i32, Extract(Rs1, 1), Rs2Hi);
13543 return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
13544 }
13545
13546 if (Subtarget.is64Bit())
13547 return DAG.getNode(Opc, DL, VT, Rs1, Rs2);
13548
13549 return SDValue();
13550 }
13551 case Intrinsic::riscv_pmqwacc_i32x2:
13552 case Intrinsic::riscv_pmqrwacc_i32x2: {
13553 EVT VT = Op.getValueType();
13554 SDValue Acc = Op.getOperand(1);
13555 SDValue Rs1 = Op.getOperand(2);
13556 SDValue Rs2 = Op.getOperand(3);
13557
13558 if (!Subtarget.is64Bit()) {
13559 unsigned Opc = IntNo == Intrinsic::riscv_pmqwacc_i32x2
13560 ? RISCVISD::PMQWACC_H
13561 : RISCVISD::PMQRWACC_H;
13562 return DAG.getNode(Opc, DL, VT, Acc, Rs1, Rs2);
13563 }
13564
13565 Rs1 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16, Rs1,
13566 DAG.getUNDEF(MVT::v2i16));
13567 Rs2 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16, Rs2,
13568 DAG.getUNDEF(MVT::v2i16));
13569 SDValue Zip = DAG.getNode(RISCVISD::PZIP, DL, MVT::v4i16, Rs1, Rs2);
13570 unsigned Opc = IntNo == Intrinsic::riscv_pmqwacc_i32x2
13571 ? RISCVISD::PMQACC_W_H01
13572 : RISCVISD::PMQRACC_W_H01;
13573 return DAG.getNode(Opc, DL, VT, Acc, Zip, Zip);
13574 }
13575 case Intrinsic::riscv_mulh_h0:
13576 case Intrinsic::riscv_mulh_h1:
13577 case Intrinsic::riscv_mulhsu_h0:
13578 case Intrinsic::riscv_mulhsu_h1: {
13579 // mulh.h0/h1 exist only on RV32 and pmulh.w.h0/h1 only on RV64; the
13580 // other XLEN lowers the scalar intrinsic via the packed form in
13581 // ReplaceNodeResults.
13582 EVT VT = Op.getValueType();
13583 if (VT != MVT::i32 || Subtarget.is64Bit())
13584 return SDValue();
13585
13586 SDValue Rs1 = Op.getOperand(1);
13587 SDValue Rs2 = Op.getOperand(2);
13588 unsigned Opc = getRVPScalarMulHighPartsOpcode(IntNo);
13589 return DAG.getNode(Opc, DL, VT, Rs1, Rs2);
13590 }
13591 case Intrinsic::riscv_pm4add:
13592 case Intrinsic::riscv_pm2add:
13593 case Intrinsic::riscv_pm2add_x:
13594 case Intrinsic::riscv_pm4addu:
13595 case Intrinsic::riscv_pm2addu:
13596 case Intrinsic::riscv_pmq2add:
13597 case Intrinsic::riscv_pmqr2add:
13598 case Intrinsic::riscv_pm2sadd:
13599 case Intrinsic::riscv_pm2sadd_x:
13600 case Intrinsic::riscv_pm2sub:
13601 case Intrinsic::riscv_pm2sub_x:
13602 case Intrinsic::riscv_pm4addsu:
13603 case Intrinsic::riscv_pm2addsu: {
13604 EVT VT = Op.getValueType();
13605 unsigned Opc = getRVPHorizontalMulOpcode(IntNo);
13606 SDValue Rs1 = Op.getOperand(1);
13607 SDValue Rs2 = Op.getOperand(2);
13608
13609 // RV32 applies the 32-bit instruction independently to both halves of a
13610 // 64-bit packed input.
13611 if (!Subtarget.is64Bit() && VT == MVT::v2i32) {
13612 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL);
13613 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
13614 SDValue Lo = DAG.getNode(Opc, DL, MVT::i32, Rs1Lo, Rs2Lo);
13615 SDValue Hi = DAG.getNode(Opc, DL, MVT::i32, Rs1Hi, Rs2Hi);
13616 return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
13617 }
13618
13619 return DAG.getNode(Opc, DL, VT, Rs1, Rs2);
13620 }
13621 case Intrinsic::riscv_pmerge: {
13622 EVT VT = Op.getValueType();
13623 auto buildMerge = [&](SDValue Rs1, SDValue Rs2, SDValue Mask,
13624 EVT ResultVT) {
13625 MVT IntVT = MVT::getIntegerVT(ResultVT.getSizeInBits());
13626 SDValue Res =
13627 DAG.getNode(RISCVISD::MERGE, DL, IntVT, DAG.getBitcast(IntVT, Mask),
13628 DAG.getBitcast(IntVT, Rs1), DAG.getBitcast(IntVT, Rs2));
13629 return DAG.getBitcast(ResultVT, Res);
13630 };
13631
13632 // 64-bit packed types on RV32: split into two 32-bit halves. v2i32 has no
13633 // legal 32-bit vector half, so bitcast it to v4i16 (same 64 bits) first;
13634 // the merge result is identical.
13635 if (!Subtarget.is64Bit() &&
13636 (VT == MVT::v8i8 || VT == MVT::v4i16 || VT == MVT::v2i32)) {
13637 EVT WorkVT = VT == MVT::v2i32 ? EVT(MVT::v4i16) : VT;
13638 SDValue Rs1 = DAG.getBitcast(WorkVT, Op.getOperand(1));
13639 SDValue Rs2 = DAG.getBitcast(WorkVT, Op.getOperand(2));
13640 SDValue Mask = DAG.getBitcast(WorkVT, Op.getOperand(3));
13641 MVT HalfVT = WorkVT == MVT::v8i8 ? MVT::v4i8 : MVT::v2i16;
13642 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL, HalfVT, HalfVT);
13643 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL, HalfVT, HalfVT);
13644 auto [MaskLo, MaskHi] = DAG.SplitVector(Mask, DL, HalfVT, HalfVT);
13645 SDValue ResLo = buildMerge(Rs1Lo, Rs2Lo, MaskLo, HalfVT);
13646 SDValue ResHi = buildMerge(Rs1Hi, Rs2Hi, MaskHi, HalfVT);
13647 SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, DL, WorkVT, ResLo, ResHi);
13648 return DAG.getBitcast(VT, Res);
13649 }
13650
13651 return buildMerge(Op.getOperand(1), Op.getOperand(2), Op.getOperand(3), VT);
13652 }
13653 case Intrinsic::experimental_get_vector_length:
13654 return lowerGetVectorLength(Op.getNode(), DAG, Subtarget);
13655 case Intrinsic::riscv_vmv_x_s: {
13656 SDValue Res = DAG.getNode(RISCVISD::VMV_X_S, DL, XLenVT, Op.getOperand(1));
13657 return DAG.getNode(ISD::TRUNCATE, DL, Op.getValueType(), Res);
13658 }
13659 case Intrinsic::riscv_vfmv_f_s:
13660 return DAG.getExtractVectorElt(DL, Op.getValueType(), Op.getOperand(1), 0);
13661 case Intrinsic::riscv_vmv_v_x:
13662 return lowerScalarSplat(Op.getOperand(1), Op.getOperand(2),
13663 Op.getOperand(3), Op.getSimpleValueType(), DL, DAG,
13664 Subtarget);
13665 case Intrinsic::riscv_vfmv_v_f:
13666 return DAG.getNode(RISCVISD::VFMV_V_F_VL, DL, Op.getValueType(),
13667 Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
13668 case Intrinsic::riscv_vmv_s_x: {
13669 SDValue Scalar = Op.getOperand(2);
13670
13671 if (Scalar.getValueType().bitsLE(XLenVT)) {
13672 Scalar = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, Scalar);
13673 return DAG.getNode(RISCVISD::VMV_S_X_VL, DL, Op.getValueType(),
13674 Op.getOperand(1), Scalar, Op.getOperand(3));
13675 }
13676
13677 assert(Scalar.getValueType() == MVT::i64 && "Unexpected scalar VT!");
13678
13679 // This is an i64 value that lives in two scalar registers. We have to
13680 // insert this in a convoluted way. First we build vXi64 splat containing
13681 // the two values that we assemble using some bit math. Next we'll use
13682 // vid.v and vmseq to build a mask with bit 0 set. Then we'll use that mask
13683 // to merge element 0 from our splat into the source vector.
13684 // FIXME: This is probably not the best way to do this, but it is
13685 // consistent with INSERT_VECTOR_ELT lowering so it is a good starting
13686 // point.
13687 // sw lo, (a0)
13688 // sw hi, 4(a0)
13689 // vlse vX, (a0)
13690 //
13691 // vid.v vVid
13692 // vmseq.vx mMask, vVid, 0
13693 // vmerge.vvm vDest, vSrc, vVal, mMask
13694 MVT VT = Op.getSimpleValueType();
13695 SDValue Vec = Op.getOperand(1);
13696 SDValue VL = getVLOperand(Op);
13697
13698 SDValue SplattedVal = splatSplitI64WithVL(DL, VT, SDValue(), Scalar, VL, DAG);
13699 if (Op.getOperand(1).isUndef())
13700 return SplattedVal;
13701 SDValue SplattedIdx =
13702 DAG.getNode(RISCVISD::VMV_V_X_VL, DL, VT, DAG.getUNDEF(VT),
13703 DAG.getConstant(0, DL, MVT::i32), VL);
13704
13705 MVT MaskVT = getMaskTypeFor(VT);
13706 SDValue Mask = getAllOnesMask(VT, VL, DL, DAG);
13707 SDValue VID = DAG.getNode(RISCVISD::VID_VL, DL, VT, Mask, VL);
13708 SDValue SelectCond =
13709 DAG.getNode(RISCVISD::SETCC_VL, DL, MaskVT,
13710 {VID, SplattedIdx, DAG.getCondCode(ISD::SETEQ),
13711 DAG.getUNDEF(MaskVT), Mask, VL});
13712 return DAG.getNode(RISCVISD::VMERGE_VL, DL, VT, SelectCond, SplattedVal,
13713 Vec, DAG.getUNDEF(VT), VL);
13714 }
13715 case Intrinsic::riscv_vfmv_s_f:
13716 return DAG.getNode(RISCVISD::VFMV_S_F_VL, DL, Op.getValueType(),
13717 Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
13718 // EGS * EEW >= 128 bits
13719 case Intrinsic::riscv_vaesdf_vv:
13720 case Intrinsic::riscv_vaesdf_vs:
13721 case Intrinsic::riscv_vaesdm_vv:
13722 case Intrinsic::riscv_vaesdm_vs:
13723 case Intrinsic::riscv_vaesef_vv:
13724 case Intrinsic::riscv_vaesef_vs:
13725 case Intrinsic::riscv_vaesem_vv:
13726 case Intrinsic::riscv_vaesem_vs:
13727 case Intrinsic::riscv_vaeskf1:
13728 case Intrinsic::riscv_vaeskf2:
13729 case Intrinsic::riscv_vaesz_vs:
13730 case Intrinsic::riscv_vsm4k:
13731 case Intrinsic::riscv_vsm4r_vv:
13732 case Intrinsic::riscv_vsm4r_vs: {
13733 if (!isValidEGW(4, Op.getSimpleValueType(), Subtarget) ||
13734 !isValidEGW(4, Op->getOperand(1).getSimpleValueType(), Subtarget) ||
13735 !isValidEGW(4, Op->getOperand(2).getSimpleValueType(), Subtarget))
13736 reportFatalUsageError("EGW should be greater than or equal to 4 * SEW.");
13737 return Op;
13738 }
13739 // EGS * EEW >= 256 bits
13740 case Intrinsic::riscv_vsm3c:
13741 case Intrinsic::riscv_vsm3me: {
13742 if (!isValidEGW(8, Op.getSimpleValueType(), Subtarget) ||
13743 !isValidEGW(8, Op->getOperand(1).getSimpleValueType(), Subtarget))
13744 reportFatalUsageError("EGW should be greater than or equal to 8 * SEW.");
13745 return Op;
13746 }
13747 // zvknha(SEW=32)/zvknhb(SEW=[32|64])
13748 case Intrinsic::riscv_vsha2ch:
13749 case Intrinsic::riscv_vsha2cl:
13750 case Intrinsic::riscv_vsha2ms: {
13751 if (Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
13752 !Subtarget.hasStdExtZvknhb())
13753 reportFatalUsageError("SEW=64 needs Zvknhb to be enabled.");
13754 if (!isValidEGW(4, Op.getSimpleValueType(), Subtarget) ||
13755 !isValidEGW(4, Op->getOperand(1).getSimpleValueType(), Subtarget) ||
13756 !isValidEGW(4, Op->getOperand(2).getSimpleValueType(), Subtarget))
13757 reportFatalUsageError("EGW should be greater than or equal to 4 * SEW.");
13758 return Op;
13759 }
13760 case Intrinsic::riscv_sf_vc_v_x:
13761 case Intrinsic::riscv_sf_vc_v_i:
13762 case Intrinsic::riscv_sf_vc_v_xv:
13763 case Intrinsic::riscv_sf_vc_v_iv:
13764 case Intrinsic::riscv_sf_vc_v_vv:
13765 case Intrinsic::riscv_sf_vc_v_fv:
13766 case Intrinsic::riscv_sf_vc_v_xvv:
13767 case Intrinsic::riscv_sf_vc_v_ivv:
13768 case Intrinsic::riscv_sf_vc_v_vvv:
13769 case Intrinsic::riscv_sf_vc_v_fvv:
13770 case Intrinsic::riscv_sf_vc_v_xvw:
13771 case Intrinsic::riscv_sf_vc_v_ivw:
13772 case Intrinsic::riscv_sf_vc_v_vvw:
13773 case Intrinsic::riscv_sf_vc_v_fvw: {
13774 MVT VT = Op.getSimpleValueType();
13775
13776 SmallVector<SDValue> Operands{Op->op_values()};
13778
13779 MVT RetVT = VT;
13780 if (VT.isFixedLengthVector())
13782 else if (VT.isFloatingPoint())
13785
13786 SDValue NewNode = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, RetVT, Operands);
13787
13788 if (VT.isFixedLengthVector())
13789 NewNode = convertFromScalableVector(VT, NewNode, DAG, Subtarget);
13790 else if (VT.isFloatingPoint())
13791 NewNode = DAG.getBitcast(VT, NewNode);
13792
13793 if (Op == NewNode)
13794 break;
13795
13796 return NewNode;
13797 }
13798 }
13799
13800 return lowerVectorIntrinsicScalars(Op, DAG, Subtarget);
13801}
13802
13804 unsigned Type) {
13805 SDLoc DL(Op);
13806 SmallVector<SDValue> Operands{Op->op_values()};
13807 Operands.erase(Operands.begin() + 1);
13808
13809 const RISCVSubtarget &Subtarget =
13811 MVT VT = Op.getSimpleValueType();
13812 MVT RetVT = VT;
13813 MVT FloatVT = VT;
13814
13815 if (VT.isFloatingPoint()) {
13816 RetVT = MVT::getVectorVT(MVT::getIntegerVT(VT.getScalarSizeInBits()),
13817 VT.getVectorElementCount());
13818 FloatVT = RetVT;
13819 }
13820 if (VT.isFixedLengthVector())
13821 RetVT = getContainerForFixedLengthVector(RetVT, Subtarget);
13822
13824
13825 SDVTList VTs = DAG.getVTList({RetVT, MVT::Other});
13826 SDValue NewNode = DAG.getNode(Type, DL, VTs, Operands);
13827 SDValue Chain = NewNode.getValue(1);
13828
13829 if (VT.isFixedLengthVector())
13830 NewNode = convertFromScalableVector(FloatVT, NewNode, DAG, Subtarget);
13831 if (VT.isFloatingPoint())
13832 NewNode = DAG.getBitcast(VT, NewNode);
13833
13834 NewNode = DAG.getMergeValues({NewNode, Chain}, DL);
13835
13836 return NewNode;
13837}
13838
13840 unsigned Type) {
13841 SmallVector<SDValue> Operands{Op->op_values()};
13842 Operands.erase(Operands.begin() + 1);
13844
13845 return DAG.getNode(Type, SDLoc(Op), Op.getValueType(), Operands);
13846}
13847
13848static SDValue
13850 const RISCVSubtarget &Subtarget,
13851 SelectionDAG &DAG) {
13852 bool IsStrided;
13853 switch (IntNo) {
13854 case Intrinsic::riscv_seg2_load_mask:
13855 case Intrinsic::riscv_seg3_load_mask:
13856 case Intrinsic::riscv_seg4_load_mask:
13857 case Intrinsic::riscv_seg5_load_mask:
13858 case Intrinsic::riscv_seg6_load_mask:
13859 case Intrinsic::riscv_seg7_load_mask:
13860 case Intrinsic::riscv_seg8_load_mask:
13861 IsStrided = false;
13862 break;
13863 case Intrinsic::riscv_sseg2_load_mask:
13864 case Intrinsic::riscv_sseg3_load_mask:
13865 case Intrinsic::riscv_sseg4_load_mask:
13866 case Intrinsic::riscv_sseg5_load_mask:
13867 case Intrinsic::riscv_sseg6_load_mask:
13868 case Intrinsic::riscv_sseg7_load_mask:
13869 case Intrinsic::riscv_sseg8_load_mask:
13870 IsStrided = true;
13871 break;
13872 default:
13873 llvm_unreachable("unexpected intrinsic ID");
13874 };
13875
13876 static const Intrinsic::ID VlsegInts[7] = {
13877 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
13878 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
13879 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
13880 Intrinsic::riscv_vlseg8_mask};
13881 static const Intrinsic::ID VlssegInts[7] = {
13882 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
13883 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
13884 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
13885 Intrinsic::riscv_vlsseg8_mask};
13886
13887 SDLoc DL(Op);
13888 unsigned NF = Op->getNumValues() - 1;
13889 assert(NF >= 2 && NF <= 8 && "Unexpected seg number");
13890 MVT XLenVT = Subtarget.getXLenVT();
13891 MVT VT = Op->getSimpleValueType(0);
13892 MVT ContainerVT = ::getContainerForFixedLengthVector(VT, Subtarget);
13893 unsigned Sz = NF * ContainerVT.getVectorMinNumElements() *
13894 ContainerVT.getScalarSizeInBits();
13895 EVT VecTupTy = MVT::getRISCVVectorTupleVT(Sz, NF);
13896
13897 // Operands: (chain, int_id, pointer, mask, vl) or
13898 // (chain, int_id, pointer, offset, mask, vl)
13899 SDValue VL = Op.getOperand(Op.getNumOperands() - 1);
13900 SDValue Mask = Op.getOperand(Op.getNumOperands() - 2);
13901 MVT MaskVT = Mask.getSimpleValueType();
13902 MVT MaskContainerVT = ::getContainerForFixedLengthVector(MaskVT, Subtarget);
13903 Mask = convertToScalableVector(MaskContainerVT, Mask, DAG, Subtarget);
13904
13905 SDValue IntID = DAG.getTargetConstant(
13906 IsStrided ? VlssegInts[NF - 2] : VlsegInts[NF - 2], DL, XLenVT);
13908
13909 SDVTList VTs = DAG.getVTList({VecTupTy, MVT::Other});
13911 Load->getChain(),
13912 IntID,
13913 DAG.getUNDEF(VecTupTy),
13914 Op.getOperand(2),
13915 Mask,
13916 VL,
13919 DAG.getTargetConstant(Log2_64(VT.getScalarSizeInBits()), DL, XLenVT)};
13920 // Insert the stride operand.
13921 if (IsStrided)
13922 Ops.insert(std::next(Ops.begin(), 4), Op.getOperand(3));
13923
13924 SDValue Result =
13926 Load->getMemoryVT(), Load->getMemOperand());
13928 for (unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
13929 SDValue SubVec = DAG.getNode(RISCVISD::TUPLE_EXTRACT, DL, ContainerVT,
13930 Result.getValue(0),
13931 DAG.getTargetConstant(RetIdx, DL, MVT::i32));
13932 Results.push_back(convertFromScalableVector(VT, SubVec, DAG, Subtarget));
13933 }
13934 Results.push_back(Result.getValue(1));
13935 return DAG.getMergeValues(Results, DL);
13936}
13937
13938SDValue RISCVTargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
13939 SelectionDAG &DAG) const {
13940 unsigned IntNo = Op.getConstantOperandVal(1);
13941 switch (IntNo) {
13942 default:
13943 break;
13944 case Intrinsic::riscv_seg2_load_mask:
13945 case Intrinsic::riscv_seg3_load_mask:
13946 case Intrinsic::riscv_seg4_load_mask:
13947 case Intrinsic::riscv_seg5_load_mask:
13948 case Intrinsic::riscv_seg6_load_mask:
13949 case Intrinsic::riscv_seg7_load_mask:
13950 case Intrinsic::riscv_seg8_load_mask:
13951 case Intrinsic::riscv_sseg2_load_mask:
13952 case Intrinsic::riscv_sseg3_load_mask:
13953 case Intrinsic::riscv_sseg4_load_mask:
13954 case Intrinsic::riscv_sseg5_load_mask:
13955 case Intrinsic::riscv_sseg6_load_mask:
13956 case Intrinsic::riscv_sseg7_load_mask:
13957 case Intrinsic::riscv_sseg8_load_mask:
13958 return lowerFixedVectorSegLoadIntrinsics(IntNo, Op, Subtarget, DAG);
13959
13960 case Intrinsic::riscv_sf_vc_v_x_se:
13961 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_X_SE);
13962 case Intrinsic::riscv_sf_vc_v_i_se:
13963 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_I_SE);
13964 case Intrinsic::riscv_sf_vc_v_xv_se:
13965 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_XV_SE);
13966 case Intrinsic::riscv_sf_vc_v_iv_se:
13967 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_IV_SE);
13968 case Intrinsic::riscv_sf_vc_v_vv_se:
13969 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_VV_SE);
13970 case Intrinsic::riscv_sf_vc_v_fv_se:
13971 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_FV_SE);
13972 case Intrinsic::riscv_sf_vc_v_xvv_se:
13973 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_XVV_SE);
13974 case Intrinsic::riscv_sf_vc_v_ivv_se:
13975 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_IVV_SE);
13976 case Intrinsic::riscv_sf_vc_v_vvv_se:
13977 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_VVV_SE);
13978 case Intrinsic::riscv_sf_vc_v_fvv_se:
13979 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_FVV_SE);
13980 case Intrinsic::riscv_sf_vc_v_xvw_se:
13981 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_XVW_SE);
13982 case Intrinsic::riscv_sf_vc_v_ivw_se:
13983 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_IVW_SE);
13984 case Intrinsic::riscv_sf_vc_v_vvw_se:
13985 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_VVW_SE);
13986 case Intrinsic::riscv_sf_vc_v_fvw_se:
13987 return getVCIXISDNodeWCHAIN(Op, DAG, RISCVISD::SF_VC_V_FVW_SE);
13988 }
13989
13990 return lowerVectorIntrinsicScalars(Op, DAG, Subtarget);
13991}
13992
13993static SDValue
13995 const RISCVSubtarget &Subtarget,
13996 SelectionDAG &DAG) {
13997 bool IsStrided;
13998 switch (IntNo) {
13999 case Intrinsic::riscv_seg2_store_mask:
14000 case Intrinsic::riscv_seg3_store_mask:
14001 case Intrinsic::riscv_seg4_store_mask:
14002 case Intrinsic::riscv_seg5_store_mask:
14003 case Intrinsic::riscv_seg6_store_mask:
14004 case Intrinsic::riscv_seg7_store_mask:
14005 case Intrinsic::riscv_seg8_store_mask:
14006 IsStrided = false;
14007 break;
14008 case Intrinsic::riscv_sseg2_store_mask:
14009 case Intrinsic::riscv_sseg3_store_mask:
14010 case Intrinsic::riscv_sseg4_store_mask:
14011 case Intrinsic::riscv_sseg5_store_mask:
14012 case Intrinsic::riscv_sseg6_store_mask:
14013 case Intrinsic::riscv_sseg7_store_mask:
14014 case Intrinsic::riscv_sseg8_store_mask:
14015 IsStrided = true;
14016 break;
14017 default:
14018 llvm_unreachable("unexpected intrinsic ID");
14019 }
14020
14021 SDLoc DL(Op);
14022 static const Intrinsic::ID VssegInts[] = {
14023 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
14024 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
14025 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
14026 Intrinsic::riscv_vsseg8_mask};
14027 static const Intrinsic::ID VsssegInts[] = {
14028 Intrinsic::riscv_vssseg2_mask, Intrinsic::riscv_vssseg3_mask,
14029 Intrinsic::riscv_vssseg4_mask, Intrinsic::riscv_vssseg5_mask,
14030 Intrinsic::riscv_vssseg6_mask, Intrinsic::riscv_vssseg7_mask,
14031 Intrinsic::riscv_vssseg8_mask};
14032
14033 // Operands: (chain, int_id, vec*, ptr, mask, vl) or
14034 // (chain, int_id, vec*, ptr, stride, mask, vl)
14035 unsigned NF = Op->getNumOperands() - (IsStrided ? 6 : 5);
14036 assert(NF >= 2 && NF <= 8 && "Unexpected seg number");
14037 MVT XLenVT = Subtarget.getXLenVT();
14038 MVT VT = Op->getOperand(2).getSimpleValueType();
14039 MVT ContainerVT = ::getContainerForFixedLengthVector(VT, Subtarget);
14040 unsigned Sz = NF * ContainerVT.getVectorMinNumElements() *
14041 ContainerVT.getScalarSizeInBits();
14042 EVT VecTupTy = MVT::getRISCVVectorTupleVT(Sz, NF);
14043
14044 SDValue VL = Op.getOperand(Op.getNumOperands() - 1);
14045 SDValue Mask = Op.getOperand(Op.getNumOperands() - 2);
14046 MVT MaskVT = Mask.getSimpleValueType();
14047 MVT MaskContainerVT = ::getContainerForFixedLengthVector(MaskVT, Subtarget);
14048 Mask = convertToScalableVector(MaskContainerVT, Mask, DAG, Subtarget);
14049
14050 SDValue IntID = DAG.getTargetConstant(
14051 IsStrided ? VsssegInts[NF - 2] : VssegInts[NF - 2], DL, XLenVT);
14052 SDValue Ptr = Op->getOperand(NF + 2);
14053
14054 auto *FixedIntrinsic = cast<MemIntrinsicSDNode>(Op);
14055
14056 SDValue StoredVal = DAG.getUNDEF(VecTupTy);
14057 for (unsigned i = 0; i < NF; i++)
14058 StoredVal = DAG.getNode(
14059 RISCVISD::TUPLE_INSERT, DL, VecTupTy, StoredVal,
14060 convertToScalableVector(ContainerVT, FixedIntrinsic->getOperand(2 + i),
14061 DAG, Subtarget),
14062 DAG.getTargetConstant(i, DL, MVT::i32));
14063
14065 FixedIntrinsic->getChain(),
14066 IntID,
14067 StoredVal,
14068 Ptr,
14069 Mask,
14070 VL,
14071 DAG.getTargetConstant(Log2_64(VT.getScalarSizeInBits()), DL, XLenVT)};
14072 // Insert the stride operand.
14073 if (IsStrided)
14074 Ops.insert(std::next(Ops.begin(), 4),
14075 Op.getOperand(Op.getNumOperands() - 3));
14076
14077 return DAG.getMemIntrinsicNode(
14078 ISD::INTRINSIC_VOID, DL, DAG.getVTList(MVT::Other), Ops,
14079 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
14080}
14081
14082SDValue RISCVTargetLowering::LowerINTRINSIC_VOID(SDValue Op,
14083 SelectionDAG &DAG) const {
14084 unsigned IntNo = Op.getConstantOperandVal(1);
14085 switch (IntNo) {
14086 default:
14087 break;
14088 case Intrinsic::riscv_seg2_store_mask:
14089 case Intrinsic::riscv_seg3_store_mask:
14090 case Intrinsic::riscv_seg4_store_mask:
14091 case Intrinsic::riscv_seg5_store_mask:
14092 case Intrinsic::riscv_seg6_store_mask:
14093 case Intrinsic::riscv_seg7_store_mask:
14094 case Intrinsic::riscv_seg8_store_mask:
14095 case Intrinsic::riscv_sseg2_store_mask:
14096 case Intrinsic::riscv_sseg3_store_mask:
14097 case Intrinsic::riscv_sseg4_store_mask:
14098 case Intrinsic::riscv_sseg5_store_mask:
14099 case Intrinsic::riscv_sseg6_store_mask:
14100 case Intrinsic::riscv_sseg7_store_mask:
14101 case Intrinsic::riscv_sseg8_store_mask:
14102 return lowerFixedVectorSegStoreIntrinsics(IntNo, Op, Subtarget, DAG);
14103
14104 case Intrinsic::riscv_sf_vc_xv_se:
14105 return getVCIXISDNodeVOID(Op, DAG, RISCVISD::SF_VC_XV_SE);
14106 case Intrinsic::riscv_sf_vc_iv_se:
14107 return getVCIXISDNodeVOID(Op, DAG, RISCVISD::SF_VC_IV_SE);
14108 case Intrinsic::riscv_sf_vc_vv_se:
14109 return getVCIXISDNodeVOID(Op, DAG, RISCVISD::SF_VC_VV_SE);
14110 case Intrinsic::riscv_sf_vc_fv_se:
14111 return getVCIXISDNodeVOID(Op, DAG, RISCVISD::SF_VC_FV_SE);
14112 case Intrinsic::riscv_sf_vc_xvv_se:
14113 return getVCIXISDNodeVOID(Op, DAG, RISCVISD::SF_VC_XVV_SE);
14114 case Intrinsic::riscv_sf_vc_ivv_se:
14115 return getVCIXISDNodeVOID(Op, DAG, RISCVISD::SF_VC_IVV_SE);
14116 case Intrinsic::riscv_sf_vc_vvv_se:
14117 return getVCIXISDNodeVOID(Op, DAG, RISCVISD::SF_VC_VVV_SE);
14118 case Intrinsic::riscv_sf_vc_fvv_se:
14119 return getVCIXISDNodeVOID(Op, DAG, RISCVISD::SF_VC_FVV_SE);
14120 case Intrinsic::riscv_sf_vc_xvw_se:
14121 return getVCIXISDNodeVOID(Op, DAG, RISCVISD::SF_VC_XVW_SE);
14122 case Intrinsic::riscv_sf_vc_ivw_se:
14123 return getVCIXISDNodeVOID(Op, DAG, RISCVISD::SF_VC_IVW_SE);
14124 case Intrinsic::riscv_sf_vc_vvw_se:
14125 return getVCIXISDNodeVOID(Op, DAG, RISCVISD::SF_VC_VVW_SE);
14126 case Intrinsic::riscv_sf_vc_fvw_se:
14127 return getVCIXISDNodeVOID(Op, DAG, RISCVISD::SF_VC_FVW_SE);
14128 }
14129
14130 return lowerVectorIntrinsicScalars(Op, DAG, Subtarget);
14131}
14132
14133static unsigned getRVVReductionOp(unsigned ISDOpcode) {
14134 switch (ISDOpcode) {
14135 default:
14136 llvm_unreachable("Unhandled reduction");
14137 case ISD::VP_REDUCE_ADD:
14138 case ISD::VECREDUCE_ADD:
14139 return RISCVISD::VECREDUCE_ADD_VL;
14140 case ISD::VP_REDUCE_UMAX:
14142 return RISCVISD::VECREDUCE_UMAX_VL;
14143 case ISD::VP_REDUCE_SMAX:
14145 return RISCVISD::VECREDUCE_SMAX_VL;
14146 case ISD::VP_REDUCE_UMIN:
14148 return RISCVISD::VECREDUCE_UMIN_VL;
14149 case ISD::VP_REDUCE_SMIN:
14151 return RISCVISD::VECREDUCE_SMIN_VL;
14152 case ISD::VP_REDUCE_AND:
14153 case ISD::VECREDUCE_AND:
14154 return RISCVISD::VECREDUCE_AND_VL;
14155 case ISD::VP_REDUCE_OR:
14156 case ISD::VECREDUCE_OR:
14157 return RISCVISD::VECREDUCE_OR_VL;
14158 case ISD::VP_REDUCE_XOR:
14159 case ISD::VECREDUCE_XOR:
14160 return RISCVISD::VECREDUCE_XOR_VL;
14161 case ISD::VP_REDUCE_FADD:
14162 return RISCVISD::VECREDUCE_FADD_VL;
14163 case ISD::VP_REDUCE_SEQ_FADD:
14164 return RISCVISD::VECREDUCE_SEQ_FADD_VL;
14165 case ISD::VP_REDUCE_FMAX:
14166 case ISD::VP_REDUCE_FMAXIMUM:
14167 return RISCVISD::VECREDUCE_FMAX_VL;
14168 case ISD::VP_REDUCE_FMIN:
14169 case ISD::VP_REDUCE_FMINIMUM:
14170 return RISCVISD::VECREDUCE_FMIN_VL;
14171 }
14172
14173}
14174
14175SDValue RISCVTargetLowering::lowerVectorMaskVecReduction(SDValue Op,
14176 SelectionDAG &DAG,
14177 bool IsVP) const {
14178 SDLoc DL(Op);
14179 SDValue Vec = Op.getOperand(IsVP ? 1 : 0);
14180 MVT VecVT = Vec.getSimpleValueType();
14181 assert((Op.getOpcode() == ISD::VECREDUCE_AND ||
14182 Op.getOpcode() == ISD::VECREDUCE_OR ||
14183 Op.getOpcode() == ISD::VECREDUCE_XOR ||
14184 Op.getOpcode() == ISD::VP_REDUCE_AND ||
14185 Op.getOpcode() == ISD::VP_REDUCE_OR ||
14186 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
14187 "Unexpected reduction lowering");
14188
14189 MVT XLenVT = Subtarget.getXLenVT();
14190
14191 MVT ContainerVT = VecVT;
14192 if (VecVT.isFixedLengthVector()) {
14193 ContainerVT = getContainerForFixedLengthVector(VecVT);
14194 Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget);
14195 }
14196
14197 SDValue Mask, VL;
14198 if (IsVP) {
14199 Mask = Op.getOperand(2);
14200 VL = Op.getOperand(3);
14201 } else {
14202 std::tie(Mask, VL) =
14203 getDefaultVLOps(VecVT, ContainerVT, DL, DAG, Subtarget);
14204 }
14205
14206 ISD::CondCode CC;
14207 switch (Op.getOpcode()) {
14208 default:
14209 llvm_unreachable("Unhandled reduction");
14210 case ISD::VECREDUCE_AND:
14211 case ISD::VP_REDUCE_AND: {
14212 // vcpop ~x == 0
14213 if (VecVT.isFixedLengthVector())
14214 Vec = DAG.getNode(RISCVISD::VMXOR_VL, DL, ContainerVT, Vec,
14215 DAG.getAllOnesConstant(DL, ContainerVT), VL);
14216 else
14217 Vec = DAG.getNOT(DL, Vec, ContainerVT);
14218 Vec = DAG.getNode(RISCVISD::VCPOP_VL, DL, XLenVT, Vec, Mask, VL);
14219 CC = ISD::SETEQ;
14220 break;
14221 }
14222 case ISD::VECREDUCE_OR:
14223 case ISD::VP_REDUCE_OR:
14224 // vcpop x != 0
14225 Vec = DAG.getNode(RISCVISD::VCPOP_VL, DL, XLenVT, Vec, Mask, VL);
14226 CC = ISD::SETNE;
14227 break;
14228 case ISD::VECREDUCE_XOR:
14229 case ISD::VP_REDUCE_XOR: {
14230 // ((vcpop x) & 1) != 0
14231 SDValue One = DAG.getConstant(1, DL, XLenVT);
14232 Vec = DAG.getNode(RISCVISD::VCPOP_VL, DL, XLenVT, Vec, Mask, VL);
14233 Vec = DAG.getNode(ISD::AND, DL, XLenVT, Vec, One);
14234 CC = ISD::SETNE;
14235 break;
14236 }
14237 }
14238
14239 SDValue Zero = DAG.getConstant(0, DL, XLenVT);
14240 SDValue SetCC = DAG.getSetCC(DL, XLenVT, Vec, Zero, CC);
14241 SetCC = DAG.getNode(ISD::TRUNCATE, DL, Op.getValueType(), SetCC);
14242
14243 if (!IsVP)
14244 return SetCC;
14245
14246 // Now include the start value in the operation.
14247 // Note that we must return the start value when no elements are operated
14248 // upon. The vcpop instructions we've emitted in each case above will return
14249 // 0 for an inactive vector, and so we've already received the neutral value:
14250 // AND gives us (0 == 0) -> 1 and OR/XOR give us (0 != 0) -> 0. Therefore we
14251 // can simply include the start value.
14252 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Op.getOpcode());
14253 return DAG.getNode(BaseOpc, DL, Op.getValueType(), SetCC, Op.getOperand(0));
14254}
14255
14256static bool isNonZeroAVL(SDValue AVL) {
14257 auto *RegisterAVL = dyn_cast<RegisterSDNode>(AVL);
14258 auto *ImmAVL = dyn_cast<ConstantSDNode>(AVL);
14259 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
14260 (ImmAVL && ImmAVL->getZExtValue() >= 1);
14261}
14262
14263/// Helper to lower a reduction sequence of the form:
14264/// scalar = reduce_op vec, scalar_start
14265static SDValue lowerReductionSeq(unsigned RVVOpcode, MVT ResVT,
14266 SDValue StartValue, SDValue Vec, SDValue Mask,
14267 SDValue VL, const SDLoc &DL, SelectionDAG &DAG,
14268 const RISCVSubtarget &Subtarget) {
14269 const MVT VecVT = Vec.getSimpleValueType();
14270 const MVT M1VT = RISCVTargetLowering::getM1VT(VecVT);
14271 const MVT XLenVT = Subtarget.getXLenVT();
14272 const bool NonZeroAVL = isNonZeroAVL(VL);
14273
14274 // The reduction needs an LMUL1 input; do the splat at either LMUL1
14275 // or the original VT if fractional.
14276 auto InnerVT = VecVT.bitsLE(M1VT) ? VecVT : M1VT;
14277 // We reuse the VL of the reduction to reduce vsetvli toggles if we can
14278 // prove it is non-zero. For the AVL=0 case, we need the scalar to
14279 // be the result of the reduction operation.
14280 auto InnerVL = NonZeroAVL ? VL : DAG.getConstant(1, DL, XLenVT);
14281 SDValue InitialValue =
14282 lowerScalarInsert(StartValue, InnerVL, InnerVT, DL, DAG, Subtarget);
14283 if (M1VT != InnerVT)
14284 InitialValue =
14285 DAG.getInsertSubvector(DL, DAG.getUNDEF(M1VT), InitialValue, 0);
14286 SDValue PassThru = NonZeroAVL ? DAG.getUNDEF(M1VT) : InitialValue;
14288 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
14289 SDValue Reduction = DAG.getNode(RVVOpcode, DL, M1VT, Ops);
14290 return DAG.getExtractVectorElt(DL, ResVT, Reduction, 0);
14291}
14292
14293SDValue RISCVTargetLowering::lowerVECREDUCE(SDValue Op,
14294 SelectionDAG &DAG) const {
14295 SDLoc DL(Op);
14296 SDValue Vec = Op.getOperand(0);
14297 EVT VecEVT = Vec.getValueType();
14298
14299 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Op.getOpcode());
14300
14301 // Due to ordering in legalize types we may have a vector type that needs to
14302 // be split. Do that manually so we can get down to a legal type.
14303 while (getTypeAction(*DAG.getContext(), VecEVT) ==
14305 auto [Lo, Hi] = DAG.SplitVector(Vec, DL);
14306 VecEVT = Lo.getValueType();
14307 Vec = DAG.getNode(BaseOpc, DL, VecEVT, Lo, Hi);
14308 }
14309
14310 // TODO: The type may need to be widened rather than split. Or widened before
14311 // it can be split.
14312 if (!isTypeLegal(VecEVT))
14313 return SDValue();
14314
14315 MVT VecVT = VecEVT.getSimpleVT();
14316 MVT VecEltVT = VecVT.getVectorElementType();
14317 unsigned RVVOpcode = getRVVReductionOp(Op.getOpcode());
14318
14319 MVT ContainerVT = VecVT;
14320 if (VecVT.isFixedLengthVector()) {
14321 ContainerVT = getContainerForFixedLengthVector(VecVT);
14322 Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget);
14323 }
14324
14325 auto [Mask, VL] = getDefaultVLOps(VecVT, ContainerVT, DL, DAG, Subtarget);
14326
14327 SDValue StartV;
14328 switch (BaseOpc) {
14329 default:
14330 StartV = DAG.getIdentityElement(BaseOpc, DL, VecEltVT, SDNodeFlags());
14331 break;
14332 case ISD::AND:
14333 case ISD::OR:
14334 case ISD::UMAX:
14335 case ISD::UMIN:
14336 case ISD::SMAX:
14337 case ISD::SMIN:
14338 StartV = DAG.getExtractVectorElt(DL, VecEltVT, Vec, 0);
14339 break;
14340 }
14341 return lowerReductionSeq(RVVOpcode, Op.getSimpleValueType(), StartV, Vec,
14342 Mask, VL, DL, DAG, Subtarget);
14343}
14344
14345// Given a reduction op, this function returns the matching reduction opcode,
14346// the vector SDValue and the scalar SDValue required to lower this to a
14347// RISCVISD node.
14348static std::tuple<unsigned, SDValue, SDValue>
14350 const RISCVSubtarget &Subtarget) {
14351 SDLoc DL(Op);
14352 auto Flags = Op->getFlags();
14353 unsigned Opcode = Op.getOpcode();
14354 switch (Opcode) {
14355 default:
14356 llvm_unreachable("Unhandled reduction");
14357 case ISD::VECREDUCE_FADD: {
14358 // Use positive zero if we can. It is cheaper to materialize.
14359 SDValue Zero =
14360 DAG.getConstantFP(Flags.hasNoSignedZeros() ? 0.0 : -0.0, DL, EltVT);
14361 return std::make_tuple(RISCVISD::VECREDUCE_FADD_VL, Op.getOperand(0), Zero);
14362 }
14364 return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL, Op.getOperand(1),
14365 Op.getOperand(0));
14369 case ISD::VECREDUCE_FMAX: {
14370 SDValue Front = DAG.getExtractVectorElt(DL, EltVT, Op.getOperand(0), 0);
14371 unsigned RVVOpc =
14372 (Opcode == ISD::VECREDUCE_FMIN || Opcode == ISD::VECREDUCE_FMINIMUM)
14373 ? RISCVISD::VECREDUCE_FMIN_VL
14374 : RISCVISD::VECREDUCE_FMAX_VL;
14375 return std::make_tuple(RVVOpc, Op.getOperand(0), Front);
14376 }
14377 }
14378}
14379
14380SDValue RISCVTargetLowering::lowerFPVECREDUCE(SDValue Op,
14381 SelectionDAG &DAG) const {
14382 SDLoc DL(Op);
14383 MVT VecEltVT = Op.getSimpleValueType();
14384
14385 unsigned RVVOpcode;
14386 SDValue VectorVal, ScalarVal;
14387 std::tie(RVVOpcode, VectorVal, ScalarVal) =
14388 getRVVFPReductionOpAndOperands(Op, DAG, VecEltVT, Subtarget);
14389 MVT VecVT = VectorVal.getSimpleValueType();
14390
14391 MVT ContainerVT = VecVT;
14392 if (VecVT.isFixedLengthVector()) {
14393 ContainerVT = getContainerForFixedLengthVector(VecVT);
14394 VectorVal = convertToScalableVector(ContainerVT, VectorVal, DAG, Subtarget);
14395 }
14396
14397 MVT ResVT = Op.getSimpleValueType();
14398 auto [Mask, VL] = getDefaultVLOps(VecVT, ContainerVT, DL, DAG, Subtarget);
14399 SDValue Res = lowerReductionSeq(RVVOpcode, ResVT, ScalarVal, VectorVal, Mask,
14400 VL, DL, DAG, Subtarget);
14401 if (Op.getOpcode() != ISD::VECREDUCE_FMINIMUM &&
14402 Op.getOpcode() != ISD::VECREDUCE_FMAXIMUM)
14403 return Res;
14404
14405 if (Op->getFlags().hasNoNaNs())
14406 return Res;
14407
14408 // Force output to NaN if any element is Nan.
14409 SDValue IsNan =
14410 DAG.getNode(RISCVISD::SETCC_VL, DL, Mask.getValueType(),
14411 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
14412 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
14413 MVT XLenVT = Subtarget.getXLenVT();
14414 SDValue CPop = DAG.getNode(RISCVISD::VCPOP_VL, DL, XLenVT, IsNan, Mask, VL);
14415 SDValue NoNaNs = DAG.getSetCC(DL, XLenVT, CPop,
14416 DAG.getConstant(0, DL, XLenVT), ISD::SETEQ);
14417 return DAG.getSelect(
14418 DL, ResVT, NoNaNs, Res,
14419 DAG.getConstantFP(APFloat::getNaN(ResVT.getFltSemantics()), DL, ResVT));
14420}
14421
14422SDValue RISCVTargetLowering::lowerVPREDUCE(SDValue Op,
14423 SelectionDAG &DAG) const {
14424 SDLoc DL(Op);
14425 unsigned Opc = Op.getOpcode();
14426 SDValue Start = Op.getOperand(0);
14427 SDValue Vec = Op.getOperand(1);
14428 EVT VecEVT = Vec.getValueType();
14429 MVT XLenVT = Subtarget.getXLenVT();
14430
14431 // TODO: The type may need to be widened rather than split. Or widened before
14432 // it can be split.
14433 if (!isTypeLegal(VecEVT))
14434 return SDValue();
14435
14436 MVT VecVT = VecEVT.getSimpleVT();
14437 unsigned RVVOpcode = getRVVReductionOp(Opc);
14438
14439 SDValue VL = Op.getOperand(3);
14440 SDValue Mask = Op.getOperand(2);
14441 if (VecVT.isFixedLengthVector()) {
14442 auto ContainerVT = getContainerForFixedLengthVector(VecVT);
14443 Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget);
14444 Mask = convertToScalableVector(getMaskTypeFor(ContainerVT), Mask, DAG,
14445 Subtarget);
14446 }
14447 SDValue Res =
14448 lowerReductionSeq(RVVOpcode, Op.getSimpleValueType(), Op.getOperand(0),
14449 Vec, Mask, VL, DL, DAG, Subtarget);
14450 if ((Opc != ISD::VP_REDUCE_FMINIMUM && Opc != ISD::VP_REDUCE_FMAXIMUM) ||
14451 Op->getFlags().hasNoNaNs())
14452 return Res;
14453
14454 // Propagate NaNs.
14455 MVT PredVT = getMaskTypeFor(Vec.getSimpleValueType());
14456 // Check if any of the elements in Vec is NaN.
14457 SDValue IsNaN = DAG.getNode(
14458 RISCVISD::SETCC_VL, DL, PredVT,
14459 {Vec, Vec, DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(PredVT), Mask, VL});
14460 SDValue VCPop = DAG.getNode(RISCVISD::VCPOP_VL, DL, XLenVT, IsNaN, Mask, VL);
14461 // Check if the start value is NaN.
14462 SDValue StartIsNaN = DAG.getSetCC(DL, XLenVT, Start, Start, ISD::SETUO);
14463 VCPop = DAG.getNode(ISD::OR, DL, XLenVT, VCPop, StartIsNaN);
14464 SDValue NoNaNs = DAG.getSetCC(DL, XLenVT, VCPop,
14465 DAG.getConstant(0, DL, XLenVT), ISD::SETEQ);
14466 MVT ResVT = Res.getSimpleValueType();
14467 return DAG.getSelect(
14468 DL, ResVT, NoNaNs, Res,
14469 DAG.getConstantFP(APFloat::getNaN(ResVT.getFltSemantics()), DL, ResVT));
14470}
14471
14473 SDValue V, MVT WideVT);
14474
14475SDValue RISCVTargetLowering::lowerINSERT_SUBVECTOR(SDValue Op,
14476 SelectionDAG &DAG) const {
14477 SDValue Vec = Op.getOperand(0);
14478 SDValue SubVec = Op.getOperand(1);
14479 MVT VecVT = Vec.getSimpleValueType();
14480 MVT SubVecVT = SubVec.getSimpleValueType();
14481
14482 SDLoc DL(Op);
14483 MVT XLenVT = Subtarget.getXLenVT();
14484 unsigned OrigIdx = Op.getConstantOperandVal(2);
14485 const RISCVRegisterInfo *TRI = Subtarget.getRegisterInfo();
14486
14487 bool IsPExtInsert =
14488 Subtarget.hasStdExtP() &&
14489 ((Subtarget.is64Bit() &&
14490 (SubVecVT == MVT::v2i16 || SubVecVT == MVT::v4i8)) ||
14491 (!Subtarget.is64Bit() && (VecVT == MVT::v4i16 || VecVT == MVT::v8i8)));
14492
14493 // Fold insert of a 32-bit packed type into a zero-filled 64-bit packed vector
14494 // at index 0 (a zero-extend) to avoid scalarizing it into a byte-wise repack.
14495 if (IsPExtInsert) {
14496 if ((VecVT != MVT::v4i16 && VecVT != MVT::v8i8) ||
14497 SubVecVT.getSizeInBits() != 32 || OrigIdx != 0 ||
14499 return SDValue();
14500
14501 if (!Subtarget.is64Bit()) {
14502 SDValue Zero = DAG.getBitcast(SubVecVT, DAG.getConstant(0, DL, MVT::i32));
14503 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VecVT, SubVec, Zero);
14504 }
14505 return widenPackedVectorWithZeros(DAG, DL, SubVec, VecVT);
14506 }
14507
14508 if (OrigIdx == 0 && Vec.isUndef())
14509 return Op;
14510
14511 // We don't have the ability to slide mask vectors up indexed by their i1
14512 // elements; the smallest we can do is i8. Often we are able to bitcast to
14513 // equivalent i8 vectors. Note that when inserting a fixed-length vector
14514 // into a scalable one, we might not necessarily have enough scalable
14515 // elements to safely divide by 8: nxv1i1 = insert nxv1i1, v4i1 is valid.
14516 if (SubVecVT.getVectorElementType() == MVT::i1) {
14517 if (VecVT.getVectorMinNumElements() >= 8 &&
14518 SubVecVT.getVectorMinNumElements() >= 8) {
14519 assert(OrigIdx % 8 == 0 && "Invalid index");
14520 assert(VecVT.getVectorMinNumElements() % 8 == 0 &&
14521 SubVecVT.getVectorMinNumElements() % 8 == 0 &&
14522 "Unexpected mask vector lowering");
14523 OrigIdx /= 8;
14524 SubVecVT =
14525 MVT::getVectorVT(MVT::i8, SubVecVT.getVectorMinNumElements() / 8,
14526 SubVecVT.isScalableVector());
14527 VecVT = MVT::getVectorVT(MVT::i8, VecVT.getVectorMinNumElements() / 8,
14528 VecVT.isScalableVector());
14529 Vec = DAG.getBitcast(VecVT, Vec);
14530 SubVec = DAG.getBitcast(SubVecVT, SubVec);
14531 } else {
14532 // We can't slide this mask vector up indexed by its i1 elements.
14533 // This poses a problem when we wish to insert a scalable vector which
14534 // can't be re-expressed as a larger type. Just choose the slow path and
14535 // extend to a larger type, then truncate back down.
14536 MVT ExtVecVT = VecVT.changeVectorElementType(MVT::i8);
14537 MVT ExtSubVecVT = SubVecVT.changeVectorElementType(MVT::i8);
14538 Vec = DAG.getNode(ISD::ZERO_EXTEND, DL, ExtVecVT, Vec);
14539 SubVec = DAG.getNode(ISD::ZERO_EXTEND, DL, ExtSubVecVT, SubVec);
14540 Vec = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, ExtVecVT, Vec, SubVec,
14541 Op.getOperand(2));
14542 SDValue SplatZero = DAG.getConstant(0, DL, ExtVecVT);
14543 return DAG.getSetCC(DL, VecVT, Vec, SplatZero, ISD::SETNE);
14544 }
14545 }
14546
14547 // If the subvector vector is a fixed-length type and we don't know VLEN
14548 // exactly, we cannot use subregister manipulation to simplify the codegen; we
14549 // don't know which register of a LMUL group contains the specific subvector
14550 // as we only know the minimum register size. Therefore we must slide the
14551 // vector group up the full amount.
14552 const auto VLen = Subtarget.getRealVLen();
14553 if (SubVecVT.isFixedLengthVector() && !VLen) {
14554 MVT ContainerVT = VecVT;
14555 if (VecVT.isFixedLengthVector()) {
14556 ContainerVT = getContainerForFixedLengthVector(VecVT);
14557 Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget);
14558 }
14559
14560 SubVec = DAG.getInsertSubvector(DL, DAG.getUNDEF(ContainerVT), SubVec, 0);
14561
14562 SDValue Mask =
14563 getDefaultVLOps(VecVT, ContainerVT, DL, DAG, Subtarget).first;
14564 // Set the vector length to only the number of elements we care about. Note
14565 // that for slideup this includes the offset.
14566 unsigned EndIndex = OrigIdx + SubVecVT.getVectorNumElements();
14567 SDValue VL = DAG.getConstant(EndIndex, DL, XLenVT);
14568
14569 // Use tail agnostic policy if we're inserting over Vec's tail.
14571 if (VecVT.isFixedLengthVector() && EndIndex == VecVT.getVectorNumElements())
14573
14574 // If we're inserting into the lowest elements, use a tail undisturbed
14575 // vmv.v.v.
14576 if (OrigIdx == 0) {
14577 SubVec =
14578 DAG.getNode(RISCVISD::VMV_V_V_VL, DL, ContainerVT, Vec, SubVec, VL);
14579 } else {
14580 SDValue SlideupAmt = DAG.getConstant(OrigIdx, DL, XLenVT);
14581 SubVec = getVSlideup(DAG, Subtarget, DL, ContainerVT, Vec, SubVec,
14582 SlideupAmt, Mask, VL, Policy);
14583 }
14584
14585 if (VecVT.isFixedLengthVector())
14586 SubVec = convertFromScalableVector(VecVT, SubVec, DAG, Subtarget);
14587 return DAG.getBitcast(Op.getValueType(), SubVec);
14588 }
14589
14590 MVT ContainerVecVT = VecVT;
14591 if (VecVT.isFixedLengthVector()) {
14592 ContainerVecVT = getContainerForFixedLengthVector(VecVT);
14593 Vec = convertToScalableVector(ContainerVecVT, Vec, DAG, Subtarget);
14594 }
14595
14596 MVT ContainerSubVecVT = SubVecVT;
14597 if (SubVecVT.isFixedLengthVector()) {
14598 ContainerSubVecVT = getContainerForFixedLengthVector(SubVecVT);
14599 SubVec = convertToScalableVector(ContainerSubVecVT, SubVec, DAG, Subtarget);
14600 }
14601
14602 unsigned SubRegIdx;
14603 ElementCount RemIdx;
14604 // insert_subvector scales the index by vscale if the subvector is scalable,
14605 // and decomposeSubvectorInsertExtractToSubRegs takes this into account. So if
14606 // we have a fixed length subvector, we need to adjust the index by 1/vscale.
14607 if (SubVecVT.isFixedLengthVector()) {
14608 assert(VLen);
14609 unsigned Vscale = *VLen / RISCV::RVVBitsPerBlock;
14610 auto Decompose =
14612 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale, TRI);
14613 SubRegIdx = Decompose.first;
14614 RemIdx = ElementCount::getFixed((Decompose.second * Vscale) +
14615 (OrigIdx % Vscale));
14616 } else {
14617 auto Decompose =
14619 ContainerVecVT, ContainerSubVecVT, OrigIdx, TRI);
14620 SubRegIdx = Decompose.first;
14621 RemIdx = ElementCount::getScalable(Decompose.second);
14622 }
14623
14624 TypeSize VecRegSize = TypeSize::getScalable(RISCV::RVVBitsPerBlock);
14626 Subtarget.expandVScale(SubVecVT.getSizeInBits()).getKnownMinValue()));
14627 bool ExactlyVecRegSized =
14628 Subtarget.expandVScale(SubVecVT.getSizeInBits())
14629 .isKnownMultipleOf(Subtarget.expandVScale(VecRegSize));
14630
14631 // 1. If the Idx has been completely eliminated and this subvector's size is
14632 // a vector register or a multiple thereof, or the surrounding elements are
14633 // undef, then this is a subvector insert which naturally aligns to a vector
14634 // register. These can easily be handled using subregister manipulation.
14635 // 2. If the subvector isn't an exact multiple of a valid register group size,
14636 // then the insertion must preserve the undisturbed elements of the register.
14637 // We do this by lowering to an EXTRACT_SUBVECTOR grabbing the nearest LMUL=1
14638 // vector type (which resolves to a subregister copy), performing a VSLIDEUP
14639 // to place the subvector within the vector register, and an INSERT_SUBVECTOR
14640 // of that LMUL=1 type back into the larger vector (resolving to another
14641 // subregister operation). See below for how our VSLIDEUP works. We go via a
14642 // LMUL=1 type to avoid allocating a large register group to hold our
14643 // subvector.
14644 if (RemIdx.isZero() && (ExactlyVecRegSized || Vec.isUndef())) {
14645 if (SubVecVT.isFixedLengthVector()) {
14646 // We may get NoSubRegister if inserting at index 0 and the subvec
14647 // container is the same as the vector, e.g. vec=v4i32,subvec=v4i32,idx=0
14648 if (SubRegIdx == RISCV::NoSubRegister) {
14649 assert(OrigIdx == 0);
14650 return Op;
14651 }
14652
14653 // Use a insert_subvector that will resolve to an insert subreg.
14654 assert(VLen);
14655 unsigned Vscale = *VLen / RISCV::RVVBitsPerBlock;
14656 SDValue Insert =
14657 DAG.getInsertSubvector(DL, Vec, SubVec, OrigIdx / Vscale);
14658 if (VecVT.isFixedLengthVector())
14659 Insert = convertFromScalableVector(VecVT, Insert, DAG, Subtarget);
14660 return Insert;
14661 }
14662 return Op;
14663 }
14664
14665 // VSLIDEUP works by leaving elements 0<i<OFFSET undisturbed, elements
14666 // OFFSET<=i<VL set to the "subvector" and vl<=i<VLMAX set to the tail policy
14667 // (in our case undisturbed). This means we can set up a subvector insertion
14668 // where OFFSET is the insertion offset, and the VL is the OFFSET plus the
14669 // size of the subvector.
14670 MVT InterSubVT = ContainerVecVT;
14671 SDValue AlignedExtract = Vec;
14672 unsigned AlignedIdx = OrigIdx - RemIdx.getKnownMinValue();
14673 if (SubVecVT.isFixedLengthVector()) {
14674 assert(VLen);
14675 AlignedIdx /= *VLen / RISCV::RVVBitsPerBlock;
14676 }
14677 if (ContainerVecVT.bitsGT(RISCVTargetLowering::getM1VT(ContainerVecVT))) {
14678 InterSubVT = RISCVTargetLowering::getM1VT(ContainerVecVT);
14679 // Extract a subvector equal to the nearest full vector register type. This
14680 // should resolve to a EXTRACT_SUBREG instruction.
14681 AlignedExtract = DAG.getExtractSubvector(DL, InterSubVT, Vec, AlignedIdx);
14682 }
14683
14684 SubVec = DAG.getInsertSubvector(DL, DAG.getUNDEF(InterSubVT), SubVec, 0);
14685
14686 auto [Mask, VL] = getDefaultVLOps(VecVT, ContainerVecVT, DL, DAG, Subtarget);
14687
14688 ElementCount EndIndex = RemIdx + SubVecVT.getVectorElementCount();
14689 VL = DAG.getElementCount(DL, XLenVT, SubVecVT.getVectorElementCount());
14690
14691 // Use tail agnostic policy if we're inserting over InterSubVT's tail.
14693 if (Subtarget.expandVScale(EndIndex) ==
14694 Subtarget.expandVScale(InterSubVT.getVectorElementCount()))
14696
14697 // If we're inserting into the lowest elements, use a tail undisturbed
14698 // vmv.v.v.
14699 if (RemIdx.isZero()) {
14700 SubVec = DAG.getNode(RISCVISD::VMV_V_V_VL, DL, InterSubVT, AlignedExtract,
14701 SubVec, VL);
14702 } else {
14703 SDValue SlideupAmt = DAG.getElementCount(DL, XLenVT, RemIdx);
14704
14705 // Construct the vector length corresponding to RemIdx + length(SubVecVT).
14706 VL = DAG.getNode(ISD::ADD, DL, XLenVT, SlideupAmt, VL);
14707
14708 SubVec = getVSlideup(DAG, Subtarget, DL, InterSubVT, AlignedExtract, SubVec,
14709 SlideupAmt, Mask, VL, Policy);
14710 }
14711
14712 // If required, insert this subvector back into the correct vector register.
14713 // This should resolve to an INSERT_SUBREG instruction.
14714 if (ContainerVecVT.bitsGT(InterSubVT))
14715 SubVec = DAG.getInsertSubvector(DL, Vec, SubVec, AlignedIdx);
14716
14717 if (VecVT.isFixedLengthVector())
14718 SubVec = convertFromScalableVector(VecVT, SubVec, DAG, Subtarget);
14719
14720 // We might have bitcast from a mask type: cast back to the original type if
14721 // required.
14722 return DAG.getBitcast(Op.getSimpleValueType(), SubVec);
14723}
14724
14725SDValue RISCVTargetLowering::lowerEXTRACT_SUBVECTOR(SDValue Op,
14726 SelectionDAG &DAG) const {
14727 SDValue Vec = Op.getOperand(0);
14728 MVT SubVecVT = Op.getSimpleValueType();
14729 MVT VecVT = Vec.getSimpleValueType();
14730
14731 SDLoc DL(Op);
14732 MVT XLenVT = Subtarget.getXLenVT();
14733 unsigned OrigIdx = Op.getConstantOperandVal(1);
14734 const RISCVRegisterInfo *TRI = Subtarget.getRegisterInfo();
14735
14736 // With an index of 0 this is a cast-like subvector, which can be performed
14737 // with subregister operations.
14738 if (OrigIdx == 0)
14739 return Op;
14740
14741 // We don't have the ability to slide mask vectors down indexed by their i1
14742 // elements; the smallest we can do is i8. Often we are able to bitcast to
14743 // equivalent i8 vectors. Note that when extracting a fixed-length vector
14744 // from a scalable one, we might not necessarily have enough scalable
14745 // elements to safely divide by 8: v8i1 = extract nxv1i1 is valid.
14746 if (SubVecVT.getVectorElementType() == MVT::i1) {
14747 if (VecVT.getVectorMinNumElements() >= 8 &&
14748 SubVecVT.getVectorMinNumElements() >= 8) {
14749 assert(OrigIdx % 8 == 0 && "Invalid index");
14750 assert(VecVT.getVectorMinNumElements() % 8 == 0 &&
14751 SubVecVT.getVectorMinNumElements() % 8 == 0 &&
14752 "Unexpected mask vector lowering");
14753 OrigIdx /= 8;
14754 SubVecVT =
14755 MVT::getVectorVT(MVT::i8, SubVecVT.getVectorMinNumElements() / 8,
14756 SubVecVT.isScalableVector());
14757 VecVT = MVT::getVectorVT(MVT::i8, VecVT.getVectorMinNumElements() / 8,
14758 VecVT.isScalableVector());
14759 Vec = DAG.getBitcast(VecVT, Vec);
14760 } else {
14761 // We can't slide this mask vector down, indexed by its i1 elements.
14762 // This poses a problem when we wish to extract a scalable vector which
14763 // can't be re-expressed as a larger type. Just choose the slow path and
14764 // extend to a larger type, then truncate back down.
14765 // TODO: We could probably improve this when extracting certain fixed
14766 // from fixed, where we can extract as i8 and shift the correct element
14767 // right to reach the desired subvector?
14768 MVT ExtVecVT = VecVT.changeVectorElementType(MVT::i8);
14769 MVT ExtSubVecVT = SubVecVT.changeVectorElementType(MVT::i8);
14770 Vec = DAG.getNode(ISD::ZERO_EXTEND, DL, ExtVecVT, Vec);
14771 Vec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, ExtSubVecVT, Vec,
14772 Op.getOperand(1));
14773 SDValue SplatZero = DAG.getConstant(0, DL, ExtSubVecVT);
14774 return DAG.getSetCC(DL, SubVecVT, Vec, SplatZero, ISD::SETNE);
14775 }
14776 }
14777
14778 const auto VLen = Subtarget.getRealVLen();
14779
14780 // If the subvector vector is a fixed-length type and we don't know VLEN
14781 // exactly, we cannot use subregister manipulation to simplify the codegen; we
14782 // don't know which register of a LMUL group contains the specific subvector
14783 // as we only know the minimum register size. Therefore we must slide the
14784 // vector group down the full amount.
14785 if (SubVecVT.isFixedLengthVector() && !VLen) {
14786 MVT ContainerVT = VecVT;
14787 if (VecVT.isFixedLengthVector()) {
14788 ContainerVT = getContainerForFixedLengthVector(VecVT);
14789 Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget);
14790 }
14791
14792 // Shrink down Vec so we're performing the slidedown on a smaller LMUL.
14793 unsigned LastIdx = OrigIdx + SubVecVT.getVectorNumElements() - 1;
14794 if (auto ShrunkVT =
14795 getSmallestVTForIndex(ContainerVT, LastIdx, DL, DAG, Subtarget)) {
14796 ContainerVT = *ShrunkVT;
14797 Vec = DAG.getExtractSubvector(DL, ContainerVT, Vec, 0);
14798 }
14799
14800 SDValue Mask =
14801 getDefaultVLOps(VecVT, ContainerVT, DL, DAG, Subtarget).first;
14802 // Set the vector length to only the number of elements we care about. This
14803 // avoids sliding down elements we're going to discard straight away.
14804 SDValue VL = DAG.getConstant(SubVecVT.getVectorNumElements(), DL, XLenVT);
14805 SDValue SlidedownAmt = DAG.getConstant(OrigIdx, DL, XLenVT);
14806 SDValue Slidedown =
14807 getVSlidedown(DAG, Subtarget, DL, ContainerVT,
14808 DAG.getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
14809 // Now we can use a cast-like subvector extract to get the result.
14810 Slidedown = DAG.getExtractSubvector(DL, SubVecVT, Slidedown, 0);
14811 return DAG.getBitcast(Op.getValueType(), Slidedown);
14812 }
14813
14814 if (VecVT.isFixedLengthVector()) {
14815 VecVT = getContainerForFixedLengthVector(VecVT);
14816 Vec = convertToScalableVector(VecVT, Vec, DAG, Subtarget);
14817 }
14818
14819 MVT ContainerSubVecVT = SubVecVT;
14820 if (SubVecVT.isFixedLengthVector())
14821 ContainerSubVecVT = getContainerForFixedLengthVector(SubVecVT);
14822
14823 unsigned SubRegIdx;
14824 ElementCount RemIdx;
14825 // extract_subvector scales the index by vscale if the subvector is scalable,
14826 // and decomposeSubvectorInsertExtractToSubRegs takes this into account. So if
14827 // we have a fixed length subvector, we need to adjust the index by 1/vscale.
14828 if (SubVecVT.isFixedLengthVector()) {
14829 assert(VLen);
14830 unsigned Vscale = *VLen / RISCV::RVVBitsPerBlock;
14831 auto Decompose =
14833 VecVT, ContainerSubVecVT, OrigIdx / Vscale, TRI);
14834 SubRegIdx = Decompose.first;
14835 RemIdx = ElementCount::getFixed((Decompose.second * Vscale) +
14836 (OrigIdx % Vscale));
14837 } else {
14838 auto Decompose =
14840 VecVT, ContainerSubVecVT, OrigIdx, TRI);
14841 SubRegIdx = Decompose.first;
14842 RemIdx = ElementCount::getScalable(Decompose.second);
14843 }
14844
14845 // If the Idx has been completely eliminated then this is a subvector extract
14846 // which naturally aligns to a vector register. These can easily be handled
14847 // using subregister manipulation. We use an extract_subvector that will
14848 // resolve to an extract subreg.
14849 if (RemIdx.isZero()) {
14850 if (SubVecVT.isFixedLengthVector()) {
14851 assert(VLen);
14852 unsigned Vscale = *VLen / RISCV::RVVBitsPerBlock;
14853 Vec =
14854 DAG.getExtractSubvector(DL, ContainerSubVecVT, Vec, OrigIdx / Vscale);
14855 return convertFromScalableVector(SubVecVT, Vec, DAG, Subtarget);
14856 }
14857 return Op;
14858 }
14859
14860 // Else SubVecVT is M1 or smaller and may need to be slid down: if SubVecVT
14861 // was > M1 then the index would need to be a multiple of VLMAX, and so would
14862 // divide exactly.
14863 assert(RISCVVType::decodeVLMUL(getLMUL(ContainerSubVecVT)).second ||
14864 getLMUL(ContainerSubVecVT) == RISCVVType::LMUL_1);
14865
14866 // If the vector type is an LMUL-group type, extract a subvector equal to the
14867 // nearest full vector register type.
14868 MVT InterSubVT = VecVT;
14869 if (VecVT.bitsGT(RISCVTargetLowering::getM1VT(VecVT))) {
14870 // If VecVT has an LMUL > 1, then SubVecVT should have a smaller LMUL, and
14871 // we should have successfully decomposed the extract into a subregister.
14872 // We use an extract_subvector that will resolve to a subreg extract.
14873 assert(SubRegIdx != RISCV::NoSubRegister);
14874 (void)SubRegIdx;
14875 unsigned Idx = OrigIdx - RemIdx.getKnownMinValue();
14876 if (SubVecVT.isFixedLengthVector()) {
14877 assert(VLen);
14878 Idx /= *VLen / RISCV::RVVBitsPerBlock;
14879 }
14880 InterSubVT = RISCVTargetLowering::getM1VT(VecVT);
14881 Vec = DAG.getExtractSubvector(DL, InterSubVT, Vec, Idx);
14882 }
14883
14884 // Slide this vector register down by the desired number of elements in order
14885 // to place the desired subvector starting at element 0.
14886 SDValue SlidedownAmt = DAG.getElementCount(DL, XLenVT, RemIdx);
14887 auto [Mask, VL] = getDefaultScalableVLOps(InterSubVT, DL, DAG, Subtarget);
14888 if (SubVecVT.isFixedLengthVector())
14889 VL = DAG.getConstant(SubVecVT.getVectorNumElements(), DL, XLenVT);
14890 SDValue Slidedown =
14891 getVSlidedown(DAG, Subtarget, DL, InterSubVT, DAG.getUNDEF(InterSubVT),
14892 Vec, SlidedownAmt, Mask, VL);
14893
14894 // Now the vector is in the right position, extract our final subvector. This
14895 // should resolve to a COPY.
14896 Slidedown = DAG.getExtractSubvector(DL, SubVecVT, Slidedown, 0);
14897
14898 // We might have bitcast from a mask type: cast back to the original type if
14899 // required.
14900 return DAG.getBitcast(Op.getSimpleValueType(), Slidedown);
14901}
14902
14903// Widen a vector's operands to i8, then truncate its results back to the
14904// original type, typically i1. All operand and result types must be the same.
14906 SelectionDAG &DAG) {
14907 MVT VT = N.getSimpleValueType();
14908 MVT WideVT = VT.changeVectorElementType(MVT::i8);
14910 for (SDValue Op : N->ops()) {
14911 assert(Op.getSimpleValueType() == VT &&
14912 "Operands and result must be same type");
14913 WideOps.push_back(DAG.getNode(ISD::ZERO_EXTEND, DL, WideVT, Op));
14914 }
14915
14916 unsigned NumVals = N->getNumValues();
14917
14919 NumVals,
14920 N.getValueType().changeVectorElementType(*DAG.getContext(), MVT::i8)));
14921 SDValue WideN = DAG.getNode(N.getOpcode(), DL, VTs, WideOps);
14922 SmallVector<SDValue, 4> TruncVals;
14923 for (unsigned I = 0; I < NumVals; I++) {
14924 TruncVals.push_back(
14925 DAG.getSetCC(DL, N->getSimpleValueType(I), WideN.getValue(I),
14926 DAG.getConstant(0, DL, WideVT), ISD::SETNE));
14927 }
14928
14929 if (TruncVals.size() > 1)
14930 return DAG.getMergeValues(TruncVals, DL);
14931 return TruncVals.front();
14932}
14933
14934SDValue RISCVTargetLowering::lowerVECTOR_DEINTERLEAVE(SDValue Op,
14935 SelectionDAG &DAG) const {
14936 SDLoc DL(Op);
14937 MVT VecVT = Op.getSimpleValueType();
14938
14939 const unsigned Factor = Op->getNumValues();
14940 assert(Factor <= 8);
14941
14942 // 1 bit element vectors need to be widened to e8
14943 if (VecVT.getVectorElementType() == MVT::i1)
14944 return widenVectorOpsToi8(Op, DL, DAG);
14945
14946 bool IsFixedVector = VecVT.isFixedLengthVector();
14947
14948 MVT ContainerVecVT = VecVT;
14949 if (IsFixedVector)
14950 ContainerVecVT = getContainerForFixedLengthVector(VecVT);
14951
14952 // If concatenating would exceed LMUL=8, we need to split.
14953 if ((ContainerVecVT.getSizeInBits().getKnownMinValue() * Factor) >
14954 (8 * RISCV::RVVBitsPerBlock)) {
14955 SmallVector<SDValue, 8> Ops(Factor * 2);
14956 for (unsigned i = 0; i != Factor; ++i) {
14957 auto [OpLo, OpHi] = DAG.SplitVectorOperand(Op.getNode(), i);
14958 Ops[i * 2] = OpLo;
14959 Ops[i * 2 + 1] = OpHi;
14960 }
14961
14962 SmallVector<EVT, 8> VTs(Factor, Ops[0].getValueType());
14963
14964 SDValue Lo = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, VTs,
14965 ArrayRef(Ops).slice(0, Factor));
14966 SDValue Hi = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, VTs,
14967 ArrayRef(Ops).slice(Factor, Factor));
14968
14969 SmallVector<SDValue, 8> Res(Factor);
14970 for (unsigned i = 0; i != Factor; ++i)
14971 Res[i] = DAG.getNode(ISD::CONCAT_VECTORS, DL, VecVT, Lo.getValue(i),
14972 Hi.getValue(i));
14973
14974 return DAG.getMergeValues(Res, DL);
14975 }
14976
14977 if (Subtarget.hasStdExtZvzip() && Factor == 2 && !IsFixedVector) {
14978 MVT VT = Op->getSimpleValueType(0);
14979 MVT NewVT = VT.getDoubleNumVectorElementsVT();
14980 if (isTypeLegal(NewVT) &&
14982 SDValue V1 = Op->getOperand(0);
14983 SDValue V2 = Op->getOperand(1);
14984 SDValue V = DAG.getNode(ISD::CONCAT_VECTORS, DL, NewVT, V1, V2);
14985 SDValue Even =
14986 lowerZvzipVUNZIP(RISCVISD::VUNZIPE_VL, V, DL, DAG, Subtarget);
14987 SDValue Odd =
14988 lowerZvzipVUNZIP(RISCVISD::VUNZIPO_VL, V, DL, DAG, Subtarget);
14989 return DAG.getMergeValues({Even, Odd}, DL);
14990 }
14991 }
14992
14993 SmallVector<SDValue, 8> Ops(Op->op_values());
14994
14995 // Concatenate the vectors as one vector to deinterleave
14996 MVT ConcatVT =
14998 VecVT.getVectorElementCount() * PowerOf2Ceil(Factor));
14999 if (Ops.size() < PowerOf2Ceil(Factor))
15000 Ops.append(PowerOf2Ceil(Factor) - Factor, DAG.getUNDEF(VecVT));
15001 SDValue Concat = DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVT, Ops);
15002
15003 if (Factor == 2 && !IsFixedVector) {
15004 // We can deinterleave through vnsrl.wi if the element type is smaller than
15005 // ELEN
15006 if (VecVT.getScalarSizeInBits() < Subtarget.getELen()) {
15007 SDValue Even = getDeinterleaveShiftAndTrunc(DL, VecVT, Concat, 2, 0, DAG);
15008 SDValue Odd = getDeinterleaveShiftAndTrunc(DL, VecVT, Concat, 2, 1, DAG);
15009 return DAG.getMergeValues({Even, Odd}, DL);
15010 }
15011
15012 // For the indices, use the vmv.v.x of an i8 constant to fill the largest
15013 // possibly mask vector, then extract the required subvector. Doing this
15014 // (instead of a vid, vmsne sequence) reduces LMUL, and allows the mask
15015 // creation to be rematerialized during register allocation to reduce
15016 // register pressure if needed.
15017
15018 MVT MaskVT = ConcatVT.changeVectorElementType(MVT::i1);
15019
15020 SDValue EvenSplat = DAG.getConstant(0b01010101, DL, MVT::nxv8i8);
15021 EvenSplat = DAG.getBitcast(MVT::nxv64i1, EvenSplat);
15022 SDValue EvenMask = DAG.getExtractSubvector(DL, MaskVT, EvenSplat, 0);
15023
15024 SDValue OddSplat = DAG.getConstant(0b10101010, DL, MVT::nxv8i8);
15025 OddSplat = DAG.getBitcast(MVT::nxv64i1, OddSplat);
15026 SDValue OddMask = DAG.getExtractSubvector(DL, MaskVT, OddSplat, 0);
15027
15028 // vcompress the even and odd elements into two separate vectors
15029 SDValue EvenWide = DAG.getNode(ISD::VECTOR_COMPRESS, DL, ConcatVT, Concat,
15030 EvenMask, DAG.getUNDEF(ConcatVT));
15031 SDValue OddWide = DAG.getNode(ISD::VECTOR_COMPRESS, DL, ConcatVT, Concat,
15032 OddMask, DAG.getUNDEF(ConcatVT));
15033
15034 // Extract the result half of the gather for even and odd
15035 SDValue Even = DAG.getExtractSubvector(DL, VecVT, EvenWide, 0);
15036 SDValue Odd = DAG.getExtractSubvector(DL, VecVT, OddWide, 0);
15037
15038 return DAG.getMergeValues({Even, Odd}, DL);
15039 }
15040
15041 // Store with unit-stride store and load it back with segmented load.
15042 SDValue Mask, VL;
15043 MVT XLenVT = Subtarget.getXLenVT();
15044 auto &MF = DAG.getMachineFunction();
15045 SDValue Chain = DAG.getEntryNode();
15046 Align Alignment = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
15047 SDValue StackPtr;
15048 MachinePointerInfo PtrInfo;
15049 if (IsFixedVector) {
15050 // Calculating the stack size.
15051 ElementCount ActualConcatEC = VecVT.getVectorElementCount() * Factor;
15052 EVT ConcatEVT = EVT::getVectorVT(
15053 *DAG.getContext(), VecVT.getVectorElementType(), ActualConcatEC);
15054 StackPtr = DAG.CreateStackTemporary(ConcatEVT.getStoreSize(), Alignment);
15055 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
15056 PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
15057
15058 // If this is a fixed vector, instead of using the concat vector, we simply
15059 // store each fixed vector operand directly onto the stack, individually.
15060 // The reason being that if the fixed vector is (much) smaller than the
15061 // container vector, we will be wasting space on stack.
15062 TypeSize VecSize = VecVT.getStoreSize();
15063 SDValue BasePtr = StackPtr;
15064 MachinePointerInfo PI = PtrInfo;
15065 SmallVector<SDValue, 8> Tokens(Factor);
15066 for (auto [Idx, FieldOp] : enumerate(Op->op_values())) {
15067 if (Idx) {
15068 // Advance the pointer.
15069 BasePtr = DAG.getObjectPtrOffset(DL, BasePtr, VecSize);
15070 PI = PI.getWithOffset(VecSize);
15071 }
15072 Tokens[Idx] = DAG.getStore(Chain, DL, FieldOp, BasePtr, PI, Alignment);
15073 }
15074 Chain = DAG.getTokenFactor(DL, Tokens);
15075
15076 // Calculating Mask and VL for later usages.
15077 std::tie(Mask, VL) =
15078 getDefaultVLOps(VecVT, ContainerVecVT, DL, DAG, Subtarget);
15079 ConcatVT = getContainerForFixedLengthVector(ConcatVT);
15080 } else {
15081 std::tie(Mask, VL) = getDefaultScalableVLOps(VecVT, DL, DAG, Subtarget);
15082 StackPtr = DAG.CreateStackTemporary(ConcatVT.getStoreSize(), Alignment);
15083 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
15084 PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
15085
15086 SDValue StoreOps[] = {
15087 Chain, DAG.getTargetConstant(Intrinsic::riscv_vse, DL, XLenVT), Concat,
15088 StackPtr, VL};
15089
15090 Chain = DAG.getMemIntrinsicNode(
15091 ISD::INTRINSIC_VOID, DL, DAG.getVTList(MVT::Other), StoreOps,
15092 ConcatVT.getVectorElementType(), PtrInfo, Alignment,
15094 }
15095
15096 // Load it back with segmented load.
15097 SDValue Passthru = DAG.getUNDEF(ConcatVT);
15098 static const Intrinsic::ID VlsegIntrinsicsIds[] = {
15099 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
15100 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
15101 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
15102 Intrinsic::riscv_vlseg8_mask};
15103
15104 SDValue LoadOps[] = {
15105 Chain,
15106 DAG.getTargetConstant(VlsegIntrinsicsIds[Factor - 2], DL, XLenVT),
15107 Passthru,
15108 StackPtr,
15109 Mask,
15110 VL,
15113 DAG.getTargetConstant(Log2_64(VecVT.getScalarSizeInBits()), DL, XLenVT)};
15114
15115 unsigned Sz = Factor * ContainerVecVT.getVectorMinNumElements() *
15116 ContainerVecVT.getScalarSizeInBits();
15117 EVT VecTupTy = MVT::getRISCVVectorTupleVT(Sz, Factor);
15118
15119 SDValue Load = DAG.getMemIntrinsicNode(
15120 ISD::INTRINSIC_W_CHAIN, DL, DAG.getVTList({VecTupTy, MVT::Other}),
15121 LoadOps, ConcatVT.getVectorElementType(), PtrInfo, Alignment,
15123
15124 SmallVector<SDValue, 8> Res(Factor);
15125
15126 for (unsigned i = 0U; i < Factor; ++i) {
15127 SDValue FieldRes =
15128 DAG.getNode(RISCVISD::TUPLE_EXTRACT, DL, ContainerVecVT, Load,
15129 DAG.getTargetConstant(i, DL, MVT::i32));
15130 if (IsFixedVector)
15131 FieldRes = convertFromScalableVector(VecVT, FieldRes, DAG, Subtarget);
15132 Res[i] = FieldRes;
15133 }
15134
15135 return DAG.getMergeValues(Res, DL);
15136}
15137
15138SDValue RISCVTargetLowering::lowerVECTOR_INTERLEAVE(SDValue Op,
15139 SelectionDAG &DAG) const {
15140 SDLoc DL(Op);
15141 MVT VecVT = Op.getSimpleValueType();
15142
15143 const unsigned Factor = Op.getNumOperands();
15144 assert(Factor <= 8);
15145
15146 // i1 vectors need to be widened to i8
15147 if (VecVT.getVectorElementType() == MVT::i1)
15148 return widenVectorOpsToi8(Op, DL, DAG);
15149
15150 MVT ContainerVecVT = VecVT;
15151 if (VecVT.isFixedLengthVector())
15152 ContainerVecVT = getContainerForFixedLengthVector(VecVT);
15153
15154 // If the VT is larger than LMUL=8, we need to split and reassemble.
15155 if ((ContainerVecVT.getSizeInBits().getKnownMinValue() * Factor) >
15156 (8 * RISCV::RVVBitsPerBlock) ||
15157 // In an unlikely case, a vector type might be legal to RISC-V but
15158 // exceeds the MVT limit, in which we also want to split it.
15159 (Subtarget.hasStdExtZvzip() && Factor == 2 &&
15161 VecVT.getVectorElementCount() * Factor)))) {
15162 SmallVector<SDValue, 8> Ops(Factor * 2);
15163 for (unsigned i = 0; i != Factor; ++i) {
15164 auto [OpLo, OpHi] = DAG.SplitVectorOperand(Op.getNode(), i);
15165 Ops[i] = OpLo;
15166 Ops[i + Factor] = OpHi;
15167 }
15168
15169 SmallVector<EVT, 8> VTs(Factor, Ops[0].getValueType());
15170
15171 SDValue Res[] = {DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, VTs,
15172 ArrayRef(Ops).take_front(Factor)),
15174 ArrayRef(Ops).drop_front(Factor))};
15175
15176 SmallVector<SDValue, 8> Concats(Factor);
15177 for (unsigned i = 0; i != Factor; ++i) {
15178 unsigned IdxLo = 2 * i;
15179 unsigned IdxHi = 2 * i + 1;
15180 Concats[i] = DAG.getNode(ISD::CONCAT_VECTORS, DL, VecVT,
15181 Res[IdxLo / Factor].getValue(IdxLo % Factor),
15182 Res[IdxHi / Factor].getValue(IdxHi % Factor));
15183 }
15184
15185 return DAG.getMergeValues(Concats, DL);
15186 }
15187
15188 MVT XLenVT = Subtarget.getXLenVT();
15189 auto [Mask, VL] = getDefaultVLOps(VecVT, ContainerVecVT, DL, DAG, Subtarget);
15190
15191 SDValue Interleaved;
15192
15193 // Spill to the stack using a segment store for simplicity.
15194 if (Factor != 2) {
15195 EVT MemVT =
15197 VecVT.getVectorElementCount() * Factor);
15198
15199 // Allocate a stack slot.
15200 // Note that in the case where VecVT is fixed vector, even we later
15201 // create a container for each (fixed vector) operand, we still allocate
15202 // the stack with fixed vector size, rather than container size, as
15203 // fixed vector size is already sufficient.
15204 Align Alignment = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
15205 SDValue StackPtr =
15206 DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
15207 EVT PtrVT = StackPtr.getValueType();
15208 auto &MF = DAG.getMachineFunction();
15209 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
15210 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
15211
15212 static const Intrinsic::ID IntrIds[] = {
15213 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
15214 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
15215 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
15216 Intrinsic::riscv_vsseg8_mask,
15217 };
15218
15219 unsigned Sz = Factor * ContainerVecVT.getVectorMinNumElements() *
15220 ContainerVecVT.getScalarSizeInBits();
15221 EVT VecTupTy = MVT::getRISCVVectorTupleVT(Sz, Factor);
15222
15223 SDValue StoredVal = DAG.getUNDEF(VecTupTy);
15224 for (unsigned i = 0; i < Factor; i++) {
15225 SDValue OpVal = Op.getOperand(i);
15226 if (VecVT.isFixedLengthVector())
15227 OpVal = convertToScalableVector(ContainerVecVT, OpVal, DAG, Subtarget);
15228 StoredVal = DAG.getNode(RISCVISD::TUPLE_INSERT, DL, VecTupTy, StoredVal,
15229 OpVal, DAG.getTargetConstant(i, DL, MVT::i32));
15230 }
15231
15232 SDValue Ops[] = {DAG.getEntryNode(),
15233 DAG.getTargetConstant(IntrIds[Factor - 2], DL, XLenVT),
15234 StoredVal,
15235 StackPtr,
15236 Mask,
15237 VL,
15239 DL, XLenVT)};
15240
15241 SDValue Chain = DAG.getMemIntrinsicNode(
15242 ISD::INTRINSIC_VOID, DL, DAG.getVTList(MVT::Other), Ops,
15243 VecVT.getVectorElementType(), PtrInfo, Alignment,
15245
15246 SmallVector<SDValue, 8> Loads(Factor);
15247
15248 SDValue Increment = DAG.getTypeSize(DL, PtrVT, VecVT.getStoreSize());
15249 for (unsigned i = 0; i != Factor; ++i) {
15250 if (i != 0)
15251 StackPtr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, Increment);
15252
15253 Loads[i] = DAG.getLoad(VecVT, DL, Chain, StackPtr, PtrInfo);
15254 }
15255
15256 return DAG.getMergeValues(Loads, DL);
15257 }
15258
15259 if (Subtarget.hasStdExtZvzip() && !Op.getOperand(0).isUndef() &&
15260 !Op.getOperand(1).isUndef()) {
15261 MVT VT = Op->getSimpleValueType(0);
15262 MVT NewVT = VT.getDoubleNumVectorElementsVT();
15263 if (isLegalVTForZvzipInterleavedOperand(NewVT, Subtarget)) {
15264 // Freeze the sources so we can increase their use count.
15265 SDValue V1 = DAG.getFreeze(Op->getOperand(0));
15266 SDValue V2 = DAG.getFreeze(Op->getOperand(1));
15267 SDValue Interleaved = lowerZvzipVZIP(V1, V2, DL, DAG, Subtarget);
15268 SDValue Lo = DAG.getExtractSubvector(DL, VT, Interleaved, 0);
15269 SDValue Hi = DAG.getExtractSubvector(DL, VT, Interleaved,
15271 return DAG.getMergeValues({Lo, Hi}, DL);
15272 }
15273 }
15274
15275 // If the element type is smaller than ELEN, then we can interleave with
15276 // vwaddu.vv and vwmaccu.vx
15277 if (VecVT.getScalarSizeInBits() < Subtarget.getELen()) {
15278 Interleaved = getWideningInterleave(Op.getOperand(0), Op.getOperand(1), DL,
15279 DAG, Subtarget);
15280 } else {
15281 // Otherwise, fallback to using vrgathere16.vv
15282 MVT ConcatVT = MVT::getVectorVT(VecVT.getVectorElementType(),
15283 VecVT.getVectorElementCount() * 2);
15284 SDValue Concat = DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVT,
15285 Op.getOperand(0), Op.getOperand(1));
15286
15287 MVT IdxVT = ConcatVT.changeVectorElementType(MVT::i16);
15288
15289 // 0 1 2 3 4 5 6 7 ...
15290 SDValue StepVec = DAG.getStepVector(DL, IdxVT);
15291
15292 // 1 1 1 1 1 1 1 1 ...
15293 SDValue Ones = DAG.getSplatVector(IdxVT, DL, DAG.getConstant(1, DL, XLenVT));
15294
15295 // 1 0 1 0 1 0 1 0 ...
15296 SDValue OddMask = DAG.getNode(ISD::AND, DL, IdxVT, StepVec, Ones);
15297 OddMask = DAG.getSetCC(
15298 DL, IdxVT.changeVectorElementType(MVT::i1), OddMask,
15299 DAG.getSplatVector(IdxVT, DL, DAG.getConstant(0, DL, XLenVT)),
15301
15302 SDValue VLMax = DAG.getSplatVector(IdxVT, DL, computeVLMax(VecVT, DL, DAG));
15303
15304 // Build up the index vector for interleaving the concatenated vector
15305 // 0 0 1 1 2 2 3 3 ...
15306 SDValue Idx = DAG.getNode(ISD::SRL, DL, IdxVT, StepVec, Ones);
15307 // 0 n 1 n+1 2 n+2 3 n+3 ...
15308 Idx =
15309 DAG.getNode(RISCVISD::ADD_VL, DL, IdxVT, Idx, VLMax, Idx, OddMask, VL);
15310
15311 // Then perform the interleave
15312 // v[0] v[n] v[1] v[n+1] v[2] v[n+2] v[3] v[n+3] ...
15313 SDValue TrueMask = getAllOnesMask(IdxVT, VL, DL, DAG);
15314 Interleaved = DAG.getNode(RISCVISD::VRGATHEREI16_VV_VL, DL, ConcatVT,
15315 Concat, Idx, DAG.getUNDEF(ConcatVT), TrueMask, VL);
15316 }
15317
15318 // Extract the two halves from the interleaved result
15319 SDValue Lo = DAG.getExtractSubvector(DL, VecVT, Interleaved, 0);
15320 SDValue Hi = DAG.getExtractSubvector(DL, VecVT, Interleaved,
15321 VecVT.getVectorMinNumElements());
15322
15323 return DAG.getMergeValues({Lo, Hi}, DL);
15324}
15325
15326// Lower step_vector to the vid instruction. Any non-identity step value must
15327// be accounted for my manual expansion.
15328SDValue RISCVTargetLowering::lowerSTEP_VECTOR(SDValue Op,
15329 SelectionDAG &DAG) const {
15330 SDLoc DL(Op);
15331 MVT VT = Op.getSimpleValueType();
15332 assert(VT.isScalableVector() && "Expected scalable vector");
15333 MVT XLenVT = Subtarget.getXLenVT();
15334 auto [Mask, VL] = getDefaultScalableVLOps(VT, DL, DAG, Subtarget);
15335 SDValue StepVec = DAG.getNode(RISCVISD::VID_VL, DL, VT, Mask, VL);
15336 uint64_t StepValImm = Op.getConstantOperandVal(0);
15337 if (StepValImm != 1) {
15338 if (isPowerOf2_64(StepValImm)) {
15339 SDValue StepVal =
15340 DAG.getNode(RISCVISD::VMV_V_X_VL, DL, VT, DAG.getUNDEF(VT),
15341 DAG.getConstant(Log2_64(StepValImm), DL, XLenVT), VL);
15342 StepVec = DAG.getNode(ISD::SHL, DL, VT, StepVec, StepVal);
15343 } else {
15344 SDValue StepVal = lowerScalarSplat(
15345 SDValue(), DAG.getConstant(StepValImm, DL, VT.getVectorElementType()),
15346 VL, VT, DL, DAG, Subtarget);
15347 StepVec = DAG.getNode(ISD::MUL, DL, VT, StepVec, StepVal);
15348 }
15349 }
15350 return StepVec;
15351}
15352
15353// Implement vector_reverse using vrgather.vv with indices determined by
15354// subtracting the id of each element from (VLMAX-1). This will convert
15355// the indices like so:
15356// (0, 1,..., VLMAX-2, VLMAX-1) -> (VLMAX-1, VLMAX-2,..., 1, 0).
15357// TODO: This code assumes VLMAX <= 65536 for LMUL=8 SEW=16.
15358SDValue RISCVTargetLowering::lowerVECTOR_REVERSE(SDValue Op,
15359 SelectionDAG &DAG) const {
15360 SDLoc DL(Op);
15361 MVT VecVT = Op.getSimpleValueType();
15362
15363 // Reverse a 64-bit packed vector on RV32 by reversing each 32-bit half and
15364 // swapping them.
15365 if (Subtarget.hasStdExtP() && !Subtarget.hasVInstructions()) {
15366 assert(!Subtarget.is64Bit() && VecVT.getSizeInBits() == 64 &&
15367 "Unexpected packed VECTOR_REVERSE type");
15368 SDValue V = Op.getOperand(0);
15369 if (VecVT == MVT::v2i32) {
15370 // A 2-element reverse is just an element swap.
15371 SDValue Lo = DAG.getExtractVectorElt(DL, MVT::i32, V, 0);
15372 SDValue Hi = DAG.getExtractVectorElt(DL, MVT::i32, V, 1);
15373 return DAG.getBuildVector(VecVT, DL, {Hi, Lo});
15374 }
15375 auto [Lo, Hi] = DAG.SplitVector(V, DL);
15376 Lo = DAG.getNode(ISD::VECTOR_REVERSE, DL, Lo.getSimpleValueType(), Lo);
15377 Hi = DAG.getNode(ISD::VECTOR_REVERSE, DL, Hi.getSimpleValueType(), Hi);
15378 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VecVT, Hi, Lo);
15379 }
15380
15381 if (VecVT.getVectorElementType() == MVT::i1) {
15382 MVT WidenVT = MVT::getVectorVT(MVT::i8, VecVT.getVectorElementCount());
15383 SDValue Op1 = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenVT, Op.getOperand(0));
15384 SDValue Op2 = DAG.getNode(ISD::VECTOR_REVERSE, DL, WidenVT, Op1);
15385 return DAG.getSetCC(DL, VecVT, Op2,
15386 DAG.getConstant(0, DL, Op2.getValueType()), ISD::SETNE);
15387 }
15388
15389 MVT ContainerVT = VecVT;
15390 SDValue Vec = Op.getOperand(0);
15391 if (VecVT.isFixedLengthVector()) {
15392 ContainerVT = getContainerForFixedLengthVector(VecVT);
15393 Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget);
15394 }
15395
15396 MVT XLenVT = Subtarget.getXLenVT();
15397 auto [Mask, VL] = getDefaultVLOps(VecVT, ContainerVT, DL, DAG, Subtarget);
15398
15399 // On some uarchs vrgather.vv will read from every input register for each
15400 // output register, regardless of the indices. However to reverse a vector
15401 // each output register only needs to read from one register. So decompose it
15402 // into LMUL * M1 vrgather.vvs, so we get O(LMUL) performance instead of
15403 // O(LMUL^2).
15404 //
15405 // vsetvli a1, zero, e64, m4, ta, ma
15406 // vrgatherei16.vv v12, v8, v16
15407 // ->
15408 // vsetvli a1, zero, e64, m1, ta, ma
15409 // vrgather.vv v15, v8, v16
15410 // vrgather.vv v14, v9, v16
15411 // vrgather.vv v13, v10, v16
15412 // vrgather.vv v12, v11, v16
15413 if (ContainerVT.bitsGT(RISCVTargetLowering::getM1VT(ContainerVT)) &&
15414 ContainerVT.getVectorElementCount().isKnownMultipleOf(2)) {
15415 auto [Lo, Hi] = DAG.SplitVector(Vec, DL);
15416 Lo = DAG.getNode(ISD::VECTOR_REVERSE, DL, Lo.getValueType(), Lo);
15417 Hi = DAG.getNode(ISD::VECTOR_REVERSE, DL, Hi.getValueType(), Hi);
15418 SDValue Concat = DAG.getNode(ISD::CONCAT_VECTORS, DL, ContainerVT, Hi, Lo);
15419
15420 // Fixed length vectors might not fit exactly into their container, and so
15421 // leave a gap in the front of the vector after being reversed. Slide this
15422 // away.
15423 //
15424 // x x x x 3 2 1 0 <- v4i16 @ vlen=128
15425 // 0 1 2 3 x x x x <- reverse
15426 // x x x x 0 1 2 3 <- vslidedown.vx
15427 if (VecVT.isFixedLengthVector()) {
15428 SDValue Offset = DAG.getNode(
15429 ISD::SUB, DL, XLenVT,
15430 DAG.getElementCount(DL, XLenVT, ContainerVT.getVectorElementCount()),
15431 DAG.getElementCount(DL, XLenVT, VecVT.getVectorElementCount()));
15432 Concat =
15433 getVSlidedown(DAG, Subtarget, DL, ContainerVT,
15434 DAG.getUNDEF(ContainerVT), Concat, Offset, Mask, VL);
15435 Concat = convertFromScalableVector(VecVT, Concat, DAG, Subtarget);
15436 }
15437 return Concat;
15438 }
15439
15440 unsigned EltSize = ContainerVT.getScalarSizeInBits();
15441 unsigned MinSize = ContainerVT.getSizeInBits().getKnownMinValue();
15442 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
15443 unsigned MaxVLMAX =
15444 VecVT.isFixedLengthVector()
15445 ? VecVT.getVectorNumElements()
15446 : RISCVTargetLowering::computeVLMAX(VectorBitsMax, EltSize, MinSize);
15447
15448 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
15449 MVT IntVT = ContainerVT.changeVectorElementTypeToInteger();
15450
15451 // If this is SEW=8 and VLMAX is potentially more than 256, we need
15452 // to use vrgatherei16.vv.
15453 if (MaxVLMAX > 256 && EltSize == 8) {
15454 // If this is LMUL=8, we have to split before can use vrgatherei16.vv.
15455 // Reverse each half, then reassemble them in reverse order.
15456 // NOTE: It's also possible that after splitting that VLMAX no longer
15457 // requires vrgatherei16.vv.
15458 if (MinSize == (8 * RISCV::RVVBitsPerBlock)) {
15459 auto [Lo, Hi] = DAG.SplitVectorOperand(Op.getNode(), 0);
15460 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VecVT);
15461 Lo = DAG.getNode(ISD::VECTOR_REVERSE, DL, LoVT, Lo);
15462 Hi = DAG.getNode(ISD::VECTOR_REVERSE, DL, HiVT, Hi);
15463 // Reassemble the low and high pieces reversed.
15464 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VecVT, Hi, Lo);
15465 }
15466
15467 // Just promote the int type to i16 which will double the LMUL.
15468 IntVT = MVT::getVectorVT(MVT::i16, ContainerVT.getVectorElementCount());
15469 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
15470 }
15471
15472 // At LMUL > 1, do the index computation in 16 bits to reduce register
15473 // pressure.
15474 if (IntVT.getScalarType().bitsGT(MVT::i16) &&
15475 IntVT.bitsGT(RISCVTargetLowering::getM1VT(IntVT))) {
15476 assert(isUInt<16>(MaxVLMAX - 1)); // Largest VLMAX is 65536 @ zvl65536b
15477 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
15478 IntVT = IntVT.changeVectorElementType(MVT::i16);
15479 }
15480
15481 // Calculate VLMAX-1 for the desired SEW.
15482 SDValue VLMinus1 = DAG.getNode(
15483 ISD::SUB, DL, XLenVT,
15484 DAG.getElementCount(DL, XLenVT, VecVT.getVectorElementCount()),
15485 DAG.getConstant(1, DL, XLenVT));
15486
15487 // Splat VLMAX-1 taking care to handle SEW==64 on RV32.
15488 bool IsRV32E64 =
15489 !Subtarget.is64Bit() && IntVT.getVectorElementType() == MVT::i64;
15490 SDValue SplatVL;
15491 if (!IsRV32E64)
15492 SplatVL = DAG.getSplatVector(IntVT, DL, VLMinus1);
15493 else
15494 SplatVL = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, IntVT, DAG.getUNDEF(IntVT),
15495 VLMinus1, DAG.getRegister(RISCV::X0, XLenVT));
15496
15497 SDValue VID = DAG.getNode(RISCVISD::VID_VL, DL, IntVT, Mask, VL);
15498 SDValue Indices = DAG.getNode(RISCVISD::SUB_VL, DL, IntVT, SplatVL, VID,
15499 DAG.getUNDEF(IntVT), Mask, VL);
15500
15501 SDValue Gather = DAG.getNode(GatherOpc, DL, ContainerVT, Vec, Indices,
15502 DAG.getUNDEF(ContainerVT), Mask, VL);
15503 if (VecVT.isFixedLengthVector())
15504 Gather = convertFromScalableVector(VecVT, Gather, DAG, Subtarget);
15505 return Gather;
15506}
15507
15508SDValue RISCVTargetLowering::lowerVECTOR_SPLICE(SDValue Op,
15509 SelectionDAG &DAG) const {
15510 SDLoc DL(Op);
15511 SDValue V1 = Op.getOperand(0);
15512 SDValue V2 = Op.getOperand(1);
15513 SDValue Offset = Op.getOperand(2);
15514 MVT XLenVT = Subtarget.getXLenVT();
15515 MVT VecVT = Op.getSimpleValueType();
15516
15517 SDValue VLMax = computeVLMax(VecVT, DL, DAG);
15518
15519 SDValue DownOffset, UpOffset;
15520 if (Op.getOpcode() == ISD::VECTOR_SPLICE_LEFT) {
15521 // The operand is a TargetConstant, we need to rebuild it as a regular
15522 // constant.
15523 DownOffset = Offset;
15524 UpOffset = DAG.getNode(ISD::SUB, DL, XLenVT, VLMax, Offset);
15525 } else {
15526 // The operand is a TargetConstant, we need to rebuild it as a regular
15527 // constant rather than negating the original operand.
15528 UpOffset = Offset;
15529 DownOffset = DAG.getNode(ISD::SUB, DL, XLenVT, VLMax, Offset);
15530 }
15531
15532 SDValue TrueMask = getAllOnesMask(VecVT, VLMax, DL, DAG);
15533
15534 SDValue SlideDown = getVSlidedown(
15535 DAG, Subtarget, DL, VecVT, DAG.getUNDEF(VecVT), V1, DownOffset, TrueMask,
15536 Subtarget.hasVLDependentLatency() ? UpOffset
15537 : DAG.getRegister(RISCV::X0, XLenVT));
15538 return getVSlideup(DAG, Subtarget, DL, VecVT, SlideDown, V2, UpOffset,
15539 TrueMask, DAG.getRegister(RISCV::X0, XLenVT),
15541}
15542
15543SDValue
15544RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(SDValue Op,
15545 SelectionDAG &DAG) const {
15546 SDLoc DL(Op);
15547 auto *Load = cast<LoadSDNode>(Op);
15548
15550 Load->getMemoryVT(),
15551 *Load->getMemOperand()) &&
15552 "Expecting a correctly-aligned load");
15553
15554 MVT VT = Op.getSimpleValueType();
15555 MVT XLenVT = Subtarget.getXLenVT();
15556 MVT ContainerVT = getContainerForFixedLengthVector(VT);
15557
15558 // If we know the exact VLEN and our fixed length vector completely fills
15559 // the container, use a whole register load instead.
15560 const auto [MinVLMAX, MaxVLMAX] =
15561 RISCVTargetLowering::computeVLMAXBounds(ContainerVT, Subtarget);
15562 if (MinVLMAX == MaxVLMAX && MinVLMAX == VT.getVectorNumElements() &&
15563 RISCVTargetLowering::getM1VT(ContainerVT).bitsLE(ContainerVT)) {
15564 MachineMemOperand *MMO = Load->getMemOperand();
15565 SDValue NewLoad =
15566 DAG.getLoad(ContainerVT, DL, Load->getChain(), Load->getBasePtr(),
15567 MMO->getPointerInfo(), MMO->getBaseAlign(), MMO->getFlags(),
15568 MMOMetadata(MMO->getAAInfo(), MMO->getRanges()));
15569 SDValue Result = convertFromScalableVector(VT, NewLoad, DAG, Subtarget);
15570 return DAG.getMergeValues({Result, NewLoad.getValue(1)}, DL);
15571 }
15572
15573 SDValue VL = DAG.getConstant(VT.getVectorNumElements(), DL, XLenVT);
15574
15575 bool IsMaskOp = VT.getVectorElementType() == MVT::i1;
15576 SDValue IntID = DAG.getTargetConstant(
15577 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle, DL, XLenVT);
15578 SmallVector<SDValue, 4> Ops{Load->getChain(), IntID};
15579 if (!IsMaskOp)
15580 Ops.push_back(DAG.getUNDEF(ContainerVT));
15581 Ops.push_back(Load->getBasePtr());
15582 Ops.push_back(VL);
15583 SDVTList VTs = DAG.getVTList({ContainerVT, MVT::Other});
15584 SDValue NewLoad =
15586 Load->getMemoryVT(), Load->getMemOperand());
15587
15588 SDValue Result = convertFromScalableVector(VT, NewLoad, DAG, Subtarget);
15589 return DAG.getMergeValues({Result, NewLoad.getValue(1)}, DL);
15590}
15591
15592SDValue
15593RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(SDValue Op,
15594 SelectionDAG &DAG) const {
15595 SDLoc DL(Op);
15596 auto *Store = cast<StoreSDNode>(Op);
15597
15599 Store->getMemoryVT(),
15600 *Store->getMemOperand()) &&
15601 "Expecting a correctly-aligned store");
15602
15603 SDValue StoreVal = Store->getValue();
15604 MVT VT = StoreVal.getSimpleValueType();
15605 MVT XLenVT = Subtarget.getXLenVT();
15606
15607 // If the size less than a byte, we need to pad with zeros to make a byte.
15608 if (VT.getVectorElementType() == MVT::i1 && VT.getVectorNumElements() < 8) {
15609 VT = MVT::v8i1;
15610 StoreVal =
15611 DAG.getInsertSubvector(DL, DAG.getConstant(0, DL, VT), StoreVal, 0);
15612 }
15613
15614 MVT ContainerVT = getContainerForFixedLengthVector(VT);
15615
15616 SDValue NewValue =
15617 convertToScalableVector(ContainerVT, StoreVal, DAG, Subtarget);
15618
15619 // If we know the exact VLEN and our fixed length vector completely fills
15620 // the container, use a whole register store instead.
15621 const auto [MinVLMAX, MaxVLMAX] =
15622 RISCVTargetLowering::computeVLMAXBounds(ContainerVT, Subtarget);
15623 if (MinVLMAX == MaxVLMAX && MinVLMAX == VT.getVectorNumElements() &&
15624 RISCVTargetLowering::getM1VT(ContainerVT).bitsLE(ContainerVT)) {
15625 MachineMemOperand *MMO = Store->getMemOperand();
15626 return DAG.getStore(Store->getChain(), DL, NewValue, Store->getBasePtr(),
15627 MMO->getPointerInfo(), MMO->getBaseAlign(),
15628 MMO->getFlags(), MMO->getAAInfo());
15629 }
15630
15631 SDValue VL = DAG.getConstant(VT.getVectorNumElements(), DL, XLenVT);
15632
15633 bool IsMaskOp = VT.getVectorElementType() == MVT::i1;
15634 SDValue IntID = DAG.getTargetConstant(
15635 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse, DL, XLenVT);
15636 return DAG.getMemIntrinsicNode(
15637 ISD::INTRINSIC_VOID, DL, DAG.getVTList(MVT::Other),
15638 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
15639 Store->getMemoryVT(), Store->getMemOperand());
15640}
15641
15642SDValue RISCVTargetLowering::lowerMaskedLoad(SDValue Op,
15643 SelectionDAG &DAG) const {
15644 SDLoc DL(Op);
15645 MVT VT = Op.getSimpleValueType();
15646
15647 const auto *MemSD = cast<MemSDNode>(Op);
15648 EVT MemVT = MemSD->getMemoryVT();
15649 MachineMemOperand *MMO = MemSD->getMemOperand();
15650 SDValue Chain = MemSD->getChain();
15651 SDValue BasePtr = MemSD->getBasePtr();
15652
15653 SDValue Mask, PassThru, VL;
15654 bool IsExpandingLoad = false;
15655 if (const auto *VPLoad = dyn_cast<VPLoadSDNode>(Op)) {
15656 Mask = VPLoad->getMask();
15657 PassThru = DAG.getUNDEF(VT);
15658 VL = VPLoad->getVectorLength();
15659 } else {
15660 const auto *MLoad = cast<MaskedLoadSDNode>(Op);
15661 Mask = MLoad->getMask();
15662 PassThru = MLoad->getPassThru();
15663 IsExpandingLoad = MLoad->isExpandingLoad();
15664 }
15665
15666 bool IsUnmasked = ISD::isConstantSplatVectorAllOnes(Mask.getNode());
15667
15668 MVT XLenVT = Subtarget.getXLenVT();
15669
15670 MVT ContainerVT = VT;
15671 if (VT.isFixedLengthVector()) {
15672 ContainerVT = getContainerForFixedLengthVector(VT);
15673 PassThru = convertToScalableVector(ContainerVT, PassThru, DAG, Subtarget);
15674 if (!IsUnmasked) {
15675 MVT MaskVT = getMaskTypeFor(ContainerVT);
15676 Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
15677 }
15678 }
15679
15680 if (!VL)
15681 VL = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).second;
15682
15683 SDValue ExpandingVL;
15684 if (!IsUnmasked && IsExpandingLoad) {
15685 ExpandingVL = VL;
15686 VL =
15687 DAG.getNode(RISCVISD::VCPOP_VL, DL, XLenVT, Mask,
15688 getAllOnesMask(Mask.getSimpleValueType(), VL, DL, DAG), VL);
15689 }
15690
15691 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
15692 : Intrinsic::riscv_vle_mask;
15693 SmallVector<SDValue, 8> Ops{Chain, DAG.getTargetConstant(IntID, DL, XLenVT)};
15694 if (IntID == Intrinsic::riscv_vle)
15695 Ops.push_back(DAG.getUNDEF(ContainerVT));
15696 else
15697 Ops.push_back(PassThru);
15698 Ops.push_back(BasePtr);
15699 if (IntID == Intrinsic::riscv_vle_mask)
15700 Ops.push_back(Mask);
15701 Ops.push_back(VL);
15702 if (IntID == Intrinsic::riscv_vle_mask)
15703 Ops.push_back(DAG.getTargetConstant(RISCVVType::TAIL_AGNOSTIC, DL, XLenVT));
15704
15705 SDVTList VTs = DAG.getVTList({ContainerVT, MVT::Other});
15706
15707 SDValue Result =
15708 DAG.getMemIntrinsicNode(ISD::INTRINSIC_W_CHAIN, DL, VTs, Ops, MemVT, MMO);
15709 Chain = Result.getValue(1);
15710 if (ExpandingVL) {
15711 MVT IndexVT = ContainerVT;
15712 if (ContainerVT.isFloatingPoint())
15713 IndexVT = ContainerVT.changeVectorElementTypeToInteger();
15714
15715 MVT IndexEltVT = IndexVT.getVectorElementType();
15716 bool UseVRGATHEREI16 = false;
15717 // If index vector is an i8 vector and the element count exceeds 256, we
15718 // should change the element type of index vector to i16 to avoid
15719 // overflow.
15720 uint64_t MaxEltCount = VT.getVectorMinNumElements();
15721 if (VT.isScalableVector())
15722 MaxEltCount *= Subtarget.getRealMaxVLen() / RISCV::RVVBitsPerBlock;
15723 if (IndexEltVT == MVT::i8 && MaxEltCount > 256) {
15724 // FIXME: We need to do vector splitting manually for LMUL=8 cases.
15725 assert(getLMUL(IndexVT) != RISCVVType::LMUL_8);
15726 IndexVT = IndexVT.changeVectorElementType(MVT::i16);
15727 UseVRGATHEREI16 = true;
15728 }
15729
15730 SDValue Iota =
15731 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, IndexVT,
15732 DAG.getTargetConstant(Intrinsic::riscv_viota, DL, XLenVT),
15733 DAG.getUNDEF(IndexVT), Mask, ExpandingVL);
15734 Result =
15735 DAG.getNode(UseVRGATHEREI16 ? RISCVISD::VRGATHEREI16_VV_VL
15736 : RISCVISD::VRGATHER_VV_VL,
15737 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
15738 }
15739
15740 if (VT.isFixedLengthVector())
15741 Result = convertFromScalableVector(VT, Result, DAG, Subtarget);
15742
15743 return DAG.getMergeValues({Result, Chain}, DL);
15744}
15745
15746SDValue RISCVTargetLowering::lowerLoadFF(SDValue Op, SelectionDAG &DAG) const {
15747 SDLoc DL(Op);
15748 MVT VT = Op->getSimpleValueType(0);
15749
15750 const auto *VPLoadFF = cast<VPLoadFFSDNode>(Op);
15751 EVT MemVT = VPLoadFF->getMemoryVT();
15752 MachineMemOperand *MMO = VPLoadFF->getMemOperand();
15753 SDValue Chain = VPLoadFF->getChain();
15754 SDValue BasePtr = VPLoadFF->getBasePtr();
15755
15756 SDValue Mask = VPLoadFF->getMask();
15757 SDValue VL = VPLoadFF->getVectorLength();
15758
15759 MVT XLenVT = Subtarget.getXLenVT();
15760
15761 MVT ContainerVT = VT;
15762 if (VT.isFixedLengthVector()) {
15763 ContainerVT = getContainerForFixedLengthVector(VT);
15764 MVT MaskVT = getMaskTypeFor(ContainerVT);
15765 Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
15766 }
15767
15768 unsigned IntID = Intrinsic::riscv_vleff_mask;
15769 SDValue Ops[] = {
15770 Chain,
15771 DAG.getTargetConstant(IntID, DL, XLenVT),
15772 DAG.getUNDEF(ContainerVT),
15773 BasePtr,
15774 Mask,
15775 VL,
15777
15778 SDVTList VTs = DAG.getVTList({ContainerVT, Op->getValueType(1), MVT::Other});
15779
15780 SDValue Result =
15781 DAG.getMemIntrinsicNode(ISD::INTRINSIC_W_CHAIN, DL, VTs, Ops, MemVT, MMO);
15782 SDValue OutVL = Result.getValue(1);
15783 Chain = Result.getValue(2);
15784
15785 if (VT.isFixedLengthVector())
15786 Result = convertFromScalableVector(VT, Result, DAG, Subtarget);
15787
15788 return DAG.getMergeValues({Result, OutVL, Chain}, DL);
15789}
15790
15791SDValue RISCVTargetLowering::lowerMaskedStore(SDValue Op,
15792 SelectionDAG &DAG) const {
15793 SDLoc DL(Op);
15794
15795 const auto *MemSD = cast<MemSDNode>(Op);
15796 EVT MemVT = MemSD->getMemoryVT();
15797 MachineMemOperand *MMO = MemSD->getMemOperand();
15798 SDValue Chain = MemSD->getChain();
15799 SDValue BasePtr = MemSD->getBasePtr();
15800 SDValue Val, Mask, VL;
15801
15802 bool IsCompressingStore = false;
15803 if (const auto *VPStore = dyn_cast<VPStoreSDNode>(Op)) {
15804 Val = VPStore->getValue();
15805 Mask = VPStore->getMask();
15806 VL = VPStore->getVectorLength();
15807 } else {
15808 const auto *MStore = cast<MaskedStoreSDNode>(Op);
15809 Val = MStore->getValue();
15810 Mask = MStore->getMask();
15811 IsCompressingStore = MStore->isCompressingStore();
15812 }
15813
15814 bool IsUnmasked =
15815 ISD::isConstantSplatVectorAllOnes(Mask.getNode()) || IsCompressingStore;
15816
15817 MVT VT = Val.getSimpleValueType();
15818 MVT XLenVT = Subtarget.getXLenVT();
15819
15820 MVT ContainerVT = VT;
15821 if (VT.isFixedLengthVector()) {
15822 ContainerVT = getContainerForFixedLengthVector(VT);
15823
15824 Val = convertToScalableVector(ContainerVT, Val, DAG, Subtarget);
15825 if (!IsUnmasked || IsCompressingStore) {
15826 MVT MaskVT = getMaskTypeFor(ContainerVT);
15827 Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
15828 }
15829 }
15830
15831 if (!VL)
15832 VL = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).second;
15833
15834 if (IsCompressingStore) {
15835 Val = DAG.getNode(
15836 ISD::INTRINSIC_WO_CHAIN, DL, ContainerVT,
15837 DAG.getTargetConstant(Intrinsic::riscv_vcompress, DL, XLenVT),
15838 DAG.getUNDEF(ContainerVT), Val, Mask, VL);
15839 VL =
15840 DAG.getNode(RISCVISD::VCPOP_VL, DL, XLenVT, Mask,
15841 getAllOnesMask(Mask.getSimpleValueType(), VL, DL, DAG), VL);
15842 }
15843
15844 unsigned IntID =
15845 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
15846 SmallVector<SDValue, 8> Ops{Chain, DAG.getTargetConstant(IntID, DL, XLenVT)};
15847 Ops.push_back(Val);
15848 Ops.push_back(BasePtr);
15849 if (!IsUnmasked)
15850 Ops.push_back(Mask);
15851 Ops.push_back(VL);
15852
15854 DAG.getVTList(MVT::Other), Ops, MemVT, MMO);
15855}
15856
15857SDValue RISCVTargetLowering::lowerVectorCompress(SDValue Op,
15858 SelectionDAG &DAG) const {
15859 SDLoc DL(Op);
15860 SDValue Val = Op.getOperand(0);
15861 SDValue Mask = Op.getOperand(1);
15862 SDValue Passthru = Op.getOperand(2);
15863
15864 MVT VT = Val.getSimpleValueType();
15865 MVT XLenVT = Subtarget.getXLenVT();
15866 MVT ContainerVT = VT;
15867 if (VT.isFixedLengthVector()) {
15868 ContainerVT = getContainerForFixedLengthVector(VT);
15869 MVT MaskVT = getMaskTypeFor(ContainerVT);
15870 Val = convertToScalableVector(ContainerVT, Val, DAG, Subtarget);
15871 Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
15872 Passthru = convertToScalableVector(ContainerVT, Passthru, DAG, Subtarget);
15873 }
15874
15875 SDValue VL = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).second;
15876 SDValue Res =
15877 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, ContainerVT,
15878 DAG.getTargetConstant(Intrinsic::riscv_vcompress, DL, XLenVT),
15879 Passthru, Val, Mask, VL);
15880
15881 if (VT.isFixedLengthVector())
15882 Res = convertFromScalableVector(VT, Res, DAG, Subtarget);
15883
15884 return Res;
15885}
15886
15887SDValue RISCVTargetLowering::lowerVectorStrictFSetcc(SDValue Op,
15888 SelectionDAG &DAG) const {
15889 unsigned Opc = Op.getOpcode();
15890 SDLoc DL(Op);
15891 SDValue Chain = Op.getOperand(0);
15892 SDValue Op1 = Op.getOperand(1);
15893 SDValue Op2 = Op.getOperand(2);
15894 SDValue CC = Op.getOperand(3);
15895 ISD::CondCode CCVal = cast<CondCodeSDNode>(CC)->get();
15896 MVT VT = Op.getSimpleValueType();
15897 MVT InVT = Op1.getSimpleValueType();
15898
15899 // RVV VMFEQ/VMFNE ignores qNan, so we expand strict_fsetccs with OEQ/UNE
15900 // condition code.
15901 if (Opc == ISD::STRICT_FSETCCS) {
15902 // Expand strict_fsetccs(x, oeq) to
15903 // (and strict_fsetccs(x, y, oge), strict_fsetccs(x, y, ole))
15904 SDVTList VTList = Op->getVTList();
15905 if (CCVal == ISD::SETEQ || CCVal == ISD::SETOEQ) {
15906 SDValue OLECCVal = DAG.getCondCode(ISD::SETOLE);
15907 SDValue Tmp1 = DAG.getNode(ISD::STRICT_FSETCCS, DL, VTList, Chain, Op1,
15908 Op2, OLECCVal);
15909 SDValue Tmp2 = DAG.getNode(ISD::STRICT_FSETCCS, DL, VTList, Chain, Op2,
15910 Op1, OLECCVal);
15911 SDValue OutChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
15912 Tmp1.getValue(1), Tmp2.getValue(1));
15913 // Tmp1 and Tmp2 might be the same node.
15914 if (Tmp1 != Tmp2)
15915 Tmp1 = DAG.getNode(ISD::AND, DL, VT, Tmp1, Tmp2);
15916 return DAG.getMergeValues({Tmp1, OutChain}, DL);
15917 }
15918
15919 // Expand (strict_fsetccs x, y, une) to (not (strict_fsetccs x, y, oeq))
15920 if (CCVal == ISD::SETNE || CCVal == ISD::SETUNE) {
15921 SDValue OEQCCVal = DAG.getCondCode(ISD::SETOEQ);
15922 SDValue OEQ = DAG.getNode(ISD::STRICT_FSETCCS, DL, VTList, Chain, Op1,
15923 Op2, OEQCCVal);
15924 SDValue Res = DAG.getNOT(DL, OEQ, VT);
15925 return DAG.getMergeValues({Res, OEQ.getValue(1)}, DL);
15926 }
15927 }
15928
15929 MVT ContainerInVT = InVT;
15930 if (InVT.isFixedLengthVector()) {
15931 ContainerInVT = getContainerForFixedLengthVector(InVT);
15932 Op1 = convertToScalableVector(ContainerInVT, Op1, DAG, Subtarget);
15933 Op2 = convertToScalableVector(ContainerInVT, Op2, DAG, Subtarget);
15934 }
15935 MVT MaskVT = getMaskTypeFor(ContainerInVT);
15936
15937 auto [Mask, VL] = getDefaultVLOps(InVT, ContainerInVT, DL, DAG, Subtarget);
15938
15939 SDValue Res;
15940 if (Opc == ISD::STRICT_FSETCC &&
15941 (CCVal == ISD::SETLT || CCVal == ISD::SETOLT || CCVal == ISD::SETLE ||
15942 CCVal == ISD::SETOLE)) {
15943 // VMFLT/VMFLE/VMFGT/VMFGE raise exception for qNan. Generate a mask to only
15944 // active when both input elements are ordered.
15945 SDValue True = getAllOnesMask(ContainerInVT, VL, DL, DAG);
15946 SDValue OrderMask1 = DAG.getNode(
15947 RISCVISD::STRICT_FSETCC_VL, DL, DAG.getVTList(MaskVT, MVT::Other),
15948 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
15949 True, VL});
15950 SDValue OrderMask2 = DAG.getNode(
15951 RISCVISD::STRICT_FSETCC_VL, DL, DAG.getVTList(MaskVT, MVT::Other),
15952 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
15953 True, VL});
15954 Mask =
15955 DAG.getNode(RISCVISD::VMAND_VL, DL, MaskVT, OrderMask1, OrderMask2, VL);
15956 // Use Mask as the passthru operand to let the result be 0 if either of the
15957 // inputs is unordered.
15958 Res = DAG.getNode(RISCVISD::STRICT_FSETCCS_VL, DL,
15959 DAG.getVTList(MaskVT, MVT::Other),
15960 {Chain, Op1, Op2, CC, Mask, Mask, VL});
15961 } else {
15962 unsigned RVVOpc = Opc == ISD::STRICT_FSETCC ? RISCVISD::STRICT_FSETCC_VL
15963 : RISCVISD::STRICT_FSETCCS_VL;
15964 Res = DAG.getNode(RVVOpc, DL, DAG.getVTList(MaskVT, MVT::Other),
15965 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
15966 }
15967
15968 if (VT.isFixedLengthVector()) {
15969 SDValue SubVec = convertFromScalableVector(VT, Res, DAG, Subtarget);
15970 return DAG.getMergeValues({SubVec, Res.getValue(1)}, DL);
15971 }
15972 return Res;
15973}
15974
15975// Lower vector ABS to smax(X, sub(0, X)).
15976SDValue RISCVTargetLowering::lowerABS(SDValue Op, SelectionDAG &DAG) const {
15977 SDLoc DL(Op);
15978 MVT VT = Op.getSimpleValueType();
15979 SDValue X = Op.getOperand(0);
15980
15981 assert(VT.isFixedLengthVector() && "Unexpected type for ISD::ABS");
15982
15983 MVT ContainerVT = getContainerForFixedLengthVector(VT);
15984 X = convertToScalableVector(ContainerVT, X, DAG, Subtarget);
15985
15986 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
15987
15988 SDValue SplatZero = DAG.getNode(
15989 RISCVISD::VMV_V_X_VL, DL, ContainerVT, DAG.getUNDEF(ContainerVT),
15990 DAG.getConstant(0, DL, Subtarget.getXLenVT()), VL);
15991 SDValue Result;
15992 if (Subtarget.hasStdExtZvabd()) {
15993 Result = DAG.getNode(RISCVISD::ABDS_VL, DL, ContainerVT, X, SplatZero,
15994 DAG.getUNDEF(ContainerVT), Mask, VL);
15995 } else {
15996 SDValue NegX = DAG.getNode(RISCVISD::SUB_VL, DL, ContainerVT, SplatZero, X,
15997 DAG.getUNDEF(ContainerVT), Mask, VL);
15998 Result = DAG.getNode(RISCVISD::SMAX_VL, DL, ContainerVT, X, NegX,
15999 DAG.getUNDEF(ContainerVT), Mask, VL);
16000 }
16001 return convertFromScalableVector(VT, Result, DAG, Subtarget);
16002}
16003
16004SDValue RISCVTargetLowering::lowerToScalableOp(SDValue Op,
16005 SelectionDAG &DAG) const {
16006 const auto &TSInfo =
16007 static_cast<const RISCVSelectionDAGInfo &>(DAG.getSelectionDAGInfo());
16008
16009 unsigned NewOpc = getRISCVVLOp(Op);
16010 bool HasPassthruOp = TSInfo.hasPassthruOp(NewOpc);
16011 bool HasMask = TSInfo.hasMaskOp(NewOpc);
16012
16013 MVT VT = Op.getSimpleValueType();
16014 MVT ContainerVT = getContainerForFixedLengthVector(VT);
16015
16016 // Create list of operands by converting existing ones to scalable types.
16018 for (const SDValue &V : Op->op_values()) {
16019 assert(!isa<VTSDNode>(V) && "Unexpected VTSDNode node!");
16020
16021 // Pass through non-vector operands.
16022 if (!V.getValueType().isVector()) {
16023 Ops.push_back(V);
16024 continue;
16025 }
16026
16027 // "cast" fixed length vector to a scalable vector.
16028 assert(useRVVForFixedLengthVectorVT(V.getSimpleValueType()) &&
16029 "Only fixed length vectors are supported!");
16030 MVT VContainerVT = ContainerVT.changeVectorElementType(
16031 V.getSimpleValueType().getVectorElementType());
16032 Ops.push_back(convertToScalableVector(VContainerVT, V, DAG, Subtarget));
16033 }
16034
16035 SDLoc DL(Op);
16036 auto [Mask, VL] = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
16037 if (HasPassthruOp)
16038 Ops.push_back(DAG.getUNDEF(ContainerVT));
16039 if (HasMask)
16040 Ops.push_back(Mask);
16041 Ops.push_back(VL);
16042
16043 // StrictFP operations have two result values. Their lowered result should
16044 // have same result count.
16045 if (Op->isStrictFPOpcode()) {
16046 SDValue ScalableRes =
16047 DAG.getNode(NewOpc, DL, DAG.getVTList(ContainerVT, MVT::Other), Ops,
16048 Op->getFlags());
16049 SDValue SubVec = convertFromScalableVector(VT, ScalableRes, DAG, Subtarget);
16050 return DAG.getMergeValues({SubVec, ScalableRes.getValue(1)}, DL);
16051 }
16052
16053 SDValue ScalableRes =
16054 DAG.getNode(NewOpc, DL, ContainerVT, Ops, Op->getFlags());
16055 return convertFromScalableVector(VT, ScalableRes, DAG, Subtarget);
16056}
16057
16058// Lower a VP_* ISD node to the corresponding RISCVISD::*_VL node:
16059// * Operands of each node are assumed to be in the same order.
16060// * The EVL operand is promoted from i32 to i64 on RV64.
16061// * Fixed-length vectors are converted to their scalable-vector container
16062// types.
16063SDValue RISCVTargetLowering::lowerVPOp(SDValue Op, SelectionDAG &DAG) const {
16064 const auto &TSInfo =
16065 static_cast<const RISCVSelectionDAGInfo &>(DAG.getSelectionDAGInfo());
16066
16067 unsigned RISCVISDOpc = getRISCVVLOp(Op);
16068 bool HasPassthruOp = TSInfo.hasPassthruOp(RISCVISDOpc);
16069
16070 SDLoc DL(Op);
16071 MVT VT = Op.getSimpleValueType();
16073
16074 MVT ContainerVT = VT;
16075 if (VT.isFixedLengthVector())
16076 ContainerVT = getContainerForFixedLengthVector(VT);
16077
16078 for (const auto &OpIdx : enumerate(Op->ops())) {
16079 SDValue V = OpIdx.value();
16080 assert(!isa<VTSDNode>(V) && "Unexpected VTSDNode node!");
16081 // Add dummy passthru value before the mask. Or if there isn't a mask,
16082 // before EVL.
16083 if (HasPassthruOp) {
16084 auto MaskIdx = ISD::getVPMaskIdx(Op.getOpcode());
16085 if (MaskIdx) {
16086 if (*MaskIdx == OpIdx.index())
16087 Ops.push_back(DAG.getUNDEF(ContainerVT));
16088 } else if (ISD::getVPExplicitVectorLengthIdx(Op.getOpcode()) ==
16089 OpIdx.index()) {
16090 assert(Op.getOpcode() == ISD::VP_MERGE);
16091 // For VP_MERGE, copy the false operand instead of an undef value.
16092 Ops.push_back(Ops.back());
16093 }
16094 }
16095 // VFCVT_RM_X_F_VL requires a rounding mode to be injected before the VL.
16096 if (RISCVISDOpc == RISCVISD::VFCVT_RM_X_F_VL &&
16097 ISD::getVPExplicitVectorLengthIdx(Op.getOpcode()) == OpIdx.index())
16099 Subtarget.getXLenVT()));
16100 // Pass through operands which aren't fixed-length vectors.
16101 if (!V.getValueType().isFixedLengthVector()) {
16102 Ops.push_back(V);
16103 continue;
16104 }
16105 // "cast" fixed length vector to a scalable vector.
16106 MVT OpVT = V.getSimpleValueType();
16107 MVT ContainerVT = getContainerForFixedLengthVector(OpVT);
16108 assert(useRVVForFixedLengthVectorVT(OpVT) &&
16109 "Only fixed length vectors are supported!");
16110 Ops.push_back(convertToScalableVector(ContainerVT, V, DAG, Subtarget));
16111 }
16112
16113 if (!VT.isFixedLengthVector())
16114 return DAG.getNode(RISCVISDOpc, DL, VT, Ops, Op->getFlags());
16115
16116 SDValue VPOp = DAG.getNode(RISCVISDOpc, DL, ContainerVT, Ops, Op->getFlags());
16117
16118 return convertFromScalableVector(VT, VPOp, DAG, Subtarget);
16119}
16120
16121SDValue RISCVTargetLowering::lowerVPMergeMask(SDValue Op,
16122 SelectionDAG &DAG) const {
16123 SDLoc DL(Op);
16124 MVT VT = Op.getSimpleValueType();
16125 MVT XLenVT = Subtarget.getXLenVT();
16126
16127 SDValue Mask = Op.getOperand(0);
16128 SDValue TrueVal = Op.getOperand(1);
16129 SDValue FalseVal = Op.getOperand(2);
16130 SDValue VL = Op.getOperand(3);
16131
16132 // Use default legalization if a vector of EVL type would be legal.
16133 EVT EVLVecVT = EVT::getVectorVT(*DAG.getContext(), VL.getValueType(),
16135 if (isTypeLegal(EVLVecVT))
16136 return SDValue();
16137
16138 MVT ContainerVT = VT;
16139 if (VT.isFixedLengthVector()) {
16140 ContainerVT = getContainerForFixedLengthVector(VT);
16141 Mask = convertToScalableVector(ContainerVT, Mask, DAG, Subtarget);
16142 TrueVal = convertToScalableVector(ContainerVT, TrueVal, DAG, Subtarget);
16143 FalseVal = convertToScalableVector(ContainerVT, FalseVal, DAG, Subtarget);
16144 }
16145
16146 // Promote to a vector of i8.
16147 MVT PromotedVT = ContainerVT.changeVectorElementType(MVT::i8);
16148
16149 // Promote TrueVal and FalseVal using VLMax.
16150 // FIXME: Is there a better way to do this?
16151 SDValue VLMax = DAG.getRegister(RISCV::X0, XLenVT);
16152 SDValue SplatOne = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, PromotedVT,
16153 DAG.getUNDEF(PromotedVT),
16154 DAG.getConstant(1, DL, XLenVT), VLMax);
16155 SDValue SplatZero = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, PromotedVT,
16156 DAG.getUNDEF(PromotedVT),
16157 DAG.getConstant(0, DL, XLenVT), VLMax);
16158 TrueVal = DAG.getNode(RISCVISD::VMERGE_VL, DL, PromotedVT, TrueVal, SplatOne,
16159 SplatZero, DAG.getUNDEF(PromotedVT), VL);
16160 // Any element past VL uses FalseVal, so use VLMax
16161 FalseVal = DAG.getNode(RISCVISD::VMERGE_VL, DL, PromotedVT, FalseVal,
16162 SplatOne, SplatZero, DAG.getUNDEF(PromotedVT), VLMax);
16163
16164 // VP_MERGE the two promoted values.
16165 SDValue VPMerge = DAG.getNode(RISCVISD::VMERGE_VL, DL, PromotedVT, Mask,
16166 TrueVal, FalseVal, FalseVal, VL);
16167
16168 // Convert back to mask.
16169 SDValue TrueMask = DAG.getNode(RISCVISD::VMSET_VL, DL, ContainerVT, VL);
16170 SDValue Result = DAG.getNode(
16171 RISCVISD::SETCC_VL, DL, ContainerVT,
16172 {VPMerge, DAG.getConstant(0, DL, PromotedVT), DAG.getCondCode(ISD::SETNE),
16173 DAG.getUNDEF(getMaskTypeFor(ContainerVT)), TrueMask, VLMax});
16174
16175 if (VT.isFixedLengthVector())
16176 Result = convertFromScalableVector(VT, Result, DAG, Subtarget);
16177 return Result;
16178}
16179
16180SDValue
16181RISCVTargetLowering::lowerVPSpliceExperimental(SDValue Op,
16182 SelectionDAG &DAG) const {
16183 using namespace SDPatternMatch;
16184
16185 SDLoc DL(Op);
16186
16187 SDValue Op1 = Op.getOperand(0);
16188 SDValue Op2 = Op.getOperand(1);
16189 SDValue Offset = Op.getOperand(2);
16190 SDValue Mask = Op.getOperand(3);
16191 SDValue EVL1 = Op.getOperand(4);
16192 SDValue EVL2 = Op.getOperand(5);
16193
16194 const MVT XLenVT = Subtarget.getXLenVT();
16195 MVT VT = Op.getSimpleValueType();
16196 MVT ContainerVT = VT;
16197 if (VT.isFixedLengthVector()) {
16198 ContainerVT = getContainerForFixedLengthVector(VT);
16199 Op1 = convertToScalableVector(ContainerVT, Op1, DAG, Subtarget);
16200 Op2 = convertToScalableVector(ContainerVT, Op2, DAG, Subtarget);
16201 MVT MaskVT = getMaskTypeFor(ContainerVT);
16202 Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
16203 }
16204
16205 bool IsMaskVector = VT.getVectorElementType() == MVT::i1;
16206 if (IsMaskVector) {
16207 ContainerVT = ContainerVT.changeVectorElementType(MVT::i8);
16208
16209 // Expand input operands
16210 SDValue SplatOneOp1 = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerVT,
16211 DAG.getUNDEF(ContainerVT),
16212 DAG.getConstant(1, DL, XLenVT), EVL1);
16213 SDValue SplatZeroOp1 = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerVT,
16214 DAG.getUNDEF(ContainerVT),
16215 DAG.getConstant(0, DL, XLenVT), EVL1);
16216 Op1 = DAG.getNode(RISCVISD::VMERGE_VL, DL, ContainerVT, Op1, SplatOneOp1,
16217 SplatZeroOp1, DAG.getUNDEF(ContainerVT), EVL1);
16218
16219 SDValue SplatOneOp2 = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerVT,
16220 DAG.getUNDEF(ContainerVT),
16221 DAG.getConstant(1, DL, XLenVT), EVL2);
16222 SDValue SplatZeroOp2 = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerVT,
16223 DAG.getUNDEF(ContainerVT),
16224 DAG.getConstant(0, DL, XLenVT), EVL2);
16225 Op2 = DAG.getNode(RISCVISD::VMERGE_VL, DL, ContainerVT, Op2, SplatOneOp2,
16226 SplatZeroOp2, DAG.getUNDEF(ContainerVT), EVL2);
16227 }
16228
16229 auto getVectorFirstEle = [](SDValue Vec) {
16230 SDValue FirstEle;
16231 if (sd_match(Vec, m_InsertElt(m_Value(), m_Value(FirstEle), m_Zero())))
16232 return FirstEle;
16233
16234 if (Vec.getOpcode() == ISD::SPLAT_VECTOR ||
16236 return Vec.getOperand(0);
16237
16238 return SDValue();
16239 };
16240
16241 if (!IsMaskVector && isNullConstant(Offset) && isOneConstant(EVL1))
16242 if (auto FirstEle = getVectorFirstEle(Op->getOperand(0))) {
16243 MVT EltVT = ContainerVT.getVectorElementType();
16244 SDValue Result;
16245 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
16246 (EltVT == MVT::bf16 && !Subtarget.hasVInstructionsBF16())) {
16247 EltVT = EltVT.changeTypeToInteger();
16248 ContainerVT = ContainerVT.changeVectorElementType(EltVT);
16249 Op2 = DAG.getBitcast(ContainerVT, Op2);
16250 FirstEle =
16251 DAG.getAnyExtOrTrunc(DAG.getBitcast(EltVT, FirstEle), DL, XLenVT);
16252 }
16253 Result = DAG.getNode(EltVT.isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL
16254 : RISCVISD::VSLIDE1UP_VL,
16255 DL, ContainerVT, DAG.getUNDEF(ContainerVT), Op2,
16256 FirstEle, Mask, EVL2);
16257 Result = DAG.getBitcast(
16259 Result);
16260 return VT.isFixedLengthVector()
16261 ? convertFromScalableVector(VT, Result, DAG, Subtarget)
16262 : Result;
16263 }
16264
16265 int64_t ImmValue = cast<ConstantSDNode>(Offset)->getSExtValue();
16266 SDValue DownOffset, UpOffset;
16267 if (ImmValue >= 0) {
16268 // The operand is a TargetConstant, we need to rebuild it as a regular
16269 // constant.
16270 DownOffset = DAG.getConstant(ImmValue, DL, XLenVT);
16271 UpOffset = DAG.getNode(ISD::SUB, DL, XLenVT, EVL1, DownOffset);
16272 } else {
16273 // The operand is a TargetConstant, we need to rebuild it as a regular
16274 // constant rather than negating the original operand.
16275 UpOffset = DAG.getConstant(-ImmValue, DL, XLenVT);
16276 DownOffset = DAG.getNode(ISD::SUB, DL, XLenVT, EVL1, UpOffset);
16277 }
16278
16279 if (ImmValue != 0)
16280 Op1 = getVSlidedown(DAG, Subtarget, DL, ContainerVT,
16281 DAG.getUNDEF(ContainerVT), Op1, DownOffset, Mask,
16282 Subtarget.hasVLDependentLatency() ? UpOffset : EVL2);
16283 SDValue Result = getVSlideup(DAG, Subtarget, DL, ContainerVT, Op1, Op2,
16284 UpOffset, Mask, EVL2, RISCVVType::TAIL_AGNOSTIC);
16285
16286 if (IsMaskVector) {
16287 // Truncate Result back to a mask vector (Result has same EVL as Op2)
16288 Result = DAG.getNode(
16289 RISCVISD::SETCC_VL, DL, ContainerVT.changeVectorElementType(MVT::i1),
16290 {Result, DAG.getConstant(0, DL, ContainerVT),
16291 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
16292 Mask, EVL2});
16293 }
16294
16295 if (!VT.isFixedLengthVector())
16296 return Result;
16297 return convertFromScalableVector(VT, Result, DAG, Subtarget);
16298}
16299
16300SDValue
16301RISCVTargetLowering::lowerVPReverseExperimental(SDValue Op,
16302 SelectionDAG &DAG) const {
16303 SDLoc DL(Op);
16304 MVT VT = Op.getSimpleValueType();
16305 MVT XLenVT = Subtarget.getXLenVT();
16306
16307 SDValue Op1 = Op.getOperand(0);
16308 SDValue Mask = Op.getOperand(1);
16309 SDValue EVL = Op.getOperand(2);
16310
16311 MVT ContainerVT = VT;
16312 if (VT.isFixedLengthVector()) {
16313 ContainerVT = getContainerForFixedLengthVector(VT);
16314 Op1 = convertToScalableVector(ContainerVT, Op1, DAG, Subtarget);
16315 MVT MaskVT = getMaskTypeFor(ContainerVT);
16316 Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
16317 }
16318
16319 MVT GatherVT = ContainerVT;
16320 MVT IndicesVT = ContainerVT.changeVectorElementTypeToInteger();
16321 // Check if we are working with mask vectors
16322 bool IsMaskVector = ContainerVT.getVectorElementType() == MVT::i1;
16323 if (IsMaskVector) {
16324 GatherVT = IndicesVT = ContainerVT.changeVectorElementType(MVT::i8);
16325
16326 // Expand input operand
16327 SDValue SplatOne = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, IndicesVT,
16328 DAG.getUNDEF(IndicesVT),
16329 DAG.getConstant(1, DL, XLenVT), EVL);
16330 SDValue SplatZero = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, IndicesVT,
16331 DAG.getUNDEF(IndicesVT),
16332 DAG.getConstant(0, DL, XLenVT), EVL);
16333 Op1 = DAG.getNode(RISCVISD::VMERGE_VL, DL, IndicesVT, Op1, SplatOne,
16334 SplatZero, DAG.getUNDEF(IndicesVT), EVL);
16335 }
16336
16337 unsigned EltSize = GatherVT.getScalarSizeInBits();
16338 unsigned MinSize = GatherVT.getSizeInBits().getKnownMinValue();
16339 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
16340 unsigned MaxVLMAX =
16341 RISCVTargetLowering::computeVLMAX(VectorBitsMax, EltSize, MinSize);
16342
16343 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
16344 // If this is SEW=8 and VLMAX is unknown or more than 256, we need
16345 // to use vrgatherei16.vv.
16346 // TODO: It's also possible to use vrgatherei16.vv for other types to
16347 // decrease register width for the index calculation.
16348 // NOTE: This code assumes VLMAX <= 65536 for LMUL=8 SEW=16.
16349 if (MaxVLMAX > 256 && EltSize == 8) {
16350 // If this is LMUL=8, we have to split before using vrgatherei16.vv.
16351 // Split the vector in half and reverse each half using a full register
16352 // reverse.
16353 // Swap the halves and concatenate them.
16354 // Slide the concatenated result by (VLMax - VL).
16355 if (MinSize == (8 * RISCV::RVVBitsPerBlock)) {
16356 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(GatherVT);
16357 auto [Lo, Hi] = DAG.SplitVector(Op1, DL);
16358
16359 SDValue LoRev = DAG.getNode(ISD::VECTOR_REVERSE, DL, LoVT, Lo);
16360 SDValue HiRev = DAG.getNode(ISD::VECTOR_REVERSE, DL, HiVT, Hi);
16361
16362 // Reassemble the low and high pieces reversed.
16363 // NOTE: this Result is unmasked (because we do not need masks for
16364 // shuffles). If in the future this has to change, we can use a SELECT_VL
16365 // between Result and UNDEF using the mask originally passed to VP_REVERSE
16366 SDValue Result =
16367 DAG.getNode(ISD::CONCAT_VECTORS, DL, GatherVT, HiRev, LoRev);
16368
16369 // Slide off any elements from past EVL that were reversed into the low
16370 // elements.
16371 SDValue VLMax =
16372 DAG.getElementCount(DL, XLenVT, GatherVT.getVectorElementCount());
16373 SDValue Diff = DAG.getNode(ISD::SUB, DL, XLenVT, VLMax, EVL);
16374
16375 Result = getVSlidedown(DAG, Subtarget, DL, GatherVT,
16376 DAG.getUNDEF(GatherVT), Result, Diff, Mask, EVL);
16377
16378 if (IsMaskVector) {
16379 // Truncate Result back to a mask vector
16380 Result =
16381 DAG.getNode(RISCVISD::SETCC_VL, DL, ContainerVT,
16382 {Result, DAG.getConstant(0, DL, GatherVT),
16384 DAG.getUNDEF(getMaskTypeFor(ContainerVT)), Mask, EVL});
16385 }
16386
16387 if (!VT.isFixedLengthVector())
16388 return Result;
16389 return convertFromScalableVector(VT, Result, DAG, Subtarget);
16390 }
16391
16392 // Just promote the int type to i16 which will double the LMUL.
16393 IndicesVT = MVT::getVectorVT(MVT::i16, IndicesVT.getVectorElementCount());
16394 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
16395 }
16396
16397 SDValue VID = DAG.getNode(RISCVISD::VID_VL, DL, IndicesVT, Mask, EVL);
16398 SDValue VecLen =
16399 DAG.getNode(ISD::SUB, DL, XLenVT, EVL, DAG.getConstant(1, DL, XLenVT));
16400 SDValue VecLenSplat = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, IndicesVT,
16401 DAG.getUNDEF(IndicesVT), VecLen, EVL);
16402 SDValue VRSUB = DAG.getNode(RISCVISD::SUB_VL, DL, IndicesVT, VecLenSplat, VID,
16403 DAG.getUNDEF(IndicesVT), Mask, EVL);
16404 SDValue Result = DAG.getNode(GatherOpc, DL, GatherVT, Op1, VRSUB,
16405 DAG.getUNDEF(GatherVT), Mask, EVL);
16406
16407 if (IsMaskVector) {
16408 // Truncate Result back to a mask vector
16409 Result = DAG.getNode(
16410 RISCVISD::SETCC_VL, DL, ContainerVT,
16411 {Result, DAG.getConstant(0, DL, GatherVT), DAG.getCondCode(ISD::SETNE),
16412 DAG.getUNDEF(getMaskTypeFor(ContainerVT)), Mask, EVL});
16413 }
16414
16415 if (!VT.isFixedLengthVector())
16416 return Result;
16417 return convertFromScalableVector(VT, Result, DAG, Subtarget);
16418}
16419
16420SDValue RISCVTargetLowering::lowerVPStridedLoad(SDValue Op,
16421 SelectionDAG &DAG) const {
16422 SDLoc DL(Op);
16423 MVT XLenVT = Subtarget.getXLenVT();
16424 MVT VT = Op.getSimpleValueType();
16425 MVT ContainerVT = VT;
16426 if (VT.isFixedLengthVector())
16427 ContainerVT = getContainerForFixedLengthVector(VT);
16428
16429 SDVTList VTs = DAG.getVTList({ContainerVT, MVT::Other});
16430
16431 auto *VPNode = cast<VPStridedLoadSDNode>(Op);
16432 // Check if the mask is known to be all ones
16433 SDValue Mask = VPNode->getMask();
16434 bool IsUnmasked = ISD::isConstantSplatVectorAllOnes(Mask.getNode());
16435
16436 SDValue IntID = DAG.getTargetConstant(IsUnmasked ? Intrinsic::riscv_vlse
16437 : Intrinsic::riscv_vlse_mask,
16438 DL, XLenVT);
16439 SmallVector<SDValue, 8> Ops{VPNode->getChain(), IntID,
16440 DAG.getUNDEF(ContainerVT), VPNode->getBasePtr(),
16441 VPNode->getStride()};
16442 if (!IsUnmasked) {
16443 if (VT.isFixedLengthVector()) {
16444 MVT MaskVT = ContainerVT.changeVectorElementType(MVT::i1);
16445 Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
16446 }
16447 Ops.push_back(Mask);
16448 }
16449 Ops.push_back(VPNode->getVectorLength());
16450 if (!IsUnmasked) {
16451 SDValue Policy =
16453 Ops.push_back(Policy);
16454 }
16455
16456 SDValue Result =
16458 VPNode->getMemoryVT(), VPNode->getMemOperand());
16459 SDValue Chain = Result.getValue(1);
16460
16461 if (VT.isFixedLengthVector())
16462 Result = convertFromScalableVector(VT, Result, DAG, Subtarget);
16463
16464 return DAG.getMergeValues({Result, Chain}, DL);
16465}
16466
16467SDValue RISCVTargetLowering::lowerVPStridedStore(SDValue Op,
16468 SelectionDAG &DAG) const {
16469 SDLoc DL(Op);
16470 MVT XLenVT = Subtarget.getXLenVT();
16471
16472 auto *VPNode = cast<VPStridedStoreSDNode>(Op);
16473 SDValue StoreVal = VPNode->getValue();
16474 MVT VT = StoreVal.getSimpleValueType();
16475 MVT ContainerVT = VT;
16476 if (VT.isFixedLengthVector()) {
16477 ContainerVT = getContainerForFixedLengthVector(VT);
16478 StoreVal = convertToScalableVector(ContainerVT, StoreVal, DAG, Subtarget);
16479 }
16480
16481 // Check if the mask is known to be all ones
16482 SDValue Mask = VPNode->getMask();
16483 bool IsUnmasked = ISD::isConstantSplatVectorAllOnes(Mask.getNode());
16484
16485 SDValue IntID = DAG.getTargetConstant(IsUnmasked ? Intrinsic::riscv_vsse
16486 : Intrinsic::riscv_vsse_mask,
16487 DL, XLenVT);
16488 SmallVector<SDValue, 8> Ops{VPNode->getChain(), IntID, StoreVal,
16489 VPNode->getBasePtr(), VPNode->getStride()};
16490 if (!IsUnmasked) {
16491 if (VT.isFixedLengthVector()) {
16492 MVT MaskVT = ContainerVT.changeVectorElementType(MVT::i1);
16493 Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
16494 }
16495 Ops.push_back(Mask);
16496 }
16497 Ops.push_back(VPNode->getVectorLength());
16498
16499 return DAG.getMemIntrinsicNode(ISD::INTRINSIC_VOID, DL, VPNode->getVTList(),
16500 Ops, VPNode->getMemoryVT(),
16501 VPNode->getMemOperand());
16502}
16503
16504// Custom lower MGATHER/VP_GATHER to a legalized form for RVV. It will then be
16505// matched to a RVV indexed load. The RVV indexed load instructions only
16506// support the "unsigned unscaled" addressing mode; indices are implicitly
16507// zero-extended or truncated to XLEN and are treated as byte offsets. Any
16508// signed or scaled indexing is extended to the XLEN value type and scaled
16509// accordingly.
16510SDValue RISCVTargetLowering::lowerMaskedGather(SDValue Op,
16511 SelectionDAG &DAG) const {
16512 SDLoc DL(Op);
16513 MVT VT = Op.getSimpleValueType();
16514
16515 const auto *MemSD = cast<MemSDNode>(Op.getNode());
16516 EVT MemVT = MemSD->getMemoryVT();
16517 MachineMemOperand *MMO = MemSD->getMemOperand();
16518 SDValue Chain = MemSD->getChain();
16519 SDValue BasePtr = MemSD->getBasePtr();
16520
16521 [[maybe_unused]] ISD::LoadExtType LoadExtType;
16522 SDValue Index, Mask, PassThru, VL;
16523
16524 if (auto *VPGN = dyn_cast<VPGatherSDNode>(Op.getNode())) {
16525 Index = VPGN->getIndex();
16526 Mask = VPGN->getMask();
16527 PassThru = DAG.getUNDEF(VT);
16528 VL = VPGN->getVectorLength();
16529 // VP doesn't support extending loads.
16531 } else {
16532 // Else it must be a MGATHER.
16533 auto *MGN = cast<MaskedGatherSDNode>(Op.getNode());
16534 Index = MGN->getIndex();
16535 Mask = MGN->getMask();
16536 PassThru = MGN->getPassThru();
16537 LoadExtType = MGN->getExtensionType();
16538 }
16539
16540 MVT IndexVT = Index.getSimpleValueType();
16541 MVT XLenVT = Subtarget.getXLenVT();
16542
16544 "Unexpected VTs!");
16545 assert(BasePtr.getSimpleValueType() == XLenVT && "Unexpected pointer type");
16546 // Targets have to explicitly opt-in for extending vector loads.
16547 assert(LoadExtType == ISD::NON_EXTLOAD &&
16548 "Unexpected extending MGATHER/VP_GATHER");
16549
16550 // If the mask is known to be all ones, optimize to an unmasked intrinsic;
16551 // the selection of the masked intrinsics doesn't do this for us.
16552 bool IsUnmasked = ISD::isConstantSplatVectorAllOnes(Mask.getNode());
16553
16554 MVT ContainerVT = VT;
16555 if (VT.isFixedLengthVector()) {
16556 ContainerVT = getContainerForFixedLengthVector(VT);
16557 IndexVT = MVT::getVectorVT(IndexVT.getVectorElementType(),
16558 ContainerVT.getVectorElementCount());
16559
16560 Index = convertToScalableVector(IndexVT, Index, DAG, Subtarget);
16561
16562 if (!IsUnmasked) {
16563 MVT MaskVT = getMaskTypeFor(ContainerVT);
16564 Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
16565 PassThru = convertToScalableVector(ContainerVT, PassThru, DAG, Subtarget);
16566 }
16567 }
16568
16569 if (!VL)
16570 VL = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).second;
16571
16572 if (XLenVT == MVT::i32 && IndexVT.getVectorElementType().bitsGT(XLenVT)) {
16573 IndexVT = IndexVT.changeVectorElementType(XLenVT);
16574 Index = DAG.getNode(ISD::TRUNCATE, DL, IndexVT, Index);
16575 }
16576
16577 unsigned IntID =
16578 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
16579 SmallVector<SDValue, 8> Ops{Chain, DAG.getTargetConstant(IntID, DL, XLenVT)};
16580 if (IsUnmasked)
16581 Ops.push_back(DAG.getUNDEF(ContainerVT));
16582 else
16583 Ops.push_back(PassThru);
16584 Ops.push_back(BasePtr);
16585 Ops.push_back(Index);
16586 if (!IsUnmasked)
16587 Ops.push_back(Mask);
16588 Ops.push_back(VL);
16589 if (!IsUnmasked)
16590 Ops.push_back(DAG.getTargetConstant(RISCVVType::TAIL_AGNOSTIC, DL, XLenVT));
16591
16592 SDVTList VTs = DAG.getVTList({ContainerVT, MVT::Other});
16593 SDValue Result =
16594 DAG.getMemIntrinsicNode(ISD::INTRINSIC_W_CHAIN, DL, VTs, Ops, MemVT, MMO);
16595 Chain = Result.getValue(1);
16596
16597 if (VT.isFixedLengthVector())
16598 Result = convertFromScalableVector(VT, Result, DAG, Subtarget);
16599
16600 return DAG.getMergeValues({Result, Chain}, DL);
16601}
16602
16603// Custom lower MSCATTER/VP_SCATTER to a legalized form for RVV. It will then be
16604// matched to a RVV indexed store. The RVV indexed store instructions only
16605// support the "unsigned unscaled" addressing mode; indices are implicitly
16606// zero-extended or truncated to XLEN and are treated as byte offsets. Any
16607// signed or scaled indexing is extended to the XLEN value type and scaled
16608// accordingly.
16609SDValue RISCVTargetLowering::lowerMaskedScatter(SDValue Op,
16610 SelectionDAG &DAG) const {
16611 SDLoc DL(Op);
16612 const auto *MemSD = cast<MemSDNode>(Op.getNode());
16613 EVT MemVT = MemSD->getMemoryVT();
16614 MachineMemOperand *MMO = MemSD->getMemOperand();
16615 SDValue Chain = MemSD->getChain();
16616 SDValue BasePtr = MemSD->getBasePtr();
16617
16618 [[maybe_unused]] bool IsTruncatingStore = false;
16619 SDValue Index, Mask, Val, VL;
16620
16621 if (auto *VPSN = dyn_cast<VPScatterSDNode>(Op.getNode())) {
16622 Index = VPSN->getIndex();
16623 Mask = VPSN->getMask();
16624 Val = VPSN->getValue();
16625 VL = VPSN->getVectorLength();
16626 // VP doesn't support truncating stores.
16627 IsTruncatingStore = false;
16628 } else {
16629 // Else it must be a MSCATTER.
16630 auto *MSN = cast<MaskedScatterSDNode>(Op.getNode());
16631 Index = MSN->getIndex();
16632 Mask = MSN->getMask();
16633 Val = MSN->getValue();
16634 IsTruncatingStore = MSN->isTruncatingStore();
16635 }
16636
16637 MVT VT = Val.getSimpleValueType();
16638 MVT IndexVT = Index.getSimpleValueType();
16639 MVT XLenVT = Subtarget.getXLenVT();
16640
16642 "Unexpected VTs!");
16643 assert(BasePtr.getSimpleValueType() == XLenVT && "Unexpected pointer type");
16644 // Targets have to explicitly opt-in for extending vector loads and
16645 // truncating vector stores.
16646 assert(!IsTruncatingStore && "Unexpected truncating MSCATTER/VP_SCATTER");
16647
16648 // If the mask is known to be all ones, optimize to an unmasked intrinsic;
16649 // the selection of the masked intrinsics doesn't do this for us.
16650 bool IsUnmasked = ISD::isConstantSplatVectorAllOnes(Mask.getNode());
16651
16652 MVT ContainerVT = VT;
16653 if (VT.isFixedLengthVector()) {
16654 ContainerVT = getContainerForFixedLengthVector(VT);
16655 IndexVT = MVT::getVectorVT(IndexVT.getVectorElementType(),
16656 ContainerVT.getVectorElementCount());
16657
16658 Index = convertToScalableVector(IndexVT, Index, DAG, Subtarget);
16659 Val = convertToScalableVector(ContainerVT, Val, DAG, Subtarget);
16660
16661 if (!IsUnmasked) {
16662 MVT MaskVT = getMaskTypeFor(ContainerVT);
16663 Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
16664 }
16665 }
16666
16667 if (!VL)
16668 VL = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).second;
16669
16670 if (XLenVT == MVT::i32 && IndexVT.getVectorElementType().bitsGT(XLenVT)) {
16671 IndexVT = IndexVT.changeVectorElementType(XLenVT);
16672 Index = DAG.getNode(ISD::TRUNCATE, DL, IndexVT, Index);
16673 }
16674
16675 unsigned IntID =
16676 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
16677 SmallVector<SDValue, 8> Ops{Chain, DAG.getTargetConstant(IntID, DL, XLenVT)};
16678 Ops.push_back(Val);
16679 Ops.push_back(BasePtr);
16680 Ops.push_back(Index);
16681 if (!IsUnmasked)
16682 Ops.push_back(Mask);
16683 Ops.push_back(VL);
16684
16686 DAG.getVTList(MVT::Other), Ops, MemVT, MMO);
16687}
16688
16689SDValue RISCVTargetLowering::lowerGET_ROUNDING(SDValue Op,
16690 SelectionDAG &DAG) const {
16691 const MVT XLenVT = Subtarget.getXLenVT();
16692 SDLoc DL(Op);
16693 SDValue Chain = Op->getOperand(0);
16694 SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::frm, DL, XLenVT);
16695 SDVTList VTs = DAG.getVTList(XLenVT, MVT::Other);
16696 SDValue RM = DAG.getNode(RISCVISD::READ_CSR, DL, VTs, Chain, SysRegNo);
16697
16698 // Encoding used for rounding mode in RISC-V differs from that used in
16699 // FLT_ROUNDS. To convert it the RISC-V rounding mode is used as an index in a
16700 // table, which consists of a sequence of 4-bit fields, each representing
16701 // corresponding FLT_ROUNDS mode.
16702 static const int Table =
16708
16709 SDValue Shift =
16710 DAG.getNode(ISD::SHL, DL, XLenVT, RM, DAG.getConstant(2, DL, XLenVT));
16711 SDValue Shifted = DAG.getNode(ISD::SRL, DL, XLenVT,
16712 DAG.getConstant(Table, DL, XLenVT), Shift);
16713 SDValue Masked = DAG.getNode(ISD::AND, DL, XLenVT, Shifted,
16714 DAG.getConstant(7, DL, XLenVT));
16715
16716 return DAG.getMergeValues({Masked, Chain}, DL);
16717}
16718
16719SDValue RISCVTargetLowering::lowerSET_ROUNDING(SDValue Op,
16720 SelectionDAG &DAG) const {
16721 const MVT XLenVT = Subtarget.getXLenVT();
16722 SDLoc DL(Op);
16723 SDValue Chain = Op->getOperand(0);
16724 SDValue RMValue = Op->getOperand(1);
16725 SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::frm, DL, XLenVT);
16726
16727 // Encoding used for rounding mode in RISC-V differs from that used in
16728 // FLT_ROUNDS. To convert it the C rounding mode is used as an index in
16729 // a table, which consists of a sequence of 4-bit fields, each representing
16730 // corresponding RISC-V mode.
16731 static const unsigned Table =
16737
16738 RMValue = DAG.getNode(ISD::ZERO_EXTEND, DL, XLenVT, RMValue);
16739
16740 SDValue Shift = DAG.getNode(ISD::SHL, DL, XLenVT, RMValue,
16741 DAG.getConstant(2, DL, XLenVT));
16742 SDValue Shifted = DAG.getNode(ISD::SRL, DL, XLenVT,
16743 DAG.getConstant(Table, DL, XLenVT), Shift);
16744 RMValue = DAG.getNode(ISD::AND, DL, XLenVT, Shifted,
16745 DAG.getConstant(0x7, DL, XLenVT));
16746 return DAG.getNode(RISCVISD::WRITE_CSR, DL, MVT::Other, Chain, SysRegNo,
16747 RMValue);
16748}
16749
16750SDValue RISCVTargetLowering::lowerGET_FPENV(SDValue Op,
16751 SelectionDAG &DAG) const {
16752 const MVT XLenVT = Subtarget.getXLenVT();
16753 SDLoc DL(Op);
16754 SDValue Chain = Op->getOperand(0);
16755 SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
16756 SDVTList VTs = DAG.getVTList(XLenVT, MVT::Other);
16757 return DAG.getNode(RISCVISD::READ_CSR, DL, VTs, Chain, SysRegNo);
16758}
16759
16760SDValue RISCVTargetLowering::lowerSET_FPENV(SDValue Op,
16761 SelectionDAG &DAG) const {
16762 const MVT XLenVT = Subtarget.getXLenVT();
16763 SDLoc DL(Op);
16764 SDValue Chain = Op->getOperand(0);
16765 SDValue EnvValue = Op->getOperand(1);
16766 SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
16767
16768 EnvValue = DAG.getNode(ISD::ZERO_EXTEND, DL, XLenVT, EnvValue);
16769 return DAG.getNode(RISCVISD::WRITE_CSR, DL, MVT::Other, Chain, SysRegNo,
16770 EnvValue);
16771}
16772
16773SDValue RISCVTargetLowering::lowerRESET_FPENV(SDValue Op,
16774 SelectionDAG &DAG) const {
16775 const MVT XLenVT = Subtarget.getXLenVT();
16776 SDLoc DL(Op);
16777 SDValue Chain = Op->getOperand(0);
16778 SDValue EnvValue = DAG.getRegister(RISCV::X0, XLenVT);
16779 SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
16780
16781 return DAG.getNode(RISCVISD::WRITE_CSR, DL, MVT::Other, Chain, SysRegNo,
16782 EnvValue);
16783}
16784
16787
16788SDValue RISCVTargetLowering::lowerGET_FPMODE(SDValue Op,
16789 SelectionDAG &DAG) const {
16790 const MVT XLenVT = Subtarget.getXLenVT();
16791 SDLoc DL(Op);
16792 SDValue Chain = Op->getOperand(0);
16793 SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
16794 SDVTList VTs = DAG.getVTList(XLenVT, MVT::Other);
16795 SDValue Result = DAG.getNode(RISCVISD::READ_CSR, DL, VTs, Chain, SysRegNo);
16796 Chain = Result.getValue(1);
16797 return DAG.getMergeValues({Result, Chain}, DL);
16798}
16799
16800SDValue RISCVTargetLowering::lowerSET_FPMODE(SDValue Op,
16801 SelectionDAG &DAG) const {
16802 const MVT XLenVT = Subtarget.getXLenVT();
16803 const uint64_t ModeMaskValue = Subtarget.is64Bit() ? ModeMask64 : ModeMask32;
16804 SDLoc DL(Op);
16805 SDValue Chain = Op->getOperand(0);
16806 SDValue EnvValue = Op->getOperand(1);
16807 SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
16808 SDValue ModeMask = DAG.getConstant(ModeMaskValue, DL, XLenVT);
16809
16810 EnvValue = DAG.getNode(ISD::ZERO_EXTEND, DL, XLenVT, EnvValue);
16811 EnvValue = DAG.getNode(ISD::AND, DL, XLenVT, EnvValue, ModeMask);
16812 Chain = DAG.getNode(RISCVISD::CLEAR_CSR, DL, MVT::Other, Chain, SysRegNo,
16813 ModeMask);
16814 return DAG.getNode(RISCVISD::SET_CSR, DL, MVT::Other, Chain, SysRegNo,
16815 EnvValue);
16816}
16817
16818SDValue RISCVTargetLowering::lowerRESET_FPMODE(SDValue Op,
16819 SelectionDAG &DAG) const {
16820 const MVT XLenVT = Subtarget.getXLenVT();
16821 const uint64_t ModeMaskValue = Subtarget.is64Bit() ? ModeMask64 : ModeMask32;
16822 SDLoc DL(Op);
16823 SDValue Chain = Op->getOperand(0);
16824 SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
16825 SDValue ModeMask = DAG.getConstant(ModeMaskValue, DL, XLenVT);
16826
16827 return DAG.getNode(RISCVISD::CLEAR_CSR, DL, MVT::Other, Chain, SysRegNo,
16828 ModeMask);
16829}
16830
16831SDValue RISCVTargetLowering::lowerEH_DWARF_CFA(SDValue Op,
16832 SelectionDAG &DAG) const {
16834
16835 bool isRISCV64 = Subtarget.is64Bit();
16836 EVT PtrVT = getPointerTy(DAG.getDataLayout());
16837
16838 int FI = MF.getFrameInfo().CreateFixedObject(isRISCV64 ? 8 : 4, 0, false);
16839 return DAG.getFrameIndex(FI, PtrVT);
16840}
16841
16842// Returns the opcode of the target-specific SDNode that implements the 32-bit
16843// form of the given Opcode.
16844static unsigned getRISCVWOpcode(unsigned Opcode) {
16845 switch (Opcode) {
16846 default:
16847 llvm_unreachable("Unexpected opcode");
16848 case ISD::SHL:
16849 return RISCVISD::SLLW;
16850 case ISD::SRA:
16851 return RISCVISD::SRAW;
16852 case ISD::SRL:
16853 return RISCVISD::SRLW;
16854 case ISD::SDIV:
16855 return RISCVISD::DIVW;
16856 case ISD::UDIV:
16857 return RISCVISD::DIVUW;
16858 case ISD::UREM:
16859 return RISCVISD::REMUW;
16860 case ISD::ROTL:
16861 return RISCVISD::ROLW;
16862 case ISD::ROTR:
16863 return RISCVISD::RORW;
16864 }
16865}
16866
16867// Converts the given i8/i16/i32 operation to a target-specific SelectionDAG
16868// node. Because i8/i16/i32 isn't a legal type for RV64, these operations would
16869// otherwise be promoted to i64, making it difficult to select the
16870// SLLW/DIVUW/.../*W later one because the fact the operation was originally of
16871// type i8/i16/i32 is lost.
16873 unsigned ExtOpc = ISD::ANY_EXTEND) {
16874 SDLoc DL(N);
16875 unsigned WOpcode = getRISCVWOpcode(N->getOpcode());
16876 SDValue NewOp0 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(0));
16877 SDValue NewOp1 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(1));
16878 SDValue NewRes = DAG.getNode(WOpcode, DL, MVT::i64, NewOp0, NewOp1);
16879 // ReplaceNodeResults requires we maintain the same type for the return value.
16880 return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewRes);
16881}
16882
16883// Converts the given 32-bit operation to a i64 operation with signed extension
16884// semantic to reduce the signed extension instructions.
16886 SDLoc DL(N);
16887 SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0));
16888 SDValue NewOp1 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(1));
16889 SDValue NewWOp = DAG.getNode(N->getOpcode(), DL, MVT::i64, NewOp0, NewOp1);
16890 SDValue NewRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, NewWOp,
16891 DAG.getValueType(MVT::i32));
16892 return DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, NewRes);
16893}
16894
16895// Zero-extend a 32-bit packed vector to the 64-bit packed type WideVT,
16896// clearing the upper lanes.
16898 SDValue V, MVT WideVT) {
16899 SDValue Wide =
16900 DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, DAG.getBitcast(MVT::i32, V));
16901 return DAG.getBitcast(WideVT, Wide);
16902}
16903
16906 SelectionDAG &DAG) const {
16907 SDLoc DL(N);
16908 switch (N->getOpcode()) {
16909 default:
16910 llvm_unreachable("Don't know how to custom type legalize this operation!");
16913 case ISD::FP_TO_SINT:
16914 case ISD::FP_TO_UINT: {
16915 bool IsStrict = N->isStrictFPOpcode();
16916 bool IsSigned = N->getOpcode() == ISD::FP_TO_SINT ||
16917 N->getOpcode() == ISD::STRICT_FP_TO_SINT;
16918 SDValue Op0 = IsStrict ? N->getOperand(1) : N->getOperand(0);
16919
16920 // On RV32 only f16 is handled here: it is the only FP type whose finite
16921 // values always fit in an i32 after truncation towards zero, so convert in
16922 // i32 and extend instead of calling __fix(un)hfdi, which compiler-rt does
16923 // not provide. Out of range values and NaN are poison, so the fcvt clamping
16924 // is acceptable. Without Zfh/Zhinx the i32 conversion promotes f16 to f32.
16925 if (!Subtarget.is64Bit()) {
16926 assert(N->getValueType(0) == MVT::i64 &&
16927 "Unexpected custom legalisation");
16928 if (Op0.getValueType() != MVT::f16)
16929 return;
16930 SDValue Cvt;
16931 if (IsStrict) {
16932 Cvt = DAG.getNode(IsSigned ? ISD::STRICT_FP_TO_SINT
16934 DL, {MVT::i32, MVT::Other}, {N->getOperand(0), Op0});
16935 } else {
16936 Cvt = DAG.getNode(IsSigned ? ISD::FP_TO_SINT : ISD::FP_TO_UINT, DL,
16937 MVT::i32, Op0);
16938 }
16939 Results.push_back(DAG.getNode(
16940 IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, DL, MVT::i64, Cvt));
16941 if (IsStrict)
16942 Results.push_back(Cvt.getValue(1));
16943 return;
16944 }
16945
16946 assert(N->getValueType(0) == MVT::i32 && "Unexpected custom legalisation");
16947 if (getTypeAction(*DAG.getContext(), Op0.getValueType()) !=
16949 if (!isTypeLegal(Op0.getValueType()))
16950 return;
16951 if (IsStrict) {
16952 SDValue Chain = N->getOperand(0);
16953 // In absence of Zfh, promote f16 to f32, then convert.
16954 if (Op0.getValueType() == MVT::f16 &&
16955 !Subtarget.hasStdExtZfhOrZhinx()) {
16956 Op0 = DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {MVT::f32, MVT::Other},
16957 {Chain, Op0});
16958 Chain = Op0.getValue(1);
16959 }
16960 unsigned Opc = IsSigned ? RISCVISD::STRICT_FCVT_W_RV64
16961 : RISCVISD::STRICT_FCVT_WU_RV64;
16962 SDVTList VTs = DAG.getVTList(MVT::i64, MVT::Other);
16963 SDValue Res = DAG.getNode(
16964 Opc, DL, VTs, Chain, Op0,
16965 DAG.getTargetConstant(RISCVFPRndMode::RTZ, DL, MVT::i64));
16966 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
16967 Results.push_back(Res.getValue(1));
16968 return;
16969 }
16970 // For bf16, or f16 in absence of Zfh, promote [b]f16 to f32 and then
16971 // convert.
16972 if ((Op0.getValueType() == MVT::f16 &&
16973 !Subtarget.hasStdExtZfhOrZhinx()) ||
16974 Op0.getValueType() == MVT::bf16)
16975 Op0 = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Op0);
16976
16977 unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
16978 SDValue Res =
16979 DAG.getNode(Opc, DL, MVT::i64, Op0,
16980 DAG.getTargetConstant(RISCVFPRndMode::RTZ, DL, MVT::i64));
16981 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
16982 return;
16983 }
16984 // If the FP type needs to be softened, emit a library call using the 'si'
16985 // version. If we left it to default legalization we'd end up with 'di'. If
16986 // the FP type doesn't need to be softened just let generic type
16987 // legalization promote the result type.
16988 RTLIB::Libcall LC;
16989 if (IsSigned)
16990 LC = RTLIB::getFPTOSINT(Op0.getValueType(), N->getValueType(0));
16991 else
16992 LC = RTLIB::getFPTOUINT(Op0.getValueType(), N->getValueType(0));
16993 MakeLibCallOptions CallOptions;
16994 EVT OpVT = Op0.getValueType();
16995 CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0));
16996 SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
16997 SDValue Result;
16998 std::tie(Result, Chain) =
16999 makeLibCall(DAG, LC, N->getValueType(0), Op0, CallOptions, DL, Chain);
17000 Results.push_back(Result);
17001 if (IsStrict)
17002 Results.push_back(Chain);
17003 break;
17004 }
17005 case ISD::LROUND: {
17006 SDValue Op0 = N->getOperand(0);
17007 EVT Op0VT = Op0.getValueType();
17008 if (getTypeAction(*DAG.getContext(), Op0.getValueType()) !=
17010 if (!isTypeLegal(Op0VT))
17011 return;
17012
17013 // In absence of Zfh, promote f16 to f32, then convert.
17014 if (Op0.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx())
17015 Op0 = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Op0);
17016
17017 SDValue Res =
17018 DAG.getNode(RISCVISD::FCVT_W_RV64, DL, MVT::i64, Op0,
17019 DAG.getTargetConstant(RISCVFPRndMode::RMM, DL, MVT::i64));
17020 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
17021 return;
17022 }
17023 // If the FP type needs to be softened, emit a library call to lround. We'll
17024 // need to truncate the result. We assume any value that doesn't fit in i32
17025 // is allowed to return an unspecified value.
17026 RTLIB::Libcall LC = RTLIB::getLROUND(Op0.getValueType());
17027 assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected FP type for LROUND!");
17028 MakeLibCallOptions CallOptions;
17029 EVT OpVT = Op0.getValueType();
17030 CallOptions.setTypeListBeforeSoften(OpVT, MVT::i64);
17031 SDValue Result = makeLibCall(DAG, LC, MVT::i64, Op0, CallOptions, DL).first;
17032 Result = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Result);
17033 Results.push_back(Result);
17034 break;
17035 }
17038 assert(!Subtarget.is64Bit() && "READCYCLECOUNTER/READSTEADYCOUNTER only "
17039 "has custom type legalization on riscv32");
17040
17041 SDValue LoCounter, HiCounter;
17042 MVT XLenVT = Subtarget.getXLenVT();
17043 if (N->getOpcode() == ISD::READCYCLECOUNTER) {
17044 LoCounter = DAG.getTargetConstant(RISCVSysReg::cycle, DL, XLenVT);
17045 HiCounter = DAG.getTargetConstant(RISCVSysReg::cycleh, DL, XLenVT);
17046 } else {
17047 LoCounter = DAG.getTargetConstant(RISCVSysReg::time, DL, XLenVT);
17048 HiCounter = DAG.getTargetConstant(RISCVSysReg::timeh, DL, XLenVT);
17049 }
17050 SDVTList VTs = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other);
17051 SDValue RCW = DAG.getNode(RISCVISD::READ_COUNTER_WIDE, DL, VTs,
17052 N->getOperand(0), LoCounter, HiCounter);
17053
17054 Results.push_back(
17055 DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, RCW, RCW.getValue(1)));
17056 Results.push_back(RCW.getValue(2));
17057 break;
17058 }
17059 case ISD::LOAD: {
17060 if (!ISD::isNON_EXTLoad(N))
17061 return;
17062
17063 // Use a SEXTLOAD instead of the default EXTLOAD. Similar to the
17064 // sext_inreg we emit for ADD/SUB/MUL/SLLI.
17066
17067 if (N->getValueType(0) == MVT::i64) {
17068 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
17069 "Unexpected custom legalisation");
17070
17071 if (Ld->getAlign() < Subtarget.getZilsdAlign())
17072 return;
17073
17074 SDLoc DL(N);
17075 SDValue Result = DAG.getMemIntrinsicNode(
17076 RISCVISD::LD_RV32, DL,
17077 DAG.getVTList({MVT::i32, MVT::i32, MVT::Other}),
17078 {Ld->getChain(), Ld->getBasePtr()}, MVT::i64, Ld->getMemOperand());
17079 SDValue Lo = Result.getValue(0);
17080 SDValue Hi = Result.getValue(1);
17081 SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi);
17082 Results.append({Pair, Result.getValue(2)});
17083 return;
17084 }
17085
17086 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
17087 "Unexpected custom legalisation");
17088
17089 SDLoc dl(N);
17090 SDValue Res = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Ld->getChain(),
17091 Ld->getBasePtr(), Ld->getMemoryVT(),
17092 Ld->getMemOperand());
17093 Results.push_back(DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Res));
17094 Results.push_back(Res.getValue(1));
17095 return;
17096 }
17097 case ISD::MUL: {
17098 unsigned Size = N->getSimpleValueType(0).getSizeInBits();
17099 unsigned XLen = Subtarget.getXLen();
17100 if (Size > XLen) {
17101 // This multiply needs to be expanded, try to use MULH+MUL or WMUL if
17102 // possible. We duplicate the default legalization to
17103 // MULHU/MULHS/UMUL_LOHI/SMUL_LOHI to minimize the number of calls to
17104 // MaskedValueIsZero and ComputeNumSignBits
17105 // FIXME: Should we have a target independent MULHSU/WMULSU node? Are
17106 // there are other targets that could use it?
17107 assert(Size == (XLen * 2) && "Unexpected custom legalisation");
17108
17109 auto MakeMULPair = [&](SDValue L, SDValue R, unsigned HighOpc,
17110 unsigned LoHiOpc) {
17111 MVT XLenVT = Subtarget.getXLenVT();
17112 L = DAG.getNode(ISD::TRUNCATE, DL, XLenVT, L);
17113 R = DAG.getNode(ISD::TRUNCATE, DL, XLenVT, R);
17114 SDValue Lo, Hi;
17115 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit()) {
17116 SDVTList VTs = DAG.getVTList(MVT::i32, MVT::i32);
17117 Lo = DAG.getNode(LoHiOpc, DL, VTs, L, R);
17118 Hi = Lo.getValue(1);
17119 } else {
17120 Lo = DAG.getNode(ISD::MUL, DL, XLenVT, L, R);
17121 Hi = DAG.getNode(HighOpc, DL, XLenVT, L, R);
17122 }
17123 return DAG.getNode(ISD::BUILD_PAIR, DL, N->getValueType(0), Lo, Hi);
17124 };
17125
17126 SDValue LHS = N->getOperand(0);
17127 SDValue RHS = N->getOperand(1);
17128
17129 APInt HighMask = APInt::getHighBitsSet(Size, XLen);
17130 bool LHSIsU = DAG.MaskedValueIsZero(LHS, HighMask);
17131 bool RHSIsU = DAG.MaskedValueIsZero(RHS, HighMask);
17132 if (LHSIsU && RHSIsU) {
17133 Results.push_back(MakeMULPair(LHS, RHS, ISD::MULHU, ISD::UMUL_LOHI));
17134 return;
17135 }
17136
17137 bool LHSIsS = DAG.ComputeNumSignBits(LHS) > XLen;
17138 bool RHSIsS = DAG.ComputeNumSignBits(RHS) > XLen;
17139 if (LHSIsS && RHSIsS)
17140 Results.push_back(MakeMULPair(LHS, RHS, ISD::MULHS, ISD::SMUL_LOHI));
17141 else if (RHSIsU && LHSIsS)
17142 Results.push_back(
17143 MakeMULPair(LHS, RHS, RISCVISD::MULHSU, RISCVISD::WMULSU));
17144 else if (LHSIsU && RHSIsS)
17145 Results.push_back(
17146 MakeMULPair(RHS, LHS, RISCVISD::MULHSU, RISCVISD::WMULSU));
17147
17148 return;
17149 }
17150 [[fallthrough]];
17151 }
17152 case ISD::ADD:
17153 case ISD::SUB:
17154 if (N->getValueType(0) == MVT::i64) {
17155 assert(!Subtarget.is64Bit() && Subtarget.hasStdExtP() &&
17156 "Unexpected custom legalisation");
17157
17158 // Expand to ADDD/SUBD.
17159 auto [LHSLo, LHSHi] =
17160 DAG.SplitScalar(N->getOperand(0), DL, MVT::i32, MVT::i32);
17161 auto [RHSLo, RHSHi] =
17162 DAG.SplitScalar(N->getOperand(1), DL, MVT::i32, MVT::i32);
17163 unsigned Opc =
17164 N->getOpcode() == ISD::ADD ? RISCVISD::ADDD : RISCVISD::SUBD;
17165 SDValue Res = DAG.getNode(Opc, DL, DAG.getVTList(MVT::i32, MVT::i32),
17166 LHSLo, LHSHi, RHSLo, RHSHi);
17167 Res = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Res, Res.getValue(1));
17168 Results.push_back(Res);
17169 return;
17170 }
17171
17172 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
17173 "Unexpected custom legalisation");
17174 Results.push_back(customLegalizeToWOpWithSExt(N, DAG));
17175 break;
17176 case ISD::TRUNCATE: {
17177 MVT VT = N->getSimpleValueType(0);
17178 assert(VT.isFixedLengthVector() && Subtarget.hasStdExtP() &&
17179 Subtarget.is64Bit() && (VT == MVT::v2i16 || VT == MVT::v4i8) &&
17180 "Unexpected custom legalisation");
17181
17182 // v4i16->v4i8 and v2i32->v2i16 truncates aren't legal on their own, but
17183 // the widened result type is. Bitcast the operand to the widened result
17184 // type and use a shuffle to select the low half of each element, which
17185 // gets matched to a P-extension packed narrowing convert
17186 // (unzip8p/unzip16p).
17187
17188 SDValue Op0 = N->getOperand(0);
17189
17190 // Input should be a 64-bit vector.
17191 if (!Op0.getValueType().is64BitVector())
17192 break;
17193
17194 MVT WidenVT = getTypeToTransformTo(*DAG.getContext(), VT).getSimpleVT();
17195
17196 unsigned NumElts = VT.getVectorNumElements();
17197 SmallVector<int, 8> ShuffleMask(WidenVT.getVectorNumElements(), -1);
17198 for (unsigned i = 0; i != NumElts; ++i)
17199 ShuffleMask[i] = i * 2;
17200
17201 SDValue Src = DAG.getBitcast(WidenVT, Op0);
17202 Results.push_back(DAG.getVectorShuffle(WidenVT, DL, Src,
17203 DAG.getUNDEF(WidenVT), ShuffleMask));
17204 return;
17205 }
17206 case ISD::SHL:
17207 case ISD::SRA:
17208 case ISD::SRL: {
17209 EVT VT = N->getValueType(0);
17210 if (VT.isFixedLengthVector() && Subtarget.hasStdExtP()) {
17211 assert(Subtarget.is64Bit() && (VT == MVT::v2i16 || VT == MVT::v4i8) &&
17212 "Unexpected vector type for P-extension shift");
17213
17214 // If shift amount is a splat, don't scalarize - let normal widening
17215 // and SIMD patterns handle it (pslli.h, psrli.h, etc.)
17216 SDValue ShiftAmt = N->getOperand(1);
17217 if (DAG.isSplatValue(ShiftAmt, /*AllowUndefs=*/true))
17218 break;
17219
17220 EVT WidenVT = getTypeToTransformTo(*DAG.getContext(), VT);
17221 unsigned WidenNumElts = WidenVT.getVectorNumElements();
17222 // Unroll with OrigNumElts operations, padding result to WidenNumElts
17223 SDValue Res = DAG.UnrollVectorOp(N, WidenNumElts);
17224 Results.push_back(Res);
17225 break;
17226 }
17227
17228 if (VT == MVT::i64) {
17229 assert(!Subtarget.is64Bit() && Subtarget.hasStdExtP() &&
17230 "Unexpected custom legalisation");
17231
17232 SDValue LHS = N->getOperand(0);
17233 SDValue ShAmt = N->getOperand(1);
17234
17235 unsigned WideOpc = 0;
17236 APInt HighMask = APInt::getHighBitsSet(64, 32);
17237 if (DAG.MaskedValueIsZero(LHS, HighMask))
17238 WideOpc = RISCVISD::WSLL;
17239 else if (DAG.ComputeMaxSignificantBits(LHS) <= 32)
17240 WideOpc = RISCVISD::WSLA;
17241
17242 if (WideOpc) {
17243 SDValue Res =
17244 DAG.getNode(WideOpc, DL, DAG.getVTList(MVT::i32, MVT::i32),
17245 DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, LHS),
17246 DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, ShAmt));
17247 Results.push_back(DAG.getNode(ISD::BUILD_PAIR, DL, N->getValueType(0),
17248 Res, Res.getValue(1)));
17249 return;
17250 }
17251
17252 // Only handle constant shifts < 32. Non-constant shifts are handled by
17253 // lowerShiftLeftParts/lowerShiftRightParts, and shifts >= 32 use default
17254 // legalization.
17255 auto *ShAmtC = dyn_cast<ConstantSDNode>(N->getOperand(1));
17256 if (!ShAmtC || ShAmtC->getZExtValue() >= 32)
17257 break;
17258
17259 auto [Lo, Hi] = DAG.SplitScalar(LHS, DL, MVT::i32, MVT::i32);
17260
17261 // If the shift amount operand is coming from a vector legalization it may
17262 // have an illegal type.
17263 if (ShAmt.getValueType() != MVT::i32)
17264 ShAmt = DAG.getZExtOrTrunc(ShAmt, DL, MVT::i32);
17265
17266 SDValue LoRes, HiRes;
17267 if (N->getOpcode() == ISD::SHL) {
17268 // Lo = slli Lo, shamt
17269 // Hi = nsrli {Hi, Lo}, (32 - shamt)
17270 uint64_t ShAmtVal = ShAmtC->getZExtValue();
17271 LoRes = DAG.getNode(ISD::SHL, DL, MVT::i32, Lo, ShAmt);
17272 HiRes = DAG.getNode(RISCVISD::NSRL, DL, MVT::i32, Lo, Hi,
17273 DAG.getConstant(32 - ShAmtVal, DL, MVT::i32));
17274 } else {
17275 bool IsSRA = N->getOpcode() == ISD::SRA;
17276 LoRes = DAG.getNode(IsSRA ? RISCVISD::NSRA : RISCVISD::NSRL, DL,
17277 MVT::i32, Lo, Hi, ShAmt);
17278 HiRes =
17279 DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, DL, MVT::i32, Hi, ShAmt);
17280 }
17281 SDValue Res = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, LoRes, HiRes);
17282 Results.push_back(Res);
17283 return;
17284 }
17285
17286 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
17287 "Unexpected custom legalisation");
17288 if (N->getOperand(1).getOpcode() != ISD::Constant) {
17289 // If we can use a BSET instruction, allow default promotion to apply.
17290 if (N->getOpcode() == ISD::SHL && Subtarget.hasStdExtZbs() &&
17291 isOneConstant(N->getOperand(0)))
17292 break;
17293 Results.push_back(customLegalizeToWOp(N, DAG));
17294 break;
17295 }
17296
17297 // Custom legalize ISD::SHL by placing a SIGN_EXTEND_INREG after. This is
17298 // similar to customLegalizeToWOpWithSExt, but we must zero_extend the
17299 // shift amount.
17300 if (N->getOpcode() == ISD::SHL) {
17301 SDLoc DL(N);
17302 SDValue NewOp0 =
17303 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0));
17304 SDValue NewOp1 =
17305 DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, N->getOperand(1));
17306 SDValue NewWOp = DAG.getNode(ISD::SHL, DL, MVT::i64, NewOp0, NewOp1);
17307 SDValue NewRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, NewWOp,
17308 DAG.getValueType(MVT::i32));
17309 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, NewRes));
17310 }
17311
17312 break;
17313 }
17314 case ISD::ROTL:
17315 case ISD::ROTR:
17316 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
17317 "Unexpected custom legalisation");
17318 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
17319 Subtarget.hasVendorXTHeadBb()) &&
17320 "Unexpected custom legalization");
17321 if (!isa<ConstantSDNode>(N->getOperand(1)) &&
17322 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
17323 return;
17324 Results.push_back(customLegalizeToWOp(N, DAG));
17325 break;
17326 case ISD::CTTZ:
17328 case ISD::CTLZ:
17330 case ISD::CTLS: {
17331 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
17332 "Unexpected custom legalisation");
17333
17334 SDValue NewOp0 =
17335 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0));
17336 unsigned Opc;
17337 switch (N->getOpcode()) {
17338 default: llvm_unreachable("Unexpected opcode");
17339 case ISD::CTTZ:
17341 Opc = RISCVISD::CTZW;
17342 break;
17343 case ISD::CTLZ:
17345 Opc = RISCVISD::CLZW;
17346 break;
17347 case ISD::CTLS:
17348 Opc = RISCVISD::CLSW;
17349 break;
17350 }
17351
17352 SDValue Res = DAG.getNode(Opc, DL, MVT::i64, NewOp0);
17353 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
17354 return;
17355 }
17356 case ISD::SDIV:
17357 case ISD::UDIV:
17358 case ISD::UREM: {
17359 MVT VT = N->getSimpleValueType(0);
17360 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
17361 Subtarget.is64Bit() && Subtarget.hasStdExtM() &&
17362 "Unexpected custom legalisation");
17363 // Don't promote division/remainder by constant since we should expand those
17364 // to multiply by magic constant.
17366 if (N->getOperand(1).getOpcode() == ISD::Constant &&
17367 !isIntDivCheap(N->getValueType(0), Attr))
17368 return;
17369
17370 // If the input is i32, use ANY_EXTEND since the W instructions don't read
17371 // the upper 32 bits. For other types we need to sign or zero extend
17372 // based on the opcode.
17373 unsigned ExtOpc = ISD::ANY_EXTEND;
17374 if (VT != MVT::i32)
17375 ExtOpc = N->getOpcode() == ISD::SDIV ? ISD::SIGN_EXTEND
17377
17378 Results.push_back(customLegalizeToWOp(N, DAG, ExtOpc));
17379 break;
17380 }
17381 case ISD::SADDO:
17382 case ISD::SSUBO: {
17383 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
17384 "Unexpected custom legalisation");
17385
17386 // This is similar to the default legalization, but we return the
17387 // sext_inreg instead of the add/sub.
17388 bool IsAdd = N->getOpcode() == ISD::SADDO;
17389 SDValue LHS = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, N->getOperand(0));
17390 SDValue RHS = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, N->getOperand(1));
17391 SDValue Op =
17392 DAG.getNode(IsAdd ? ISD::ADD : ISD::SUB, DL, MVT::i64, LHS, RHS);
17393 SDValue Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, Op,
17394 DAG.getValueType(MVT::i32));
17395
17396 SDValue Overflow;
17397
17398 // If the RHS is a constant, we can simplify ConditionRHS below. Otherwise
17399 // use the default legalization.
17400 if (IsAdd && isa<ConstantSDNode>(N->getOperand(1))) {
17401 SDValue Zero = DAG.getConstant(0, DL, MVT::i64);
17402
17403 // For an addition, the result should be less than one of the operands
17404 // (LHS) if and only if the other operand (RHS) is negative, otherwise
17405 // there will be overflow.
17406 EVT OType = N->getValueType(1);
17407 SDValue ResultLowerThanLHS =
17408 DAG.getSetCC(DL, OType, Res, LHS, ISD::SETLT);
17409 SDValue ConditionRHS = DAG.getSetCC(DL, OType, RHS, Zero, ISD::SETLT);
17410
17411 Overflow =
17412 DAG.getNode(ISD::XOR, DL, OType, ConditionRHS, ResultLowerThanLHS);
17413 } else {
17414 Overflow = DAG.getSetCC(DL, N->getValueType(1), Res, Op, ISD::SETNE);
17415 }
17416
17417 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
17418 Results.push_back(Overflow);
17419 return;
17420 }
17421 case ISD::UADDO:
17422 case ISD::USUBO: {
17423 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
17424 "Unexpected custom legalisation");
17425 bool IsAdd = N->getOpcode() == ISD::UADDO;
17426 // Create an ADDW or SUBW.
17427 SDValue LHS = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0));
17428 SDValue RHS = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(1));
17429 SDValue Res =
17430 DAG.getNode(IsAdd ? ISD::ADD : ISD::SUB, DL, MVT::i64, LHS, RHS);
17431 Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, Res,
17432 DAG.getValueType(MVT::i32));
17433
17434 SDValue Overflow;
17435 if (IsAdd && isOneConstant(RHS)) {
17436 // Special case uaddo X, 1 overflowed if the addition result is 0.
17437 // The general case (X + C) < C is not necessarily beneficial. Although we
17438 // reduce the live range of X, we may introduce the materialization of
17439 // constant C, especially when the setcc result is used by branch. We have
17440 // no compare with constant and branch instructions.
17441 Overflow = DAG.getSetCC(DL, N->getValueType(1), Res,
17442 DAG.getConstant(0, DL, MVT::i64), ISD::SETEQ);
17443 } else if (IsAdd && isAllOnesConstant(RHS)) {
17444 // Special case uaddo X, -1 overflowed if X != 0.
17445 Overflow = DAG.getSetCC(DL, N->getValueType(1), N->getOperand(0),
17446 DAG.getConstant(0, DL, MVT::i32), ISD::SETNE);
17447 } else {
17448 // Sign extend the LHS and perform an unsigned compare with the ADDW
17449 // result. Since the inputs are sign extended from i32, this is equivalent
17450 // to comparing the lower 32 bits.
17451 LHS = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, N->getOperand(0));
17452 Overflow = DAG.getSetCC(DL, N->getValueType(1), Res, LHS,
17453 IsAdd ? ISD::SETULT : ISD::SETUGT);
17454 }
17455
17456 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
17457 Results.push_back(Overflow);
17458 return;
17459 }
17460 case ISD::UADDSAT:
17461 case ISD::USUBSAT:
17462 case ISD::SADDSAT:
17463 case ISD::SSUBSAT: {
17464 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
17465 "Unexpected custom legalisation");
17466
17467 if (Subtarget.hasStdExtP()) {
17468 // On RV64, map scalar i32 saturating add/sub through lane 0 of a packed
17469 // v2i32 operation so we can select ps*.w instructions.
17470 SDValue LHS = DAG.getNode(
17471 ISD::SCALAR_TO_VECTOR, DL, MVT::v2i32,
17472 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0)));
17473 SDValue RHS = DAG.getNode(
17474 ISD::SCALAR_TO_VECTOR, DL, MVT::v2i32,
17475 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(1)));
17476 SDValue VecRes = DAG.getNode(N->getOpcode(), DL, MVT::v2i32, LHS, RHS);
17477 SDValue Zero = DAG.getConstant(0, DL, Subtarget.getXLenVT());
17478 Results.push_back(
17479 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, VecRes, Zero));
17480 return;
17481 }
17482
17483 assert(!Subtarget.hasStdExtZbb() && "Unexpected custom legalisation");
17484 Results.push_back(expandAddSubSat(N, DAG));
17485 return;
17486 }
17487 case ISD::ABS:
17488 case ISD::ABS_MIN_POISON: {
17489 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
17490 "Unexpected custom legalisation");
17491
17492 if (Subtarget.hasStdExtP()) {
17493 SDValue Src =
17494 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0));
17495 SDValue Abs = DAG.getNode(RISCVISD::ABSW, DL, MVT::i64, Src);
17496 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Abs));
17497 return;
17498 }
17499
17500 if (Subtarget.hasStdExtZbb()) {
17501 // Emit a special node that will be expanded to NEGW+MAX at isel.
17502 // This allows us to remember that the result is sign extended. Expanding
17503 // to NEGW+MAX here requires a Freeze which breaks ComputeNumSignBits.
17504 SDValue Src = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64,
17505 N->getOperand(0));
17506 SDValue Abs = DAG.getNode(RISCVISD::NEGW_MAX, DL, MVT::i64, Src);
17507 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Abs));
17508 return;
17509 }
17510
17511 // Expand abs to Y = (sraiw X, 31); subw(xor(X, Y), Y)
17512 SDValue Src = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0));
17513
17514 // Freeze the source so we can increase it's use count.
17515 Src = DAG.getFreeze(Src);
17516
17517 // Copy sign bit to all bits using the sraiw pattern.
17518 SDValue SignFill = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, Src,
17519 DAG.getValueType(MVT::i32));
17520 SignFill = DAG.getNode(ISD::SRA, DL, MVT::i64, SignFill,
17521 DAG.getConstant(31, DL, MVT::i64));
17522
17523 SDValue NewRes = DAG.getNode(ISD::XOR, DL, MVT::i64, Src, SignFill);
17524 NewRes = DAG.getNode(ISD::SUB, DL, MVT::i64, NewRes, SignFill);
17525
17526 // NOTE: The result is only required to be anyextended, but sext is
17527 // consistent with type legalization of sub.
17528 NewRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, NewRes,
17529 DAG.getValueType(MVT::i32));
17530 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, NewRes));
17531 return;
17532 }
17533 case ISD::BITCAST: {
17534 EVT VT = N->getValueType(0);
17535 assert(VT.isInteger() && !VT.isVector() && "Unexpected VT!");
17536 SDValue Op0 = N->getOperand(0);
17537 EVT Op0VT = Op0.getValueType();
17538 MVT XLenVT = Subtarget.getXLenVT();
17539 if (VT == MVT::i16 &&
17540 ((Op0VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
17541 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
17542 SDValue FPConv = DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, XLenVT, Op0);
17543 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FPConv));
17544 } else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.is64Bit() &&
17545 Subtarget.hasStdExtFOrZfinx()) {
17546 SDValue FPConv =
17547 DAG.getNode(RISCVISD::FMV_X_ANYEXTW_RV64, DL, MVT::i64, Op0);
17548 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, FPConv));
17549 } else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.is64Bit() &&
17550 Subtarget.hasStdExtDOrZdinx()) {
17551 SDValue NewReg = DAG.getNode(RISCVISD::SplitF64, DL,
17552 DAG.getVTList(MVT::i32, MVT::i32), Op0);
17553 SDValue Lo = NewReg.getValue(0);
17554 SDValue Hi = NewReg.getValue(1);
17555 // For big-endian, swap the order when building the i64 pair.
17556 if (!Subtarget.isLittleEndian())
17557 std::swap(Lo, Hi);
17558 SDValue RetReg = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi);
17559 Results.push_back(RetReg);
17560 } else if (!VT.isVector() && Op0VT.isFixedLengthVector() &&
17561 isTypeLegal(Op0VT)) {
17562 // Custom-legalize bitcasts from fixed-length vector types to illegal
17563 // scalar types in order to improve codegen. Bitcast the vector to a
17564 // one-element vector type whose element type is the same as the result
17565 // type, and extract the first element.
17566 EVT BVT = EVT::getVectorVT(*DAG.getContext(), VT, 1);
17567 if (isTypeLegal(BVT)) {
17568 SDValue BVec = DAG.getBitcast(BVT, Op0);
17569 Results.push_back(DAG.getExtractVectorElt(DL, VT, BVec, 0));
17570 }
17571 }
17572 break;
17573 }
17574 case ISD::BITREVERSE: {
17575 assert(N->getValueType(0) == MVT::i8 && Subtarget.hasStdExtZbkb() &&
17576 "Unexpected custom legalisation");
17577 MVT XLenVT = Subtarget.getXLenVT();
17578 SDValue NewOp = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, N->getOperand(0));
17579 SDValue NewRes = DAG.getNode(RISCVISD::BREV8, DL, XLenVT, NewOp);
17580 // ReplaceNodeResults requires we maintain the same type for the return
17581 // value.
17582 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i8, NewRes));
17583 break;
17584 }
17585 case RISCVISD::BREV8:
17586 case RISCVISD::ORC_B: {
17587 MVT VT = N->getSimpleValueType(0);
17588 MVT XLenVT = Subtarget.getXLenVT();
17589 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
17590 "Unexpected custom legalisation");
17591 assert(((N->getOpcode() == RISCVISD::BREV8 && Subtarget.hasStdExtZbkb()) ||
17592 (N->getOpcode() == RISCVISD::ORC_B && Subtarget.hasStdExtZbb())) &&
17593 "Unexpected extension");
17594 SDValue NewOp = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, N->getOperand(0));
17595 SDValue NewRes = DAG.getNode(N->getOpcode(), DL, XLenVT, NewOp);
17596 // ReplaceNodeResults requires we maintain the same type for the return
17597 // value.
17598 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NewRes));
17599 break;
17600 }
17601 case RISCVISD::ASUB:
17602 case RISCVISD::ASUBU:
17603 case RISCVISD::MULHSU:
17604 case RISCVISD::MULHR:
17605 case RISCVISD::MULHRU:
17606 case RISCVISD::MULHRSU: {
17607 MVT VT = N->getSimpleValueType(0);
17608 SDValue Op0 = N->getOperand(0);
17609 SDValue Op1 = N->getOperand(1);
17610 unsigned Opcode = N->getOpcode();
17611 // PMULH* variants don't support i8
17612 [[maybe_unused]] bool IsMulH =
17613 Opcode == RISCVISD::MULHSU || Opcode == RISCVISD::MULHR ||
17614 Opcode == RISCVISD::MULHRU || Opcode == RISCVISD::MULHRSU;
17615 assert(VT == MVT::v2i16 || (!IsMulH && VT == MVT::v4i8));
17616 MVT NewVT = MVT::v4i16;
17617 if (VT == MVT::v4i8)
17618 NewVT = MVT::v8i8;
17619 SDValue Undef = DAG.getUNDEF(VT);
17620 Op0 = DAG.getNode(ISD::CONCAT_VECTORS, DL, NewVT, {Op0, Undef});
17621 Op1 = DAG.getNode(ISD::CONCAT_VECTORS, DL, NewVT, {Op1, Undef});
17622 Results.push_back(DAG.getNode(Opcode, DL, NewVT, {Op0, Op1}));
17623 return;
17624 }
17626 // Custom-legalize an EXTRACT_VECTOR_ELT where XLEN<SEW, as the SEW element
17627 // type is illegal (currently only vXi64 RV32).
17628 // With vmv.x.s, when SEW > XLEN, only the least-significant XLEN bits are
17629 // transferred to the destination register. We issue two of these from the
17630 // upper- and lower- halves of the SEW-bit vector element, slid down to the
17631 // first element.
17632 SDValue Vec = N->getOperand(0);
17633 SDValue Idx = N->getOperand(1);
17634
17635 // The vector type hasn't been legalized yet so we can't issue target
17636 // specific nodes if it needs legalization.
17637 // FIXME: We would manually legalize if it's important.
17638 if (!isTypeLegal(Vec.getValueType()))
17639 return;
17640
17641 MVT VecVT = Vec.getSimpleValueType();
17642
17643 assert(!Subtarget.is64Bit() && N->getValueType(0) == MVT::i64 &&
17644 VecVT.getVectorElementType() == MVT::i64 &&
17645 "Unexpected EXTRACT_VECTOR_ELT legalization");
17646
17647 // If this is a fixed vector, we need to convert it to a scalable vector.
17648 MVT ContainerVT = VecVT;
17649 if (VecVT.isFixedLengthVector()) {
17650 ContainerVT = getContainerForFixedLengthVector(VecVT);
17651 Vec = convertToScalableVector(ContainerVT, Vec, DAG, Subtarget);
17652 }
17653
17654 MVT XLenVT = Subtarget.getXLenVT();
17655
17656 // Use a VL of 1 to avoid processing more elements than we need.
17657 auto [Mask, VL] = getDefaultVLOps(1, ContainerVT, DL, DAG, Subtarget);
17658
17659 // Unless the index is known to be 0, we must slide the vector down to get
17660 // the desired element into index 0.
17661 if (!isNullConstant(Idx)) {
17662 Vec = getVSlidedown(DAG, Subtarget, DL, ContainerVT,
17663 DAG.getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
17664 }
17665
17666 // Extract the lower XLEN bits of the correct vector element.
17667 SDValue EltLo = DAG.getNode(RISCVISD::VMV_X_S, DL, XLenVT, Vec);
17668
17669 // To extract the upper XLEN bits of the vector element, shift the first
17670 // element right by 32 bits and re-extract the lower XLEN bits.
17671 SDValue ThirtyTwoV = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, ContainerVT,
17672 DAG.getUNDEF(ContainerVT),
17673 DAG.getConstant(32, DL, XLenVT), VL);
17674 SDValue LShr32 =
17675 DAG.getNode(RISCVISD::SRL_VL, DL, ContainerVT, Vec, ThirtyTwoV,
17676 DAG.getUNDEF(ContainerVT), Mask, VL);
17677
17678 SDValue EltHi = DAG.getNode(RISCVISD::VMV_X_S, DL, XLenVT, LShr32);
17679
17680 Results.push_back(DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, EltLo, EltHi));
17681 break;
17682 }
17684 unsigned IntNo = N->getConstantOperandVal(0);
17685 switch (IntNo) {
17686 default:
17688 "Don't know how to custom type legalize this intrinsic!");
17689 case Intrinsic::experimental_get_vector_length: {
17690 SDValue Res = lowerGetVectorLength(N, DAG, Subtarget);
17691 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
17692 return;
17693 }
17694 case Intrinsic::riscv_psext_h:
17695 reportFatalUsageError("unsupported llvm.riscv.psext intrinsic");
17696 case Intrinsic::riscv_pzext_h:
17697 reportFatalUsageError("unsupported llvm.riscv.pzext intrinsic");
17698 case Intrinsic::riscv_psext_b:
17699 case Intrinsic::riscv_pzext_b: {
17700 bool IsSExt = IntNo == Intrinsic::riscv_psext_b;
17701 const char *UnsupportedMsg =
17702 IsSExt ? "unsupported llvm.riscv.psext intrinsic"
17703 : "unsupported llvm.riscv.pzext intrinsic";
17704 EVT VT = N->getValueType(0);
17705 if (!Subtarget.is64Bit() || VT != MVT::v2i16)
17706 reportFatalUsageError(UnsupportedMsg);
17707
17708 SDValue Src = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16,
17709 N->getOperand(1), DAG.getUNDEF(VT));
17710 SDValue Res;
17711 if (IsSExt)
17712 Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::v4i16, Src,
17713 DAG.getValueType(MVT::v4i8));
17714 else
17715 Res = lowerPZExt(Src, DL, DAG, Subtarget);
17716 Results.push_back(DAG.getExtractSubvector(DL, VT, Res, 0));
17717 return;
17718 }
17719 case Intrinsic::riscv_pmhacc:
17720 case Intrinsic::riscv_pmhracc:
17721 case Intrinsic::riscv_pmhaccu:
17722 case Intrinsic::riscv_pmhraccu:
17723 case Intrinsic::riscv_pmhaccsu:
17724 case Intrinsic::riscv_pmhraccsu: {
17725 EVT VT = N->getValueType(0);
17726 if (!Subtarget.is64Bit() || VT != MVT::v2i16)
17727 return;
17728
17729 EVT WideVT = MVT::v4i16;
17730 SDValue Undef = DAG.getUNDEF(VT);
17731 SDValue Rd =
17732 DAG.getNode(ISD::CONCAT_VECTORS, DL, WideVT, N->getOperand(1), Undef);
17733 SDValue Rs1 =
17734 DAG.getNode(ISD::CONCAT_VECTORS, DL, WideVT, N->getOperand(2), Undef);
17735 SDValue Rs2 =
17736 DAG.getNode(ISD::CONCAT_VECTORS, DL, WideVT, N->getOperand(3), Undef);
17738 WideVT, Rd, Rs1, Rs2);
17739 Results.push_back(DAG.getExtractSubvector(DL, VT, Res, 0));
17740 return;
17741 }
17742 case Intrinsic::riscv_pmhacc_b0:
17743 case Intrinsic::riscv_pmhacc_b1:
17744 case Intrinsic::riscv_pmhaccsu_b0:
17745 case Intrinsic::riscv_pmhaccsu_b1: {
17746 // pmhacc.h.bXX operates on the whole register: v2i16 on RV32 and
17747 // v4i16 on RV64. On RV64 a v2i16 result widens to the packed v4i16
17748 // form and extracts the low half.
17749 EVT VT = N->getValueType(0);
17750 if (!Subtarget.is64Bit() || VT != MVT::v2i16)
17751 return;
17752
17753 EVT WideVT = MVT::v4i16;
17754 SDValue Undef = DAG.getUNDEF(VT);
17755 SDValue Rd =
17756 DAG.getNode(ISD::CONCAT_VECTORS, DL, WideVT, N->getOperand(1), Undef);
17757 SDValue Rs1 =
17758 DAG.getNode(ISD::CONCAT_VECTORS, DL, WideVT, N->getOperand(2), Undef);
17759 // Third operand is v4i8 - expand to v8i8
17760 SDValue Rs2 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i8,
17761 N->getOperand(3), DAG.getUNDEF(MVT::v4i8));
17763 DL, WideVT, Rd, Rs1, Rs2);
17764 Results.push_back(DAG.getExtractSubvector(DL, VT, Res, 0));
17765 return;
17766 }
17767 case Intrinsic::riscv_pm4add:
17768 case Intrinsic::riscv_pm2add:
17769 case Intrinsic::riscv_pm2add_x:
17770 case Intrinsic::riscv_pm4addu:
17771 case Intrinsic::riscv_pm2addu:
17772 case Intrinsic::riscv_pmq2add:
17773 case Intrinsic::riscv_pmqr2add:
17774 case Intrinsic::riscv_pm2sadd:
17775 case Intrinsic::riscv_pm2sadd_x:
17776 case Intrinsic::riscv_pm2sub:
17777 case Intrinsic::riscv_pm2sub_x:
17778 case Intrinsic::riscv_pm4addsu:
17779 case Intrinsic::riscv_pm2addsu: {
17780 MVT VT = N->getSimpleValueType(0);
17781 unsigned Opc = getRVPHorizontalMulOpcode(IntNo);
17782 SDValue Rs1 = N->getOperand(1);
17783 SDValue Rs2 = N->getOperand(2);
17784
17785 if (!Subtarget.is64Bit() && VT == MVT::i64) {
17786 SDValue Res = lowerRV32HorizontalMul64(IntNo, Rs1, Rs2, DL, DAG);
17787 Results.push_back(Res);
17788 return;
17789 }
17790
17791 assert(Subtarget.is64Bit() && VT == MVT::i32 &&
17792 "Unexpected horizontal multiply legalization");
17793 MVT SrcVT = Rs1.getSimpleValueType();
17794 MVT WideSrcVT = SrcVT == MVT::v4i8 ? MVT::v8i8 : MVT::v4i16;
17795 Rs1 = DAG.getNode(ISD::CONCAT_VECTORS, DL, WideSrcVT, Rs1,
17796 DAG.getUNDEF(SrcVT));
17797 Rs2 = DAG.getNode(ISD::CONCAT_VECTORS, DL, WideSrcVT, Rs2,
17798 DAG.getUNDEF(SrcVT));
17799 SDValue Wide = DAG.getNode(Opc, DL, MVT::v2i32, Rs1, Rs2);
17800 Results.push_back(DAG.getExtractVectorElt(DL, MVT::i32, Wide, 0));
17801 return;
17802 }
17803
17804 case Intrinsic::riscv_pmul_00:
17805 case Intrinsic::riscv_pmul_01:
17806 case Intrinsic::riscv_pmul_11:
17807 case Intrinsic::riscv_pmulu_00:
17808 case Intrinsic::riscv_pmulu_01:
17809 case Intrinsic::riscv_pmulu_11:
17810 case Intrinsic::riscv_pmulsu_00:
17811 case Intrinsic::riscv_pmulsu_11: {
17812 MVT VT = N->getSimpleValueType(0);
17813 if (!Subtarget.is64Bit() || VT != MVT::v2i16)
17814 return;
17815
17816 SDValue Undef = DAG.getUNDEF(MVT::v4i8);
17817 SDValue Rs1 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i8,
17818 N->getOperand(1), Undef);
17819 SDValue Rs2 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i8,
17820 N->getOperand(2), Undef);
17821 SDValue Res =
17822 DAG.getNode(getRVPMulHalvesOpcode(IntNo), DL, MVT::v4i16, Rs1, Rs2);
17823 Results.push_back(DAG.getExtractSubvector(DL, VT, Res, 0));
17824 return;
17825 }
17826 case Intrinsic::riscv_mul_00:
17827 case Intrinsic::riscv_mul_01:
17828 case Intrinsic::riscv_mul_11:
17829 case Intrinsic::riscv_mulu_00:
17830 case Intrinsic::riscv_mulu_01:
17831 case Intrinsic::riscv_mulu_11:
17832 case Intrinsic::riscv_mulsu_00:
17833 case Intrinsic::riscv_mulsu_11: {
17834 // mul.hXX exists only on RV32 and mul.wXX only on RV64; the other XLEN
17835 // has to build the product here.
17836 MVT VT = N->getSimpleValueType(0);
17837 MVT SrcVT = N->getOperand(1).getSimpleValueType();
17838 if (Subtarget.hasStdExtP() && Subtarget.is64Bit() && VT == MVT::i32 &&
17839 SrcVT == MVT::v2i16) {
17840 // The halfword product is the first element of the packed one.
17841 SDValue Undef = DAG.getUNDEF(SrcVT);
17842 SDValue Rs1 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16,
17843 N->getOperand(1), Undef);
17844 SDValue Rs2 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16,
17845 N->getOperand(2), Undef);
17846 SDValue Res =
17847 DAG.getNode(getRVPMulHalvesOpcode(IntNo), DL, MVT::v2i32, Rs1, Rs2);
17848 Results.push_back(DAG.getExtractVectorElt(DL, MVT::i32, Res, 0));
17849 return;
17850 }
17851 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit() && VT == MVT::i64 &&
17852 SrcVT == MVT::v2i32) {
17853 auto [Opc, Rs1Lane, Rs2Lane] = getRVPWordMulPartsOpcodeAndLanes(IntNo);
17854 SDValue Rs1 =
17855 DAG.getExtractVectorElt(DL, MVT::i32, N->getOperand(1), Rs1Lane);
17856 SDValue Rs2 =
17857 DAG.getExtractVectorElt(DL, MVT::i32, N->getOperand(2), Rs2Lane);
17858 SDValue Res =
17859 DAG.getNode(Opc, DL, DAG.getVTList(MVT::i32, MVT::i32), Rs1, Rs2);
17860 Results.push_back(
17861 DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Res, Res.getValue(1)));
17862 return;
17863 }
17864 reportFatalUsageError("unsupported llvm.riscv multiply-parts intrinsic");
17865 }
17866 case Intrinsic::riscv_pmulh_b0:
17867 case Intrinsic::riscv_pmulh_b1:
17868 case Intrinsic::riscv_pmulhsu_b0:
17869 case Intrinsic::riscv_pmulhsu_b1: {
17870 // A 32-bit result has no legal container on RV64; widen the result and
17871 // both sources to the 64-bit packed form.
17872 EVT VT = N->getValueType(0);
17873 if (!Subtarget.is64Bit() || VT != MVT::v2i16)
17874 return;
17875
17876 SDValue Undef = DAG.getUNDEF(VT);
17877 SDValue Rs1 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16,
17878 N->getOperand(1), Undef);
17879 SDValue Src2 = N->getOperand(2);
17880 SDValue Rs2 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i8, Src2,
17881 DAG.getUNDEF(Src2.getValueType()));
17882 SDValue Res = DAG.getNode(getRVPMulHighPartsOpcode(IntNo), DL, MVT::v4i16,
17883 Rs1, Rs2);
17884 Results.push_back(DAG.getExtractSubvector(DL, VT, Res, 0));
17885 return;
17886 }
17887 case Intrinsic::riscv_mulh_h0:
17888 case Intrinsic::riscv_mulh_h1:
17889 case Intrinsic::riscv_mulhsu_h0:
17890 case Intrinsic::riscv_mulhsu_h1: {
17891 // mulh.h0/h1 exist only on RV32 and pmulh.w.h0/h1 only on RV64; the
17892 // other XLEN has to build the product here.
17893 MVT VT = N->getSimpleValueType(0);
17894 MVT SrcVT = N->getOperand(2).getSimpleValueType();
17895 if (Subtarget.hasStdExtP() && Subtarget.is64Bit() && VT == MVT::i32 &&
17896 SrcVT == MVT::v2i16) {
17897 // The halfword product is the first element of the packed one.
17898 SDValue Rd = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2i32,
17899 N->getOperand(1));
17900 SDValue Undef = DAG.getUNDEF(SrcVT);
17901 SDValue Rs1 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16,
17902 N->getOperand(2), Undef);
17903 SDValue Res = DAG.getNode(getRVPMulHighPartsWOpcode(IntNo), DL,
17904 MVT::v2i32, Rd, Rs1);
17905 Results.push_back(DAG.getExtractVectorElt(DL, MVT::i32, Res, 0));
17906 return;
17907 }
17909 "unsupported llvm.riscv multiply-high-parts intrinsic");
17910 }
17911 case Intrinsic::riscv_macc_00:
17912 case Intrinsic::riscv_macc_01:
17913 case Intrinsic::riscv_macc_11:
17914 case Intrinsic::riscv_maccu_00:
17915 case Intrinsic::riscv_maccu_01:
17916 case Intrinsic::riscv_maccu_11:
17917 case Intrinsic::riscv_maccsu_00:
17918 case Intrinsic::riscv_maccsu_11: {
17919 // macc.hXX exists only on RV32 and macc.wXX only on RV64; the other XLEN
17920 // has to build the product here.
17921 MVT VT = N->getSimpleValueType(0);
17922 MVT SrcVT = N->getOperand(2).getSimpleValueType();
17923 if (Subtarget.hasStdExtP() && Subtarget.is64Bit() && VT == MVT::i32 &&
17924 SrcVT == MVT::v2i16) {
17925 // Accumulate into the first element of the packed product.
17926 SDValue Undef = DAG.getUNDEF(SrcVT);
17927 SDValue Rd = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2i32,
17928 N->getOperand(1));
17929 SDValue Rs1 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16,
17930 N->getOperand(2), Undef);
17931 SDValue Rs2 = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16,
17932 N->getOperand(3), Undef);
17933 SDValue Res = DAG.getNode(getRVPMulAccHalvesOpcode(IntNo), DL,
17934 MVT::v2i32, Rd, Rs1, Rs2);
17935 Results.push_back(DAG.getExtractVectorElt(DL, MVT::i32, Res, 0));
17936 return;
17937 }
17938 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit() && VT == MVT::i64 &&
17939 SrcVT == MVT::v2i32) {
17940 auto [Opc, Rs1Lane, Rs2Lane] =
17942 auto [RdLo, RdHi] =
17943 DAG.SplitScalar(N->getOperand(1), DL, MVT::i32, MVT::i32);
17944 SDValue Rs1 =
17945 DAG.getExtractVectorElt(DL, MVT::i32, N->getOperand(2), Rs1Lane);
17946 SDValue Rs2 =
17947 DAG.getExtractVectorElt(DL, MVT::i32, N->getOperand(3), Rs2Lane);
17948 SDValue Res = DAG.getNode(Opc, DL, DAG.getVTList(MVT::i32, MVT::i32),
17949 RdLo, RdHi, Rs1, Rs2);
17950 Results.push_back(
17951 DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Res, Res.getValue(1)));
17952 return;
17953 }
17954 reportFatalUsageError("unsupported llvm.riscv multiply-parts intrinsic");
17955 }
17956 case Intrinsic::riscv_paadd:
17957 case Intrinsic::riscv_paaddu:
17958 case Intrinsic::riscv_pasub:
17959 case Intrinsic::riscv_pasubu:
17960 case Intrinsic::riscv_pabd:
17961 case Intrinsic::riscv_pabdu:
17962 case Intrinsic::riscv_pas:
17963 case Intrinsic::riscv_psa:
17964 case Intrinsic::riscv_psas:
17965 case Intrinsic::riscv_pssa:
17966 case Intrinsic::riscv_paas:
17967 case Intrinsic::riscv_pasa:
17968 case Intrinsic::riscv_pmerge:
17969 case Intrinsic::riscv_pmulq:
17970 case Intrinsic::riscv_pmulqr:
17971 case Intrinsic::riscv_pmulhr:
17972 case Intrinsic::riscv_pmulhru:
17973 case Intrinsic::riscv_pmulhsu:
17974 case Intrinsic::riscv_pmulhrsu:
17975 case Intrinsic::riscv_psabs:
17976 case Intrinsic::riscv_psati:
17977 case Intrinsic::riscv_pusati: {
17978 EVT VT = N->getValueType(0);
17979 if (!Subtarget.is64Bit() || (VT != MVT::v4i8 && VT != MVT::v2i16))
17980 return;
17981
17982 unsigned Opc;
17983 switch (IntNo) {
17984 case Intrinsic::riscv_paadd:
17986 break;
17987 case Intrinsic::riscv_paaddu:
17989 break;
17990 case Intrinsic::riscv_pasub:
17991 Opc = RISCVISD::ASUB;
17992 break;
17993 case Intrinsic::riscv_pasubu:
17994 Opc = RISCVISD::ASUBU;
17995 break;
17996 case Intrinsic::riscv_pabd:
17997 Opc = ISD::ABDS;
17998 break;
17999 case Intrinsic::riscv_pabdu:
18000 Opc = ISD::ABDU;
18001 break;
18002 case Intrinsic::riscv_psabs:
18003 Opc = RISCVISD::PSABS;
18004 break;
18005 case Intrinsic::riscv_pmulq:
18006 Opc = RISCVISD::MULQ;
18007 break;
18008 case Intrinsic::riscv_pmulqr:
18009 Opc = RISCVISD::MULQR;
18010 break;
18011 case Intrinsic::riscv_pmulhr:
18012 case Intrinsic::riscv_pmulhru:
18013 case Intrinsic::riscv_pmulhsu:
18014 case Intrinsic::riscv_pmulhrsu:
18015 Opc = getRVPMulHighOpcode(IntNo);
18016 break;
18017 default:
18018 // pas/psa/psas/pssa/paas/pasa, pmerge and psati/pusati: re-emit at the
18019 // widened type rather than lowering to a generic node.
18021 break;
18022 }
18023
18024 EVT WideVT = VT == MVT::v4i8 ? MVT::v8i8 : MVT::v4i16;
18025 SDValue Undef = DAG.getUNDEF(VT);
18027 for (SDValue &Op : Ops) {
18028 if (Op.getValueType() == VT)
18029 Op = DAG.getNode(ISD::CONCAT_VECTORS, DL, WideVT, Op, Undef);
18030 }
18031 SDValue Res;
18033 Res = DAG.getNode(Opc, DL, WideVT, Ops);
18034 else
18035 Res = DAG.getNode(Opc, DL, WideVT, ArrayRef(Ops).slice(1));
18036 Results.push_back(DAG.getExtractSubvector(DL, VT, Res, 0));
18037 return;
18038 }
18039 case Intrinsic::riscv_mulhr_i32:
18040 case Intrinsic::riscv_mulhru_u32:
18041 case Intrinsic::riscv_mulhsu_i32:
18042 case Intrinsic::riscv_mulhrsu_i32: {
18043 // RV64 has no scalar mulh instructions; reuse the packed pmulh.w
18044 // family on the low words, whose element 0 is the scalar product.
18045 MVT VT = N->getSimpleValueType(0);
18046 if (!Subtarget.is64Bit() || VT != MVT::i32)
18047 return;
18048 unsigned Opc = getRVScalarMulHighOpcode(IntNo);
18049 SDValue Rs1 =
18050 DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2i32, N->getOperand(1));
18051 SDValue Rs2 =
18052 DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2i32, N->getOperand(2));
18053 SDValue Res = DAG.getNode(Opc, DL, MVT::v2i32, Rs1, Rs2);
18054 Results.push_back(DAG.getExtractVectorElt(DL, MVT::i32, Res, 0));
18055 return;
18056 }
18057 case Intrinsic::riscv_pnclipp:
18058 case Intrinsic::riscv_pnclipup: {
18059 bool IsSigned = IntNo == Intrinsic::riscv_pnclipp;
18060 EVT VT = N->getValueType(0);
18061 if (!Subtarget.is64Bit() || (VT != MVT::v4i8 && VT != MVT::v2i16))
18062 return;
18063 unsigned Opc = IsSigned ? RISCVISD::PNCLIPP : RISCVISD::PNCLIPUP;
18064 SDValue Src1 = N->getOperand(1);
18065 SDValue Src2 = N->getOperand(2);
18066 if (VT == MVT::v4i8) {
18067 MVT WideSrcVT = MVT::v4i16;
18068 SDValue Packed =
18069 DAG.getNode(ISD::CONCAT_VECTORS, DL, WideSrcVT, {Src1, Src2});
18070 SDValue Res = DAG.getNode(Opc, DL, MVT::v8i8, {Packed, Packed});
18071 Results.push_back(DAG.getExtractSubvector(DL, VT, Res, 0));
18072 } else {
18073 MVT WideSrcVT = MVT::v2i32;
18074 SDValue Packed =
18075 DAG.getNode(ISD::BUILD_VECTOR, DL, WideSrcVT, {Src1, Src2});
18076 SDValue Res = DAG.getNode(Opc, DL, MVT::v4i16, {Packed, Packed});
18077 Results.push_back(DAG.getExtractSubvector(DL, VT, Res, 0));
18078 }
18079 return;
18080 }
18081 case Intrinsic::riscv_psll:
18082 case Intrinsic::riscv_psrl:
18083 case Intrinsic::riscv_psra:
18084 case Intrinsic::riscv_pssha:
18085 case Intrinsic::riscv_psshar:
18086 case Intrinsic::riscv_psshl:
18087 case Intrinsic::riscv_psshlr: {
18088 MVT VT = N->getSimpleValueType(0);
18089 if (!Subtarget.is64Bit() || (VT != MVT::v4i8 && VT != MVT::v2i16))
18090 return;
18091
18092 EVT WideVT = VT == MVT::v4i8 ? MVT::v8i8 : MVT::v4i16;
18093 SDValue Op0 = DAG.getNode(ISD::CONCAT_VECTORS, DL, WideVT,
18094 N->getOperand(1), DAG.getUNDEF(VT));
18095 SDValue ShAmt = N->getOperand(2);
18096 ShAmt = DAG.getAnyExtOrTrunc(ShAmt, DL, Subtarget.getXLenVT());
18097 SDValue Res =
18098 DAG.getNode(getRVPShiftOpcode(IntNo), DL, WideVT, Op0, ShAmt);
18099 Results.push_back(DAG.getExtractSubvector(DL, VT, Res, 0));
18100 return;
18101 }
18102 case Intrinsic::riscv_pnsrl:
18103 case Intrinsic::riscv_pnsra:
18104 case Intrinsic::riscv_pnsrar: {
18105 MVT VT = N->getSimpleValueType(0);
18106 if (!Subtarget.is64Bit() || (VT != MVT::v4i8 && VT != MVT::v2i16))
18107 return;
18108
18109 SDValue Src = N->getOperand(1);
18110 MVT SrcVT = Src.getSimpleValueType();
18111 if (!((VT == MVT::v4i8 && SrcVT == MVT::v4i16) ||
18112 (VT == MVT::v2i16 && SrcVT == MVT::v2i32)))
18113 reportFatalUsageError("unsupported packed narrowing shift intrinsic");
18114
18115 MVT XLenVT = Subtarget.getXLenVT();
18116 SDValue ShAmt =
18117 DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, N->getOperand(2));
18118 unsigned Opc;
18119 switch (IntNo) {
18120 default:
18121 llvm_unreachable("Unexpected packed narrowing shift intrinsic");
18122 case Intrinsic::riscv_pnsrl:
18123 Opc = RISCVISD::PSRL;
18124 break;
18125 case Intrinsic::riscv_pnsra:
18126 Opc = RISCVISD::PSRA;
18127 break;
18128 case Intrinsic::riscv_pnsrar:
18129 Opc = RISCVISD::PSSHAR;
18130 ShAmt = DAG.getNode(ISD::AND, DL, XLenVT, ShAmt,
18131 DAG.getConstant(31, DL, XLenVT));
18132 ShAmt = DAG.getNegative(ShAmt, DL, XLenVT);
18133 break;
18134 }
18135
18136 SDValue Shifted = DAG.getNode(Opc, DL, SrcVT, Src, ShAmt);
18137 MVT UnzipVT = VT == MVT::v4i8 ? MVT::v8i8 : MVT::v4i16;
18138 Shifted = DAG.getBitcast(UnzipVT, Shifted);
18139 SDValue Unzip = DAG.getNode(RISCVISD::PUNZIPE, DL, UnzipVT, Shifted,
18140 DAG.getUNDEF(UnzipVT));
18141 Results.push_back(DAG.getExtractSubvector(DL, VT, Unzip, 0));
18142 return;
18143 }
18144 case Intrinsic::riscv_predsum:
18145 case Intrinsic::riscv_predsumu: {
18146 bool IsSigned = IntNo == Intrinsic::riscv_predsum;
18147 SDValue Vec = N->getOperand(1);
18148 MVT VecVT = Vec.getSimpleValueType();
18149 auto Ext = [&](SDValue V) {
18150 return DAG.getNode(IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, DL,
18151 MVT::i64, V);
18152 };
18153 auto RedSum = [&](MVT VT, SDValue V, SDValue Acc) {
18154 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, N->getOperand(0), V,
18155 Acc);
18156 };
18157
18158 // RV32: i64 accumulator. Reduce to a 32-bit partial sum, then
18159 // widening-accumulate into i64 via wadda/waddau (v2i32 uses wadda alone).
18160 if (!Subtarget.is64Bit() && N->getValueType(0) == MVT::i64) {
18161 SDValue Acc = N->getOperand(2);
18162 SDValue Res;
18163 if (VecVT == MVT::v2i32) {
18164 Res = DAG.getNode(ISD::ADD, DL, MVT::i64, Acc,
18165 Ext(DAG.getExtractVectorElt(DL, MVT::i32, Vec, 0)));
18166 Res = DAG.getNode(ISD::ADD, DL, MVT::i64, Res,
18167 Ext(DAG.getExtractVectorElt(DL, MVT::i32, Vec, 1)));
18168 } else {
18169 // The paired predsum.dbs/dhs computes the 32-bit element sum.
18170 SDValue Partial =
18171 RedSum(MVT::i32, Vec, DAG.getConstant(0, DL, MVT::i32));
18172 Res = DAG.getNode(ISD::ADD, DL, MVT::i64, Acc, Ext(Partial));
18173 }
18174 Results.push_back(Res);
18175 return;
18176 }
18177
18178 // RV64: i32 accumulator. Reduce at i64 (XLEN), then truncate.
18179 if (!Subtarget.is64Bit() || N->getValueType(0) != MVT::i32)
18180 return;
18181
18182 // Zero the upper lanes (zext.w) so they don't contribute to the sum.
18183 if (VecVT == MVT::v4i8 || VecVT == MVT::v2i16)
18185 DAG, DL, Vec, VecVT == MVT::v4i8 ? MVT::v8i8 : MVT::v4i16);
18186
18187 // The result is truncated to i32, so the accumulator's upper bits are
18188 // unused and need no sign/zero extension.
18189 SDValue Acc =
18190 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(2));
18191 SDValue Res = RedSum(MVT::i64, Vec, Acc);
18192 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
18193 return;
18194 }
18195 case Intrinsic::riscv_pabdsumu:
18196 case Intrinsic::riscv_pabdsumau: {
18197 bool IsAcc = IntNo == Intrinsic::riscv_pabdsumau;
18198 // The two packed sources (rs1, rs2) are the last two operands.
18199 SDValue Rs1 = N->getOperand(N->getNumOperands() - 2);
18200 SDValue Rs2 = N->getOperand(N->getNumOperands() - 1);
18201 MVT VecVT = Rs1.getSimpleValueType();
18202
18203 // RV32: i64 result, always from a v8i8 source. The accumulator, if any,
18204 // folds into the widening add below.
18205 if (!Subtarget.is64Bit() && N->getValueType(0) == MVT::i64) {
18206 // Sum of absolute differences of two v4i8 halves.
18207 auto Sad = [&](SDValue A, SDValue B) {
18208 SDValue S = DAG.getNode(
18209 ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
18210 DAG.getTargetConstant(Intrinsic::riscv_pabdsumu, DL, MVT::i32), A,
18211 B);
18212 return DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, S);
18213 };
18214 auto [Rs1Lo, Rs1Hi] = DAG.SplitVector(Rs1, DL);
18215 auto [Rs2Lo, Rs2Hi] = DAG.SplitVector(Rs2, DL);
18216 SDValue Lo = Sad(Rs1Lo, Rs2Lo);
18217 SDValue Hi = Sad(Rs1Hi, Rs2Hi);
18218 // (acc + lo) + hi keeps the accumulate chained so it folds into a
18219 // single waddau; without an accumulator lo + hi folds into waddu.
18220 SDValue Res =
18221 IsAcc ? DAG.getNode(ISD::ADD, DL, MVT::i64, N->getOperand(1), Lo)
18222 : Lo;
18223 Res = DAG.getNode(ISD::ADD, DL, MVT::i64, Res, Hi);
18224 Results.push_back(Res);
18225 return;
18226 }
18227
18228 // RV64: i32 result, so reduce at i64 and truncate. The source is v4i8 or
18229 // v8i8; widen a v4i8 to v8i8, zeroing the upper bytes (v8i8 is legal).
18230 if (!Subtarget.is64Bit() || N->getValueType(0) != MVT::i32)
18231 return;
18232 if (VecVT == MVT::v4i8) {
18233 Rs1 = widenPackedVectorWithZeros(DAG, DL, Rs1, MVT::v8i8);
18234 Rs2 = widenPackedVectorWithZeros(DAG, DL, Rs2, MVT::v8i8);
18235 }
18236 SmallVector<SDValue, 4> Ops = {N->getOperand(0)};
18237 if (IsAcc)
18238 Ops.push_back(
18239 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(1)));
18240 Ops.push_back(Rs1);
18241 Ops.push_back(Rs2);
18242 SDValue Res = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i64, Ops);
18243 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
18244 return;
18245 }
18246 case Intrinsic::riscv_mqacc_00:
18247 case Intrinsic::riscv_mqacc_01:
18248 case Intrinsic::riscv_mqacc_11:
18249 case Intrinsic::riscv_mqracc_00:
18250 case Intrinsic::riscv_mqracc_01:
18251 case Intrinsic::riscv_mqracc_11: {
18252 EVT VT = N->getValueType(0);
18253 if (Subtarget.is64Bit() && VT == MVT::i32) {
18254 SDValue Rd = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v2i32,
18255 N->getOperand(1));
18256 auto WidenSrc = [&](SDValue V) {
18257 return DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4i16,
18258 {V, DAG.getUNDEF(MVT::v2i16)});
18259 };
18260 SDValue Rs1 = WidenSrc(N->getOperand(2));
18261 SDValue Rs2 = WidenSrc(N->getOperand(3));
18262 unsigned Opc = getRVPQFormatAccOpcode(IntNo);
18263 SDValue Res = DAG.getNode(Opc, DL, MVT::v2i32, Rd, Rs1, Rs2);
18264 Results.push_back(DAG.getExtractVectorElt(DL, MVT::i32, Res, 0));
18265 return;
18266 }
18267
18268 if (!Subtarget.is64Bit() && VT == MVT::i64) {
18269 bool IsRound = IntNo == Intrinsic::riscv_mqracc_00 ||
18270 IntNo == Intrinsic::riscv_mqracc_01 ||
18271 IntNo == Intrinsic::riscv_mqracc_11;
18272 bool Hi1 = IntNo == Intrinsic::riscv_mqacc_11 ||
18273 IntNo == Intrinsic::riscv_mqracc_11;
18274 bool Hi2 = IntNo == Intrinsic::riscv_mqacc_01 ||
18275 IntNo == Intrinsic::riscv_mqacc_11 ||
18276 IntNo == Intrinsic::riscv_mqracc_01 ||
18277 IntNo == Intrinsic::riscv_mqracc_11;
18278 MVT XLenVT = Subtarget.getXLenVT();
18279 SDValue Rs1 = N->getOperand(2);
18280 SDValue Rs2 = N->getOperand(3);
18281 SDValue A = DAG.getExtractVectorElt(DL, XLenVT, Rs1, Hi1 ? 1 : 0);
18282 SDValue B = DAG.getExtractVectorElt(DL, XLenVT, Rs2, Hi2 ? 1 : 0);
18283 auto [RdLo, RdHi] =
18284 DAG.SplitScalar(N->getOperand(1), DL, XLenVT, XLenVT);
18285 unsigned Opc = IsRound ? RISCVISD::MQRWACC : RISCVISD::MQWACC;
18286 SDVTList VTs = DAG.getVTList(XLenVT, XLenVT);
18287 SDValue Acc = DAG.getNode(Opc, DL, VTs, {RdLo, RdHi, A, B});
18288 Results.push_back(DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64,
18289 Acc.getValue(0), Acc.getValue(1)));
18290 return;
18291 }
18292 return;
18293 }
18294 case Intrinsic::riscv_orc_b:
18295 case Intrinsic::riscv_brev8:
18296 case Intrinsic::riscv_sha256sig0:
18297 case Intrinsic::riscv_sha256sig1:
18298 case Intrinsic::riscv_sha256sum0:
18299 case Intrinsic::riscv_sha256sum1:
18300 case Intrinsic::riscv_sm3p0:
18301 case Intrinsic::riscv_sm3p1: {
18302 if (!Subtarget.is64Bit() || N->getValueType(0) != MVT::i32)
18303 return;
18304 unsigned Opc;
18305 switch (IntNo) {
18306 case Intrinsic::riscv_orc_b: Opc = RISCVISD::ORC_B; break;
18307 case Intrinsic::riscv_brev8: Opc = RISCVISD::BREV8; break;
18308 case Intrinsic::riscv_sha256sig0: Opc = RISCVISD::SHA256SIG0; break;
18309 case Intrinsic::riscv_sha256sig1: Opc = RISCVISD::SHA256SIG1; break;
18310 case Intrinsic::riscv_sha256sum0: Opc = RISCVISD::SHA256SUM0; break;
18311 case Intrinsic::riscv_sha256sum1: Opc = RISCVISD::SHA256SUM1; break;
18312 case Intrinsic::riscv_sm3p0: Opc = RISCVISD::SM3P0; break;
18313 case Intrinsic::riscv_sm3p1: Opc = RISCVISD::SM3P1; break;
18314 }
18315
18316 SDValue NewOp =
18317 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(1));
18318 SDValue Res = DAG.getNode(Opc, DL, MVT::i64, NewOp);
18319 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
18320 return;
18321 }
18322 case Intrinsic::riscv_sm4ks:
18323 case Intrinsic::riscv_sm4ed: {
18324 unsigned Opc =
18325 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
18326 SDValue NewOp0 =
18327 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(1));
18328 SDValue NewOp1 =
18329 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(2));
18330 SDValue Res =
18331 DAG.getNode(Opc, DL, MVT::i64, NewOp0, NewOp1, N->getOperand(3));
18332 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
18333 return;
18334 }
18335 case Intrinsic::riscv_mopr: {
18336 if (!Subtarget.is64Bit() || N->getValueType(0) != MVT::i32)
18337 return;
18338 SDValue NewOp =
18339 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(1));
18340 SDValue Res = DAG.getNode(
18341 RISCVISD::MOP_R, DL, MVT::i64, NewOp,
18342 DAG.getTargetConstant(N->getConstantOperandVal(2), DL, MVT::i64));
18343 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
18344 return;
18345 }
18346 case Intrinsic::riscv_moprr: {
18347 if (!Subtarget.is64Bit() || N->getValueType(0) != MVT::i32)
18348 return;
18349 SDValue NewOp0 =
18350 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(1));
18351 SDValue NewOp1 =
18352 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(2));
18353 SDValue Res = DAG.getNode(
18354 RISCVISD::MOP_RR, DL, MVT::i64, NewOp0, NewOp1,
18355 DAG.getTargetConstant(N->getConstantOperandVal(3), DL, MVT::i64));
18356 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
18357 return;
18358 }
18359 case Intrinsic::riscv_clmulh:
18360 case Intrinsic::riscv_clmulr: {
18361 if (!Subtarget.is64Bit() || N->getValueType(0) != MVT::i32)
18362 return;
18363
18364 // Extend inputs to XLen, and shift by 32. This will add 64 trailing zeros
18365 // to the full 128-bit clmul result of multiplying two xlen values.
18366 // Perform clmulr or clmulh on the shifted values. Finally, extract the
18367 // upper 32 bits.
18368 //
18369 // The alternative is to mask the inputs to 32 bits and use clmul, but
18370 // that requires two shifts to mask each input without zext.w.
18371 // FIXME: If the inputs are known zero extended or could be freely
18372 // zero extended, the mask form would be better.
18373 SDValue NewOp0 =
18374 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(1));
18375 SDValue NewOp1 =
18376 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(2));
18377 NewOp0 = DAG.getNode(ISD::SHL, DL, MVT::i64, NewOp0,
18378 DAG.getConstant(32, DL, MVT::i64));
18379 NewOp1 = DAG.getNode(ISD::SHL, DL, MVT::i64, NewOp1,
18380 DAG.getConstant(32, DL, MVT::i64));
18381 unsigned Opc =
18382 IntNo == Intrinsic::riscv_clmulh ? ISD::CLMULH : ISD::CLMULR;
18383 SDValue Res = DAG.getNode(Opc, DL, MVT::i64, NewOp0, NewOp1);
18384 Res = DAG.getNode(ISD::SRL, DL, MVT::i64, Res,
18385 DAG.getConstant(32, DL, MVT::i64));
18386 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
18387 return;
18388 }
18389 case Intrinsic::riscv_vmv_x_s: {
18390 EVT VT = N->getValueType(0);
18391 MVT XLenVT = Subtarget.getXLenVT();
18392 if (VT.bitsLT(XLenVT)) {
18393 // Simple case just extract using vmv.x.s and truncate.
18394 SDValue Extract = DAG.getNode(RISCVISD::VMV_X_S, DL,
18395 Subtarget.getXLenVT(), N->getOperand(1));
18396 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, Extract));
18397 return;
18398 }
18399
18400 assert(VT == MVT::i64 && !Subtarget.is64Bit() &&
18401 "Unexpected custom legalization");
18402
18403 // We need to do the move in two steps.
18404 SDValue Vec = N->getOperand(1);
18405 MVT VecVT = Vec.getSimpleValueType();
18406
18407 // First extract the lower XLEN bits of the element.
18408 SDValue EltLo = DAG.getNode(RISCVISD::VMV_X_S, DL, XLenVT, Vec);
18409
18410 // To extract the upper XLEN bits of the vector element, shift the first
18411 // element right by 32 bits and re-extract the lower XLEN bits.
18412 auto [Mask, VL] = getDefaultVLOps(1, VecVT, DL, DAG, Subtarget);
18413
18414 SDValue ThirtyTwoV =
18415 DAG.getNode(RISCVISD::VMV_V_X_VL, DL, VecVT, DAG.getUNDEF(VecVT),
18416 DAG.getConstant(32, DL, XLenVT), VL);
18417 SDValue LShr32 = DAG.getNode(RISCVISD::SRL_VL, DL, VecVT, Vec, ThirtyTwoV,
18418 DAG.getUNDEF(VecVT), Mask, VL);
18419 SDValue EltHi = DAG.getNode(RISCVISD::VMV_X_S, DL, XLenVT, LShr32);
18420
18421 Results.push_back(
18422 DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, EltLo, EltHi));
18423 break;
18424 }
18425 }
18426 break;
18427 }
18428 case ISD::VECREDUCE_ADD:
18429 case ISD::VECREDUCE_AND:
18430 case ISD::VECREDUCE_OR:
18431 case ISD::VECREDUCE_XOR:
18436 if (SDValue V = lowerVECREDUCE(SDValue(N, 0), DAG))
18437 Results.push_back(V);
18438 break;
18439 case ISD::VP_REDUCE_ADD:
18440 case ISD::VP_REDUCE_AND:
18441 case ISD::VP_REDUCE_OR:
18442 case ISD::VP_REDUCE_XOR:
18443 case ISD::VP_REDUCE_SMAX:
18444 case ISD::VP_REDUCE_UMAX:
18445 case ISD::VP_REDUCE_SMIN:
18446 case ISD::VP_REDUCE_UMIN:
18447 if (SDValue V = lowerVPREDUCE(SDValue(N, 0), DAG))
18448 Results.push_back(V);
18449 break;
18450 case ISD::GET_ROUNDING: {
18451 SDVTList VTs = DAG.getVTList(Subtarget.getXLenVT(), MVT::Other);
18452 SDValue Res = DAG.getNode(ISD::GET_ROUNDING, DL, VTs, N->getOperand(0));
18453 Results.push_back(Res.getValue(0));
18454 Results.push_back(Res.getValue(1));
18455 break;
18456 }
18457 }
18458}
18459
18460/// Given a binary operator, return the *associative* generic ISD::VECREDUCE_OP
18461/// which corresponds to it.
18462static unsigned getVecReduceOpcode(unsigned Opc) {
18463 switch (Opc) {
18464 default:
18465 llvm_unreachable("Unhandled binary to transform reduction");
18466 case ISD::ADD:
18467 return ISD::VECREDUCE_ADD;
18468 case ISD::UMAX:
18469 return ISD::VECREDUCE_UMAX;
18470 case ISD::SMAX:
18471 return ISD::VECREDUCE_SMAX;
18472 case ISD::UMIN:
18473 return ISD::VECREDUCE_UMIN;
18474 case ISD::SMIN:
18475 return ISD::VECREDUCE_SMIN;
18476 case ISD::AND:
18477 return ISD::VECREDUCE_AND;
18478 case ISD::OR:
18479 return ISD::VECREDUCE_OR;
18480 case ISD::XOR:
18481 return ISD::VECREDUCE_XOR;
18482 case ISD::FADD:
18483 // Note: This is the associative form of the generic reduction opcode.
18484 return ISD::VECREDUCE_FADD;
18485 case ISD::FMAXNUM:
18486 return ISD::VECREDUCE_FMAX;
18487 case ISD::FMINNUM:
18488 return ISD::VECREDUCE_FMIN;
18489 }
18490}
18491
18492/// Perform two related transforms whose purpose is to incrementally recognize
18493/// an explode_vector followed by scalar reduction as a vector reduction node.
18494/// This exists to recover from a deficiency in SLP which can't handle
18495/// forests with multiple roots sharing common nodes. In some cases, one
18496/// of the trees will be vectorized, and the other will remain (unprofitably)
18497/// scalarized.
18498static SDValue
18500 const RISCVSubtarget &Subtarget) {
18501
18502 // This transforms need to run before all integer types have been legalized
18503 // to i64 (so that the vector element type matches the add type), and while
18504 // it's safe to introduce odd sized vector types.
18506 return SDValue();
18507
18508 // Without V, this transform isn't useful. We could form the (illegal)
18509 // operations and let them be scalarized again, but there's really no point.
18510 if (!Subtarget.hasVInstructions())
18511 return SDValue();
18512
18513 const SDLoc DL(N);
18514 const EVT VT = N->getValueType(0);
18515 const unsigned Opc = N->getOpcode();
18516
18517 if (!VT.isInteger()) {
18518 switch (Opc) {
18519 default:
18520 return SDValue();
18521 case ISD::FADD:
18522 // For FADD, we only handle the case with reassociation allowed. We
18523 // could handle strict reduction order, but at the moment, there's no
18524 // known reason to, and the complexity isn't worth it.
18525 if (!N->getFlags().hasAllowReassociation())
18526 return SDValue();
18527 break;
18528 case ISD::FMAXNUM:
18529 case ISD::FMINNUM:
18530 break;
18531 }
18532 }
18533
18534 const unsigned ReduceOpc = getVecReduceOpcode(Opc);
18535 assert(Opc == ISD::getVecReduceBaseOpcode(ReduceOpc) &&
18536 "Inconsistent mappings");
18537 SDValue LHS = N->getOperand(0);
18538 SDValue RHS = N->getOperand(1);
18539
18540 if (!LHS.hasOneUse() || !RHS.hasOneUse())
18541 return SDValue();
18542
18543 if (RHS.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
18544 std::swap(LHS, RHS);
18545
18546 if (RHS.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
18547 !isa<ConstantSDNode>(RHS.getOperand(1)))
18548 return SDValue();
18549
18550 uint64_t RHSIdx = cast<ConstantSDNode>(RHS.getOperand(1))->getLimitedValue();
18551 SDValue SrcVec = RHS.getOperand(0);
18552 EVT SrcVecVT = SrcVec.getValueType();
18553 if (SrcVecVT.getVectorElementType() != VT)
18554 return SDValue();
18555 if (SrcVecVT.isScalableVector())
18556 return SDValue();
18557
18558 if (SrcVecVT.getScalarSizeInBits() > Subtarget.getELen())
18559 return SDValue();
18560
18561 // match binop (extract_vector_elt V, 0), (extract_vector_elt V, 1) to
18562 // reduce_op (extract_subvector [2 x VT] from V). This will form the
18563 // root of our reduction tree. TODO: We could extend this to any two
18564 // adjacent aligned constant indices if desired.
18565 if (LHS.getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
18566 LHS.getOperand(0) == SrcVec && isa<ConstantSDNode>(LHS.getOperand(1))) {
18567 uint64_t LHSIdx =
18568 cast<ConstantSDNode>(LHS.getOperand(1))->getLimitedValue();
18569 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
18570 EVT ReduceVT = EVT::getVectorVT(*DAG.getContext(), VT, 2);
18571 SDValue Vec = DAG.getExtractSubvector(DL, ReduceVT, SrcVec, 0);
18572 return DAG.getNode(ReduceOpc, DL, VT, Vec, N->getFlags());
18573 }
18574 }
18575
18576 // Match (binop (reduce (extract_subvector V, 0),
18577 // (extract_vector_elt V, sizeof(SubVec))))
18578 // into a reduction of one more element from the original vector V.
18579 if (LHS.getOpcode() != ReduceOpc)
18580 return SDValue();
18581
18582 SDValue ReduceVec = LHS.getOperand(0);
18583 if (ReduceVec.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
18584 ReduceVec.hasOneUse() && ReduceVec.getOperand(0) == RHS.getOperand(0) &&
18585 isNullConstant(ReduceVec.getOperand(1)) &&
18586 ReduceVec.getValueType().getVectorNumElements() == RHSIdx) {
18587 // For illegal types (e.g. 3xi32), most will be combined again into a
18588 // wider (hopefully legal) type. If this is a terminal state, we are
18589 // relying on type legalization here to produce something reasonable
18590 // and this lowering quality could probably be improved. (TODO)
18591 EVT ReduceVT = EVT::getVectorVT(*DAG.getContext(), VT, RHSIdx + 1);
18592 SDValue Vec = DAG.getExtractSubvector(DL, ReduceVT, SrcVec, 0);
18593 return DAG.getNode(ReduceOpc, DL, VT, Vec,
18594 ReduceVec->getFlags() & N->getFlags());
18595 }
18596
18597 return SDValue();
18598}
18599
18600
18601// Try to fold (<bop> x, (reduction.<bop> vec, start))
18603 const RISCVSubtarget &Subtarget) {
18604 auto BinOpToRVVReduce = [](unsigned Opc) {
18605 switch (Opc) {
18606 default:
18607 llvm_unreachable("Unhandled binary to transform reduction");
18608 case ISD::ADD:
18609 return RISCVISD::VECREDUCE_ADD_VL;
18610 case ISD::UMAX:
18611 return RISCVISD::VECREDUCE_UMAX_VL;
18612 case ISD::SMAX:
18613 return RISCVISD::VECREDUCE_SMAX_VL;
18614 case ISD::UMIN:
18615 return RISCVISD::VECREDUCE_UMIN_VL;
18616 case ISD::SMIN:
18617 return RISCVISD::VECREDUCE_SMIN_VL;
18618 case ISD::AND:
18619 return RISCVISD::VECREDUCE_AND_VL;
18620 case ISD::OR:
18621 return RISCVISD::VECREDUCE_OR_VL;
18622 case ISD::XOR:
18623 return RISCVISD::VECREDUCE_XOR_VL;
18624 case ISD::FADD:
18625 return RISCVISD::VECREDUCE_FADD_VL;
18626 case ISD::FMAXNUM:
18627 return RISCVISD::VECREDUCE_FMAX_VL;
18628 case ISD::FMINNUM:
18629 return RISCVISD::VECREDUCE_FMIN_VL;
18630 }
18631 };
18632
18633 auto IsReduction = [&BinOpToRVVReduce](SDValue V, unsigned Opc) {
18634 return V.getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
18635 isNullConstant(V.getOperand(1)) &&
18636 V.getOperand(0).getOpcode() == BinOpToRVVReduce(Opc);
18637 };
18638
18639 unsigned Opc = N->getOpcode();
18640 unsigned ReduceIdx;
18641 if (IsReduction(N->getOperand(0), Opc))
18642 ReduceIdx = 0;
18643 else if (IsReduction(N->getOperand(1), Opc))
18644 ReduceIdx = 1;
18645 else
18646 return SDValue();
18647
18648 // Skip if FADD disallows reassociation but the combiner needs.
18649 if (Opc == ISD::FADD && !N->getFlags().hasAllowReassociation())
18650 return SDValue();
18651
18652 SDValue Extract = N->getOperand(ReduceIdx);
18653 SDValue Reduce = Extract.getOperand(0);
18654 if (!Extract.hasOneUse() || !Reduce.hasOneUse())
18655 return SDValue();
18656
18657 SDValue ScalarV = Reduce.getOperand(2);
18658 EVT ScalarVT = ScalarV.getValueType();
18659 if (ScalarV.getOpcode() == ISD::INSERT_SUBVECTOR &&
18660 ScalarV.getOperand(0)->isUndef() &&
18661 isNullConstant(ScalarV.getOperand(2)))
18662 ScalarV = ScalarV.getOperand(1);
18663
18664 // Make sure that ScalarV is a splat with VL=1.
18665 if (ScalarV.getOpcode() != RISCVISD::VFMV_S_F_VL &&
18666 ScalarV.getOpcode() != RISCVISD::VMV_S_X_VL &&
18667 ScalarV.getOpcode() != RISCVISD::VMV_V_X_VL)
18668 return SDValue();
18669
18670 if (!isNonZeroAVL(ScalarV.getOperand(2)))
18671 return SDValue();
18672
18673 // Check the scalar of ScalarV is neutral element
18674 // TODO: Deal with value other than neutral element.
18675 if (!DAG.isIdentityElement(N->getOpcode(), N->getFlags(),
18676 ScalarV.getOperand(1), 0))
18677 return SDValue();
18678
18679 // If the AVL is zero, operand 0 will be returned. So it's not safe to fold.
18680 // FIXME: We might be able to improve this if operand 0 is undef.
18681 if (!isNonZeroAVL(Reduce.getOperand(5)))
18682 return SDValue();
18683
18684 SDValue NewStart = N->getOperand(1 - ReduceIdx);
18685
18686 SDLoc DL(N);
18687 SDValue NewScalarV =
18688 lowerScalarInsert(NewStart, ScalarV.getOperand(2),
18689 ScalarV.getSimpleValueType(), DL, DAG, Subtarget);
18690
18691 // If we looked through an INSERT_SUBVECTOR we need to restore it.
18692 if (ScalarVT != ScalarV.getValueType())
18693 NewScalarV =
18694 DAG.getInsertSubvector(DL, DAG.getUNDEF(ScalarVT), NewScalarV, 0);
18695
18696 SDValue Ops[] = {Reduce.getOperand(0), Reduce.getOperand(1),
18697 NewScalarV, Reduce.getOperand(3),
18698 Reduce.getOperand(4), Reduce.getOperand(5)};
18699 SDValue NewReduce =
18700 DAG.getNode(Reduce.getOpcode(), DL, Reduce.getValueType(), Ops);
18701 return DAG.getNode(Extract.getOpcode(), DL, Extract.getValueType(), NewReduce,
18702 Extract.getOperand(1));
18703}
18704
18705// Optimize (add (shl x, c0), (shl y, c1)) ->
18706// (SLLI (SH*ADD x, y), c0), if c1-c0 equals to [1|2|3].
18707// or
18708// (SLLI (QC.SHLADD x, y, c1 - c0), c0), if 4 <= (c1-c0) <=31.
18710 const RISCVSubtarget &Subtarget) {
18711 // Perform this optimization only in the zba/xandesperf/xqciac/xtheadba
18712 // extension.
18713 if (!Subtarget.hasShlAdd(3))
18714 return SDValue();
18715
18716 // Skip for vector types and larger types.
18717 EVT VT = N->getValueType(0);
18718 if (VT.isVector() || VT.getSizeInBits() > Subtarget.getXLen())
18719 return SDValue();
18720
18721 // The two operand nodes must be SHL and have no other use.
18722 SDValue N0 = N->getOperand(0);
18723 SDValue N1 = N->getOperand(1);
18724 if (N0->getOpcode() != ISD::SHL || N1->getOpcode() != ISD::SHL ||
18725 !N0->hasOneUse() || !N1->hasOneUse())
18726 return SDValue();
18727
18728 // Check c0 and c1.
18729 auto *N0C = dyn_cast<ConstantSDNode>(N0->getOperand(1));
18730 auto *N1C = dyn_cast<ConstantSDNode>(N1->getOperand(1));
18731 if (!N0C || !N1C)
18732 return SDValue();
18733 int64_t C0 = N0C->getSExtValue();
18734 int64_t C1 = N1C->getSExtValue();
18735 if (C0 <= 0 || C1 <= 0)
18736 return SDValue();
18737
18738 int64_t Diff = std::abs(C0 - C1);
18739 if (!Subtarget.hasShlAdd(Diff))
18740 return SDValue();
18741
18742 // Build nodes.
18743 SDLoc DL(N);
18744 int64_t Bits = std::min(C0, C1);
18745 SDValue NS = (C0 < C1) ? N0->getOperand(0) : N1->getOperand(0);
18746 SDValue NL = (C0 > C1) ? N0->getOperand(0) : N1->getOperand(0);
18747 SDValue SHADD = DAG.getNode(RISCVISD::SHL_ADD, DL, VT, NL,
18748 DAG.getTargetConstant(Diff, DL, VT), NS);
18749 return DAG.getNode(ISD::SHL, DL, VT, SHADD, DAG.getConstant(Bits, DL, VT));
18750}
18751
18752// Check if this SDValue is an add immediate that is fed by a shift of 1, 2,
18753// or 3.
18755 SelectionDAG &DAG) {
18756 using namespace llvm::SDPatternMatch;
18757
18758 // Looking for a reg-reg add and not an addi.
18759 if (isa<ConstantSDNode>(N->getOperand(1)))
18760 return SDValue();
18761
18762 // Based on testing it seems that performance degrades if the ADDI has
18763 // more than 2 uses.
18764 if (AddI->use_size() > 2)
18765 return SDValue();
18766
18767 APInt AddVal;
18768 SDValue SHLVal;
18769 if (!sd_match(AddI, m_Add(m_Value(SHLVal), m_ConstInt(AddVal))))
18770 return SDValue();
18771
18772 APInt VShift;
18773 if (!sd_match(SHLVal, m_OneUse(m_Shl(m_Value(), m_ConstInt(VShift)))))
18774 return SDValue();
18775
18776 if (VShift.slt(1) || VShift.sgt(3))
18777 return SDValue();
18778
18779 SDLoc DL(N);
18780 EVT VT = N->getValueType(0);
18781 // The shift must be positive but the add can be signed.
18782 uint64_t ShlConst = VShift.getZExtValue();
18783 int64_t AddConst = AddVal.getSExtValue();
18784
18785 SDValue SHADD = DAG.getNode(RISCVISD::SHL_ADD, DL, VT, SHLVal->getOperand(0),
18786 DAG.getTargetConstant(ShlConst, DL, VT), Other);
18787 return DAG.getNode(ISD::ADD, DL, VT, SHADD,
18788 DAG.getSignedConstant(AddConst, DL, VT));
18789}
18790
18791// Optimize (add (add (shl x, c0), c1), y) ->
18792// (ADDI (SH*ADD y, x), c1), if c0 equals to [1|2|3].
18794 const RISCVSubtarget &Subtarget) {
18795 // Perform this optimization only in the zba extension.
18796 if (!ReassocShlAddiAdd || !Subtarget.hasShlAdd(3))
18797 return SDValue();
18798
18799 // Skip for vector types and larger types.
18800 EVT VT = N->getValueType(0);
18801 if (VT != Subtarget.getXLenVT())
18802 return SDValue();
18803
18804 SDValue AddI = N->getOperand(0);
18805 SDValue Other = N->getOperand(1);
18806 if (SDValue V = combineShlAddIAddImpl(N, AddI, Other, DAG))
18807 return V;
18808 if (SDValue V = combineShlAddIAddImpl(N, Other, AddI, DAG))
18809 return V;
18810 return SDValue();
18811}
18812
18813// Combine a constant select operand into its use:
18814//
18815// (and (select cond, -1, c), x)
18816// -> (select cond, x, (and x, c)) [AllOnes=1]
18817// (or (select cond, 0, c), x)
18818// -> (select cond, x, (or x, c)) [AllOnes=0]
18819// (xor (select cond, 0, c), x)
18820// -> (select cond, x, (xor x, c)) [AllOnes=0]
18821// (add (select cond, 0, c), x)
18822// -> (select cond, x, (add x, c)) [AllOnes=0]
18823// (sub x, (select cond, 0, c))
18824// -> (select cond, x, (sub x, c)) [AllOnes=0]
18826 SelectionDAG &DAG, bool AllOnes,
18827 const RISCVSubtarget &Subtarget) {
18828 EVT VT = N->getValueType(0);
18829
18830 // Skip vectors.
18831 if (VT.isVector())
18832 return SDValue();
18833
18834 if (!Subtarget.hasConditionalMoveFusion()) {
18835 // (select cond, x, (and x, c)) has custom lowering with Zicond.
18836 if (!Subtarget.hasStdExtZicond() || N->getOpcode() != ISD::AND)
18837 return SDValue();
18838
18839 // Maybe harmful when condition code has multiple use.
18840 if (Slct.getOpcode() == ISD::SELECT && !Slct.getOperand(0).hasOneUse())
18841 return SDValue();
18842
18843 // Maybe harmful when VT is wider than XLen.
18844 if (VT.getSizeInBits() > Subtarget.getXLen())
18845 return SDValue();
18846 }
18847
18848 if ((Slct.getOpcode() != ISD::SELECT &&
18849 Slct.getOpcode() != RISCVISD::SELECT_CC) ||
18850 !Slct.hasOneUse())
18851 return SDValue();
18852
18853 auto isZeroOrAllOnes = [](SDValue N, bool AllOnes) {
18855 };
18856
18857 bool SwapSelectOps;
18858 unsigned OpOffset = Slct.getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
18859 SDValue TrueVal = Slct.getOperand(1 + OpOffset);
18860 SDValue FalseVal = Slct.getOperand(2 + OpOffset);
18861 SDValue NonConstantVal;
18862 if (isZeroOrAllOnes(TrueVal, AllOnes)) {
18863 SwapSelectOps = false;
18864 NonConstantVal = FalseVal;
18865 } else if (isZeroOrAllOnes(FalseVal, AllOnes)) {
18866 SwapSelectOps = true;
18867 NonConstantVal = TrueVal;
18868 } else
18869 return SDValue();
18870
18871 // Slct is now know to be the desired identity constant when CC is true.
18872 TrueVal = OtherOp;
18873 FalseVal = DAG.getNode(N->getOpcode(), SDLoc(N), VT, OtherOp, NonConstantVal);
18874 // Unless SwapSelectOps says the condition should be false.
18875 if (SwapSelectOps)
18876 std::swap(TrueVal, FalseVal);
18877
18878 if (Slct.getOpcode() == RISCVISD::SELECT_CC)
18879 return DAG.getNode(RISCVISD::SELECT_CC, SDLoc(N), VT,
18880 {Slct.getOperand(0), Slct.getOperand(1),
18881 Slct.getOperand(2), TrueVal, FalseVal});
18882
18883 return DAG.getNode(ISD::SELECT, SDLoc(N), VT,
18884 {Slct.getOperand(0), TrueVal, FalseVal});
18885}
18886
18887// Attempt combineSelectAndUse on each operand of a commutative operator N.
18889 bool AllOnes,
18890 const RISCVSubtarget &Subtarget) {
18891 SDValue N0 = N->getOperand(0);
18892 SDValue N1 = N->getOperand(1);
18893 if (SDValue Result = combineSelectAndUse(N, N0, N1, DAG, AllOnes, Subtarget))
18894 return Result;
18895 if (SDValue Result = combineSelectAndUse(N, N1, N0, DAG, AllOnes, Subtarget))
18896 return Result;
18897 return SDValue();
18898}
18899
18900// Transform (add (mul x, c0), c1) ->
18901// (add (mul (add x, c1/c0), c0), c1%c0).
18902// if c1/c0 and c1%c0 are simm12, while c1 is not. A special corner case
18903// that should be excluded is when c0*(c1/c0) is simm12, which will lead
18904// to an infinite loop in DAGCombine if transformed.
18905// Or transform (add (mul x, c0), c1) ->
18906// (add (mul (add x, c1/c0+1), c0), c1%c0-c0),
18907// if c1/c0+1 and c1%c0-c0 are simm12, while c1 is not. A special corner
18908// case that should be excluded is when c0*(c1/c0+1) is simm12, which will
18909// lead to an infinite loop in DAGCombine if transformed.
18910// Or transform (add (mul x, c0), c1) ->
18911// (add (mul (add x, c1/c0-1), c0), c1%c0+c0),
18912// if c1/c0-1 and c1%c0+c0 are simm12, while c1 is not. A special corner
18913// case that should be excluded is when c0*(c1/c0-1) is simm12, which will
18914// lead to an infinite loop in DAGCombine if transformed.
18915// Or transform (add (mul x, c0), c1) ->
18916// (mul (add x, c1/c0), c0).
18917// if c1%c0 is zero, and c1/c0 is simm12 while c1 is not.
18919 const RISCVSubtarget &Subtarget) {
18920 // Skip for vector types and larger types.
18921 EVT VT = N->getValueType(0);
18922 if (VT.isVector() || VT.getSizeInBits() > Subtarget.getXLen())
18923 return SDValue();
18924 // The first operand node must be a MUL and has no other use.
18925 SDValue N0 = N->getOperand(0);
18926 if (!N0->hasOneUse() || N0->getOpcode() != ISD::MUL)
18927 return SDValue();
18928 // Check if c0 and c1 match above conditions.
18929 auto *N0C = dyn_cast<ConstantSDNode>(N0->getOperand(1));
18930 auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1));
18931 if (!N0C || !N1C)
18932 return SDValue();
18933 // If N0C has multiple uses it's possible one of the cases in
18934 // DAGCombiner::isMulAddWithConstProfitable will be true, which would result
18935 // in an infinite loop.
18936 if (!N0C->hasOneUse())
18937 return SDValue();
18938 int64_t C0 = N0C->getSExtValue();
18939 int64_t C1 = N1C->getSExtValue();
18940 int64_t CA, CB;
18941 // If C1 already fits in an add immediate, there is nothing to split out: the
18942 // (add (mul x, c0), c1) form is already canonical/cheap. Splitting it would
18943 // fight the generic DAGCombiner fold add(mul(add(A, CA), CM), CB) ->
18944 // add(mul(A, CM), CM*CA+CB) (which is gated on isLegalAddImmediate) and cause
18945 // an infinite loop.
18946 if (C0 == -1 || C0 == 0 || C0 == 1 ||
18947 Subtarget.getTargetLowering()->isLegalAddImmediate(C1))
18948 return SDValue();
18949 // Search for proper CA (non-zero) and CB that both are simm12.
18950 if ((C1 / C0) != 0 && isInt<12>(C1 / C0) && isInt<12>(C1 % C0) &&
18951 !isInt<12>(C0 * (C1 / C0))) {
18952 CA = C1 / C0;
18953 CB = C1 % C0;
18954 } else if ((C1 / C0 + 1) != 0 && isInt<12>(C1 / C0 + 1) &&
18955 isInt<12>(C1 % C0 - C0) && !isInt<12>(C0 * (C1 / C0 + 1))) {
18956 CA = C1 / C0 + 1;
18957 CB = C1 % C0 - C0;
18958 } else if ((C1 / C0 - 1) != 0 && isInt<12>(C1 / C0 - 1) &&
18959 isInt<12>(C1 % C0 + C0) && !isInt<12>(C0 * (C1 / C0 - 1))) {
18960 CA = C1 / C0 - 1;
18961 CB = C1 % C0 + C0;
18962 } else
18963 return SDValue();
18964 // Build new nodes (add (mul (add x, c1/c0), c0), c1%c0).
18965 SDLoc DL(N);
18966 SDValue New0 = DAG.getNode(ISD::ADD, DL, VT, N0->getOperand(0),
18967 DAG.getSignedConstant(CA, DL, VT));
18968 SDValue New1 =
18969 DAG.getNode(ISD::MUL, DL, VT, New0, DAG.getSignedConstant(C0, DL, VT));
18970 return DAG.getNode(ISD::ADD, DL, VT, New1, DAG.getSignedConstant(CB, DL, VT));
18971}
18972
18973// add (zext, zext) -> zext (add (zext, zext))
18974// sub (zext, zext) -> sext (sub (zext, zext))
18975// mul (zext, zext) -> zext (mul (zext, zext))
18976// sdiv (zext, zext) -> zext (sdiv (zext, zext))
18977// udiv (zext, zext) -> zext (udiv (zext, zext))
18978// srem (zext, zext) -> zext (srem (zext, zext))
18979// urem (zext, zext) -> zext (urem (zext, zext))
18980//
18981// where the sum of the extend widths match, and the the range of the bin op
18982// fits inside the width of the narrower bin op. (For profitability on rvv, we
18983// use a power of two for both inner and outer extend.)
18985
18986 EVT VT = N->getValueType(0);
18987 if (!VT.isVector() || !DAG.getTargetLoweringInfo().isTypeLegal(VT))
18988 return SDValue();
18989
18990 SDValue N0 = N->getOperand(0);
18991 SDValue N1 = N->getOperand(1);
18993 return SDValue();
18994 if (!N0.hasOneUse() || !N1.hasOneUse())
18995 return SDValue();
18996
18997 SDValue Src0 = N0.getOperand(0);
18998 SDValue Src1 = N1.getOperand(0);
18999 EVT SrcVT = Src0.getValueType();
19000 if (!DAG.getTargetLoweringInfo().isTypeLegal(SrcVT) ||
19001 SrcVT != Src1.getValueType() || SrcVT.getScalarSizeInBits() < 8 ||
19002 SrcVT.getScalarSizeInBits() >= VT.getScalarSizeInBits() / 2)
19003 return SDValue();
19004
19005 LLVMContext &C = *DAG.getContext();
19007 EVT NarrowVT = EVT::getVectorVT(C, ElemVT, VT.getVectorElementCount());
19008
19009 Src0 = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(Src0), NarrowVT, Src0);
19010 Src1 = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(Src1), NarrowVT, Src1);
19011
19012 // Src0 and Src1 are zero extended, so they're always positive if signed.
19013 //
19014 // sub can produce a negative from two positive operands, so it needs sign
19015 // extended. Other nodes produce a positive from two positive operands, so
19016 // zero extend instead.
19017 unsigned OuterExtend =
19018 N->getOpcode() == ISD::SUB ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
19019
19020 return DAG.getNode(
19021 OuterExtend, SDLoc(N), VT,
19022 DAG.getNode(N->getOpcode(), SDLoc(N), NarrowVT, Src0, Src1));
19023}
19024
19025// Try to turn (add (xor bool, 1) -1) into (neg bool).
19027 SDValue N0 = N->getOperand(0);
19028 SDValue N1 = N->getOperand(1);
19029 EVT VT = N->getValueType(0);
19030 SDLoc DL(N);
19031
19032 // RHS should be -1.
19033 if (!isAllOnesConstant(N1))
19034 return SDValue();
19035
19036 // Look for (xor X, 1).
19037 if (N0.getOpcode() != ISD::XOR || !isOneConstant(N0.getOperand(1)))
19038 return SDValue();
19039
19040 // First xor input should be 0 or 1.
19042 if (!DAG.MaskedValueIsZero(N0.getOperand(0), Mask))
19043 return SDValue();
19044
19045 // Emit a negate of the setcc.
19046 return DAG.getNegative(N0.getOperand(0), DL, VT);
19047}
19048
19049// Fold (add X, (mulhs X, C)) -> (mulhsu X, C) if C is negative. This occurs
19050// in the expansion of sdiv i32 X, 7 using magic multiply.
19051//
19052// mulhs returns the hi from X * C = hi * 2^32 + lo.
19053//
19054// Since C<0, u(C) as an unsigned constant is 2^32 + C = u(C).
19055// mulhsu computes
19056// X * u(C0) = X * (C + 2^32)
19057// = X * 2^32 + C * X // C * X is the same as mulhs
19058// = X * 2^32 + hi * 2^32 + lo
19059// = (X + hi) * 2^32 + lo
19060// So mulhsu computes (X + hi).
19062 const RISCVSubtarget &Subtarget) {
19063 EVT VT = N->getValueType(0);
19064 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
19065 bool IsPExtPackedDoubleType =
19066 VT.isSimple() && Subtarget.isPExtPackedDoubleType(VT.getSimpleVT());
19067 if (!TLI.isOperationLegal(ISD::MULHS, VT) && !IsPExtPackedDoubleType &&
19068 !(Subtarget.hasStdExtP() && !Subtarget.is64Bit() && VT == MVT::v4i8) &&
19069 !(Subtarget.hasStdExtP() && Subtarget.is64Bit() && VT == MVT::v8i8))
19070 return SDValue();
19071
19072 using namespace SDPatternMatch;
19073 SDValue X, Mulh;
19074 APInt C;
19075 if (!sd_match(N,
19076 m_Add(m_Value(X),
19078 m_ConstInt(C)))))) ||
19079 !C.isNegative())
19080 return SDValue();
19081
19082 SDLoc DL(N);
19083
19084 // We don't have a v4i8 MULHSU instruction, use a WMULSU+SRL+TRUNC.
19085 auto MakePWMulSU = [&](SDValue A, SDValue B) -> SDValue {
19086 SDValue WMul = DAG.getNode(RISCVISD::PWMULSU, DL, MVT::v4i16, A, B);
19087 SDValue Shifted = DAG.getNode(ISD::SRL, DL, MVT::v4i16, WMul,
19088 DAG.getConstant(8, DL, MVT::v4i16));
19089 return DAG.getNode(ISD::TRUNCATE, DL, MVT::v4i8, Shifted);
19090 };
19091
19092 // We need to split double wide vectors ourselves, op legalization won't
19093 // run for custom nodes.
19094 if (IsPExtPackedDoubleType) {
19096 auto [XLo, XHi] = DAG.SplitVector(X, DL, HalfVT, HalfVT);
19097 auto [CLo, CHi] = DAG.SplitVector(Mulh.getOperand(1), DL, HalfVT, HalfVT);
19098 SDValue ResLo, ResHi;
19099 if (HalfVT == MVT::v4i8) {
19100 ResLo = MakePWMulSU(XLo, CLo);
19101 ResHi = MakePWMulSU(XHi, CHi);
19102 } else {
19103 ResLo = DAG.getNode(RISCVISD::MULHSU, DL, HalfVT, XLo, CLo);
19104 ResHi = DAG.getNode(RISCVISD::MULHSU, DL, HalfVT, XHi, CHi);
19105 }
19106 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, ResLo, ResHi);
19107 }
19108
19109 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit() && VT == MVT::v4i8)
19110 return MakePWMulSU(X, Mulh.getOperand(1));
19111
19112 // We don't have a v8i8 MULHSU instruction on RV64 either; build it from a
19113 // pair of widening byte multiplies recombined with PPAIRO.
19114 if (Subtarget.hasStdExtP() && Subtarget.is64Bit() && VT == MVT::v8i8) {
19115 SDValue C = Mulh.getOperand(1);
19116 SDValue Lo = DAG.getNode(RISCVISD::PMULSU_HALVES_00, DL, MVT::v4i16, X, C);
19117 SDValue Hi = DAG.getNode(RISCVISD::PMULSU_HALVES_11, DL, MVT::v4i16, X, C);
19118 return DAG.getNode(RISCVISD::PPAIRO, DL, VT, DAG.getBitcast(VT, Lo),
19119 DAG.getBitcast(VT, Hi));
19120 }
19121
19122 return DAG.getNode(RISCVISD::MULHSU, DL, VT, X, Mulh.getOperand(1));
19123}
19124
19125// Fold an add of a multiply-parts product into the accumulating form.
19127 const RISCVSubtarget &Subtarget) {
19128 if (!Subtarget.hasStdExtP())
19129 return SDValue();
19130
19131 for (unsigned I = 0; I != 2; ++I) {
19132 SDValue Mul = N->getOperand(I);
19133 if (Mul.getOpcode() != ISD::INTRINSIC_WO_CHAIN || !Mul.hasOneUse())
19134 continue;
19135 Intrinsic::ID AccId =
19136 getRVPMulPartsAccIntrinsic(Mul.getConstantOperandVal(0));
19137 if (AccId == Intrinsic::not_intrinsic)
19138 continue;
19139
19140 SDLoc DL(N);
19141 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, N->getValueType(0),
19142 DAG.getTargetConstant(AccId, DL, Subtarget.getXLenVT()),
19143 N->getOperand(1 - I), Mul.getOperand(1),
19144 Mul.getOperand(2));
19145 }
19146 return SDValue();
19147}
19148
19150 const RISCVSubtarget &Subtarget) {
19151 // Recognize the RV64 decompositions listed for the 32-bit packed widening
19152 // add/sub operations. Mixed signed/unsigned PM2 forms are outside that group.
19153 if (!Subtarget.hasStdExtP() || !Subtarget.is64Bit())
19154 return SDValue();
19155
19156 unsigned Opcode = N->getOpcode();
19157 if (Opcode != ISD::ADD && Opcode != ISD::SUB)
19158 return SDValue();
19159
19160 EVT VT = N->getValueType(0);
19161 if (VT != MVT::v4i16 && VT != MVT::v2i32)
19162 return SDValue();
19163
19164 SDValue N0 = N->getOperand(0);
19165 SDValue N1 = N->getOperand(1);
19166 unsigned ExtendOpcode = N0.getOpcode();
19167 if ((ExtendOpcode != ISD::SIGN_EXTEND && ExtendOpcode != ISD::ZERO_EXTEND) ||
19168 N1.getOpcode() != ExtendOpcode || !N0.hasOneUse() || !N1.hasOneUse())
19169 return SDValue();
19170 bool IsSExt = ExtendOpcode == ISD::SIGN_EXTEND;
19171
19172 SDValue A = N0.getOperand(0);
19173 SDValue B = N1.getOperand(0);
19174 MVT SrcVT = VT == MVT::v4i16 ? MVT::v4i8 : MVT::v2i16;
19175 MVT LegalSrcVT = VT == MVT::v4i16 ? MVT::v8i8 : MVT::v4i16;
19176 if (A.getValueType() != SrcVT || B.getValueType() != SrcVT)
19177 return SDValue();
19178
19179 if (VT == MVT::v4i16 && !IsSExt)
19180 return SDValue();
19181
19182 bool IsPM2Halfword = VT == MVT::v2i32 && (IsSExt || Opcode == ISD::ADD);
19183 if (VT == MVT::v2i32 && !IsPM2Halfword)
19184 return SDValue();
19185
19186 SDLoc DL(N);
19187 A = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, A, DAG.getUNDEF(SrcVT));
19188 B = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, B, DAG.getUNDEF(SrcVT));
19189
19190 SDValue Zip = DAG.getNode(RISCVISD::PZIP, DL, LegalSrcVT, A, B);
19191 if (VT == MVT::v4i16) {
19192 SDValue ZipAsVT = DAG.getBitcast(VT, Zip);
19193 SDValue Low = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, ZipAsVT,
19194 DAG.getValueType(MVT::v4i8));
19195 SDValue High = DAG.getNode(RISCVISD::PSRA, DL, VT, ZipAsVT,
19196 DAG.getConstant(8, DL, MVT::i64));
19197 return DAG.getNode(Opcode, DL, VT, Low, High);
19198 }
19199
19200 SDValue Ones = DAG.getConstant(1, DL, LegalSrcVT);
19201 if (IsSExt) {
19202 unsigned Opc = Opcode == ISD::ADD ? RISCVISD::PM2ADD_H : RISCVISD::PM2SUB_H;
19203 return DAG.getNode(Opc, DL, VT, Zip, Ones);
19204 }
19205
19206 if (Opcode == ISD::ADD)
19207 return DAG.getNode(RISCVISD::PM2ADDU_H, DL, VT, Zip, Ones);
19208
19209 return SDValue();
19210}
19211
19213 const RISCVSubtarget &Subtarget) {
19214 using namespace SDPatternMatch;
19215
19216 if (!Subtarget.hasStdExtP() || !Subtarget.is64Bit())
19217 return SDValue();
19218
19219 if (N->getOpcode() != ISD::ADD)
19220 return SDValue();
19221
19222 MVT VT = N->getSimpleValueType(0);
19223 if (VT != MVT::v4i16 && VT != MVT::v2i32)
19224 return SDValue();
19225
19226 auto MatchExtend = [](SDValue V, unsigned ExtendOpcode, MVT SrcVT,
19227 SDValue &Src) {
19228 return sd_match(
19229 V, m_OneUse(m_Node(ExtendOpcode, m_Value(Src, m_SpecificVT(SrcVT)))));
19230 };
19231
19232 auto Match = [&](SDValue Ext, SDValue Add, SDValue &Acc, SDValue &A,
19233 SDValue &B, bool &IsSExt) {
19234 MVT SrcVT = VT == MVT::v4i16 ? MVT::v4i8 : MVT::v2i16;
19235 unsigned ExtendOpcode = Ext.getOpcode();
19236 if (ExtendOpcode != ISD::SIGN_EXTEND && ExtendOpcode != ISD::ZERO_EXTEND)
19237 return false;
19238
19239 if (!MatchExtend(Ext, ExtendOpcode, SrcVT, B))
19240 return false;
19241
19242 if (!sd_match(Add, m_OneUse(m_Add(m_Value(), m_Value()))))
19243 return false;
19244
19245 if (MatchExtend(Add.getOperand(0), ExtendOpcode, SrcVT, A))
19246 Acc = Add.getOperand(1);
19247 else if (MatchExtend(Add.getOperand(1), ExtendOpcode, SrcVT, A))
19248 Acc = Add.getOperand(0);
19249 else
19250 return false;
19251
19252 if (Acc.getValueType() != VT)
19253 return false;
19254
19255 IsSExt = ExtendOpcode == ISD::SIGN_EXTEND;
19256 return true;
19257 };
19258
19259 SDValue Acc, A, B;
19260 bool IsSExt;
19261 if (!Match(N->getOperand(0), N->getOperand(1), Acc, A, B, IsSExt) &&
19262 !Match(N->getOperand(1), N->getOperand(0), Acc, A, B, IsSExt))
19263 return SDValue();
19264
19265 if (VT == MVT::v4i16 && !IsSExt)
19266 return SDValue();
19267
19268 SDLoc DL(N);
19269 MVT LegalSrcVT = VT == MVT::v4i16 ? MVT::v8i8 : MVT::v4i16;
19270 MVT SrcVT = VT == MVT::v4i16 ? MVT::v4i8 : MVT::v2i16;
19271 A = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, A, DAG.getUNDEF(SrcVT));
19272 B = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, B, DAG.getUNDEF(SrcVT));
19273
19274 SDValue Zip = DAG.getNode(RISCVISD::PZIP, DL, LegalSrcVT, A, B);
19275 if (VT == MVT::v4i16) {
19276 SDValue ZipAsVT = DAG.getBitcast(VT, Zip);
19277 SDValue Low = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, ZipAsVT,
19278 DAG.getValueType(MVT::v4i8));
19279 SDValue High = DAG.getNode(RISCVISD::PSRA, DL, VT, ZipAsVT,
19280 DAG.getConstant(8, DL, MVT::i64));
19281 return DAG.getNode(ISD::ADD, DL, VT,
19282 DAG.getNode(ISD::ADD, DL, VT, Acc, Low), High);
19283 }
19284
19285 SDValue Ones = DAG.getConstant(1, DL, LegalSrcVT);
19286 unsigned Opc = IsSExt ? RISCVISD::PM2ADDA_H : RISCVISD::PM2ADDAU_H;
19287 return DAG.getNode(Opc, DL, VT, Acc, Zip, Ones);
19288}
19289
19290// Fold sub(add(Acc, ext A), ext B) to Acc + (A - B), where ext is sext/zext.
19292 const RISCVSubtarget &Subtarget) {
19293 using namespace SDPatternMatch;
19294
19295 if (!Subtarget.hasStdExtP() || !Subtarget.is64Bit())
19296 return SDValue();
19297
19298 if (N->getOpcode() != ISD::SUB)
19299 return SDValue();
19300
19301 MVT VT = N->getSimpleValueType(0);
19302 if (VT != MVT::v4i16 && VT != MVT::v2i32)
19303 return SDValue();
19304
19305 MVT SrcVT = VT == MVT::v4i16 ? MVT::v4i8 : MVT::v2i16;
19306 auto Extend = [&](SDValue &Ext, SDValue &Src) {
19307 return m_Value(
19308 Ext, m_OneUse(m_AnyOf(m_SExt(m_Value(Src, m_SpecificVT(SrcVT))),
19309 m_ZExt(m_Value(Src, m_SpecificVT(SrcVT))))));
19310 };
19311
19312 SDValue Acc, ExtA, A, ExtB, B;
19313 if (!sd_match(N, m_Sub(m_OneUse(m_Add(m_Value(Acc), Extend(ExtA, A))),
19314 Extend(ExtB, B))) ||
19315 ExtA.getOpcode() != ExtB.getOpcode())
19316 return SDValue();
19317
19318 SDLoc DL(N);
19319 if (ExtA.getOpcode() == ISD::ZERO_EXTEND) {
19320 // No unsigned PM2 accumulate-subtract; keep the binary widening subtract
19321 // off the accumulator's dependency chain.
19322 return DAG.getNode(ISD::ADD, DL, VT, Acc,
19323 DAG.getNode(ISD::SUB, DL, VT, ExtA, ExtB));
19324 }
19325
19326 MVT LegalSrcVT = VT == MVT::v4i16 ? MVT::v8i8 : MVT::v4i16;
19327 A = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, A, DAG.getUNDEF(SrcVT));
19328 B = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, B, DAG.getUNDEF(SrcVT));
19329
19330 SDValue Zip = DAG.getNode(RISCVISD::PZIP, DL, LegalSrcVT, A, B);
19331 if (VT == MVT::v4i16) {
19332 SDValue ZipAsVT = DAG.getBitcast(VT, Zip);
19333 SDValue Low = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, ZipAsVT,
19334 DAG.getValueType(MVT::v4i8));
19335 SDValue High = DAG.getNode(RISCVISD::PSRA, DL, VT, ZipAsVT,
19336 DAG.getConstant(8, DL, MVT::i64));
19337 return DAG.getNode(ISD::ADD, DL, VT, Acc,
19338 DAG.getNode(ISD::SUB, DL, VT, Low, High));
19339 }
19340
19341 SDValue Ones = DAG.getConstant(1, DL, LegalSrcVT);
19342 return DAG.getNode(RISCVISD::PM2SUBA_H, DL, VT, Acc, Zip, Ones);
19343}
19344
19347 const RISCVSubtarget &Subtarget) {
19348 SelectionDAG &DAG = DCI.DAG;
19349 if (SDValue V = combineAddOfBooleanXor(N, DAG))
19350 return V;
19351 if (SDValue V = transformAddImmMulImm(N, DAG, Subtarget))
19352 return V;
19353 if (!DCI.isBeforeLegalize() && !DCI.isCalledByLegalizer()) {
19354 if (SDValue V = transformAddShlImm(N, DAG, Subtarget))
19355 return V;
19356 if (SDValue V = combineShlAddIAdd(N, DAG, Subtarget))
19357 return V;
19358 }
19359 if (SDValue V = combineBinOpToReduce(N, DAG, Subtarget))
19360 return V;
19361 if (SDValue V = combineBinOpOfExtractToReduceTree(N, DAG, Subtarget))
19362 return V;
19363 if (SDValue V = combinePExtWideningAddAcc(N, DAG, Subtarget))
19364 return V;
19365 if (SDValue V = combinePExtWideningAddSub(N, DAG, Subtarget))
19366 return V;
19367 if (SDValue V = combineBinOpOfZExt(N, DAG))
19368 return V;
19369 if (SDValue V = combineAddMulParts(N, DAG, Subtarget))
19370 return V;
19371 if (SDValue V = combineAddMulh(N, DAG, Subtarget))
19372 return V;
19373
19374 // fold (add (select lhs, rhs, cc, 0, y), x) ->
19375 // (select lhs, rhs, cc, x, (add x, y))
19376 return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false, Subtarget);
19377}
19378
19379// Try to turn a sub boolean RHS and constant LHS into an addi.
19381 SDValue N0 = N->getOperand(0);
19382 SDValue N1 = N->getOperand(1);
19383 EVT VT = N->getValueType(0);
19384 SDLoc DL(N);
19385
19386 // Require a constant LHS.
19387 auto *N0C = dyn_cast<ConstantSDNode>(N0);
19388 if (!N0C)
19389 return SDValue();
19390
19391 // All our optimizations involve subtracting 1 from the immediate and forming
19392 // an ADDI. Make sure the new immediate is valid for an ADDI.
19393 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
19394 if (!ImmValMinus1.isSignedIntN(12))
19395 return SDValue();
19396
19397 SDValue NewLHS;
19398 if (N1.getOpcode() == ISD::SETCC && N1.hasOneUse()) {
19399 // (sub constant, (setcc x, y, eq/neq)) ->
19400 // (add (setcc x, y, neq/eq), constant - 1)
19401 ISD::CondCode CCVal = cast<CondCodeSDNode>(N1.getOperand(2))->get();
19402 EVT SetCCOpVT = N1.getOperand(0).getValueType();
19403 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.isInteger())
19404 return SDValue();
19405 CCVal = ISD::getSetCCInverse(CCVal, SetCCOpVT);
19406 NewLHS =
19407 DAG.getSetCC(SDLoc(N1), VT, N1.getOperand(0), N1.getOperand(1), CCVal);
19408 } else if (N1.getOpcode() == ISD::XOR && isOneConstant(N1.getOperand(1)) &&
19409 N1.getOperand(0).getOpcode() == ISD::SETCC) {
19410 // (sub C, (xor (setcc), 1)) -> (add (setcc), C-1).
19411 // Since setcc returns a bool the xor is equivalent to 1-setcc.
19412 NewLHS = N1.getOperand(0);
19413 } else
19414 return SDValue();
19415
19416 SDValue NewRHS = DAG.getConstant(ImmValMinus1, DL, VT);
19417 return DAG.getNode(ISD::ADD, DL, VT, NewLHS, NewRHS);
19418}
19419
19420// Looks for (sub (shl X, 8-Y), (shr X, Y)) where the Y-th bit in each byte is
19421// potentially set. It is fine for Y to be 0, meaning that (sub (shl X, 8), X)
19422// is also valid. Replace with (orc.b X). For example, 0b0000_1000_0000_1000 is
19423// valid with Y=3, while 0b0000_1000_0000_0100 is not.
19425 const RISCVSubtarget &Subtarget) {
19426 if (!Subtarget.hasStdExtZbb())
19427 return SDValue();
19428
19429 EVT VT = N->getValueType(0);
19430
19431 if (VT != Subtarget.getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
19432 return SDValue();
19433
19434 SDValue N0 = N->getOperand(0);
19435 SDValue N1 = N->getOperand(1);
19436
19437 if (N0->getOpcode() != ISD::SHL)
19438 return SDValue();
19439
19440 auto *ShAmtCLeft = dyn_cast<ConstantSDNode>(N0.getOperand(1));
19441 if (!ShAmtCLeft)
19442 return SDValue();
19443 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
19444
19445 if (ShiftedAmount >= 8)
19446 return SDValue();
19447
19448 SDValue LeftShiftOperand = N0->getOperand(0);
19449 SDValue RightShiftOperand = N1;
19450
19451 if (ShiftedAmount != 0) { // Right operand must be a right shift.
19452 if (N1->getOpcode() != ISD::SRL)
19453 return SDValue();
19454 auto *ShAmtCRight = dyn_cast<ConstantSDNode>(N1.getOperand(1));
19455 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
19456 return SDValue();
19457 RightShiftOperand = N1.getOperand(0);
19458 }
19459
19460 // At least one shift should have a single use.
19461 if (!N0.hasOneUse() && (ShiftedAmount == 0 || !N1.hasOneUse()))
19462 return SDValue();
19463
19464 if (LeftShiftOperand != RightShiftOperand)
19465 return SDValue();
19466
19467 APInt Mask = APInt::getSplat(VT.getSizeInBits(), APInt(8, 0x1));
19468 Mask <<= ShiftedAmount;
19469 // Check that X has indeed the right shape (only the Y-th bit can be set in
19470 // every byte).
19471 if (!DAG.MaskedValueIsZero(LeftShiftOperand, ~Mask))
19472 return SDValue();
19473
19474 return DAG.getNode(RISCVISD::ORC_B, SDLoc(N), VT, LeftShiftOperand);
19475}
19476
19478 const RISCVSubtarget &Subtarget) {
19479 if (SDValue V = combineSubOfBoolean(N, DAG))
19480 return V;
19481
19482 EVT VT = N->getValueType(0);
19483 SDValue N0 = N->getOperand(0);
19484 SDValue N1 = N->getOperand(1);
19485 // fold (sub 0, (setcc x, 0, setlt)) -> (sra x, xlen - 1)
19486 if (isNullConstant(N0) && N1.getOpcode() == ISD::SETCC && N1.hasOneUse() &&
19487 isNullConstant(N1.getOperand(1)) &&
19488 N1.getValueType() == N1.getOperand(0).getValueType()) {
19489 ISD::CondCode CCVal = cast<CondCodeSDNode>(N1.getOperand(2))->get();
19490 if (CCVal == ISD::SETLT) {
19491 SDLoc DL(N);
19492 unsigned ShAmt = N0.getValueSizeInBits() - 1;
19493 return DAG.getNode(ISD::SRA, DL, VT, N1.getOperand(0),
19494 DAG.getConstant(ShAmt, DL, VT));
19495 }
19496 }
19497
19498 // fold (sub 0, (srl (and X, (1 << ShAmt)), ShAmt)) ->
19499 // (sra (shl X, ShAmt2), bits - 1)
19500 // where ShAmt2 = (bits - 1) - ShAmt. This extracts bit ShAmt of X and
19501 // sign-extends it across the whole register.
19502 {
19503 using namespace SDPatternMatch;
19504 SDValue X;
19505 uint64_t Mask, ShAmt;
19506 if (isNullConstant(N0) &&
19507 sd_match(N1,
19509 m_ConstInt(ShAmt)))) &&
19510 isPowerOf2_64(Mask) && Log2_64(Mask) == ShAmt) {
19511 SDLoc DL(N);
19512 unsigned Bits = VT.getSizeInBits();
19513 unsigned ShAmt2 = Bits - 1 - ShAmt;
19514 SDValue Shl = DAG.getNode(ISD::SHL, DL, VT, X,
19515 DAG.getShiftAmountConstant(ShAmt2, VT, DL));
19516 return DAG.getNode(ISD::SRA, DL, VT, Shl,
19517 DAG.getShiftAmountConstant(Bits - 1, VT, DL));
19518 }
19519 }
19520
19521 if (SDValue V = combinePExtWideningSubAcc(N, DAG, Subtarget))
19522 return V;
19523 if (SDValue V = combinePExtWideningAddSub(N, DAG, Subtarget))
19524 return V;
19525 if (SDValue V = combineBinOpOfZExt(N, DAG))
19526 return V;
19527 if (SDValue V = combineSubShiftToOrcB(N, DAG, Subtarget))
19528 return V;
19529
19530 // fold (sub x, (select lhs, rhs, cc, 0, y)) ->
19531 // (select lhs, rhs, cc, x, (sub x, y))
19532 return combineSelectAndUse(N, N1, N0, DAG, /*AllOnes*/ false, Subtarget);
19533}
19534
19535// Apply DeMorgan's law to (and/or (xor X, 1), (xor Y, 1)) if X and Y are 0/1.
19536// Legalizing setcc can introduce xors like this. Doing this transform reduces
19537// the number of xors and may allow the xor to fold into a branch condition.
19539 SDValue N0 = N->getOperand(0);
19540 SDValue N1 = N->getOperand(1);
19541 bool IsAnd = N->getOpcode() == ISD::AND;
19542
19543 if (N0.getOpcode() != ISD::XOR || N1.getOpcode() != ISD::XOR)
19544 return SDValue();
19545
19546 if (!N0.hasOneUse() || !N1.hasOneUse())
19547 return SDValue();
19548
19549 SDValue N01 = N0.getOperand(1);
19550 SDValue N11 = N1.getOperand(1);
19551
19552 // For AND, SimplifyDemandedBits may have turned one of the (xor X, 1) into
19553 // (xor X, -1) based on the upper bits of the other operand being 0. If the
19554 // operation is And, allow one of the Xors to use -1.
19555 if (isOneConstant(N01)) {
19556 if (!isOneConstant(N11) && !(IsAnd && isAllOnesConstant(N11)))
19557 return SDValue();
19558 } else if (isOneConstant(N11)) {
19559 // N01 and N11 being 1 was already handled. Handle N11==1 and N01==-1.
19560 if (!(IsAnd && isAllOnesConstant(N01)))
19561 return SDValue();
19562 } else
19563 return SDValue();
19564
19565 EVT VT = N->getValueType(0);
19566
19567 SDValue N00 = N0.getOperand(0);
19568 SDValue N10 = N1.getOperand(0);
19569
19570 // The LHS of the xors needs to be 0/1.
19572 if (!DAG.MaskedValueIsZero(N00, Mask) || !DAG.MaskedValueIsZero(N10, Mask))
19573 return SDValue();
19574
19575 // Invert the opcode and insert a new xor.
19576 SDLoc DL(N);
19577 unsigned Opc = IsAnd ? ISD::OR : ISD::AND;
19578 SDValue Logic = DAG.getNode(Opc, DL, VT, N00, N10);
19579 return DAG.getNode(ISD::XOR, DL, VT, Logic, DAG.getConstant(1, DL, VT));
19580}
19581
19582// Handle P extension truncate patterns, both on packed vectors and on scalar
19583// i32 (the RV32-only asub/asubu and mulhr* instructions):
19584// ASUB/ASUBU: (trunc (srl (sub ([s|z]ext a), ([s|z]ext b)), 1))
19585// MULHSU: (trunc (srl (mul (sext a), (zext b)), EltBits))
19586// MULHR*: (trunc (srl (add (mul (sext a), (zext b)), round_const), EltBits))
19588 const RISCVSubtarget &Subtarget) {
19589 SDValue N0 = N->getOperand(0);
19590 EVT VT = N->getValueType(0);
19591 if (N0.getOpcode() != ISD::SRL)
19592 return SDValue();
19593
19594 if (VT != MVT::v4i16 && VT != MVT::v2i16 && VT != MVT::v8i8 &&
19595 VT != MVT::v4i8 && VT != MVT::v2i32 && VT != MVT::i32)
19596 return SDValue();
19597
19599 if (!C)
19600 return SDValue();
19601
19602 SDValue Op = N0.getOperand(0);
19603 unsigned ShAmtVal = C->getZExtValue();
19604 unsigned EltBits = VT.getScalarSizeInBits();
19605
19606 // Check for rounding pattern: (add (mul ...), round_const)
19607 bool IsRounding = false;
19608 if (Op.getOpcode() == ISD::ADD && (EltBits == 16 || EltBits == 32)) {
19609 ConstantSDNode *RndC = isConstOrConstSplat(Op.getOperand(1));
19610 if (RndC && RndC->getZExtValue() == (1ULL << (EltBits - 1)) &&
19611 Op.getOperand(0).getOpcode() == ISD::MUL) {
19612 Op = Op.getOperand(0);
19613 IsRounding = true;
19614 }
19615 }
19616
19617 // Ensure Op is a binary operation before accessing its operands.
19618 if (Op.getNumOperands() != 2)
19619 return SDValue();
19620
19621 SDValue LHS = Op.getOperand(0);
19622 SDValue RHS = Op.getOperand(1);
19623
19624 bool LHSIsSExt = LHS.getOpcode() == ISD::SIGN_EXTEND;
19625 bool LHSIsZExt = LHS.getOpcode() == ISD::ZERO_EXTEND;
19626 bool RHSIsSExt = RHS.getOpcode() == ISD::SIGN_EXTEND;
19627 bool RHSIsZExt = RHS.getOpcode() == ISD::ZERO_EXTEND;
19628
19629 if (!(LHSIsSExt || LHSIsZExt) || !(RHSIsSExt || RHSIsZExt))
19630 return SDValue();
19631
19632 SDValue A = LHS.getOperand(0);
19633 SDValue B = RHS.getOperand(0);
19634
19635 if (A.getValueType() != VT || B.getValueType() != VT)
19636 return SDValue();
19637
19638 unsigned Opc;
19639 switch (Op.getOpcode()) {
19640 default:
19641 return SDValue();
19642 case ISD::SUB:
19643 // PASUB/PASUBU: shift amount must be 1
19644 if (ShAmtVal != 1)
19645 return SDValue();
19646 if (LHSIsSExt && RHSIsSExt)
19647 Opc = RISCVISD::ASUB;
19648 else if (LHSIsZExt && RHSIsZExt)
19649 Opc = RISCVISD::ASUBU;
19650 else
19651 return SDValue();
19652 break;
19653 case ISD::MUL:
19654 // MULH*/MULHR*: shift amount must be element size, only for i16/i32
19655 if (ShAmtVal != EltBits || (EltBits != 16 && EltBits != 32))
19656 return SDValue();
19657 if (!Subtarget.is64Bit() && VT == MVT::v4i16)
19658 return SDValue();
19659 if (IsRounding) {
19660 if (LHSIsSExt && RHSIsSExt) {
19661 Opc = RISCVISD::MULHR;
19662 } else if (LHSIsZExt && RHSIsZExt) {
19663 Opc = RISCVISD::MULHRU;
19664 } else if ((LHSIsSExt && RHSIsZExt) || (LHSIsZExt && RHSIsSExt)) {
19665 Opc = RISCVISD::MULHRSU;
19666 // commuted case
19667 if (LHSIsZExt && RHSIsSExt)
19668 std::swap(A, B);
19669 } else {
19670 return SDValue();
19671 }
19672 } else {
19673 // Scalar mulhsu is handled elsewhere, only match the packed MULHSU here.
19674 if (!VT.isVector())
19675 return SDValue();
19676 if ((LHSIsSExt && RHSIsZExt) || (LHSIsZExt && RHSIsSExt)) {
19677 Opc = RISCVISD::MULHSU;
19678 // commuted case
19679 if (LHSIsZExt && RHSIsSExt)
19680 std::swap(A, B);
19681 } else
19682 return SDValue();
19683 }
19684
19685 // RV32 has scalar rounded multiply-high instructions, but no paired form.
19686 // Split v2i32 while the widening multiply shape is still visible.
19687 if (!Subtarget.is64Bit() && VT == MVT::v2i32) {
19688 if (!IsRounding)
19689 return SDValue();
19690 SDLoc DL(N);
19691 SDValue ALo = DAG.getExtractVectorElt(DL, MVT::i32, A, 0);
19692 SDValue AHi = DAG.getExtractVectorElt(DL, MVT::i32, A, 1);
19693 SDValue BLo = DAG.getExtractVectorElt(DL, MVT::i32, B, 0);
19694 SDValue BHi = DAG.getExtractVectorElt(DL, MVT::i32, B, 1);
19695 SDValue Lo = DAG.getNode(Opc, DL, MVT::i32, ALo, BLo);
19696 SDValue Hi = DAG.getNode(Opc, DL, MVT::i32, AHi, BHi);
19697 return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
19698 }
19699
19700 // On RV64, v8i8 MULHSU is built from a pair of widening byte multiplies
19701 // (picking out the even/odd result lanes) recombined with PPAIRO.
19702 if (Subtarget.is64Bit() && VT == MVT::v8i8 && Opc == RISCVISD::MULHSU) {
19703 SDLoc DL(N);
19704 SDValue Lo =
19705 DAG.getNode(RISCVISD::PMULSU_HALVES_00, DL, MVT::v4i16, A, B);
19706 SDValue Hi =
19707 DAG.getNode(RISCVISD::PMULSU_HALVES_11, DL, MVT::v4i16, A, B);
19708 return DAG.getNode(RISCVISD::PPAIRO, DL, VT, DAG.getBitcast(VT, Lo),
19709 DAG.getBitcast(VT, Hi));
19710 }
19711 break;
19712 }
19713
19714 return DAG.getNode(Opc, SDLoc(N), VT, {A, B});
19715}
19716
19718 const RISCVSubtarget &Subtarget) {
19719 SDValue N0 = N->getOperand(0);
19720 EVT VT = N->getValueType(0);
19721
19722 // P truncate patterns: packed vectors, plus RV32-only scalar i32.
19723 if (Subtarget.hasStdExtP() &&
19724 (VT.isFixedLengthVector() || (VT == MVT::i32 && !Subtarget.is64Bit())))
19725 return combinePExtTruncate(N, DAG, Subtarget);
19726
19727 // Pre-promote (i1 (truncate (srl X, Y))) on RV64 with Zbs without zero
19728 // extending X. This is safe since we only need the LSB after the shift and
19729 // shift amounts larger than 31 would produce poison. If we wait until
19730 // type legalization, we'll create RISCVISD::SRLW and we can't recover it
19731 // to use a BEXT instruction.
19732 if (Subtarget.is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
19733 N0.getValueType() == MVT::i32 && N0.getOpcode() == ISD::SRL &&
19734 !isa<ConstantSDNode>(N0.getOperand(1)) && N0.hasOneUse()) {
19735 SDLoc DL(N0);
19736 SDValue Op0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N0.getOperand(0));
19737 SDValue Op1 = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, N0.getOperand(1));
19738 SDValue Srl = DAG.getNode(ISD::SRL, DL, MVT::i64, Op0, Op1);
19739 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), VT, Srl);
19740 }
19741
19742 return SDValue();
19743}
19744
19745// InstCombinerImpl::transformZExtICmp will narrow a zext of an icmp with a
19746// truncation. But RVV doesn't have truncation instructions for more than twice
19747// the bitwidth.
19748//
19749// E.g. trunc <vscale x 1 x i64> %x to <vscale x 1 x i8> will generate:
19750//
19751// vsetvli a0, zero, e32, m2, ta, ma
19752// vnsrl.wi v12, v8, 0
19753// vsetvli zero, zero, e16, m1, ta, ma
19754// vnsrl.wi v8, v12, 0
19755// vsetvli zero, zero, e8, mf2, ta, ma
19756// vnsrl.wi v8, v8, 0
19757//
19758// So reverse the combine so we generate an vmseq/vmsne again:
19759//
19760// and (lshr (trunc X), ShAmt), 1
19761// -->
19762// zext (icmp ne (and X, (1 << ShAmt)), 0)
19763//
19764// and (lshr (not (trunc X)), ShAmt), 1
19765// -->
19766// zext (icmp eq (and X, (1 << ShAmt)), 0)
19768 const RISCVSubtarget &Subtarget) {
19769 using namespace SDPatternMatch;
19770 SDLoc DL(N);
19771
19772 if (!Subtarget.hasVInstructions())
19773 return SDValue();
19774
19775 EVT VT = N->getValueType(0);
19776 if (!VT.isVector())
19777 return SDValue();
19778
19779 APInt ShAmt;
19780 SDValue Inner;
19781 if (!sd_match(N, m_And(m_OneUse(m_Srl(m_Value(Inner), m_ConstInt(ShAmt))),
19782 m_One())))
19783 return SDValue();
19784
19785 SDValue X;
19786 bool IsNot;
19787 if (sd_match(Inner, m_Not(m_Trunc(m_Value(X)))))
19788 IsNot = true;
19789 else if (sd_match(Inner, m_Trunc(m_Value(X))))
19790 IsNot = false;
19791 else
19792 return SDValue();
19793
19794 EVT WideVT = X.getValueType();
19795 if (VT.getScalarSizeInBits() >= WideVT.getScalarSizeInBits() / 2)
19796 return SDValue();
19797
19798 SDValue Res =
19799 DAG.getNode(ISD::AND, DL, WideVT, X,
19800 DAG.getConstant(1ULL << ShAmt.getZExtValue(), DL, WideVT));
19801 Res = DAG.getSetCC(DL,
19802 EVT::getVectorVT(*DAG.getContext(), MVT::i1,
19803 WideVT.getVectorElementCount()),
19804 Res, DAG.getConstant(0, DL, WideVT),
19805 IsNot ? ISD::SETEQ : ISD::SETNE);
19806 return DAG.getNode(ISD::ZERO_EXTEND, DL, VT, Res);
19807}
19808
19811 SelectionDAG &DAG = DCI.DAG;
19812 if (N->getOpcode() != ISD::AND)
19813 return SDValue();
19814
19815 SDValue N0 = N->getOperand(0);
19816 if (N0.getOpcode() != ISD::ATOMIC_LOAD)
19817 return SDValue();
19818 if (!N0.hasOneUse())
19819 return SDValue();
19820
19823 return SDValue();
19824
19825 EVT LoadedVT = ALoad->getMemoryVT();
19826 ConstantSDNode *MaskConst = dyn_cast<ConstantSDNode>(N->getOperand(1));
19827 if (!MaskConst)
19828 return SDValue();
19829 uint64_t Mask = MaskConst->getZExtValue();
19830 uint64_t ExpectedMask = maskTrailingOnes<uint64_t>(LoadedVT.getSizeInBits());
19831 if (Mask != ExpectedMask)
19832 return SDValue();
19833
19834 SDValue ZextLoad = DAG.getAtomicLoad(
19835 ISD::ZEXTLOAD, SDLoc(N), ALoad->getMemoryVT(), N->getValueType(0),
19836 ALoad->getChain(), ALoad->getBasePtr(), ALoad->getMemOperand());
19837 DCI.CombineTo(N, ZextLoad);
19838 DAG.ReplaceAllUsesOfValueWith(SDValue(N0.getNode(), 1), ZextLoad.getValue(1));
19840 return SDValue(N, 0);
19841}
19842
19843// Sometimes a mask is applied after a shift. If that shift was fed by a
19844// load, there is sometimes the opportunity to narrow the load, which is
19845// hidden by the intermediate shift. Detect that case and commute the
19846// shift/and in order to enable load narrowing.
19848 EVT VT = N->getValueType(0);
19849 if (!VT.isScalarInteger())
19850 return SDValue();
19851
19852 using namespace SDPatternMatch;
19853 SDValue LoadNode;
19854 APInt MaskVal, ShiftVal;
19855 // (and (shl (load ...), ShiftAmt), Mask)
19856 if (!sd_match(
19858 m_ConstInt(ShiftVal))),
19859 m_ConstInt(MaskVal)))) {
19860 return SDValue();
19861 }
19862
19863 uint64_t ShiftAmt = ShiftVal.getZExtValue();
19864
19865 if (ShiftAmt >= VT.getSizeInBits())
19866 return SDValue();
19867
19868 // Calculate the appropriate mask if it were applied before the shift.
19869 APInt InnerMask = MaskVal.lshr(ShiftAmt);
19870 bool IsNarrowable =
19871 InnerMask == 0xff || InnerMask == 0xffff || InnerMask == 0xffffffff;
19872
19873 if (!IsNarrowable)
19874 return SDValue();
19875
19876 // AND the loaded value and change the shift appropriately, allowing
19877 // the load to be narrowed.
19878 SDLoc DL(N);
19879 SDValue InnerAnd = DAG.getNode(ISD::AND, DL, VT, LoadNode,
19880 DAG.getConstant(InnerMask, DL, VT));
19881 return DAG.getNode(ISD::SHL, DL, VT, InnerAnd,
19882 DAG.getShiftAmountConstant(ShiftAmt, VT, DL));
19883}
19884
19885// Combines two comparison operation and logic operation to one selection
19886// operation(min, max) and logic operation. Returns new constructed Node if
19887// conditions for optimization are satisfied.
19890 const RISCVSubtarget &Subtarget) {
19891 SelectionDAG &DAG = DCI.DAG;
19892 SDValue N0 = N->getOperand(0);
19893
19894 // Pre-promote (i32 (and (srl X, Y), 1)) on RV64 with Zbs without zero
19895 // extending X. This is safe since we only need the LSB after the shift and
19896 // shift amounts larger than 31 would produce poison. If we wait until
19897 // type legalization, we'll create RISCVISD::SRLW and we can't recover it
19898 // to use a BEXT instruction.
19899 if (Subtarget.is64Bit() && Subtarget.hasStdExtZbs() &&
19900 N->getValueType(0) == MVT::i32 && isOneConstant(N->getOperand(1)) &&
19901 N0.getOpcode() == ISD::SRL && !isa<ConstantSDNode>(N0.getOperand(1)) &&
19902 N0.hasOneUse()) {
19903 SDLoc DL(N);
19904 SDValue Op0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N0.getOperand(0));
19905 SDValue Op1 = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, N0.getOperand(1));
19906 SDValue Srl = DAG.getNode(ISD::SRL, DL, MVT::i64, Op0, Op1);
19907 SDValue And = DAG.getNode(ISD::AND, DL, MVT::i64, Srl,
19908 DAG.getConstant(1, DL, MVT::i64));
19909 return DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, And);
19910 }
19911
19913 return V;
19914 if (SDValue V = reverseZExtICmpCombine(N, DAG, Subtarget))
19915 return V;
19916 if (SDValue V = combineBinOpToReduce(N, DAG, Subtarget))
19917 return V;
19918 if (SDValue V = combineBinOpOfExtractToReduceTree(N, DAG, Subtarget))
19919 return V;
19920 if (SDValue V = reduceANDOfAtomicLoad(N, DCI))
19921 return V;
19922
19923 if (DCI.isAfterLegalizeDAG())
19924 if (SDValue V = combineDeMorganOfBoolean(N, DAG))
19925 return V;
19926
19927 // fold (and (select lhs, rhs, cc, -1, y), x) ->
19928 // (select lhs, rhs, cc, x, (and x, y))
19929 return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ true, Subtarget);
19930}
19931
19932// Try to pull an xor with 1 through a select idiom that uses czero_eqz/nez.
19933// FIXME: Generalize to other binary operators with same operand.
19935 SelectionDAG &DAG) {
19936 assert(N->getOpcode() == ISD::OR && "Unexpected opcode");
19937
19938 if (N0.getOpcode() != RISCVISD::CZERO_EQZ ||
19939 N1.getOpcode() != RISCVISD::CZERO_NEZ ||
19940 !N0.hasOneUse() || !N1.hasOneUse())
19941 return SDValue();
19942
19943 // Should have the same condition.
19944 SDValue Cond = N0.getOperand(1);
19945 if (Cond != N1.getOperand(1))
19946 return SDValue();
19947
19948 SDValue TrueV = N0.getOperand(0);
19949 SDValue FalseV = N1.getOperand(0);
19950
19951 if (TrueV.getOpcode() != ISD::XOR || FalseV.getOpcode() != ISD::XOR ||
19952 TrueV.getOperand(1) != FalseV.getOperand(1) ||
19953 !isOneConstant(TrueV.getOperand(1)) ||
19954 !TrueV.hasOneUse() || !FalseV.hasOneUse())
19955 return SDValue();
19956
19957 EVT VT = N->getValueType(0);
19958 SDLoc DL(N);
19959
19960 SDValue NewN0 = DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV.getOperand(0),
19961 Cond);
19962 SDValue NewN1 =
19963 DAG.getNode(RISCVISD::CZERO_NEZ, DL, VT, FalseV.getOperand(0), Cond);
19964 SDValue NewOr =
19965 DAG.getNode(ISD::OR, DL, VT, NewN0, NewN1, SDNodeFlags::Disjoint);
19966 return DAG.getNode(ISD::XOR, DL, VT, NewOr, TrueV.getOperand(1));
19967}
19968
19969// (xor X, (xor (and X, C2), Y))
19970// ->(qc_insb X, (sra Y, ShAmt), Width, ShAmt)
19971// where C2 is a shifted mask with width = Width and shift = ShAmt
19972// qc_insb might become qc.insb or qc.insbi depending on the operands.
19974 const RISCVSubtarget &Subtarget) {
19975 if (!Subtarget.hasVendorXqcibm())
19976 return SDValue();
19977
19978 using namespace SDPatternMatch;
19979 SDValue Base, Inserted;
19980 APInt CMask;
19981 if (!sd_match(N, m_Xor(m_Value(Base),
19983 m_ConstInt(CMask))),
19984 m_Value(Inserted))))))
19985 return SDValue();
19986
19987 if (N->getValueType(0) != MVT::i32)
19988 return SDValue();
19989 unsigned Width, ShAmt;
19990 if (!CMask.isShiftedMask(ShAmt, Width))
19991 return SDValue();
19992
19993 // Check if all zero bits in CMask are also zero in Inserted
19994 if (!DAG.MaskedValueIsZero(Inserted, ~CMask))
19995 return SDValue();
19996
19997 SDLoc DL(N);
19998
19999 // `Inserted` needs to be right shifted before it is put into the
20000 // instruction.
20001 Inserted = DAG.getNode(ISD::SRA, DL, MVT::i32, Inserted,
20002 DAG.getShiftAmountConstant(ShAmt, MVT::i32, DL));
20003
20004 SDValue Ops[] = {Base, Inserted, DAG.getConstant(Width, DL, MVT::i32),
20005 DAG.getConstant(ShAmt, DL, MVT::i32)};
20006 return DAG.getNode(RISCVISD::QC_INSB, DL, MVT::i32, Ops);
20007}
20008
20010 const RISCVSubtarget &Subtarget) {
20011 if (!Subtarget.hasVendorXqcibm())
20012 return SDValue();
20013
20014 using namespace SDPatternMatch;
20015
20016 SDValue X;
20017 APInt MaskImm;
20018 if (!sd_match(N, m_Or(m_OneUse(m_Value(X)), m_ConstInt(MaskImm))))
20019 return SDValue();
20020
20021 unsigned ShAmt, Width;
20022 if (!MaskImm.isShiftedMask(ShAmt, Width) || MaskImm.isSignedIntN(12))
20023 return SDValue();
20024
20025 if (N->getValueType(0) != MVT::i32)
20026 return SDValue();
20027
20028 // If Zbs is enabled and it is a single bit set we can use BSETI which
20029 // can be compressed to C_BSETI when Xqcibm in enabled.
20030 if (Width == 1 && Subtarget.hasStdExtZbs())
20031 return SDValue();
20032
20033 // If C1 is a shifted mask (but can't be formed as an ORI),
20034 // use a bitfield insert of -1.
20035 // Transform (or x, C1)
20036 // -> (qc.insbi x, -1, width, shift)
20037 SDLoc DL(N);
20038
20039 SDValue Ops[] = {X, DAG.getSignedConstant(-1, DL, MVT::i32),
20040 DAG.getConstant(Width, DL, MVT::i32),
20041 DAG.getConstant(ShAmt, DL, MVT::i32)};
20042 return DAG.getNode(RISCVISD::QC_INSB, DL, MVT::i32, Ops);
20043}
20044
20045// Generate a QC_INSB/QC_INSBI from 'or (and X, MaskImm), OrImm' iff the value
20046// being inserted only sets known zero bits.
20048 const RISCVSubtarget &Subtarget) {
20049 // Supported only in Xqcibm for now.
20050 if (!Subtarget.hasVendorXqcibm())
20051 return SDValue();
20052
20053 using namespace SDPatternMatch;
20054
20055 SDValue Inserted;
20056 APInt MaskImm, OrImm;
20057 if (!sd_match(
20058 N, m_SpecificVT(MVT::i32, m_Or(m_OneUse(m_And(m_Value(Inserted),
20059 m_ConstInt(MaskImm))),
20060 m_ConstInt(OrImm)))))
20061 return SDValue();
20062
20063 // Compute the Known Zero for the AND as this allows us to catch more general
20064 // cases than just looking for AND with imm.
20065 KnownBits Known = DAG.computeKnownBits(N->getOperand(0));
20066
20067 // The bits being inserted must only set those bits that are known to be
20068 // zero.
20069 if (!OrImm.isSubsetOf(Known.Zero)) {
20070 // FIXME: It's okay if the OrImm sets NotKnownZero bits to 1, but we don't
20071 // currently handle this case.
20072 return SDValue();
20073 }
20074
20075 unsigned ShAmt, Width;
20076 // The KnownZero mask must be a shifted mask (e.g., 1110..011, 11100..00).
20077 if (!Known.Zero.isShiftedMask(ShAmt, Width))
20078 return SDValue();
20079
20080 // QC_INSB(I) dst, src, #width, #shamt.
20081 SDLoc DL(N);
20082
20083 SDValue ImmNode =
20084 DAG.getSignedConstant(OrImm.getSExtValue() >> ShAmt, DL, MVT::i32);
20085
20086 SDValue Ops[] = {Inserted, ImmNode, DAG.getConstant(Width, DL, MVT::i32),
20087 DAG.getConstant(ShAmt, DL, MVT::i32)};
20088 return DAG.getNode(RISCVISD::QC_INSB, DL, MVT::i32, Ops);
20089}
20090
20092 const RISCVSubtarget &Subtarget) {
20093 SelectionDAG &DAG = DCI.DAG;
20094
20095 if (SDValue V = combineOrAndToBitfieldInsert(N, DAG, Subtarget))
20096 return V;
20097 if (SDValue V = combineBinOpToReduce(N, DAG, Subtarget))
20098 return V;
20099 if (SDValue V = combineBinOpOfExtractToReduceTree(N, DAG, Subtarget))
20100 return V;
20101
20102 if (DCI.isAfterLegalizeDAG()) {
20103 if (SDValue V = combineOrToBitfieldInsert(N, DAG, Subtarget))
20104 return V;
20105 if (SDValue V = combineDeMorganOfBoolean(N, DAG))
20106 return V;
20107 }
20108
20109 // Look for Or of CZERO_EQZ/NEZ with same condition which is the select idiom.
20110 // We may be able to pull a common operation out of the true and false value.
20111 SDValue N0 = N->getOperand(0);
20112 SDValue N1 = N->getOperand(1);
20113 if (SDValue V = combineOrOfCZERO(N, N0, N1, DAG))
20114 return V;
20115 if (SDValue V = combineOrOfCZERO(N, N1, N0, DAG))
20116 return V;
20117
20118 // fold (or (select cond, 0, y), x) ->
20119 // (select cond, x, (or x, y))
20120 return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false, Subtarget);
20121}
20122
20123// Fold (vmxor_vl (setcc_vl a, b, cc), vmset_vl) -> (setcc_vl a, b, !cc) for
20124// integer compares. The NOT also flips the masked-off lanes, which the inverted
20125// compare copies unchanged from the passthru. So the passthru must be undef,
20126// but any mask is fine.
20128 SDValue Cmp = N->getOperand(0);
20129 if (Cmp.getOpcode() != RISCVISD::VMSET_VL &&
20130 N->getOperand(1).getOpcode() != RISCVISD::VMSET_VL)
20131 return SDValue();
20132
20133 if (Cmp.getOpcode() == RISCVISD::VMSET_VL)
20134 Cmp = N->getOperand(1);
20135
20136 if (Cmp.getOpcode() != RISCVISD::SETCC_VL || !Cmp.hasOneUse() ||
20137 !Cmp.getOperand(0).getValueType().isInteger() ||
20138 !Cmp.getOperand(3).isUndef())
20139 return SDValue();
20140
20141 ISD::CondCode CC = cast<CondCodeSDNode>(Cmp.getOperand(2))->get();
20142 CC = ISD::getSetCCInverse(CC, Cmp.getOperand(0).getValueType());
20143 return DAG.getNode(RISCVISD::SETCC_VL, SDLoc(N), Cmp.getValueType(),
20144 {Cmp.getOperand(0), Cmp.getOperand(1), DAG.getCondCode(CC),
20145 Cmp.getOperand(3), Cmp.getOperand(4), Cmp.getOperand(5)});
20146}
20147
20149 const RISCVSubtarget &Subtarget) {
20150 SDValue N0 = N->getOperand(0);
20151 SDValue N1 = N->getOperand(1);
20152
20153 // Pre-promote (i32 (xor (shl -1, X), ~0)) on RV64 with Zbs so we can use
20154 // (ADDI (BSET X0, X), -1). If we wait until type legalization, we'll create
20155 // RISCVISD:::SLLW and we can't recover it to use a BSET instruction.
20156 if (Subtarget.is64Bit() && Subtarget.hasStdExtZbs() &&
20157 N->getValueType(0) == MVT::i32 && isAllOnesConstant(N1) &&
20158 N0.getOpcode() == ISD::SHL && isAllOnesConstant(N0.getOperand(0)) &&
20159 !isa<ConstantSDNode>(N0.getOperand(1)) && N0.hasOneUse()) {
20160 SDLoc DL(N);
20161 SDValue Op0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N0.getOperand(0));
20162 SDValue Op1 = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, N0.getOperand(1));
20163 SDValue Shl = DAG.getNode(ISD::SHL, DL, MVT::i64, Op0, Op1);
20164 SDValue Not = DAG.getNOT(DL, Shl, MVT::i64);
20165 return DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Not);
20166 }
20167
20168 // fold (xor (sllw 1, x), -1) -> (rolw ~1, x)
20169 // NOTE: Assumes ROL being legal means ROLW is legal.
20170 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
20171 if (N0.getOpcode() == RISCVISD::SLLW &&
20173 TLI.isOperationLegal(ISD::ROTL, MVT::i64)) {
20174 SDLoc DL(N);
20175 return DAG.getNode(RISCVISD::ROLW, DL, MVT::i64,
20176 DAG.getConstant(~1, DL, MVT::i64), N0.getOperand(1));
20177 }
20178
20179 // Fold (xor (setcc constant, y, setlt), 1) -> (setcc y, constant + 1, setlt)
20180 if (N0.getOpcode() == ISD::SETCC && isOneConstant(N1) && N0.hasOneUse()) {
20181 auto *ConstN00 = dyn_cast<ConstantSDNode>(N0.getOperand(0));
20183 if (ConstN00 && CC == ISD::SETLT) {
20184 EVT VT = N0.getValueType();
20185 SDLoc DL(N0);
20186 const APInt &Imm = ConstN00->getAPIntValue();
20187 if ((Imm + 1).isSignedIntN(12))
20188 return DAG.getSetCC(DL, VT, N0.getOperand(1),
20189 DAG.getConstant(Imm + 1, DL, VT), CC);
20190 }
20191 }
20192
20193 if (SDValue V = combineXorToBitfieldInsert(N, DAG, Subtarget))
20194 return V;
20195
20196 if (SDValue V = combineBinOpToReduce(N, DAG, Subtarget))
20197 return V;
20198 if (SDValue V = combineBinOpOfExtractToReduceTree(N, DAG, Subtarget))
20199 return V;
20200
20201 // fold (xor (select cond, 0, y), x) ->
20202 // (select cond, x, (xor x, y))
20203 return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false, Subtarget);
20204}
20205
20206// Try to expand a multiply to a sequence of shifts and add/subs,
20207// for a machine without native mul instruction.
20209 uint64_t MulAmt) {
20210 SDLoc DL(N);
20211 EVT VT = N->getValueType(0);
20213
20214 SDValue Result = DAG.getConstant(0, DL, N->getValueType(0));
20215 SDValue N0 = N->getOperand(0);
20216
20217 // Find the Non-adjacent form of the multiplier.
20218 for (uint64_t E = MulAmt, I = 0; E && I < BitWidth; ++I, E >>= 1) {
20219 if (E & 1) {
20220 bool IsAdd = (E & 3) == 1;
20221 E -= IsAdd ? 1 : -1;
20222 SDValue ShiftVal = DAG.getNode(ISD::SHL, DL, VT, N0,
20223 DAG.getShiftAmountConstant(I, VT, DL));
20224 ISD::NodeType AddSubOp = IsAdd ? ISD::ADD : ISD::SUB;
20225 Result = DAG.getNode(AddSubOp, DL, VT, Result, ShiftVal);
20226 }
20227 }
20228
20229 return Result;
20230}
20231
20232// X * (2^N +/- 2^M) -> (add/sub (shl X, C1), (shl X, C2))
20234 uint64_t MulAmt) {
20235 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
20236 SDValue X = N->getOperand(0);
20238 uint64_t ShiftAmt1;
20239 bool CanSub = isPowerOf2_64(MulAmt + MulAmtLowBit);
20240 auto PreferSub = [X, MulAmtLowBit]() {
20241 // For MulAmt == 3 << M both (X << M + 2) - (X << M)
20242 // and (X << M + 1) + (X << M) are valid expansions.
20243 // Prefer SUB if we can get (X << M + 2) for free,
20244 // because X is exact (Y >> M + 2).
20245 uint64_t ShAmt = Log2_64(MulAmtLowBit) + 2;
20246 using namespace SDPatternMatch;
20247 return sd_match(X, m_ExactSr(m_Value(), m_SpecificInt(ShAmt)));
20248 };
20249 if (isPowerOf2_64(MulAmt - MulAmtLowBit) && !(CanSub && PreferSub())) {
20250 Op = ISD::ADD;
20251 ShiftAmt1 = MulAmt - MulAmtLowBit;
20252 } else if (CanSub) {
20253 Op = ISD::SUB;
20254 ShiftAmt1 = MulAmt + MulAmtLowBit;
20255 } else {
20256 return SDValue();
20257 }
20258 EVT VT = N->getValueType(0);
20259 SDLoc DL(N);
20260 SDValue Shift1 = DAG.getNode(ISD::SHL, DL, VT, X,
20261 DAG.getConstant(Log2_64(ShiftAmt1), DL, VT));
20262 SDValue Shift2 = DAG.getNode(ISD::SHL, DL, VT, X,
20263 DAG.getConstant(Log2_64(MulAmtLowBit), DL, VT));
20264 return DAG.getNode(Op, DL, VT, Shift1, Shift2);
20265}
20266
20267static SDValue getShlAddShlAdd(SDNode *N, SelectionDAG &DAG, unsigned ShX,
20268 unsigned ShY, bool AddX, unsigned Shift) {
20269 SDLoc DL(N);
20270 EVT VT = N->getValueType(0);
20271 SDValue X = N->getOperand(0);
20272 // Put the shift first if we can fold:
20273 // a. a zext into the shift forming a slli.uw
20274 // b. an exact shift right forming one shorter shift or no shift at all
20275 using namespace SDPatternMatch;
20276 if (Shift != 0 &&
20277 sd_match(X, m_AnyOf(m_And(m_Value(), m_SpecificInt(UINT64_C(0xffffffff))),
20278 m_ExactSr(m_Value(), m_ConstInt())))) {
20279 X = DAG.getNode(ISD::SHL, DL, VT, X, DAG.getConstant(Shift, DL, VT));
20280 Shift = 0;
20281 }
20282 SDValue ShlAdd = DAG.getNode(RISCVISD::SHL_ADD, DL, VT, X,
20283 DAG.getTargetConstant(ShY, DL, VT), X);
20284 if (ShX != 0)
20285 ShlAdd = DAG.getNode(RISCVISD::SHL_ADD, DL, VT, ShlAdd,
20286 DAG.getTargetConstant(ShX, DL, VT), AddX ? X : ShlAdd);
20287 if (Shift == 0)
20288 return ShlAdd;
20289 // Otherwise, put the shl last so that it can fold with following instructions
20290 // (e.g. sext or add).
20291 return DAG.getNode(ISD::SHL, DL, VT, ShlAdd, DAG.getConstant(Shift, DL, VT));
20292}
20293
20295 uint64_t MulAmt, unsigned Shift) {
20296 switch (MulAmt) {
20297 // 3/5/9 -> (shYadd X, X)
20298 case 3:
20299 return getShlAddShlAdd(N, DAG, 0, 1, /*AddX=*/false, Shift);
20300 case 5:
20301 return getShlAddShlAdd(N, DAG, 0, 2, /*AddX=*/false, Shift);
20302 case 9:
20303 return getShlAddShlAdd(N, DAG, 0, 3, /*AddX=*/false, Shift);
20304 // 3/5/9 * 3/5/9 -> (shXadd (shYadd X, X), (shYadd X, X))
20305 case 5 * 3:
20306 return getShlAddShlAdd(N, DAG, 2, 1, /*AddX=*/false, Shift);
20307 case 9 * 3:
20308 return getShlAddShlAdd(N, DAG, 3, 1, /*AddX=*/false, Shift);
20309 case 5 * 5:
20310 return getShlAddShlAdd(N, DAG, 2, 2, /*AddX=*/false, Shift);
20311 case 9 * 5:
20312 return getShlAddShlAdd(N, DAG, 3, 2, /*AddX=*/false, Shift);
20313 case 9 * 9:
20314 return getShlAddShlAdd(N, DAG, 3, 3, /*AddX=*/false, Shift);
20315 default:
20316 break;
20317 }
20318
20319 int ShX;
20320 if (int ShY = isShifted359(MulAmt - 1, ShX)) {
20321 assert(ShX != 0 && "MulAmt=4,6,10 handled before");
20322 // 2/4/8 * 3/5/9 + 1 -> (shXadd (shYadd X, X), X)
20323 if (ShX <= 3)
20324 return getShlAddShlAdd(N, DAG, ShX, ShY, /*AddX=*/true, Shift);
20325 // 2^N * 3/5/9 + 1 -> (add (shYadd (shl X, N), (shl X, N)), X)
20326 if (Shift == 0) {
20327 SDLoc DL(N);
20328 EVT VT = N->getValueType(0);
20329 SDValue X = N->getOperand(0);
20330 SDValue Shl =
20331 DAG.getNode(ISD::SHL, DL, VT, X, DAG.getConstant(ShX, DL, VT));
20332 SDValue ShlAdd = DAG.getNode(RISCVISD::SHL_ADD, DL, VT, Shl,
20333 DAG.getTargetConstant(ShY, DL, VT), Shl);
20334 return DAG.getNode(ISD::ADD, DL, VT, ShlAdd, X);
20335 }
20336 }
20337 return SDValue();
20338}
20339
20340// Try to expand a scalar multiply to a faster sequence.
20343 const RISCVSubtarget &Subtarget) {
20344
20345 EVT VT = N->getValueType(0);
20346
20347 // LI + MUL is usually smaller than the alternative sequence.
20349 return SDValue();
20350
20351 if (VT != Subtarget.getXLenVT())
20352 return SDValue();
20353
20354 bool ShouldExpandMul =
20355 (!DCI.isBeforeLegalize() && !DCI.isCalledByLegalizer()) ||
20356 !Subtarget.hasStdExtZmmul();
20357 if (!ShouldExpandMul)
20358 return SDValue();
20359
20360 ConstantSDNode *CNode = dyn_cast<ConstantSDNode>(N->getOperand(1));
20361 if (!CNode)
20362 return SDValue();
20363 uint64_t MulAmt = CNode->getZExtValue();
20364
20365 // Don't do this if the Xqciac extension is enabled and the MulAmt in simm12.
20366 if (Subtarget.hasVendorXqciac() && isInt<12>(CNode->getSExtValue()))
20367 return SDValue();
20368
20369 // WARNING: The code below is knowingly incorrect with regards to undef
20370 // semantics. We're adding additional uses of X here, and in principle, we
20371 // should be freezing X before doing so. However, adding freeze here causes
20372 // real regressions, and no other target properly freezes X in these cases
20373 // either.
20374 if (Subtarget.hasShlAdd(3)) {
20375 // 3/5/9 * 2^N -> (shl (shXadd X, X), N)
20376 // 3/5/9 * 3/5/9 * 2^N - In particular, this covers multiples
20377 // of 25 which happen to be quite common.
20378 // (2/4/8 * 3/5/9 + 1) * 2^N
20379 unsigned Shift = llvm::countr_zero(MulAmt);
20380 if (SDValue V = expandMulToShlAddShlAdd(N, DAG, MulAmt >> Shift, Shift))
20381 return V;
20382
20383 // If this is a power 2 + 2/4/8, we can use a shift followed by a single
20384 // shXadd. First check if this a sum of two power of 2s because that's
20385 // easy. Then count how many zeros are up to the first bit.
20386 SDValue X = N->getOperand(0);
20387 if (Shift >= 1 && Shift <= 3 && isPowerOf2_64(MulAmt & (MulAmt - 1))) {
20388 unsigned ShiftAmt = llvm::countr_zero((MulAmt & (MulAmt - 1)));
20389 SDLoc DL(N);
20390 SDValue Shift1 =
20391 DAG.getNode(ISD::SHL, DL, VT, X, DAG.getConstant(ShiftAmt, DL, VT));
20392 return DAG.getNode(RISCVISD::SHL_ADD, DL, VT, X,
20393 DAG.getTargetConstant(Shift, DL, VT), Shift1);
20394 }
20395
20396 // TODO: 2^(C1>3) * 3/5/9 - 1
20397
20398 // 2^n + 2/4/8 + 1 -> (add (shl X, C1), (shXadd X, X))
20399 if (MulAmt > 2 && isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
20400 unsigned ScaleShift = llvm::countr_zero(MulAmt - 1);
20401 if (ScaleShift >= 1 && ScaleShift < 4) {
20402 unsigned ShiftAmt = llvm::countr_zero((MulAmt - 1) & (MulAmt - 2));
20403 SDLoc DL(N);
20404 SDValue Shift1 =
20405 DAG.getNode(ISD::SHL, DL, VT, X, DAG.getConstant(ShiftAmt, DL, VT));
20406 return DAG.getNode(
20407 ISD::ADD, DL, VT, Shift1,
20408 DAG.getNode(RISCVISD::SHL_ADD, DL, VT, X,
20409 DAG.getTargetConstant(ScaleShift, DL, VT), X));
20410 }
20411 }
20412
20413 // 2^N - 3/5/9 --> (sub (shl X, C1), (shXadd X, x))
20414 for (uint64_t Offset : {3, 5, 9}) {
20415 if (isPowerOf2_64(MulAmt + Offset)) {
20416 unsigned ShAmt = llvm::countr_zero(MulAmt + Offset);
20417 if (ShAmt >= VT.getSizeInBits())
20418 continue;
20419 SDLoc DL(N);
20420 SDValue Shift1 =
20421 DAG.getNode(ISD::SHL, DL, VT, X, DAG.getConstant(ShAmt, DL, VT));
20422 SDValue Mul359 =
20423 DAG.getNode(RISCVISD::SHL_ADD, DL, VT, X,
20424 DAG.getTargetConstant(Log2_64(Offset - 1), DL, VT), X);
20425 return DAG.getNode(ISD::SUB, DL, VT, Shift1, Mul359);
20426 }
20427 }
20428 }
20429
20430 if (SDValue V = expandMulToAddOrSubOfShl(N, DAG, MulAmt))
20431 return V;
20432
20433 if (!Subtarget.hasStdExtZmmul())
20434 return expandMulToNAFSequence(N, DAG, MulAmt);
20435
20436 return SDValue();
20437}
20438
20439// Combine vXi32 (mul (and (lshr X, 15), 0x10001), 0xffff) ->
20440// (bitcast (sra (v2Xi16 (bitcast X)), 15))
20441// Same for other equivalent types with other equivalent constants.
20443 EVT VT = N->getValueType(0);
20444 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
20445
20446 // Do this for legal vectors unless they are i1 or i8 vectors.
20447 if (!VT.isVector() || !TLI.isTypeLegal(VT) || VT.getScalarSizeInBits() < 16)
20448 return SDValue();
20449
20450 if (N->getOperand(0).getOpcode() != ISD::AND ||
20451 N->getOperand(0).getOperand(0).getOpcode() != ISD::SRL)
20452 return SDValue();
20453
20454 SDValue And = N->getOperand(0);
20455 SDValue Srl = And.getOperand(0);
20456
20457 APInt V1, V2, V3;
20458 if (!ISD::isConstantSplatVector(N->getOperand(1).getNode(), V1) ||
20459 !ISD::isConstantSplatVector(And.getOperand(1).getNode(), V2) ||
20461 return SDValue();
20462
20463 unsigned HalfSize = VT.getScalarSizeInBits() / 2;
20464 if (!V1.isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
20465 V3 != (HalfSize - 1))
20466 return SDValue();
20467
20468 EVT HalfVT = EVT::getVectorVT(*DAG.getContext(),
20469 EVT::getIntegerVT(*DAG.getContext(), HalfSize),
20470 VT.getVectorElementCount() * 2);
20471 SDLoc DL(N);
20472 SDValue Cast = DAG.getNode(ISD::BITCAST, DL, HalfVT, Srl.getOperand(0));
20473 SDValue Sra = DAG.getNode(ISD::SRA, DL, HalfVT, Cast,
20474 DAG.getConstant(HalfSize - 1, DL, HalfVT));
20475 return DAG.getNode(ISD::BITCAST, DL, VT, Sra);
20476}
20477
20479 const RISCVSubtarget &Subtarget) {
20480 if (!Subtarget.hasStdExtP())
20481 return SDValue();
20482
20483 EVT VT = N->getValueType(0);
20484 if (VT != MVT::v4i16 && VT != MVT::v2i32)
20485 return SDValue();
20486
20487 SDValue N0 = N->getOperand(0);
20488 SDValue N1 = N->getOperand(1);
20489 bool N0IsSExt = N0.getOpcode() == ISD::SIGN_EXTEND;
20490 bool N0IsZExt = N0.getOpcode() == ISD::ZERO_EXTEND;
20491 bool N1IsSExt = N1.getOpcode() == ISD::SIGN_EXTEND;
20492 bool N1IsZExt = N1.getOpcode() == ISD::ZERO_EXTEND;
20493
20494 if (!(N0IsSExt || N0IsZExt) || !(N1IsSExt || N1IsZExt) || !N0.hasOneUse() ||
20495 !N1.hasOneUse())
20496 return SDValue();
20497
20498 SDValue A = N0.getOperand(0);
20499 SDValue B = N1.getOperand(0);
20500 EVT SrcVT = VT == MVT::v4i16 ? MVT::v4i8 : MVT::v2i16;
20501 if (A.getValueType() != SrcVT || B.getValueType() != SrcVT)
20502 return SDValue();
20503
20504 unsigned RV32Opc, RV64Opc;
20505 bool IsSignedUnsigned = false;
20506 if (N0IsSExt && N1IsSExt) {
20507 RV32Opc = RISCVISD::PWMUL;
20508 RV64Opc = RISCVISD::PMUL_HALVES_01;
20509 } else if (N0IsZExt && N1IsZExt) {
20510 RV32Opc = RISCVISD::PWMULU;
20511 RV64Opc = RISCVISD::PMULU_HALVES_01;
20512 } else {
20513 IsSignedUnsigned = true;
20514 RV32Opc = RISCVISD::PWMULSU;
20515 RV64Opc = RISCVISD::PMULSU_HALVES_00;
20516 if (N0IsZExt && N1IsSExt)
20517 std::swap(A, B);
20518 }
20519
20520 SDLoc DL(N);
20521 if (!Subtarget.is64Bit())
20522 return DAG.getNode(RV32Opc, DL, VT, A, B);
20523
20524 MVT LegalSrcVT = VT == MVT::v4i16 ? MVT::v8i8 : MVT::v4i16;
20525 A = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, A, DAG.getUNDEF(SrcVT));
20526 B = DAG.getNode(ISD::CONCAT_VECTORS, DL, LegalSrcVT, B, DAG.getUNDEF(SrcVT));
20527
20528 if (IsSignedUnsigned) {
20529 SDValue Zero = DAG.getConstant(0, DL, LegalSrcVT);
20530 A = DAG.getNode(RISCVISD::PZIP, DL, LegalSrcVT, A, Zero);
20531 B = DAG.getNode(RISCVISD::PZIP, DL, LegalSrcVT, B, Zero);
20532 return DAG.getNode(RV64Opc, DL, VT, A, B);
20533 }
20534
20535 SDValue Zip = DAG.getNode(RISCVISD::PZIP, DL, LegalSrcVT, A, B);
20536 return DAG.getNode(RV64Opc, DL, VT, Zip, Zip);
20537}
20538
20541 const RISCVSubtarget &Subtarget) {
20542 EVT VT = N->getValueType(0);
20543 if (!VT.isVector())
20544 return expandMul(N, DAG, DCI, Subtarget);
20545
20546 SDLoc DL(N);
20547 SDValue N0 = N->getOperand(0);
20548 SDValue N1 = N->getOperand(1);
20549 SDValue MulOper;
20550 unsigned AddSubOpc;
20551
20552 // vmadd: (mul (add x, 1), y) -> (add (mul x, y), y)
20553 // (mul x, add (y, 1)) -> (add x, (mul x, y))
20554 // vnmsub: (mul (sub 1, x), y) -> (sub y, (mul x, y))
20555 // (mul x, (sub 1, y)) -> (sub x, (mul x, y))
20556 auto IsAddSubWith1 = [&](SDValue V) -> bool {
20557 AddSubOpc = V->getOpcode();
20558 if ((AddSubOpc == ISD::ADD || AddSubOpc == ISD::SUB) && V->hasOneUse()) {
20559 SDValue Opnd = V->getOperand(1);
20560 MulOper = V->getOperand(0);
20561 if (AddSubOpc == ISD::SUB)
20562 std::swap(Opnd, MulOper);
20563 if (isOneOrOneSplat(Opnd))
20564 return true;
20565 }
20566 return false;
20567 };
20568
20569 if (IsAddSubWith1(N0)) {
20570 SDValue MulVal = DAG.getNode(ISD::MUL, DL, VT, N1, MulOper);
20571 return DAG.getNode(AddSubOpc, DL, VT, N1, MulVal);
20572 }
20573
20574 if (IsAddSubWith1(N1)) {
20575 SDValue MulVal = DAG.getNode(ISD::MUL, DL, VT, N0, MulOper);
20576 return DAG.getNode(AddSubOpc, DL, VT, N0, MulVal);
20577 }
20578
20579 if (SDValue V = combineBinOpOfZExt(N, DAG))
20580 return V;
20581
20582 if (SDValue V = combinePExtWideningMul(N, DAG, Subtarget))
20583 return V;
20584
20586 return V;
20587
20588 return SDValue();
20589}
20590
20591/// According to the property that indexed load/store instructions zero-extend
20592/// their indices, try to narrow the type of index operand.
20593static bool narrowIndex(SDValue &N, ISD::MemIndexType IndexType, SelectionDAG &DAG) {
20594 if (isIndexTypeSigned(IndexType))
20595 return false;
20596
20597 if (!N->hasOneUse())
20598 return false;
20599
20600 EVT VT = N.getValueType();
20601 SDLoc DL(N);
20602
20603 // In general, what we're doing here is seeing if we can sink a truncate to
20604 // a smaller element type into the expression tree building our index.
20605 // TODO: We can generalize this and handle a bunch more cases if useful.
20606
20607 // Narrow a buildvector to the narrowest element type. This requires less
20608 // work and less register pressure at high LMUL, and creates smaller constants
20609 // which may be cheaper to materialize.
20610 if (ISD::isBuildVectorOfConstantSDNodes(N.getNode())) {
20612 unsigned ActiveBits = std::max(8u, Known.countMaxActiveBits());
20613 LLVMContext &C = *DAG.getContext();
20614 EVT ResultVT = EVT::getIntegerVT(C, ActiveBits).getRoundIntegerType(C);
20615 if (ResultVT.bitsLT(VT.getVectorElementType())) {
20616 N = DAG.getNode(ISD::TRUNCATE, DL,
20617 VT.changeVectorElementType(C, ResultVT), N);
20618 return true;
20619 }
20620 }
20621
20622 // Handle the pattern (shl (zext x to ty), C) and bits(x) + C < bits(ty).
20623 if (N.getOpcode() != ISD::SHL)
20624 return false;
20625
20626 SDValue N0 = N.getOperand(0);
20627 if (N0.getOpcode() != ISD::ZERO_EXTEND &&
20628 N0.getOpcode() != RISCVISD::VZEXT_VL)
20629 return false;
20630 if (!N0->hasOneUse())
20631 return false;
20632
20633 APInt ShAmt;
20634 SDValue N1 = N.getOperand(1);
20635 if (!ISD::isConstantSplatVector(N1.getNode(), ShAmt))
20636 return false;
20637
20638 SDValue Src = N0.getOperand(0);
20639 EVT SrcVT = Src.getValueType();
20640 unsigned SrcElen = SrcVT.getScalarSizeInBits();
20641
20642 // Consider any leading zeros in the source.
20643 SrcElen -= DAG.computeKnownBits(Src).countMinLeadingZeros();
20644
20645 unsigned ShAmtV = ShAmt.getZExtValue();
20646 unsigned NewElen = PowerOf2Ceil(SrcElen + ShAmtV);
20647 NewElen = std::max(NewElen, 8U);
20648 // Make sure the new elen is at least as large as the original elen.
20649 NewElen = std::max<unsigned>(NewElen, SrcVT.getScalarSizeInBits());
20650
20651 // Skip if NewElen is not narrower than the original extended type.
20652 if (NewElen >= N0.getValueType().getScalarSizeInBits())
20653 return false;
20654
20655 EVT NewEltVT = EVT::getIntegerVT(*DAG.getContext(), NewElen);
20656 EVT NewVT = SrcVT.changeVectorElementType(*DAG.getContext(), NewEltVT);
20657
20658 SDValue NewExt = DAG.getNode(N0->getOpcode(), DL, NewVT, N0->ops());
20659 SDValue NewShAmtVec = DAG.getConstant(ShAmtV, DL, NewVT);
20660 N = DAG.getNode(ISD::SHL, DL, NewVT, NewExt, NewShAmtVec);
20661 return true;
20662}
20663
20664/// Given
20665/// ```
20666/// %b = splat %base
20667/// %s = <%offset, %offset + 1, %offset + 2, %offset + 3, ...>
20668/// %a = add nuw %b, %s
20669/// %N = splat %n
20670/// %p = setcc ult %a, %N
20671/// ```
20672/// in which the SETCC's condition code could be (U)LT or (U)GT.
20673/// We can turn it into
20674/// ```
20675/// %s = <0, 1, 2, 3, ...>
20676/// %m = sub %n, min(%n, %base + %offset)
20677/// %M = splat %m
20678/// %p = setcc ult %s, %M
20679/// ```
20680/// where the SETCC's condition code is also canonicalized into (U)LT;
20681/// The idea behind this canonicalization is that if %p is used as a mask
20682/// in a masked.load/store, we can easily turn it to use VL-predicate later
20683/// by assigning `vl = min(%m, <number of vector elements>)`.
20685 EVT MaskVT, SDValue LHS, SDValue RHS, ISD::CondCode CC, const SDLoc &DL,
20687
20688 // This transformation performs checks against the vector element type, which
20689 // is also used to generate scalar value that will be splatted later. Because
20690 // of this, the emitted scalar value might not be legal type and therefore we
20691 // need to run this before type legalizer.
20692 if (!DCI.isBeforeLegalize())
20693 return SDValue();
20694
20695 using namespace SDPatternMatch;
20696 if (!MaskVT.isFixedLengthVector() ||
20697 !(CC == ISD::SETUGT || CC == ISD::SETGT || CC == ISD::SETULT ||
20698 CC == ISD::SETLT) ||
20699 !LHS.getValueType().isInteger())
20700 return SDValue();
20701
20702 // Canonicalize the comparison.
20703 if (CC == ISD::SETUGT || CC == ISD::SETGT) {
20704 std::swap(LHS, RHS);
20706 }
20707 bool IsSigned = ISD::isSignedIntSetCC(CC);
20708
20709 EVT ElementVT = LHS.getValueType().getScalarType();
20710 uint64_t ElementSize = LHS.getScalarValueSizeInBits();
20711
20712 SDValue Boundary = DAG.getSplatValue(RHS);
20713 if (!Boundary)
20714 return SDValue();
20715
20716 SDValue LHSOp0, LHSOp1;
20717 if (IsSigned) {
20718 if (!sd_match(LHS, m_NSWAddLike(m_Value(LHSOp0), m_Value(LHSOp1))))
20719 return SDValue();
20720 } else {
20721 if (!sd_match(LHS, m_NUWAddLike(m_Value(LHSOp0), m_Value(LHSOp1))))
20722 return SDValue();
20723 }
20724
20725 SDValue BaseIndex = DAG.getSplatValue(LHSOp0);
20726 if (!BaseIndex) {
20727 std::swap(LHSOp0, LHSOp1);
20728 BaseIndex = DAG.getSplatValue(LHSOp0);
20729 }
20730 if (!BaseIndex || !isa<BuildVectorSDNode>(LHSOp1))
20731 return SDValue();
20732
20733 // Return {a,n} from a build_vector sequence of {a, a+n, a+2n, a+3n, ....}
20734 auto StepVector = cast<BuildVectorSDNode>(LHSOp1)->isArithmeticSequence();
20735 if (!StepVector || !StepVector->second.isOne())
20736 return SDValue();
20737 const APInt &Start = StepVector->first;
20738
20739 Boundary = DAG.getExtOrTrunc(IsSigned, Boundary, DL, ElementVT);
20740 BaseIndex = DAG.getExtOrTrunc(IsSigned, BaseIndex, DL, ElementVT);
20741 SDValue Offset = DAG.getConstant(IsSigned ? Start.sextOrTrunc(ElementSize)
20742 : Start.zextOrTrunc(ElementSize),
20743 DL, ElementVT);
20744
20745 if (IsSigned) {
20746 // Two additional conditions:
20747 // 1. Offset + BaseIndex never overflow
20748 if (!DAG.willNotOverflowAdd(/*IsSigned=*/true, BaseIndex, Offset))
20749 return SDValue();
20750
20751 // 2. Offset + BaseIndex has to be non-negative
20752 auto BaseIndexKB = DAG.computeKnownBits(BaseIndex);
20753 auto OffsetKB = DAG.computeKnownBits(Offset);
20754 if (!KnownBits::add(BaseIndexKB, OffsetKB, /*NSW=*/true,
20755 /*NUW=*/false)
20756 .isNonNegative())
20757 return SDValue();
20758 }
20759
20760 unsigned MinOpc = IsSigned ? ISD::SMIN : ISD::UMIN;
20761 SDValue NewStepVector = DAG.getStepVector(DL, LHS.getValueType());
20762 BaseIndex = DAG.getNode(ISD::ADD, DL, ElementVT, BaseIndex, Offset,
20763 IsSigned ? SDNodeFlags::NoSignedWrap
20765 BaseIndex = DAG.getNode(MinOpc, DL, ElementVT, Boundary, BaseIndex);
20766 Boundary = DAG.getNode(ISD::SUB, DL, ElementVT, Boundary, BaseIndex);
20767 Boundary = DAG.getSplat(RHS.getValueType(), DL, Boundary);
20768
20769 return DAG.getSetCC(DL, MaskVT, NewStepVector, Boundary, CC);
20770}
20771
20772/// Try to map an integer comparison with size > XLEN to vector instructions
20773/// before type legalization splits it up into chunks.
20774static SDValue
20776 const SDLoc &DL, SelectionDAG &DAG,
20777 const RISCVSubtarget &Subtarget) {
20778 assert(ISD::isIntEqualitySetCC(CC) && "Bad comparison predicate");
20779
20780 if (!Subtarget.useRVVForFixedLengthVectors())
20781 return SDValue();
20782
20783 MVT XLenVT = Subtarget.getXLenVT();
20784 EVT OpVT = X.getValueType();
20785 // We're looking for an oversized integer equality comparison.
20786 if (!OpVT.isScalarInteger())
20787 return SDValue();
20788
20789 unsigned OpSize = OpVT.getSizeInBits();
20790 // The size should be larger than XLen and smaller than the maximum vector
20791 // size.
20792 if (OpSize <= Subtarget.getXLen() || OpSize > Subtarget.getRealMinVLen() * 8)
20793 return SDValue();
20794
20795 // Don't perform this combine if constructing the vector will be expensive.
20796 auto IsVectorBitCastCheap = [](SDValue X) {
20798 return isa<ConstantSDNode>(X) || X.getValueType().isVector() ||
20799 X.getOpcode() == ISD::LOAD;
20800 };
20801 if (!IsVectorBitCastCheap(X) || !IsVectorBitCastCheap(Y))
20802 return SDValue();
20803
20805 Attribute::NoImplicitFloat))
20806 return SDValue();
20807
20808 // Bail out for non-byte-sized types.
20809 if (!OpVT.isByteSized())
20810 return SDValue();
20811
20812 // Find a preferred vector element type by inspecting how the value is used.
20813 auto GetPreferredEltVT = [](SDValue V) -> MVT {
20814 // Look backwards: check if V itself is derived from a vector
20815 SDValue Peek = peekThroughBitcasts(V);
20816 EVT PeekVT = Peek.getValueType();
20817
20818 if (PeekVT.isVector() && PeekVT.isInteger()) {
20819 EVT EltVT = PeekVT.getVectorElementType();
20820 if (EltVT.isSimple())
20821 return EltVT.getSimpleVT();
20822 }
20823
20824 // Look forwards: check if V is bitcasted to a vector elsewhere in the DAG
20825 for (SDUse &Use : V->uses()) {
20826 // Ensure we are checking the use of the specific value result, not the
20827 // node's chain
20828 if (Use.getResNo() != V.getResNo())
20829 continue;
20830
20831 SDNode *User = Use.getUser();
20832 if (User->getOpcode() == ISD::BITCAST) {
20833 EVT CastVT = User->getValueType(0);
20834 if (CastVT.isVector() && CastVT.isInteger()) {
20835 EVT EltVT = CastVT.getVectorElementType();
20836 if (EltVT.isSimple())
20837 return EltVT.getSimpleVT();
20838 }
20839 }
20840 }
20842 };
20843
20844 auto IsValidEltVT = [&](MVT VT) {
20845 if (VT == MVT::INVALID_SIMPLE_VALUE_TYPE || !VT.isInteger())
20846 return false;
20847
20848 // Make sure we don't try to create an impossible vector type where the
20849 // elements don't perfectly fill up the OpSize boundary.
20850 unsigned EltSize = VT.getSizeInBits();
20851 if (OpSize % EltSize != 0)
20852 return false;
20853
20854 // Construct the proposed vector type to check its legality
20855 unsigned NumElts = OpSize / EltSize;
20856 EVT TestVecVT = EVT::getVectorVT(*DAG.getContext(), VT, NumElts);
20857 return Subtarget.getTargetLowering()->isTypeLegal(TestVecVT);
20858 };
20859
20860 // Get preferred VT from either X or Y.
20861 MVT EltVT = GetPreferredEltVT(X);
20862 if (!IsValidEltVT(EltVT))
20863 EltVT = GetPreferredEltVT(Y);
20864
20865 // If both are unsuitable, use the safe default (i8)
20866 if (!IsValidEltVT(EltVT))
20867 EltVT = MVT::i8;
20868
20869 unsigned EltSize = EltVT.getSizeInBits();
20870 unsigned NumElts = OpSize / EltSize;
20871 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NumElts);
20872 EVT CmpVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1, NumElts);
20873
20874 SDValue VecX = DAG.getBitcast(VecVT, X);
20875 SDValue VecY;
20876 // Constant fold the common case of comparing with zero. Later optimizations
20877 // might not do this for us.
20878 if (isNullConstant(Y))
20879 VecY = DAG.getConstant(0, DL, VecVT);
20880 else
20881 VecY = DAG.getBitcast(VecVT, Y);
20882
20883 SDValue Cmp = DAG.getSetCC(DL, CmpVT, VecX, VecY, ISD::SETNE);
20884 return DAG.getSetCC(DL, VT, DAG.getNode(ISD::VECREDUCE_OR, DL, XLenVT, Cmp),
20885 DAG.getConstant(0, DL, XLenVT), CC);
20886}
20887
20890 const RISCVSubtarget &Subtarget) {
20891 SelectionDAG &DAG = DCI.DAG;
20892 SDLoc dl(N);
20893 SDValue N0 = N->getOperand(0);
20894 SDValue N1 = N->getOperand(1);
20895 EVT VT = N->getValueType(0);
20896 EVT OpVT = N0.getValueType();
20897
20898 ISD::CondCode Cond = cast<CondCodeSDNode>(N->getOperand(2))->get();
20899 if (SDValue V =
20900 canonicalizeMaskForVLPredicate(VT, N0, N1, Cond, dl, DAG, DCI))
20901 return V;
20902
20903 // Looking for an equality compare.
20904 if (!isIntEqualitySetCC(Cond))
20905 return SDValue();
20906
20907 if (SDValue V =
20908 combineVectorSizedSetCCEquality(VT, N0, N1, Cond, dl, DAG, Subtarget))
20909 return V;
20910
20911 if (DCI.isAfterLegalizeDAG() && isa<ConstantSDNode>(N1) &&
20912 N0.getOpcode() == ISD::AND && N0.hasOneUse() &&
20914 const APInt &AndRHSC = N0.getConstantOperandAPInt(1);
20915 // (X & -(1 << C)) == 0 -> (X >> C) == 0 if the AND constant can't use ANDI.
20916 if (isNullConstant(N1) && !isInt<12>(AndRHSC.getSExtValue()) &&
20917 AndRHSC.isNegatedPowerOf2()) {
20918 unsigned ShiftBits = AndRHSC.countr_zero();
20919 SDValue Shift = DAG.getNode(ISD::SRL, dl, OpVT, N0.getOperand(0),
20920 DAG.getConstant(ShiftBits, dl, OpVT));
20921 return DAG.getSetCC(dl, VT, Shift, N1, Cond);
20922 }
20923
20924 // Similar to above but handling the lower 32 bits by using sraiw. Allow
20925 // comparing with constants other than 0 if the constant can be folded into
20926 // addi or xori after shifting.
20927 uint64_t N1Int = cast<ConstantSDNode>(N1)->getZExtValue();
20928 uint64_t AndRHSInt = AndRHSC.getZExtValue();
20929 if (OpVT == MVT::i64 && isUInt<32>(AndRHSInt) &&
20930 isPowerOf2_32(-uint32_t(AndRHSInt)) && (N1Int & AndRHSInt) == N1Int) {
20931 unsigned ShiftBits = llvm::countr_zero(AndRHSInt);
20932 int64_t NewC = SignExtend64<32>(N1Int) >> ShiftBits;
20933 if (ShiftBits != 0 && NewC >= -2048 && NewC <= 2048) {
20934 SDValue SExt =
20935 DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, OpVT, N0.getOperand(0),
20936 DAG.getValueType(MVT::i32));
20937 SDValue Shift = DAG.getNode(ISD::SRA, dl, OpVT, SExt,
20938 DAG.getConstant(ShiftBits, dl, OpVT));
20939 return DAG.getSetCC(dl, VT, Shift,
20940 DAG.getSignedConstant(NewC, dl, OpVT), Cond);
20941 }
20942 }
20943
20944 // Fold (and X, Mask) ==/!= C -> X ==/!= sext(C, countr_one(Mask)) if the
20945 // Mask is only clearing redundant sign bits.
20946 if (isMask_64(AndRHSInt)) {
20947 unsigned TrailingOnes = llvm::countr_one(AndRHSInt);
20948 unsigned N1Width = llvm::bit_width(N1Int);
20949 int64_t N1SExt = SignExtend64(N1Int, TrailingOnes);
20950 if (N1Width <= TrailingOnes && isInt<12>(N1SExt) &&
20951 DAG.ComputeMaxSignificantBits(N0.getOperand(0)) <= TrailingOnes)
20952 return DAG.getSetCC(dl, VT, N0.getOperand(0),
20953 DAG.getSignedConstant(N1SExt, dl, OpVT), Cond);
20954 }
20955 }
20956
20957 // Replace (seteq (i64 (and X, 0xffffffff)), C1) with
20958 // (seteq (i64 (sext_inreg (X, i32)), C1')) where C1' is C1 sign extended from
20959 // bit 31. Same for setne. C1' may be cheaper to materialize and the
20960 // sext_inreg can become a sext.w instead of a shift pair.
20961 if (OpVT != MVT::i64 || !Subtarget.is64Bit())
20962 return SDValue();
20963
20964 // RHS needs to be a constant.
20965 auto *N1C = dyn_cast<ConstantSDNode>(N1);
20966 if (!N1C)
20967 return SDValue();
20968
20969 // LHS needs to be (and X, 0xffffffff).
20970 if (N0.getOpcode() != ISD::AND || !N0.hasOneUse() ||
20972 N0.getConstantOperandVal(1) != UINT64_C(0xffffffff))
20973 return SDValue();
20974
20975 // Don't do this if the sign bit is provably zero, it will be turned back into
20976 // an AND.
20977 APInt SignMask = APInt::getOneBitSet(64, 31);
20978 if (DAG.MaskedValueIsZero(N0.getOperand(0), SignMask))
20979 return SDValue();
20980
20981 const APInt &C1 = N1C->getAPIntValue();
20982
20983 // If the constant is larger than 2^32 - 1 it is impossible for both sides
20984 // to be equal.
20985 if (C1.getActiveBits() > 32)
20986 return DAG.getBoolConstant(Cond == ISD::SETNE, dl, VT, OpVT);
20987
20988 SDValue SExtOp = DAG.getNode(ISD::SIGN_EXTEND_INREG, N, OpVT,
20989 N0.getOperand(0), DAG.getValueType(MVT::i32));
20990 return DAG.getSetCC(dl, VT, SExtOp, DAG.getConstant(C1.trunc(32).sext(64),
20991 dl, OpVT), Cond);
20992}
20993
20994static SDValue
20996 const RISCVSubtarget &Subtarget) {
20997 SelectionDAG &DAG = DCI.DAG;
20998 SDValue Src = N->getOperand(0);
20999 EVT VT = N->getValueType(0);
21000 EVT SrcVT = cast<VTSDNode>(N->getOperand(1))->getVT();
21001 unsigned Opc = Src.getOpcode();
21002 SDLoc DL(N);
21003
21004 // Fold (sext_inreg (fmv_x_anyexth X), i16) -> (fmv_x_signexth X)
21005 // Don't do this with Zhinx. We need to explicitly sign extend the GPR.
21006 if (Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.bitsGE(MVT::i16) &&
21007 Subtarget.hasStdExtZfhmin())
21008 return DAG.getNode(RISCVISD::FMV_X_SIGNEXTH, DL, VT, Src.getOperand(0));
21009
21010 // Fold (sext_inreg (shl X, Y), i32) -> (sllw X, Y) iff Y u< 32
21011 if (Opc == ISD::SHL && Subtarget.is64Bit() && SrcVT == MVT::i32 &&
21012 VT == MVT::i64 && !isa<ConstantSDNode>(Src.getOperand(1)) &&
21013 DAG.computeKnownBits(Src.getOperand(1)).countMaxActiveBits() <= 5)
21014 return DAG.getNode(RISCVISD::SLLW, DL, VT, Src.getOperand(0),
21015 Src.getOperand(1));
21016
21017 // Fold (sext_inreg (setcc), i1) -> (sub 0, (setcc))
21018 if (Opc == ISD::SETCC && SrcVT == MVT::i1 && DCI.isAfterLegalizeDAG())
21019 return DAG.getNegative(Src, DL, VT);
21020
21021 // Fold (sext_inreg (xor (setcc), -1), i1) -> (add (setcc), -1)
21022 if (Opc == ISD::XOR && SrcVT == MVT::i1 &&
21023 isAllOnesConstant(Src.getOperand(1)) &&
21024 Src.getOperand(0).getOpcode() == ISD::SETCC && DCI.isAfterLegalizeDAG())
21025 return DAG.getNode(ISD::ADD, DL, VT, Src.getOperand(0),
21026 DAG.getAllOnesConstant(DL, VT));
21027
21028 return SDValue();
21029}
21030
21031namespace {
21032// Forward declaration of the structure holding the necessary information to
21033// apply a combine.
21034struct CombineResult;
21035
21036enum ExtKind : uint8_t {
21037 ZExt = 1 << 0,
21038 SExt = 1 << 1,
21039 FPExt = 1 << 2,
21040 BF16Ext = 1 << 3
21041};
21042/// Helper class for folding sign/zero extensions.
21043/// In particular, this class is used for the following combines:
21044/// add | add_vl | or disjoint -> vwadd(u) | vwadd(u)_w
21045/// sub | sub_vl -> vwsub(u) | vwsub(u)_w
21046/// mul | mul_vl -> vwmul(u) | vwmul_su
21047/// shl | shl_vl -> vwsll
21048/// fadd -> vfwadd | vfwadd_w