LLVM 24.0.0git
LegalizeVectorTypes.cpp
Go to the documentation of this file.
1//===------- LegalizeVectorTypes.cpp - Legalization of vector types -------===//
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 performs vector type splitting and scalarization for LegalizeTypes.
10// Scalarization is the act of changing a computation in an illegal one-element
11// vector type to be a computation in its scalar element type. For example,
12// implementing <1 x f32> arithmetic in a scalar f32 register. This is needed
13// as a base case when scalarizing vector arithmetic like <4 x f32>, which
14// eventually decomposes to scalars if the target doesn't support v4f32 or v2f32
15// types.
16// Splitting is the act of changing a computation in an invalid vector type to
17// be a computation in two vectors of half the size. For example, implementing
18// <128 x f32> operations in terms of two <64 x f32> operations.
19//
20//===----------------------------------------------------------------------===//
21
22#include "LegalizeTypes.h"
27#include "llvm/IR/DataLayout.h"
31#include <numeric>
32
33using namespace llvm;
34
35#define DEBUG_TYPE "legalize-types"
36
37//===----------------------------------------------------------------------===//
38// Result Vector Scalarization: <1 x ty> -> ty.
39//===----------------------------------------------------------------------===//
40
41void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
42 LLVM_DEBUG(dbgs() << "Scalarize node result " << ResNo << ": ";
43 N->dump(&DAG));
44 SDValue R = SDValue();
45
46 // See if the target wants to custom expand this node.
47 if (CustomLowerNode(N, N->getValueType(ResNo), true))
48 return;
49
50 switch (N->getOpcode()) {
51 default:
52#ifndef NDEBUG
53 dbgs() << "ScalarizeVectorResult #" << ResNo << ": ";
54 N->dump(&DAG);
55 dbgs() << "\n";
56#endif
57 report_fatal_error("Do not know how to scalarize the result of this "
58 "operator!\n");
59
62 R = ScalarizeVecRes_LOOP_DEPENDENCE_MASK(N);
63 break;
64 case ISD::MERGE_VALUES: R = ScalarizeVecRes_MERGE_VALUES(N, ResNo);break;
65 case ISD::BITCAST: R = ScalarizeVecRes_BITCAST(N); break;
68 R = ScalarizeVecRes_BUILD_VECTOR_OR_SPLAT(N);
69 break;
70 case ISD::EXTRACT_SUBVECTOR: R = ScalarizeVecRes_EXTRACT_SUBVECTOR(N); break;
72 R = ScalarizeVecRes_VECTOR_SHUFFLE_VAR(N);
73 break;
74 case ISD::FP_ROUND: R = ScalarizeVecRes_FP_ROUND(N); break;
76 R = ScalarizeVecRes_CONVERT_FROM_ARBITRARY_FP(N);
77 break;
79 R = ScalarizeVecRes_CONVERT_TO_ARBITRARY_FP(N);
80 break;
81 case ISD::AssertZext:
82 case ISD::AssertSext:
83 case ISD::FPOWI:
85 R = ScalarizeVecRes_UnaryOpWithExtraInput(N);
86 break;
87 case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break;
89 R = ScalarizeVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N));
90 break;
114 R = ScalarizeVecRes_ATOMIC_RMW(cast<AtomicSDNode>(N));
115 break;
116 case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break;
117 case ISD::SCALAR_TO_VECTOR: R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break;
120 R = ScalarizeVecRes_VECTOR_INTERLEAVE_DEINTERLEAVE(N);
121 break;
122 case ISD::SIGN_EXTEND_INREG: R = ScalarizeVecRes_InregOp(N); break;
123 case ISD::VSELECT: R = ScalarizeVecRes_VSELECT(N); break;
124 case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break;
125 case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break;
126 case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break;
128 R = ScalarizeVecRes_VECTOR_MATCH(N);
129 break;
130 case ISD::POISON:
131 case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break;
132 case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break;
133 case ISD::IS_FPCLASS: R = ScalarizeVecRes_IS_FPCLASS(N); break;
137 R = ScalarizeVecRes_VecInregOp(N);
138 break;
139 case ISD::ABS:
141 case ISD::ANY_EXTEND:
142 case ISD::BITREVERSE:
143 case ISD::BSWAP:
144 case ISD::CTLZ:
146 case ISD::CTPOP:
147 case ISD::CTTZ:
149 case ISD::FABS:
150 case ISD::FACOS:
151 case ISD::FASIN:
152 case ISD::FATAN:
153 case ISD::FCEIL:
154 case ISD::FCOS:
155 case ISD::FCOSH:
156 case ISD::FEXP:
157 case ISD::FEXP2:
158 case ISD::FEXP10:
159 case ISD::FFLOOR:
160 case ISD::FLOG:
161 case ISD::FLOG10:
162 case ISD::FLOG2:
163 case ISD::FNEARBYINT:
164 case ISD::FNEG:
165 case ISD::FREEZE:
166 case ISD::ARITH_FENCE:
167 case ISD::FP_EXTEND:
168 case ISD::FP_TO_SINT:
169 case ISD::FP_TO_UINT:
170 case ISD::FRINT:
171 case ISD::LRINT:
172 case ISD::LLRINT:
173 case ISD::FROUND:
174 case ISD::FROUNDEVEN:
175 case ISD::LROUND:
176 case ISD::LLROUND:
177 case ISD::FSIN:
178 case ISD::FSINH:
179 case ISD::FSQRT:
180 case ISD::FTAN:
181 case ISD::FTANH:
182 case ISD::FTRUNC:
183 case ISD::SIGN_EXTEND:
184 case ISD::SINT_TO_FP:
185 case ISD::TRUNCATE:
186 case ISD::UINT_TO_FP:
187 case ISD::ZERO_EXTEND:
189 R = ScalarizeVecRes_UnaryOp(N);
190 break;
192 R = ScalarizeVecRes_ADDRSPACECAST(N);
193 break;
194 case ISD::FMODF:
195 case ISD::FFREXP:
196 case ISD::FSINCOS:
197 case ISD::FSINCOSPI:
198 R = ScalarizeVecRes_UnaryOpWithTwoResults(N, ResNo);
199 break;
200 case ISD::ADD:
201 case ISD::AND:
202 case ISD::AVGCEILS:
203 case ISD::AVGCEILU:
204 case ISD::AVGFLOORS:
205 case ISD::AVGFLOORU:
206 case ISD::FADD:
207 case ISD::FCOPYSIGN:
208 case ISD::FDIV:
209 case ISD::FMUL:
210 case ISD::FMINNUM:
211 case ISD::FMAXNUM:
214 case ISD::FMINIMUM:
215 case ISD::FMAXIMUM:
216 case ISD::FMINIMUMNUM:
217 case ISD::FMAXIMUMNUM:
218 case ISD::ABDS:
219 case ISD::ABDU:
220 case ISD::SMIN:
221 case ISD::SMAX:
222 case ISD::UMIN:
223 case ISD::UMAX:
224
225 case ISD::SADDSAT:
226 case ISD::UADDSAT:
227 case ISD::SSUBSAT:
228 case ISD::USUBSAT:
229 case ISD::SSHLSAT:
230 case ISD::USHLSAT:
231
232 case ISD::FPOW:
233 case ISD::FATAN2:
234 case ISD::FREM:
235 case ISD::FSUB:
236 case ISD::MUL:
237 case ISD::MULHS:
238 case ISD::MULHU:
239 case ISD::OR:
240 case ISD::SDIV:
241 case ISD::SREM:
242 case ISD::SUB:
243 case ISD::UDIV:
244 case ISD::UREM:
245 case ISD::XOR:
246 case ISD::SHL:
247 case ISD::SRA:
248 case ISD::SRL:
249 case ISD::ROTL:
250 case ISD::ROTR:
251 case ISD::CLMUL:
252 case ISD::CLMULR:
253 case ISD::CLMULH:
254 case ISD::PEXT:
255 case ISD::PDEP:
256 R = ScalarizeVecRes_BinOp(N);
257 break;
258
259 case ISD::MASKED_UDIV:
260 case ISD::MASKED_SDIV:
261 case ISD::MASKED_UREM:
262 case ISD::MASKED_SREM:
263 R = ScalarizeVecRes_MaskedBinOp(N);
264 break;
265
266 case ISD::FLDEXP:
267 R = ScalarizeVecRes_FPOp_MultiType(N);
268 break;
269
270 case ISD::SCMP:
271 case ISD::UCMP:
272 R = ScalarizeVecRes_CMP(N);
273 break;
274
275 case ISD::FMA:
276 case ISD::FSHL:
277 case ISD::FSHR:
278 R = ScalarizeVecRes_TernaryOp(N);
279 break;
280
281#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
282 case ISD::STRICT_##DAGN:
283#include "llvm/IR/ConstrainedOps.def"
284 R = ScalarizeVecRes_StrictFPOp(N);
285 break;
286
289 R = ScalarizeVecRes_FP_TO_XINT_SAT(N);
290 break;
291
292 case ISD::UADDO:
293 case ISD::SADDO:
294 case ISD::USUBO:
295 case ISD::SSUBO:
296 case ISD::UMULO:
297 case ISD::SMULO:
298 R = ScalarizeVecRes_OverflowOp(N, ResNo);
299 break;
300 case ISD::SMULFIX:
301 case ISD::SMULFIXSAT:
302 case ISD::UMULFIX:
303 case ISD::UMULFIXSAT:
304 case ISD::SDIVFIX:
305 case ISD::SDIVFIXSAT:
306 case ISD::UDIVFIX:
307 case ISD::UDIVFIXSAT:
308 R = ScalarizeVecRes_FIX(N);
309 break;
314 R = ScalarizeVecRes_PartialReduction(N);
315 break;
316 }
317
318 // If R is null, the sub-method took care of registering the result.
319 if (R.getNode())
320 SetScalarizedVector(SDValue(N, ResNo), R);
321}
322
323SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) {
324 SDValue LHS = GetScalarizedVector(N->getOperand(0));
325 SDValue RHS = GetScalarizedVector(N->getOperand(1));
326 return DAG.getNode(N->getOpcode(), SDLoc(N),
327 LHS.getValueType(), LHS, RHS, N->getFlags());
328}
329
330SDValue DAGTypeLegalizer::ScalarizeVecRes_MaskedBinOp(SDNode *N) {
331 SDLoc DL(N);
332 SDValue LHS = GetScalarizedVector(N->getOperand(0));
333 SDValue RHS = GetScalarizedVector(N->getOperand(1));
334 SDValue Mask = N->getOperand(2);
335 EVT MaskVT = Mask.getValueType();
336 // The vselect result and input vectors need scalarizing, but it's
337 // not a given that the mask does. For instance, in AVX512 v1i1 is legal.
338 // See the similar logic in ScalarizeVecRes_SETCC.
339 if (getTypeAction(MaskVT) == TargetLowering::TypeScalarizeVector)
340 Mask = GetScalarizedVector(Mask);
341 else
342 Mask = DAG.getExtractVectorElt(DL, MaskVT.getVectorElementType(), Mask, 0);
343 // Vectors may have a different boolean contents to scalars, so truncate to i1
344 // and let type legalization promote appropriately.
345 Mask = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Mask);
346 // Masked binary ops don't have UB on disabled lanes but produce poison, so
347 // use 1 as the divisor to avoid division by zero and overflow.
348 SDValue Divisor = DAG.getSelect(DL, LHS.getValueType(), Mask, RHS,
349 DAG.getConstant(1, DL, LHS.getValueType()));
350 return DAG.getNode(ISD::getUnmaskedBinOpOpcode(N->getOpcode()), DL,
351 LHS.getValueType(), LHS, Divisor);
352}
353
354SDValue DAGTypeLegalizer::ScalarizeVecRes_CMP(SDNode *N) {
355 SDLoc DL(N);
356
357 SDValue LHS = N->getOperand(0);
358 SDValue RHS = N->getOperand(1);
359 if (getTypeAction(LHS.getValueType()) ==
361 LHS = GetScalarizedVector(LHS);
362 RHS = GetScalarizedVector(RHS);
363 } else {
364 EVT VT = LHS.getValueType().getVectorElementType();
365 LHS = DAG.getExtractVectorElt(DL, VT, LHS, 0);
366 RHS = DAG.getExtractVectorElt(DL, VT, RHS, 0);
367 }
368
369 return DAG.getNode(N->getOpcode(), SDLoc(N),
370 N->getValueType(0).getVectorElementType(), LHS, RHS);
371}
372
373SDValue DAGTypeLegalizer::ScalarizeVecRes_TernaryOp(SDNode *N) {
374 SDValue Op0 = GetScalarizedVector(N->getOperand(0));
375 SDValue Op1 = GetScalarizedVector(N->getOperand(1));
376 SDValue Op2 = GetScalarizedVector(N->getOperand(2));
377 return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
378 Op2, N->getFlags());
379}
380
381SDValue DAGTypeLegalizer::ScalarizeVecRes_FIX(SDNode *N) {
382 SDValue Op0 = GetScalarizedVector(N->getOperand(0));
383 SDValue Op1 = GetScalarizedVector(N->getOperand(1));
384 SDValue Op2 = N->getOperand(2);
385 return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
386 Op2, N->getFlags());
387}
388
389SDValue DAGTypeLegalizer::ScalarizeVecRes_PartialReduction(SDNode *N) {
390 SDValue Acc = GetScalarizedVector(N->getOperand(0));
391 SDValue L = N->getOperand(1);
392 SDValue R = N->getOperand(2);
393 EVT ResVT = Acc.getValueType();
394 EVT InVT = L.getValueType();
395 bool IsFP = ResVT.isFloatingPoint();
396 SDLoc DL(N);
397
398 // Make sure we're not trying an extending partial reduction in this path.
399 assert(InVT.getScalarType() == ResVT && "Extending operands unsupported");
400
401 SDValue Mul = DAG.getNode(IsFP ? ISD::FMUL : ISD::MUL, DL, InVT, L, R);
402 SDValue In = DAG.getNode(IsFP ? ISD::VECREDUCE_FADD : ISD::VECREDUCE_ADD, DL,
403 ResVT, Mul);
404
405 return DAG.getNode(IsFP ? ISD::FADD : ISD::ADD, DL, ResVT, Acc, In);
406}
407
409DAGTypeLegalizer::ScalarizeVecRes_UnaryOpWithTwoResults(SDNode *N,
410 unsigned ResNo) {
411 assert(N->getValueType(0).getVectorNumElements() == 1 &&
412 "Unexpected vector type!");
413 SDValue Elt = GetScalarizedVector(N->getOperand(0));
414
415 EVT VT0 = N->getValueType(0);
416 EVT VT1 = N->getValueType(1);
417 SDLoc dl(N);
418
419 SDNode *ScalarNode =
420 DAG.getNode(N->getOpcode(), dl,
421 {VT0.getScalarType(), VT1.getScalarType()}, Elt)
422 .getNode();
423
424 // Replace the other vector result not being explicitly scalarized here.
425 unsigned OtherNo = 1 - ResNo;
426 EVT OtherVT = N->getValueType(OtherNo);
427 if (getTypeAction(OtherVT) == TargetLowering::TypeScalarizeVector) {
428 SetScalarizedVector(SDValue(N, OtherNo), SDValue(ScalarNode, OtherNo));
429 } else {
430 SDValue OtherVal = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, OtherVT,
431 SDValue(ScalarNode, OtherNo));
432 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
433 }
434
435 return SDValue(ScalarNode, ResNo);
436}
437
438SDValue DAGTypeLegalizer::ScalarizeVecRes_StrictFPOp(SDNode *N) {
439 EVT VT = N->getValueType(0).getVectorElementType();
440 unsigned NumOpers = N->getNumOperands();
441 SDValue Chain = N->getOperand(0);
442 EVT ValueVTs[] = {VT, MVT::Other};
443 SDLoc dl(N);
444
445 SmallVector<SDValue, 4> Opers(NumOpers);
446
447 // The Chain is the first operand.
448 Opers[0] = Chain;
449
450 // Now process the remaining operands.
451 for (unsigned i = 1; i < NumOpers; ++i) {
452 SDValue Oper = N->getOperand(i);
453 EVT OperVT = Oper.getValueType();
454
455 if (OperVT.isVector()) {
456 if (getTypeAction(OperVT) == TargetLowering::TypeScalarizeVector)
457 Oper = GetScalarizedVector(Oper);
458 else
459 Oper =
460 DAG.getExtractVectorElt(dl, OperVT.getVectorElementType(), Oper, 0);
461 }
462
463 Opers[i] = Oper;
464 }
465
466 SDValue Result = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(ValueVTs),
467 Opers, N->getFlags());
468
469 // Legalize the chain result - switch anything that used the old chain to
470 // use the new one.
471 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
472 return Result;
473}
474
475SDValue DAGTypeLegalizer::ScalarizeVecRes_OverflowOp(SDNode *N,
476 unsigned ResNo) {
477 SDLoc DL(N);
478 EVT ResVT = N->getValueType(0);
479 EVT OvVT = N->getValueType(1);
480
481 SDValue ScalarLHS, ScalarRHS;
482 if (getTypeAction(ResVT) == TargetLowering::TypeScalarizeVector) {
483 ScalarLHS = GetScalarizedVector(N->getOperand(0));
484 ScalarRHS = GetScalarizedVector(N->getOperand(1));
485 } else {
486 SmallVector<SDValue, 1> ElemsLHS, ElemsRHS;
487 DAG.ExtractVectorElements(N->getOperand(0), ElemsLHS);
488 DAG.ExtractVectorElements(N->getOperand(1), ElemsRHS);
489 ScalarLHS = ElemsLHS[0];
490 ScalarRHS = ElemsRHS[0];
491 }
492
493 SDVTList ScalarVTs = DAG.getVTList(
495 SDNode *ScalarNode = DAG.getNode(N->getOpcode(), DL, ScalarVTs,
496 {ScalarLHS, ScalarRHS}, N->getFlags())
497 .getNode();
498
499 // Replace the other vector result not being explicitly scalarized here.
500 unsigned OtherNo = 1 - ResNo;
501 EVT OtherVT = N->getValueType(OtherNo);
502 if (getTypeAction(OtherVT) == TargetLowering::TypeScalarizeVector) {
503 SetScalarizedVector(SDValue(N, OtherNo), SDValue(ScalarNode, OtherNo));
504 } else {
505 SDValue OtherVal = DAG.getNode(
506 ISD::SCALAR_TO_VECTOR, DL, OtherVT, SDValue(ScalarNode, OtherNo));
507 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
508 }
509
510 return SDValue(ScalarNode, ResNo);
511}
512
513SDValue DAGTypeLegalizer::ScalarizeVecRes_MERGE_VALUES(SDNode *N,
514 unsigned ResNo) {
515 SDValue Op = DisintegrateMERGE_VALUES(N, ResNo);
516 return GetScalarizedVector(Op);
517}
518
519SDValue DAGTypeLegalizer::ScalarizeVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
520 SDLoc DL(N);
521 // Reuse the expansion (which should scalarize).
522 SDValue Mask = TLI.expandLoopDependenceMask(N, DAG);
523 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
524 N->getValueType(0).getScalarType(), Mask,
525 DAG.getVectorIdxConstant(0, DL));
526}
527
528SDValue DAGTypeLegalizer::ScalarizeVecRes_BITCAST(SDNode *N) {
529 SDValue Op = N->getOperand(0);
530 if (getTypeAction(Op.getValueType()) == TargetLowering::TypeScalarizeVector)
531 Op = GetScalarizedVector(Op);
532 EVT NewVT = N->getValueType(0).getVectorElementType();
533 return DAG.getNode(ISD::BITCAST, SDLoc(N),
534 NewVT, Op);
535}
536
537SDValue DAGTypeLegalizer::ScalarizeVecRes_BUILD_VECTOR_OR_SPLAT(SDNode *N) {
538 EVT EltVT = N->getValueType(0).getVectorElementType();
539 SDValue InOp = N->getOperand(0);
540 // The BUILD_VECTOR / SPLAT operands may be of wider element types and
541 // we may need to truncate them back to the requested return type.
542 if (EltVT.isInteger())
543 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
544 return InOp;
545}
546
547SDValue DAGTypeLegalizer::ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
548 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
549 N->getValueType(0).getVectorElementType(),
550 N->getOperand(0), N->getOperand(1));
551}
552
553SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE_VAR(SDNode *N) {
554 // Index 0 is the only in-range index.
555 return GetScalarizedVector(N->getOperand(0));
556}
557
558SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_ROUND(SDNode *N) {
559 SDLoc DL(N);
560 SDValue Op = N->getOperand(0);
561 EVT OpVT = Op.getValueType();
562 // The result needs scalarizing, but it's not a given that the source does.
563 // See similar logic in ScalarizeVecRes_UnaryOp.
564 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
565 Op = GetScalarizedVector(Op);
566 } else {
567 EVT VT = OpVT.getVectorElementType();
568 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
569 }
570 return DAG.getNode(ISD::FP_ROUND, DL,
571 N->getValueType(0).getVectorElementType(), Op,
572 N->getOperand(1));
573}
574
575SDValue DAGTypeLegalizer::ScalarizeVecRes_CONVERT_FROM_ARBITRARY_FP(SDNode *N) {
576 SDLoc DL(N);
577 SDValue Op = N->getOperand(0);
578 EVT OpVT = Op.getValueType();
579 // The result needs scalarizing, but it's not a given that the source does.
580 // See similar logic in ScalarizeVecRes_UnaryOp.
581 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
582 Op = GetScalarizedVector(Op);
583 } else {
584 EVT VT = OpVT.getVectorElementType();
585 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
586 }
587 return DAG.getNode(ISD::CONVERT_FROM_ARBITRARY_FP, DL,
588 N->getValueType(0).getVectorElementType(), Op,
589 N->getOperand(1));
590}
591
592SDValue DAGTypeLegalizer::ScalarizeVecRes_CONVERT_TO_ARBITRARY_FP(SDNode *N) {
593 SDLoc DL(N);
594 SDValue Op = N->getOperand(0);
595 EVT OpVT = Op.getValueType();
596 // The result needs scalarizing, but it's not a given that the source does.
597 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
598 Op = GetScalarizedVector(Op);
599 } else {
600 EVT VT = OpVT.getVectorElementType();
601 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
602 }
603 return DAG.getNode(ISD::CONVERT_TO_ARBITRARY_FP, DL,
604 N->getValueType(0).getVectorElementType(), Op,
605 N->getOperand(1), N->getOperand(2), N->getOperand(3));
606}
607
608SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOpWithExtraInput(SDNode *N) {
609 SDValue Op = GetScalarizedVector(N->getOperand(0));
610 return DAG.getNode(N->getOpcode(), SDLoc(N), Op.getValueType(), Op,
611 N->getOperand(1));
612}
613
614SDValue DAGTypeLegalizer::ScalarizeVecRes_FPOp_MultiType(SDNode *N) {
615 SDLoc DL(N);
616 SDValue LHS = GetScalarizedVector(N->getOperand(0));
617 SDValue RHS = N->getOperand(1);
618 EVT RHSVT = RHS.getValueType();
619 // The exponent has its own type action and may not have been scalarized:
620 // v1i1 is legal on AVX-512, v1i32 is widened on AArch64.
621 if (RHSVT.isVector()) {
622 if (getTypeAction(RHSVT) == TargetLowering::TypeScalarizeVector)
623 RHS = GetScalarizedVector(RHS);
624 else
625 RHS = DAG.getExtractVectorElt(DL, RHSVT.getVectorElementType(), RHS, 0);
626 }
627 return DAG.getNode(N->getOpcode(), DL, LHS.getValueType(), LHS, RHS,
628 N->getFlags());
629}
630
631SDValue DAGTypeLegalizer::ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N) {
632 // The value to insert may have a wider type than the vector element type,
633 // so be sure to truncate it to the element type if necessary.
634 SDValue Op = N->getOperand(1);
635 EVT EltVT = N->getValueType(0).getVectorElementType();
636 if (Op.getValueType() != EltVT)
637 // FIXME: Can this happen for floating point types?
638 Op = DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, Op);
639 return Op;
640}
641
642SDValue DAGTypeLegalizer::ScalarizeVecRes_ATOMIC_LOAD(AtomicSDNode *N) {
643 SDValue Result = DAG.getAtomicLoad(
644 N->getExtensionType(), SDLoc(N), N->getMemoryVT().getVectorElementType(),
645 N->getValueType(0).getVectorElementType(), N->getChain(), N->getBasePtr(),
646 N->getMemOperand());
647
648 // Legalize the chain result - switch anything that used the old chain to
649 // use the new one.
650 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
651 return Result;
652}
653
654SDValue DAGTypeLegalizer::ScalarizeVecRes_ATOMIC_RMW(AtomicSDNode *N) {
655 SDValue Result = DAG.getAtomic(
656 N->getOpcode(), SDLoc(N), N->getMemoryVT().getVectorElementType(),
657 N->getChain(), N->getBasePtr(), GetScalarizedVector(N->getVal()),
658 N->getMemOperand());
659
660 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
661 return Result;
662}
663
664SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) {
665 assert(N->isUnindexed() && "Indexed vector load?");
666
667 SDValue Result = DAG.getLoad(
668 ISD::UNINDEXED, N->getExtensionType(),
669 N->getValueType(0).getVectorElementType(), SDLoc(N), N->getChain(),
670 N->getBasePtr(), DAG.getPOISON(N->getBasePtr().getValueType()),
671 N->getPointerInfo(), N->getMemoryVT().getVectorElementType(),
672 N->getBaseAlign(), N->getMemOperand()->getFlags(),
673 N->getMMOMetadataForSubAccess());
674
675 // Legalize the chain result - switch anything that used the old chain to
676 // use the new one.
677 ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
678 return Result;
679}
680
681SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) {
682 // Get the dest type - it doesn't always match the input type, e.g. int_to_fp.
683 EVT DestVT = N->getValueType(0).getVectorElementType();
684 SDValue Op = N->getOperand(0);
685 EVT OpVT = Op.getValueType();
686 SDLoc DL(N);
687 // The result needs scalarizing, but it's not a given that the source does.
688 // This is a workaround for targets where it's impossible to scalarize the
689 // result of a conversion, because the source type is legal.
690 // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32}
691 // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is
692 // legal and was not scalarized.
693 // See the similar logic in ScalarizeVecRes_SETCC
694 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
695 Op = GetScalarizedVector(Op);
696 } else {
697 EVT VT = OpVT.getVectorElementType();
698 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
699 }
700 return DAG.getNode(N->getOpcode(), SDLoc(N), DestVT, Op, N->getFlags());
701}
702
703SDValue DAGTypeLegalizer::ScalarizeVecRes_InregOp(SDNode *N) {
704 EVT EltVT = N->getValueType(0).getVectorElementType();
705 EVT ExtVT = cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType();
706 SDValue LHS = GetScalarizedVector(N->getOperand(0));
707 return DAG.getNode(N->getOpcode(), SDLoc(N), EltVT,
708 LHS, DAG.getValueType(ExtVT));
709}
710
711SDValue DAGTypeLegalizer::ScalarizeVecRes_VecInregOp(SDNode *N) {
712 SDLoc DL(N);
713 SDValue Op = N->getOperand(0);
714
715 EVT OpVT = Op.getValueType();
716 EVT OpEltVT = OpVT.getVectorElementType();
717 EVT EltVT = N->getValueType(0).getVectorElementType();
718
719 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
720 Op = GetScalarizedVector(Op);
721 } else {
722 Op = DAG.getExtractVectorElt(DL, OpEltVT, Op, 0);
723 }
724
725 switch (N->getOpcode()) {
727 return DAG.getNode(ISD::ANY_EXTEND, DL, EltVT, Op);
729 return DAG.getNode(ISD::SIGN_EXTEND, DL, EltVT, Op);
731 return DAG.getNode(ISD::ZERO_EXTEND, DL, EltVT, Op);
732 }
733
734 llvm_unreachable("Illegal extend_vector_inreg opcode");
735}
736
737SDValue DAGTypeLegalizer::ScalarizeVecRes_ADDRSPACECAST(SDNode *N) {
738 EVT DestVT = N->getValueType(0).getVectorElementType();
739 SDValue Op = N->getOperand(0);
740 EVT OpVT = Op.getValueType();
741 SDLoc DL(N);
742 // The result needs scalarizing, but it's not a given that the source does.
743 // This is a workaround for targets where it's impossible to scalarize the
744 // result of a conversion, because the source type is legal.
745 // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32}
746 // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is
747 // legal and was not scalarized.
748 // See the similar logic in ScalarizeVecRes_SETCC
749 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
750 Op = GetScalarizedVector(Op);
751 } else {
752 EVT VT = OpVT.getVectorElementType();
753 Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
754 }
755 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
756 unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
757 unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
758 return DAG.getAddrSpaceCast(DL, DestVT, Op, SrcAS, DestAS,
759 AddrSpaceCastN->getFlags());
760}
761
762SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) {
763 // If the operand is wider than the vector element type then it is implicitly
764 // truncated. Make that explicit here.
765 EVT EltVT = N->getValueType(0).getVectorElementType();
766 SDValue InOp = N->getOperand(0);
767 if (InOp.getValueType() != EltVT)
768 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
769 return InOp;
770}
771
773DAGTypeLegalizer::ScalarizeVecRes_VECTOR_INTERLEAVE_DEINTERLEAVE(SDNode *N) {
774 assert(N->getNumValues() == N->getNumOperands() &&
775 "Expected one result per operand");
776
777 // Interleaving or deinterleaving one-element vectors leaves each result
778 // equal to the corresponding operand.
779 for (unsigned I = 0; I != N->getNumValues(); ++I)
780 SetScalarizedVector(SDValue(N, I), GetScalarizedVector(N->getOperand(I)));
781 return SDValue();
782}
783
784SDValue DAGTypeLegalizer::ScalarizeVecRes_VSELECT(SDNode *N) {
785 SDValue Cond = N->getOperand(0);
786 EVT OpVT = Cond.getValueType();
787 SDLoc DL(N);
788 // The vselect result and true/value operands needs scalarizing, but it's
789 // not a given that the Cond does. For instance, in AVX512 v1i1 is legal.
790 // See the similar logic in ScalarizeVecRes_SETCC
791 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
792 Cond = GetScalarizedVector(Cond);
793 } else {
794 EVT VT = OpVT.getVectorElementType();
795 Cond = DAG.getExtractVectorElt(DL, VT, Cond, 0);
796 }
797
798 SDValue LHS = GetScalarizedVector(N->getOperand(1));
800 TLI.getBooleanContents(false, false);
801 TargetLowering::BooleanContent VecBool = TLI.getBooleanContents(true, false);
802
803 // If integer and float booleans have different contents then we can't
804 // reliably optimize in all cases. There is a full explanation for this in
805 // DAGCombiner::visitSELECT() where the same issue affects folding
806 // (select C, 0, 1) to (xor C, 1).
807 if (TLI.getBooleanContents(false, false) !=
808 TLI.getBooleanContents(false, true)) {
809 // At least try the common case where the boolean is generated by a
810 // comparison.
811 if (Cond->getOpcode() == ISD::SETCC) {
812 EVT OpVT = Cond->getOperand(0).getValueType();
813 ScalarBool = TLI.getBooleanContents(OpVT.getScalarType());
814 VecBool = TLI.getBooleanContents(OpVT);
815 } else
817 }
818
819 EVT CondVT = Cond.getValueType();
820 if (ScalarBool != VecBool) {
821 switch (ScalarBool) {
823 break;
827 // Vector read from all ones, scalar expects a single 1 so mask.
828 Cond = DAG.getNode(ISD::AND, SDLoc(N), CondVT,
829 Cond, DAG.getConstant(1, SDLoc(N), CondVT));
830 break;
834 // Vector reads from a one, scalar from all ones so sign extend.
835 Cond = DAG.getNode(ISD::SIGN_EXTEND_INREG, SDLoc(N), CondVT,
836 Cond, DAG.getValueType(MVT::i1));
837 break;
838 }
839 }
840
841 // Truncate the condition if needed
842 auto BoolVT = getSetCCResultType(CondVT);
843 if (BoolVT.bitsLT(CondVT))
844 Cond = DAG.getNode(ISD::TRUNCATE, SDLoc(N), BoolVT, Cond);
845
846 return DAG.getSelect(SDLoc(N), LHS.getValueType(), Cond, LHS,
847 GetScalarizedVector(N->getOperand(2)), N->getFlags());
848}
849
850SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) {
851 SDValue LHS = GetScalarizedVector(N->getOperand(1));
852 return DAG.getSelect(SDLoc(N),
853 LHS.getValueType(), N->getOperand(0), LHS,
854 GetScalarizedVector(N->getOperand(2)));
855}
856
857SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT_CC(SDNode *N) {
858 SDValue LHS = GetScalarizedVector(N->getOperand(2));
859 return DAG.getNode(ISD::SELECT_CC, SDLoc(N), LHS.getValueType(),
860 N->getOperand(0), N->getOperand(1),
861 LHS, GetScalarizedVector(N->getOperand(3)),
862 N->getOperand(4));
863}
864
865SDValue DAGTypeLegalizer::ScalarizeVecRes_UNDEF(SDNode *N) {
866 return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
867}
868
869SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N) {
870 // Figure out if the scalar is the LHS or RHS and return it.
871 SDValue Arg = N->getOperand(2).getOperand(0);
872 if (Arg.isUndef())
873 return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
874 unsigned Op = !cast<ConstantSDNode>(Arg)->isZero();
875 return GetScalarizedVector(N->getOperand(Op));
876}
877
878SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_TO_XINT_SAT(SDNode *N) {
879 SDValue Src = N->getOperand(0);
880 EVT SrcVT = Src.getValueType();
881 SDLoc dl(N);
882
883 // Handle case where result is scalarized but operand is not
884 if (getTypeAction(SrcVT) == TargetLowering::TypeScalarizeVector)
885 Src = GetScalarizedVector(Src);
886 else
887 Src = DAG.getNode(
889 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
890
891 EVT DstVT = N->getValueType(0).getVectorElementType();
892 return DAG.getNode(N->getOpcode(), dl, DstVT, Src, N->getOperand(1));
893}
894
895SDValue DAGTypeLegalizer::ScalarizeVecRes_SETCC(SDNode *N) {
896 assert(N->getValueType(0).isVector() &&
897 N->getOperand(0).getValueType().isVector() &&
898 "Operand types must be vectors");
899 SDValue LHS = N->getOperand(0);
900 SDValue RHS = N->getOperand(1);
901 EVT OpVT = LHS.getValueType();
902 EVT NVT = N->getValueType(0).getVectorElementType();
903 SDLoc DL(N);
904
905 // The result needs scalarizing, but it's not a given that the source does.
906 if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
907 LHS = GetScalarizedVector(LHS);
908 RHS = GetScalarizedVector(RHS);
909 } else {
910 EVT VT = OpVT.getVectorElementType();
911 LHS = DAG.getExtractVectorElt(DL, VT, LHS, 0);
912 RHS = DAG.getExtractVectorElt(DL, VT, RHS, 0);
913 }
914
915 // Turn it into a scalar SETCC.
916 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
917 N->getOperand(2));
918 // Vectors may have a different boolean contents to scalars. Promote the
919 // value appropriately.
920 ISD::NodeType ExtendCode =
921 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
922 return DAG.getNode(ExtendCode, DL, NVT, Res);
923}
924
925SDValue DAGTypeLegalizer::ScalarizeVecRes_IS_FPCLASS(SDNode *N) {
926 SDLoc DL(N);
927 SDValue Arg = N->getOperand(0);
928 SDValue Test = N->getOperand(1);
929 EVT ArgVT = Arg.getValueType();
930 EVT ResultVT = N->getValueType(0).getVectorElementType();
931
932 if (getTypeAction(ArgVT) == TargetLowering::TypeScalarizeVector) {
933 Arg = GetScalarizedVector(Arg);
934 } else {
935 EVT VT = ArgVT.getVectorElementType();
936 Arg = DAG.getExtractVectorElt(DL, VT, Arg, 0);
937 }
938
939 SDValue Res =
940 DAG.getNode(ISD::IS_FPCLASS, DL, MVT::i1, {Arg, Test}, N->getFlags());
941 // Vectors may have a different boolean contents to scalars. Promote the
942 // value appropriately.
943 ISD::NodeType ExtendCode =
944 TargetLowering::getExtendForContent(TLI.getBooleanContents(ArgVT));
945 return DAG.getNode(ExtendCode, DL, ResultVT, Res);
946}
947
948//===----------------------------------------------------------------------===//
949// Operand Vector Scalarization <1 x ty> -> ty.
950//===----------------------------------------------------------------------===//
951
952bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) {
953 LLVM_DEBUG(dbgs() << "Scalarize node operand " << OpNo << ": ";
954 N->dump(&DAG));
955 SDValue Res = SDValue();
956
957 // See if the target wants to custom scalarize this node.
958 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
959 return false;
960
961 switch (N->getOpcode()) {
962 default:
963#ifndef NDEBUG
964 dbgs() << "ScalarizeVectorOperand Op #" << OpNo << ": ";
965 N->dump(&DAG);
966 dbgs() << "\n";
967#endif
968 report_fatal_error("Do not know how to scalarize this operator's "
969 "operand!\n");
970 case ISD::BITCAST:
971 Res = ScalarizeVecOp_BITCAST(N);
972 break;
973 case ISD::FAKE_USE:
974 Res = ScalarizeVecOp_FAKE_USE(N);
975 break;
977 // Index 0 is the only in-range index.
978 Res = N->getOperand(0);
979 break;
980 case ISD::ANY_EXTEND:
981 case ISD::ZERO_EXTEND:
982 case ISD::SIGN_EXTEND:
983 case ISD::TRUNCATE:
984 case ISD::FP_TO_SINT:
985 case ISD::FP_TO_UINT:
986 case ISD::SINT_TO_FP:
987 case ISD::UINT_TO_FP:
988 case ISD::LROUND:
989 case ISD::LLROUND:
990 case ISD::LRINT:
991 case ISD::LLRINT:
992 Res = ScalarizeVecOp_UnaryOp(N);
993 break;
997 Res = ScalarizeVecOp_UnaryOpWithExtraInput(N);
998 break;
1000 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1001 "Unexpected vector type!");
1002 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1003 SDValue Op = DAG.getNode(
1004 N->getOpcode(), SDLoc(N), N->getValueType(0).getScalarType(), Elt,
1005 N->getOperand(1), N->getOperand(2), N->getOperand(3));
1006 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
1007 break;
1008 }
1013 Res = ScalarizeVecOp_UnaryOp_StrictFP(N);
1014 break;
1016 Res = ScalarizeVecOp_CONCAT_VECTORS(N);
1017 break;
1019 Res = ScalarizeVecOp_INSERT_SUBVECTOR(N, OpNo);
1020 break;
1022 Res = ScalarizeVecOp_EXTRACT_VECTOR_ELT(N);
1023 break;
1024 case ISD::VSELECT:
1025 Res = ScalarizeVecOp_VSELECT(N);
1026 break;
1027 case ISD::SETCC:
1028 Res = ScalarizeVecOp_VSETCC(N);
1029 break;
1030 case ISD::STRICT_FSETCC:
1032 Res = ScalarizeVecOp_VSTRICT_FSETCC(N, OpNo);
1033 break;
1034 case ISD::STORE:
1035 Res = ScalarizeVecOp_STORE(cast<StoreSDNode>(N), OpNo);
1036 break;
1037 case ISD::ATOMIC_STORE:
1038 Res = ScalarizeVecOp_ATOMIC_STORE(cast<AtomicSDNode>(N));
1039 break;
1040 case ISD::MLOAD:
1041 Res = ScalarizeVecOp_MLOAD(cast<MaskedLoadSDNode>(N), OpNo);
1042 break;
1043 case ISD::MSTORE:
1044 Res = ScalarizeVecOp_MSTORE(cast<MaskedStoreSDNode>(N), OpNo);
1045 break;
1047 Res = ScalarizeVecOp_STRICT_FP_ROUND(N, OpNo);
1048 break;
1049 case ISD::FP_ROUND:
1050 Res = ScalarizeVecOp_FP_ROUND(N, OpNo);
1051 break;
1053 Res = ScalarizeVecOp_STRICT_FP_EXTEND(N);
1054 break;
1055 case ISD::FP_EXTEND:
1056 Res = ScalarizeVecOp_FP_EXTEND(N);
1057 break;
1060 case ISD::VECREDUCE_ADD:
1061 case ISD::VECREDUCE_MUL:
1062 case ISD::VECREDUCE_AND:
1063 case ISD::VECREDUCE_OR:
1064 case ISD::VECREDUCE_XOR:
1075 Res = ScalarizeVecOp_VECREDUCE(N);
1076 break;
1079 Res = ScalarizeVecOp_VECREDUCE_SEQ(N);
1080 break;
1081 case ISD::SCMP:
1082 case ISD::UCMP:
1083 Res = ScalarizeVecOp_CMP(N);
1084 break;
1086 Res = ScalarizeVecOp_VECTOR_FIND_LAST_ACTIVE(N);
1087 break;
1088 case ISD::CTTZ_ELTS:
1090 Res = ScalarizeVecOp_CTTZ_ELTS(N);
1091 break;
1092 case ISD::VECTOR_MATCH:
1093 Res = ScalarizeVecOp_VECTOR_MATCH(N, OpNo);
1094 break;
1095 case ISD::MASKED_UDIV:
1096 case ISD::MASKED_SDIV:
1097 case ISD::MASKED_UREM:
1098 case ISD::MASKED_SREM:
1099 Res = ScalarizeVecOp_MaskedBinOp(N, OpNo);
1100 break;
1101 }
1102
1103 // If the result is null, the sub-method took care of registering results etc.
1104 if (!Res.getNode()) return false;
1105
1106 // If the result is N, the sub-method updated N in place. Tell the legalizer
1107 // core about this.
1108 if (Res.getNode() == N)
1109 return true;
1110
1111 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
1112 "Invalid operand expansion");
1113
1114 ReplaceValueWith(SDValue(N, 0), Res);
1115 return false;
1116}
1117
1118/// If the value to convert is a vector that needs to be scalarized, it must be
1119/// <1 x ty>. Convert the element instead.
1120SDValue DAGTypeLegalizer::ScalarizeVecOp_BITCAST(SDNode *N) {
1121 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1122 return DAG.getNode(ISD::BITCAST, SDLoc(N),
1123 N->getValueType(0), Elt);
1124}
1125
1126// Need to legalize vector operands of fake uses. Must be <1 x ty>.
1127SDValue DAGTypeLegalizer::ScalarizeVecOp_FAKE_USE(SDNode *N) {
1128 assert(N->getOperand(1).getValueType().getVectorNumElements() == 1 &&
1129 "Fake Use: Unexpected vector type!");
1130 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1131 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0), Elt);
1132}
1133
1134/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
1135/// Do the operation on the element instead.
1136SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp(SDNode *N) {
1137 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1138 "Unexpected vector type!");
1139 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1140 SDValue Op = DAG.getNode(N->getOpcode(), SDLoc(N),
1141 N->getValueType(0).getScalarType(), Elt);
1142 // Revectorize the result so the types line up with what the uses of this
1143 // expression expect.
1144 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
1145}
1146
1147/// Same as ScalarizeVecOp_UnaryOp with an extra operand (for example a
1148/// typesize).
1149SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOpWithExtraInput(SDNode *N) {
1150 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1151 "Unexpected vector type!");
1152 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1153 SDValue Op =
1154 DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0).getScalarType(),
1155 Elt, N->getOperand(1));
1156 // Revectorize the result so the types line up with what the uses of this
1157 // expression expect.
1158 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
1159}
1160
1161/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
1162/// Do the strict FP operation on the element instead.
1163SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp_StrictFP(SDNode *N) {
1164 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1165 "Unexpected vector type!");
1166 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1167 SDValue Res = DAG.getNode(N->getOpcode(), SDLoc(N),
1168 { N->getValueType(0).getScalarType(), MVT::Other },
1169 { N->getOperand(0), Elt });
1170 // Legalize the chain result - switch anything that used the old chain to
1171 // use the new one.
1172 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1173 // Revectorize the result so the types line up with what the uses of this
1174 // expression expect.
1175 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1176
1177 // Do our own replacement and return SDValue() to tell the caller that we
1178 // handled all replacements since caller can only handle a single result.
1179 ReplaceValueWith(SDValue(N, 0), Res);
1180 return SDValue();
1181}
1182
1183/// The vectors to concatenate have length one - use a BUILD_VECTOR instead.
1184SDValue DAGTypeLegalizer::ScalarizeVecOp_CONCAT_VECTORS(SDNode *N) {
1185 SmallVector<SDValue, 8> Ops(N->getNumOperands());
1186 for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i)
1187 Ops[i] = GetScalarizedVector(N->getOperand(i));
1188 return DAG.getBuildVector(N->getValueType(0), SDLoc(N), Ops);
1189}
1190
1191/// The inserted subvector is to be scalarized - use insert vector element
1192/// instead.
1193SDValue DAGTypeLegalizer::ScalarizeVecOp_INSERT_SUBVECTOR(SDNode *N,
1194 unsigned OpNo) {
1195 // We should not be attempting to scalarize the containing vector
1196 assert(OpNo == 1);
1197 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1198 SDValue ContainingVec = N->getOperand(0);
1199 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
1200 ContainingVec.getValueType(), ContainingVec, Elt,
1201 N->getOperand(2));
1202}
1203
1204/// If the input is a vector that needs to be scalarized, it must be <1 x ty>,
1205/// so just return the element, ignoring the index.
1206SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
1207 EVT VT = N->getValueType(0);
1208 SDValue Res = GetScalarizedVector(N->getOperand(0));
1209 if (Res.getValueType() != VT)
1210 Res = VT.isFloatingPoint()
1211 ? DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, Res)
1212 : DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), VT, Res);
1213 return Res;
1214}
1215
1216/// If the input condition is a vector that needs to be scalarized, it must be
1217/// <1 x i1>, so just convert to a normal ISD::SELECT
1218/// (still with vector output type since that was acceptable if we got here).
1219SDValue DAGTypeLegalizer::ScalarizeVecOp_VSELECT(SDNode *N) {
1220 SDValue ScalarCond = GetScalarizedVector(N->getOperand(0));
1221 EVT VT = N->getValueType(0);
1222
1223 return DAG.getNode(ISD::SELECT, SDLoc(N), VT, ScalarCond, N->getOperand(1),
1224 N->getOperand(2));
1225}
1226
1227/// If the operand is a vector that needs to be scalarized then the
1228/// result must be a single-element vector, so just convert to a scalar
1229/// SETCC and wrap with a scalar_to_vector since the res type is legal
1230/// if we got here
1231SDValue DAGTypeLegalizer::ScalarizeVecOp_VSETCC(SDNode *N) {
1232 assert(N->getValueType(0).isVector() &&
1233 N->getOperand(0).getValueType().isVector() &&
1234 "Operand types must be vectors");
1235 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1236 "Expected single-element vector type");
1237
1238 EVT VT = N->getValueType(0);
1239 SDValue LHS = GetScalarizedVector(N->getOperand(0));
1240 SDValue RHS = GetScalarizedVector(N->getOperand(1));
1241
1242 EVT OpVT = N->getOperand(0).getValueType();
1243 EVT NVT = VT.getVectorElementType();
1244 SDLoc DL(N);
1245 // Turn it into a scalar SETCC.
1246 SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
1247 N->getOperand(2));
1248
1249 // Vectors may have a different boolean contents to scalars. Promote the
1250 // value appropriately.
1251 ISD::NodeType ExtendCode =
1252 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
1253
1254 Res = DAG.getNode(ExtendCode, DL, NVT, Res);
1255
1256 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res);
1257}
1258
1259// Similiar to ScalarizeVecOp_VSETCC, with added logic to update chains.
1260SDValue DAGTypeLegalizer::ScalarizeVecOp_VSTRICT_FSETCC(SDNode *N,
1261 unsigned OpNo) {
1262 assert(OpNo == 1 && "Wrong operand for scalarization!");
1263 assert(N->getValueType(0).isVector() &&
1264 N->getOperand(1).getValueType().isVector() &&
1265 "Operand types must be vectors");
1266 assert(N->getValueType(0).getVectorNumElements() == 1 &&
1267 "Expected single-element vector type");
1268
1269 EVT VT = N->getValueType(0);
1270 SDValue Ch = N->getOperand(0);
1271 SDValue LHS = GetScalarizedVector(N->getOperand(1));
1272 SDValue RHS = GetScalarizedVector(N->getOperand(2));
1273 SDValue CC = N->getOperand(3);
1274
1275 EVT OpVT = N->getOperand(1).getValueType();
1276 EVT NVT = VT.getVectorElementType();
1277 SDLoc DL(N);
1278 SDValue Res = DAG.getNode(N->getOpcode(), DL, {MVT::i1, MVT::Other},
1279 {Ch, LHS, RHS, CC});
1280
1281 // Legalize the chain result - switch anything that used the old chain to
1282 // use the new one.
1283 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1284
1285 ISD::NodeType ExtendCode =
1286 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
1287
1288 Res = DAG.getNode(ExtendCode, DL, NVT, Res);
1289 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res);
1290
1291 // Do our own replacement and return SDValue() to tell the caller that we
1292 // handled all replacements since caller can only handle a single result.
1293 ReplaceValueWith(SDValue(N, 0), Res);
1294 return SDValue();
1295}
1296
1297/// If the value to store is a vector that needs to be scalarized, it must be
1298/// <1 x ty>. Just store the element.
1299SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){
1300 assert(N->isUnindexed() && "Indexed store of one-element vector?");
1301 assert(OpNo == 1 && "Do not know how to scalarize this operand!");
1302 SDLoc dl(N);
1303
1304 if (N->isTruncatingStore())
1305 return DAG.getTruncStore(
1306 N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
1307 N->getBasePtr(), N->getPointerInfo(),
1308 N->getMemoryVT().getVectorElementType(), N->getBaseAlign(),
1309 N->getMemOperand()->getFlags(), N->getMMOMetadataForSubAccess());
1310
1311 return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
1312 N->getBasePtr(), N->getPointerInfo(), N->getBaseAlign(),
1313 N->getMemOperand()->getFlags(),
1314 N->getMMOMetadataForSubAccess());
1315}
1316
1317/// If the value to store is a vector that needs to be scalarized, it must be
1318/// <1 x ty>. Just store the element.
1319SDValue DAGTypeLegalizer::ScalarizeVecOp_ATOMIC_STORE(AtomicSDNode *N) {
1320 SDValue ScalarVal = GetScalarizedVector(N->getVal());
1321 return DAG.getAtomic(ISD::ATOMIC_STORE, SDLoc(N),
1322 N->getMemoryVT().getVectorElementType(), N->getChain(),
1323 ScalarVal, N->getBasePtr(), N->getMemOperand());
1324}
1325
1326/// If the mask is a vector that needs to be scalarized, it must be <1 x i1>.
1327/// Promote it to a target boolean instead.
1328SDValue DAGTypeLegalizer::ScalarizeVecOp_MLOAD(MaskedLoadSDNode *N,
1329 unsigned OpNo) {
1330 assert(OpNo == 3 && "Can only scalarize the mask operand!");
1331 EVT DataVT = N->getValueType(0);
1332 SDValue Mask = PromoteTargetBoolean(N->getOperand(OpNo), DataVT);
1333 SmallVector<SDValue, 4> NewOps(N->ops());
1334 NewOps[OpNo] = Mask;
1335 SDNode *Res = DAG.UpdateNodeOperands(N, NewOps);
1336 if (Res == N)
1337 return SDValue(Res, 0);
1338
1339 // Update triggered CSE, do our own replacement since caller can't.
1340 ReplaceValueWith(SDValue(N, 0), SDValue(Res, 0));
1341 ReplaceValueWith(SDValue(N, 1), SDValue(Res, 1));
1342 return SDValue();
1343}
1344
1345/// If the mask is a vector that needs to be scalarized, it must be <1 x i1>.
1346/// Promote it to a target boolean instead.
1347SDValue DAGTypeLegalizer::ScalarizeVecOp_MSTORE(MaskedStoreSDNode *N,
1348 unsigned OpNo) {
1349 assert(!N->isCompressingStore() && "CompressingStore not expected");
1350 if (OpNo != 4)
1351 reportFatalInternalError("Scalarization of MSTORE data is not supported");
1352 EVT DataVT = N->getValue().getValueType();
1353 SmallVector<SDValue, 4> NewOps(N->ops());
1354 NewOps[OpNo] = PromoteTargetBoolean(N->getOperand(OpNo), DataVT);
1355 return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0);
1356}
1357
1358/// If the value to round is a vector that needs to be scalarized, it must be
1359/// <1 x ty>. Convert the element instead.
1360SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_ROUND(SDNode *N, unsigned OpNo) {
1361 assert(OpNo == 0 && "Wrong operand for scalarization!");
1362 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1363 SDValue Res = DAG.getNode(ISD::FP_ROUND, SDLoc(N),
1364 N->getValueType(0).getVectorElementType(), Elt,
1365 N->getOperand(1));
1366 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1367}
1368
1369SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_ROUND(SDNode *N,
1370 unsigned OpNo) {
1371 assert(OpNo == 1 && "Wrong operand for scalarization!");
1372 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1373 SDValue Res =
1374 DAG.getNode(ISD::STRICT_FP_ROUND, SDLoc(N),
1375 {N->getValueType(0).getVectorElementType(), MVT::Other},
1376 {N->getOperand(0), Elt, N->getOperand(2)});
1377 // Legalize the chain result - switch anything that used the old chain to
1378 // use the new one.
1379 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1380
1381 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1382
1383 // Do our own replacement and return SDValue() to tell the caller that we
1384 // handled all replacements since caller can only handle a single result.
1385 ReplaceValueWith(SDValue(N, 0), Res);
1386 return SDValue();
1387}
1388
1389/// If the value to extend is a vector that needs to be scalarized, it must be
1390/// <1 x ty>. Convert the element instead.
1391SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_EXTEND(SDNode *N) {
1392 SDValue Elt = GetScalarizedVector(N->getOperand(0));
1393 SDValue Res = DAG.getNode(ISD::FP_EXTEND, SDLoc(N),
1394 N->getValueType(0).getVectorElementType(), Elt);
1395 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1396}
1397
1398/// If the value to extend is a vector that needs to be scalarized, it must be
1399/// <1 x ty>. Convert the element instead.
1400SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_EXTEND(SDNode *N) {
1401 SDValue Elt = GetScalarizedVector(N->getOperand(1));
1402 SDValue Res =
1403 DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(N),
1404 {N->getValueType(0).getVectorElementType(), MVT::Other},
1405 {N->getOperand(0), Elt});
1406 // Legalize the chain result - switch anything that used the old chain to
1407 // use the new one.
1408 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
1409
1410 Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
1411
1412 // Do our own replacement and return SDValue() to tell the caller that we
1413 // handled all replacements since caller can only handle a single result.
1414 ReplaceValueWith(SDValue(N, 0), Res);
1415 return SDValue();
1416}
1417
1418SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE(SDNode *N) {
1419 SDValue Res = GetScalarizedVector(N->getOperand(0));
1420 // Result type may be wider than element type.
1421 if (Res.getValueType() != N->getValueType(0))
1422 Res = DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), N->getValueType(0), Res);
1423 return Res;
1424}
1425
1426SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE_SEQ(SDNode *N) {
1427 SDValue AccOp = N->getOperand(0);
1428 SDValue VecOp = N->getOperand(1);
1429
1430 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
1431
1432 SDValue Op = GetScalarizedVector(VecOp);
1433 return DAG.getNode(BaseOpc, SDLoc(N), N->getValueType(0),
1434 AccOp, Op, N->getFlags());
1435}
1436
1437SDValue DAGTypeLegalizer::ScalarizeVecOp_CMP(SDNode *N) {
1438 SDValue LHS = GetScalarizedVector(N->getOperand(0));
1439 SDValue RHS = GetScalarizedVector(N->getOperand(1));
1440
1441 EVT ResVT = N->getValueType(0).getVectorElementType();
1442 SDValue Cmp = DAG.getNode(N->getOpcode(), SDLoc(N), ResVT, LHS, RHS);
1443 return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Cmp);
1444}
1445
1446SDValue DAGTypeLegalizer::ScalarizeVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
1447 // Since there is no "none-active" result, the only valid return for <1 x ty>
1448 // is 0. Note: Since we check the high mask during splitting this is safe.
1449 // As e.g., a <2 x ty> operation would split to:
1450 // any_active(%hi_mask) ? (1 + last_active(%hi_mask))
1451 // : `last_active(%lo_mask)`
1452 // Which then scalarizes to:
1453 // %mask[1] ? 1 : 0
1454 EVT VT = N->getValueType(0);
1455 return DAG.getConstant(0, SDLoc(N), VT);
1456}
1457
1458SDValue DAGTypeLegalizer::ScalarizeVecOp_CTTZ_ELTS(SDNode *N) {
1459 // The number of trailing zero elements is 1 if the element is 0, and 0
1460 // otherwise.
1461 if (N->getOpcode() == ISD::CTTZ_ELTS_ZERO_POISON)
1462 return DAG.getConstant(0, SDLoc(N), N->getValueType(0));
1463 SDValue Op = GetScalarizedVector(N->getOperand(0));
1464 SDValue SetCC =
1465 DAG.getSetCC(SDLoc(N), MVT::i1, Op,
1466 DAG.getConstant(0, SDLoc(N), Op.getValueType()), ISD::SETEQ);
1467 return DAG.getZExtOrTrunc(SetCC, SDLoc(N), N->getValueType(0));
1468}
1469
1470SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_MATCH(SDNode *N) {
1471 SDLoc DL(N);
1472 // Reuse the expansion (which should scalarize).
1473 SDValue Mask = TLI.expandVectorMatch(N, DAG);
1474 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL,
1475 N->getValueType(0).getScalarType(), Mask,
1476 DAG.getVectorIdxConstant(0, DL));
1477}
1478
1479SDValue DAGTypeLegalizer::ScalarizeVecOp_VECTOR_MATCH(SDNode *N,
1480 unsigned OpNo) {
1481 return TLI.expandVectorMatch(N, DAG);
1482}
1483
1484SDValue DAGTypeLegalizer::ScalarizeVecOp_MaskedBinOp(SDNode *N, unsigned OpNo) {
1485 assert(OpNo == 2 && "Can only scalarize mask operand");
1486 SDLoc DL(N);
1487 EVT VT = N->getOperand(0).getValueType().getVectorElementType();
1488 SDValue LHS = DAG.getExtractVectorElt(DL, VT, N->getOperand(0), 0);
1489 SDValue RHS = DAG.getExtractVectorElt(DL, VT, N->getOperand(1), 0);
1490 SDValue Mask = GetScalarizedVector(N->getOperand(2));
1491 // Vectors may have a different boolean contents to scalars, so truncate to i1
1492 // and let type legalization promote appropriately.
1493 Mask = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Mask);
1494 // Masked binary ops don't have UB on disabled lanes but produce poison, so
1495 // use 1 as the divisor to avoid division by zero and overflow.
1496 SDValue BinOp =
1497 DAG.getNode(ISD::getUnmaskedBinOpOpcode(N->getOpcode()), DL, VT, LHS,
1498 DAG.getSelect(DL, VT, Mask, RHS, DAG.getConstant(1, DL, VT)));
1499 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, N->getValueType(0), BinOp);
1500}
1501
1502//===----------------------------------------------------------------------===//
1503// Result Vector Splitting
1504//===----------------------------------------------------------------------===//
1505
1506/// This method is called when the specified result of the specified node is
1507/// found to need vector splitting. At this point, the node may also have
1508/// invalid operands or may have other results that need legalization, we just
1509/// know that (at least) one result needs vector splitting.
1510void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
1511 LLVM_DEBUG(dbgs() << "Split node result: "; N->dump(&DAG));
1512 SDValue Lo, Hi;
1513
1514 // See if the target wants to custom expand this node.
1515 if (CustomLowerNode(N, N->getValueType(ResNo), true))
1516 return;
1517
1518 switch (N->getOpcode()) {
1519 default:
1520#ifndef NDEBUG
1521 dbgs() << "SplitVectorResult #" << ResNo << ": ";
1522 N->dump(&DAG);
1523 dbgs() << "\n";
1524#endif
1525 report_fatal_error("Do not know how to split the result of this "
1526 "operator!\n");
1527
1530 SplitVecRes_LOOP_DEPENDENCE_MASK(N, Lo, Hi);
1531 break;
1533 SplitVecRes_MASK_BEFOREFIRST(N, Lo, Hi);
1534 break;
1535 case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
1536 case ISD::AssertZext: SplitVecRes_AssertZext(N, Lo, Hi); break;
1537 case ISD::AssertSext: SplitVecRes_AssertSext(N, Lo, Hi); break;
1538 case ISD::VSELECT:
1539 case ISD::SELECT:
1540 case ISD::VP_MERGE: SplitRes_Select(N, Lo, Hi); break;
1541 case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
1542 case ISD::POISON:
1543 case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
1544 case ISD::BITCAST: SplitVecRes_BITCAST(N, Lo, Hi); break;
1545 case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break;
1546 case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break;
1547 case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break;
1548 case ISD::INSERT_SUBVECTOR: SplitVecRes_INSERT_SUBVECTOR(N, Lo, Hi); break;
1549 case ISD::FPOWI:
1550 case ISD::FLDEXP:
1551 case ISD::FCOPYSIGN: SplitVecRes_FPOp_MultiType(N, Lo, Hi); break;
1552 case ISD::IS_FPCLASS: SplitVecRes_IS_FPCLASS(N, Lo, Hi); break;
1553 case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break;
1554 case ISD::SPLAT_VECTOR:
1556 SplitVecRes_ScalarOp(N, Lo, Hi);
1557 break;
1558 case ISD::STEP_VECTOR:
1559 SplitVecRes_STEP_VECTOR(N, Lo, Hi);
1560 break;
1561 case ISD::SIGN_EXTEND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break;
1562 case ISD::ATOMIC_LOAD:
1563 SplitVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N), Lo, Hi);
1564 break;
1565 case ISD::LOAD:
1566 SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi);
1567 break;
1568 case ISD::VP_LOAD:
1569 SplitVecRes_VP_LOAD(cast<VPLoadSDNode>(N), Lo, Hi);
1570 break;
1571 case ISD::VP_LOAD_FF:
1572 SplitVecRes_VP_LOAD_FF(cast<VPLoadFFSDNode>(N), Lo, Hi);
1573 break;
1574 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
1575 SplitVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N), Lo, Hi);
1576 break;
1577 case ISD::MLOAD:
1578 SplitVecRes_MLOAD(cast<MaskedLoadSDNode>(N), Lo, Hi);
1579 break;
1580 case ISD::MGATHER:
1581 case ISD::VP_GATHER:
1582 SplitVecRes_Gather(cast<MemSDNode>(N), Lo, Hi, /*SplitSETCC*/ true);
1583 break;
1585 SplitVecRes_VECTOR_COMPRESS(N, Lo, Hi);
1586 break;
1588 SplitVecRes_VECTOR_SHUFFLE_VAR(N, Lo, Hi);
1589 break;
1590 case ISD::SETCC:
1591 SplitVecRes_SETCC(N, Lo, Hi);
1592 break;
1593 case ISD::VECTOR_REPEAT:
1594 SplitVecRes_VECTOR_REPEAT(N, Lo, Hi);
1595 break;
1597 SplitVecRes_VECTOR_REVERSE(N, Lo, Hi);
1598 break;
1600 SplitVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N), Lo, Hi);
1601 break;
1604 SplitVecRes_VECTOR_SPLICE(N, Lo, Hi);
1605 break;
1607 SplitVecRes_VECTOR_DEINTERLEAVE(N);
1608 return;
1610 SplitVecRes_VECTOR_INTERLEAVE(N);
1611 return;
1612 case ISD::VAARG:
1613 SplitVecRes_VAARG(N, Lo, Hi);
1614 break;
1615
1619 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
1620 break;
1621
1622 case ISD::ABS:
1624 case ISD::BITREVERSE:
1625 case ISD::BSWAP:
1626 case ISD::CTLZ:
1627 case ISD::CTTZ:
1630 case ISD::CTPOP:
1631 case ISD::FABS:
1632 case ISD::FACOS:
1633 case ISD::FASIN:
1634 case ISD::FATAN:
1635 case ISD::FCEIL:
1636 case ISD::FCOS:
1637 case ISD::FCOSH:
1638 case ISD::FEXP:
1639 case ISD::FEXP2:
1640 case ISD::FEXP10:
1641 case ISD::FFLOOR:
1642 case ISD::FLOG:
1643 case ISD::FLOG10:
1644 case ISD::FLOG2:
1645 case ISD::FNEARBYINT:
1646 case ISD::FNEG:
1647 case ISD::FREEZE:
1648 case ISD::ARITH_FENCE:
1649 case ISD::FP_EXTEND:
1650 case ISD::FP_ROUND:
1651 case ISD::FP_TO_SINT:
1652 case ISD::FP_TO_UINT:
1653 case ISD::FRINT:
1654 case ISD::LRINT:
1655 case ISD::LLRINT:
1656 case ISD::FROUND:
1657 case ISD::FROUNDEVEN:
1658 case ISD::LROUND:
1659 case ISD::LLROUND:
1660 case ISD::FSIN:
1661 case ISD::FSINH:
1662 case ISD::FSQRT:
1663 case ISD::FTAN:
1664 case ISD::FTANH:
1665 case ISD::FTRUNC:
1666 case ISD::SINT_TO_FP:
1667 case ISD::TRUNCATE:
1668 case ISD::UINT_TO_FP:
1669 case ISD::FCANONICALIZE:
1673 SplitVecRes_UnaryOp(N, Lo, Hi);
1674 break;
1675 case ISD::ADDRSPACECAST:
1676 SplitVecRes_ADDRSPACECAST(N, Lo, Hi);
1677 break;
1678 case ISD::FMODF:
1679 case ISD::FFREXP:
1680 case ISD::FSINCOS:
1681 case ISD::FSINCOSPI:
1682 SplitVecRes_UnaryOpWithTwoResults(N, ResNo, Lo, Hi);
1683 break;
1684
1685 case ISD::ANY_EXTEND:
1686 case ISD::SIGN_EXTEND:
1687 case ISD::ZERO_EXTEND:
1688 SplitVecRes_ExtendOp(N, Lo, Hi);
1689 break;
1690
1691 case ISD::ADD:
1692 case ISD::SUB:
1693 case ISD::MUL:
1694 case ISD::CLMUL:
1695 case ISD::CLMULR:
1696 case ISD::CLMULH:
1697 case ISD::PEXT:
1698 case ISD::PDEP:
1699 case ISD::MULHS:
1700 case ISD::MULHU:
1701 case ISD::ABDS:
1702 case ISD::ABDU:
1703 case ISD::AVGCEILS:
1704 case ISD::AVGCEILU:
1705 case ISD::AVGFLOORS:
1706 case ISD::AVGFLOORU:
1707 case ISD::FADD:
1708 case ISD::FSUB:
1709 case ISD::FMUL:
1710 case ISD::FMINNUM:
1711 case ISD::FMINNUM_IEEE:
1712 case ISD::FMAXNUM:
1713 case ISD::FMAXNUM_IEEE:
1714 case ISD::FMINIMUM:
1715 case ISD::FMAXIMUM:
1716 case ISD::FMINIMUMNUM:
1717 case ISD::FMAXIMUMNUM:
1718 case ISD::SDIV: case ISD::VP_SDIV:
1719 case ISD::UDIV: case ISD::VP_UDIV:
1720 case ISD::FDIV:
1721 case ISD::FPOW:
1722 case ISD::FATAN2:
1723 case ISD::AND:
1724 case ISD::OR:
1725 case ISD::XOR:
1726 case ISD::SHL:
1727 case ISD::SRA:
1728 case ISD::SRL:
1729 case ISD::UREM: case ISD::VP_UREM:
1730 case ISD::SREM: case ISD::VP_SREM:
1731 case ISD::FREM:
1732 case ISD::SMIN:
1733 case ISD::SMAX:
1734 case ISD::UMIN:
1735 case ISD::UMAX:
1736 case ISD::SADDSAT:
1737 case ISD::UADDSAT:
1738 case ISD::SSUBSAT:
1739 case ISD::USUBSAT:
1740 case ISD::SSHLSAT:
1741 case ISD::USHLSAT:
1742 case ISD::ROTL:
1743 case ISD::ROTR:
1744 SplitVecRes_BinOp(N, Lo, Hi);
1745 break;
1746 case ISD::MASKED_UDIV:
1747 case ISD::MASKED_SDIV:
1748 case ISD::MASKED_UREM:
1749 case ISD::MASKED_SREM:
1750 SplitVecRes_MaskedBinOp(N, Lo, Hi);
1751 break;
1752 case ISD::FMA:
1753 case ISD::FSHL:
1754 case ISD::FSHR:
1755 SplitVecRes_TernaryOp(N, Lo, Hi);
1756 break;
1757
1758 case ISD::SCMP: case ISD::UCMP:
1759 SplitVecRes_CMP(N, Lo, Hi);
1760 break;
1761
1762#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
1763 case ISD::STRICT_##DAGN:
1764#include "llvm/IR/ConstrainedOps.def"
1765 SplitVecRes_StrictFPOp(N, Lo, Hi);
1766 break;
1767
1770 SplitVecRes_FP_TO_XINT_SAT(N, Lo, Hi);
1771 break;
1772
1773 case ISD::UADDO:
1774 case ISD::SADDO:
1775 case ISD::USUBO:
1776 case ISD::SSUBO:
1777 case ISD::UMULO:
1778 case ISD::SMULO:
1779 SplitVecRes_OverflowOp(N, ResNo, Lo, Hi);
1780 break;
1781 case ISD::SMULFIX:
1782 case ISD::SMULFIXSAT:
1783 case ISD::UMULFIX:
1784 case ISD::UMULFIXSAT:
1785 case ISD::SDIVFIX:
1786 case ISD::SDIVFIXSAT:
1787 case ISD::UDIVFIX:
1788 case ISD::UDIVFIXSAT:
1789 SplitVecRes_FIX(N, Lo, Hi);
1790 break;
1791 case ISD::EXPERIMENTAL_VP_SPLICE:
1792 SplitVecRes_VP_SPLICE(N, Lo, Hi);
1793 break;
1794 case ISD::EXPERIMENTAL_VP_REVERSE:
1795 SplitVecRes_VP_REVERSE(N, Lo, Hi);
1796 break;
1801 SplitVecRes_PARTIAL_REDUCE_MLA(N, Lo, Hi);
1802 break;
1804 SplitVecRes_GET_ACTIVE_LANE_MASK(N, Lo, Hi);
1805 break;
1806 case ISD::VECTOR_MATCH:
1807 SplitVecRes_VECTOR_MATCH(N, Lo, Hi);
1808 break;
1809 }
1810
1811 // If Lo/Hi is null, the sub-method took care of registering results etc.
1812 if (Lo.getNode())
1813 SetSplitVector(SDValue(N, ResNo), Lo, Hi);
1814}
1815
1816void DAGTypeLegalizer::IncrementPointer(MemSDNode *N, EVT MemVT,
1817 MachinePointerInfo &MPI, SDValue &Ptr,
1818 uint64_t *ScaledOffset) {
1819 SDLoc DL(N);
1820 unsigned IncrementSize = MemVT.getSizeInBits().getKnownMinValue() / 8;
1821
1822 if (MemVT.isScalableVector()) {
1823 SDValue BytesIncrement = DAG.getVScale(
1824 DL, Ptr.getValueType(),
1825 APInt(Ptr.getValueSizeInBits().getFixedValue(), IncrementSize));
1826 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
1827 if (ScaledOffset)
1828 *ScaledOffset += IncrementSize;
1829 Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, BytesIncrement,
1831 } else {
1832 MPI = N->getPointerInfo().getWithOffset(IncrementSize);
1833 // Increment the pointer to the other half.
1834 Ptr = DAG.getObjectPtrOffset(DL, Ptr, TypeSize::getFixed(IncrementSize));
1835 }
1836}
1837
1838std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask) {
1839 return SplitMask(Mask, SDLoc(Mask));
1840}
1841
1842std::pair<SDValue, SDValue> DAGTypeLegalizer::SplitMask(SDValue Mask,
1843 const SDLoc &DL) {
1844 SDValue MaskLo, MaskHi;
1845 EVT MaskVT = Mask.getValueType();
1846 if (getTypeAction(MaskVT) == TargetLowering::TypeSplitVector)
1847 GetSplitVector(Mask, MaskLo, MaskHi);
1848 else
1849 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
1850 return std::make_pair(MaskLo, MaskHi);
1851}
1852
1853void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDValue &Lo, SDValue &Hi) {
1854 SDValue LHSLo, LHSHi;
1855 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1856 SDValue RHSLo, RHSHi;
1857 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1858 SDLoc dl(N);
1859
1860 const SDNodeFlags Flags = N->getFlags();
1861 unsigned Opcode = N->getOpcode();
1862 if (N->getNumOperands() == 2) {
1863 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Flags);
1864 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Flags);
1865 return;
1866 }
1867
1868 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
1869 assert((N->getOpcode() == ISD::VP_UDIV || N->getOpcode() == ISD::VP_SDIV ||
1870 N->getOpcode() == ISD::VP_UREM || N->getOpcode() == ISD::VP_SREM) &&
1871 "Expected VP opcode");
1872
1873 SDValue MaskLo, MaskHi;
1874 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
1875
1876 SDValue EVLLo, EVLHi;
1877 std::tie(EVLLo, EVLHi) =
1878 DAG.SplitEVL(N->getOperand(3), N->getValueType(0), dl);
1879
1880 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(),
1881 {LHSLo, RHSLo, MaskLo, EVLLo}, Flags);
1882 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(),
1883 {LHSHi, RHSHi, MaskHi, EVLHi}, Flags);
1884}
1885
1886void DAGTypeLegalizer::SplitVecRes_MaskedBinOp(SDNode *N, SDValue &Lo,
1887 SDValue &Hi) {
1888 SDValue LHSLo, LHSHi;
1889 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1890 SDValue RHSLo, RHSHi;
1891 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1892
1893 SDValue MaskLo, MaskHi, Mask = N->getOperand(2);
1894 if (Mask.getOpcode() == ISD::SETCC)
1895 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
1896 else
1897 std::tie(MaskLo, MaskHi) = SplitMask(Mask);
1898
1899 SDLoc dl(N);
1900
1901 const SDNodeFlags Flags = N->getFlags();
1902 unsigned Opcode = N->getOpcode();
1903 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, MaskLo,
1904 Flags);
1905 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, MaskHi,
1906 Flags);
1907}
1908
1909void DAGTypeLegalizer::SplitVecRes_TernaryOp(SDNode *N, SDValue &Lo,
1910 SDValue &Hi) {
1911 SDValue Op0Lo, Op0Hi;
1912 GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
1913 SDValue Op1Lo, Op1Hi;
1914 GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
1915 SDValue Op2Lo, Op2Hi;
1916 GetSplitVector(N->getOperand(2), Op2Lo, Op2Hi);
1917 SDLoc dl(N);
1918
1919 const SDNodeFlags Flags = N->getFlags();
1920 unsigned Opcode = N->getOpcode();
1921 Lo =
1922 DAG.getNode(Opcode, dl, Op0Lo.getValueType(), Op0Lo, Op1Lo, Op2Lo, Flags);
1923 Hi =
1924 DAG.getNode(Opcode, dl, Op0Hi.getValueType(), Op0Hi, Op1Hi, Op2Hi, Flags);
1925}
1926
1927void DAGTypeLegalizer::SplitVecRes_CMP(SDNode *N, SDValue &Lo, SDValue &Hi) {
1928 LLVMContext &Ctxt = *DAG.getContext();
1929 SDLoc dl(N);
1930
1931 SDValue LHS = N->getOperand(0);
1932 SDValue RHS = N->getOperand(1);
1933
1934 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
1935 if (getTypeAction(LHS.getValueType()) == TargetLowering::TypeSplitVector) {
1936 GetSplitVector(LHS, LHSLo, LHSHi);
1937 GetSplitVector(RHS, RHSLo, RHSHi);
1938 } else {
1939 std::tie(LHSLo, LHSHi) = DAG.SplitVector(LHS, dl);
1940 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, dl);
1941 }
1942
1943 EVT SplitResVT = N->getValueType(0).getHalfNumVectorElementsVT(Ctxt);
1944 Lo = DAG.getNode(N->getOpcode(), dl, SplitResVT, LHSLo, RHSLo);
1945 Hi = DAG.getNode(N->getOpcode(), dl, SplitResVT, LHSHi, RHSHi);
1946}
1947
1948void DAGTypeLegalizer::SplitVecRes_FIX(SDNode *N, SDValue &Lo, SDValue &Hi) {
1949 SDValue LHSLo, LHSHi;
1950 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
1951 SDValue RHSLo, RHSHi;
1952 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
1953 SDLoc dl(N);
1954 SDValue Op2 = N->getOperand(2);
1955
1956 unsigned Opcode = N->getOpcode();
1957 Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Op2,
1958 N->getFlags());
1959 Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Op2,
1960 N->getFlags());
1961}
1962
1963void DAGTypeLegalizer::SplitVecRes_BITCAST(SDNode *N, SDValue &Lo,
1964 SDValue &Hi) {
1965 // We know the result is a vector. The input may be either a vector or a
1966 // scalar value.
1967 EVT LoVT, HiVT;
1968 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1969 SDLoc dl(N);
1970
1971 SDValue InOp = N->getOperand(0);
1972 EVT InVT = InOp.getValueType();
1973
1974 // Handle some special cases efficiently.
1975 switch (getTypeAction(InVT)) {
1982 break;
1985 // A scalar to vector conversion, where the scalar needs expansion.
1986 // If the vector is being split in two then we can just convert the
1987 // expanded pieces.
1988 if (LoVT == HiVT) {
1989 GetExpandedOp(InOp, Lo, Hi);
1990 if (DAG.getDataLayout().isBigEndian())
1991 std::swap(Lo, Hi);
1992 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
1993 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
1994 return;
1995 }
1996 break;
1998 // If the input is a vector that needs to be split, convert each split
1999 // piece of the input now.
2000 GetSplitVector(InOp, Lo, Hi);
2001 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
2002 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
2003 return;
2005 report_fatal_error("scalarization of scalable vectors is not supported");
2006 }
2007
2008 if (LoVT.isScalableVector()) {
2009 auto [InLo, InHi] = DAG.SplitVectorOperand(N, 0);
2010 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, InLo);
2011 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, InHi);
2012 return;
2013 }
2014
2015 // In the general case, convert the input to an integer and split it by hand.
2016 EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits());
2017 EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits());
2018 if (DAG.getDataLayout().isBigEndian())
2019 std::swap(LoIntVT, HiIntVT);
2020
2021 SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi);
2022
2023 if (DAG.getDataLayout().isBigEndian())
2024 std::swap(Lo, Hi);
2025 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
2026 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
2027}
2028
2029void DAGTypeLegalizer::SplitVecRes_LOOP_DEPENDENCE_MASK(SDNode *N, SDValue &Lo,
2030 SDValue &Hi) {
2031 SDLoc DL(N);
2032 EVT LoVT, HiVT;
2033 SDValue PtrA = N->getOperand(0);
2034 SDValue PtrB = N->getOperand(1);
2035 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2036
2037 // The lane offset for the "Lo" half of the mask is unchanged.
2038 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, PtrA, PtrB,
2039 /*ElementSizeInBytes=*/N->getOperand(2),
2040 /*LaneOffset=*/N->getOperand(3));
2041 // The lane offset for the "Hi" half of the mask is incremented by the number
2042 // of elements in the "Lo" half.
2043 unsigned LaneOffset =
2044 N->getConstantOperandVal(3) + LoVT.getVectorMinNumElements();
2045 // Note: The lane offset is implicitly scalable for scalable masks.
2046 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, PtrA, PtrB,
2047 /*ElementSizeInBytes=*/N->getOperand(2),
2048 /*LaneOffset=*/DAG.getConstant(LaneOffset, DL, MVT::i64));
2049}
2050
2051void DAGTypeLegalizer::SplitVecRes_MASK_BEFOREFIRST(SDNode *N, SDValue &Lo,
2052 SDValue &Hi) {
2053 SDLoc DL(N);
2054 SDValue InLo, InHi;
2055 GetSplitVector(N->getOperand(0), InLo, InHi);
2056 EVT VT = InLo.getValueType();
2057 Lo = DAG.getNode(ISD::MASK_BEFOREFIRST, DL, VT, InLo);
2058
2059 // hi = AnyLoActive ? all-zeros : (mask_beforefirst hi)
2060 SDValue AnyLoActive = DAG.getNode(ISD::VECREDUCE_OR, DL, MVT::i1, InLo);
2061 SDValue Cond = DAG.getBoolExtOrTrunc(AnyLoActive, DL,
2062 getSetCCResultType(MVT::i1), MVT::i1);
2063 Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, DAG.getConstant(0, DL, VT),
2064 DAG.getNode(ISD::MASK_BEFOREFIRST, DL, VT, InHi));
2065}
2066
2067void DAGTypeLegalizer::SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo,
2068 SDValue &Hi) {
2069 EVT LoVT, HiVT;
2070 SDLoc dl(N);
2071 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2072 unsigned LoNumElts = LoVT.getVectorNumElements();
2073 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts);
2074 Lo = DAG.getBuildVector(LoVT, dl, LoOps);
2075
2076 SmallVector<SDValue, 8> HiOps(N->op_begin()+LoNumElts, N->op_end());
2077 Hi = DAG.getBuildVector(HiVT, dl, HiOps);
2078}
2079
2080void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo,
2081 SDValue &Hi) {
2082 assert(!(N->getNumOperands() & 1) && "Unsupported CONCAT_VECTORS");
2083 SDLoc dl(N);
2084 unsigned NumSubvectors = N->getNumOperands() / 2;
2085 if (NumSubvectors == 1) {
2086 Lo = N->getOperand(0);
2087 Hi = N->getOperand(1);
2088 return;
2089 }
2090
2091 EVT LoVT, HiVT;
2092 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2093
2094 SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors);
2095 Lo = DAG.getNode(ISD::CONCAT_VECTORS, dl, LoVT, LoOps);
2096
2097 SmallVector<SDValue, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end());
2098 Hi = DAG.getNode(ISD::CONCAT_VECTORS, dl, HiVT, HiOps);
2099}
2100
2101void DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo,
2102 SDValue &Hi) {
2103 SDValue Vec = N->getOperand(0);
2104 SDValue Idx = N->getOperand(1);
2105 SDLoc dl(N);
2106
2107 EVT LoVT, HiVT;
2108 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2109
2110 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, LoVT, Vec, Idx);
2111 uint64_t IdxVal = Idx->getAsZExtVal();
2112 Hi = DAG.getNode(
2113 ISD::EXTRACT_SUBVECTOR, dl, HiVT, Vec,
2114 DAG.getVectorIdxConstant(IdxVal + LoVT.getVectorMinNumElements(), dl));
2115}
2116
2117void DAGTypeLegalizer::SplitVecRes_INSERT_SUBVECTOR(SDNode *N, SDValue &Lo,
2118 SDValue &Hi) {
2119 SDValue Vec = N->getOperand(0);
2120 SDValue SubVec = N->getOperand(1);
2121 SDValue Idx = N->getOperand(2);
2122 SDLoc dl(N);
2123 GetSplitVector(Vec, Lo, Hi);
2124
2125 EVT VecVT = Vec.getValueType();
2126 EVT LoVT = Lo.getValueType();
2127 EVT SubVecVT = SubVec.getValueType();
2128 unsigned VecElems = VecVT.getVectorMinNumElements();
2129 unsigned SubElems = SubVecVT.getVectorMinNumElements();
2130 unsigned LoElems = LoVT.getVectorMinNumElements();
2131
2132 // If we know the index is in the first half, and we know the subvector
2133 // doesn't cross the boundary between the halves, we can avoid spilling the
2134 // vector, and insert into the lower half of the split vector directly.
2135 unsigned IdxVal = Idx->getAsZExtVal();
2136 if (IdxVal + SubElems <= LoElems) {
2137 Lo = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, LoVT, Lo, SubVec, Idx);
2138 return;
2139 }
2140 // Similarly if the subvector is fully in the high half, but mind that we
2141 // can't tell whether a fixed-length subvector is fully within the high half
2142 // of a scalable vector.
2143 if (VecVT.isScalableVector() == SubVecVT.isScalableVector() &&
2144 IdxVal >= LoElems && IdxVal + SubElems <= VecElems) {
2145 Hi = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, Hi.getValueType(), Hi, SubVec,
2146 DAG.getVectorIdxConstant(IdxVal - LoElems, dl));
2147 return;
2148 }
2149
2150 if (getTypeAction(SubVecVT) == TargetLowering::TypeWidenVector &&
2151 Vec.isUndef() && SubVecVT.getVectorElementType() == MVT::i1) {
2152 SDValue WideSubVec = GetWidenedVector(SubVec);
2153 if (WideSubVec.getValueType() == VecVT) {
2154 std::tie(Lo, Hi) = DAG.SplitVector(WideSubVec, SDLoc(WideSubVec));
2155 return;
2156 }
2157 }
2158
2159 // Spill the vector to the stack.
2160 // In cases where the vector is illegal it will be broken down into parts
2161 // and stored in parts - we should use the alignment for the smallest part.
2162 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
2164 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
2165 auto &MF = DAG.getMachineFunction();
2166 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
2167 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
2168
2169 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
2170 SmallestAlign);
2171
2172 // Store the new subvector into the specified index.
2173 SDValue SubVecPtr =
2174 TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVecVT, Idx);
2175 Store = DAG.getStore(Store, dl, SubVec, SubVecPtr,
2177
2178 // Load the Lo part from the stack slot.
2179 Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, PtrInfo,
2180 SmallestAlign);
2181
2182 // Increment the pointer to the other part.
2183 auto *Load = cast<LoadSDNode>(Lo);
2184 MachinePointerInfo MPI = Load->getPointerInfo();
2185 IncrementPointer(Load, LoVT, MPI, StackPtr);
2186
2187 // Load the Hi part from the stack slot.
2188 Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, MPI, SmallestAlign);
2189}
2190
2191// Handle splitting an FP where the second operand does not match the first
2192// type. The second operand may be a scalar, or a vector that has exactly as
2193// many elements as the first
2194void DAGTypeLegalizer::SplitVecRes_FPOp_MultiType(SDNode *N, SDValue &Lo,
2195 SDValue &Hi) {
2196 SDValue LHSLo, LHSHi;
2197 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
2198 SDLoc DL(N);
2199
2200 SDValue RHSLo, RHSHi;
2201 SDValue RHS = N->getOperand(1);
2202 EVT RHSVT = RHS.getValueType();
2203 if (RHSVT.isVector()) {
2204 if (getTypeAction(RHSVT) == TargetLowering::TypeSplitVector)
2205 GetSplitVector(RHS, RHSLo, RHSHi);
2206 else
2207 std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, SDLoc(RHS));
2208
2209 Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo, RHSLo);
2210 Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi, RHSHi);
2211 } else {
2212 Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo, RHS);
2213 Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi, RHS);
2214 }
2215}
2216
2217void DAGTypeLegalizer::SplitVecRes_IS_FPCLASS(SDNode *N, SDValue &Lo,
2218 SDValue &Hi) {
2219 SDLoc DL(N);
2220 SDValue ArgLo, ArgHi;
2221 SDValue Test = N->getOperand(1);
2222 SDValue FpValue = N->getOperand(0);
2223 if (getTypeAction(FpValue.getValueType()) == TargetLowering::TypeSplitVector)
2224 GetSplitVector(FpValue, ArgLo, ArgHi);
2225 else
2226 std::tie(ArgLo, ArgHi) = DAG.SplitVector(FpValue, SDLoc(FpValue));
2227 EVT LoVT, HiVT;
2228 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2229
2230 Lo = DAG.getNode(ISD::IS_FPCLASS, DL, LoVT, ArgLo, Test, N->getFlags());
2231 Hi = DAG.getNode(ISD::IS_FPCLASS, DL, HiVT, ArgHi, Test, N->getFlags());
2232}
2233
2234void DAGTypeLegalizer::SplitVecRes_InregOp(SDNode *N, SDValue &Lo,
2235 SDValue &Hi) {
2236 SDValue LHSLo, LHSHi;
2237 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
2238 SDLoc dl(N);
2239
2240 EVT LoVT, HiVT;
2241 std::tie(LoVT, HiVT) =
2242 DAG.GetSplitDestVTs(cast<VTSDNode>(N->getOperand(1))->getVT());
2243
2244 Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo,
2245 DAG.getValueType(LoVT));
2246 Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi,
2247 DAG.getValueType(HiVT));
2248}
2249
2250void DAGTypeLegalizer::SplitVecRes_ExtVecInRegOp(SDNode *N, SDValue &Lo,
2251 SDValue &Hi) {
2252 unsigned Opcode = N->getOpcode();
2253 SDValue N0 = N->getOperand(0);
2254
2255 SDLoc dl(N);
2256 SDValue InLo, InHi;
2257
2258 if (getTypeAction(N0.getValueType()) == TargetLowering::TypeSplitVector)
2259 GetSplitVector(N0, InLo, InHi);
2260 else
2261 std::tie(InLo, InHi) = DAG.SplitVectorOperand(N, 0);
2262
2263 EVT InLoVT = InLo.getValueType();
2264 unsigned InNumElements = InLoVT.getVectorNumElements();
2265
2266 EVT OutLoVT, OutHiVT;
2267 std::tie(OutLoVT, OutHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2268 unsigned OutNumElements = OutLoVT.getVectorNumElements();
2269 assert((2 * OutNumElements) <= InNumElements &&
2270 "Illegal extend vector in reg split");
2271
2272 // *_EXTEND_VECTOR_INREG instructions extend the lowest elements of the
2273 // input vector (i.e. we only use InLo):
2274 // OutLo will extend the first OutNumElements from InLo.
2275 // OutHi will extend the next OutNumElements from InLo.
2276
2277 // Shuffle the elements from InLo for OutHi into the bottom elements to
2278 // create a 'fake' InHi.
2279 SmallVector<int, 8> SplitHi(InNumElements, -1);
2280 for (unsigned i = 0; i != OutNumElements; ++i)
2281 SplitHi[i] = i + OutNumElements;
2282 InHi = DAG.getVectorShuffle(InLoVT, dl, InLo, DAG.getPOISON(InLoVT), SplitHi);
2283
2284 Lo = DAG.getNode(Opcode, dl, OutLoVT, InLo);
2285 Hi = DAG.getNode(Opcode, dl, OutHiVT, InHi);
2286}
2287
2288void DAGTypeLegalizer::SplitVecRes_StrictFPOp(SDNode *N, SDValue &Lo,
2289 SDValue &Hi) {
2290 unsigned NumOps = N->getNumOperands();
2291 SDValue Chain = N->getOperand(0);
2292 EVT LoVT, HiVT;
2293 SDLoc dl(N);
2294 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2295
2298
2299 // The Chain is the first operand.
2300 OpsLo[0] = Chain;
2301 OpsHi[0] = Chain;
2302
2303 // Now process the remaining operands.
2304 for (unsigned i = 1; i < NumOps; ++i) {
2305 SDValue Op = N->getOperand(i);
2306 SDValue OpLo = Op;
2307 SDValue OpHi = Op;
2308
2309 EVT InVT = Op.getValueType();
2310 if (InVT.isVector()) {
2311 // If the input also splits, handle it directly for a
2312 // compile time speedup. Otherwise split it by hand.
2313 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
2314 GetSplitVector(Op, OpLo, OpHi);
2315 else
2316 std::tie(OpLo, OpHi) = DAG.SplitVectorOperand(N, i);
2317 }
2318
2319 OpsLo[i] = OpLo;
2320 OpsHi[i] = OpHi;
2321 }
2322
2323 EVT LoValueVTs[] = {LoVT, MVT::Other};
2324 EVT HiValueVTs[] = {HiVT, MVT::Other};
2325 Lo = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(LoValueVTs), OpsLo,
2326 N->getFlags());
2327 Hi = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(HiValueVTs), OpsHi,
2328 N->getFlags());
2329
2330 // Build a factor node to remember that this Op is independent of the
2331 // other one.
2332 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
2333 Lo.getValue(1), Hi.getValue(1));
2334
2335 // Legalize the chain result - switch anything that used the old chain to
2336 // use the new one.
2337 ReplaceValueWith(SDValue(N, 1), Chain);
2338}
2339
2340SDValue DAGTypeLegalizer::UnrollVectorOp_StrictFP(SDNode *N, unsigned ResNE) {
2341 EVT VT = N->getValueType(0);
2342 if (VT.isScalableVector())
2343 report_fatal_error("Cannot unroll scalable vector strict-fp operation!");
2344
2345 SDValue Chain = N->getOperand(0);
2346 unsigned NE = VT.getVectorNumElements();
2347 EVT EltVT = VT.getVectorElementType();
2348 SDLoc dl(N);
2349
2351 SmallVector<SDValue, 4> Operands(N->getNumOperands());
2352
2353 // If ResNE is 0, fully unroll the vector op.
2354 if (ResNE == 0)
2355 ResNE = NE;
2356 else if (NE > ResNE)
2357 NE = ResNE;
2358
2359 //The results of each unrolled operation, including the chain.
2360 SDVTList ChainVTs = DAG.getVTList(EltVT, MVT::Other);
2362
2363 unsigned i;
2364 for (i = 0; i != NE; ++i) {
2365 Operands[0] = Chain;
2366 for (unsigned j = 1, e = N->getNumOperands(); j != e; ++j) {
2367 SDValue Operand = N->getOperand(j);
2368 EVT OperandVT = Operand.getValueType();
2369 if (OperandVT.isVector()) {
2370 EVT OperandEltVT = OperandVT.getVectorElementType();
2371 Operands[j] = DAG.getExtractVectorElt(dl, OperandEltVT, Operand, i);
2372 } else {
2373 Operands[j] = Operand;
2374 }
2375 }
2376 SDValue Scalar =
2377 DAG.getNode(N->getOpcode(), dl, ChainVTs, Operands, N->getFlags());
2378
2379 //Add in the scalar as well as its chain value to the
2380 //result vectors.
2381 Scalars.push_back(Scalar);
2382 Chains.push_back(Scalar.getValue(1));
2383 }
2384
2385 for (; i < ResNE; ++i)
2386 Scalars.push_back(DAG.getPOISON(EltVT));
2387
2388 // Build a new factor node to connect the chain back together.
2389 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
2390 ReplaceValueWith(SDValue(N, 1), Chain);
2391
2392 // Create a new BUILD_VECTOR node
2393 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, ResNE);
2394 return DAG.getBuildVector(VecVT, dl, Scalars);
2395}
2396
2397void DAGTypeLegalizer::SplitVecRes_OverflowOp(SDNode *N, unsigned ResNo,
2398 SDValue &Lo, SDValue &Hi) {
2399 SDLoc dl(N);
2400 EVT ResVT = N->getValueType(0);
2401 EVT OvVT = N->getValueType(1);
2402 EVT LoResVT, HiResVT, LoOvVT, HiOvVT;
2403 std::tie(LoResVT, HiResVT) = DAG.GetSplitDestVTs(ResVT);
2404 std::tie(LoOvVT, HiOvVT) = DAG.GetSplitDestVTs(OvVT);
2405
2406 SDValue LoLHS, HiLHS, LoRHS, HiRHS;
2407 if (getTypeAction(ResVT) == TargetLowering::TypeSplitVector) {
2408 GetSplitVector(N->getOperand(0), LoLHS, HiLHS);
2409 GetSplitVector(N->getOperand(1), LoRHS, HiRHS);
2410 } else {
2411 std::tie(LoLHS, HiLHS) = DAG.SplitVectorOperand(N, 0);
2412 std::tie(LoRHS, HiRHS) = DAG.SplitVectorOperand(N, 1);
2413 }
2414
2415 unsigned Opcode = N->getOpcode();
2416 SDVTList LoVTs = DAG.getVTList(LoResVT, LoOvVT);
2417 SDVTList HiVTs = DAG.getVTList(HiResVT, HiOvVT);
2418 SDNode *LoNode =
2419 DAG.getNode(Opcode, dl, LoVTs, {LoLHS, LoRHS}, N->getFlags()).getNode();
2420 SDNode *HiNode =
2421 DAG.getNode(Opcode, dl, HiVTs, {HiLHS, HiRHS}, N->getFlags()).getNode();
2422
2423 Lo = SDValue(LoNode, ResNo);
2424 Hi = SDValue(HiNode, ResNo);
2425
2426 // Replace the other vector result not being explicitly split here.
2427 unsigned OtherNo = 1 - ResNo;
2428 EVT OtherVT = N->getValueType(OtherNo);
2429 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
2430 SetSplitVector(SDValue(N, OtherNo),
2431 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
2432 } else {
2433 SDValue OtherVal = DAG.getNode(
2434 ISD::CONCAT_VECTORS, dl, OtherVT,
2435 SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
2436 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
2437 }
2438}
2439
2440void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo,
2441 SDValue &Hi) {
2442 SDValue Vec = N->getOperand(0);
2443 SDValue Elt = N->getOperand(1);
2444 SDValue Idx = N->getOperand(2);
2445 SDLoc dl(N);
2446 GetSplitVector(Vec, Lo, Hi);
2447
2448 if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
2449 unsigned IdxVal = CIdx->getZExtValue();
2450 unsigned LoNumElts = Lo.getValueType().getVectorMinNumElements();
2451 if (IdxVal < LoNumElts) {
2452 Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl,
2453 Lo.getValueType(), Lo, Elt, Idx);
2454 return;
2455 } else if (!Vec.getValueType().isScalableVector()) {
2456 Hi = DAG.getInsertVectorElt(dl, Hi, Elt, IdxVal - LoNumElts);
2457 return;
2458 }
2459 }
2460
2461 // Make the vector elements byte-addressable if they aren't already.
2462 EVT VecVT = Vec.getValueType();
2463 EVT EltVT = VecVT.getVectorElementType();
2464 if (!EltVT.isByteSized()) {
2465 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
2466 VecVT = VecVT.changeElementType(*DAG.getContext(), EltVT);
2467 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
2468 // Extend the element type to match if needed.
2469 if (EltVT.bitsGT(Elt.getValueType()))
2470 Elt = DAG.getNode(ISD::ANY_EXTEND, dl, EltVT, Elt);
2471 }
2472
2473 // Spill the vector to the stack.
2474 // In cases where the vector is illegal it will be broken down into parts
2475 // and stored in parts - we should use the alignment for the smallest part.
2476 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
2478 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
2479 auto &MF = DAG.getMachineFunction();
2480 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
2481 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
2482
2483 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
2484 SmallestAlign);
2485
2486 // Store the new element. This may be larger than the vector element type,
2487 // so use a truncating store.
2488 SDValue EltPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
2489 Store = DAG.getTruncStore(
2490 Store, dl, Elt, EltPtr, MachinePointerInfo::getUnknownStack(MF), EltVT,
2491 commonAlignment(SmallestAlign,
2492 EltVT.getFixedSizeInBits() / 8));
2493
2494 EVT LoVT, HiVT;
2495 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VecVT);
2496
2497 // Load the Lo part from the stack slot.
2498 Lo = DAG.getLoad(LoVT, dl, Store, StackPtr, PtrInfo, SmallestAlign);
2499
2500 // Increment the pointer to the other part.
2501 auto Load = cast<LoadSDNode>(Lo);
2502 MachinePointerInfo MPI = Load->getPointerInfo();
2503 IncrementPointer(Load, LoVT, MPI, StackPtr);
2504
2505 Hi = DAG.getLoad(HiVT, dl, Store, StackPtr, MPI, SmallestAlign);
2506
2507 // If we adjusted the original type, we need to truncate the results.
2508 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2509 if (LoVT != Lo.getValueType())
2510 Lo = DAG.getNode(ISD::TRUNCATE, dl, LoVT, Lo);
2511 if (HiVT != Hi.getValueType())
2512 Hi = DAG.getNode(ISD::TRUNCATE, dl, HiVT, Hi);
2513}
2514
2515void DAGTypeLegalizer::SplitVecRes_STEP_VECTOR(SDNode *N, SDValue &Lo,
2516 SDValue &Hi) {
2517 EVT LoVT, HiVT;
2518 SDLoc dl(N);
2519 assert(N->getValueType(0).isScalableVector() &&
2520 "Only scalable vectors are supported for STEP_VECTOR");
2521 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2522 SDValue Step = N->getOperand(0);
2523
2524 Lo = DAG.getNode(ISD::STEP_VECTOR, dl, LoVT, Step);
2525
2526 // Hi = Lo + (EltCnt * Step)
2527 EVT EltVT = Step.getValueType();
2528 APInt StepVal = Step->getAsAPIntVal();
2529 SDValue StartOfHi =
2530 DAG.getVScale(dl, EltVT, StepVal * LoVT.getVectorMinNumElements());
2531 StartOfHi = DAG.getSExtOrTrunc(StartOfHi, dl, HiVT.getVectorElementType());
2532 StartOfHi = DAG.getNode(ISD::SPLAT_VECTOR, dl, HiVT, StartOfHi);
2533
2534 Hi = DAG.getNode(ISD::STEP_VECTOR, dl, HiVT, Step);
2535 Hi = DAG.getNode(ISD::ADD, dl, HiVT, Hi, StartOfHi);
2536}
2537
2538void DAGTypeLegalizer::SplitVecRes_ScalarOp(SDNode *N, SDValue &Lo,
2539 SDValue &Hi) {
2540 EVT LoVT, HiVT;
2541 SDLoc dl(N);
2542 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2543 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, N->getOperand(0));
2544 if (N->getOpcode() == ISD::SCALAR_TO_VECTOR) {
2545 Hi = DAG.getPOISON(HiVT);
2546 } else {
2547 assert(N->getOpcode() == ISD::SPLAT_VECTOR && "Unexpected opcode");
2548 Hi = Lo;
2549 }
2550}
2551
2552void DAGTypeLegalizer::SplitVecRes_ATOMIC_LOAD(AtomicSDNode *LD, SDValue &Lo,
2553 SDValue &Hi) {
2554 assert(LD->getExtensionType() == ISD::NON_EXTLOAD &&
2555 "Extended load during type legalization!");
2556 SDLoc dl(LD);
2557 EVT VT = LD->getValueType(0);
2558 EVT LoVT, HiVT;
2559 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VT);
2560
2561 SDValue Ch = LD->getChain();
2562 SDValue Ptr = LD->getBasePtr();
2563
2564 EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits());
2565 EVT MemIntVT =
2566 EVT::getIntegerVT(*DAG.getContext(), LD->getMemoryVT().getSizeInBits());
2567 SDValue ALD = DAG.getAtomicLoad(LD->getExtensionType(), dl, MemIntVT, IntVT,
2568 Ch, Ptr, LD->getMemOperand());
2569
2570 EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits());
2571 EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits());
2572 SDValue ExtractLo, ExtractHi;
2573 SplitInteger(ALD, LoIntVT, HiIntVT, ExtractLo, ExtractHi);
2574
2575 Lo = DAG.getBitcast(LoVT, ExtractLo);
2576 Hi = DAG.getBitcast(HiVT, ExtractHi);
2577
2578 // Legalize the chain result - switch anything that used the old chain to
2579 // use the new one.
2580 ReplaceValueWith(SDValue(LD, 1), ALD.getValue(1));
2581}
2582
2583void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
2584 SDValue &Hi) {
2585 assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!");
2586 EVT LoVT, HiVT;
2587 SDLoc dl(LD);
2588 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
2589
2590 ISD::LoadExtType ExtType = LD->getExtensionType();
2591 SDValue Ch = LD->getChain();
2592 SDValue Ptr = LD->getBasePtr();
2593 SDValue Offset = DAG.getPOISON(Ptr.getValueType());
2594 EVT MemoryVT = LD->getMemoryVT();
2595 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
2596 MMOMetadata Metadata = LD->getMMOMetadataForSubAccess();
2597
2598 EVT LoMemVT, HiMemVT;
2599 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2600
2601 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized()) {
2602 SDValue Value, NewChain;
2603 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
2604 std::tie(Lo, Hi) = DAG.SplitVector(Value, dl);
2605 ReplaceValueWith(SDValue(LD, 1), NewChain);
2606 return;
2607 }
2608
2609 Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, LoVT, dl, Ch, Ptr, Offset,
2610 LD->getPointerInfo(), LoMemVT, LD->getBaseAlign(), MMOFlags,
2611 Metadata);
2612
2613 MachinePointerInfo MPI;
2614 IncrementPointer(LD, LoMemVT, MPI, Ptr);
2615
2616 Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, dl, Ch, Ptr, Offset, MPI,
2617 HiMemVT, LD->getBaseAlign(), MMOFlags, Metadata);
2618
2619 // Build a factor node to remember that this load is independent of the
2620 // other one.
2621 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2622 Hi.getValue(1));
2623
2624 // Legalize the chain result - switch anything that used the old chain to
2625 // use the new one.
2626 ReplaceValueWith(SDValue(LD, 1), Ch);
2627}
2628
2629void DAGTypeLegalizer::SplitVecRes_VP_LOAD(VPLoadSDNode *LD, SDValue &Lo,
2630 SDValue &Hi) {
2631 assert(LD->isUnindexed() && "Indexed VP load during type legalization!");
2632 EVT LoVT, HiVT;
2633 SDLoc dl(LD);
2634 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));
2635
2636 ISD::LoadExtType ExtType = LD->getExtensionType();
2637 SDValue Ch = LD->getChain();
2638 SDValue Ptr = LD->getBasePtr();
2639 SDValue Offset = LD->getOffset();
2640 assert(Offset.isUndef() && "Unexpected indexed variable-length load offset");
2641 Align Alignment = LD->getBaseAlign();
2642 SDValue Mask = LD->getMask();
2643 SDValue EVL = LD->getVectorLength();
2644 EVT MemoryVT = LD->getMemoryVT();
2645
2646 EVT LoMemVT, HiMemVT;
2647 bool HiIsEmpty = false;
2648 std::tie(LoMemVT, HiMemVT) =
2649 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2650
2651 // Split Mask operand
2652 SDValue MaskLo, MaskHi;
2653 if (Mask.getOpcode() == ISD::SETCC) {
2654 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2655 } else {
2656 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2657 GetSplitVector(Mask, MaskLo, MaskHi);
2658 else
2659 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2660 }
2661
2662 // Split EVL operand
2663 SDValue EVLLo, EVLHi;
2664 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, LD->getValueType(0), dl);
2665
2666 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2667 LD->getPointerInfo(), MachineMemOperand::MOLoad,
2669 MMOMetadata(LD->getAAInfo(), LD->getRanges()));
2670
2671 Lo =
2672 DAG.getLoadVP(LD->getAddressingMode(), ExtType, LoVT, dl, Ch, Ptr, Offset,
2673 MaskLo, EVLLo, LoMemVT, MMO, LD->isExpandingLoad());
2674
2675 if (HiIsEmpty) {
2676 // The hi vp_load has zero storage size. We therefore simply set it to
2677 // the low vp_load and rely on subsequent removal from the chain.
2678 Hi = Lo;
2679 } else {
2680 // Generate hi vp_load.
2681 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2682 LD->isExpandingLoad());
2683
2684 MachinePointerInfo MPI;
2685 if (LoMemVT.isScalableVector())
2686 MPI = MachinePointerInfo(LD->getPointerInfo().getAddrSpace());
2687 else
2688 MPI = LD->getPointerInfo().getWithOffset(
2689 LoMemVT.getStoreSize().getFixedValue());
2690
2691 MMO = DAG.getMachineFunction().getMachineMemOperand(
2693 Alignment, MMOMetadata(LD->getAAInfo(), LD->getRanges()));
2694
2695 Hi = DAG.getLoadVP(LD->getAddressingMode(), ExtType, HiVT, dl, Ch, Ptr,
2696 Offset, MaskHi, EVLHi, HiMemVT, MMO,
2697 LD->isExpandingLoad());
2698 }
2699
2700 // Build a factor node to remember that this load is independent of the
2701 // other one.
2702 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2703 Hi.getValue(1));
2704
2705 // Legalize the chain result - switch anything that used the old chain to
2706 // use the new one.
2707 ReplaceValueWith(SDValue(LD, 1), Ch);
2708}
2709
2710void DAGTypeLegalizer::SplitVecRes_VP_LOAD_FF(VPLoadFFSDNode *LD, SDValue &Lo,
2711 SDValue &Hi) {
2712 SDLoc dl(LD);
2713 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(LD->getValueType(0));
2714
2715 SDValue Ch = LD->getChain();
2716 SDValue Ptr = LD->getBasePtr();
2717 Align Alignment = LD->getBaseAlign();
2718 SDValue Mask = LD->getMask();
2719 SDValue EVL = LD->getVectorLength();
2720
2721 // Split Mask operand
2722 SDValue MaskLo, MaskHi;
2723 if (Mask.getOpcode() == ISD::SETCC) {
2724 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2725 } else {
2726 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2727 GetSplitVector(Mask, MaskLo, MaskHi);
2728 else
2729 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2730 }
2731
2732 // Split EVL operand
2733 auto [EVLLo, EVLHi] = DAG.SplitEVL(EVL, LD->getValueType(0), dl);
2734
2735 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2736 LD->getPointerInfo(), MachineMemOperand::MOLoad,
2738 MMOMetadata(LD->getAAInfo(), LD->getRanges()));
2739
2740 Lo = DAG.getLoadFFVP(LoVT, dl, Ch, Ptr, MaskLo, EVLLo, MMO);
2741
2742 // Fill the upper half with poison.
2743 Hi = DAG.getPOISON(HiVT);
2744
2745 ReplaceValueWith(SDValue(LD, 1), Lo.getValue(1));
2746 ReplaceValueWith(SDValue(LD, 2), Lo.getValue(2));
2747}
2748
2749void DAGTypeLegalizer::SplitVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *SLD,
2750 SDValue &Lo, SDValue &Hi) {
2751 assert(SLD->isUnindexed() &&
2752 "Indexed VP strided load during type legalization!");
2753 assert(SLD->getOffset().isUndef() &&
2754 "Unexpected indexed variable-length load offset");
2755
2756 SDLoc DL(SLD);
2757
2758 EVT LoVT, HiVT;
2759 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(SLD->getValueType(0));
2760
2761 EVT LoMemVT, HiMemVT;
2762 bool HiIsEmpty = false;
2763 std::tie(LoMemVT, HiMemVT) =
2764 DAG.GetDependentSplitDestVTs(SLD->getMemoryVT(), LoVT, &HiIsEmpty);
2765
2766 SDValue Mask = SLD->getMask();
2767 SDValue LoMask, HiMask;
2768 if (Mask.getOpcode() == ISD::SETCC) {
2769 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
2770 } else {
2771 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2772 GetSplitVector(Mask, LoMask, HiMask);
2773 else
2774 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
2775 }
2776
2777 SDValue LoEVL, HiEVL;
2778 std::tie(LoEVL, HiEVL) =
2779 DAG.SplitEVL(SLD->getVectorLength(), SLD->getValueType(0), DL);
2780
2781 // Generate the low vp_strided_load
2782 Lo = DAG.getStridedLoadVP(
2783 SLD->getAddressingMode(), SLD->getExtensionType(), LoVT, DL,
2784 SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(), SLD->getStride(),
2785 LoMask, LoEVL, LoMemVT, SLD->getMemOperand(), SLD->isExpandingLoad());
2786
2787 if (HiIsEmpty) {
2788 // The high vp_strided_load has zero storage size. We therefore simply set
2789 // it to the low vp_strided_load and rely on subsequent removal from the
2790 // chain.
2791 Hi = Lo;
2792 } else {
2793 // Generate the high vp_strided_load.
2794 // To calculate the high base address, we need to sum to the low base
2795 // address stride number of bytes for each element already loaded by low,
2796 // that is: Ptr = Ptr + (LoEVL * Stride)
2797 EVT PtrVT = SLD->getBasePtr().getValueType();
2799 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
2800 DAG.getSExtOrTrunc(SLD->getStride(), DL, PtrVT));
2801 SDValue Ptr =
2802 DAG.getNode(ISD::ADD, DL, PtrVT, SLD->getBasePtr(), Increment);
2803
2804 Align Alignment = SLD->getBaseAlign();
2805 if (LoMemVT.isScalableVector())
2807 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
2808
2809 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2810 MachinePointerInfo(SLD->getPointerInfo().getAddrSpace()),
2812 Alignment, MMOMetadata(SLD->getAAInfo(), SLD->getRanges()));
2813
2814 Hi = DAG.getStridedLoadVP(SLD->getAddressingMode(), SLD->getExtensionType(),
2815 HiVT, DL, SLD->getChain(), Ptr, SLD->getOffset(),
2816 SLD->getStride(), HiMask, HiEVL, HiMemVT, MMO,
2817 SLD->isExpandingLoad());
2818 }
2819
2820 // Build a factor node to remember that this load is independent of the
2821 // other one.
2822 SDValue Ch = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo.getValue(1),
2823 Hi.getValue(1));
2824
2825 // Legalize the chain result - switch anything that used the old chain to
2826 // use the new one.
2827 ReplaceValueWith(SDValue(SLD, 1), Ch);
2828}
2829
2830void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD,
2831 SDValue &Lo, SDValue &Hi) {
2832 assert(MLD->isUnindexed() && "Indexed masked load during type legalization!");
2833 EVT LoVT, HiVT;
2834 SDLoc dl(MLD);
2835 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(MLD->getValueType(0));
2836
2837 SDValue Ch = MLD->getChain();
2838 SDValue Ptr = MLD->getBasePtr();
2839 SDValue Offset = MLD->getOffset();
2840 assert(Offset.isUndef() && "Unexpected indexed masked load offset");
2841 SDValue Mask = MLD->getMask();
2842 SDValue PassThru = MLD->getPassThru();
2843 Align Alignment = MLD->getBaseAlign();
2844 ISD::LoadExtType ExtType = MLD->getExtensionType();
2845 MachineMemOperand::Flags MMOFlags = MLD->getMemOperand()->getFlags();
2846
2847 // Split Mask operand
2848 SDValue MaskLo, MaskHi;
2849 if (Mask.getOpcode() == ISD::SETCC) {
2850 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
2851 } else {
2852 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
2853 GetSplitVector(Mask, MaskLo, MaskHi);
2854 else
2855 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
2856 }
2857
2858 EVT MemoryVT = MLD->getMemoryVT();
2859 EVT LoMemVT, HiMemVT;
2860 bool HiIsEmpty = false;
2861 std::tie(LoMemVT, HiMemVT) =
2862 DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);
2863
2864 SDValue PassThruLo, PassThruHi;
2865 if (getTypeAction(PassThru.getValueType()) == TargetLowering::TypeSplitVector)
2866 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2867 else
2868 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2869
2870 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2872 Alignment,
2873 MMOMetadata(MLD->getAAInfo(), MLD->getRanges(), MLD->getMemCacheHint()));
2874
2875 Lo = DAG.getMaskedLoad(LoVT, dl, Ch, Ptr, Offset, MaskLo, PassThruLo, LoMemVT,
2876 MMO, MLD->getAddressingMode(), ExtType,
2877 MLD->isExpandingLoad());
2878
2879 if (HiIsEmpty) {
2880 // The hi masked load has zero storage size. We therefore simply set it to
2881 // the low masked load and rely on subsequent removal from the chain.
2882 Hi = Lo;
2883 } else {
2884 // Generate hi masked load.
2885 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
2886 MLD->isExpandingLoad());
2887
2888 MachinePointerInfo MPI;
2889 if (LoMemVT.isScalableVector())
2890 MPI = MachinePointerInfo(MLD->getPointerInfo().getAddrSpace());
2891 else
2892 MPI = MLD->getPointerInfo().getWithOffset(
2893 LoMemVT.getStoreSize().getFixedValue());
2894
2895 MMO = DAG.getMachineFunction().getMachineMemOperand(
2896 MPI, MMOFlags, LocationSize::beforeOrAfterPointer(), Alignment,
2897 MMOMetadata(MLD->getAAInfo(), MLD->getRanges(),
2898 MLD->getMemCacheHint()));
2899
2900 Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, Offset, MaskHi, PassThruHi,
2901 HiMemVT, MMO, MLD->getAddressingMode(), ExtType,
2902 MLD->isExpandingLoad());
2903 }
2904
2905 // Build a factor node to remember that this load is independent of the
2906 // other one.
2907 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
2908 Hi.getValue(1));
2909
2910 // Legalize the chain result - switch anything that used the old chain to
2911 // use the new one.
2912 ReplaceValueWith(SDValue(MLD, 1), Ch);
2913
2914}
2915
2916void DAGTypeLegalizer::SplitVecRes_Gather(MemSDNode *N, SDValue &Lo,
2917 SDValue &Hi, bool SplitSETCC) {
2918 EVT LoVT, HiVT;
2919 SDLoc dl(N);
2920 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
2921
2922 SDValue Ch = N->getChain();
2923 SDValue Ptr = N->getBasePtr();
2924 struct Operands {
2925 SDValue Mask;
2926 SDValue Index;
2927 SDValue Scale;
2928 } Ops = [&]() -> Operands {
2929 if (auto *MSC = dyn_cast<MaskedGatherSDNode>(N)) {
2930 return {MSC->getMask(), MSC->getIndex(), MSC->getScale()};
2931 }
2932 auto *VPSC = cast<VPGatherSDNode>(N);
2933 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale()};
2934 }();
2935
2936 EVT MemoryVT = N->getMemoryVT();
2937 Align Alignment = N->getBaseAlign();
2938
2939 // Split Mask operand
2940 SDValue MaskLo, MaskHi;
2941 if (SplitSETCC && Ops.Mask.getOpcode() == ISD::SETCC) {
2942 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
2943 } else {
2944 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, dl);
2945 }
2946
2947 EVT LoMemVT, HiMemVT;
2948 // Split MemoryVT
2949 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
2950
2951 SDValue IndexHi, IndexLo;
2952 if (getTypeAction(Ops.Index.getValueType()) ==
2954 GetSplitVector(Ops.Index, IndexLo, IndexHi);
2955 else
2956 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, dl);
2957
2958 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
2959 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
2960 N->getPointerInfo(), MMOFlags, LocationSize::beforeOrAfterPointer(),
2961 Alignment, MMOMetadata(N->getAAInfo(), N->getRanges()));
2962
2963 if (auto *MGT = dyn_cast<MaskedGatherSDNode>(N)) {
2964 SDValue PassThru = MGT->getPassThru();
2965 SDValue PassThruLo, PassThruHi;
2966 if (getTypeAction(PassThru.getValueType()) ==
2968 GetSplitVector(PassThru, PassThruLo, PassThruHi);
2969 else
2970 std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);
2971
2972 ISD::LoadExtType ExtType = MGT->getExtensionType();
2973 ISD::MemIndexType IndexTy = MGT->getIndexType();
2974
2975 SDValue OpsLo[] = {Ch, PassThruLo, MaskLo, Ptr, IndexLo, Ops.Scale};
2976 Lo = DAG.getMaskedGather(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl,
2977 OpsLo, MMO, IndexTy, ExtType);
2978
2979 SDValue OpsHi[] = {Ch, PassThruHi, MaskHi, Ptr, IndexHi, Ops.Scale};
2980 Hi = DAG.getMaskedGather(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl,
2981 OpsHi, MMO, IndexTy, ExtType);
2982 } else {
2983 auto *VPGT = cast<VPGatherSDNode>(N);
2984 SDValue EVLLo, EVLHi;
2985 std::tie(EVLLo, EVLHi) =
2986 DAG.SplitEVL(VPGT->getVectorLength(), MemoryVT, dl);
2987
2988 SDValue OpsLo[] = {Ch, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
2989 Lo = DAG.getGatherVP(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl, OpsLo,
2990 MMO, VPGT->getIndexType());
2991
2992 SDValue OpsHi[] = {Ch, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
2993 Hi = DAG.getGatherVP(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl, OpsHi,
2994 MMO, VPGT->getIndexType());
2995 }
2996
2997 // Build a factor node to remember that this load is independent of the
2998 // other one.
2999 Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
3000 Hi.getValue(1));
3001
3002 // Legalize the chain result - switch anything that used the old chain to
3003 // use the new one.
3004 ReplaceValueWith(SDValue(N, 1), Ch);
3005}
3006
3007void DAGTypeLegalizer::SplitVecRes_VECTOR_COMPRESS(SDNode *N, SDValue &Lo,
3008 SDValue &Hi) {
3009 // This is not "trivial", as there is a dependency between the two subvectors.
3010 // Depending on the number of 1s in the mask, the elements from the Hi vector
3011 // need to be moved to the Lo vector. Passthru values make this even harder.
3012 // We try to use VECTOR_COMPRESS if the target has custom lowering with
3013 // smaller types and passthru is undef, as it is most likely faster than the
3014 // fully expand path. Otherwise, just do the full expansion as one "big"
3015 // operation and then extract the Lo and Hi vectors from that. This gets
3016 // rid of VECTOR_COMPRESS and all other operands can be legalized later.
3017 SDLoc DL(N);
3018 EVT VecVT = N->getValueType(0);
3019
3020 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VecVT);
3021 bool HasCustomLowering = false;
3022 EVT CheckVT = LoVT;
3023 while (CheckVT.getVectorMinNumElements() > 1) {
3024 // TLI.isOperationLegalOrCustom requires a legal type, but we could have a
3025 // custom lowering for illegal types. So we do the checks separately.
3026 if (TLI.isOperationLegal(ISD::VECTOR_COMPRESS, CheckVT) ||
3027 TLI.isOperationCustom(ISD::VECTOR_COMPRESS, CheckVT)) {
3028 HasCustomLowering = true;
3029 break;
3030 }
3031 CheckVT = CheckVT.getHalfNumVectorElementsVT(*DAG.getContext());
3032 }
3033
3034 SDValue Passthru = N->getOperand(2);
3035 if (!HasCustomLowering) {
3036 SDValue Compressed = TLI.expandVECTOR_COMPRESS(N, DAG);
3037 std::tie(Lo, Hi) = DAG.SplitVector(Compressed, DL, LoVT, HiVT);
3038 return;
3039 }
3040
3041 // Try to VECTOR_COMPRESS smaller vectors and combine via a stack store+load.
3042 SDValue Mask = N->getOperand(1);
3043 SDValue LoMask, HiMask;
3044 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
3045 std::tie(LoMask, HiMask) = SplitMask(Mask);
3046
3047 SDValue UndefPassthru = DAG.getPOISON(LoVT);
3048 Lo = DAG.getNode(ISD::VECTOR_COMPRESS, DL, LoVT, Lo, LoMask, UndefPassthru);
3049 Hi = DAG.getNode(ISD::VECTOR_COMPRESS, DL, HiVT, Hi, HiMask, UndefPassthru);
3050
3051 SDValue StackPtr = DAG.CreateStackTemporary(
3052 VecVT.getStoreSize(), DAG.getReducedAlign(VecVT, /*UseABI=*/false));
3053 MachineFunction &MF = DAG.getMachineFunction();
3054 MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(
3055 MF, cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex());
3056
3057 EVT LoMaskVT = LoMask.getValueType();
3058 assert(LoMaskVT.getScalarType() == MVT::i1 && "Expected vector of i1s");
3059
3060 // We store LoVec and then insert HiVec starting at offset=|1s| in LoMask.
3061 EVT WideLoMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
3062 LoMaskVT.getVectorElementCount());
3063 SDValue WideLoMask = DAG.getNode(ISD::ZERO_EXTEND, DL, WideLoMaskVT, LoMask);
3064 SDValue Offset = DAG.getNode(ISD::VECREDUCE_ADD, DL, MVT::i32, WideLoMask);
3065 Offset = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Offset);
3066
3067 SDValue Chain = DAG.getEntryNode();
3068 Chain = DAG.getStore(Chain, DL, Lo, StackPtr, PtrInfo);
3069 Chain = DAG.getStore(Chain, DL, Hi, Offset,
3071
3072 SDValue Compressed = DAG.getLoad(VecVT, DL, Chain, StackPtr, PtrInfo);
3073 if (!Passthru.isUndef()) {
3074 // Compress the input mask so only inactive lanes of the result are replaced
3075 // by their passthrough value.
3076 EVT MaskVT = Mask.getValueType();
3077 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32,
3078 MaskVT.getVectorElementCount());
3079 SDValue WideMask = DAG.getNode(ISD::ZERO_EXTEND, DL, WideMaskVT, Mask);
3080 SDValue NumActiveElts =
3081 DAG.getNode(ISD::VECREDUCE_ADD, DL, MVT::i32, WideMask);
3082
3083 SDValue StepVector = DAG.getStepVector(DL, WideMaskVT);
3084 SDValue SplatNumActiveElts = DAG.getSplat(WideMaskVT, DL, NumActiveElts);
3085 SDValue CompressedMask =
3086 DAG.getSetCC(DL, MaskVT, StepVector, SplatNumActiveElts, ISD::SETULT);
3087
3088 Compressed = DAG.getNode(ISD::VSELECT, DL, VecVT, CompressedMask,
3089 Compressed, Passthru);
3090 }
3091 std::tie(Lo, Hi) = DAG.SplitVector(Compressed, DL);
3092}
3093
3094void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE_VAR(SDNode *N, SDValue &Lo,
3095 SDValue &Hi) {
3096 // TODO: Split into half-width shuffles when the target lowers them natively.
3097 SDValue Res = TLI.expandVECTOR_SHUFFLE_VAR(N, DAG);
3098 std::tie(Lo, Hi) = DAG.SplitVector(Res, SDLoc(N));
3099}
3100
3101void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) {
3102 assert(N->getValueType(0).isVector() &&
3103 N->getOperand(0).getValueType().isVector() &&
3104 "Operand types must be vectors");
3105
3106 EVT LoVT, HiVT;
3107 SDLoc DL(N);
3108 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
3109
3110 // If the input also splits, handle it directly. Otherwise split it by hand.
3111 SDValue LL, LH, RL, RH;
3112 if (getTypeAction(N->getOperand(0).getValueType()) ==
3114 GetSplitVector(N->getOperand(0), LL, LH);
3115 else
3116 std::tie(LL, LH) = DAG.SplitVectorOperand(N, 0);
3117
3118 if (getTypeAction(N->getOperand(1).getValueType()) ==
3120 GetSplitVector(N->getOperand(1), RL, RH);
3121 else
3122 std::tie(RL, RH) = DAG.SplitVectorOperand(N, 1);
3123
3124 Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2));
3125 Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2));
3126}
3127
3128void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
3129 SDValue &Hi) {
3130 // Get the dest types - they may not match the input types, e.g. int_to_fp.
3131 EVT LoVT, HiVT;
3132 SDLoc dl(N);
3133 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
3134
3135 // If the input also splits, handle it directly for a compile time speedup.
3136 // Otherwise split it by hand.
3137 EVT InVT = N->getOperand(0).getValueType();
3138 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
3139 GetSplitVector(N->getOperand(0), Lo, Hi);
3140 else
3141 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
3142
3143 const SDNodeFlags Flags = N->getFlags();
3144 unsigned Opcode = N->getOpcode();
3145 if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP) {
3146 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1), N->getOperand(2),
3147 N->getOperand(3), Flags);
3148 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1), N->getOperand(2),
3149 N->getOperand(3), Flags);
3150 return;
3151 }
3152
3153 if (Opcode == ISD::FP_ROUND || Opcode == ISD::AssertNoFPClass ||
3155 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1), Flags);
3156 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1), Flags);
3157 } else {
3158 Lo = DAG.getNode(Opcode, dl, LoVT, Lo, Flags);
3159 Hi = DAG.getNode(Opcode, dl, HiVT, Hi, Flags);
3160 }
3161}
3162
3163void DAGTypeLegalizer::SplitVecRes_ADDRSPACECAST(SDNode *N, SDValue &Lo,
3164 SDValue &Hi) {
3165 SDLoc dl(N);
3166 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
3167
3168 // If the input also splits, handle it directly for a compile time speedup.
3169 // Otherwise split it by hand.
3170 EVT InVT = N->getOperand(0).getValueType();
3171 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
3172 GetSplitVector(N->getOperand(0), Lo, Hi);
3173 else
3174 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
3175
3176 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
3177 unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace();
3178 unsigned DestAS = AddrSpaceCastN->getDestAddressSpace();
3179 SDNodeFlags Flags = AddrSpaceCastN->getFlags();
3180 Lo = DAG.getAddrSpaceCast(dl, LoVT, Lo, SrcAS, DestAS, Flags);
3181 Hi = DAG.getAddrSpaceCast(dl, HiVT, Hi, SrcAS, DestAS, Flags);
3182}
3183
3184void DAGTypeLegalizer::SplitVecRes_UnaryOpWithTwoResults(SDNode *N,
3185 unsigned ResNo,
3186 SDValue &Lo,
3187 SDValue &Hi) {
3188 SDLoc dl(N);
3189 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0));
3190 auto [LoVT1, HiVT1] = DAG.GetSplitDestVTs(N->getValueType(1));
3191
3192 // If the input also splits, handle it directly for a compile time speedup.
3193 // Otherwise split it by hand.
3194 EVT InVT = N->getOperand(0).getValueType();
3195 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
3196 GetSplitVector(N->getOperand(0), Lo, Hi);
3197 else
3198 std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0);
3199
3200 Lo = DAG.getNode(N->getOpcode(), dl, {LoVT, LoVT1}, Lo, N->getFlags());
3201 Hi = DAG.getNode(N->getOpcode(), dl, {HiVT, HiVT1}, Hi, N->getFlags());
3202
3203 SDNode *HiNode = Hi.getNode();
3204 SDNode *LoNode = Lo.getNode();
3205
3206 // Replace the other vector result not being explicitly split here.
3207 unsigned OtherNo = 1 - ResNo;
3208 EVT OtherVT = N->getValueType(OtherNo);
3209 if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
3210 SetSplitVector(SDValue(N, OtherNo), SDValue(LoNode, OtherNo),
3211 SDValue(HiNode, OtherNo));
3212 } else {
3213 SDValue OtherVal =
3214 DAG.getNode(ISD::CONCAT_VECTORS, dl, OtherVT, SDValue(LoNode, OtherNo),
3215 SDValue(HiNode, OtherNo));
3216 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
3217 }
3218}
3219
3220void DAGTypeLegalizer::SplitVecRes_ExtendOp(SDNode *N, SDValue &Lo,
3221 SDValue &Hi) {
3222 SDLoc dl(N);
3223 EVT SrcVT = N->getOperand(0).getValueType();
3224 EVT DestVT = N->getValueType(0);
3225 EVT LoVT, HiVT;
3226 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(DestVT);
3227
3228 // We can do better than a generic split operation if the extend is doing
3229 // more than just doubling the width of the elements and the following are
3230 // true:
3231 // - The number of vector elements is even,
3232 // - the source type is legal,
3233 // - the type of a split source is illegal,
3234 // - the type of an extended (by doubling element size) source is legal, and
3235 // - the type of that extended source when split is legal.
3236 //
3237 // This won't necessarily completely legalize the operation, but it will
3238 // more effectively move in the right direction and prevent falling down
3239 // to scalarization in many cases due to the input vector being split too
3240 // far.
3241 if (SrcVT.getVectorElementCount().isKnownEven() &&
3242 SrcVT.getScalarSizeInBits() * 2 < DestVT.getScalarSizeInBits()) {
3243 LLVMContext &Ctx = *DAG.getContext();
3244 EVT NewSrcVT = SrcVT.widenIntegerVectorElementType(Ctx);
3245 EVT SplitSrcVT = SrcVT.getHalfNumVectorElementsVT(Ctx);
3246
3247 EVT SplitLoVT, SplitHiVT;
3248 std::tie(SplitLoVT, SplitHiVT) = DAG.GetSplitDestVTs(NewSrcVT);
3249 if (TLI.isTypeLegal(SrcVT) && !TLI.isTypeLegal(SplitSrcVT) &&
3250 TLI.isTypeLegal(NewSrcVT) && TLI.isTypeLegal(SplitLoVT)) {
3251 LLVM_DEBUG(dbgs() << "Split vector extend via incremental extend:";
3252 N->dump(&DAG); dbgs() << "\n");
3253 // Extend the source vector by one step.
3254 SDValue NewSrc =
3255 DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0));
3256 // Get the low and high halves of the new, extended one step, vector.
3257 std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
3258 // Extend those vector halves the rest of the way.
3259 Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo);
3260 Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi);
3261 return;
3262 }
3263 }
3264 // Fall back to the generic unary operator splitting otherwise.
3265 SplitVecRes_UnaryOp(N, Lo, Hi);
3266}
3267
3268void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N,
3269 SDValue &Lo, SDValue &Hi) {
3270 // The low and high parts of the original input give four input vectors.
3271 SDValue Inputs[4];
3272 SDLoc DL(N);
3273 GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]);
3274 GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]);
3275 EVT NewVT = Inputs[0].getValueType();
3276 unsigned NewElts = NewVT.getVectorNumElements();
3277
3278 auto &&IsConstant = [](const SDValue &N) {
3279 APInt SplatValue;
3280 return N.getResNo() == 0 &&
3281 (ISD::isConstantSplatVector(N.getNode(), SplatValue) ||
3283 };
3284 auto &&BuildVector = [NewElts, &DAG = DAG, NewVT, &DL](SDValue &Input1,
3285 SDValue &Input2,
3286 ArrayRef<int> Mask) {
3287 assert(Input1->getOpcode() == ISD::BUILD_VECTOR &&
3288 Input2->getOpcode() == ISD::BUILD_VECTOR &&
3289 "Expected build vector node.");
3290 EVT EltVT = NewVT.getVectorElementType();
3291 SmallVector<SDValue> Ops(NewElts, DAG.getPOISON(EltVT));
3292 for (unsigned I = 0; I < NewElts; ++I) {
3293 if (Mask[I] == PoisonMaskElem)
3294 continue;
3295 unsigned Idx = Mask[I];
3296 if (Idx >= NewElts)
3297 Ops[I] = Input2.getOperand(Idx - NewElts);
3298 else
3299 Ops[I] = Input1.getOperand(Idx);
3300 // Make the type of all elements the same as the element type.
3301 if (Ops[I].getValueType().bitsGT(EltVT))
3302 Ops[I] = DAG.getNode(ISD::TRUNCATE, DL, EltVT, Ops[I]);
3303 }
3304 return DAG.getBuildVector(NewVT, DL, Ops);
3305 };
3306
3307 // If Lo or Hi uses elements from at most two of the four input vectors, then
3308 // express it as a vector shuffle of those two inputs. Otherwise extract the
3309 // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR.
3310 SmallVector<int> OrigMask(N->getMask());
3311 // Try to pack incoming shuffles/inputs.
3312 auto &&TryPeekThroughShufflesInputs = [&Inputs, &NewVT, this, NewElts,
3313 &DL](SmallVectorImpl<int> &Mask) {
3314 // Check if all inputs are shuffles of the same operands or non-shuffles.
3315 MapVector<std::pair<SDValue, SDValue>, SmallVector<unsigned>> ShufflesIdxs;
3316 for (unsigned Idx = 0; Idx < std::size(Inputs); ++Idx) {
3317 SDValue Input = Inputs[Idx];
3318 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Input.getNode());
3319 if (!Shuffle ||
3320 Input.getOperand(0).getValueType() != Input.getValueType())
3321 continue;
3322 ShufflesIdxs[std::make_pair(Input.getOperand(0), Input.getOperand(1))]
3323 .push_back(Idx);
3324 ShufflesIdxs[std::make_pair(Input.getOperand(1), Input.getOperand(0))]
3325 .push_back(Idx);
3326 }
3327 for (auto &P : ShufflesIdxs) {
3328 if (P.second.size() < 2)
3329 continue;
3330 // Use shuffles operands instead of shuffles themselves.
3331 // 1. Adjust mask.
3332 for (int &Idx : Mask) {
3333 if (Idx == PoisonMaskElem)
3334 continue;
3335 unsigned SrcRegIdx = Idx / NewElts;
3336 if (Inputs[SrcRegIdx].isUndef()) {
3338 continue;
3339 }
3340 auto *Shuffle =
3341 dyn_cast<ShuffleVectorSDNode>(Inputs[SrcRegIdx].getNode());
3342 if (!Shuffle || !is_contained(P.second, SrcRegIdx))
3343 continue;
3344 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3345 if (MaskElt == PoisonMaskElem) {
3347 continue;
3348 }
3349 Idx = MaskElt % NewElts +
3350 P.second[Shuffle->getOperand(MaskElt / NewElts) == P.first.first
3351 ? 0
3352 : 1] *
3353 NewElts;
3354 }
3355 // 2. Update inputs.
3356 Inputs[P.second[0]] = P.first.first;
3357 Inputs[P.second[1]] = P.first.second;
3358 // Clear the pair data.
3359 P.second.clear();
3360 ShufflesIdxs[std::make_pair(P.first.second, P.first.first)].clear();
3361 }
3362 // Check if any concat_vectors can be simplified.
3363 SmallBitVector UsedSubVector(2 * std::size(Inputs));
3364 for (int &Idx : Mask) {
3365 if (Idx == PoisonMaskElem)
3366 continue;
3367 unsigned SrcRegIdx = Idx / NewElts;
3368 if (Inputs[SrcRegIdx].isUndef()) {
3370 continue;
3371 }
3373 getTypeAction(Inputs[SrcRegIdx].getValueType());
3374 if (Inputs[SrcRegIdx].getOpcode() == ISD::CONCAT_VECTORS &&
3375 Inputs[SrcRegIdx].getNumOperands() == 2 &&
3376 !Inputs[SrcRegIdx].getOperand(1).isUndef() &&
3377 (TypeAction == TargetLowering::TypeLegal ||
3378 TypeAction == TargetLowering::TypeWidenVector))
3379 UsedSubVector.set(2 * SrcRegIdx + (Idx % NewElts) / (NewElts / 2));
3380 }
3381 if (UsedSubVector.count() > 1) {
3383 for (unsigned I = 0; I < std::size(Inputs); ++I) {
3384 if (UsedSubVector.test(2 * I) == UsedSubVector.test(2 * I + 1))
3385 continue;
3386 if (Pairs.empty() || Pairs.back().size() == 2)
3387 Pairs.emplace_back();
3388 if (UsedSubVector.test(2 * I)) {
3389 Pairs.back().emplace_back(I, 0);
3390 } else {
3391 assert(UsedSubVector.test(2 * I + 1) &&
3392 "Expected to be used one of the subvectors.");
3393 Pairs.back().emplace_back(I, 1);
3394 }
3395 }
3396 if (!Pairs.empty() && Pairs.front().size() > 1) {
3397 // Adjust mask.
3398 for (int &Idx : Mask) {
3399 if (Idx == PoisonMaskElem)
3400 continue;
3401 unsigned SrcRegIdx = Idx / NewElts;
3402 auto *It = find_if(
3403 Pairs, [SrcRegIdx](ArrayRef<std::pair<unsigned, int>> Idxs) {
3404 return Idxs.front().first == SrcRegIdx ||
3405 Idxs.back().first == SrcRegIdx;
3406 });
3407 if (It == Pairs.end())
3408 continue;
3409 Idx = It->front().first * NewElts + (Idx % NewElts) % (NewElts / 2) +
3410 (SrcRegIdx == It->front().first ? 0 : (NewElts / 2));
3411 }
3412 // Adjust inputs.
3413 for (ArrayRef<std::pair<unsigned, int>> Idxs : Pairs) {
3414 Inputs[Idxs.front().first] = DAG.getNode(
3416 Inputs[Idxs.front().first].getValueType(),
3417 Inputs[Idxs.front().first].getOperand(Idxs.front().second),
3418 Inputs[Idxs.back().first].getOperand(Idxs.back().second));
3419 }
3420 }
3421 }
3422 bool Changed;
3423 do {
3424 // Try to remove extra shuffles (except broadcasts) and shuffles with the
3425 // reused operands.
3426 Changed = false;
3427 for (unsigned I = 0; I < std::size(Inputs); ++I) {
3428 auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Inputs[I].getNode());
3429 if (!Shuffle)
3430 continue;
3431 if (Shuffle->getOperand(0).getValueType() != NewVT)
3432 continue;
3433 int Op = -1;
3434 if (!Inputs[I].hasOneUse() && Shuffle->getOperand(1).isUndef() &&
3435 !Shuffle->isSplat()) {
3436 Op = 0;
3437 } else if (!Inputs[I].hasOneUse() &&
3438 !Shuffle->getOperand(1).isUndef()) {
3439 // Find the only used operand, if possible.
3440 for (int &Idx : Mask) {
3441 if (Idx == PoisonMaskElem)
3442 continue;
3443 unsigned SrcRegIdx = Idx / NewElts;
3444 if (SrcRegIdx != I)
3445 continue;
3446 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3447 if (MaskElt == PoisonMaskElem) {
3449 continue;
3450 }
3451 int OpIdx = MaskElt / NewElts;
3452 if (Op == -1) {
3453 Op = OpIdx;
3454 continue;
3455 }
3456 if (Op != OpIdx) {
3457 Op = -1;
3458 break;
3459 }
3460 }
3461 }
3462 if (Op < 0) {
3463 // Try to check if one of the shuffle operands is used already.
3464 for (int OpIdx = 0; OpIdx < 2; ++OpIdx) {
3465 if (Shuffle->getOperand(OpIdx).isUndef())
3466 continue;
3467 auto *It = find(Inputs, Shuffle->getOperand(OpIdx));
3468 if (It == std::end(Inputs))
3469 continue;
3470 int FoundOp = std::distance(std::begin(Inputs), It);
3471 // Found that operand is used already.
3472 // 1. Fix the mask for the reused operand.
3473 for (int &Idx : Mask) {
3474 if (Idx == PoisonMaskElem)
3475 continue;
3476 unsigned SrcRegIdx = Idx / NewElts;
3477 if (SrcRegIdx != I)
3478 continue;
3479 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3480 if (MaskElt == PoisonMaskElem) {
3482 continue;
3483 }
3484 int MaskIdx = MaskElt / NewElts;
3485 if (OpIdx == MaskIdx)
3486 Idx = MaskElt % NewElts + FoundOp * NewElts;
3487 }
3488 // 2. Set Op to the unused OpIdx.
3489 Op = (OpIdx + 1) % 2;
3490 break;
3491 }
3492 }
3493 if (Op >= 0) {
3494 Changed = true;
3495 Inputs[I] = Shuffle->getOperand(Op);
3496 // Adjust mask.
3497 for (int &Idx : Mask) {
3498 if (Idx == PoisonMaskElem)
3499 continue;
3500 unsigned SrcRegIdx = Idx / NewElts;
3501 if (SrcRegIdx != I)
3502 continue;
3503 int MaskElt = Shuffle->getMaskElt(Idx % NewElts);
3504 int OpIdx = MaskElt / NewElts;
3505 if (OpIdx != Op)
3506 continue;
3507 Idx = MaskElt % NewElts + SrcRegIdx * NewElts;
3508 }
3509 }
3510 }
3511 } while (Changed);
3512 };
3513 TryPeekThroughShufflesInputs(OrigMask);
3514 // Proces unique inputs.
3515 auto &&MakeUniqueInputs = [&Inputs, &IsConstant,
3516 NewElts](SmallVectorImpl<int> &Mask) {
3517 SetVector<SDValue> UniqueInputs;
3518 SetVector<SDValue> UniqueConstantInputs;
3519 for (const auto &I : Inputs) {
3520 if (IsConstant(I))
3521 UniqueConstantInputs.insert(I);
3522 else if (!I.isUndef())
3523 UniqueInputs.insert(I);
3524 }
3525 // Adjust mask in case of reused inputs. Also, need to insert constant
3526 // inputs at first, otherwise it affects the final outcome.
3527 if (UniqueInputs.size() != std::size(Inputs)) {
3528 auto &&UniqueVec = UniqueInputs.takeVector();
3529 auto &&UniqueConstantVec = UniqueConstantInputs.takeVector();
3530 unsigned ConstNum = UniqueConstantVec.size();
3531 for (int &Idx : Mask) {
3532 if (Idx == PoisonMaskElem)
3533 continue;
3534 unsigned SrcRegIdx = Idx / NewElts;
3535 if (Inputs[SrcRegIdx].isUndef()) {
3537 continue;
3538 }
3539 const auto It = find(UniqueConstantVec, Inputs[SrcRegIdx]);
3540 if (It != UniqueConstantVec.end()) {
3541 Idx = (Idx % NewElts) +
3542 NewElts * std::distance(UniqueConstantVec.begin(), It);
3543 assert(Idx >= 0 && "Expected defined mask idx.");
3544 continue;
3545 }
3546 const auto RegIt = find(UniqueVec, Inputs[SrcRegIdx]);
3547 assert(RegIt != UniqueVec.end() && "Cannot find non-const value.");
3548 Idx = (Idx % NewElts) +
3549 NewElts * (std::distance(UniqueVec.begin(), RegIt) + ConstNum);
3550 assert(Idx >= 0 && "Expected defined mask idx.");
3551 }
3552 copy(UniqueConstantVec, std::begin(Inputs));
3553 copy(UniqueVec, std::next(std::begin(Inputs), ConstNum));
3554 }
3555 };
3556 MakeUniqueInputs(OrigMask);
3557 SDValue OrigInputs[4];
3558 copy(Inputs, std::begin(OrigInputs));
3559 for (unsigned High = 0; High < 2; ++High) {
3560 SDValue &Output = High ? Hi : Lo;
3561
3562 // Build a shuffle mask for the output, discovering on the fly which
3563 // input vectors to use as shuffle operands.
3564 unsigned FirstMaskIdx = High * NewElts;
3565 SmallVector<int> Mask(NewElts * std::size(Inputs), PoisonMaskElem);
3566 copy(ArrayRef(OrigMask).slice(FirstMaskIdx, NewElts), Mask.begin());
3567 assert(!Output && "Expected default initialized initial value.");
3568 TryPeekThroughShufflesInputs(Mask);
3569 MakeUniqueInputs(Mask);
3570 SDValue TmpInputs[4];
3571 copy(Inputs, std::begin(TmpInputs));
3572 // Track changes in the output registers.
3573 int UsedIdx = -1;
3574 bool SecondIteration = false;
3575 auto &&AccumulateResults = [&UsedIdx, &SecondIteration](unsigned Idx) {
3576 if (UsedIdx < 0) {
3577 UsedIdx = Idx;
3578 return false;
3579 }
3580 if (UsedIdx >= 0 && static_cast<unsigned>(UsedIdx) == Idx)
3581 SecondIteration = true;
3582 return SecondIteration;
3583 };
3585 Mask, std::size(Inputs), std::size(Inputs),
3586 /*NumOfUsedRegs=*/1,
3587 [&Output, &DAG = DAG, NewVT]() { Output = DAG.getPOISON(NewVT); },
3588 [&Output, &DAG = DAG, NewVT, &DL, &Inputs,
3589 &BuildVector](ArrayRef<int> Mask, unsigned Idx, unsigned /*Unused*/) {
3590 if (Inputs[Idx]->getOpcode() == ISD::BUILD_VECTOR)
3591 Output = BuildVector(Inputs[Idx], Inputs[Idx], Mask);
3592 else
3593 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx],
3594 DAG.getPOISON(NewVT), Mask);
3595 Inputs[Idx] = Output;
3596 },
3597 [&AccumulateResults, &Output, &DAG = DAG, NewVT, &DL, &Inputs,
3598 &TmpInputs, &BuildVector](ArrayRef<int> Mask, unsigned Idx1,
3599 unsigned Idx2, bool /*Unused*/) {
3600 if (AccumulateResults(Idx1)) {
3601 if (Inputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
3602 Inputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
3603 Output = BuildVector(Inputs[Idx1], Inputs[Idx2], Mask);
3604 else
3605 Output = DAG.getVectorShuffle(NewVT, DL, Inputs[Idx1],
3606 Inputs[Idx2], Mask);
3607 } else {
3608 if (TmpInputs[Idx1]->getOpcode() == ISD::BUILD_VECTOR &&
3609 TmpInputs[Idx2]->getOpcode() == ISD::BUILD_VECTOR)
3610 Output = BuildVector(TmpInputs[Idx1], TmpInputs[Idx2], Mask);
3611 else
3612 Output = DAG.getVectorShuffle(NewVT, DL, TmpInputs[Idx1],
3613 TmpInputs[Idx2], Mask);
3614 }
3615 Inputs[Idx1] = Output;
3616 });
3617 copy(OrigInputs, std::begin(Inputs));
3618 }
3619}
3620
3621void DAGTypeLegalizer::SplitVecRes_VAARG(SDNode *N, SDValue &Lo, SDValue &Hi) {
3622 EVT OVT = N->getValueType(0);
3623 EVT NVT = OVT.getHalfNumVectorElementsVT(*DAG.getContext());
3624 SDValue Chain = N->getOperand(0);
3625 SDValue Ptr = N->getOperand(1);
3626 SDValue SV = N->getOperand(2);
3627 SDLoc dl(N);
3628
3629 const Align Alignment =
3630 DAG.getDataLayout().getABITypeAlign(NVT.getTypeForEVT(*DAG.getContext()));
3631
3632 Lo = DAG.getVAArg(NVT, dl, Chain, Ptr, SV, Alignment.value());
3633 Hi = DAG.getVAArg(NVT, dl, Lo.getValue(1), Ptr, SV, Alignment.value());
3634 Chain = Hi.getValue(1);
3635
3636 // Modified the chain - switch anything that used the old chain to use
3637 // the new one.
3638 ReplaceValueWith(SDValue(N, 1), Chain);
3639}
3640
3641void DAGTypeLegalizer::SplitVecRes_FP_TO_XINT_SAT(SDNode *N, SDValue &Lo,
3642 SDValue &Hi) {
3643 EVT DstVTLo, DstVTHi;
3644 std::tie(DstVTLo, DstVTHi) = DAG.GetSplitDestVTs(N->getValueType(0));
3645 SDLoc dl(N);
3646
3647 SDValue SrcLo, SrcHi;
3648 EVT SrcVT = N->getOperand(0).getValueType();
3649 if (getTypeAction(SrcVT) == TargetLowering::TypeSplitVector)
3650 GetSplitVector(N->getOperand(0), SrcLo, SrcHi);
3651 else
3652 std::tie(SrcLo, SrcHi) = DAG.SplitVectorOperand(N, 0);
3653
3654 Lo = DAG.getNode(N->getOpcode(), dl, DstVTLo, SrcLo, N->getOperand(1));
3655 Hi = DAG.getNode(N->getOpcode(), dl, DstVTHi, SrcHi, N->getOperand(1));
3656}
3657
3658void DAGTypeLegalizer::SplitVecRes_VECTOR_REPEAT(SDNode *N, SDValue &Lo,
3659 SDValue &Hi) {
3660 EVT VT = N->getValueType(0);
3661 SDValue Src = N->getOperand(0);
3662 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VT);
3663 assert(LoVT == HiVT && "Expected equal split types");
3664
3665 // Use smaller even/odd source vectors so their broadcasts can be
3666 // reinterleaved in the original lane order for every value of vscale.
3667 SDLoc DL(N);
3668 auto [SrcLo, SrcHi] = DAG.SplitVector(Src, DL);
3669 EVT SplitSrcVT = SrcLo.getValueType();
3670 SDValue Deinterleaved =
3671 DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL,
3672 DAG.getVTList(SplitSrcVT, SplitSrcVT), SrcLo, SrcHi);
3673 SDValue Even =
3674 DAG.getNode(ISD::VECTOR_REPEAT, DL, LoVT, Deinterleaved.getValue(0));
3675 SDValue Odd =
3676 DAG.getNode(ISD::VECTOR_REPEAT, DL, LoVT, Deinterleaved.getValue(1));
3677 SDValue Interleaved = DAG.getNode(ISD::VECTOR_INTERLEAVE, DL,
3678 DAG.getVTList(LoVT, LoVT), Even, Odd);
3679 Lo = Interleaved.getValue(0);
3680 Hi = Interleaved.getValue(1);
3681}
3682
3683void DAGTypeLegalizer::SplitVecRes_VECTOR_REVERSE(SDNode *N, SDValue &Lo,
3684 SDValue &Hi) {
3685 SDValue InLo, InHi;
3686 GetSplitVector(N->getOperand(0), InLo, InHi);
3687 SDLoc DL(N);
3688
3689 Lo = DAG.getNode(ISD::VECTOR_REVERSE, DL, InHi.getValueType(), InHi);
3690 Hi = DAG.getNode(ISD::VECTOR_REVERSE, DL, InLo.getValueType(), InLo);
3691}
3692
3693void DAGTypeLegalizer::SplitVecRes_VECTOR_SPLICE(SDNode *N, SDValue &Lo,
3694 SDValue &Hi) {
3695 SDLoc DL(N);
3696
3697 SDValue Expanded = TLI.expandVectorSplice(N, DAG);
3698 std::tie(Lo, Hi) = DAG.SplitVector(Expanded, DL);
3699}
3700
3701void DAGTypeLegalizer::SplitVecRes_VP_REVERSE(SDNode *N, SDValue &Lo,
3702 SDValue &Hi) {
3703 EVT VT = N->getValueType(0);
3704 SDValue Val = N->getOperand(0);
3705 SDValue Mask = N->getOperand(1);
3706 SDValue EVL = N->getOperand(2);
3707 SDLoc DL(N);
3708
3709 // The stack round-trip uses a byte stride, so a sub-byte element (e.g. i1)
3710 // would get stride 0 and alias every lane. Widen to a byte integer, reverse,
3711 // then truncate back.
3712 EVT OrigVT = VT;
3713 if (!VT.getVectorElementType().isByteSized()) {
3714 EVT WideEltVT = VT.getVectorElementType().changeTypeToInteger();
3715 WideEltVT = WideEltVT.getRoundIntegerType(*DAG.getContext());
3716 VT = VT.changeVectorElementType(*DAG.getContext(), WideEltVT);
3717 Val = DAG.getNode(ISD::ANY_EXTEND, DL, VT, Val);
3718 }
3719
3720 // Fallback to VP_STRIDED_STORE to stack followed by VP_LOAD.
3721 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3722
3723 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3725 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3726 EVT PtrVT = StackPtr.getValueType();
3727 auto &MF = DAG.getMachineFunction();
3728 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3729 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3730
3731 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3733 Alignment);
3734 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3736 Alignment);
3737
3738 EVL = DAG.getNode(
3739 ISD::UMIN, DL, EVL.getValueType(), DAG.getFreeze(EVL),
3740 DAG.getElementCount(DL, EVL.getValueType(), VT.getVectorElementCount()));
3741
3742 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3743 SDValue NumElemMinus1 =
3744 DAG.getNode(ISD::SUB, DL, PtrVT, DAG.getZExtOrTrunc(EVL, DL, PtrVT),
3745 DAG.getConstant(1, DL, PtrVT));
3746 SDValue StartOffset = DAG.getNode(ISD::MUL, DL, PtrVT, NumElemMinus1,
3747 DAG.getConstant(EltWidth, DL, PtrVT));
3748 SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, StartOffset);
3749 SDValue Stride = DAG.getConstant(-(int64_t)EltWidth, DL, PtrVT);
3750
3751 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3752 SDValue Store = DAG.getStridedStoreVP(DAG.getEntryNode(), DL, Val, StorePtr,
3753 DAG.getPOISON(PtrVT), Stride, TrueMask,
3754 EVL, MemVT, StoreMMO, ISD::UNINDEXED);
3755
3756 SDValue Load = DAG.getLoadVP(VT, DL, Store, StackPtr, Mask, EVL, LoadMMO);
3757
3758 // Truncate back if we widened above.
3759 if (OrigVT != VT)
3760 Load = DAG.getNode(ISD::TRUNCATE, DL, OrigVT, Load);
3761
3762 std::tie(Lo, Hi) = DAG.SplitVector(Load, DL);
3763}
3764
3765void DAGTypeLegalizer::SplitVecRes_VP_SPLICE(SDNode *N, SDValue &Lo,
3766 SDValue &Hi) {
3767 EVT VT = N->getValueType(0);
3768 SDValue V1 = N->getOperand(0);
3769 SDValue V2 = N->getOperand(1);
3770 int64_t Imm = cast<ConstantSDNode>(N->getOperand(2))->getSExtValue();
3771 SDValue Mask = N->getOperand(3);
3772 SDValue EVL1 = N->getOperand(4);
3773 SDValue EVL2 = N->getOperand(5);
3774 SDLoc DL(N);
3775
3776 // Since EVL2 is considered the real VL it gets promoted during
3777 // SelectionDAGBuilder. Promote EVL1 here if needed.
3778 if (getTypeAction(EVL1.getValueType()) == TargetLowering::TypePromoteInteger)
3779 EVL1 = ZExtPromotedInteger(EVL1);
3780
3781 // The stack splice addresses elements by byte offset/stride, which breaks for
3782 // a sub-byte element (e.g. i1): getVectorElementPointer asserts and the
3783 // stride is 0. Widen to a byte integer, splice, then truncate back.
3784 EVT OrigVT = VT;
3785 if (!VT.getVectorElementType().isByteSized()) {
3786 EVT WideEltVT = VT.getVectorElementType().changeTypeToInteger();
3787 WideEltVT = WideEltVT.getRoundIntegerType(*DAG.getContext());
3788 VT = VT.changeVectorElementType(*DAG.getContext(), WideEltVT);
3789 V1 = DAG.getNode(ISD::ANY_EXTEND, DL, VT, V1);
3790 V2 = DAG.getNode(ISD::ANY_EXTEND, DL, VT, V2);
3791 }
3792
3793 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
3794
3795 EVT MemVT = EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(),
3796 VT.getVectorElementCount() * 2);
3797 SDValue StackPtr = DAG.CreateStackTemporary(MemVT.getStoreSize(), Alignment);
3798 EVT PtrVT = StackPtr.getValueType();
3799 auto &MF = DAG.getMachineFunction();
3800 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
3801 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
3802
3803 MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand(
3805 Alignment);
3806 MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand(
3808 Alignment);
3809
3810 SDValue EltByteSize =
3811 DAG.getTypeSize(DL, PtrVT, VT.getVectorElementType().getStoreSize());
3812 SDValue EVL1Ptr = DAG.getZExtOrTrunc(DAG.getFreeze(EVL1), DL, PtrVT);
3813 SDValue EVL1Bytes = DAG.getNode(ISD::MUL, DL, PtrVT, EVL1Ptr, EltByteSize);
3814 // Clip EVL1Bytes to make sure we stay within the stack object.
3815 SDValue VTBytes = DAG.getTypeSize(DL, PtrVT, VT.getStoreSize());
3816 EVL1Bytes = DAG.getNode(ISD::UMIN, DL, PtrVT, EVL1Bytes, VTBytes);
3817 SDValue StackPtr2 = DAG.getMemBasePlusOffset(StackPtr, EVL1Bytes, DL);
3818 SDValue PoisonPtr = DAG.getPOISON(PtrVT);
3819
3820 SDValue TrueMask = DAG.getBoolConstant(true, DL, Mask.getValueType(), VT);
3821 SDValue StoreV1 =
3822 DAG.getStoreVP(DAG.getEntryNode(), DL, V1, StackPtr, PoisonPtr, TrueMask,
3823 EVL1, V1.getValueType(), StoreMMO, ISD::UNINDEXED);
3824
3826 DAG.getStoreVP(StoreV1, DL, V2, StackPtr2, PoisonPtr, TrueMask, EVL2,
3827 V2.getValueType(), StoreMMO, ISD::UNINDEXED);
3828
3829 SDValue Load;
3830 if (Imm >= 0) {
3831 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VT, N->getOperand(2));
3832 Load = DAG.getLoadVP(VT, DL, StoreV2, StackPtr, Mask, EVL2, LoadMMO);
3833 } else {
3834 uint64_t TrailingElts = -Imm;
3835 unsigned EltWidth = VT.getScalarSizeInBits() / 8;
3836 SDValue TrailingBytes = DAG.getConstant(TrailingElts * EltWidth, DL, PtrVT);
3837
3838 // Make sure TrailingBytes doesn't exceed the size of vec1.
3839 SDValue OffsetToV2 = DAG.getNode(ISD::SUB, DL, PtrVT, StackPtr2, StackPtr);
3840 TrailingBytes =
3841 DAG.getNode(ISD::UMIN, DL, PtrVT, TrailingBytes, OffsetToV2);
3842
3843 // Calculate the start address of the spliced result.
3844 StackPtr2 = DAG.getNode(ISD::SUB, DL, PtrVT, StackPtr2, TrailingBytes);
3845 Load = DAG.getLoadVP(VT, DL, StoreV2, StackPtr2, Mask, EVL2, LoadMMO);
3846 }
3847
3848 // Truncate back if we widened above.
3849 if (OrigVT != VT)
3850 Load = DAG.getNode(ISD::TRUNCATE, DL, OrigVT, Load);
3851
3852 EVT LoVT, HiVT;
3853 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(OrigVT);
3854 Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoVT, Load,
3855 DAG.getVectorIdxConstant(0, DL));
3856 Hi =
3857 DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, Load,
3858 DAG.getVectorIdxConstant(LoVT.getVectorMinNumElements(), DL));
3859}
3860
3861void DAGTypeLegalizer::SplitVecRes_PARTIAL_REDUCE_MLA(SDNode *N, SDValue &Lo,
3862 SDValue &Hi) {
3863 SDLoc DL(N);
3864 SDValue Acc = N->getOperand(0);
3865 SDValue Input1 = N->getOperand(1);
3866 SDValue Input2 = N->getOperand(2);
3867
3868 SDValue AccLo, AccHi;
3869 GetSplitVector(Acc, AccLo, AccHi);
3870 unsigned Opcode = N->getOpcode();
3871
3872 // If the input types don't need splitting, just accumulate into the
3873 // low part of the accumulator.
3874 if (getTypeAction(Input1.getValueType()) != TargetLowering::TypeSplitVector) {
3875 Lo = DAG.getNode(Opcode, DL, AccLo.getValueType(), AccLo, Input1, Input2);
3876 Hi = AccHi;
3877 return;
3878 }
3879
3880 SDValue Input1Lo, Input1Hi;
3881 SDValue Input2Lo, Input2Hi;
3882 GetSplitVector(Input1, Input1Lo, Input1Hi);
3883 GetSplitVector(Input2, Input2Lo, Input2Hi);
3884 EVT ResultVT = AccLo.getValueType();
3885
3886 Lo = DAG.getNode(Opcode, DL, ResultVT, AccLo, Input1Lo, Input2Lo);
3887 Hi = DAG.getNode(Opcode, DL, ResultVT, AccHi, Input1Hi, Input2Hi);
3888}
3889
3890void DAGTypeLegalizer::SplitVecRes_GET_ACTIVE_LANE_MASK(SDNode *N, SDValue &Lo,
3891 SDValue &Hi) {
3892 SDLoc DL(N);
3893 SDValue Op0 = N->getOperand(0);
3894 SDValue Op1 = N->getOperand(1);
3895 EVT OpVT = Op0.getValueType();
3896
3897 EVT LoVT, HiVT;
3898 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
3899
3900 Lo = DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, LoVT, Op0, Op1);
3901 SDValue LoElts = DAG.getElementCount(DL, OpVT, LoVT.getVectorElementCount());
3902 SDValue HiStartVal = DAG.getNode(ISD::UADDSAT, DL, OpVT, Op0, LoElts);
3903 Hi = DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, HiVT, HiStartVal, Op1);
3904}
3905
3906void DAGTypeLegalizer::SplitVecRes_VECTOR_MATCH(SDNode *N, SDValue &Lo,
3907 SDValue &Hi) {
3908 SDValue SourceLo, SourceHi;
3909 GetSplitVector(N->getOperand(0), SourceLo, SourceHi);
3910 SDValue MaskLo, MaskHi;
3911 GetSplitVector(N->getOperand(2), MaskLo, MaskHi);
3912 SDLoc DL(N);
3913
3914 Lo = DAG.getNode(ISD::VECTOR_MATCH, DL, MaskLo.getValueType(), SourceLo,
3915 N->getOperand(1), MaskLo, N->getFlags());
3916 Hi = DAG.getNode(ISD::VECTOR_MATCH, DL, MaskHi.getValueType(), SourceHi,
3917 N->getOperand(1), MaskHi, N->getFlags());
3918}
3919
3920void DAGTypeLegalizer::SplitVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
3921 unsigned Factor = N->getNumOperands();
3922
3923 SmallVector<SDValue, 8> Ops(Factor * 2);
3924 for (unsigned i = 0; i != Factor; ++i) {
3925 SDValue OpLo, OpHi;
3926 GetSplitVector(N->getOperand(i), OpLo, OpHi);
3927 Ops[i * 2] = OpLo;
3928 Ops[i * 2 + 1] = OpHi;
3929 }
3930
3931 SmallVector<EVT, 8> VTs(Factor, Ops[0].getValueType());
3932
3933 SDLoc DL(N);
3934 SDValue ResLo = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, VTs,
3935 ArrayRef(Ops).slice(0, Factor));
3936 SDValue ResHi = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, VTs,
3937 ArrayRef(Ops).slice(Factor, Factor));
3938
3939 for (unsigned i = 0; i != Factor; ++i)
3940 SetSplitVector(SDValue(N, i), ResLo.getValue(i), ResHi.getValue(i));
3941}
3942
3943void DAGTypeLegalizer::SplitVecRes_VECTOR_INTERLEAVE(SDNode *N) {
3944 unsigned Factor = N->getNumOperands();
3945
3946 SmallVector<SDValue, 8> Ops(Factor * 2);
3947 for (unsigned i = 0; i != Factor; ++i) {
3948 SDValue OpLo, OpHi;
3949 GetSplitVector(N->getOperand(i), OpLo, OpHi);
3950 Ops[i] = OpLo;
3951 Ops[i + Factor] = OpHi;
3952 }
3953
3954 SmallVector<EVT, 8> VTs(Factor, Ops[0].getValueType());
3955
3956 SDLoc DL(N);
3957 SDValue Res[] = {DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, VTs,
3958 ArrayRef(Ops).slice(0, Factor)),
3959 DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, VTs,
3960 ArrayRef(Ops).slice(Factor, Factor))};
3961
3962 for (unsigned i = 0; i != Factor; ++i) {
3963 unsigned IdxLo = 2 * i;
3964 unsigned IdxHi = 2 * i + 1;
3965 SetSplitVector(SDValue(N, i), Res[IdxLo / Factor].getValue(IdxLo % Factor),
3966 Res[IdxHi / Factor].getValue(IdxHi % Factor));
3967 }
3968}
3969
3970//===----------------------------------------------------------------------===//
3971// Operand Vector Splitting
3972//===----------------------------------------------------------------------===//
3973
3974/// This method is called when the specified operand of the specified node is
3975/// found to need vector splitting. At this point, all of the result types of
3976/// the node are known to be legal, but other operands of the node may need
3977/// legalization as well as the specified one.
3978bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
3979 LLVM_DEBUG(dbgs() << "Split node operand: "; N->dump(&DAG));
3980 SDValue Res = SDValue();
3981
3982 // See if the target wants to custom split this node.
3983 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
3984 return false;
3985
3986 switch (N->getOpcode()) {
3987 default:
3988#ifndef NDEBUG
3989 dbgs() << "SplitVectorOperand Op #" << OpNo << ": ";
3990 N->dump(&DAG);
3991 dbgs() << "\n";
3992#endif
3993 report_fatal_error("Do not know how to split this operator's "
3994 "operand!\n");
3995
3996 case ISD::STRICT_FSETCC:
3998 case ISD::SETCC: Res = SplitVecOp_VSETCC(N); break;
3999 case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break;
4000 case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break;
4001 case ISD::INSERT_SUBVECTOR: Res = SplitVecOp_INSERT_SUBVECTOR(N, OpNo); break;
4002 case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break;
4003 case ISD::CONCAT_VECTORS: Res = SplitVecOp_CONCAT_VECTORS(N); break;
4005 Res = SplitVecOp_VECTOR_FIND_LAST_ACTIVE(N);
4006 break;
4007 case ISD::TRUNCATE:
4008 Res = SplitVecOp_TruncateHelper(N);
4009 break;
4011 case ISD::FP_ROUND:
4014 Res = SplitVecOp_FP_ROUND(N);
4015 break;
4016 case ISD::FCOPYSIGN: Res = SplitVecOp_FPOpDifferentTypes(N); break;
4017 case ISD::STORE:
4018 Res = SplitVecOp_STORE(cast<StoreSDNode>(N), OpNo);
4019 break;
4020 case ISD::ATOMIC_STORE:
4021 Res = SplitVecOp_ATOMIC_STORE(cast<AtomicSDNode>(N));
4022 break;
4023 case ISD::VP_STORE:
4024 Res = SplitVecOp_VP_STORE(cast<VPStoreSDNode>(N), OpNo);
4025 break;
4026 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
4027 Res = SplitVecOp_VP_STRIDED_STORE(cast<VPStridedStoreSDNode>(N), OpNo);
4028 break;
4029 case ISD::MSTORE:
4030 Res = SplitVecOp_MSTORE(cast<MaskedStoreSDNode>(N), OpNo);
4031 break;
4032 case ISD::MSCATTER:
4033 case ISD::VP_SCATTER:
4034 Res = SplitVecOp_Scatter(cast<MemSDNode>(N), OpNo);
4035 break;
4036 case ISD::MGATHER:
4037 case ISD::VP_GATHER:
4038 Res = SplitVecOp_Gather(cast<MemSDNode>(N), OpNo);
4039 break;
4040 case ISD::VSELECT:
4041 Res = SplitVecOp_VSELECT(N, OpNo);
4042 break;
4043 case ISD::MASKED_UDIV:
4044 case ISD::MASKED_SDIV:
4045 case ISD::MASKED_UREM:
4046 case ISD::MASKED_SREM:
4047 Res = SplitVecOp_MaskedBinOp(N, OpNo);
4048 break;
4050 Res = SplitVecOp_VECTOR_COMPRESS(N, OpNo);
4051 break;
4053 Res = SplitVecOp_VECTOR_SHUFFLE_VAR(N, OpNo);
4054 break;
4057 case ISD::SINT_TO_FP:
4058 case ISD::UINT_TO_FP:
4059 if (N->getValueType(0).bitsLT(
4060 N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType()))
4061 Res = SplitVecOp_TruncateHelper(N);
4062 else
4063 Res = SplitVecOp_UnaryOp(N);
4064 break;
4067 Res = SplitVecOp_FP_TO_XINT_SAT(N);
4068 break;
4069 case ISD::FP_TO_SINT:
4070 case ISD::FP_TO_UINT:
4074 case ISD::FP_EXTEND:
4075 case ISD::SIGN_EXTEND:
4076 case ISD::ZERO_EXTEND:
4077 case ISD::ANY_EXTEND:
4078 case ISD::FTRUNC:
4079 case ISD::LROUND:
4080 case ISD::LLROUND:
4081 case ISD::LRINT:
4082 case ISD::LLRINT:
4083 Res = SplitVecOp_UnaryOp(N);
4084 break;
4085 case ISD::FLDEXP:
4086 Res = SplitVecOp_FPOpDifferentTypes(N);
4087 break;
4088
4089 case ISD::SCMP:
4090 case ISD::UCMP:
4091 Res = SplitVecOp_CMP(N);
4092 break;
4093
4094 case ISD::FAKE_USE:
4095 Res = SplitVecOp_FAKE_USE(N);
4096 break;
4100 Res = SplitVecOp_ExtVecInRegOp(N);
4101 break;
4102
4105 case ISD::VECREDUCE_ADD:
4106 case ISD::VECREDUCE_MUL:
4107 case ISD::VECREDUCE_AND:
4108 case ISD::VECREDUCE_OR:
4109 case ISD::VECREDUCE_XOR:
4120 Res = SplitVecOp_VECREDUCE(N, OpNo);
4121 break;
4124 Res = SplitVecOp_VECREDUCE_SEQ(N);
4125 break;
4126 case ISD::VP_REDUCE_FADD:
4127 case ISD::VP_REDUCE_SEQ_FADD:
4128 case ISD::VP_REDUCE_FMUL:
4129 case ISD::VP_REDUCE_SEQ_FMUL:
4130 case ISD::VP_REDUCE_ADD:
4131 case ISD::VP_REDUCE_MUL:
4132 case ISD::VP_REDUCE_AND:
4133 case ISD::VP_REDUCE_OR:
4134 case ISD::VP_REDUCE_XOR:
4135 case ISD::VP_REDUCE_SMAX:
4136 case ISD::VP_REDUCE_SMIN:
4137 case ISD::VP_REDUCE_UMAX:
4138 case ISD::VP_REDUCE_UMIN:
4139 case ISD::VP_REDUCE_FMAX:
4140 case ISD::VP_REDUCE_FMIN:
4141 case ISD::VP_REDUCE_FMAXIMUM:
4142 case ISD::VP_REDUCE_FMINIMUM:
4143 Res = SplitVecOp_VP_REDUCE(N, OpNo);
4144 break;
4145 case ISD::CTTZ_ELTS:
4147 Res = SplitVecOp_CttzElts(N);
4148 break;
4149 case ISD::VP_CTTZ_ELTS:
4150 case ISD::VP_CTTZ_ELTS_ZERO_POISON:
4151 Res = SplitVecOp_VP_CttzElements(N);
4152 break;
4154 Res = SplitVecOp_VECTOR_HISTOGRAM(N);
4155 break;
4160 Res = SplitVecOp_PARTIAL_REDUCE_MLA(N);
4161 break;
4162 case ISD::VECTOR_MATCH:
4163 Res = SplitVecOp_VECTOR_MATCH(N, OpNo);
4164 break;
4165 }
4166
4167 // If the result is null, the sub-method took care of registering results etc.
4168 if (!Res.getNode()) return false;
4169
4170 // If the result is N, the sub-method updated N in place. Tell the legalizer
4171 // core about this.
4172 if (Res.getNode() == N)
4173 return true;
4174
4175 if (N->isStrictFPOpcode())
4176 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
4177 "Invalid operand expansion");
4178 else
4179 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
4180 "Invalid operand expansion");
4181
4182 ReplaceValueWith(SDValue(N, 0), Res);
4183 return false;
4184}
4185
4186SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
4187 SDLoc DL(N);
4188
4189 SDValue LoMask, HiMask;
4190 GetSplitVector(N->getOperand(0), LoMask, HiMask);
4191
4192 EVT VT = N->getValueType(0);
4193 EVT SplitVT = LoMask.getValueType();
4194 ElementCount SplitEC = SplitVT.getVectorElementCount();
4195
4196 // Find the last active in both the low and the high masks.
4197 SDValue LoFind = DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, VT, LoMask);
4198 SDValue HiFind = DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, VT, HiMask);
4199
4200 // Check if any lane is active in the high mask.
4201 // FIXME: This would not be necessary if VECTOR_FIND_LAST_ACTIVE returned a
4202 // sentinel value for "none active".
4203 SDValue AnyHiActive = DAG.getNode(ISD::VECREDUCE_OR, DL, MVT::i1, HiMask);
4204 SDValue Cond = DAG.getBoolExtOrTrunc(AnyHiActive, DL,
4205 getSetCCResultType(MVT::i1), MVT::i1);
4206
4207 // Return: AnyHiActive ? (HiFind + SplitEC) : LoFind;
4208 return DAG.getNode(ISD::SELECT, DL, VT, Cond,
4209 DAG.getNode(ISD::ADD, DL, VT, HiFind,
4210 DAG.getElementCount(DL, VT, SplitEC)),
4211 LoFind);
4212}
4213
4214SDValue DAGTypeLegalizer::SplitVecOp_VSELECT(SDNode *N, unsigned OpNo) {
4215 // The only possibility for an illegal operand is the mask, since result type
4216 // legalization would have handled this node already otherwise.
4217 assert(OpNo == 0 && "Illegal operand must be mask");
4218
4219 SDValue Mask = N->getOperand(0);
4220 SDValue Src0 = N->getOperand(1);
4221 SDValue Src1 = N->getOperand(2);
4222 EVT Src0VT = Src0.getValueType();
4223 SDLoc DL(N);
4224 assert(Mask.getValueType().isVector() && "VSELECT without a vector mask?");
4225
4226 SDValue Lo, Hi;
4227 GetSplitVector(N->getOperand(0), Lo, Hi);
4228 assert(Lo.getValueType() == Hi.getValueType() &&
4229 "Lo and Hi have differing types");
4230
4231 EVT LoOpVT, HiOpVT;
4232 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(Src0VT);
4233 assert(LoOpVT == HiOpVT && "Asymmetric vector split?");
4234
4235 SDValue LoOp0, HiOp0, LoOp1, HiOp1, LoMask, HiMask;
4236 std::tie(LoOp0, HiOp0) = DAG.SplitVector(Src0, DL);
4237 std::tie(LoOp1, HiOp1) = DAG.SplitVector(Src1, DL);
4238 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
4239
4240 SDValue LoSelect =
4241 DAG.getNode(ISD::VSELECT, DL, LoOpVT, LoMask, LoOp0, LoOp1);
4242 SDValue HiSelect =
4243 DAG.getNode(ISD::VSELECT, DL, HiOpVT, HiMask, HiOp0, HiOp1);
4244
4245 return DAG.getNode(ISD::CONCAT_VECTORS, DL, Src0VT, LoSelect, HiSelect);
4246}
4247
4248SDValue DAGTypeLegalizer::SplitVecOp_MaskedBinOp(SDNode *N, unsigned OpNo) {
4249 assert(OpNo == 2 && "Illegal operand must be mask");
4250
4251 SDLoc DL(N);
4252 auto [LHSLo, LHSHi] = DAG.SplitVector(N->getOperand(0), DL);
4253 auto [RHSLo, RHSHi] = DAG.SplitVector(N->getOperand(1), DL);
4254 SDValue MaskLo, MaskHi;
4255 GetSplitVector(N->getOperand(2), MaskLo, MaskHi);
4256
4257 SDValue Lo = DAG.getNode(N->getOpcode(), DL, LHSLo.getValueType(), LHSLo,
4258 RHSLo, MaskLo, N->getFlags());
4259 SDValue Hi = DAG.getNode(N->getOpcode(), DL, LHSHi.getValueType(), LHSHi,
4260 RHSHi, MaskHi, N->getFlags());
4261 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), Lo, Hi);
4262}
4263
4264SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_COMPRESS(SDNode *N, unsigned OpNo) {
4265 // The only possibility for an illegal operand is the mask, since result type
4266 // legalization would have handled this node already otherwise.
4267 assert(OpNo == 1 && "Illegal operand must be mask");
4268
4269 // To split the mask, we need to split the result type too, so we can just
4270 // reuse that logic here.
4271 SDValue Lo, Hi;
4272 SplitVecRes_VECTOR_COMPRESS(N, Lo, Hi);
4273
4274 EVT VecVT = N->getValueType(0);
4275 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VecVT, Lo, Hi);
4276}
4277
4278SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_SHUFFLE_VAR(SDNode *N,
4279 unsigned OpNo) {
4280 // The only possibility for an illegal operand is the mask, since result type
4281 // legalization would have handled this node already otherwise.
4282 assert(OpNo == 1 && "Illegal operand must be mask");
4283 // TODO: Legalize the mask type instead once a target lowers the node.
4284 return TLI.expandVECTOR_SHUFFLE_VAR(N, DAG);
4285}
4286
4287SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE(SDNode *N, unsigned OpNo) {
4288 EVT ResVT = N->getValueType(0);
4289 SDValue Lo, Hi;
4290 SDLoc dl(N);
4291
4292 SDValue VecOp = N->getOperand(OpNo);
4293 EVT VecVT = VecOp.getValueType();
4294 assert(VecVT.isVector() && "Can only split reduce vector operand");
4295 GetSplitVector(VecOp, Lo, Hi);
4296 EVT LoOpVT, HiOpVT;
4297 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
4298
4299 // Use the appropriate scalar instruction on the split subvectors before
4300 // reducing the now partially reduced smaller vector.
4301 unsigned CombineOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
4302 SDValue Partial = DAG.getNode(CombineOpc, dl, LoOpVT, Lo, Hi, N->getFlags());
4303 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, N->getFlags());
4304}
4305
4306SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE_SEQ(SDNode *N) {
4307 EVT ResVT = N->getValueType(0);
4308 SDValue Lo, Hi;
4309 SDLoc dl(N);
4310
4311 SDValue AccOp = N->getOperand(0);
4312 SDValue VecOp = N->getOperand(1);
4313 SDNodeFlags Flags = N->getFlags();
4314
4315 EVT VecVT = VecOp.getValueType();
4316 assert(VecVT.isVector() && "Can only split reduce vector operand");
4317 GetSplitVector(VecOp, Lo, Hi);
4318 EVT LoOpVT, HiOpVT;
4319 std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);
4320
4321 // Reduce low half.
4322 SDValue Partial = DAG.getNode(N->getOpcode(), dl, ResVT, AccOp, Lo, Flags);
4323
4324 // Reduce high half, using low half result as initial value.
4325 return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, Hi, Flags);
4326}
4327
4328SDValue DAGTypeLegalizer::SplitVecOp_VP_REDUCE(SDNode *N, unsigned OpNo) {
4329 assert(N->isVPOpcode() && "Expected VP opcode");
4330 assert(OpNo == 1 && "Can only split reduce vector operand");
4331
4332 unsigned Opc = N->getOpcode();
4333 EVT ResVT = N->getValueType(0);
4334 SDValue Lo, Hi;
4335 SDLoc dl(N);
4336
4337 SDValue VecOp = N->getOperand(OpNo);
4338 EVT VecVT = VecOp.getValueType();
4339 assert(VecVT.isVector() && "Can only split reduce vector operand");
4340 GetSplitVector(VecOp, Lo, Hi);
4341
4342 SDValue MaskLo, MaskHi;
4343 std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(2));
4344
4345 SDValue EVLLo, EVLHi;
4346 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(N->getOperand(3), VecVT, dl);
4347
4348 const SDNodeFlags Flags = N->getFlags();
4349
4350 SDValue ResLo =
4351 DAG.getNode(Opc, dl, ResVT, {N->getOperand(0), Lo, MaskLo, EVLLo}, Flags);
4352 return DAG.getNode(Opc, dl, ResVT, {ResLo, Hi, MaskHi, EVLHi}, Flags);
4353}
4354
4355SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) {
4356 // The result has a legal vector type, but the input needs splitting.
4357 EVT ResVT = N->getValueType(0);
4358 SDValue Lo, Hi;
4359 SDLoc dl(N);
4360 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
4361 EVT InVT = Lo.getValueType();
4362
4363 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
4364 InVT.getVectorElementCount());
4365
4366 if (N->isStrictFPOpcode()) {
4367 Lo = DAG.getNode(N->getOpcode(), dl, {OutVT, MVT::Other},
4368 {N->getOperand(0), Lo});
4369 Hi = DAG.getNode(N->getOpcode(), dl, {OutVT, MVT::Other},
4370 {N->getOperand(0), Hi});
4371
4372 // Build a factor node to remember that this operation is independent
4373 // of the other one.
4374 SDValue Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
4375 Hi.getValue(1));
4376
4377 // Legalize the chain result - switch anything that used the old chain to
4378 // use the new one.
4379 ReplaceValueWith(SDValue(N, 1), Ch);
4380 } else {
4381 Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo);
4382 Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi);
4383 }
4384
4385 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4386}
4387
4388// Split a FAKE_USE use of a vector into FAKE_USEs of hi and lo part.
4389SDValue DAGTypeLegalizer::SplitVecOp_FAKE_USE(SDNode *N) {
4390 SDValue Lo, Hi;
4391 GetSplitVector(N->getOperand(1), Lo, Hi);
4392 SDValue Chain =
4393 DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0), Lo);
4394 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, Chain, Hi);
4395}
4396
4397SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) {
4398 // For example, i64 = BITCAST v4i16 on alpha. Typically the vector will
4399 // end up being split all the way down to individual components. Convert the
4400 // split pieces into integers and reassemble.
4401 EVT ResVT = N->getValueType(0);
4402 SDValue Lo, Hi;
4403 GetSplitVector(N->getOperand(0), Lo, Hi);
4404 SDLoc dl(N);
4405
4406 if (ResVT.isScalableVector()) {
4407 auto [LoVT, HiVT] = DAG.GetSplitDestVTs(ResVT);
4408 Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
4409 Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
4410 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
4411 }
4412
4413 Lo = BitConvertToInteger(Lo);
4414 Hi = BitConvertToInteger(Hi);
4415
4416 if (DAG.getDataLayout().isBigEndian())
4417 std::swap(Lo, Hi);
4418
4419 return DAG.getNode(ISD::BITCAST, dl, ResVT, JoinIntegers(Lo, Hi));
4420}
4421
4422SDValue DAGTypeLegalizer::SplitVecOp_INSERT_SUBVECTOR(SDNode *N,
4423 unsigned OpNo) {
4424 assert(OpNo == 1 && "Invalid OpNo; can only split SubVec.");
4425 // We know that the result type is legal.
4426 EVT ResVT = N->getValueType(0);
4427
4428 SDValue Vec = N->getOperand(0);
4429 SDValue SubVec = N->getOperand(1);
4430 SDValue Idx = N->getOperand(2);
4431 SDLoc dl(N);
4432
4433 SDValue Lo, Hi;
4434 GetSplitVector(SubVec, Lo, Hi);
4435
4436 uint64_t IdxVal = Idx->getAsZExtVal();
4438
4439 SDValue FirstInsertion =
4440 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, Vec, Lo, Idx);
4441 SDValue SecondInsertion =
4442 DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, FirstInsertion, Hi,
4443 DAG.getVectorIdxConstant(IdxVal + LoElts, dl));
4444
4445 return SecondInsertion;
4446}
4447
4448SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
4449 // We know that the extracted result type is legal.
4450 EVT SubVT = N->getValueType(0);
4451 SDValue Idx = N->getOperand(1);
4452 SDLoc dl(N);
4453 SDValue Lo, Hi;
4454
4455 GetSplitVector(N->getOperand(0), Lo, Hi);
4456
4457 ElementCount LoElts = Lo.getValueType().getVectorElementCount();
4458 // Note: For scalable vectors, the index is scaled by vscale.
4459 ElementCount IdxVal =
4460 ElementCount::get(Idx->getAsZExtVal(), SubVT.isScalableVector());
4461 uint64_t IdxValMin = IdxVal.getKnownMinValue();
4462
4463 EVT SrcVT = N->getOperand(0).getValueType();
4464 ElementCount NumResultElts = SubVT.getVectorElementCount();
4465
4466 // If the extracted elements are all in the low half, do a simple extract.
4467 if (ElementCount::isKnownLE(IdxVal + NumResultElts, LoElts))
4468 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx);
4469
4470 unsigned LoEltsMin = LoElts.getKnownMinValue();
4471 if (IdxValMin < LoEltsMin && SubVT.isFixedLengthVector() &&
4472 SrcVT.isFixedLengthVector()) {
4473 // Extracted subvector crosses vector split, so we need to blend the two
4474 // halves.
4475 // TODO: May be able to emit partial extract_subvector.
4477 Elts.reserve(NumResultElts.getFixedValue());
4478
4479 // This is not valid for scalable vectors. If SubVT is scalable, this is the
4480 // same as unrolling a scalable dimension (invalid). If ScrVT is scalable,
4481 // `Lo[LoEltsMin]` may not be the last element of `Lo`.
4482 DAG.ExtractVectorElements(Lo, Elts, /*Start=*/IdxValMin,
4483 /*Count=*/LoEltsMin - IdxValMin);
4484 DAG.ExtractVectorElements(Hi, Elts, /*Start=*/0,
4485 /*Count=*/SubVT.getVectorNumElements() -
4486 Elts.size());
4487 return DAG.getBuildVector(SubVT, dl, Elts);
4488 }
4489
4490 if (SubVT.isScalableVector() == SrcVT.isScalableVector()) {
4491 ElementCount ExtractIdx = IdxVal - LoElts;
4492 if (ExtractIdx.isKnownMultipleOf(NumResultElts))
4493 return DAG.getExtractSubvector(dl, SubVT, Hi,
4494 ExtractIdx.getKnownMinValue());
4495
4496 EVT HiVT = Hi.getValueType();
4497 assert(HiVT.isFixedLengthVector() &&
4498 "Only fixed-vector extracts are supported in this case");
4499
4500 // We cannot create an extract_subvector that isn't a multiple of the
4501 // result size, which may go out of bounds for the last elements. Shuffle
4502 // the desired elements down to 0 and do a simple 0 extract.
4503 SmallVector<int, 8> Mask(HiVT.getVectorNumElements(), -1);
4504 for (int I = 0; I != int(NumResultElts.getFixedValue()); ++I)
4505 Mask[I] = int(ExtractIdx.getFixedValue()) + I;
4506
4507 SDValue Shuffle =
4508 DAG.getVectorShuffle(HiVT, dl, Hi, DAG.getPOISON(HiVT), Mask);
4509 return DAG.getExtractSubvector(dl, SubVT, Shuffle, 0);
4510 }
4511
4512 // After this point the DAG node only permits extracting fixed-width
4513 // subvectors from scalable vectors.
4514 assert(SubVT.isFixedLengthVector() &&
4515 "Extracting scalable subvector from fixed-width unsupported");
4516
4517 // If the element type is i1 and we're not promoting the result, then we may
4518 // end up loading the wrong data since the bits are packed tightly into
4519 // bytes. For example, if we extract a v4i1 (legal) from a nxv4i1 (legal)
4520 // type at index 4, then we will load a byte starting at index 0.
4521 if (SubVT.getScalarType() == MVT::i1)
4522 report_fatal_error("Don't know how to extract fixed-width predicate "
4523 "subvector from a scalable predicate vector");
4524
4525 // Spill the vector to the stack. We should use the alignment for
4526 // the smallest part.
4527 SDValue Vec = N->getOperand(0);
4528 EVT VecVT = Vec.getValueType();
4529 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
4531 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
4532 auto &MF = DAG.getMachineFunction();
4533 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
4534 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
4535
4536 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
4537 SmallestAlign);
4538
4539 // Extract the subvector by loading the correct part.
4540 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVT, Idx);
4541
4542 return DAG.getLoad(
4543 SubVT, dl, Store, StackPtr,
4544 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()));
4545}
4546
4547SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
4548 SDValue Vec = N->getOperand(0);
4549 SDValue Idx = N->getOperand(1);
4550 EVT VecVT = Vec.getValueType();
4551
4552 if (const ConstantSDNode *Index = dyn_cast<ConstantSDNode>(Idx)) {
4553 uint64_t IdxVal = Index->getZExtValue();
4554
4555 SDValue Lo, Hi;
4556 GetSplitVector(Vec, Lo, Hi);
4557
4558 uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
4559
4560 if (IdxVal < LoElts)
4561 return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0);
4562 else if (!Vec.getValueType().isScalableVector())
4563 return SDValue(DAG.UpdateNodeOperands(N, Hi,
4564 DAG.getConstant(IdxVal - LoElts, SDLoc(N),
4565 Idx.getValueType())), 0);
4566 }
4567
4568 // See if the target wants to custom expand this node.
4569 if (CustomLowerNode(N, N->getValueType(0), true))
4570 return SDValue();
4571
4572 // Make the vector elements byte-addressable if they aren't already.
4573 SDLoc dl(N);
4574 EVT EltVT = VecVT.getVectorElementType();
4575 if (!EltVT.isByteSized()) {
4576 EltVT = EltVT.changeTypeToInteger().getRoundIntegerType(*DAG.getContext());
4577 VecVT = VecVT.changeElementType(*DAG.getContext(), EltVT);
4578 Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
4579 SDValue NewExtract =
4580 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Vec, Idx);
4581 return DAG.getAnyExtOrTrunc(NewExtract, dl, N->getValueType(0));
4582 }
4583
4584 // Store the vector to the stack.
4585 // In cases where the vector is illegal it will be broken down into parts
4586 // and stored in parts - we should use the alignment for the smallest part.
4587 Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
4589 DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
4590 auto &MF = DAG.getMachineFunction();
4591 auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
4592 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
4593 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
4594 SmallestAlign);
4595
4596 // Load back the required element.
4597 StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
4598
4599 // EXTRACT_VECTOR_ELT can extend the element type to the width of the return
4600 // type, leaving the high bits undefined. But it can't truncate.
4601 assert(N->getValueType(0).bitsGE(EltVT) && "Illegal EXTRACT_VECTOR_ELT.");
4602
4603 return DAG.getExtLoad(
4604 ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
4605 MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT,
4606 commonAlignment(SmallestAlign, EltVT.getFixedSizeInBits() / 8));
4607}
4608
4609SDValue DAGTypeLegalizer::SplitVecOp_ExtVecInRegOp(SDNode *N) {
4610 SDValue Lo, Hi;
4611
4612 // *_EXTEND_VECTOR_INREG only reference the lower half of the input, so
4613 // splitting the result has the same effect as splitting the input operand.
4614 SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
4615
4616 return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), N->getValueType(0), Lo, Hi);
4617}
4618
4619SDValue DAGTypeLegalizer::SplitVecOp_Gather(MemSDNode *N, unsigned OpNo) {
4620 (void)OpNo;
4621 SDValue Lo, Hi;
4622 SplitVecRes_Gather(N, Lo, Hi);
4623
4624 SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, N, N->getValueType(0), Lo, Hi);
4625 ReplaceValueWith(SDValue(N, 0), Res);
4626 return SDValue();
4627}
4628
4629SDValue DAGTypeLegalizer::SplitVecOp_VP_STORE(VPStoreSDNode *N, unsigned OpNo) {
4630 assert(N->isUnindexed() && "Indexed vp_store of vector?");
4631 SDValue Ch = N->getChain();
4632 SDValue Ptr = N->getBasePtr();
4633 SDValue Offset = N->getOffset();
4634 assert(Offset.isUndef() && "Unexpected VP store offset");
4635 SDValue Mask = N->getMask();
4636 SDValue EVL = N->getVectorLength();
4637 SDValue Data = N->getValue();
4638 Align Alignment = N->getBaseAlign();
4639 SDLoc DL(N);
4640
4641 SDValue DataLo, DataHi;
4642 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4643 // Split Data operand
4644 GetSplitVector(Data, DataLo, DataHi);
4645 else
4646 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
4647
4648 // Split Mask operand
4649 SDValue MaskLo, MaskHi;
4650 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
4651 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
4652 } else {
4653 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
4654 GetSplitVector(Mask, MaskLo, MaskHi);
4655 else
4656 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
4657 }
4658
4659 EVT MemoryVT = N->getMemoryVT();
4660 EVT LoMemVT, HiMemVT;
4661 bool HiIsEmpty = false;
4662 std::tie(LoMemVT, HiMemVT) =
4663 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
4664
4665 // Split EVL
4666 SDValue EVLLo, EVLHi;
4667 std::tie(EVLLo, EVLHi) = DAG.SplitEVL(EVL, Data.getValueType(), DL);
4668
4669 SDValue Lo, Hi;
4670 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4671 N->getPointerInfo(), MachineMemOperand::MOStore,
4673 MMOMetadata(N->getAAInfo(), N->getRanges()));
4674
4675 Lo = DAG.getStoreVP(Ch, DL, DataLo, Ptr, Offset, MaskLo, EVLLo, LoMemVT, MMO,
4676 N->getAddressingMode(), N->isTruncatingStore(),
4677 N->isCompressingStore());
4678
4679 // If the hi vp_store has zero storage size, only the lo vp_store is needed.
4680 if (HiIsEmpty)
4681 return Lo;
4682
4683 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
4684 N->isCompressingStore());
4685
4686 MachinePointerInfo MPI;
4687 if (LoMemVT.isScalableVector()) {
4688 Alignment = commonAlignment(Alignment,
4689 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4690 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
4691 } else
4692 MPI = N->getPointerInfo().getWithOffset(
4693 LoMemVT.getStoreSize().getFixedValue());
4694
4695 MMO = DAG.getMachineFunction().getMachineMemOperand(
4697 Alignment, MMOMetadata(N->getAAInfo(), N->getRanges()));
4698
4699 Hi = DAG.getStoreVP(Ch, DL, DataHi, Ptr, Offset, MaskHi, EVLHi, HiMemVT, MMO,
4700 N->getAddressingMode(), N->isTruncatingStore(),
4701 N->isCompressingStore());
4702
4703 // Build a factor node to remember that this store is independent of the
4704 // other one.
4705 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4706}
4707
4708SDValue DAGTypeLegalizer::SplitVecOp_VP_STRIDED_STORE(VPStridedStoreSDNode *N,
4709 unsigned OpNo) {
4710 assert(N->isUnindexed() && "Indexed vp_strided_store of a vector?");
4711 assert(N->getOffset().isUndef() && "Unexpected VP strided store offset");
4712
4713 SDLoc DL(N);
4714
4715 SDValue Data = N->getValue();
4716 SDValue LoData, HiData;
4717 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4718 GetSplitVector(Data, LoData, HiData);
4719 else
4720 std::tie(LoData, HiData) = DAG.SplitVector(Data, DL);
4721
4722 EVT LoMemVT, HiMemVT;
4723 bool HiIsEmpty = false;
4724 std::tie(LoMemVT, HiMemVT) = DAG.GetDependentSplitDestVTs(
4725 N->getMemoryVT(), LoData.getValueType(), &HiIsEmpty);
4726
4727 SDValue Mask = N->getMask();
4728 SDValue LoMask, HiMask;
4729 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC)
4730 SplitVecRes_SETCC(Mask.getNode(), LoMask, HiMask);
4731 else if (getTypeAction(Mask.getValueType()) ==
4733 GetSplitVector(Mask, LoMask, HiMask);
4734 else
4735 std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);
4736
4737 SDValue LoEVL, HiEVL;
4738 std::tie(LoEVL, HiEVL) =
4739 DAG.SplitEVL(N->getVectorLength(), Data.getValueType(), DL);
4740
4741 // Generate the low vp_strided_store
4742 SDValue Lo = DAG.getStridedStoreVP(
4743 N->getChain(), DL, LoData, N->getBasePtr(), N->getOffset(),
4744 N->getStride(), LoMask, LoEVL, LoMemVT, N->getMemOperand(),
4745 N->getAddressingMode(), N->isTruncatingStore(), N->isCompressingStore());
4746
4747 // If the high vp_strided_store has zero storage size, only the low
4748 // vp_strided_store is needed.
4749 if (HiIsEmpty)
4750 return Lo;
4751
4752 // Generate the high vp_strided_store.
4753 // To calculate the high base address, we need to sum to the low base
4754 // address stride number of bytes for each element already stored by low,
4755 // that is: Ptr = Ptr + (LoEVL * Stride)
4756 EVT PtrVT = N->getBasePtr().getValueType();
4758 DAG.getNode(ISD::MUL, DL, PtrVT, LoEVL,
4759 DAG.getSExtOrTrunc(N->getStride(), DL, PtrVT));
4760 SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, N->getBasePtr(), Increment);
4761
4762 Align Alignment = N->getBaseAlign();
4763 if (LoMemVT.isScalableVector())
4764 Alignment = commonAlignment(Alignment,
4765 LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4766
4767 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4768 MachinePointerInfo(N->getPointerInfo().getAddrSpace()),
4770 Alignment, MMOMetadata(N->getAAInfo(), N->getRanges()));
4771
4772 SDValue Hi = DAG.getStridedStoreVP(
4773 N->getChain(), DL, HiData, Ptr, N->getOffset(), N->getStride(), HiMask,
4774 HiEVL, HiMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(),
4775 N->isCompressingStore());
4776
4777 // Build a factor node to remember that this store is independent of the
4778 // other one.
4779 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4780}
4781
4782SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N,
4783 unsigned OpNo) {
4784 assert(N->isUnindexed() && "Indexed masked store of vector?");
4785 SDValue Ch = N->getChain();
4786 SDValue Ptr = N->getBasePtr();
4787 SDValue Offset = N->getOffset();
4788 assert(Offset.isUndef() && "Unexpected indexed masked store offset");
4789 SDValue Mask = N->getMask();
4790 SDValue Data = N->getValue();
4791 Align Alignment = N->getBaseAlign();
4792 SDLoc DL(N);
4793
4794 SDValue DataLo, DataHi;
4795 if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
4796 // Split Data operand
4797 GetSplitVector(Data, DataLo, DataHi);
4798 else
4799 std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);
4800
4801 // Split Mask operand
4802 SDValue MaskLo, MaskHi;
4803 if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
4804 SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
4805 } else {
4806 if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
4807 GetSplitVector(Mask, MaskLo, MaskHi);
4808 else
4809 std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
4810 }
4811
4812 EVT MemoryVT = N->getMemoryVT();
4813 EVT LoMemVT, HiMemVT;
4814 bool HiIsEmpty = false;
4815 std::tie(LoMemVT, HiMemVT) =
4816 DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);
4817
4818 SDValue Lo, Hi, Res;
4819 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4820 N->getPointerInfo(), MachineMemOperand::MOStore,
4822 MMOMetadata(N->getAAInfo(), N->getRanges(), N->getMemCacheHint()));
4823
4824 Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, Offset, MaskLo, LoMemVT, MMO,
4825 N->getAddressingMode(), N->isTruncatingStore(),
4826 N->isCompressingStore());
4827
4828 if (HiIsEmpty) {
4829 // The hi masked store has zero storage size.
4830 // Only the lo masked store is needed.
4831 Res = Lo;
4832 } else {
4833
4834 Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
4835 N->isCompressingStore());
4836
4837 MachinePointerInfo MPI;
4838 if (LoMemVT.isScalableVector()) {
4840 Alignment, LoMemVT.getSizeInBits().getKnownMinValue() / 8);
4841 MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
4842 } else
4843 MPI = N->getPointerInfo().getWithOffset(
4844 LoMemVT.getStoreSize().getFixedValue());
4845
4846 MMO = DAG.getMachineFunction().getMachineMemOperand(
4848 Alignment,
4849 MMOMetadata(N->getAAInfo(), N->getRanges(), N->getMemCacheHint()));
4850
4851 Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, Offset, MaskHi, HiMemVT, MMO,
4852 N->getAddressingMode(), N->isTruncatingStore(),
4853 N->isCompressingStore());
4854
4855 // Build a factor node to remember that this store is independent of the
4856 // other one.
4857 Res = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4858 }
4859
4860 return Res;
4861}
4862
4863SDValue DAGTypeLegalizer::SplitVecOp_Scatter(MemSDNode *N, unsigned OpNo) {
4864 SDValue Ch = N->getChain();
4865 SDValue Ptr = N->getBasePtr();
4866 EVT MemoryVT = N->getMemoryVT();
4867 Align Alignment = N->getBaseAlign();
4868 SDLoc DL(N);
4869 struct Operands {
4870 SDValue Mask;
4871 SDValue Index;
4872 SDValue Scale;
4873 SDValue Data;
4874 } Ops = [&]() -> Operands {
4875 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
4876 return {MSC->getMask(), MSC->getIndex(), MSC->getScale(),
4877 MSC->getValue()};
4878 }
4879 auto *VPSC = cast<VPScatterSDNode>(N);
4880 return {VPSC->getMask(), VPSC->getIndex(), VPSC->getScale(),
4881 VPSC->getValue()};
4882 }();
4883 // Split all operands
4884
4885 EVT LoMemVT, HiMemVT;
4886 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4887
4888 SDValue DataLo, DataHi;
4889 if (getTypeAction(Ops.Data.getValueType()) == TargetLowering::TypeSplitVector)
4890 // Split Data operand
4891 GetSplitVector(Ops.Data, DataLo, DataHi);
4892 else
4893 std::tie(DataLo, DataHi) = DAG.SplitVector(Ops.Data, DL);
4894
4895 // Split Mask operand
4896 SDValue MaskLo, MaskHi;
4897 if (OpNo == 1 && Ops.Mask.getOpcode() == ISD::SETCC) {
4898 SplitVecRes_SETCC(Ops.Mask.getNode(), MaskLo, MaskHi);
4899 } else {
4900 std::tie(MaskLo, MaskHi) = SplitMask(Ops.Mask, DL);
4901 }
4902
4903 SDValue IndexHi, IndexLo;
4904 if (getTypeAction(Ops.Index.getValueType()) ==
4906 GetSplitVector(Ops.Index, IndexLo, IndexHi);
4907 else
4908 std::tie(IndexLo, IndexHi) = DAG.SplitVector(Ops.Index, DL);
4909
4910 SDValue Lo;
4911 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4912 MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
4913 N->getPointerInfo(), MMOFlags, LocationSize::beforeOrAfterPointer(),
4914 Alignment, MMOMetadata(N->getAAInfo(), N->getRanges()));
4915
4916 if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) {
4917 SDValue OpsLo[] = {Ch, DataLo, MaskLo, Ptr, IndexLo, Ops.Scale};
4918 Lo =
4919 DAG.getMaskedScatter(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4920 MSC->getIndexType(), MSC->isTruncatingStore());
4921
4922 // The order of the Scatter operation after split is well defined. The "Hi"
4923 // part comes after the "Lo". So these two operations should be chained one
4924 // after another.
4925 SDValue OpsHi[] = {Lo, DataHi, MaskHi, Ptr, IndexHi, Ops.Scale};
4926 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi,
4927 MMO, MSC->getIndexType(),
4928 MSC->isTruncatingStore());
4929 }
4930 auto *VPSC = cast<VPScatterSDNode>(N);
4931 SDValue EVLLo, EVLHi;
4932 std::tie(EVLLo, EVLHi) =
4933 DAG.SplitEVL(VPSC->getVectorLength(), Ops.Data.getValueType(), DL);
4934
4935 SDValue OpsLo[] = {Ch, DataLo, Ptr, IndexLo, Ops.Scale, MaskLo, EVLLo};
4936 Lo = DAG.getScatterVP(DAG.getVTList(MVT::Other), LoMemVT, DL, OpsLo, MMO,
4937 VPSC->getIndexType());
4938
4939 // The order of the Scatter operation after split is well defined. The "Hi"
4940 // part comes after the "Lo". So these two operations should be chained one
4941 // after another.
4942 SDValue OpsHi[] = {Lo, DataHi, Ptr, IndexHi, Ops.Scale, MaskHi, EVLHi};
4943 return DAG.getScatterVP(DAG.getVTList(MVT::Other), HiMemVT, DL, OpsHi, MMO,
4944 VPSC->getIndexType());
4945}
4946
4947SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
4948 assert(N->isUnindexed() && "Indexed store of vector?");
4949 assert(OpNo == 1 && "Can only split the stored value");
4950 SDLoc DL(N);
4951
4952 bool isTruncating = N->isTruncatingStore();
4953 SDValue Ch = N->getChain();
4954 SDValue Ptr = N->getBasePtr();
4955 EVT MemoryVT = N->getMemoryVT();
4956 Align Alignment = N->getBaseAlign();
4957 MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
4958 MMOMetadata Metadata = N->getMMOMetadataForSubAccess();
4959 SDValue Lo, Hi;
4960 GetSplitVector(N->getOperand(1), Lo, Hi);
4961
4962 EVT LoMemVT, HiMemVT;
4963 std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);
4964
4965 // Scalarize if the split halves are not byte-sized.
4966 if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized())
4967 return TLI.scalarizeVectorStore(N, DAG);
4968
4969 if (isTruncating)
4970 Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), LoMemVT,
4971 Alignment, MMOFlags, Metadata);
4972 else
4973 Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), Alignment, MMOFlags,
4974 Metadata);
4975
4976 MachinePointerInfo MPI;
4977 IncrementPointer(N, LoMemVT, MPI, Ptr);
4978
4979 if (isTruncating)
4980 Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, MPI, HiMemVT, Alignment, MMOFlags,
4981 Metadata);
4982 else
4983 Hi = DAG.getStore(Ch, DL, Hi, Ptr, MPI, Alignment, MMOFlags, Metadata);
4984
4985 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
4986}
4987
4988SDValue DAGTypeLegalizer::SplitVecOp_ATOMIC_STORE(AtomicSDNode *N) {
4989 SDLoc DL(N);
4990 LLVMContext &Ctx = *DAG.getContext();
4991 SDValue StVal = N->getVal();
4992 EVT VT = StVal.getValueType();
4993 EVT MemIntVT = EVT::getIntegerVT(Ctx, N->getMemoryVT().getSizeInBits());
4994
4995 // The store needs a single value spanning the full memory width. If the
4996 // value can be held in a legal vector register, keep it there and extract
4997 // the low integer element of the memory width. This lets the store be issued
4998 // directly from a vector register (e.g. a single MOVQ/MOVD) instead of
4999 // bitcasting the split vector straight to a scalar integer, which would
5000 // reassemble the value element by element in GPRs.
5001 //
5002 // Reinterpret the value as a same-shaped integer vector first: an FP element
5003 // type may not have a legal vector form (e.g. bfloat on SSE2) while the
5004 // integer-of-element-size form does. Ask the target which legal vector type
5005 // it widens to.
5006 EVT IntVecVT = VT.changeVectorElementTypeToInteger();
5007 EVT IntEltVT = IntVecVT.getVectorElementType();
5008 EVT WideVT = TLI.getLegalTypeToTransformTo(Ctx, IntVecVT);
5009 if (DAG.getDataLayout().isLittleEndian() && TLI.isTypeLegal(MemIntVT) &&
5010 WideVT.isVector() && WideVT.getVectorElementType() == IntEltVT &&
5011 IntEltVT.getSizeInBits() <= MemIntVT.getSizeInBits() &&
5012 WideVT.getSizeInBits() % MemIntVT.getSizeInBits() == 0) {
5013 SDValue Wide = ModifyToType(DAG.getBitcast(IntVecVT, StVal), WideVT);
5014 unsigned NumMemElts = WideVT.getSizeInBits() / MemIntVT.getSizeInBits();
5015 EVT MemVecVT = EVT::getVectorVT(Ctx, MemIntVT, NumMemElts);
5016 SDValue Elt = DAG.getExtractVectorElt(DL, MemIntVT,
5017 DAG.getBitcast(MemVecVT, Wide), 0);
5018 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, MemIntVT, N->getChain(), Elt,
5019 N->getBasePtr(), N->getMemOperand());
5020 }
5021
5022 // Otherwise issue a single atomic store of an integer that spans the full
5023 // memory width. Bitcasting the (illegal) vector value to that integer lets
5024 // the type legalizer further legalize the BITCAST input as needed, while the
5025 // ATOMIC_STORE itself uses only the legal integer type.
5026 EVT IntVT = EVT::getIntegerVT(Ctx, VT.getSizeInBits());
5027 SDValue AsInt = DAG.getBitcast(IntVT, StVal);
5028 return DAG.getAtomic(ISD::ATOMIC_STORE, DL, MemIntVT, N->getChain(), AsInt,
5029 N->getBasePtr(), N->getMemOperand());
5030}
5031
5032SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) {
5033 SDLoc DL(N);
5034
5035 // The input operands all must have the same type, and we know the result
5036 // type is valid. Convert this to a buildvector which extracts all the
5037 // input elements.
5038 // TODO: If the input elements are power-two vectors, we could convert this to
5039 // a new CONCAT_VECTORS node with elements that are half-wide.
5041 EVT EltVT = N->getValueType(0).getVectorElementType();
5042 for (const SDValue &Op : N->op_values()) {
5043 for (unsigned i = 0, e = Op.getValueType().getVectorNumElements();
5044 i != e; ++i) {
5045 Elts.push_back(DAG.getExtractVectorElt(DL, EltVT, Op, i));
5046 }
5047 }
5048
5049 return DAG.getBuildVector(N->getValueType(0), DL, Elts);
5050}
5051
5052SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N) {
5053 // The result type is legal, but the input type is illegal. If splitting
5054 // ends up with the result type of each half still being legal, just
5055 // do that. If, however, that would result in an illegal result type,
5056 // we can try to get more clever with power-two vectors. Specifically,
5057 // split the input type, but also widen the result element size, then
5058 // concatenate the halves and truncate again. For example, consider a target
5059 // where v8i8 is legal and v8i32 is not (ARM, which doesn't have 256-bit
5060 // vectors). To perform a "%res = v8i8 trunc v8i32 %in" we do:
5061 // %inlo = v4i32 extract_subvector %in, 0
5062 // %inhi = v4i32 extract_subvector %in, 4
5063 // %lo16 = v4i16 trunc v4i32 %inlo
5064 // %hi16 = v4i16 trunc v4i32 %inhi
5065 // %in16 = v8i16 concat_vectors v4i16 %lo16, v4i16 %hi16
5066 // %res = v8i8 trunc v8i16 %in16
5067 //
5068 // Without this transform, the original truncate would end up being
5069 // scalarized, which is pretty much always a last resort.
5070 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
5071 SDValue InVec = N->getOperand(OpNo);
5072 EVT InVT = InVec->getValueType(0);
5073 EVT OutVT = N->getValueType(0);
5074 ElementCount NumElements = OutVT.getVectorElementCount();
5075 bool IsFloat = OutVT.isFloatingPoint();
5076
5077 unsigned InElementSize = InVT.getScalarSizeInBits();
5078 unsigned OutElementSize = OutVT.getScalarSizeInBits();
5079
5080 // Determine the split output VT. If its legal we can just split dirctly.
5081 EVT LoOutVT, HiOutVT;
5082 std::tie(LoOutVT, HiOutVT) = DAG.GetSplitDestVTs(OutVT);
5083 assert(LoOutVT == HiOutVT && "Unequal split?");
5084
5085 // If the input elements are only 1/2 the width of the result elements,
5086 // just use the normal splitting. Our trick only work if there's room
5087 // to split more than once.
5088 if (isTypeLegal(LoOutVT) || InElementSize <= OutElementSize * 2 ||
5089 (IsFloat && !isPowerOf2_32(InElementSize)))
5090 return SplitVecOp_UnaryOp(N);
5091 SDLoc DL(N);
5092
5093 // Don't touch if this will be scalarized.
5094 EVT FinalVT = InVT;
5095 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
5096 FinalVT = FinalVT.getHalfNumVectorElementsVT(*DAG.getContext());
5097
5098 if (getTypeAction(FinalVT) == TargetLowering::TypeScalarizeVector)
5099 return SplitVecOp_UnaryOp(N);
5100
5101 // Get the split input vector.
5102 SDValue InLoVec, InHiVec;
5103 GetSplitVector(InVec, InLoVec, InHiVec);
5104
5105 // Truncate them to 1/2 the element size.
5106 //
5107 // This assumes the number of elements is a power of two; any vector that
5108 // isn't should be widened, not split.
5109 EVT HalfElementVT = IsFloat ?
5110 EVT::getFloatingPointVT(InElementSize/2) :
5111 EVT::getIntegerVT(*DAG.getContext(), InElementSize/2);
5112 EVT HalfVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT,
5113 NumElements.divideCoefficientBy(2));
5114
5115 SDValue HalfLo;
5116 SDValue HalfHi;
5117 SDValue Chain;
5118 if (N->isStrictFPOpcode()) {
5119 HalfLo = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
5120 {N->getOperand(0), InLoVec});
5121 HalfHi = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
5122 {N->getOperand(0), InHiVec});
5123 // Legalize the chain result - switch anything that used the old chain to
5124 // use the new one.
5125 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, HalfLo.getValue(1),
5126 HalfHi.getValue(1));
5127 } else {
5128 HalfLo = DAG.getNode(N->getOpcode(), DL, HalfVT, InLoVec);
5129 HalfHi = DAG.getNode(N->getOpcode(), DL, HalfVT, InHiVec);
5130 }
5131
5132 // Concatenate them to get the full intermediate truncation result.
5133 EVT InterVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT, NumElements);
5134 SDValue InterVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InterVT, HalfLo,
5135 HalfHi);
5136 // Now finish up by truncating all the way down to the original result
5137 // type. This should normally be something that ends up being legal directly,
5138 // but in theory if a target has very wide vectors and an annoyingly
5139 // restricted set of legal types, this split can chain to build things up.
5140
5141 if (N->isStrictFPOpcode()) {
5142 SDValue Res = DAG.getNode(
5143 ISD::STRICT_FP_ROUND, DL, {OutVT, MVT::Other},
5144 {Chain, InterVec,
5145 DAG.getTargetConstant(0, DL, TLI.getPointerTy(DAG.getDataLayout()))});
5146 // Relink the chain
5147 ReplaceValueWith(SDValue(N, 1), SDValue(Res.getNode(), 1));
5148 return Res;
5149 }
5150
5151 return IsFloat
5152 ? DAG.getNode(ISD::FP_ROUND, DL, OutVT, InterVec,
5153 DAG.getTargetConstant(
5154 0, DL, TLI.getPointerTy(DAG.getDataLayout())))
5155 : DAG.getNode(ISD::TRUNCATE, DL, OutVT, InterVec);
5156}
5157
5158SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) {
5159 unsigned Opc = N->getOpcode();
5160 bool isStrict = Opc == ISD::STRICT_FSETCC || Opc == ISD::STRICT_FSETCCS;
5161 assert(N->getValueType(0).isVector() &&
5162 N->getOperand(isStrict ? 1 : 0).getValueType().isVector() &&
5163 "Operand types must be vectors");
5164 // The result has a legal vector type, but the input needs splitting.
5165 SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes;
5166 SDLoc DL(N);
5167 GetSplitVector(N->getOperand(isStrict ? 1 : 0), Lo0, Hi0);
5168 GetSplitVector(N->getOperand(isStrict ? 2 : 1), Lo1, Hi1);
5169
5170 EVT VT = N->getValueType(0);
5171 EVT PartResVT = getSetCCResultType(Lo0.getValueType());
5172
5173 if (Opc == ISD::SETCC) {
5174 LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2));
5175 HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2));
5176 } else {
5177 assert(isStrict && "unexpected node");
5178 LoRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
5179 N->getOperand(0), Lo0, Lo1, N->getOperand(3));
5180 HiRes = DAG.getNode(Opc, DL, DAG.getVTList(PartResVT, N->getValueType(1)),
5181 N->getOperand(0), Hi0, Hi1, N->getOperand(3));
5182 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
5183 LoRes.getValue(1), HiRes.getValue(1));
5184 ReplaceValueWith(SDValue(N, 1), NewChain);
5185 }
5186
5187 EVT ConcatVT = PartResVT.getDoubleNumVectorElementsVT(*DAG.getContext());
5188 SDValue Con = DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVT, LoRes, HiRes);
5189 if (VT == ConcatVT)
5190 return Con;
5191
5192 EVT OpVT = N->getOperand(0).getValueType();
5193 ISD::NodeType ExtendCode =
5194 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
5195 return DAG.getExtOrTrunc(Con, DL, VT, ExtendCode);
5196}
5197
5198
5199SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) {
5200 // The result has a legal vector type, but the input needs splitting.
5201 EVT ResVT = N->getValueType(0);
5202 SDValue Lo, Hi;
5203 SDLoc DL(N);
5204 GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
5205 EVT InVT = Lo.getValueType();
5206
5207 EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
5208 InVT.getVectorElementCount());
5209
5210 if (N->isStrictFPOpcode()) {
5211 Lo = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
5212 {N->getOperand(0), Lo, N->getOperand(2)});
5213 Hi = DAG.getNode(N->getOpcode(), DL, {OutVT, MVT::Other},
5214 {N->getOperand(0), Hi, N->getOperand(2)});
5215 // Legalize the chain result - switch anything that used the old chain to
5216 // use the new one.
5217 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
5218 Lo.getValue(1), Hi.getValue(1));
5219 ReplaceValueWith(SDValue(N, 1), NewChain);
5220 } else if (N->getOpcode() == ISD::CONVERT_TO_ARBITRARY_FP) {
5221 Lo = DAG.getNode(N->getOpcode(), DL, OutVT, Lo, N->getOperand(1),
5222 N->getOperand(2), N->getOperand(3));
5223 Hi = DAG.getNode(N->getOpcode(), DL, OutVT, Hi, N->getOperand(1),
5224 N->getOperand(2), N->getOperand(3));
5225 } else {
5226 Lo = DAG.getNode(N->getOpcode(), DL, OutVT, Lo, N->getOperand(1));
5227 Hi = DAG.getNode(N->getOpcode(), DL, OutVT, Hi, N->getOperand(1));
5228 }
5229
5230 return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi);
5231}
5232
5233// Split a vector type in an FP binary operation where the second operand has a
5234// different type from the first.
5235//
5236// The result (and the first input) has a legal vector type, but the second
5237// input needs splitting.
5238SDValue DAGTypeLegalizer::SplitVecOp_FPOpDifferentTypes(SDNode *N) {
5239 SDLoc DL(N);
5240
5241 EVT LHSLoVT, LHSHiVT;
5242 std::tie(LHSLoVT, LHSHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
5243
5244 if (!isTypeLegal(LHSLoVT) || !isTypeLegal(LHSHiVT))
5245 return DAG.UnrollVectorOp(N, N->getValueType(0).getVectorNumElements());
5246
5247 SDValue LHSLo, LHSHi;
5248 std::tie(LHSLo, LHSHi) =
5249 DAG.SplitVector(N->getOperand(0), DL, LHSLoVT, LHSHiVT);
5250
5251 SDValue RHSLo, RHSHi;
5252 std::tie(RHSLo, RHSHi) = DAG.SplitVector(N->getOperand(1), DL);
5253
5254 SDValue Lo = DAG.getNode(N->getOpcode(), DL, LHSLoVT, LHSLo, RHSLo);
5255 SDValue Hi = DAG.getNode(N->getOpcode(), DL, LHSHiVT, LHSHi, RHSHi);
5256
5257 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), Lo, Hi);
5258}
5259
5260SDValue DAGTypeLegalizer::SplitVecOp_CMP(SDNode *N) {
5261 LLVMContext &Ctxt = *DAG.getContext();
5262 SDLoc dl(N);
5263
5264 SDValue LHSLo, LHSHi, RHSLo, RHSHi;
5265 GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
5266 GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
5267
5268 EVT ResVT = N->getValueType(0);
5269 ElementCount SplitOpEC = LHSLo.getValueType().getVectorElementCount();
5270 EVT NewResVT =
5271 EVT::getVectorVT(Ctxt, ResVT.getVectorElementType(), SplitOpEC);
5272
5273 SDValue Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSLo, RHSLo);
5274 SDValue Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, LHSHi, RHSHi);
5275
5276 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
5277}
5278
5279SDValue DAGTypeLegalizer::SplitVecOp_FP_TO_XINT_SAT(SDNode *N) {
5280 EVT ResVT = N->getValueType(0);
5281 SDValue Lo, Hi;
5282 SDLoc dl(N);
5283 GetSplitVector(N->getOperand(0), Lo, Hi);
5284 EVT InVT = Lo.getValueType();
5285
5286 EVT NewResVT =
5287 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
5288 InVT.getVectorElementCount());
5289
5290 Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, Lo, N->getOperand(1));
5291 Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, Hi, N->getOperand(1));
5292
5293 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
5294}
5295
5296SDValue DAGTypeLegalizer::SplitVecOp_CttzElts(SDNode *N) {
5297 SDLoc DL(N);
5298 EVT ResVT = N->getValueType(0);
5299
5300 SDValue Lo, Hi;
5301 SDValue VecOp = N->getOperand(0);
5302 GetSplitVector(VecOp, Lo, Hi);
5303
5304 // if CTTZ_ELTS(Lo) != VL => CTTZ_ELTS(Lo).
5305 // else => VL + (CTTZ_ELTS(Hi) or CTTZ_ELTS_ZERO_POISON(Hi)).
5306 SDValue ResLo = DAG.getNode(ISD::CTTZ_ELTS, DL, ResVT, Lo);
5307 SDValue VL =
5308 DAG.getElementCount(DL, ResVT, Lo.getValueType().getVectorElementCount());
5309 SDValue ResLoNotVL =
5310 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VL, ISD::SETNE);
5311 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi);
5312 return DAG.getSelect(DL, ResVT, ResLoNotVL, ResLo,
5313 DAG.getNode(ISD::ADD, DL, ResVT, VL, ResHi));
5314}
5315
5316SDValue DAGTypeLegalizer::SplitVecOp_VP_CttzElements(SDNode *N) {
5317 SDLoc DL(N);
5318 EVT ResVT = N->getValueType(0);
5319
5320 SDValue Lo, Hi;
5321 SDValue VecOp = N->getOperand(0);
5322 GetSplitVector(VecOp, Lo, Hi);
5323
5324 auto [MaskLo, MaskHi] = SplitMask(N->getOperand(1));
5325 auto [EVLLo, EVLHi] =
5326 DAG.SplitEVL(N->getOperand(2), VecOp.getValueType(), DL);
5327 SDValue VLo = DAG.getZExtOrTrunc(EVLLo, DL, ResVT);
5328
5329 // if VP_CTTZ_ELTS(Lo) != EVLLo => VP_CTTZ_ELTS(Lo).
5330 // else => EVLLo + (VP_CTTZ_ELTS(Hi) or VP_CTTZ_ELTS_ZERO_POISON(Hi)).
5331 SDValue ResLo = DAG.getNode(ISD::VP_CTTZ_ELTS, DL, ResVT, Lo, MaskLo, EVLLo);
5332 SDValue ResLoNotEVL =
5333 DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VLo, ISD::SETNE);
5334 SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi, MaskHi, EVLHi);
5335 return DAG.getSelect(DL, ResVT, ResLoNotEVL, ResLo,
5336 DAG.getNode(ISD::ADD, DL, ResVT, VLo, ResHi));
5337}
5338
5339SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_HISTOGRAM(SDNode *N) {
5340 MaskedHistogramSDNode *HG = cast<MaskedHistogramSDNode>(N);
5341 SDLoc DL(HG);
5342 SDValue Inc = HG->getInc();
5343 SDValue Ptr = HG->getBasePtr();
5344 SDValue Scale = HG->getScale();
5345 SDValue IntID = HG->getIntID();
5346 EVT MemVT = HG->getMemoryVT();
5347 MachineMemOperand *MMO = HG->getMemOperand();
5348 ISD::MemIndexType IndexType = HG->getIndexType();
5349
5350 SDValue IndexLo, IndexHi, MaskLo, MaskHi;
5351 std::tie(IndexLo, IndexHi) = DAG.SplitVector(HG->getIndex(), DL);
5352 std::tie(MaskLo, MaskHi) = DAG.SplitVector(HG->getMask(), DL);
5353 SDValue OpsLo[] = {HG->getChain(), Inc, MaskLo, Ptr, IndexLo, Scale, IntID};
5354 SDValue Lo = DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL,
5355 OpsLo, MMO, IndexType);
5356 SDValue OpsHi[] = {Lo, Inc, MaskHi, Ptr, IndexHi, Scale, IntID};
5357 return DAG.getMaskedHistogram(DAG.getVTList(MVT::Other), MemVT, DL, OpsHi,
5358 MMO, IndexType);
5359}
5360
5361SDValue DAGTypeLegalizer::SplitVecOp_VECTOR_MATCH(SDNode *N, unsigned OpNo) {
5362 SDLoc DL(N);
5363
5364 if (OpNo == 0) {
5365 EVT LoResVT, HiResVT;
5366 std::tie(LoResVT, HiResVT) = DAG.GetSplitDestVTs(N->getValueType(0));
5367 SDValue SourceLo, SourceHi;
5368 std::tie(SourceLo, SourceHi) = DAG.SplitVectorOperand(N, 0);
5369 SDValue MaskLo, MaskHi;
5370 std::tie(MaskLo, MaskHi) = DAG.SplitVectorOperand(N, 2);
5371
5372 SDValue MatchLo = DAG.getNode(ISD::VECTOR_MATCH, DL, LoResVT, SourceLo,
5373 N->getOperand(1), MaskLo, N->getFlags());
5374 SDValue MatchHi = DAG.getNode(ISD::VECTOR_MATCH, DL, HiResVT, SourceHi,
5375 N->getOperand(1), MaskHi, N->getFlags());
5376 return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0), MatchLo,
5377 MatchHi);
5378 }
5379
5380 // Note: The Mask (OpNo == 2) should be widened with the result.
5381 assert(OpNo == 1 && "Unexpected VECTOR_MATCH operand");
5382
5383 SDValue NeedleLo, NeedleHi;
5384 GetSplitVector(N->getOperand(1), NeedleLo, NeedleHi);
5385
5386 SDValue MatchLo =
5387 DAG.getNode(ISD::VECTOR_MATCH, DL, N->getValueType(0), N->getOperand(0),
5388 NeedleLo, N->getOperand(2), N->getFlags());
5389 SDValue MatchHi =
5390 DAG.getNode(ISD::VECTOR_MATCH, DL, N->getValueType(0), N->getOperand(0),
5391 NeedleHi, N->getOperand(2), N->getFlags());
5392 return DAG.getNode(ISD::OR, DL, N->getValueType(0), MatchLo, MatchHi);
5393}
5394
5395SDValue DAGTypeLegalizer::SplitVecOp_PARTIAL_REDUCE_MLA(SDNode *N) {
5396 SDValue Acc = N->getOperand(0);
5397 assert(getTypeAction(Acc.getValueType()) != TargetLowering::TypeSplitVector &&
5398 "Accumulator should already be a legal type, and shouldn't need "
5399 "further splitting");
5400
5401 SDLoc DL(N);
5402 SDValue Input1Lo, Input1Hi, Input2Lo, Input2Hi;
5403 GetSplitVector(N->getOperand(1), Input1Lo, Input1Hi);
5404 GetSplitVector(N->getOperand(2), Input2Lo, Input2Hi);
5405 unsigned Opcode = N->getOpcode();
5406 EVT ResultVT = Acc.getValueType();
5407
5408 SDValue Lo = DAG.getNode(Opcode, DL, ResultVT, Acc, Input1Lo, Input2Lo);
5409 return DAG.getNode(Opcode, DL, ResultVT, Lo, Input1Hi, Input2Hi);
5410}
5411
5412//===----------------------------------------------------------------------===//
5413// Result Vector Widening
5414//===----------------------------------------------------------------------===//
5415
5416void DAGTypeLegalizer::ReplaceOtherWidenResults(SDNode *N, SDNode *WidenNode,
5417 unsigned WidenResNo) {
5418 unsigned NumResults = N->getNumValues();
5419 for (unsigned ResNo = 0; ResNo < NumResults; ResNo++) {
5420 if (ResNo == WidenResNo)
5421 continue;
5422 EVT ResVT = N->getValueType(ResNo);
5423 if (getTypeAction(ResVT) == TargetLowering::TypeWidenVector) {
5424 SetWidenedVector(SDValue(N, ResNo), SDValue(WidenNode, ResNo));
5425 } else {
5426 SDLoc DL(N);
5427 SDValue ResVal =
5428 DAG.getExtractSubvector(DL, ResVT, SDValue(WidenNode, ResNo), 0);
5429 ReplaceValueWith(SDValue(N, ResNo), ResVal);
5430 }
5431 }
5432}
5433
5434void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
5435 LLVM_DEBUG(dbgs() << "Widen node result " << ResNo << ": "; N->dump(&DAG));
5436
5437 // See if the target wants to custom widen this node.
5438 if (CustomWidenLowerNode(N, N->getValueType(ResNo)))
5439 return;
5440
5441 SDValue Res = SDValue();
5442
5443 auto unrollExpandedOp = [&]() {
5444 // We're going to widen this vector op to a legal type by padding with undef
5445 // elements. If the wide vector op is eventually going to be expanded to
5446 // scalar libcalls, then unroll into scalar ops now to avoid unnecessary
5447 // libcalls on the undef elements.
5448 EVT ResVT = N->getValueType(ResNo);
5449 EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
5450 if (WideVecVT.isScalableVector())
5451 return false;
5452 EVT VT0 = N->getValueType(0);
5453 if (!TLI.isOperationLegalOrCustomOrPromote(N->getOpcode(), WideVecVT) &&
5454 TLI.isOperationExpandOrLibCall(N->getOpcode(), VT0.getScalarType())) {
5455 SDValue Unrolled =
5456 DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
5457 Res = Unrolled.getValue(ResNo);
5458 if (N->getNumValues() > 1)
5459 ReplaceOtherWidenResults(N, Unrolled.getNode(), ResNo);
5460 return true;
5461 }
5462 return false;
5463 };
5464
5465 switch (N->getOpcode()) {
5466 default:
5467#ifndef NDEBUG
5468 dbgs() << "WidenVectorResult #" << ResNo << ": ";
5469 N->dump(&DAG);
5470 dbgs() << "\n";
5471#endif
5472 report_fatal_error("do not know how to widen the result of this operator!");
5473
5476 Res = WidenVecRes_LOOP_DEPENDENCE_MASK(N);
5477 break;
5478 case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
5479 case ISD::ADDRSPACECAST:
5480 Res = WidenVecRes_ADDRSPACECAST(N);
5481 break;
5482 case ISD::AssertZext: Res = WidenVecRes_AssertZext(N); break;
5483 case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break;
5484 case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break;
5485 case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break;
5487 Res = WidenVecRes_INSERT_SUBVECTOR(N);
5488 break;
5489 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break;
5490 case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
5491 case ISD::ATOMIC_LOAD:
5492 Res = WidenVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N));
5493 break;
5494 case ISD::LOAD: Res = WidenVecRes_LOAD(N); break;
5495 case ISD::STEP_VECTOR:
5496 case ISD::SPLAT_VECTOR:
5498 Res = WidenVecRes_ScalarOp(N);
5499 break;
5500 case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
5501 case ISD::VSELECT:
5502 case ISD::SELECT:
5503 case ISD::VP_MERGE:
5504 Res = WidenVecRes_Select(N);
5505 break;
5506 case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
5507 case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
5508 case ISD::POISON:
5509 case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
5511 Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
5512 break;
5513 case ISD::VP_LOAD:
5514 Res = WidenVecRes_VP_LOAD(cast<VPLoadSDNode>(N));
5515 break;
5516 case ISD::VP_LOAD_FF:
5517 Res = WidenVecRes_VP_LOAD_FF(cast<VPLoadFFSDNode>(N));
5518 break;
5519 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
5520 Res = WidenVecRes_VP_STRIDED_LOAD(cast<VPStridedLoadSDNode>(N));
5521 break;
5523 Res = WidenVecRes_VECTOR_COMPRESS(N);
5524 break;
5526 Res = WidenVecRes_VECTOR_SHUFFLE_VAR(N);
5527 break;
5528 case ISD::MLOAD:
5529 Res = WidenVecRes_MLOAD(cast<MaskedLoadSDNode>(N));
5530 break;
5531 case ISD::MGATHER:
5532 Res = WidenVecRes_MGATHER(cast<MaskedGatherSDNode>(N));
5533 break;
5534 case ISD::VP_GATHER:
5535 Res = WidenVecRes_VP_GATHER(cast<VPGatherSDNode>(N));
5536 break;
5538 Res = WidenVecRes_VECTOR_REVERSE(N);
5539 break;
5541 Res = WidenVecRes_GET_ACTIVE_LANE_MASK(N);
5542 break;
5544 WidenVecRes_VECTOR_INTERLEAVE(N);
5545 break;
5546 case ISD::VECTOR_MATCH:
5547 Res = WidenVecRes_VECTOR_MATCH(N);
5548 break;
5550 WidenVecRes_VECTOR_DEINTERLEAVE(N);
5551 break;
5552
5553 case ISD::ADD:
5554 case ISD::AND:
5555 case ISD::MUL:
5556 case ISD::MULHS:
5557 case ISD::MULHU:
5558 case ISD::ABDS:
5559 case ISD::ABDU:
5560 case ISD::OR:
5561 case ISD::SUB:
5562 case ISD::XOR:
5563 case ISD::SHL:
5564 case ISD::SRA:
5565 case ISD::SRL:
5566 case ISD::CLMUL:
5567 case ISD::CLMULR:
5568 case ISD::CLMULH:
5569 case ISD::PEXT:
5570 case ISD::PDEP:
5571 case ISD::FMINNUM:
5572 case ISD::FMINNUM_IEEE:
5573 case ISD::FMAXNUM:
5574 case ISD::FMAXNUM_IEEE:
5575 case ISD::FMINIMUM:
5576 case ISD::FMAXIMUM:
5577 case ISD::FMINIMUMNUM:
5578 case ISD::FMAXIMUMNUM:
5579 case ISD::SMIN:
5580 case ISD::SMAX:
5581 case ISD::UMIN:
5582 case ISD::UMAX:
5583 case ISD::UADDSAT:
5584 case ISD::SADDSAT:
5585 case ISD::USUBSAT:
5586 case ISD::SSUBSAT:
5587 case ISD::SSHLSAT:
5588 case ISD::USHLSAT:
5589 case ISD::ROTL:
5590 case ISD::ROTR:
5591 case ISD::AVGFLOORS:
5592 case ISD::AVGFLOORU:
5593 case ISD::AVGCEILS:
5594 case ISD::AVGCEILU:
5595 case ISD::AVGSUBFLOORS:
5596 case ISD::AVGSUBFLOORU:
5597 // Vector-predicated binary op widening. Note that -- unlike the
5598 // unpredicated versions -- we don't have to worry about trapping on
5599 // operations like UDIV, FADD, etc., as we pass on the original vector
5600 // length parameter. This means the widened elements containing garbage
5601 // aren't active.
5602 case ISD::VP_SDIV:
5603 case ISD::VP_UDIV:
5604 case ISD::VP_SREM:
5605 case ISD::VP_UREM:
5606 Res = WidenVecRes_Binary(N);
5607 break;
5608
5609 case ISD::MASKED_UDIV:
5610 case ISD::MASKED_SDIV:
5611 case ISD::MASKED_UREM:
5612 case ISD::MASKED_SREM:
5613 Res = WidenVecRes_MaskedBinary(N);
5614 break;
5615
5616 case ISD::SCMP:
5617 case ISD::UCMP:
5618 Res = WidenVecRes_CMP(N);
5619 break;
5620
5621 case ISD::FPOW:
5622 case ISD::FATAN2:
5623 case ISD::FREM:
5624 if (unrollExpandedOp())
5625 break;
5626 // If the target has custom/legal support for the scalar FP intrinsic ops
5627 // (they are probably not destined to become libcalls), then widen those
5628 // like any other binary ops.
5629 [[fallthrough]];
5630
5631 case ISD::FADD:
5632 case ISD::FMUL:
5633 case ISD::FSUB:
5634 case ISD::FDIV:
5635 case ISD::SDIV:
5636 case ISD::UDIV:
5637 case ISD::SREM:
5638 case ISD::UREM:
5639 Res = WidenVecRes_BinaryCanTrap(N);
5640 break;
5641
5642 case ISD::SMULFIX:
5643 case ISD::SMULFIXSAT:
5644 case ISD::UMULFIX:
5645 case ISD::UMULFIXSAT:
5646 // These are binary operations, but with an extra operand that shouldn't
5647 // be widened (the scale).
5648 Res = WidenVecRes_BinaryWithExtraScalarOp(N);
5649 break;
5650
5651#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
5652 case ISD::STRICT_##DAGN:
5653#include "llvm/IR/ConstrainedOps.def"
5654 Res = WidenVecRes_StrictFP(N);
5655 break;
5656
5657 case ISD::UADDO:
5658 case ISD::SADDO:
5659 case ISD::USUBO:
5660 case ISD::SSUBO:
5661 case ISD::UMULO:
5662 case ISD::SMULO:
5663 Res = WidenVecRes_OverflowOp(N, ResNo);
5664 break;
5665
5666 case ISD::FCOPYSIGN:
5667 Res = WidenVecRes_FCOPYSIGN(N);
5668 break;
5669
5670 case ISD::IS_FPCLASS:
5671 case ISD::FPTRUNC_ROUND:
5672 Res = WidenVecRes_UnarySameEltsWithScalarArg(N);
5673 break;
5674
5675 case ISD::FLDEXP:
5676 case ISD::FPOWI:
5677 if (!unrollExpandedOp())
5678 Res = WidenVecRes_ExpOp(N);
5679 break;
5680
5684 Res = WidenVecRes_EXTEND_VECTOR_INREG(N);
5685 break;
5686
5687 case ISD::ANY_EXTEND:
5688 case ISD::FP_EXTEND:
5689 case ISD::FP_ROUND:
5690 case ISD::FP_TO_SINT:
5691 case ISD::FP_TO_UINT:
5692 case ISD::SIGN_EXTEND:
5693 case ISD::SINT_TO_FP:
5694 case ISD::TRUNCATE:
5695 case ISD::UINT_TO_FP:
5696 case ISD::ZERO_EXTEND:
5699 Res = WidenVecRes_Convert(N);
5700 break;
5701
5704 Res = WidenVecRes_FP_TO_XINT_SAT(N);
5705 break;
5706
5707 case ISD::LRINT:
5708 case ISD::LLRINT:
5709 case ISD::LROUND:
5710 case ISD::LLROUND:
5711 Res = WidenVecRes_XROUND(N);
5712 break;
5713
5714 case ISD::FACOS:
5715 case ISD::FASIN:
5716 case ISD::FATAN:
5717 case ISD::FCEIL:
5718 case ISD::FCOS:
5719 case ISD::FCOSH:
5720 case ISD::FEXP:
5721 case ISD::FEXP2:
5722 case ISD::FEXP10:
5723 case ISD::FFLOOR:
5724 case ISD::FLOG:
5725 case ISD::FLOG10:
5726 case ISD::FLOG2:
5727 case ISD::FNEARBYINT:
5728 case ISD::FRINT:
5729 case ISD::FROUND:
5730 case ISD::FROUNDEVEN:
5731 case ISD::FSIN:
5732 case ISD::FSINH:
5733 case ISD::FSQRT:
5734 case ISD::FTAN:
5735 case ISD::FTANH:
5736 case ISD::FTRUNC:
5737 if (unrollExpandedOp())
5738 break;
5739 // If the target has custom/legal support for the scalar FP intrinsic ops
5740 // (they are probably not destined to become libcalls), then widen those
5741 // like any other unary ops.
5742 [[fallthrough]];
5743
5744 case ISD::ABS:
5746 case ISD::BITREVERSE:
5747 case ISD::BSWAP:
5748 case ISD::CTLZ:
5750 case ISD::CTPOP:
5751 case ISD::CTTZ:
5753 case ISD::FNEG:
5754 case ISD::FABS:
5755 case ISD::FREEZE:
5756 case ISD::ARITH_FENCE:
5757 case ISD::FCANONICALIZE:
5760 Res = WidenVecRes_Unary(N);
5761 break;
5762 case ISD::FMA:
5763 case ISD::FSHL:
5764 case ISD::FSHR:
5765 Res = WidenVecRes_Ternary(N);
5766 break;
5767 case ISD::FMODF:
5768 case ISD::FFREXP:
5769 case ISD::FSINCOS:
5770 case ISD::FSINCOSPI: {
5771 if (!unrollExpandedOp())
5772 Res = WidenVecRes_UnaryOpWithTwoResults(N, ResNo);
5773 break;
5774 }
5779 Res = WidenVecRes_PARTIAL_REDUCE_MLA(N);
5780 break;
5781 }
5782
5783 // If Res is null, the sub-method took care of registering the result.
5784 if (Res.getNode())
5785 SetWidenedVector(SDValue(N, ResNo), Res);
5786}
5787
5788SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
5789 // Ternary op widening.
5790 SDLoc dl(N);
5791 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5792 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5793 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5794 SDValue InOp3 = GetWidenedVector(N->getOperand(2));
5795 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
5796}
5797
5798SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
5799 // Binary op widening.
5800 SDLoc dl(N);
5801 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5802 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5803 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5804 if (N->getNumOperands() == 2)
5805 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
5806 N->getFlags());
5807
5808 assert(N->getNumOperands() == 4 && "Unexpected number of operands!");
5809 assert((N->getOpcode() == ISD::VP_UDIV || N->getOpcode() == ISD::VP_SDIV ||
5810 N->getOpcode() == ISD::VP_UREM || N->getOpcode() == ISD::VP_SREM) &&
5811 "Expected VP opcode");
5812
5813 SDValue Mask =
5814 GetWidenedMask(N->getOperand(2), WidenVT.getVectorElementCount());
5815 return DAG.getNode(N->getOpcode(), dl, WidenVT,
5816 {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
5817}
5818
5819SDValue DAGTypeLegalizer::WidenVecRes_MaskedBinary(SDNode *N) {
5820 SDLoc dl(N);
5821 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5822 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5823 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5824 SDValue Mask = N->getOperand(2);
5825 EVT WideMaskVT = WidenVT.changeVectorElementType(
5826 *DAG.getContext(), Mask.getValueType().getVectorElementType());
5827 Mask = ModifyToType(Mask, WideMaskVT, /*FillWithZeros=*/true);
5828 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Mask,
5829 N->getFlags());
5830}
5831
5832SDValue DAGTypeLegalizer::WidenVecRes_CMP(SDNode *N) {
5833 LLVMContext &Ctxt = *DAG.getContext();
5834 SDLoc dl(N);
5835
5836 SDValue LHS = N->getOperand(0);
5837 SDValue RHS = N->getOperand(1);
5838 EVT OpVT = LHS.getValueType();
5839 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector) {
5840 LHS = GetWidenedVector(LHS);
5841 RHS = GetWidenedVector(RHS);
5842 OpVT = LHS.getValueType();
5843 }
5844
5845 EVT WidenResVT = TLI.getTypeToTransformTo(Ctxt, N->getValueType(0));
5846 ElementCount WidenResEC = WidenResVT.getVectorElementCount();
5847 if (WidenResEC == OpVT.getVectorElementCount()) {
5848 return DAG.getNode(N->getOpcode(), dl, WidenResVT, LHS, RHS);
5849 }
5850
5851 return DAG.UnrollVectorOp(N, WidenResVT.getVectorNumElements());
5852}
5853
5854SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
5855 // Binary op widening, but with an extra operand that shouldn't be widened.
5856 SDLoc dl(N);
5857 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5858 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5859 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5860 SDValue InOp3 = N->getOperand(2);
5861 return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
5862 N->getFlags());
5863}
5864
5865// Given a vector of operations that have been broken up to widen, see
5866// if we can collect them together into the next widest legal VT. This
5867// implementation is trap-safe.
5869 SmallVectorImpl<SDValue> &ConcatOps,
5870 unsigned ConcatEnd, EVT VT, EVT MaxVT,
5871 EVT WidenVT) {
5872 // Check to see if we have a single operation with the widen type.
5873 if (ConcatEnd == 1) {
5874 VT = ConcatOps[0].getValueType();
5875 if (VT == WidenVT)
5876 return ConcatOps[0];
5877 }
5878
5879 SDLoc dl(ConcatOps[0]);
5880 EVT WidenEltVT = WidenVT.getVectorElementType();
5881
5882 // while (Some element of ConcatOps is not of type MaxVT) {
5883 // From the end of ConcatOps, collect elements of the same type and put
5884 // them into an op of the next larger supported type
5885 // }
5886 while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
5887 int Idx = ConcatEnd - 1;
5888 VT = ConcatOps[Idx--].getValueType();
5889 while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
5890 Idx--;
5891
5892 int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
5893 EVT NextVT;
5894 do {
5895 NextSize *= 2;
5896 NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
5897 } while (!TLI.isTypeLegal(NextVT));
5898
5899 if (!VT.isVector()) {
5900 // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
5901 SDValue VecOp = DAG.getPOISON(NextVT);
5902 unsigned NumToInsert = ConcatEnd - Idx - 1;
5903 for (unsigned i = 0, OpIdx = Idx + 1; i < NumToInsert; i++, OpIdx++)
5904 VecOp = DAG.getInsertVectorElt(dl, VecOp, ConcatOps[OpIdx], i);
5905 ConcatOps[Idx+1] = VecOp;
5906 ConcatEnd = Idx + 2;
5907 } else {
5908 // Vector type, create a CONCAT_VECTORS of type NextVT
5909 SDValue undefVec = DAG.getPOISON(VT);
5910 unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
5911 SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
5912 unsigned RealVals = ConcatEnd - Idx - 1;
5913 unsigned SubConcatEnd = 0;
5914 unsigned SubConcatIdx = Idx + 1;
5915 while (SubConcatEnd < RealVals)
5916 SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
5917 while (SubConcatEnd < OpsToConcat)
5918 SubConcatOps[SubConcatEnd++] = undefVec;
5919 ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
5920 NextVT, SubConcatOps);
5921 ConcatEnd = SubConcatIdx + 1;
5922 }
5923 }
5924
5925 // Check to see if we have a single operation with the widen type.
5926 if (ConcatEnd == 1) {
5927 VT = ConcatOps[0].getValueType();
5928 if (VT == WidenVT)
5929 return ConcatOps[0];
5930 }
5931
5932 // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
5934 MaxVT.getVectorElementCount());
5935 if (NumOps != ConcatEnd ) {
5936 SDValue UndefVal = DAG.getPOISON(MaxVT);
5937 for (unsigned j = ConcatEnd; j < NumOps; ++j)
5938 ConcatOps[j] = UndefVal;
5939 }
5940 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
5941 ArrayRef(ConcatOps.data(), NumOps));
5942}
5943
5944SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
5945 // Binary op widening for operations that can trap.
5946 unsigned Opcode = N->getOpcode();
5947 SDLoc dl(N);
5948 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
5949 EVT VT = WidenVT;
5950 ElementCount NumElts = VT.getVectorElementCount();
5951 const SDNodeFlags Flags = N->getFlags();
5952 while (!TLI.isTypeLegal(VT) && NumElts.getKnownMinValue() != 1) {
5953 NumElts = NumElts.divideCoefficientBy(2);
5954 VT = VT.changeVectorElementCount(*DAG.getContext(), NumElts);
5955 }
5956
5957 bool FoundLegalVectorType = TLI.isTypeLegal(VT) && !NumElts.isScalar();
5958 if (FoundLegalVectorType && DAG.isSafeToSpeculativelyExecute(Opcode)) {
5959 // Operation can be speculatively executed so just widen as normal.
5960 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5961 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5962 return DAG.getNode(Opcode, dl, WidenVT, InOp1, InOp2, Flags);
5963 }
5964
5965 // Generate a vp.op if it is custom/legal for the target. This avoids need
5966 // to split and tile the subvectors (below), because the inactive lanes can
5967 // simply be disabled. To avoid possible recursion, only do this if the
5968 // widened mask type is legal.
5969 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opcode);
5970 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WidenVT)) {
5971 if (EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
5972 WidenVT.getVectorElementCount());
5973 TLI.isTypeLegal(WideMaskVT)) {
5974 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5975 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5976 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
5977 SDValue EVL =
5978 DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
5979 N->getValueType(0).getVectorElementCount());
5980 return DAG.getNode(*VPOpcode, dl, WidenVT, InOp1, InOp2, Mask, EVL,
5981 Flags);
5982 }
5983 }
5984
5985 // No legal vector version so unroll the vector operation and then widen.
5986 if (NumElts.isScalar())
5987 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
5988
5989 if (!TLI.isTypeLegal(VT))
5990 report_fatal_error("Cannot widen scalable vector trapping binop!");
5991
5992 // Since the operation can trap, apply operation on the original vector.
5993 EVT MaxVT = VT;
5994 EVT EltVT = VT.getVectorElementType();
5995 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
5996 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
5997 ElementCount CurNumElts = N->getValueType(0).getVectorElementCount();
5998
5999 SmallVector<SDValue, 16> ConcatOps(CurNumElts.getKnownMinValue());
6000 unsigned ConcatEnd = 0; // Current ConcatOps index.
6001 int Idx = 0; // Current Idx into input vectors.
6002
6003 // NumElts := greatest legal vector size (at most WidenVT)
6004 // while (orig. vector has unhandled elements) {
6005 // take munches of size NumElts from the beginning and add to ConcatOps
6006 // NumElts := next smaller supported vector size or 1
6007 // }
6008 for (;;) {
6009 while (ElementCount::isKnownGE(CurNumElts, NumElts)) {
6010 SDValue EOp1 = DAG.getExtractSubvector(dl, VT, InOp1, Idx);
6011 SDValue EOp2 = DAG.getExtractSubvector(dl, VT, InOp2, Idx);
6012 ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
6013 // Subvector indices are implicitly scaled by vscale.
6014 Idx += NumElts.getKnownMinValue();
6015 CurNumElts -= NumElts;
6016 }
6017
6018 if (CurNumElts.isZero())
6019 break;
6020
6021 // Find the next smaller legal vector type.
6022 do {
6023 NumElts = NumElts.divideCoefficientBy(2);
6024 VT = VT.changeVectorElementCount(*DAG.getContext(), NumElts);
6025 } while (!TLI.isTypeLegal(VT) && NumElts.getKnownMinValue() != 1);
6026
6027 if (NumElts.isScalar()) {
6028 // Scalarize the non-type-legal remainder.
6029 for (unsigned i = 0; i != CurNumElts.getFixedValue(); ++i, ++Idx) {
6030 SDValue EOp1 = DAG.getExtractVectorElt(dl, EltVT, InOp1, Idx);
6031 SDValue EOp2 = DAG.getExtractVectorElt(dl, EltVT, InOp2, Idx);
6032 ConcatOps[ConcatEnd++] =
6033 DAG.getNode(Opcode, dl, EltVT, EOp1, EOp2, Flags);
6034 }
6035
6036 break;
6037 }
6038
6039 if (!TLI.isTypeLegal(VT))
6040 report_fatal_error("scalarization of scalable vectors is not supported");
6041 }
6042
6043 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
6044}
6045
6046SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
6047 switch (N->getOpcode()) {
6048 case ISD::STRICT_FSETCC:
6050 return WidenVecRes_STRICT_FSETCC(N);
6057 return WidenVecRes_Convert_StrictFP(N);
6058 default:
6059 break;
6060 }
6061
6062 // StrictFP op widening for operations that can trap.
6063 unsigned NumOpers = N->getNumOperands();
6064 unsigned Opcode = N->getOpcode();
6065 SDLoc dl(N);
6066 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6067 EVT WidenEltVT = WidenVT.getVectorElementType();
6068 EVT VT = WidenVT;
6069 unsigned NumElts = VT.getVectorNumElements();
6070 while (!TLI.isTypeLegal(VT) && NumElts != 1) {
6071 NumElts = NumElts / 2;
6072 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
6073 }
6074
6075 // No legal vector version so unroll the vector operation and then widen.
6076 if (NumElts == 1)
6077 return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());
6078
6079 // Since the operation can trap, apply operation on the original vector.
6080 EVT MaxVT = VT;
6082 unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
6083
6084 SmallVector<SDValue, 16> ConcatOps(CurNumElts);
6086 unsigned ConcatEnd = 0; // Current ConcatOps index.
6087 int Idx = 0; // Current Idx into input vectors.
6088
6089 // The Chain is the first operand.
6090 InOps.push_back(N->getOperand(0));
6091
6092 // Now process the remaining operands.
6093 for (unsigned i = 1; i < NumOpers; ++i) {
6094 SDValue Oper = N->getOperand(i);
6095
6096 EVT OpVT = Oper.getValueType();
6097 if (OpVT.isVector()) {
6098 if (getTypeAction(OpVT) == TargetLowering::TypeWidenVector)
6099 Oper = GetWidenedVector(Oper);
6100 else {
6101 EVT WideOpVT =
6102 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
6103 WidenVT.getVectorElementCount());
6104 Oper = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WideOpVT,
6105 DAG.getPOISON(WideOpVT), Oper,
6106 DAG.getVectorIdxConstant(0, dl));
6107 }
6108 }
6109
6110 InOps.push_back(Oper);
6111 }
6112
6113 // NumElts := greatest legal vector size (at most WidenVT)
6114 // while (orig. vector has unhandled elements) {
6115 // take munches of size NumElts from the beginning and add to ConcatOps
6116 // NumElts := next smaller supported vector size or 1
6117 // }
6118 while (CurNumElts != 0) {
6119 while (CurNumElts >= NumElts) {
6121
6122 for (unsigned i = 0; i < NumOpers; ++i) {
6123 SDValue Op = InOps[i];
6124
6125 EVT OpVT = Op.getValueType();
6126 if (OpVT.isVector()) {
6127 EVT OpExtractVT =
6128 EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
6130 Op = DAG.getExtractSubvector(dl, OpExtractVT, Op, Idx);
6131 }
6132
6133 EOps.push_back(Op);
6134 }
6135
6136 EVT OperVT[] = {VT, MVT::Other};
6137 SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
6138 ConcatOps[ConcatEnd++] = Oper;
6139 Chains.push_back(Oper.getValue(1));
6140 Idx += NumElts;
6141 CurNumElts -= NumElts;
6142 }
6143 do {
6144 NumElts = NumElts / 2;
6145 VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
6146 } while (!TLI.isTypeLegal(VT) && NumElts != 1);
6147
6148 if (NumElts == 1) {
6149 for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
6151
6152 for (unsigned i = 0; i < NumOpers; ++i) {
6153 SDValue Op = InOps[i];
6154
6155 EVT OpVT = Op.getValueType();
6156 if (OpVT.isVector())
6157 Op = DAG.getExtractVectorElt(dl, OpVT.getVectorElementType(), Op,
6158 Idx);
6159
6160 EOps.push_back(Op);
6161 }
6162
6163 EVT WidenVT[] = {WidenEltVT, MVT::Other};
6164 SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
6165 ConcatOps[ConcatEnd++] = Oper;
6166 Chains.push_back(Oper.getValue(1));
6167 }
6168 CurNumElts = 0;
6169 }
6170 }
6171
6172 // Build a factor node to remember all the Ops that have been created.
6173 SDValue NewChain;
6174 if (Chains.size() == 1)
6175 NewChain = Chains[0];
6176 else
6177 NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
6178 ReplaceValueWith(SDValue(N, 1), NewChain);
6179
6180 return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
6181}
6182
6183SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
6184 SDLoc DL(N);
6185 EVT ResVT = N->getValueType(0);
6186 EVT OvVT = N->getValueType(1);
6187 EVT WideResVT, WideOvVT;
6188 SDValue WideLHS, WideRHS;
6189
6190 // TODO: This might result in a widen/split loop.
6191 if (ResNo == 0) {
6192 WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
6193 WideOvVT = EVT::getVectorVT(
6194 *DAG.getContext(), OvVT.getVectorElementType(),
6195 WideResVT.getVectorNumElements());
6196
6197 WideLHS = GetWidenedVector(N->getOperand(0));
6198 WideRHS = GetWidenedVector(N->getOperand(1));
6199 } else {
6200 WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
6201 WideResVT = EVT::getVectorVT(
6202 *DAG.getContext(), ResVT.getVectorElementType(),
6203 WideOvVT.getVectorNumElements());
6204
6205 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
6206 SDValue Poison = DAG.getPOISON(WideResVT);
6207
6208 WideLHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
6209 N->getOperand(0), Zero);
6210 WideRHS = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideResVT, Poison,
6211 N->getOperand(1), Zero);
6212 }
6213
6214 SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
6215 SDNode *WideNode = DAG.getNode(
6216 N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();
6217
6218 // Replace the other vector result not being explicitly widened here.
6219 unsigned OtherNo = 1 - ResNo;
6220 EVT OtherVT = N->getValueType(OtherNo);
6221 if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
6222 SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
6223 } else {
6224 SDValue Zero = DAG.getVectorIdxConstant(0, DL);
6225 SDValue OtherVal = DAG.getNode(
6226 ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
6227 ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
6228 }
6229
6230 return SDValue(WideNode, ResNo);
6231}
6232
6233SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
6234 LLVMContext &Ctx = *DAG.getContext();
6235 SDValue InOp = N->getOperand(0);
6236 SDLoc DL(N);
6237
6238 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
6239 ElementCount WidenEC = WidenVT.getVectorElementCount();
6240
6241 EVT InVT = InOp.getValueType();
6242
6243 unsigned Opcode = N->getOpcode();
6244 const SDNodeFlags Flags = N->getFlags();
6245
6246 // Handle the case of ZERO_EXTEND where the promoted InVT element size does
6247 // not equal that of WidenVT.
6248 if (N->getOpcode() == ISD::ZERO_EXTEND &&
6249 getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
6250 TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
6251 WidenVT.getScalarSizeInBits()) {
6252 InOp = ZExtPromotedInteger(InOp);
6253 InVT = InOp.getValueType();
6254 if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
6255 Opcode = ISD::TRUNCATE;
6256 }
6257
6258 EVT InEltVT = InVT.getVectorElementType();
6259 EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
6260 ElementCount InVTEC = InVT.getVectorElementCount();
6261
6262 // Helper to build node with all scalar trailing operands.
6263 auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
6264 if (N->getNumOperands() == 1)
6265 return DAG.getNode(Opcode, DL, VT, Op, Flags);
6266 if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
6267 return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), N->getOperand(2),
6268 N->getOperand(3), Flags);
6269 return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), Flags);
6270 };
6271
6272 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6273 InOp = GetWidenedVector(N->getOperand(0));
6274 InVT = InOp.getValueType();
6275 InVTEC = InVT.getVectorElementCount();
6276 if (InVTEC == WidenEC)
6277 return MakeConvertNode(WidenVT, InOp);
6278 if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
6279 // If both input and result vector types are of same width, extend
6280 // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
6281 // accepts fewer elements in the result than in the input.
6282 if (Opcode == ISD::ANY_EXTEND)
6283 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6284 if (Opcode == ISD::SIGN_EXTEND)
6285 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6286 if (Opcode == ISD::ZERO_EXTEND)
6287 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
6288 }
6289
6290 // For TRUNCATE, try to widen using the legal EC of the input type instead
6291 // if the legalisation action for that intermediate type is not widening.
6292 // E.g. for trunc nxv1i64 -> nxv1i8 where
6293 // - nxv1i64 input gets widened to nxv2i64
6294 // - nxv1i8 output gets widened to nxv16i8
6295 // Then one can try widening the result to nxv2i8 (instead of going all the
6296 // way to nxv16i8) if this later allows type promotion.
6297 EVT MidResVT =
6298 EVT::getVectorVT(Ctx, WidenVT.getVectorElementType(), InVTEC);
6299 if (N->getOpcode() == ISD::TRUNCATE &&
6300 getTypeAction(MidResVT) == TargetLowering::TypePromoteInteger) {
6301 SDValue MidRes = DAG.getNode(ISD::TRUNCATE, DL, MidResVT, InOp, Flags);
6302 return DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), MidRes, 0);
6303 }
6304 }
6305
6306 if (TLI.isTypeLegal(InWidenVT)) {
6307 // Because the result and the input are different vector types, widening
6308 // the result could create a legal type but widening the input might make
6309 // it an illegal type that might lead to repeatedly splitting the input
6310 // and then widening it. To avoid this, we widen the input only if
6311 // it results in a legal type.
6312 if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
6313 // Widen the input and call convert on the widened input vector.
6314 unsigned NumConcat =
6315 WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
6316 SmallVector<SDValue, 16> Ops(NumConcat, DAG.getPOISON(InVT));
6317 Ops[0] = InOp;
6318 SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
6319 return MakeConvertNode(WidenVT, InVec);
6320 }
6321
6322 if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
6323 SDValue InVal = DAG.getExtractSubvector(DL, InWidenVT, InOp, 0);
6324 // Extract the input and convert the shorten input vector.
6325 return MakeConvertNode(WidenVT, InVal);
6326 }
6327 }
6328
6329 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6330 EVT EltVT = WidenVT.getVectorElementType();
6331 SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getPOISON(EltVT));
6332 // Use the original element count so we don't do more scalar opts than
6333 // necessary.
6334 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6335 for (unsigned i=0; i < MinElts; ++i) {
6336 SDValue Val = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6337 Ops[i] = MakeConvertNode(EltVT, Val);
6338 }
6339
6340 return DAG.getBuildVector(WidenVT, DL, Ops);
6341}
6342
6343SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
6344 SDLoc dl(N);
6345 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6346 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
6347
6348 SDValue Src = N->getOperand(0);
6349 EVT SrcVT = Src.getValueType();
6350
6351 // Also widen the input.
6352 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
6353 Src = GetWidenedVector(Src);
6354 SrcVT = Src.getValueType();
6355 }
6356
6357 // Input and output not widened to the same size, give up.
6358 if (WidenNumElts != SrcVT.getVectorElementCount())
6359 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
6360
6361 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
6362}
6363
6364SDValue DAGTypeLegalizer::WidenVecRes_XROUND(SDNode *N) {
6365 SDLoc dl(N);
6366 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6367 ElementCount WidenNumElts = WidenVT.getVectorElementCount();
6368
6369 SDValue Src = N->getOperand(0);
6370 EVT SrcVT = Src.getValueType();
6371
6372 // Also widen the input.
6373 if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
6374 Src = GetWidenedVector(Src);
6375 SrcVT = Src.getValueType();
6376 }
6377
6378 // Input and output not widened to the same size, give up.
6379 if (WidenNumElts != SrcVT.getVectorElementCount())
6380 return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());
6381
6382 return DAG.getNode(N->getOpcode(), dl, WidenVT, Src);
6383}
6384
6385SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
6386 SDValue InOp = N->getOperand(1);
6387 SDLoc DL(N);
6388 SmallVector<SDValue, 4> NewOps(N->ops());
6389
6390 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6391 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6392
6393 EVT InVT = InOp.getValueType();
6394 EVT InEltVT = InVT.getVectorElementType();
6395
6396 unsigned Opcode = N->getOpcode();
6397
6398 // FIXME: Optimizations need to be implemented here.
6399
6400 // Otherwise unroll into some nasty scalar code and rebuild the vector.
6401 EVT EltVT = WidenVT.getVectorElementType();
6402 std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
6403 SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getPOISON(EltVT));
6404 SmallVector<SDValue, 32> OpChains;
6405 // Use the original element count so we don't do more scalar opts than
6406 // necessary.
6407 unsigned MinElts = N->getValueType(0).getVectorNumElements();
6408 for (unsigned i=0; i < MinElts; ++i) {
6409 NewOps[1] = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
6410 Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
6411 OpChains.push_back(Ops[i].getValue(1));
6412 }
6413 SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
6414 ReplaceValueWith(SDValue(N, 1), NewChain);
6415
6416 return DAG.getBuildVector(WidenVT, DL, Ops);
6417}
6418
6419SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
6420 unsigned Opcode = N->getOpcode();
6421 SDValue InOp = N->getOperand(0);
6422 SDLoc DL(N);
6423
6424 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6425 EVT WidenSVT = WidenVT.getVectorElementType();
6426 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6427
6428 EVT InVT = InOp.getValueType();
6429 EVT InSVT = InVT.getVectorElementType();
6430 unsigned InVTNumElts = InVT.getVectorNumElements();
6431
6432 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
6433 InOp = GetWidenedVector(InOp);
6434 InVT = InOp.getValueType();
6435 if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
6436 switch (Opcode) {
6440 return DAG.getNode(Opcode, DL, WidenVT, InOp);
6441 }
6442 }
6443 }
6444
6445 // Unroll, extend the scalars and rebuild the vector.
6447 for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
6448 SDValue Val = DAG.getExtractVectorElt(DL, InSVT, InOp, i);
6449 switch (Opcode) {
6451 Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
6452 break;
6454 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
6455 break;
6457 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
6458 break;
6459 default:
6460 llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
6461 }
6462 Ops.push_back(Val);
6463 }
6464
6465 while (Ops.size() != WidenNumElts)
6466 Ops.push_back(DAG.getPOISON(WidenSVT));
6467
6468 return DAG.getBuildVector(WidenVT, DL, Ops);
6469}
6470
6471SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
6472 // If this is an FCOPYSIGN with same input types, we can treat it as a
6473 // normal (can trap) binary op.
6474 if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
6475 return WidenVecRes_BinaryCanTrap(N);
6476
6477 // If the types are different, fall back to unrolling.
6478 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6479 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6480}
6481
6482/// Result and first source operand are different scalar types, but must have
6483/// the same number of elements. There is an additional control argument which
6484/// should be passed through unchanged.
6485SDValue DAGTypeLegalizer::WidenVecRes_UnarySameEltsWithScalarArg(SDNode *N) {
6486 SDValue FpValue = N->getOperand(0);
6487 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6488 if (getTypeAction(FpValue.getValueType()) != TargetLowering::TypeWidenVector)
6489 return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
6490 SDValue Arg = GetWidenedVector(FpValue);
6491 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, {Arg, N->getOperand(1)},
6492 N->getFlags());
6493}
6494
6495SDValue DAGTypeLegalizer::WidenVecRes_ExpOp(SDNode *N) {
6496 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6497 SDValue InOp = GetWidenedVector(N->getOperand(0));
6498 SDValue RHS = N->getOperand(1);
6499 EVT ExpVT = RHS.getValueType();
6500 SDValue ExpOp = RHS;
6501 if (ExpVT.isVector()) {
6502 EVT WideExpVT = WidenVT.changeVectorElementType(
6503 *DAG.getContext(), ExpVT.getVectorElementType());
6504 ExpOp = ModifyToType(RHS, WideExpVT);
6505 }
6506
6507 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ExpOp);
6508}
6509
6510SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
6511 // Unary op widening.
6512 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6513 SDValue InOp = GetWidenedVector(N->getOperand(0));
6514 if (N->getNumOperands() == 1)
6515 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getFlags());
6516 assert(N->getOpcode() == ISD::AssertNoFPClass && "unexpected opcode");
6517 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, N->getOperand(1),
6518 N->getFlags());
6519}
6520
6521SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
6522 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6523 EVT ExtVT = EVT::getVectorVT(
6524 *DAG.getContext(),
6525 cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType(),
6526 WidenVT.getVectorElementCount());
6527 SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
6528 return DAG.getNode(N->getOpcode(), SDLoc(N),
6529 WidenVT, WidenLHS, DAG.getValueType(ExtVT));
6530}
6531
6532SDValue DAGTypeLegalizer::WidenVecRes_UnaryOpWithTwoResults(SDNode *N,
6533 unsigned ResNo) {
6534 EVT VT0 = N->getValueType(0);
6535 EVT VT1 = N->getValueType(1);
6536
6537 assert(VT0.isVector() && VT1.isVector() &&
6539 "expected both results to be vectors of matching element count");
6540
6541 LLVMContext &Ctx = *DAG.getContext();
6542 SDValue InOp = GetWidenedVector(N->getOperand(0));
6543
6544 EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(ResNo));
6545 ElementCount WidenEC = WidenVT.getVectorElementCount();
6546
6547 EVT WidenVT0 = EVT::getVectorVT(Ctx, VT0.getVectorElementType(), WidenEC);
6548 EVT WidenVT1 = EVT::getVectorVT(Ctx, VT1.getVectorElementType(), WidenEC);
6549
6550 SDNode *WidenNode =
6551 DAG.getNode(N->getOpcode(), SDLoc(N), {WidenVT0, WidenVT1}, InOp)
6552 .getNode();
6553
6554 ReplaceOtherWidenResults(N, WidenNode, ResNo);
6555 return SDValue(WidenNode, ResNo);
6556}
6557
6558SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
6559 SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
6560 return GetWidenedVector(WidenVec);
6561}
6562
6563SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) {
6564 SDLoc DL(N);
6565 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6566 ElementCount WidenEC = WidenVT.getVectorElementCount();
6567 auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N);
6568
6569 // The source has the same number of elements as the result, so widen it to
6570 // match WidenVT. It only lives in the widened-vector map if it is itself
6571 // widened; otherwise pad it up to the widened element count
6572 // when it is illegal.
6573 SDValue InOp = N->getOperand(0);
6574 EVT InVT = InOp.getValueType();
6575 TargetLowering::LegalizeTypeAction InAction = getTypeAction(InVT);
6576 if (InAction == TargetLowering::TypeWidenVector) {
6577 InOp = GetWidenedVector(InOp);
6578 } else if (InAction != TargetLowering::TypeLegal) {
6579 EVT InWidenVT = EVT::getVectorVT(*DAG.getContext(),
6580 InVT.getVectorElementType(), WidenEC);
6581 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(InWidenVT), InOp, 0);
6582 }
6583
6584 return DAG.getAddrSpaceCast(
6585 DL, WidenVT, InOp, AddrSpaceCastN->getSrcAddressSpace(),
6586 AddrSpaceCastN->getDestAddressSpace(), AddrSpaceCastN->getFlags());
6587}
6588
6589SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
6590 SDValue InOp = N->getOperand(0);
6591 EVT InVT = InOp.getValueType();
6592 EVT VT = N->getValueType(0);
6593 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6594 SDLoc dl(N);
6595
6596 switch (getTypeAction(InVT)) {
6598 break;
6600 report_fatal_error("scalarization of scalable vectors is not supported");
6602 // If the incoming type is a vector that is being promoted, then
6603 // we know that the elements are arranged differently and that we
6604 // must perform the conversion using a stack slot.
6605 if (InVT.isVector())
6606 break;
6607
6608 // If the InOp is promoted to the same size, convert it. Otherwise,
6609 // fall out of the switch and widen the promoted input.
6610 SDValue NInOp = GetPromotedInteger(InOp);
6611 EVT NInVT = NInOp.getValueType();
6612 if (WidenVT.bitsEq(NInVT)) {
6613 // For big endian targets we need to shift the input integer or the
6614 // interesting bits will end up at the wrong place.
6615 if (DAG.getDataLayout().isBigEndian()) {
6616 unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
6617 NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
6618 DAG.getShiftAmountConstant(ShiftAmt, NInVT, dl));
6619 }
6620 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
6621 }
6622 InOp = NInOp;
6623 InVT = NInVT;
6624 break;
6625 }
6632 break;
6634 // If the InOp is widened to the same size, convert it. Otherwise, fall
6635 // out of the switch and widen the widened input.
6636 InOp = GetWidenedVector(InOp);
6637 InVT = InOp.getValueType();
6638 if (WidenVT.bitsEq(InVT))
6639 // The input widens to the same size. Convert to the widen value.
6640 return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
6641 break;
6642 }
6643
6644 unsigned WidenSize = WidenVT.getSizeInBits();
6645 unsigned InSize = InVT.getSizeInBits();
6646 unsigned InScalarSize = InVT.getScalarSizeInBits();
6647 // x86mmx is not an acceptable vector element type, so don't try.
6648 if (WidenSize % InScalarSize == 0 && InVT != MVT::x86mmx) {
6649 // Determine new input vector type. The new input vector type will use
6650 // the same element type (if its a vector) or use the input type as a
6651 // vector. It is the same size as the type to widen to.
6652 EVT NewInVT;
6653 unsigned NewNumParts = WidenSize / InSize;
6654 if (InVT.isVector()) {
6655 EVT InEltVT = InVT.getVectorElementType();
6656 NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
6657 WidenSize / InEltVT.getSizeInBits());
6658 } else {
6659 // For big endian systems, using the promoted input scalar type
6660 // to produce the scalar_to_vector would put the desired bits into
6661 // the least significant byte(s) of the wider element zero. This
6662 // will mean that the users of the result vector are using incorrect
6663 // bits. Use the original input type instead. Although either input
6664 // type can be used on little endian systems, for consistency we
6665 // use the original type there as well.
6666 EVT OrigInVT = N->getOperand(0).getValueType();
6667 NewNumParts = WidenSize / OrigInVT.getSizeInBits();
6668 NewInVT = EVT::getVectorVT(*DAG.getContext(), OrigInVT, NewNumParts);
6669 }
6670
6671 if (TLI.isTypeLegal(NewInVT)) {
6672 SDValue NewVec;
6673 if (InVT.isVector()) {
6674 // Because the result and the input are different vector types, widening
6675 // the result could create a legal type but widening the input might
6676 // make it an illegal type that might lead to repeatedly splitting the
6677 // input and then widening it. To avoid this, we widen the input only if
6678 // it results in a legal type.
6679 if (WidenSize % InSize == 0) {
6680 SmallVector<SDValue, 16> Ops(NewNumParts, DAG.getPOISON(InVT));
6681 Ops[0] = InOp;
6682
6683 NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
6684 } else {
6686 DAG.ExtractVectorElements(InOp, Ops);
6687 Ops.append(WidenSize / InScalarSize - Ops.size(),
6688 DAG.getPOISON(InVT.getVectorElementType()));
6689
6690 NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, NewInVT, Ops);
6691 }
6692 } else {
6693 NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
6694 }
6695 return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
6696 }
6697 }
6698
6699 return CreateStackStoreLoad(InOp, WidenVT);
6700}
6701
6702SDValue DAGTypeLegalizer::WidenVecRes_LOOP_DEPENDENCE_MASK(SDNode *N) {
6703 return DAG.getNode(
6704 N->getOpcode(), SDLoc(N),
6705 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)),
6706 N->getOperand(0), N->getOperand(1), N->getOperand(2), N->getOperand(3));
6707}
6708
6709SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
6710 SDLoc dl(N);
6711 // Build a vector with poison for the new nodes.
6712 EVT VT = N->getValueType(0);
6713
6714 // Integer BUILD_VECTOR operands may be larger than the node's vector element
6715 // type. The POISONs need to have the same type as the existing operands.
6716 EVT EltVT = N->getOperand(0).getValueType();
6717 unsigned NumElts = VT.getVectorNumElements();
6718
6719 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6720 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6721
6722 SmallVector<SDValue, 16> NewOps(N->ops());
6723 assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
6724 NewOps.append(WidenNumElts - NumElts, DAG.getPOISON(EltVT));
6725
6726 return DAG.getBuildVector(WidenVT, dl, NewOps);
6727}
6728
6729SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
6730 EVT InVT = N->getOperand(0).getValueType();
6731 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
6732 SDLoc dl(N);
6733 unsigned NumOperands = N->getNumOperands();
6734
6735 bool InputWidened = false; // Indicates we need to widen the input.
6736 if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
6737 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6738 unsigned NumInElts = InVT.getVectorMinNumElements();
6739 if (WidenNumElts % NumInElts == 0) {
6740 // Add undef vectors to widen to correct length.
6741 unsigned NumConcat = WidenNumElts / NumInElts;
6742 SDValue UndefVal = DAG.getPOISON(InVT);
6743 SmallVector<SDValue, 16> Ops(NumConcat);
6744 for (unsigned i=0; i < NumOperands; ++i)
6745 Ops[i] = N->getOperand(i);
6746 for (unsigned i = NumOperands; i != NumConcat; ++i)
6747 Ops[i] = UndefVal;
6748 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
6749 }
6750 } else {
6751 InputWidened = true;
6752 if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
6753 // The inputs and the result are widen to the same value.
6754 unsigned i;
6755 for (i=1; i < NumOperands; ++i)
6756 if (!N->getOperand(i).isUndef())
6757 break;
6758
6759 if (i == NumOperands)
6760 // Everything but the first operand is an UNDEF so just return the
6761 // widened first operand.
6762 return GetWidenedVector(N->getOperand(0));
6763
6764 if (NumOperands == 2) {
6765 assert(!WidenVT.isScalableVector() &&
6766 "Cannot use vector shuffles to widen CONCAT_VECTOR result");
6767 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6768 unsigned NumInElts = InVT.getVectorNumElements();
6769
6770 // Replace concat of two operands with a shuffle.
6771 SmallVector<int, 16> MaskOps(WidenNumElts, -1);
6772 for (unsigned i = 0; i < NumInElts; ++i) {
6773 MaskOps[i] = i;
6774 MaskOps[i + NumInElts] = i + WidenNumElts;
6775 }
6776 return DAG.getVectorShuffle(WidenVT, dl,
6777 GetWidenedVector(N->getOperand(0)),
6778 GetWidenedVector(N->getOperand(1)),
6779 MaskOps);
6780 }
6781 }
6782 }
6783
6784 if (WidenVT.isScalableVector()) {
6785 SDValue WideVec = DAG.getPOISON(WidenVT);
6786 unsigned NumInElts = InVT.getVectorMinNumElements();
6787 for (unsigned I = 0; I < NumOperands; ++I)
6788 WideVec =
6789 DAG.getInsertSubvector(dl, WideVec, N->getOperand(I), I * NumInElts);
6790 return WideVec;
6791 }
6792
6793 unsigned WidenNumElts = WidenVT.getVectorNumElements();
6794 unsigned NumInElts = InVT.getVectorNumElements();
6795
6796 // Fall back to use extracts and build vector.
6797 EVT EltVT = WidenVT.getVectorElementType();
6798 SmallVector<SDValue, 16> Ops(WidenNumElts);
6799 unsigned Idx = 0;
6800 for (unsigned i=0; i < NumOperands; ++i) {
6801 SDValue InOp = N->getOperand(i);
6802 if (InputWidened)
6803 InOp = GetWidenedVector(InOp);
6804 for (unsigned j = 0; j < NumInElts; ++j)
6805 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
6806 }
6807 SDValue UndefVal = DAG.getPOISON(EltVT);
6808 for (; Idx < WidenNumElts; ++Idx)
6809 Ops[Idx] = UndefVal;
6810 return DAG.getBuildVector(WidenVT, dl, Ops);
6811}
6812
6813SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
6814 EVT VT = N->getValueType(0);
6815 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6816 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
6817 SDValue InOp2 = N->getOperand(1);
6818 SDValue Idx = N->getOperand(2);
6819 SDLoc dl(N);
6820 return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
6821}
6822
6823SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
6824 EVT VT = N->getValueType(0);
6825 EVT EltVT = VT.getVectorElementType();
6826 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
6827 SDValue InOp = N->getOperand(0);
6828 SDValue Idx = N->getOperand(1);
6829 SDLoc dl(N);
6830
6831 auto InOpTypeAction = getTypeAction(InOp.getValueType());
6832 if (InOpTypeAction == TargetLowering::TypeWidenVector)
6833 InOp = GetWidenedVector(InOp);
6834
6835 EVT InVT = InOp.getValueType();
6836
6837 // Check if we can just return the input vector after widening.
6838 uint64_t IdxVal = Idx->getAsZExtVal();
6839 if (IdxVal == 0 && InVT == WidenVT)
6840 return InOp;
6841
6842 // Check if we can extract from the vector.
6843 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
6844 unsigned InNumElts = InVT.getVectorMinNumElements();
6845 unsigned VTNumElts = VT.getVectorMinNumElements();
6846 assert(IdxVal % VTNumElts == 0 &&
6847 "Expected Idx to be a multiple of subvector minimum vector length");
6848 if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
6849 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
6850
6851 if (VT.isScalableVector()) {
6852 // Try to split the operation up into smaller extracts and concat the
6853 // results together, e.g.
6854 // nxv6i64 extract_subvector(nxv12i64, 6)
6855 // <->
6856 // nxv8i64 concat(
6857 // nxv2i64 extract_subvector(nxv16i64, 6)
6858 // nxv2i64 extract_subvector(nxv16i64, 8)
6859 // nxv2i64 extract_subvector(nxv16i64, 10)
6860 // undef)
6861 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
6862 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
6863 "down type's element count");
6864 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
6866 // Avoid recursion around e.g. nxv1i8.
6867 if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
6869 unsigned I = 0;
6870 for (; I < VTNumElts / GCD; ++I)
6871 Parts.push_back(
6872 DAG.getExtractSubvector(dl, PartVT, InOp, IdxVal + I * GCD));
6873 for (; I < WidenNumElts / GCD; ++I)
6874 Parts.push_back(DAG.getPOISON(PartVT));
6875
6876 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
6877 }
6878
6879 // Fallback to extracting through memory.
6880
6881 Align Alignment = DAG.getReducedAlign(InVT, /*UseABI=*/false);
6882 SDValue StackPtr = DAG.CreateStackTemporary(InVT.getStoreSize(), Alignment);
6883 MachineFunction &MF = DAG.getMachineFunction();
6884 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
6885 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
6886
6887 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
6890 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
6893
6894 // Write out the input vector.
6895 SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, StoreMMO);
6896
6897 // Build a mask to match the length of the non-widened result.
6898 SDValue Mask =
6899 DAG.getMaskFromElementCount(dl, WidenVT, VT.getVectorElementCount());
6900
6901 // Read back the sub-vector setting the remaining lanes to poison.
6902 StackPtr = TLI.getVectorSubVecPointer(DAG, StackPtr, InVT, VT, Idx);
6903 return DAG.getMaskedLoad(
6904 WidenVT, dl, Ch, StackPtr, DAG.getPOISON(StackPtr.getValueType()), Mask,
6905 DAG.getPOISON(WidenVT), VT, LoadMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
6906 }
6907
6908 // We could try widening the input to the right length but for now, extract
6909 // the original elements, fill the rest with undefs and build a vector.
6910 SmallVector<SDValue, 16> Ops(WidenNumElts);
6911 unsigned i;
6912 for (i = 0; i < VTNumElts; ++i)
6913 Ops[i] = DAG.getExtractVectorElt(dl, EltVT, InOp, IdxVal + i);
6914
6915 SDValue UndefVal = DAG.getPOISON(EltVT);
6916 for (; i < WidenNumElts; ++i)
6917 Ops[i] = UndefVal;
6918 return DAG.getBuildVector(WidenVT, dl, Ops);
6919}
6920
6921SDValue DAGTypeLegalizer::WidenVecRes_AssertZext(SDNode *N) {
6922 SDValue InOp = ModifyToType(
6923 N->getOperand(0),
6924 TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), true);
6925 return DAG.getNode(ISD::AssertZext, SDLoc(N), InOp.getValueType(), InOp,
6926 N->getOperand(1));
6927}
6928
6929SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
6930 SDValue InOp = GetWidenedVector(N->getOperand(0));
6931 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
6932 InOp.getValueType(), InOp,
6933 N->getOperand(1), N->getOperand(2));
6934}
6935
6936/// Either return the same load or provide appropriate casts
6937/// from the load and return that.
6938static SDValue coerceLoadedValue(SDValue LdOp, EVT FirstVT, EVT WidenVT,
6939 TypeSize LdWidth, TypeSize FirstVTWidth,
6940 SDLoc dl, SelectionDAG &DAG) {
6941 assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth) &&
6942 "Load width must be less than or equal to first value type width");
6943 TypeSize WidenWidth = WidenVT.getSizeInBits();
6944 if (!FirstVT.isVector()) {
6945 unsigned NumElts =
6946 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6947 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6948 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
6949 return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
6950 }
6951 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6952 return LdOp;
6953}
6954
6955/// Inverse of coerceLoadedValue: pull a FirstVT-sized scalar/vector out of the
6956/// widened value so it can be issued in a single atomic store.
6957static SDValue coerceStoredValue(SDValue StVal, EVT FirstVT, EVT WidenVT,
6958 TypeSize FirstVTWidth, const SDLoc &dl,
6959 SelectionDAG &DAG) {
6960 TypeSize WidenWidth = WidenVT.getSizeInBits();
6961 if (!FirstVT.isVector()) {
6962 unsigned NumElts =
6963 WidenWidth.getFixedValue() / FirstVTWidth.getFixedValue();
6964 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), FirstVT, NumElts);
6965 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, StVal);
6966 return DAG.getExtractVectorElt(dl, FirstVT, VecOp, 0);
6967 }
6968 assert(FirstVT == WidenVT && "First value type must equal widen value type");
6969 return StVal;
6970}
6971
6972static std::optional<EVT> findMemType(SelectionDAG &DAG,
6973 const TargetLowering &TLI, unsigned Width,
6974 EVT WidenVT, unsigned Align,
6975 unsigned WidenEx);
6976
6977SDValue DAGTypeLegalizer::WidenVecRes_ATOMIC_LOAD(AtomicSDNode *LD) {
6978 EVT WidenVT =
6979 TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0));
6980 EVT LdVT = LD->getMemoryVT();
6981 SDLoc dl(LD);
6982
6983 // Load information
6984 SDValue Chain = LD->getChain();
6985 SDValue BasePtr = LD->getBasePtr();
6986
6987 TypeSize LdWidth = LdVT.getSizeInBits();
6988 TypeSize WidenWidth = WidenVT.getSizeInBits();
6989 TypeSize WidthDiff = WidenWidth - LdWidth;
6990
6991 // Find the vector type that can load from.
6992 std::optional<EVT> FirstVT =
6993 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, /*LdAlign=*/0,
6994 WidthDiff.getKnownMinValue());
6995
6996 if (!FirstVT)
6997 return SDValue();
6998
6999 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
7000
7001 SDValue LdOp = DAG.getAtomicLoad(ISD::NON_EXTLOAD, dl, *FirstVT, *FirstVT,
7002 Chain, BasePtr, LD->getMemOperand());
7003
7004 // Load the element with one instruction.
7005 SDValue Result = coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth,
7006 FirstVTWidth, dl, DAG);
7007
7008 // Modified the chain - switch anything that used the old chain to use
7009 // the new one.
7010 ReplaceValueWith(SDValue(LD, 1), LdOp.getValue(1));
7011 return Result;
7012}
7013
7014SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
7015 LoadSDNode *LD = cast<LoadSDNode>(N);
7016 ISD::LoadExtType ExtType = LD->getExtensionType();
7017
7018 // A vector must always be stored in memory as-is, i.e. without any padding
7019 // between the elements, since various code depend on it, e.g. in the
7020 // handling of a bitcast of a vector type to int, which may be done with a
7021 // vector store followed by an integer load. A vector that does not have
7022 // elements that are byte-sized must therefore be stored as an integer
7023 // built out of the extracted vector elements.
7024 if (!LD->getMemoryVT().isByteSized()) {
7025 SDValue Value, NewChain;
7026 std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
7027 ReplaceValueWith(SDValue(LD, 0), Value);
7028 ReplaceValueWith(SDValue(LD, 1), NewChain);
7029 return SDValue();
7030 }
7031
7032 // Generate a vector-predicated load if it is custom/legal on the target. To
7033 // avoid possible recursion, only do this if the widened mask type is legal.
7034 // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
7035 // removed from the IR by the ExpandVectorPredication pass but we're
7036 // reintroducing them here.
7037 EVT VT = LD->getValueType(0);
7038 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7039 EVT WideMaskVT = getSetCCResultType(WideVT);
7040
7041 if (ExtType == ISD::NON_EXTLOAD &&
7042 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
7043 TLI.isTypeLegal(WideMaskVT)) {
7044 SDLoc DL(N);
7045 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
7046 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
7048 SDValue NewLoad =
7049 DAG.getLoadVP(LD->getAddressingMode(), ISD::NON_EXTLOAD, WideVT, DL,
7050 LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
7051 EVL, LD->getMemoryVT(), LD->getMemOperand());
7052
7053 // Modified the chain - switch anything that used the old chain to use
7054 // the new one.
7055 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
7056
7057 return NewLoad;
7058 }
7059
7061 SmallVector<SDValue, 16> LdChain; // Chain for the series of load
7062 if (ExtType != ISD::NON_EXTLOAD)
7063 Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
7064 else
7065 Result = GenWidenVectorLoads(LdChain, LD);
7066
7067 if (Result) {
7068 // If we generate a single load, we can use that for the chain. Otherwise,
7069 // build a factor node to remember the multiple loads are independent and
7070 // chain to that.
7071 SDValue NewChain;
7072 if (LdChain.size() == 1)
7073 NewChain = LdChain[0];
7074 else
7075 NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);
7076
7077 // Modified the chain - switch anything that used the old chain to use
7078 // the new one.
7079 ReplaceValueWith(SDValue(N, 1), NewChain);
7080
7081 return Result;
7082 }
7083
7084 if (VT.isVector()) {
7085 // If all else fails replace the load with a wide masked load.
7086 SDLoc DL(N);
7087 SDValue Mask =
7088 DAG.getMaskFromElementCount(DL, WideVT, VT.getVectorElementCount());
7089
7090 SDValue NewLoad = DAG.getMaskedLoad(
7091 WideVT, DL, LD->getChain(), LD->getBasePtr(), LD->getOffset(), Mask,
7092 DAG.getPOISON(WideVT), LD->getMemoryVT(), LD->getMemOperand(),
7093 LD->getAddressingMode(), LD->getExtensionType());
7094
7095 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
7096 return NewLoad;
7097 }
7098
7099 report_fatal_error("Unable to widen vector load");
7100}
7101
7102SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD(VPLoadSDNode *N) {
7103 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7104 SDValue Mask = N->getMask();
7105 SDValue EVL = N->getVectorLength();
7106 ISD::LoadExtType ExtType = N->getExtensionType();
7107 SDLoc dl(N);
7108
7109 // The mask should be widened as well
7110 assert(getTypeAction(Mask.getValueType()) ==
7112 "Unable to widen binary VP op");
7113 Mask = GetWidenedVector(Mask);
7114 assert(Mask.getValueType().getVectorElementCount() ==
7115 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
7116 .getVectorElementCount() &&
7117 "Unable to widen vector load");
7118
7119 SDValue Res =
7120 DAG.getLoadVP(N->getAddressingMode(), ExtType, WidenVT, dl, N->getChain(),
7121 N->getBasePtr(), N->getOffset(), Mask, EVL,
7122 N->getMemoryVT(), N->getMemOperand(), N->isExpandingLoad());
7123 // Legalize the chain result - switch anything that used the old chain to
7124 // use the new one.
7125 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7126 return Res;
7127}
7128
7129SDValue DAGTypeLegalizer::WidenVecRes_VP_LOAD_FF(VPLoadFFSDNode *N) {
7130 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7131 SDValue Mask = N->getMask();
7132 SDValue EVL = N->getVectorLength();
7133 SDLoc dl(N);
7134
7135 // The mask should be widened as well
7136 assert(getTypeAction(Mask.getValueType()) ==
7138 "Unable to widen binary VP op");
7139 Mask = GetWidenedVector(Mask);
7140 assert(Mask.getValueType().getVectorElementCount() ==
7141 TLI.getTypeToTransformTo(*DAG.getContext(), Mask.getValueType())
7142 .getVectorElementCount() &&
7143 "Unable to widen vector load");
7144
7145 SDValue Res = DAG.getLoadFFVP(WidenVT, dl, N->getChain(), N->getBasePtr(),
7146 Mask, EVL, N->getMemOperand());
7147 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7148 ReplaceValueWith(SDValue(N, 2), Res.getValue(2));
7149 return Res;
7150}
7151
7152SDValue DAGTypeLegalizer::WidenVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *N) {
7153 SDLoc DL(N);
7154
7155 // The mask should be widened as well
7156 SDValue Mask = N->getMask();
7157 assert(getTypeAction(Mask.getValueType()) ==
7159 "Unable to widen VP strided load");
7160 Mask = GetWidenedVector(Mask);
7161
7162 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7163 assert(Mask.getValueType().getVectorElementCount() ==
7164 WidenVT.getVectorElementCount() &&
7165 "Data and mask vectors should have the same number of elements");
7166
7167 SDValue Res = DAG.getStridedLoadVP(
7168 N->getAddressingMode(), N->getExtensionType(), WidenVT, DL, N->getChain(),
7169 N->getBasePtr(), N->getOffset(), N->getStride(), Mask,
7170 N->getVectorLength(), N->getMemoryVT(), N->getMemOperand(),
7171 N->isExpandingLoad());
7172
7173 // Legalize the chain result - switch anything that used the old chain to
7174 // use the new one.
7175 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7176 return Res;
7177}
7178
7179SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_COMPRESS(SDNode *N) {
7180 SDValue Vec = N->getOperand(0);
7181 SDValue Mask = N->getOperand(1);
7182 SDValue Passthru = N->getOperand(2);
7183 EVT WideVecVT =
7184 TLI.getTypeToTransformTo(*DAG.getContext(), Vec.getValueType());
7185 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
7186 Mask.getValueType().getVectorElementType(),
7187 WideVecVT.getVectorElementCount());
7188
7189 SDValue WideVec = ModifyToType(Vec, WideVecVT);
7190 SDValue WideMask = ModifyToType(Mask, WideMaskVT, /*FillWithZeroes=*/true);
7191 SDValue WidePassthru = ModifyToType(Passthru, WideVecVT);
7192 return DAG.getNode(ISD::VECTOR_COMPRESS, SDLoc(N), WideVecVT, WideVec,
7193 WideMask, WidePassthru);
7194}
7195
7196SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE_VAR(SDNode *N) {
7197 // Only indices that were out of range can select the new source elements.
7198 SDValue Src = GetWidenedVector(N->getOperand(0));
7199 EVT WideVT = Src.getValueType();
7200 EVT WideMaskVT = WideVT.changeVectorElementType(
7201 *DAG.getContext(),
7202 N->getOperand(1).getValueType().getVectorElementType());
7203 SDValue Mask = ModifyToType(N->getOperand(1), WideMaskVT);
7204 return DAG.getNode(ISD::VECTOR_SHUFFLE_VAR, SDLoc(N), WideVT, Src, Mask);
7205}
7206
7207SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {
7208 EVT VT = N->getValueType(0);
7209 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7210 SDValue Mask = N->getMask();
7211 EVT MaskVT = Mask.getValueType();
7212 SDValue PassThru = GetWidenedVector(N->getPassThru());
7213 ISD::LoadExtType ExtType = N->getExtensionType();
7214 SDLoc dl(N);
7215
7216 EVT WideMaskVT =
7217 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
7218 WidenVT.getVectorElementCount());
7219
7220 if (ExtType == ISD::NON_EXTLOAD && !N->isExpandingLoad() &&
7221 TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WidenVT) &&
7222 TLI.isTypeLegal(WideMaskVT) &&
7223 // If there is a passthru, we shouldn't use vp.load. However,
7224 // type legalizer will struggle on masked.load with
7225 // scalable vectors, so for scalable vectors, we still use vp.load
7226 // but manually merge the load result with the passthru using vp.select.
7227 (N->getPassThru()->isUndef() || VT.isScalableVector())) {
7228 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
7229 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
7231 SDValue NewLoad =
7232 DAG.getLoadVP(N->getAddressingMode(), ISD::NON_EXTLOAD, WidenVT, dl,
7233 N->getChain(), N->getBasePtr(), N->getOffset(), Mask, EVL,
7234 N->getMemoryVT(), N->getMemOperand());
7235 SDValue NewVal = NewLoad;
7236
7237 // Manually merge with vselect
7238 if (!N->getPassThru()->isUndef()) {
7239 assert(WidenVT.isScalableVector());
7240 NewVal = DAG.getNode(ISD::VSELECT, dl, WidenVT, Mask, NewVal, PassThru);
7241 // The lanes past EVL are poison.
7242 NewVal = DAG.getNode(ISD::VP_MERGE, dl, WidenVT,
7243 DAG.getAllOnesConstant(dl, WideMaskVT), NewVal,
7244 DAG.getPOISON(WidenVT), EVL);
7245 }
7246
7247 // Modified the chain - switch anything that used the old chain to use
7248 // the new one.
7249 ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));
7250
7251 return NewVal;
7252 }
7253
7254 // The mask should be widened as well
7255 Mask = ModifyToType(Mask, WideMaskVT, true);
7256
7257 SDValue Res = DAG.getMaskedLoad(
7258 WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
7259 PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
7260 ExtType, N->isExpandingLoad());
7261 // Legalize the chain result - switch anything that used the old chain to
7262 // use the new one.
7263 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7264 return Res;
7265}
7266
7267SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {
7268
7269 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7270 SDValue Mask = N->getMask();
7271 EVT MaskVT = Mask.getValueType();
7272 SDValue PassThru = GetWidenedVector(N->getPassThru());
7273 SDValue Scale = N->getScale();
7274 ElementCount WideEC = WideVT.getVectorElementCount();
7275 SDLoc dl(N);
7276
7277 // The mask should be widened as well
7278 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
7279 MaskVT.getVectorElementType(), WideEC);
7280 Mask = ModifyToType(Mask, WideMaskVT, true);
7281
7282 // Widen the Index operand
7283 SDValue Index = N->getIndex();
7284 EVT WideIndexVT = EVT::getVectorVT(
7285 *DAG.getContext(), Index.getValueType().getScalarType(), WideEC);
7286 Index = ModifyToType(Index, WideIndexVT);
7287 SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
7288 Scale };
7289
7290 // Widen the MemoryType
7291 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7292 N->getMemoryVT().getScalarType(), WideEC);
7293 SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
7294 WideMemVT, dl, Ops, N->getMemOperand(),
7295 N->getIndexType(), N->getExtensionType());
7296
7297 // Legalize the chain result - switch anything that used the old chain to
7298 // use the new one.
7299 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7300 return Res;
7301}
7302
7303SDValue DAGTypeLegalizer::WidenVecRes_VP_GATHER(VPGatherSDNode *N) {
7304 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7305 SDValue Mask = N->getMask();
7306 SDValue Scale = N->getScale();
7307 ElementCount WideEC = WideVT.getVectorElementCount();
7308 SDLoc dl(N);
7309
7310 SDValue Index = GetWidenedVector(N->getIndex());
7311 EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
7312 N->getMemoryVT().getScalarType(), WideEC);
7313 Mask = GetWidenedMask(Mask, WideEC);
7314
7315 SDValue Ops[] = {N->getChain(), N->getBasePtr(), Index, Scale,
7316 Mask, N->getVectorLength()};
7317 SDValue Res = DAG.getGatherVP(DAG.getVTList(WideVT, MVT::Other), WideMemVT,
7318 dl, Ops, N->getMemOperand(), N->getIndexType());
7319
7320 // Legalize the chain result - switch anything that used the old chain to
7321 // use the new one.
7322 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
7323 return Res;
7324}
7325
7326SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
7327 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7328 return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
7329}
7330
7331// Return true is this is a SETCC node or a strict version of it.
7332static inline bool isSETCCOp(unsigned Opcode) {
7333 switch (Opcode) {
7334 case ISD::SETCC:
7335 case ISD::STRICT_FSETCC:
7337 return true;
7338 }
7339 return false;
7340}
7341
7342// Return true if this is a node that could have two SETCCs as operands.
7343static inline bool isLogicalMaskOp(unsigned Opcode) {
7344 switch (Opcode) {
7345 case ISD::AND:
7346 case ISD::OR:
7347 case ISD::XOR:
7348 return true;
7349 }
7350 return false;
7351}
7352
7353// If N is a SETCC or a strict variant of it, return the type
7354// of the compare operands.
7356 unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
7357 return N->getOperand(OpNo).getValueType();
7358}
7359
7360// This is used just for the assert in convertMask(). Check that this either
7361// a SETCC or a previously handled SETCC by convertMask().
7362#ifndef NDEBUG
7363static inline bool isSETCCorConvertedSETCC(SDValue N) {
7364 if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
7365 N = N.getOperand(0);
7366 else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
7367 for (unsigned i = 1; i < N->getNumOperands(); ++i)
7368 if (!N->getOperand(i)->isUndef())
7369 return false;
7370 N = N.getOperand(0);
7371 }
7372
7373 if (N.getOpcode() == ISD::TRUNCATE)
7374 N = N.getOperand(0);
7375 else if (N.getOpcode() == ISD::SIGN_EXTEND)
7376 N = N.getOperand(0);
7377
7378 if (isLogicalMaskOp(N.getOpcode()))
7379 return isSETCCorConvertedSETCC(N.getOperand(0)) &&
7380 isSETCCorConvertedSETCC(N.getOperand(1));
7381
7382 return (isSETCCOp(N.getOpcode()) ||
7384}
7385#endif
7386
7387// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
7388// to ToMaskVT if needed with vector extension or truncation.
7389SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
7390 EVT ToMaskVT) {
7391 // Called from convertMaskTree for SETCC leaf nodes. Re-creates the SETCC with
7392 // result type MaskVT, then sign-extends/truncates and pads to ToMaskVT.
7393 assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");
7394
7395 // Make a new Mask node, with a legal result VT.
7396 SDValue Mask;
7398 for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
7399 Ops.push_back(InMask->getOperand(i));
7400 if (InMask->isStrictFPOpcode()) {
7401 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
7402 { MaskVT, MVT::Other }, Ops);
7403 ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
7404 }
7405 else
7406 Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops,
7407 InMask->getFlags());
7408
7409 return adjustMaskToType(Mask, ToMaskVT);
7410}
7411
7412// Adjust element width (sign-extend/truncate) and element count
7413// (extract/concat) of Mask to match ToMaskVT.
7414SDValue DAGTypeLegalizer::adjustMaskToType(SDValue Mask, EVT ToMaskVT) {
7415 LLVMContext &Ctx = *DAG.getContext();
7416 EVT MaskVT = Mask.getValueType();
7417 unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
7418 unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
7419 if (MaskScalarBits < ToMaskScalBits) {
7420 EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7421 MaskVT.getVectorNumElements());
7422 Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
7423 } else if (MaskScalarBits > ToMaskScalBits) {
7424 EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
7425 MaskVT.getVectorNumElements());
7426 Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
7427 }
7428
7429 assert(Mask->getValueType(0).getScalarSizeInBits() ==
7430 ToMaskVT.getScalarSizeInBits() &&
7431 "Mask should have the right element size by now.");
7432
7433 // Adjust Mask to the right number of elements.
7434 unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
7435 if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
7436 Mask = DAG.getExtractSubvector(SDLoc(Mask), ToMaskVT, Mask, 0);
7437 } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
7438 unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
7439 EVT SubVT = Mask->getValueType(0);
7440 SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getPOISON(SubVT));
7441 SubOps[0] = Mask;
7442 Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
7443 }
7444
7445 assert((Mask->getValueType(0) == ToMaskVT) &&
7446 "A mask of ToMaskVT should have been produced by now.");
7447
7448 return Mask;
7449}
7450
7451// Adjust both operands to a common intermediate mask type, picking a scalar
7452// width that minimizes extend/truncate overhead given the final target ToVT.
7453EVT DAGTypeLegalizer::unifyMaskTypes(SDValue &Op0, bool IsOpLenient0,
7454 SDValue &Op1, bool IsOpLenient1,
7455 EVT ToVT) {
7458 "unifyMaskTypes only handles scalar width differences");
7459
7460 // If only one of the operands lenient type-wise, we can simply
7461 // adjust its type to the other operand's type assuming that this
7462 // adjustment can be folded away.
7463 //
7464 // NOTE: We essentially rely on the fact that further optimizations
7465 // do spot redundant casts in "lenient" cases. If at some
7466 // point we decide that we want to do better here, we can
7467 // postpone converting lenient sub-trees right away and postpone
7468 // it to the moment when we know the best fitting integer type
7469 // to materialize them, and do it there.
7470 if (IsOpLenient0 != IsOpLenient1) {
7471 SDValue *LenientOp, *NonLenientOp;
7472 if (IsOpLenient0) {
7473 LenientOp = &Op0;
7474 NonLenientOp = &Op1;
7475 } else {
7476 LenientOp = &Op1;
7477 NonLenientOp = &Op0;
7478 }
7479 EVT OpVT = NonLenientOp->getValueType();
7480 *LenientOp = adjustMaskToType(*LenientOp, OpVT);
7481 return OpVT;
7482 }
7483
7484 unsigned Bits0 = Op0.getScalarValueSizeInBits();
7485 unsigned Bits1 = Op1.getScalarValueSizeInBits();
7486 unsigned NarrowBits = std::min(Bits0, Bits1);
7487 unsigned WideBits = std::max(Bits0, Bits1);
7488 unsigned ToBits = ToVT.getScalarSizeInBits();
7489 unsigned IntBits = NarrowBits == WideBits ? NarrowBits
7490 : ToBits >= WideBits ? WideBits
7491 : ToBits <= NarrowBits ? NarrowBits
7492 : ToBits;
7493 EVT OpVT = Op0.getValueType().changeVectorElementType(
7494 *DAG.getContext(), EVT::getIntegerVT(*DAG.getContext(), IntBits));
7495 Op0 = adjustMaskToType(Op0, OpVT);
7496 Op1 = adjustMaskToType(Op1, OpVT);
7497 return OpVT;
7498}
7499
7500std::pair<SDValue, bool>
7501DAGTypeLegalizer::convertMaskTreeImpl(SDValue V, EVT ToVT, unsigned Depth) {
7502 // The main idea is to recursively traverse VSELECT's mask that needs
7503 // widening to see if we can avoid unnecessary casts. The problem usually
7504 // stems from a simple fact that SETCC might naturally produce results
7505 // not in i1 (as we model it in LLVM IR) and we can continue using that
7506 // type until we have to switch it up. Another important aspect is that
7507 // "all ones" and "all zeros" constants can be materialized at any type,
7508 // so we can try to utilize that to keep SETCC results at their natural
7509 // types as much as possible.
7510 //
7511 // The algorithm traverses the mask-producing tree of operations that
7512 // retain "mask-vector"-ness of the input (i.e. it remains a vector of
7513 // -1s and 0s).
7514 //
7515 // SETCC1 SETCC2 CONST1 SETCC3 CONST2 CONST3
7516 // | / | / | /
7517 // | / | / | /
7518 // |_____/ |______/ |______/
7519 // | * choose the | * choose SETCC3 | * keep it as final type
7520 // | most fitting | type | but consider it subject to
7521 // | type | / change
7522 // | | /
7523 // | |______________/
7524 // | | * choose SETCC3 type
7525 // | /
7526 // | /
7527 // |_____________/
7528 // | * choose the most fitting type
7529 // | and then cast to the final desired type
7530 // |
7531 // VSELECT
7532 //
7533 if (Depth >= DAG.MaxRecursionDepth)
7534 return {};
7535
7536 // Bail out when encounter the vector element count mismatch.
7537 // It potentially can be just an assertion, but we deliberately try to
7538 // be overly conservative here.
7539 if (V.getValueType().getVectorNumElements() != ToVT.getVectorNumElements())
7540 return {};
7541
7542 unsigned Opcode = V.getOpcode();
7543
7544 // Base case: SETCC produces the mask at its natural type.
7545 if (isSETCCOp(Opcode)) {
7546 EVT MaskVT = getSetCCResultType(getSETCCOperandType(V));
7547 return {convertMask(V, MaskVT, MaskVT), /*IsTypeLenient=*/false};
7548 }
7549
7550 SDLoc DL(V);
7551
7552 // Base case: all-zeros or all-ones BUILD_VECTOR. Type-lenient since these are
7553 // invariant under sign-extend/truncate.
7554 if (ISD::isBuildVectorAllZeros(V.getNode()))
7555 return {DAG.getConstant(0, DL, ToVT), /*IsTypeLenient=*/true};
7556 if (ISD::isBuildVectorAllOnes(V.getNode()))
7557 return {DAG.getAllOnesConstant(DL, ToVT), /*IsTypeLenient=*/true};
7558
7559 // Logical operations (AND/OR/XOR): try picking the best fitting width out
7560 // of children's element widths.
7561 if (isLogicalMaskOp(Opcode)) {
7562 auto [Op0, IsLenientOp0] =
7563 convertMaskTreeImpl(V.getOperand(0), ToVT, Depth + 1);
7564 if (!Op0)
7565 return {};
7566 auto [Op1, IsLenientOp1] =
7567 convertMaskTreeImpl(V.getOperand(1), ToVT, Depth + 1);
7568 if (!Op1)
7569 return {};
7570 EVT OpVT = unifyMaskTypes(Op0, IsLenientOp0, Op1, IsLenientOp1, ToVT);
7571 return {DAG.getNode(Opcode, DL, OpVT, Op0, Op1),
7572 IsLenientOp0 && IsLenientOp1};
7573 }
7574
7575 // FREEZE: widen the operand and re-wrap.
7576 if (Opcode == ISD::FREEZE) {
7577 auto [Inner, IsTypeLenient] =
7578 convertMaskTreeImpl(V.getOperand(0), ToVT, Depth + 1);
7579 if (!Inner)
7580 return {};
7581 return {DAG.getNode(ISD::FREEZE, DL, Inner.getValueType(), Inner),
7582 IsTypeLenient};
7583 }
7584
7585 // Vector shuffle: try inferring the best fitting width from operands.
7586 if (Opcode == ISD::VECTOR_SHUFFLE) {
7587 auto *Shuf = cast<ShuffleVectorSDNode>(V);
7588 auto [Op0, IsLenientOp0] =
7589 convertMaskTreeImpl(V.getOperand(0), ToVT, Depth + 1);
7590 if (!Op0)
7591 return {};
7592 if (V.getOperand(1).isUndef()) {
7593 EVT OpVT = Op0.getValueType();
7594 return {DAG.getVectorShuffle(OpVT, DL, Op0, DAG.getUNDEF(OpVT),
7595 Shuf->getMask()),
7596 IsLenientOp0};
7597 }
7598 auto [Op1, IsLenientOp1] =
7599 convertMaskTreeImpl(V.getOperand(1), ToVT, Depth + 1);
7600 if (!Op1)
7601 return {};
7602 EVT OpVT = unifyMaskTypes(Op0, IsLenientOp0, Op1, IsLenientOp1, ToVT);
7603 return {DAG.getVectorShuffle(OpVT, DL, Op0, Op1, Shuf->getMask()),
7604 IsLenientOp0 && IsLenientOp1};
7605 }
7606
7607 // SELECT/VSELECT: try inferring the best fitting width from operands.
7608 if (Opcode == ISD::SELECT || Opcode == ISD::VSELECT) {
7609 auto [Op1, IsLenientOp1] =
7610 convertMaskTreeImpl(V.getOperand(1), ToVT, Depth + 1);
7611 if (!Op1)
7612 return {};
7613 auto [Op2, IsLenientOp2] =
7614 convertMaskTreeImpl(V.getOperand(2), ToVT, Depth + 1);
7615 if (!Op2)
7616 return {};
7617 EVT OpVT = unifyMaskTypes(Op1, IsLenientOp1, Op2, IsLenientOp2, ToVT);
7618
7619 // We deliberately skip traversing/modifying VSELECT's mask because
7620 //
7621 // a. We only change bitwidth of the operands and it shouldn't affect
7622 // condition on its own.
7623 //
7624 // b. This VSELECT's mask can be widened in an independent traversal
7625 // if needed.
7626 SDValue Cond = V.getOperand(0);
7627 return {DAG.getNode(Opcode, DL, OpVT, Cond, Op1, Op2),
7628 IsLenientOp1 && IsLenientOp2};
7629 }
7630
7631 return {};
7632}
7633
7634SDValue DAGTypeLegalizer::convertMaskTree(SDValue V, EVT ToVT) {
7635 // In general, we are converting from <N x i1> into <M x iW>.
7636 // This would mean that during the tree traversal we need to pay
7637 // attention to both bitwidth and element count, which can be error-prone.
7638 //
7639 // Instead, we split the task in two, we first widen the type of the tree
7640 // and then change the element count.
7641 EVT MaskTreeVT = ToVT.changeVectorElementCount(
7642 *DAG.getContext(), V.getValueType().getVectorElementCount());
7643 auto [Result, _] = convertMaskTreeImpl(V, MaskTreeVT);
7644 if (!Result)
7645 return Result;
7646 return adjustMaskToType(Result, ToVT);
7647}
7648
7649// This method tries to handle some special cases for the vselect mask
7650// and if needed adjusting the mask vector type to match that of the VSELECT.
7651// Without it, many cases end up with scalarization of the SETCC, with many
7652// unnecessary instructions.
7653SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
7654 LLVMContext &Ctx = *DAG.getContext();
7655 SDValue Cond = N->getOperand(0);
7656
7657 if (N->getOpcode() != ISD::VSELECT)
7658 return SDValue();
7659
7660 // If this is a splitted VSELECT that was previously already handled, do
7661 // nothing.
7662 EVT CondVT = Cond->getValueType(0);
7663 if (CondVT.getScalarSizeInBits() != 1)
7664 return SDValue();
7665
7666 EVT VSelVT = N->getValueType(0);
7667
7668 // This method can't handle scalable vector types.
7669 // FIXME: This support could be added in the future.
7670 if (VSelVT.isScalableVector())
7671 return SDValue();
7672
7673 // Only handle vector types which are a power of 2.
7674 if (!isPowerOf2_64(VSelVT.getSizeInBits()))
7675 return SDValue();
7676
7677 // Don't touch if this will be scalarized.
7678 EVT FinalVT = VSelVT;
7679 while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
7680 FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);
7681
7682 if (FinalVT.getVectorNumElements() == 1)
7683 return SDValue();
7684
7685 // If there is support for an i1 vector mask, don't touch.
7686 if (isSETCCOp(Cond.getOpcode())) {
7687 EVT SetCCOpVT = getSETCCOperandType(Cond);
7688 while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
7689 SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
7690 EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
7691 if (SetCCResVT.getScalarSizeInBits() == 1)
7692 return SDValue();
7693 } else if (CondVT.getScalarType() == MVT::i1) {
7694 // If there is support for an i1 vector mask (or only scalar i1 conditions),
7695 // don't touch.
7696 while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
7697 CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);
7698
7699 if (CondVT.getScalarType() == MVT::i1)
7700 return SDValue();
7701 }
7702
7703 // Widen the vselect result type if needed.
7704 if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
7705 VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);
7706
7707 // The mask of the VSELECT should have integer elements.
7708 EVT ToMaskVT = VSelVT;
7709 if (!ToMaskVT.getScalarType().isInteger())
7710 ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();
7711
7712 // Try to recursively widen the mask expression tree to the target type.
7713 return convertMaskTree(Cond, ToMaskVT);
7714}
7715
7716SDValue DAGTypeLegalizer::WidenVecRes_Select(SDNode *N) {
7717 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7718 ElementCount WidenEC = WidenVT.getVectorElementCount();
7719
7720 SDValue Cond1 = N->getOperand(0);
7721 EVT CondVT = Cond1.getValueType();
7722 unsigned Opcode = N->getOpcode();
7723 if (CondVT.isVector()) {
7724 if (SDValue WideCond = WidenVSELECTMask(N)) {
7725 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7726 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7727 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7728 return DAG.getNode(Opcode, SDLoc(N), WidenVT, WideCond, InOp1, InOp2);
7729 }
7730
7731 EVT CondEltVT = CondVT.getVectorElementType();
7732 EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
7733 if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
7734 Cond1 = GetWidenedVector(Cond1);
7735
7736 // If we have to split the condition there is no point in widening the
7737 // select. This would result in an cycle of widening the select ->
7738 // widening the condition operand -> splitting the condition operand ->
7739 // splitting the select -> widening the select. Instead split this select
7740 // further and widen the resulting type.
7741 if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
7742 SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
7743 SDValue Res = ModifyToType(SplitSelect, WidenVT);
7744 return Res;
7745 }
7746
7747 if (Cond1.getValueType() != CondWidenVT)
7748 Cond1 = ModifyToType(Cond1, CondWidenVT);
7749 }
7750
7751 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
7752 SDValue InOp2 = GetWidenedVector(N->getOperand(2));
7753 assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
7754 if (Opcode == ISD::VP_MERGE)
7755 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2,
7756 N->getOperand(3));
7757 return DAG.getNode(Opcode, SDLoc(N), WidenVT, Cond1, InOp1, InOp2);
7758}
7759
7760SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
7761 SDValue InOp1 = GetWidenedVector(N->getOperand(2));
7762 SDValue InOp2 = GetWidenedVector(N->getOperand(3));
7763 return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
7764 InOp1.getValueType(), N->getOperand(0),
7765 N->getOperand(1), InOp1, InOp2, N->getOperand(4));
7766}
7767
7768SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
7769 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7770 return DAG.getUNDEF(WidenVT);
7771}
7772
7773SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
7774 EVT VT = N->getValueType(0);
7775 SDLoc dl(N);
7776
7777 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7778 unsigned NumElts = VT.getVectorNumElements();
7779 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7780
7781 SDValue InOp1 = GetWidenedVector(N->getOperand(0));
7782 SDValue InOp2 = GetWidenedVector(N->getOperand(1));
7783
7784 // Adjust mask based on new input vector length.
7785 SmallVector<int, 16> NewMask(WidenNumElts, -1);
7786 for (unsigned i = 0; i != NumElts; ++i) {
7787 int Idx = N->getMaskElt(i);
7788 if (Idx < (int)NumElts)
7789 NewMask[i] = Idx;
7790 else
7791 NewMask[i] = Idx - NumElts + WidenNumElts;
7792 }
7793 return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
7794}
7795
7796SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_REVERSE(SDNode *N) {
7797 EVT VT = N->getValueType(0);
7798 EVT EltVT = VT.getVectorElementType();
7799 SDLoc dl(N);
7800
7801 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7802 SDValue OpValue = GetWidenedVector(N->getOperand(0));
7803 assert(WidenVT == OpValue.getValueType() && "Unexpected widened vector type");
7804
7805 SDValue ReverseVal = DAG.getNode(ISD::VECTOR_REVERSE, dl, WidenVT, OpValue);
7806 unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
7807 unsigned VTNumElts = VT.getVectorMinNumElements();
7808 unsigned IdxVal = WidenNumElts - VTNumElts;
7809
7810 if (VT.isScalableVector()) {
7811 // Try to split the 'Widen ReverseVal' into smaller extracts and concat the
7812 // results together, e.g.(nxv6i64 -> nxv8i64)
7813 // nxv8i64 vector_reverse
7814 // <->
7815 // nxv8i64 concat(
7816 // nxv2i64 extract_subvector(nxv8i64, 2)
7817 // nxv2i64 extract_subvector(nxv8i64, 4)
7818 // nxv2i64 extract_subvector(nxv8i64, 6)
7819 // nxv2i64 undef)
7820
7821 unsigned GCD = std::gcd(VTNumElts, WidenNumElts);
7822 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
7824 assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
7825 "down type's element count");
7827 unsigned i = 0;
7828 for (; i < VTNumElts / GCD; ++i)
7829 Parts.push_back(
7830 DAG.getExtractSubvector(dl, PartVT, ReverseVal, IdxVal + i * GCD));
7831 for (; i < WidenNumElts / GCD; ++i)
7832 Parts.push_back(DAG.getPOISON(PartVT));
7833
7834 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
7835 }
7836
7837 // Use VECTOR_SHUFFLE to combine new vector from 'ReverseVal' for
7838 // fixed-vectors.
7839 SmallVector<int, 16> Mask(WidenNumElts, -1);
7840 std::iota(Mask.begin(), Mask.begin() + VTNumElts, IdxVal);
7841
7842 return DAG.getVectorShuffle(WidenVT, dl, ReverseVal, DAG.getPOISON(WidenVT),
7843 Mask);
7844}
7845
7846SDValue DAGTypeLegalizer::WidenVecRes_GET_ACTIVE_LANE_MASK(SDNode *N) {
7847 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7848 return DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, SDLoc(N), NVT, N->ops());
7849}
7850
7851void DAGTypeLegalizer::WidenVecRes_VECTOR_INTERLEAVE(SDNode *N) {
7852 EVT VT = N->getValueType(0);
7853 EVT EltVT = VT.getVectorElementType();
7854 ElementCount OrigEC = VT.getVectorElementCount();
7855 unsigned Factor = N->getNumOperands();
7856 SDLoc DL(N);
7857
7858 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7859 ElementCount WidenEC = WidenVT.getVectorElementCount();
7860
7861 SmallVector<SDValue, 8> WidenOps(Factor);
7862 for (unsigned Idx = 0U; Idx < Factor; ++Idx)
7863 WidenOps[Idx] = GetWidenedVector(N->getOperand(Idx));
7864
7865 SmallVector<EVT, 8> WidenVTs(Factor, WidenVT);
7866 SDValue Interleaved =
7867 DAG.getNode(ISD::VECTOR_INTERLEAVE, DL, WidenVTs, WidenOps);
7868
7869 EVT PackedWidenVT =
7870 EVT::getVectorVT(*DAG.getContext(), EltVT, WidenEC * Factor);
7871 SmallVector<SDValue, 8> Slices(Factor);
7872 for (unsigned Idx = 0; Idx != Factor; ++Idx)
7873 Slices[Idx] = Interleaved.getValue(Idx);
7874
7875 SDValue Packed = DAG.getNode(ISD::CONCAT_VECTORS, DL, PackedWidenVT, Slices);
7876
7877 for (unsigned Idx = 0U; Idx < Factor; ++Idx) {
7878 SDValue Narrow = DAG.getExtractSubvector(DL, VT, Packed,
7879 OrigEC.getKnownMinValue() * Idx);
7880 SDValue Wide =
7881 DAG.getInsertSubvector(DL, DAG.getPOISON(WidenVT), Narrow, /*Idx=*/0U);
7882 SetWidenedVector(SDValue(N, Idx), Wide);
7883 }
7884}
7885
7886SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_MATCH(SDNode *N) {
7887 SDLoc DL(N);
7888 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7889 EVT SourceVT = N->getOperand(0).getValueType();
7890 EVT WideSourceVT =
7891 EVT::getVectorVT(*DAG.getContext(), SourceVT.getVectorElementType(),
7892 WidenVT.getVectorElementCount());
7893
7894 SDValue WideSource = DAG.getInsertSubvector(DL, DAG.getUNDEF(WideSourceVT),
7895 N->getOperand(0), 0);
7896 SDValue WideMask = DAG.getInsertSubvector(DL, DAG.getConstant(0, DL, WidenVT),
7897 N->getOperand(2), 0);
7898 return DAG.getNode(ISD::VECTOR_MATCH, DL, WidenVT, WideSource,
7899 N->getOperand(1), WideMask, N->getFlags());
7900}
7901
7902void DAGTypeLegalizer::WidenVecRes_VECTOR_DEINTERLEAVE(SDNode *N) {
7903 EVT VT = N->getValueType(0);
7904 EVT EltVT = VT.getVectorElementType();
7905 ElementCount OrigEC = VT.getVectorElementCount();
7906 unsigned Factor = N->getNumOperands();
7907 SDLoc DL(N);
7908
7909 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7910 ElementCount WidenEC = WidenVT.getVectorElementCount();
7911 // We cannot just use the widened operands directly: since they might be
7912 // individually widened, using them directly will result in de-interleaving
7913 // the "padded" lanes that sit in the middle of the vector. Instead, we should
7914 // not concat the widened operands but the original ones to effectively
7915 // generate a "packed" concated and widened vector, before extracting new
7916 // operand vectors with the widened type.
7917 EVT PackedWidenVT =
7918 EVT::getVectorVT(*DAG.getContext(), EltVT, WidenEC * Factor);
7919 EVT ConcatVT = EVT::getVectorVT(*DAG.getContext(), EltVT, OrigEC * Factor);
7920 SDValue ConcatOp = DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVT, N->ops());
7921 SDValue PackedWidenVec = DAG.getInsertSubvector(
7922 DL, DAG.getUNDEF(PackedWidenVT), ConcatOp, /*Idx=*/0U);
7923
7924 // Extract the new widened operand vectors.
7925 SmallVector<SDValue, 8> NewOps(Factor, SDValue());
7926 for (unsigned Idx = 0U; Idx < Factor; ++Idx) {
7927 NewOps[Idx] = DAG.getExtractSubvector(DL, WidenVT, PackedWidenVec,
7928 WidenEC.getKnownMinValue() * Idx);
7929 }
7930
7931 SmallVector<EVT, 8> NewVTs(Factor, WidenVT);
7932 SDValue NewRes = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, NewVTs, NewOps);
7933 // Set the widened results manually.
7934 for (unsigned Idx = 0U; Idx < Factor; ++Idx)
7935 SetWidenedVector(SDValue(N, Idx), NewRes.getValue(Idx));
7936}
7937
7938SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
7939 assert(N->getValueType(0).isVector() &&
7940 N->getOperand(0).getValueType().isVector() &&
7941 "Operands must be vectors");
7942 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
7943 ElementCount WidenEC = WidenVT.getVectorElementCount();
7944
7945 SDValue InOp1 = N->getOperand(0);
7946 EVT InVT = InOp1.getValueType();
7947 assert(InVT.isVector() && "can not widen non-vector type");
7948 EVT WidenInVT =
7949 EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), WidenEC);
7950
7951 // The input and output types often differ here, and it could be that while
7952 // we'd prefer to widen the result type, the input operands have been split.
7953 // In this case, we also need to split the result of this node as well.
7954 if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
7955 SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
7956 SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
7957 return Res;
7958 }
7959
7960 // If the inputs also widen, handle them directly. Otherwise widen by hand.
7961 SDValue InOp2 = N->getOperand(1);
7962 if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
7963 InOp1 = GetWidenedVector(InOp1);
7964 InOp2 = GetWidenedVector(InOp2);
7965 } else {
7966 SDValue Poison = DAG.getPOISON(WidenInVT);
7967 SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(N));
7968 InOp1 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7969 InOp1, ZeroIdx);
7970 InOp2 = DAG.getNode(ISD::INSERT_SUBVECTOR, SDLoc(N), WidenInVT, Poison,
7971 InOp2, ZeroIdx);
7972 }
7973
7974 // Assume that the input and output will be widen appropriately. If not,
7975 // we will have to unroll it at some point.
7976 assert(InOp1.getValueType() == WidenInVT &&
7977 InOp2.getValueType() == WidenInVT &&
7978 "Input not widened to expected type!");
7979 (void)WidenInVT;
7980 return DAG.getNode(ISD::SETCC, SDLoc(N), WidenVT, InOp1, InOp2,
7981 N->getOperand(2));
7982}
7983
7984SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
7985 assert(N->getValueType(0).isVector() &&
7986 N->getOperand(1).getValueType().isVector() &&
7987 "Operands must be vectors");
7988 EVT VT = N->getValueType(0);
7989 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
7990 unsigned WidenNumElts = WidenVT.getVectorNumElements();
7991 unsigned NumElts = VT.getVectorNumElements();
7992 EVT EltVT = VT.getVectorElementType();
7993
7994 SDLoc dl(N);
7995 SDValue Chain = N->getOperand(0);
7996 SDValue LHS = N->getOperand(1);
7997 SDValue RHS = N->getOperand(2);
7998 SDValue CC = N->getOperand(3);
7999 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
8000
8001 // Fully unroll and reassemble.
8002 SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getPOISON(EltVT));
8003 SmallVector<SDValue, 8> Chains(NumElts);
8004 for (unsigned i = 0; i != NumElts; ++i) {
8005 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
8006 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
8007
8008 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
8009 {Chain, LHSElem, RHSElem, CC});
8010 Chains[i] = Scalars[i].getValue(1);
8011 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
8012 DAG.getBoolConstant(true, dl, EltVT, VT),
8013 DAG.getBoolConstant(false, dl, EltVT, VT));
8014 }
8015
8016 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
8017 ReplaceValueWith(SDValue(N, 1), NewChain);
8018
8019 return DAG.getBuildVector(WidenVT, dl, Scalars);
8020}
8021
8022SDValue DAGTypeLegalizer::WidenVecRes_PARTIAL_REDUCE_MLA(SDNode *N) {
8023 SDLoc DL(N);
8024 EVT VT = N->getValueType(0);
8025
8026 // Expand, then widen the result.
8027 SDValue Expanded = TLI.expandPartialReduceMLA(N, DAG);
8028 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
8029 return DAG.getInsertSubvector(DL, DAG.getPOISON(WideVT), Expanded, 0);
8030}
8031
8032//===----------------------------------------------------------------------===//
8033// Widen Vector Operand
8034//===----------------------------------------------------------------------===//
8035bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
8036 LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG));
8037 SDValue Res = SDValue();
8038
8039 // See if the target wants to custom widen this node.
8040 if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
8041 return false;
8042
8043 switch (N->getOpcode()) {
8044 default:
8045#ifndef NDEBUG
8046 dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
8047 N->dump(&DAG);
8048 dbgs() << "\n";
8049#endif
8050 report_fatal_error("do not know how to widen this operator's operand!");
8051
8052 case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
8053 case ISD::FAKE_USE:
8054 Res = WidenVecOp_FAKE_USE(N);
8055 break;
8056 case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
8057 case ISD::VECTOR_REPEAT:
8058 Res = WidenVecOp_VECTOR_REPEAT(N);
8059 break;
8060 case ISD::INSERT_SUBVECTOR: Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
8061 case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
8062 case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
8063 case ISD::STORE: Res = WidenVecOp_STORE(N); break;
8064 case ISD::ATOMIC_STORE:
8065 Res = WidenVecOp_ATOMIC_STORE(cast<AtomicSDNode>(N));
8066 break;
8067 case ISD::VP_STORE: Res = WidenVecOp_VP_STORE(N, OpNo); break;
8068 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8069 Res = WidenVecOp_VP_STRIDED_STORE(N, OpNo);
8070 break;
8074 Res = WidenVecOp_EXTEND_VECTOR_INREG(N);
8075 break;
8076 case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break;
8077 case ISD::MGATHER: Res = WidenVecOp_MGATHER(N, OpNo); break;
8078 case ISD::MSCATTER: Res = WidenVecOp_MSCATTER(N, OpNo); break;
8079 case ISD::VP_SCATTER: Res = WidenVecOp_VP_SCATTER(N, OpNo); break;
8080 case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
8081 case ISD::STRICT_FSETCC:
8082 case ISD::STRICT_FSETCCS: Res = WidenVecOp_STRICT_FSETCC(N); break;
8083 case ISD::VSELECT: Res = WidenVecOp_VSELECT(N); break;
8084 case ISD::FLDEXP:
8085 case ISD::FCOPYSIGN:
8086 case ISD::LROUND:
8087 case ISD::LLROUND:
8088 case ISD::LRINT:
8089 case ISD::LLRINT:
8090 Res = WidenVecOp_UnrollVectorOp(N);
8091 break;
8092 case ISD::IS_FPCLASS: Res = WidenVecOp_IS_FPCLASS(N); break;
8093
8094 case ISD::ANY_EXTEND:
8095 case ISD::SIGN_EXTEND:
8096 case ISD::ZERO_EXTEND:
8097 Res = WidenVecOp_EXTEND(N);
8098 break;
8099
8100 case ISD::SCMP:
8101 case ISD::UCMP:
8102 Res = WidenVecOp_CMP(N);
8103 break;
8104
8105 case ISD::FP_EXTEND:
8107 case ISD::FP_ROUND:
8109 case ISD::FP_TO_SINT:
8111 case ISD::FP_TO_UINT:
8113 case ISD::SINT_TO_FP:
8115 case ISD::UINT_TO_FP:
8117 case ISD::TRUNCATE:
8120 Res = WidenVecOp_Convert(N);
8121 break;
8122
8125 Res = WidenVecOp_FP_TO_XINT_SAT(N);
8126 break;
8127
8130 case ISD::VECREDUCE_ADD:
8131 case ISD::VECREDUCE_MUL:
8132 case ISD::VECREDUCE_AND:
8133 case ISD::VECREDUCE_OR:
8134 case ISD::VECREDUCE_XOR:
8145 Res = WidenVecOp_VECREDUCE(N);
8146 break;
8149 Res = WidenVecOp_VECREDUCE_SEQ(N);
8150 break;
8151 case ISD::VP_REDUCE_FADD:
8152 case ISD::VP_REDUCE_SEQ_FADD:
8153 case ISD::VP_REDUCE_FMUL:
8154 case ISD::VP_REDUCE_SEQ_FMUL:
8155 case ISD::VP_REDUCE_ADD:
8156 case ISD::VP_REDUCE_MUL:
8157 case ISD::VP_REDUCE_AND:
8158 case ISD::VP_REDUCE_OR:
8159 case ISD::VP_REDUCE_XOR:
8160 case ISD::VP_REDUCE_SMAX:
8161 case ISD::VP_REDUCE_SMIN:
8162 case ISD::VP_REDUCE_UMAX:
8163 case ISD::VP_REDUCE_UMIN:
8164 case ISD::VP_REDUCE_FMAX:
8165 case ISD::VP_REDUCE_FMIN:
8166 case ISD::VP_REDUCE_FMAXIMUM:
8167 case ISD::VP_REDUCE_FMINIMUM:
8168 Res = WidenVecOp_VP_REDUCE(N);
8169 break;
8170 case ISD::CTTZ_ELTS:
8172 Res = WidenVecOp_CttzElements(N);
8173 break;
8174 case ISD::VP_CTTZ_ELTS:
8175 case ISD::VP_CTTZ_ELTS_ZERO_POISON:
8176 Res = WidenVecOp_VP_CttzElements(N);
8177 break;
8179 Res = WidenVecOp_VECTOR_FIND_LAST_ACTIVE(N);
8180 break;
8182 Res = WidenVecOp_VECTOR_SHUFFLE_VAR(N, OpNo);
8183 break;
8184 case ISD::VECTOR_MATCH:
8185 Res = WidenVecOp_VECTOR_MATCH(N, OpNo);
8186 break;
8187 }
8188
8189 // If Res is null, the sub-method took care of registering the result.
8190 if (!Res.getNode()) return false;
8191
8192 // If the result is N, the sub-method updated N in place. Tell the legalizer
8193 // core about this.
8194 if (Res.getNode() == N)
8195 return true;
8196
8197
8198 if (N->isStrictFPOpcode())
8199 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
8200 "Invalid operand expansion");
8201 else
8202 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
8203 "Invalid operand expansion");
8204
8205 ReplaceValueWith(SDValue(N, 0), Res);
8206 return false;
8207}
8208
8209SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
8210 SDLoc DL(N);
8211 EVT VT = N->getValueType(0);
8212
8213 SDValue InOp = N->getOperand(0);
8214 assert(getTypeAction(InOp.getValueType()) ==
8216 "Unexpected type action");
8217 InOp = GetWidenedVector(InOp);
8220 "Input wasn't widened!");
8221
8222 // We may need to further widen the operand until it has the same total
8223 // vector size as the result.
8224 EVT InVT = InOp.getValueType();
8225 if (InVT.getSizeInBits() != VT.getSizeInBits()) {
8226 EVT InEltVT = InVT.getVectorElementType();
8227 for (EVT FixedVT : MVT::vector_valuetypes()) {
8228 EVT FixedEltVT = FixedVT.getVectorElementType();
8229 if (TLI.isTypeLegal(FixedVT) &&
8230 FixedVT.getSizeInBits() == VT.getSizeInBits() &&
8231 FixedEltVT == InEltVT) {
8232 assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
8233 "Not enough elements in the fixed type for the operand!");
8234 assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
8235 "We can't have the same type as we started with!");
8236 if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
8237 InOp = DAG.getInsertSubvector(DL, DAG.getPOISON(FixedVT), InOp, 0);
8238 else
8239 InOp = DAG.getExtractSubvector(DL, FixedVT, InOp, 0);
8240 break;
8241 }
8242 }
8243 InVT = InOp.getValueType();
8244 if (InVT.getSizeInBits() != VT.getSizeInBits())
8245 // We couldn't find a legal vector type that was a widening of the input
8246 // and could be extended in-register to the result type, so we have to
8247 // scalarize.
8248 return WidenVecOp_Convert(N);
8249 }
8250
8251 // Use special DAG nodes to represent the operation of extending the
8252 // low lanes.
8253 switch (N->getOpcode()) {
8254 default:
8255 llvm_unreachable("Extend legalization on extend operation!");
8256 case ISD::ANY_EXTEND:
8257 return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
8258 case ISD::SIGN_EXTEND:
8259 return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
8260 case ISD::ZERO_EXTEND:
8261 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
8262 }
8263}
8264
8265SDValue DAGTypeLegalizer::WidenVecOp_CMP(SDNode *N) {
8266 SDLoc dl(N);
8267
8268 EVT OpVT = N->getOperand(0).getValueType();
8269 EVT ResVT = N->getValueType(0);
8270 SDValue LHS = GetWidenedVector(N->getOperand(0));
8271 SDValue RHS = GetWidenedVector(N->getOperand(1));
8272
8273 // 1. EXTRACT_SUBVECTOR
8274 // 2. SIGN_EXTEND/ZERO_EXTEND
8275 // 3. CMP
8276 LHS = DAG.getExtractSubvector(dl, OpVT, LHS, 0);
8277 RHS = DAG.getExtractSubvector(dl, OpVT, RHS, 0);
8278
8279 // At this point the result type is guaranteed to be valid, so we can use it
8280 // as the operand type by extending it appropriately
8281 ISD::NodeType ExtendOpcode =
8282 N->getOpcode() == ISD::SCMP ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
8283 LHS = DAG.getNode(ExtendOpcode, dl, ResVT, LHS);
8284 RHS = DAG.getNode(ExtendOpcode, dl, ResVT, RHS);
8285
8286 return DAG.getNode(N->getOpcode(), dl, ResVT, LHS, RHS);
8287}
8288
8289SDValue DAGTypeLegalizer::WidenVecOp_UnrollVectorOp(SDNode *N) {
8290 // The result (and first input) is legal, but the second input is illegal.
8291 // We can't do much to fix that, so just unroll and let the extracts off of
8292 // the second input be widened as needed later.
8293 return DAG.UnrollVectorOp(N);
8294}
8295
8296SDValue DAGTypeLegalizer::WidenVecOp_IS_FPCLASS(SDNode *N) {
8297 SDLoc DL(N);
8298 EVT ResultVT = N->getValueType(0);
8299 SDValue Test = N->getOperand(1);
8300 SDValue WideArg = GetWidenedVector(N->getOperand(0));
8301
8302 // Process this node similarly to SETCC.
8303 EVT WideResultVT = getSetCCResultType(WideArg.getValueType());
8304 if (ResultVT.getScalarType() == MVT::i1)
8305 WideResultVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
8306 WideResultVT.getVectorNumElements());
8307
8308 SDValue WideNode = DAG.getNode(ISD::IS_FPCLASS, DL, WideResultVT,
8309 {WideArg, Test}, N->getFlags());
8310
8311 // Extract the needed results from the result vector.
8312 EVT ResVT =
8313 EVT::getVectorVT(*DAG.getContext(), WideResultVT.getVectorElementType(),
8314 ResultVT.getVectorNumElements());
8315 SDValue CC = DAG.getExtractSubvector(DL, ResVT, WideNode, 0);
8316
8317 EVT OpVT = N->getOperand(0).getValueType();
8318 ISD::NodeType ExtendCode =
8319 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
8320 return DAG.getNode(ExtendCode, DL, ResultVT, CC);
8321}
8322
8323SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
8324 // Since the result is legal and the input is illegal.
8325 EVT VT = N->getValueType(0);
8326 EVT EltVT = VT.getVectorElementType();
8327 SDLoc dl(N);
8328 SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
8329 assert(getTypeAction(InOp.getValueType()) ==
8331 "Unexpected type action");
8332 InOp = GetWidenedVector(InOp);
8333 EVT InVT = InOp.getValueType();
8334 unsigned Opcode = N->getOpcode();
8335
8336 // Helper to build a convert node with all scalar trailing operands.
8337 auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
8338 if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
8339 return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1), N->getOperand(2),
8340 N->getOperand(3));
8341 if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
8342 return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1));
8343 return DAG.getNode(Opcode, dl, VT, Op);
8344 };
8345
8346 // See if a widened result type would be legal, if so widen the node.
8347 // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
8348 EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
8349 InVT.getVectorElementCount());
8350 if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
8351 SDValue Res;
8352 if (N->isStrictFPOpcode()) {
8353 if (Opcode == ISD::STRICT_FP_ROUND)
8354 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
8355 { N->getOperand(0), InOp, N->getOperand(2) });
8356 else
8357 Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
8358 { N->getOperand(0), InOp });
8359 // Legalize the chain result - switch anything that used the old chain to
8360 // use the new one.
8361 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
8362 } else {
8363 Res = MakeConvertNode(WideVT, InOp);
8364 }
8365 return DAG.getExtractSubvector(dl, VT, Res, 0);
8366 }
8367
8368 EVT InEltVT = InVT.getVectorElementType();
8369
8370 // Unroll the convert into some scalar code and create a nasty build vector.
8371 unsigned NumElts = VT.getVectorNumElements();
8373 if (N->isStrictFPOpcode()) {
8374 SmallVector<SDValue, 4> NewOps(N->ops());
8375 SmallVector<SDValue, 32> OpChains;
8376 for (unsigned i=0; i < NumElts; ++i) {
8377 NewOps[1] = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
8378 Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
8379 OpChains.push_back(Ops[i].getValue(1));
8380 }
8381 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
8382 ReplaceValueWith(SDValue(N, 1), NewChain);
8383 } else {
8384 for (unsigned i = 0; i < NumElts; ++i) {
8385 SDValue Elt = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
8386 Ops[i] = MakeConvertNode(EltVT, Elt);
8387 }
8388 }
8389
8390 return DAG.getBuildVector(VT, dl, Ops);
8391}
8392
8393SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
8394 EVT DstVT = N->getValueType(0);
8395 SDValue Src = GetWidenedVector(N->getOperand(0));
8396 EVT SrcVT = Src.getValueType();
8397 ElementCount WideNumElts = SrcVT.getVectorElementCount();
8398 SDLoc dl(N);
8399
8400 // See if a widened result type would be legal, if so widen the node.
8401 EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
8402 DstVT.getVectorElementType(), WideNumElts);
8403 if (TLI.isTypeLegal(WideDstVT)) {
8404 SDValue Res =
8405 DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
8406 return DAG.getNode(
8407 ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
8408 DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
8409 }
8410
8411 // Give up and unroll.
8412 return DAG.UnrollVectorOp(N);
8413}
8414
8415SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
8416 EVT VT = N->getValueType(0);
8417 SDValue InOp = GetWidenedVector(N->getOperand(0));
8418 EVT InWidenVT = InOp.getValueType();
8419 SDLoc dl(N);
8420
8421 // Check if we can convert between two legal vector types and extract.
8422 TypeSize InWidenSize = InWidenVT.getSizeInBits();
8423 TypeSize Size = VT.getSizeInBits();
8424 // x86mmx is not an acceptable vector element type, so don't try.
8425 if (!VT.isVector() && VT != MVT::x86mmx &&
8426 InWidenSize.hasKnownScalarFactor(Size)) {
8427 unsigned NewNumElts = InWidenSize.getKnownScalarFactor(Size);
8428 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
8429 if (TLI.isTypeLegal(NewVT)) {
8430 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
8431 return DAG.getExtractVectorElt(dl, VT, BitOp, 0);
8432 }
8433 }
8434
8435 // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
8436 // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
8437 // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
8438 // having to copy via memory.
8439 if (VT.isVector()) {
8440 EVT EltVT = VT.getVectorElementType();
8441 unsigned EltSize = EltVT.getFixedSizeInBits();
8442 if (InWidenSize.isKnownMultipleOf(EltSize)) {
8443 ElementCount NewNumElts =
8444 (InWidenVT.getVectorElementCount() * InWidenVT.getScalarSizeInBits())
8445 .divideCoefficientBy(EltSize);
8446 EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
8447 if (TLI.isTypeLegal(NewVT)) {
8448 SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
8449 return DAG.getExtractSubvector(dl, VT, BitOp, 0);
8450 }
8451 }
8452 }
8453
8454 return CreateStackStoreLoad(InOp, VT);
8455}
8456
8457// Vectors with sizes that are not powers of 2 need to be widened to the
8458// next largest power of 2. For example, we may get a vector of 3 32-bit
8459// integers or of 6 16-bit integers, both of which have to be widened to a
8460// 128-bit vector.
8461SDValue DAGTypeLegalizer::WidenVecOp_FAKE_USE(SDNode *N) {
8462 SDValue WidenedOp = GetWidenedVector(N->getOperand(1));
8463 return DAG.getNode(ISD::FAKE_USE, SDLoc(), MVT::Other, N->getOperand(0),
8464 WidenedOp);
8465}
8466
8467SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
8468 EVT VT = N->getValueType(0);
8469 EVT EltVT = VT.getVectorElementType();
8470 EVT InVT = N->getOperand(0).getValueType();
8471 SDLoc dl(N);
8472
8473 // If the widen width for this operand is the same as the width of the concat
8474 // and all but the first operand is undef, just use the widened operand.
8475 unsigned NumOperands = N->getNumOperands();
8476 if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
8477 unsigned i;
8478 for (i = 1; i < NumOperands; ++i)
8479 if (!N->getOperand(i).isUndef())
8480 break;
8481
8482 if (i == NumOperands)
8483 return GetWidenedVector(N->getOperand(0));
8484 }
8485
8486 if (VT.isScalableVector()) {
8487 SDValue Result = DAG.getPOISON(VT);
8488 unsigned NumInElts = InVT.getVectorMinNumElements();
8489 for (unsigned i = 0; i < NumOperands; ++i) {
8490 SDValue InOp = GetWidenedVector(N->getOperand(i));
8491 if (InOp.getValueType() != InVT)
8492 InOp = DAG.getExtractSubvector(dl, InVT, InOp, 0);
8493 Result = DAG.getInsertSubvector(dl, Result, InOp, i * NumInElts);
8494 }
8495 return Result;
8496 }
8497
8498 // Otherwise, fall back to a nasty build vector.
8499 unsigned NumElts = VT.getVectorNumElements();
8501
8502 unsigned NumInElts = InVT.getVectorNumElements();
8503
8504 unsigned Idx = 0;
8505 for (unsigned i=0; i < NumOperands; ++i) {
8506 SDValue InOp = N->getOperand(i);
8507 assert(getTypeAction(InOp.getValueType()) ==
8509 "Unexpected type action");
8510 InOp = GetWidenedVector(InOp);
8511 for (unsigned j = 0; j < NumInElts; ++j)
8512 Ops[Idx++] = DAG.getExtractVectorElt(dl, EltVT, InOp, j);
8513 }
8514 return DAG.getBuildVector(VT, dl, Ops);
8515}
8516
8517SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_REPEAT(SDNode *N) {
8518 SDLoc DL(N);
8519 EVT VT = N->getValueType(0);
8520 SDValue Src = N->getOperand(0);
8521 EVT SrcVT = Src.getValueType();
8522 EVT WidenedSrcVT = TLI.getTypeToTransformTo(*DAG.getContext(), SrcVT);
8523
8524 if (!WidenedSrcVT.getVectorElementCount().hasKnownScalarFactor(
8525 SrcVT.getVectorElementCount()))
8527 "Cannot widen VECTOR_REPEAT operand to an ElementCount that's not "
8528 "a known scalar multiple of the input ElementCount.");
8529
8530 // Repeat the original source because the extra lanes of its widened value
8531 // are unspecified.
8532 unsigned NumConcat =
8533 WidenedSrcVT.getVectorNumElements() / SrcVT.getVectorNumElements();
8534 SmallVector<SDValue, 8> Ops(NumConcat, Src);
8535 SDValue WidenedSrc = DAG.getNode(ISD::CONCAT_VECTORS, DL, WidenedSrcVT, Ops);
8536 EVT WidenedVT = VT.changeVectorElementCount(
8537 *DAG.getContext(),
8539 SDValue Widened = DAG.getNode(ISD::VECTOR_REPEAT, DL, WidenedVT, WidenedSrc);
8540 return DAG.getExtractSubvector(DL, VT, Widened, 0);
8541}
8542
8543SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
8544 EVT VT = N->getValueType(0);
8545 SDValue SubVec = N->getOperand(1);
8546 SDValue InVec = N->getOperand(0);
8547
8548 EVT OrigVT = SubVec.getValueType();
8549 SubVec = GetWidenedVector(SubVec);
8550 EVT SubVT = SubVec.getValueType();
8551
8552 // Whether or not all the elements of the widened SubVec will be inserted into
8553 // valid indices of VT.
8554 bool IndicesValid = false;
8555 // If we statically know that VT can fit SubVT, the indices are valid.
8556 if (VT.knownBitsGE(SubVT))
8557 IndicesValid = true;
8558 else if (VT.isScalableVector() && SubVT.isFixedLengthVector()) {
8559 // Otherwise, if we're inserting a fixed vector into a scalable vector and
8560 // we know the minimum vscale we can work out if it's valid ourselves.
8561 Attribute Attr = DAG.getMachineFunction().getFunction().getFnAttribute(
8562 Attribute::VScaleRange);
8563 if (Attr.isValid()) {
8564 unsigned VScaleMin = Attr.getVScaleRangeMin();
8565 if (VT.getSizeInBits().getKnownMinValue() * VScaleMin >=
8566 SubVT.getFixedSizeInBits())
8567 IndicesValid = true;
8568 }
8569 }
8570
8571 if (!IndicesValid)
8573 "Don't know how to widen the operands for INSERT_SUBVECTOR");
8574
8575 SDLoc DL(N);
8576
8577 // We need to make sure that the indices are still valid, otherwise we might
8578 // widen what was previously well-defined to something undefined.
8579 if (InVec.isUndef() && N->getConstantOperandVal(2) == 0)
8580 return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, InVec, SubVec,
8581 N->getOperand(2));
8582
8583 if (OrigVT.isScalableVector()) {
8584 // When the widened types match, overwriting the start of a vector is
8585 // effectively a merge operation that can be implement as a vselect.
8586 if (SubVT == VT && N->getConstantOperandVal(2) == 0) {
8587 SDValue Mask =
8588 DAG.getMaskFromElementCount(DL, VT, OrigVT.getVectorElementCount());
8589 return DAG.getNode(ISD::VSELECT, DL, VT, Mask, SubVec, InVec);
8590 }
8591
8592 // Fallback to inserting through memory.
8593 Align Alignment = DAG.getReducedAlign(VT, /*UseABI=*/false);
8594 SDValue StackPtr = DAG.CreateStackTemporary(VT.getStoreSize(), Alignment);
8595 MachineFunction &MF = DAG.getMachineFunction();
8596 int FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
8597 auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
8598
8599 MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
8602 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
8605
8606 // Write out the vector being inserting into.
8607 SDValue Ch =
8608 DAG.getStore(DAG.getEntryNode(), DL, InVec, StackPtr, StoreMMO);
8609
8610 // Build a mask to match the length of the sub-vector.
8611 SDValue Mask =
8612 DAG.getMaskFromElementCount(DL, SubVT, OrigVT.getVectorElementCount());
8613
8614 // Overwrite the sub-vector at the required offset.
8615 SDValue SubVecPtr =
8616 TLI.getVectorSubVecPointer(DAG, StackPtr, VT, OrigVT, N->getOperand(2));
8617 Ch = DAG.getMaskedStore(Ch, DL, SubVec, SubVecPtr,
8618 DAG.getPOISON(SubVecPtr.getValueType()), Mask, VT,
8619 StoreMMO, ISD::UNINDEXED, ISD::NON_EXTLOAD);
8620
8621 // Read back the result.
8622 return DAG.getLoad(VT, DL, Ch, StackPtr, LoadMMO);
8623 }
8624
8625 // If the operands can't be widened legally, just replace the INSERT_SUBVECTOR
8626 // with a series of INSERT_VECTOR_ELT
8627 unsigned Idx = N->getConstantOperandVal(2);
8628
8629 SDValue InsertElt = InVec;
8630 for (unsigned I = 0, E = OrigVT.getVectorNumElements(); I != E; ++I) {
8631 SDValue ExtractElt =
8632 DAG.getExtractVectorElt(DL, VT.getVectorElementType(), SubVec, I);
8633 InsertElt = DAG.getInsertVectorElt(DL, InsertElt, ExtractElt, I + Idx);
8634 }
8635
8636 return InsertElt;
8637}
8638
8639SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
8640 SDValue InOp = GetWidenedVector(N->getOperand(0));
8641 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
8642 N->getValueType(0), InOp, N->getOperand(1));
8643}
8644
8645SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
8646 SDValue InOp = GetWidenedVector(N->getOperand(0));
8647 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
8648 N->getValueType(0), InOp, N->getOperand(1));
8649}
8650
8651SDValue DAGTypeLegalizer::WidenVecOp_EXTEND_VECTOR_INREG(SDNode *N) {
8652 SDLoc DL(N);
8653 EVT ResVT = N->getValueType(0);
8654
8655 // Widen the input as requested by the legalizer.
8656 SDValue WideInOp = GetWidenedVector(N->getOperand(0));
8657 EVT WideInVT = WideInOp.getValueType();
8658
8659 // Simple case: if widened input is still smaller than or equal to result,
8660 // just use it directly.
8661 if (WideInVT.getSizeInBits() <= ResVT.getSizeInBits())
8662 return DAG.getNode(N->getOpcode(), DL, ResVT, WideInOp);
8663
8664 // EXTEND_VECTOR_INREG requires input bits <= result bits.
8665 // If widening makes the input larger than the original result, widen the
8666 // result to match, then extract back down.
8667 EVT ResEltVT = ResVT.getVectorElementType();
8668 unsigned EltBits = ResEltVT.getSizeInBits();
8669 assert((WideInVT.getSizeInBits() % EltBits) == 0 &&
8670 "Widened input size must be a multiple of result element size");
8671
8672 unsigned WideNumElts = WideInVT.getSizeInBits() / EltBits;
8673 EVT WideResVT = EVT::getVectorVT(*DAG.getContext(), ResEltVT, WideNumElts);
8674
8675 SDValue WideRes = DAG.getNode(N->getOpcode(), DL, WideResVT, WideInOp);
8676 return DAG.getExtractSubvector(DL, ResVT, WideRes, 0);
8677}
8678
8679SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
8680 // We have to widen the value, but we want only to store the original
8681 // vector type.
8682 StoreSDNode *ST = cast<StoreSDNode>(N);
8683
8684 if (!ST->getMemoryVT().getScalarType().isByteSized())
8685 return TLI.scalarizeVectorStore(ST, DAG);
8686
8687 if (ST->isTruncatingStore())
8688 return TLI.scalarizeVectorStore(ST, DAG);
8689
8690 // Generate a vector-predicated store if it is custom/legal on the target.
8691 // To avoid possible recursion, only do this if the widened mask type is
8692 // legal.
8693 // FIXME: Not all targets may support EVL in VP_STORE. These will have been
8694 // removed from the IR by the ExpandVectorPredication pass but we're
8695 // reintroducing them here.
8696 SDValue StVal = ST->getValue();
8697 EVT StVT = StVal.getValueType();
8698 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
8699 EVT WideMaskVT = getSetCCResultType(WideVT);
8700
8701 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8702 TLI.isTypeLegal(WideMaskVT)) {
8703 // Widen the value.
8704 SDLoc DL(N);
8705 StVal = GetWidenedVector(StVal);
8706 SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
8707 SDValue EVL = DAG.getElementCount(DL, TLI.getVPExplicitVectorLengthTy(),
8708 StVT.getVectorElementCount());
8709 return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(),
8710 ST->getOffset(), Mask, EVL, StVT, ST->getMemOperand(),
8711 ST->getAddressingMode());
8712 }
8713
8715 if (GenWidenVectorStores(StChain, ST)) {
8716 if (StChain.size() == 1)
8717 return StChain[0];
8718
8719 return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
8720 }
8721
8722 if (StVT.isVector()) {
8723 // If all else fails replace the store with a wide masked store.
8724 SDLoc DL(N);
8725 SDValue WideStVal = GetWidenedVector(StVal);
8726 SDValue Mask =
8727 DAG.getMaskFromElementCount(DL, WideVT, StVT.getVectorElementCount());
8728
8729 return DAG.getMaskedStore(ST->getChain(), DL, WideStVal, ST->getBasePtr(),
8730 ST->getOffset(), Mask, ST->getMemoryVT(),
8731 ST->getMemOperand(), ST->getAddressingMode(),
8732 ST->isTruncatingStore());
8733 }
8734
8735 report_fatal_error("Unable to widen vector store");
8736}
8737
8738SDValue DAGTypeLegalizer::WidenVecOp_ATOMIC_STORE(AtomicSDNode *ST) {
8739 EVT StVT = ST->getMemoryVT();
8740 SDLoc dl(ST);
8741
8742 SDValue StVal = GetWidenedVector(ST->getVal());
8743 EVT WidenVT = StVal.getValueType();
8744
8745 TypeSize StWidth = StVT.getSizeInBits();
8746 TypeSize WidenWidth = WidenVT.getSizeInBits();
8747 TypeSize WidthDiff = WidenWidth - StWidth;
8748
8749 // Find the vector type that can store the original memory width in one
8750 // atomic operation. Pass StAlign=0 (like atomic loads); a real align would
8751 // let findMemType widen the access past the value (e.g. <2 x i8> at align 4
8752 // implies a 4-byte movl, writing undef bytes past its object).
8753 std::optional<EVT> FirstVT =
8754 findMemType(DAG, TLI, StWidth.getKnownMinValue(), WidenVT, /*StAlign=*/0,
8755 WidthDiff.getKnownMinValue());
8756 if (!FirstVT)
8757 return SDValue();
8758
8759 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
8760
8761 SDValue StOp =
8762 coerceStoredValue(StVal, *FirstVT, WidenVT, FirstVTWidth, dl, DAG);
8763
8764 return DAG.getAtomic(ISD::ATOMIC_STORE, dl, *FirstVT, ST->getChain(), StOp,
8765 ST->getBasePtr(), ST->getMemOperand());
8766}
8767
8768SDValue DAGTypeLegalizer::WidenVecOp_VP_STORE(SDNode *N, unsigned OpNo) {
8769 assert((OpNo == 1 || OpNo == 3) &&
8770 "Can widen only data or mask operand of vp_store");
8771 VPStoreSDNode *ST = cast<VPStoreSDNode>(N);
8772 SDValue Mask = ST->getMask();
8773 SDValue StVal = ST->getValue();
8774 SDLoc dl(N);
8775
8776 if (OpNo == 1) {
8777 // Widen the value.
8778 StVal = GetWidenedVector(StVal);
8779
8780 // We only handle the case where the mask needs widening to an
8781 // identically-sized type as the vector inputs.
8782 assert(getTypeAction(Mask.getValueType()) ==
8784 "Unable to widen VP store");
8785 Mask = GetWidenedVector(Mask);
8786 } else {
8787 Mask = GetWidenedVector(Mask);
8788
8789 // We only handle the case where the stored value needs widening to an
8790 // identically-sized type as the mask.
8791 assert(getTypeAction(StVal.getValueType()) ==
8793 "Unable to widen VP store");
8794 StVal = GetWidenedVector(StVal);
8795 }
8796
8797 assert(Mask.getValueType().getVectorElementCount() ==
8799 "Mask and data vectors should have the same number of elements");
8800 return DAG.getStoreVP(ST->getChain(), dl, StVal, ST->getBasePtr(),
8801 ST->getOffset(), Mask, ST->getVectorLength(),
8802 ST->getMemoryVT(), ST->getMemOperand(),
8803 ST->getAddressingMode(), ST->isTruncatingStore(),
8804 ST->isCompressingStore());
8805}
8806
8807SDValue DAGTypeLegalizer::WidenVecOp_VP_STRIDED_STORE(SDNode *N,
8808 unsigned OpNo) {
8809 assert((OpNo == 1 || OpNo == 4) &&
8810 "Can widen only data or mask operand of vp_strided_store");
8811 VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
8812 SDValue Mask = SST->getMask();
8813 SDValue StVal = SST->getValue();
8814 SDLoc DL(N);
8815
8816 if (OpNo == 1)
8817 assert(getTypeAction(Mask.getValueType()) ==
8819 "Unable to widen VP strided store");
8820 else
8821 assert(getTypeAction(StVal.getValueType()) ==
8823 "Unable to widen VP strided store");
8824
8825 StVal = GetWidenedVector(StVal);
8826 Mask = GetWidenedVector(Mask);
8827
8829 Mask.getValueType().getVectorElementCount() &&
8830 "Data and mask vectors should have the same number of elements");
8831
8832 return DAG.getStridedStoreVP(
8833 SST->getChain(), DL, StVal, SST->getBasePtr(), SST->getOffset(),
8834 SST->getStride(), Mask, SST->getVectorLength(), SST->getMemoryVT(),
8835 SST->getMemOperand(), SST->getAddressingMode(), SST->isTruncatingStore(),
8836 SST->isCompressingStore());
8837}
8838
8839SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
8840 assert((OpNo == 1 || OpNo == 4) &&
8841 "Can widen only data or mask operand of mstore");
8842 MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
8843 SDValue Mask = MST->getMask();
8844 EVT MaskVT = Mask.getValueType();
8845 SDValue StVal = MST->getValue();
8846 EVT VT = StVal.getValueType();
8847 SDLoc dl(N);
8848
8849 EVT WideVT, WideMaskVT;
8850 if (OpNo == 1) {
8851 // Widen the value.
8852 StVal = GetWidenedVector(StVal);
8853
8854 WideVT = StVal.getValueType();
8855 WideMaskVT =
8856 EVT::getVectorVT(*DAG.getContext(), MaskVT.getVectorElementType(),
8857 WideVT.getVectorElementCount());
8858 } else {
8859 WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
8860
8861 EVT ValueVT = StVal.getValueType();
8862 WideVT = EVT::getVectorVT(*DAG.getContext(), ValueVT.getVectorElementType(),
8863 WideMaskVT.getVectorElementCount());
8864 }
8865
8866 if (TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
8867 TLI.isTypeLegal(WideMaskVT) && !MST->isCompressingStore()) {
8868 Mask = DAG.getInsertSubvector(dl, DAG.getPOISON(WideMaskVT), Mask, 0);
8869 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
8871 return DAG.getStoreVP(MST->getChain(), dl, StVal, MST->getBasePtr(),
8872 MST->getOffset(), Mask, EVL, MST->getMemoryVT(),
8873 MST->getMemOperand(), MST->getAddressingMode());
8874 }
8875
8876 if (OpNo == 1) {
8877 // The mask should be widened as well.
8878 Mask = ModifyToType(Mask, WideMaskVT, true);
8879 } else {
8880 // Widen the mask.
8881 Mask = ModifyToType(Mask, WideMaskVT, true);
8882
8883 StVal = ModifyToType(StVal, WideVT);
8884 }
8885
8886 assert(Mask.getValueType().getVectorElementCount() ==
8888 "Mask and data vectors should have the same number of elements");
8889 return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
8890 MST->getOffset(), Mask, MST->getMemoryVT(),
8891 MST->getMemOperand(), MST->getAddressingMode(),
8892 false, MST->isCompressingStore());
8893}
8894
8895SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
8896 assert(OpNo == 4 && "Can widen only the index of mgather");
8897 auto *MG = cast<MaskedGatherSDNode>(N);
8898 SDValue DataOp = MG->getPassThru();
8899 SDValue Mask = MG->getMask();
8900 SDValue Scale = MG->getScale();
8901
8902 // Just widen the index. It's allowed to have extra elements.
8903 SDValue Index = GetWidenedVector(MG->getIndex());
8904
8905 SDLoc dl(N);
8906 SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
8907 Scale};
8908 SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
8909 MG->getMemOperand(), MG->getIndexType(),
8910 MG->getExtensionType());
8911 ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
8912 ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
8913 return SDValue();
8914}
8915
8916SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
8917 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
8918 SDValue DataOp = MSC->getValue();
8919 SDValue Mask = MSC->getMask();
8920 SDValue Index = MSC->getIndex();
8921 SDValue Scale = MSC->getScale();
8922 EVT WideMemVT = MSC->getMemoryVT();
8923
8924 if (OpNo == 1) {
8925 DataOp = GetWidenedVector(DataOp);
8926 ElementCount WideEC = DataOp.getValueType().getVectorElementCount();
8927
8928 // Widen index.
8929 EVT IndexVT = Index.getValueType();
8930 EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
8931 IndexVT.getVectorElementType(), WideEC);
8932 Index = ModifyToType(Index, WideIndexVT);
8933
8934 // The mask should be widened as well.
8935 EVT MaskVT = Mask.getValueType();
8936 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
8937 MaskVT.getVectorElementType(), WideEC);
8938 Mask = ModifyToType(Mask, WideMaskVT, true);
8939
8940 // Widen the MemoryType
8941 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8942 MSC->getMemoryVT().getScalarType(), WideEC);
8943 } else if (OpNo == 4) {
8944 // Just widen the index. It's allowed to have extra elements.
8945 Index = GetWidenedVector(Index);
8946 } else
8947 llvm_unreachable("Can't widen this operand of mscatter");
8948
8949 SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
8950 Scale};
8951 return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
8952 Ops, MSC->getMemOperand(), MSC->getIndexType(),
8953 MSC->isTruncatingStore());
8954}
8955
8956SDValue DAGTypeLegalizer::WidenVecOp_VP_SCATTER(SDNode *N, unsigned OpNo) {
8957 VPScatterSDNode *VPSC = cast<VPScatterSDNode>(N);
8958 SDValue DataOp = VPSC->getValue();
8959 SDValue Mask = VPSC->getMask();
8960 SDValue Index = VPSC->getIndex();
8961 SDValue Scale = VPSC->getScale();
8962 EVT WideMemVT = VPSC->getMemoryVT();
8963
8964 if (OpNo == 1) {
8965 DataOp = GetWidenedVector(DataOp);
8966 Index = GetWidenedVector(Index);
8967 const auto WideEC = DataOp.getValueType().getVectorElementCount();
8968 Mask = GetWidenedMask(Mask, WideEC);
8969 WideMemVT = EVT::getVectorVT(*DAG.getContext(),
8970 VPSC->getMemoryVT().getScalarType(), WideEC);
8971 } else if (OpNo == 3) {
8972 // Just widen the index. It's allowed to have extra elements.
8973 Index = GetWidenedVector(Index);
8974 } else
8975 llvm_unreachable("Can't widen this operand of VP_SCATTER");
8976
8977 SDValue Ops[] = {
8978 VPSC->getChain(), DataOp, VPSC->getBasePtr(), Index, Scale, Mask,
8979 VPSC->getVectorLength()};
8980 return DAG.getScatterVP(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N), Ops,
8981 VPSC->getMemOperand(), VPSC->getIndexType());
8982}
8983
8984SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
8985 SDValue InOp0 = GetWidenedVector(N->getOperand(0));
8986 SDValue InOp1 = GetWidenedVector(N->getOperand(1));
8987 SDLoc dl(N);
8988 EVT VT = N->getValueType(0);
8989
8990 // WARNING: In this code we widen the compare instruction with garbage.
8991 // This garbage may contain denormal floats which may be slow. Is this a real
8992 // concern ? Should we zero the unused lanes if this is a float compare ?
8993
8994 // Get a new SETCC node to compare the newly widened operands.
8995 // Only some of the compared elements are legal.
8996 EVT SVT = getSetCCResultType(InOp0.getValueType());
8997 // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
8998 if (VT.getScalarType() == MVT::i1)
8999 SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
9000 SVT.getVectorElementCount());
9001
9002 SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
9003 SVT, InOp0, InOp1, N->getOperand(2));
9004
9005 // Extract the needed results from the result vector.
9006 EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
9009 SDValue CC = DAG.getExtractSubvector(dl, ResVT, WideSETCC, 0);
9010
9011 EVT OpVT = N->getOperand(0).getValueType();
9012 ISD::NodeType ExtendCode =
9013 TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
9014 return DAG.getNode(ExtendCode, dl, VT, CC);
9015}
9016
9017SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
9018 SDValue Chain = N->getOperand(0);
9019 SDValue LHS = GetWidenedVector(N->getOperand(1));
9020 SDValue RHS = GetWidenedVector(N->getOperand(2));
9021 SDValue CC = N->getOperand(3);
9022 SDLoc dl(N);
9023
9024 EVT VT = N->getValueType(0);
9025 EVT EltVT = VT.getVectorElementType();
9026 EVT TmpEltVT = LHS.getValueType().getVectorElementType();
9027 unsigned NumElts = VT.getVectorNumElements();
9028
9029 // Unroll into a build vector.
9030 SmallVector<SDValue, 8> Scalars(NumElts);
9031 SmallVector<SDValue, 8> Chains(NumElts);
9032
9033 for (unsigned i = 0; i != NumElts; ++i) {
9034 SDValue LHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, LHS, i);
9035 SDValue RHSElem = DAG.getExtractVectorElt(dl, TmpEltVT, RHS, i);
9036
9037 Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
9038 {Chain, LHSElem, RHSElem, CC});
9039 Chains[i] = Scalars[i].getValue(1);
9040 Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
9041 DAG.getBoolConstant(true, dl, EltVT, VT),
9042 DAG.getBoolConstant(false, dl, EltVT, VT));
9043 }
9044
9045 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
9046 ReplaceValueWith(SDValue(N, 1), NewChain);
9047
9048 return DAG.getBuildVector(VT, dl, Scalars);
9049}
9050
9051static unsigned getExtendForIntVecReduction(unsigned Opc) {
9052 switch (Opc) {
9053 default:
9054 llvm_unreachable("Expected integer vector reduction");
9055 case ISD::VECREDUCE_ADD:
9056 case ISD::VECREDUCE_MUL:
9057 case ISD::VECREDUCE_AND:
9058 case ISD::VECREDUCE_OR:
9059 case ISD::VECREDUCE_XOR:
9060 return ISD::ANY_EXTEND;
9063 return ISD::SIGN_EXTEND;
9066 return ISD::ZERO_EXTEND;
9067 }
9068}
9069
9070SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
9071 SDLoc dl(N);
9072 SDValue Op = GetWidenedVector(N->getOperand(0));
9073 EVT VT = N->getValueType(0);
9074 EVT OrigVT = N->getOperand(0).getValueType();
9075 EVT WideVT = Op.getValueType();
9076 EVT ElemVT = OrigVT.getVectorElementType();
9077 SDNodeFlags Flags = N->getFlags();
9078
9079 unsigned Opc = N->getOpcode();
9080 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
9081 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
9082 assert(NeutralElem && "Neutral element must exist");
9083
9084 // Pad the vector with the neutral element.
9085 unsigned OrigElts = OrigVT.getVectorMinNumElements();
9086 unsigned WideElts = WideVT.getVectorMinNumElements();
9087
9088 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
9089 // needing to pad the source vector, because the inactive lanes can simply be
9090 // disabled and not contribute to the result.
9091 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
9092 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
9093 SDValue Start = NeutralElem;
9094 if (VT.isInteger())
9095 Start = DAG.getNode(getExtendForIntVecReduction(Opc), dl, VT, Start);
9096 assert(Start.getValueType() == VT);
9097 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
9098 WideVT.getVectorElementCount());
9099 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
9100 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
9101 OrigVT.getVectorElementCount());
9102 return DAG.getNode(*VPOpcode, dl, VT, {Start, Op, Mask, EVL}, Flags);
9103 }
9104
9105 if (WideVT.isScalableVector()) {
9106 unsigned GCD = std::gcd(OrigElts, WideElts);
9107 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
9109 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
9110 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
9111 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
9112 return DAG.getNode(Opc, dl, VT, Op, Flags);
9113 }
9114
9115 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
9116 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
9117
9118 return DAG.getNode(Opc, dl, VT, Op, Flags);
9119}
9120
9121SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
9122 SDLoc dl(N);
9123 SDValue AccOp = N->getOperand(0);
9124 SDValue VecOp = N->getOperand(1);
9125 SDValue Op = GetWidenedVector(VecOp);
9126
9127 EVT VT = N->getValueType(0);
9128 EVT OrigVT = VecOp.getValueType();
9129 EVT WideVT = Op.getValueType();
9130 EVT ElemVT = OrigVT.getVectorElementType();
9131 SDNodeFlags Flags = N->getFlags();
9132
9133 unsigned Opc = N->getOpcode();
9134 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
9135 SDValue NeutralElem = DAG.getIdentityElement(BaseOpc, dl, ElemVT, Flags);
9136
9137 // Pad the vector with the neutral element.
9138 unsigned OrigElts = OrigVT.getVectorMinNumElements();
9139 unsigned WideElts = WideVT.getVectorMinNumElements();
9140
9141 // Generate a vp.reduce_op if it is custom/legal for the target. This avoids
9142 // needing to pad the source vector, because the inactive lanes can simply be
9143 // disabled and not contribute to the result.
9144 if (auto VPOpcode = ISD::getVPForBaseOpcode(Opc);
9145 VPOpcode && TLI.isOperationLegalOrCustom(*VPOpcode, WideVT)) {
9146 EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
9147 WideVT.getVectorElementCount());
9148 SDValue Mask = DAG.getAllOnesConstant(dl, WideMaskVT);
9149 SDValue EVL = DAG.getElementCount(dl, TLI.getVPExplicitVectorLengthTy(),
9150 OrigVT.getVectorElementCount());
9151 return DAG.getNode(*VPOpcode, dl, VT, {AccOp, Op, Mask, EVL}, Flags);
9152 }
9153
9154 if (WideVT.isScalableVector()) {
9155 unsigned GCD = std::gcd(OrigElts, WideElts);
9156 EVT SplatVT = EVT::getVectorVT(*DAG.getContext(), ElemVT,
9158 SDValue SplatNeutral = DAG.getSplatVector(SplatVT, dl, NeutralElem);
9159 for (unsigned Idx = OrigElts; Idx < WideElts; Idx = Idx + GCD)
9160 Op = DAG.getInsertSubvector(dl, Op, SplatNeutral, Idx);
9161 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
9162 }
9163
9164 for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
9165 Op = DAG.getInsertVectorElt(dl, Op, NeutralElem, Idx);
9166
9167 return DAG.getNode(Opc, dl, VT, AccOp, Op, Flags);
9168}
9169
9170SDValue DAGTypeLegalizer::WidenVecOp_VP_REDUCE(SDNode *N) {
9171 assert(N->isVPOpcode() && "Expected VP opcode");
9172
9173 SDLoc dl(N);
9174 SDValue Op = GetWidenedVector(N->getOperand(1));
9175 SDValue Mask = GetWidenedMask(N->getOperand(2),
9176 Op.getValueType().getVectorElementCount());
9177
9178 return DAG.getNode(N->getOpcode(), dl, N->getValueType(0),
9179 {N->getOperand(0), Op, Mask, N->getOperand(3)},
9180 N->getFlags());
9181}
9182
9183SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
9184 // This only gets called in the case that the left and right inputs and
9185 // result are of a legal odd vector type, and the condition is illegal i1 of
9186 // the same odd width that needs widening.
9187 EVT VT = N->getValueType(0);
9188 assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));
9189
9190 SDValue Cond = GetWidenedVector(N->getOperand(0));
9191 SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
9192 SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
9193 SDLoc DL(N);
9194
9195 SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
9196 LeftIn, RightIn);
9197 return DAG.getExtractSubvector(DL, VT, Select, 0);
9198}
9199
9200SDValue DAGTypeLegalizer::WidenVecOp_CttzElements(SDNode *N) {
9201 SDLoc DL(N);
9202 SDValue Source = N->getOperand(0);
9203 EVT SourceVT = Source.getValueType();
9204 EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), SourceVT);
9205
9206 SDValue WideSource;
9207 if (N->getOpcode() == ISD::CTTZ_ELTS_ZERO_POISON) {
9208 WideSource = GetWidenedVector(Source);
9209 } else {
9210 // Pad the widened portion with all-ones so the extra lanes appear as
9211 // active (non-zero) elements and do not contribute trailing zeros.
9212 SDValue AllOnes = DAG.getAllOnesConstant(DL, WideVT);
9213 if (WideVT.isFixedLengthVector() &&
9214 getTypeAction(WideVT) == TargetLowering::TypeSplitVector) {
9215 WideSource = GetWidenedVector(Source);
9216 unsigned WideElts = WideVT.getVectorNumElements();
9217 SmallVector<int> Mask(WideElts);
9218 std::iota(Mask.begin(), Mask.end(), 0);
9219 for (unsigned I = SourceVT.getVectorNumElements(); I != WideElts; ++I)
9220 Mask[I] += WideElts;
9221 WideSource = DAG.getVectorShuffle(WideVT, DL, WideSource, AllOnes, Mask);
9222 } else {
9223 WideSource = DAG.getInsertSubvector(DL, AllOnes, Source, 0);
9224 }
9225 }
9226
9227 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0), WideSource,
9228 N->getFlags());
9229}
9230
9231SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
9232 SDLoc DL(N);
9233 SDValue Source = GetWidenedVector(N->getOperand(0));
9234 EVT SrcVT = Source.getValueType();
9235 SDValue Mask =
9236 GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
9237
9238 return DAG.getNode(N->getOpcode(), DL, N->getValueType(0),
9239 {Source, Mask, N->getOperand(2)}, N->getFlags());
9240}
9241
9242SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_FIND_LAST_ACTIVE(SDNode *N) {
9243 SDLoc DL(N);
9244 SDValue Mask = N->getOperand(0);
9245 EVT OrigMaskVT = Mask.getValueType();
9246 SDValue WideMask = GetWidenedVector(Mask);
9247 EVT WideMaskVT = WideMask.getValueType();
9248
9249 // Pad the mask with zeros to ensure inactive lanes don't affect the result.
9250 unsigned OrigElts = OrigMaskVT.getVectorNumElements();
9251 unsigned WideElts = WideMaskVT.getVectorNumElements();
9252 if (OrigElts != WideElts) {
9253 SDValue ZeroMask = DAG.getConstant(0, DL, WideMaskVT);
9254 WideMask = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WideMaskVT, ZeroMask,
9255 Mask, DAG.getVectorIdxConstant(0, DL));
9256 }
9257
9258 return DAG.getNode(ISD::VECTOR_FIND_LAST_ACTIVE, DL, N->getValueType(0),
9259 WideMask);
9260}
9261
9262SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_SHUFFLE_VAR(SDNode *N,
9263 unsigned OpNo) {
9264 // The only possibility for an illegal operand is the mask, since result type
9265 // legalization would have handled this node already otherwise.
9266 assert(OpNo == 1 && "Illegal operand must be mask");
9267 // TODO: Legalize the mask type instead once a target lowers the node.
9268 return TLI.expandVECTOR_SHUFFLE_VAR(N, DAG);
9269}
9270
9271SDValue DAGTypeLegalizer::WidenVecOp_VECTOR_MATCH(SDNode *N, unsigned OpNo) {
9272 if (OpNo == 0) {
9273 SDLoc DL(N);
9274 EVT ResVT = N->getValueType(0);
9275 EVT SourceVT = N->getOperand(0).getValueType();
9276 EVT WideSourceVT = TLI.getTypeToTransformTo(*DAG.getContext(), SourceVT);
9277 EVT WidenVT =
9278 EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
9279 WideSourceVT.getVectorElementCount());
9280
9281 SDValue WideSource = DAG.getInsertSubvector(DL, DAG.getUNDEF(WideSourceVT),
9282 N->getOperand(0), 0);
9283 SDValue WideMask = DAG.getInsertSubvector(
9284 DL, DAG.getConstant(0, DL, WidenVT), N->getOperand(2), 0);
9285 SDValue WideMatch = DAG.getNode(ISD::VECTOR_MATCH, DL, WidenVT, WideSource,
9286 N->getOperand(1), WideMask, N->getFlags());
9287 return DAG.getExtractSubvector(DL, ResVT, WideMatch, 0);
9288 }
9289
9290 // Note: The Mask (OpNo == 2) should be widened with the result.
9291 assert(OpNo == 1 && "Unexpected VECTOR_MATCH operand");
9292
9293 SDLoc DL(N);
9294 SDValue Needle = N->getOperand(1);
9295 EVT NeedleVT = Needle.getValueType();
9296 if (NeedleVT.getVectorNumElements() == 1)
9297 return TLI.expandVectorMatch(N, DAG);
9298
9299 EVT WidenNeedleVT = TLI.getTypeToTransformTo(*DAG.getContext(), NeedleVT);
9300
9301 SDValue Fill =
9302 DAG.getExtractVectorElt(DL, NeedleVT.getVectorElementType(), Needle, 0);
9303 SDValue WideNeedle = DAG.getSplatVector(WidenNeedleVT, DL, Fill);
9304 WideNeedle = DAG.getInsertSubvector(DL, WideNeedle, Needle, 0);
9305
9306 return DAG.getNode(ISD::VECTOR_MATCH, DL, N->getValueType(0),
9307 N->getOperand(0), WideNeedle, N->getOperand(2),
9308 N->getFlags());
9309}
9310
9311//===----------------------------------------------------------------------===//
9312// Vector Widening Utilities
9313//===----------------------------------------------------------------------===//
9314
9315// Utility function to find the type to chop up a widen vector for load/store
9316// TLI: Target lowering used to determine legal types.
9317// Width: Width left need to load/store.
9318// WidenVT: The widen vector type to load to/store from
9319// Align: If 0, don't allow use of a wider type
9320// WidenEx: If Align is not 0, the amount additional we can load/store from.
9321
9322static std::optional<EVT> findMemType(SelectionDAG &DAG,
9323 const TargetLowering &TLI, unsigned Width,
9324 EVT WidenVT, unsigned Align = 0,
9325 unsigned WidenEx = 0) {
9326 EVT WidenEltVT = WidenVT.getVectorElementType();
9327 const bool Scalable = WidenVT.isScalableVector();
9328 unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinValue();
9329 unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
9330 unsigned AlignInBits = Align*8;
9331
9332 EVT RetVT = WidenEltVT;
9333 // Don't bother looking for an integer type if the vector is scalable, skip
9334 // to vector types.
9335 if (!Scalable) {
9336 // If we have one element to load/store, return it.
9337 if (Width == WidenEltWidth)
9338 return RetVT;
9339
9340 // See if there is larger legal integer than the element type to load/store.
9341 for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
9342 unsigned MemVTWidth = MemVT.getSizeInBits();
9343 if (MemVT.getSizeInBits() <= WidenEltWidth)
9344 break;
9345 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
9346 if ((Action == TargetLowering::TypeLegal ||
9348 (WidenWidth % MemVTWidth) == 0 &&
9349 isPowerOf2_32(WidenWidth / MemVTWidth) &&
9350 (MemVTWidth <= Width ||
9351 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
9352 if (MemVTWidth == WidenWidth)
9353 return MemVT;
9354 RetVT = MemVT;
9355 break;
9356 }
9357 }
9358 }
9359
9360 // See if there is a larger vector type to load/store that has the same vector
9361 // element type and is evenly divisible with the WidenVT.
9362 for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
9363 // Skip vector MVTs which don't match the scalable property of WidenVT.
9364 if (Scalable != MemVT.isScalableVector())
9365 continue;
9366 unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinValue();
9367 auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
9368 if ((Action == TargetLowering::TypeLegal ||
9370 WidenEltVT == MemVT.getVectorElementType() &&
9371 (WidenWidth % MemVTWidth) == 0 &&
9372 isPowerOf2_32(WidenWidth / MemVTWidth) &&
9373 (MemVTWidth <= Width ||
9374 (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
9375 if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
9376 return MemVT;
9377 }
9378 }
9379
9380 // Using element-wise loads and stores for widening operations is not
9381 // supported for scalable vectors
9382 if (Scalable)
9383 return std::nullopt;
9384
9385 return RetVT;
9386}
9387
9388// Builds a vector type from scalar loads
9389// VecTy: Resulting Vector type
9390// LDOps: Load operators to build a vector type
9391// [Start,End) the list of loads to use.
9394 unsigned Start, unsigned End) {
9395 SDLoc dl(LdOps[Start]);
9396 EVT LdTy = LdOps[Start].getValueType();
9397 unsigned Width = VecTy.getSizeInBits();
9398 unsigned NumElts = Width / LdTy.getSizeInBits();
9399 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
9400
9401 unsigned Idx = 1;
9402 SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
9403
9404 for (unsigned i = Start + 1; i != End; ++i) {
9405 EVT NewLdTy = LdOps[i].getValueType();
9406 if (NewLdTy != LdTy) {
9407 NumElts = Width / NewLdTy.getSizeInBits();
9408 NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
9409 VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
9410 // Readjust position and vector position based on new load type.
9411 Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
9412 LdTy = NewLdTy;
9413 }
9414 VecOp = DAG.getInsertVectorElt(dl, VecOp, LdOps[i], Idx++);
9415 }
9416 return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
9417}
9418
9419SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
9420 LoadSDNode *LD) {
9421 // The strategy assumes that we can efficiently load power-of-two widths.
9422 // The routine chops the vector into the largest vector loads with the same
9423 // element type or scalar loads and then recombines it to the widen vector
9424 // type.
9425 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
9426 EVT LdVT = LD->getMemoryVT();
9427 SDLoc dl(LD);
9428 assert(LdVT.isVector() && WidenVT.isVector());
9429 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
9431
9432 // Load information
9433 SDValue Chain = LD->getChain();
9434 SDValue BasePtr = LD->getBasePtr();
9435 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
9436 MMOMetadata Metadata = LD->getMMOMetadataForSubAccess();
9437
9438 TypeSize LdWidth = LdVT.getSizeInBits();
9439 TypeSize WidenWidth = WidenVT.getSizeInBits();
9440 TypeSize WidthDiff = WidenWidth - LdWidth;
9441 // Allow wider loads if they are sufficiently aligned to avoid memory faults
9442 // and if the original load is simple.
9443 unsigned LdAlign =
9444 (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlign().value();
9445
9446 // Find the vector type that can load from.
9447 std::optional<EVT> FirstVT =
9448 findMemType(DAG, TLI, LdWidth.getKnownMinValue(), WidenVT, LdAlign,
9449 WidthDiff.getKnownMinValue());
9450
9451 if (!FirstVT)
9452 return SDValue();
9453
9454 SmallVector<EVT, 8> MemVTs;
9455 TypeSize FirstVTWidth = FirstVT->getSizeInBits();
9456
9457 // Unless we're able to load in one instruction we must work out how to load
9458 // the remainder.
9459 if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
9460 std::optional<EVT> NewVT = FirstVT;
9461 TypeSize RemainingWidth = LdWidth;
9462 TypeSize NewVTWidth = FirstVTWidth;
9463 do {
9464 RemainingWidth -= NewVTWidth;
9465 if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
9466 // The current type we are using is too large. Find a better size.
9467 NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinValue(),
9468 WidenVT, LdAlign, WidthDiff.getKnownMinValue());
9469 if (!NewVT)
9470 return SDValue();
9471 NewVTWidth = NewVT->getSizeInBits();
9472 }
9473 MemVTs.push_back(*NewVT);
9474 } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
9475 }
9476
9477 SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
9478 LD->getBaseAlign(), MMOFlags, Metadata);
9479 LdChain.push_back(LdOp.getValue(1));
9480
9481 // Check if we can load the element with one instruction.
9482 if (MemVTs.empty())
9483 return coerceLoadedValue(LdOp, *FirstVT, WidenVT, LdWidth, FirstVTWidth, dl,
9484 DAG);
9485
9486 // Load vector by using multiple loads from largest vector to scalar.
9488 LdOps.push_back(LdOp);
9489
9490 uint64_t ScaledOffset = 0;
9491 MachinePointerInfo MPI = LD->getPointerInfo();
9492
9493 // First incremement past the first load.
9494 IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
9495 &ScaledOffset);
9496
9497 for (EVT MemVT : MemVTs) {
9498 Align NewAlign = ScaledOffset == 0
9499 ? LD->getBaseAlign()
9500 : commonAlignment(LD->getAlign(), ScaledOffset);
9501 SDValue L = DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags,
9502 Metadata);
9503
9504 LdOps.push_back(L);
9505 LdChain.push_back(L.getValue(1));
9506 IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
9507 }
9508
9509 // Build the vector from the load operations.
9510 unsigned End = LdOps.size();
9511 if (!LdOps[0].getValueType().isVector())
9512 // All the loads are scalar loads.
9513 return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
9514
9515 // If the load contains vectors, build the vector using concat vector.
9516 // All of the vectors used to load are power-of-2, and the scalar loads can be
9517 // combined to make a power-of-2 vector.
9518 SmallVector<SDValue, 16> ConcatOps(End);
9519 int i = End - 1;
9520 int Idx = End;
9521 EVT LdTy = LdOps[i].getValueType();
9522 // First, combine the scalar loads to a vector.
9523 if (!LdTy.isVector()) {
9524 for (--i; i >= 0; --i) {
9525 LdTy = LdOps[i].getValueType();
9526 if (LdTy.isVector())
9527 break;
9528 }
9529 ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
9530 }
9531
9532 ConcatOps[--Idx] = LdOps[i];
9533 for (--i; i >= 0; --i) {
9534 EVT NewLdTy = LdOps[i].getValueType();
9535 if (NewLdTy != LdTy) {
9536 // Create a larger vector.
9537 TypeSize LdTySize = LdTy.getSizeInBits();
9538 TypeSize NewLdTySize = NewLdTy.getSizeInBits();
9539 assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
9540 NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinValue()));
9541 unsigned NumOps =
9542 NewLdTySize.getKnownMinValue() / LdTySize.getKnownMinValue();
9544 unsigned j = 0;
9545 for (; j != End-Idx; ++j)
9546 WidenOps[j] = ConcatOps[Idx+j];
9547 for (; j != NumOps; ++j)
9548 WidenOps[j] = DAG.getPOISON(LdTy);
9549
9550 ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
9551 WidenOps);
9552 Idx = End - 1;
9553 LdTy = NewLdTy;
9554 }
9555 ConcatOps[--Idx] = LdOps[i];
9556 }
9557
9558 if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
9559 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
9560 ArrayRef(&ConcatOps[Idx], End - Idx));
9561
9562 // We need to fill the rest with undefs to build the vector.
9563 unsigned NumOps =
9564 WidenWidth.getKnownMinValue() / LdTy.getSizeInBits().getKnownMinValue();
9566 SDValue UndefVal = DAG.getPOISON(LdTy);
9567 {
9568 unsigned i = 0;
9569 for (; i != End-Idx; ++i)
9570 WidenOps[i] = ConcatOps[Idx+i];
9571 for (; i != NumOps; ++i)
9572 WidenOps[i] = UndefVal;
9573 }
9574 return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
9575}
9576
9577SDValue
9578DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
9579 LoadSDNode *LD,
9580 ISD::LoadExtType ExtType) {
9581 // For extension loads, it may not be more efficient to chop up the vector
9582 // and then extend it. Instead, we unroll the load and build a new vector.
9583 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
9584 EVT LdVT = LD->getMemoryVT();
9585 SDLoc dl(LD);
9586 assert(LdVT.isVector() && WidenVT.isVector());
9587 assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
9588
9589 // Load information
9590 SDValue Chain = LD->getChain();
9591 SDValue BasePtr = LD->getBasePtr();
9592 MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
9593 MMOMetadata Metadata = LD->getMMOMetadataForSubAccess();
9594
9595 if (LdVT.isScalableVector())
9596 return SDValue();
9597
9598 EVT EltVT = WidenVT.getVectorElementType();
9599 EVT LdEltVT = LdVT.getVectorElementType();
9600 unsigned NumElts = LdVT.getVectorNumElements();
9601
9602 // Load each element and widen.
9603 unsigned WidenNumElts = WidenVT.getVectorNumElements();
9604 SmallVector<SDValue, 16> Ops(WidenNumElts);
9605 unsigned Increment = LdEltVT.getSizeInBits() / 8;
9606 Ops[0] =
9607 DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
9608 LdEltVT, LD->getBaseAlign(), MMOFlags, Metadata);
9609 LdChain.push_back(Ops[0].getValue(1));
9610 unsigned i = 0, Offset = Increment;
9611 for (i=1; i < NumElts; ++i, Offset += Increment) {
9612 SDValue NewBasePtr =
9613 DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::getFixed(Offset));
9614 Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
9615 LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
9616 LD->getBaseAlign(), MMOFlags, Metadata);
9617 LdChain.push_back(Ops[i].getValue(1));
9618 }
9619
9620 // Fill the rest with undefs.
9621 SDValue UndefVal = DAG.getPOISON(EltVT);
9622 for (; i != WidenNumElts; ++i)
9623 Ops[i] = UndefVal;
9624
9625 return DAG.getBuildVector(WidenVT, dl, Ops);
9626}
9627
9628bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
9629 StoreSDNode *ST) {
9630 // The strategy assumes that we can efficiently store power-of-two widths.
9631 // The routine chops the vector into the largest vector stores with the same
9632 // element type or scalar stores.
9633 SDValue Chain = ST->getChain();
9634 SDValue BasePtr = ST->getBasePtr();
9635 MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
9636 MMOMetadata Metadata = ST->getMMOMetadataForSubAccess();
9637 SDValue ValOp = GetWidenedVector(ST->getValue());
9638 SDLoc dl(ST);
9639
9640 EVT StVT = ST->getMemoryVT();
9641 TypeSize StWidth = StVT.getSizeInBits();
9642 EVT ValVT = ValOp.getValueType();
9643 TypeSize ValWidth = ValVT.getSizeInBits();
9644 EVT ValEltVT = ValVT.getVectorElementType();
9645 unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
9646 assert(StVT.getVectorElementType() == ValEltVT);
9647 assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
9648 "Mismatch between store and value types");
9649
9650 int Idx = 0; // current index to store
9651
9652 MachinePointerInfo MPI = ST->getPointerInfo();
9653 uint64_t ScaledOffset = 0;
9654
9655 // A breakdown of how to widen this vector store. Each element of the vector
9656 // is a memory VT combined with the number of times it is to be stored to,
9657 // e,g., v5i32 -> {{v2i32,2},{i32,1}}
9659
9660 while (StWidth.isNonZero()) {
9661 // Find the largest vector type we can store with.
9662 std::optional<EVT> NewVT =
9663 findMemType(DAG, TLI, StWidth.getKnownMinValue(), ValVT);
9664 if (!NewVT)
9665 return false;
9666 MemVTs.push_back({*NewVT, 0});
9667 TypeSize NewVTWidth = NewVT->getSizeInBits();
9668
9669 do {
9670 StWidth -= NewVTWidth;
9671 MemVTs.back().second++;
9672 } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
9673 }
9674
9675 for (const auto &Pair : MemVTs) {
9676 EVT NewVT = Pair.first;
9677 unsigned Count = Pair.second;
9678 TypeSize NewVTWidth = NewVT.getSizeInBits();
9679
9680 if (NewVT.isVector()) {
9681 unsigned NumVTElts = NewVT.getVectorMinNumElements();
9682 do {
9683 Align NewAlign = ScaledOffset == 0
9684 ? ST->getBaseAlign()
9685 : commonAlignment(ST->getAlign(), ScaledOffset);
9686 SDValue EOp = DAG.getExtractSubvector(dl, NewVT, ValOp, Idx);
9687 SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
9688 MMOFlags, Metadata);
9689 StChain.push_back(PartStore);
9690
9691 Idx += NumVTElts;
9692 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
9693 &ScaledOffset);
9694 } while (--Count);
9695 } else {
9696 // Cast the vector to the scalar type we can store.
9697 unsigned NumElts = ValWidth.getFixedValue() / NewVTWidth.getFixedValue();
9698 EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
9699 SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
9700 // Readjust index position based on new vector type.
9701 Idx = Idx * ValEltWidth / NewVTWidth.getFixedValue();
9702 do {
9703 SDValue EOp = DAG.getExtractVectorElt(dl, NewVT, VecOp, Idx++);
9704 SDValue PartStore =
9705 DAG.getStore(Chain, dl, EOp, BasePtr, MPI, ST->getBaseAlign(),
9706 MMOFlags, Metadata);
9707 StChain.push_back(PartStore);
9708
9709 IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
9710 } while (--Count);
9711 // Restore index back to be relative to the original widen element type.
9712 Idx = Idx * NewVTWidth.getFixedValue() / ValEltWidth;
9713 }
9714 }
9715
9716 return true;
9717}
9718
9719/// Modifies a vector input (widen or narrows) to a vector of NVT. The
9720/// input vector must have the same element type as NVT.
9721/// FillWithZeroes specifies that the vector should be widened with zeroes.
9722SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
9723 bool FillWithZeroes) {
9724 // Note that InOp might have been widened so it might already have
9725 // the right width or it might need be narrowed.
9726 EVT InVT = InOp.getValueType();
9728 "input and widen element type must match");
9729 assert(InVT.isScalableVector() == NVT.isScalableVector() &&
9730 "cannot modify scalable vectors in this way");
9731 SDLoc dl(InOp);
9732
9733 // Check if InOp already has the right width.
9734 if (InVT == NVT)
9735 return InOp;
9736
9737 ElementCount InEC = InVT.getVectorElementCount();
9738 ElementCount WidenEC = NVT.getVectorElementCount();
9739 if (WidenEC.hasKnownScalarFactor(InEC)) {
9740 unsigned NumConcat = WidenEC.getKnownScalarFactor(InEC);
9741 SmallVector<SDValue, 16> Ops(NumConcat);
9742 SDValue FillVal =
9743 FillWithZeroes ? DAG.getConstant(0, dl, InVT) : DAG.getPOISON(InVT);
9744 Ops[0] = InOp;
9745 for (unsigned i = 1; i != NumConcat; ++i)
9746 Ops[i] = FillVal;
9747
9748 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
9749 }
9750
9751 if (InEC.hasKnownScalarFactor(WidenEC))
9752 return DAG.getExtractSubvector(dl, NVT, InOp, 0);
9753
9754 if (NVT.isScalableVector() && InVT.isScalableVector()) {
9755 // Split the input into the largest equal-sized scalable subvectors.
9756 unsigned InNumElts = InVT.getVectorMinNumElements();
9757 unsigned NewNumElts = NVT.getVectorMinNumElements();
9758 unsigned CommonFactor = std::gcd(InNumElts, NewNumElts);
9759 EVT PartVT = EVT::getVectorVT(*DAG.getContext(), NVT.getVectorElementType(),
9760 ElementCount::getScalable(CommonFactor));
9761
9763 unsigned NumCopiedParts = std::min(InNumElts, NewNumElts) / CommonFactor;
9764 for (unsigned I = 0; I != NumCopiedParts; ++I)
9765 Ops.push_back(
9766 DAG.getExtractSubvector(dl, PartVT, InOp, I * CommonFactor));
9767
9768 unsigned NumResultParts = NewNumElts / CommonFactor;
9769 if (NumResultParts > NumCopiedParts) {
9770 SDValue FillVal = FillWithZeroes ? DAG.getConstant(0, dl, PartVT)
9771 : DAG.getPOISON(PartVT);
9772 Ops.append(NumResultParts - NumCopiedParts, FillVal);
9773 }
9774
9775 return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
9776 }
9777
9778 assert(!InVT.isScalableVector() && !NVT.isScalableVector() &&
9779 "Scalable vectors should have been handled already.");
9780
9781 unsigned InNumElts = InEC.getFixedValue();
9782 unsigned WidenNumElts = WidenEC.getFixedValue();
9783
9784 // Fall back to extract and build (+ mask, if padding with zeros).
9785 SmallVector<SDValue, 16> Ops(WidenNumElts);
9786 EVT EltVT = NVT.getVectorElementType();
9787 unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
9788 unsigned Idx;
9789 for (Idx = 0; Idx < MinNumElts; ++Idx)
9790 Ops[Idx] = DAG.getExtractVectorElt(dl, EltVT, InOp, Idx);
9791
9792 SDValue UndefVal = DAG.getPOISON(EltVT);
9793 for (; Idx < WidenNumElts; ++Idx)
9794 Ops[Idx] = UndefVal;
9795
9796 SDValue Widened = DAG.getBuildVector(NVT, dl, Ops);
9797 if (!FillWithZeroes)
9798 return Widened;
9799
9800 assert(NVT.isInteger() &&
9801 "We expect to never want to FillWithZeroes for non-integral types.");
9802
9804 MaskOps.append(MinNumElts, DAG.getAllOnesConstant(dl, EltVT));
9805 MaskOps.append(WidenNumElts - MinNumElts, DAG.getConstant(0, dl, EltVT));
9806
9807 return DAG.getNode(ISD::AND, dl, NVT, Widened,
9808 DAG.getBuildVector(NVT, dl, MaskOps));
9809}
return SDValue()
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
uint64_t uint64_t
uint64_t Imm
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
dxil translate DXIL Translate Metadata
#define _
static constexpr Value * getValue(Ty &ValueOrUse)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static unsigned getExtendForIntVecReduction(SDNode *N)
static SDValue BuildVectorFromScalar(SelectionDAG &DAG, EVT VecTy, SmallVectorImpl< SDValue > &LdOps, unsigned Start, unsigned End)
static std::optional< EVT > findMemType(SelectionDAG &DAG, const TargetLowering &TLI, unsigned Width, EVT WidenVT, unsigned Align, unsigned WidenEx)
static EVT getSETCCOperandType(SDValue N)
static bool isSETCCOp(unsigned Opcode)
static bool isLogicalMaskOp(unsigned Opcode)
static bool isSETCCorConvertedSETCC(SDValue N)
static SDValue coerceStoredValue(SDValue StVal, EVT FirstVT, EVT WidenVT, TypeSize FirstVTWidth, const SDLoc &dl, SelectionDAG &DAG)
Inverse of coerceLoadedValue: pull a FirstVT-sized scalar/vector out of the widened value so it can b...
static SDValue CollectOpsToWiden(SelectionDAG &DAG, const TargetLowering &TLI, SmallVectorImpl< SDValue > &ConcatOps, unsigned ConcatEnd, EVT VT, EVT MaxVT, EVT WidenVT)
static SDValue coerceLoadedValue(SDValue LdOp, EVT FirstVT, EVT WidenVT, TypeSize LdWidth, TypeSize FirstVTWidth, SDLoc dl, SelectionDAG &DAG)
Either return the same load or provide appropriate casts from the load and return that.
#define I(x, y, z)
Definition MD5.cpp:57
static bool isUndef(const MachineInstr &MI)
This file provides utility analysis objects describing memory locations.
uint64_t High
#define P(N)
SmallVector< MachineOperand, 4 > Cond
RISCVCC::CondCode CC
const MachineOperand & HiOp1
SI Fold Operands
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
This file implements the SmallBitVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
Value * RHS
Value * LHS
This is an SDNode representing atomic operations.
LLVM_ABI unsigned getVScaleRangeMin() const
Returns the minimum value for the vscale_range attribute.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:262
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:309
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
Definition TypeSize.h:312
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:317
This class is used to represent ISD::LOAD nodes.
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
static auto integer_valuetypes()
static auto vector_valuetypes()
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
Flags
Flags values. These may be or'd together.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
This class is used to represent an MGATHER node.
const SDValue & getBasePtr() const
ISD::MemIndexType getIndexType() const
How is Index applied to BasePtr when computing addresses.
const SDValue & getInc() const
const SDValue & getScale() const
const SDValue & getMask() const
const SDValue & getIntID() const
const SDValue & getIndex() const
const SDValue & getBasePtr() const
ISD::MemIndexType getIndexType() const
This class is used to represent an MLOAD node.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
const SDValue & getMask() const
const SDValue & getPassThru() const
const SDValue & getOffset() const
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
This class is used to represent an MSTORE node.
bool isCompressingStore() const
Returns true if the op does a compression to the vector before storing.
const SDValue & getOffset() const
const SDValue & getBasePtr() const
const SDValue & getMask() const
const SDValue & getValue() const
This is an abstract virtual class for memory operations.
Align getBaseAlign() const
Returns alignment and volatility of the memory access.
const MDNode * getRanges() const
Returns the Ranges that describes the dereference.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
const MDNode * getMemCacheHint() const
Returns the cache hint metadata for this memory access.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
bool isStrictFPOpcode()
Test if this node is a strict floating point pseudo-op.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
SDNodeFlags getFlags() const
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isUndef() const
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getScalarValueSizeInBits() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
SDValue getInsertVectorElt(const SDLoc &DL, SDValue Vec, SDValue Elt, unsigned Idx)
Insert Elt into Vec at offset Idx.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
LLVMContext * getContext() const
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
Vector takeVector()
Clear the SetVector and return the underlying vector.
Definition SetVector.h:94
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
BooleanContent
Enum that describes how the target represents true/false values.
static ISD::NodeType getExtendForContent(BooleanContent Content)
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:352
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
This class is used to represent an VP_GATHER node.
const SDValue & getScale() const
ISD::MemIndexType getIndexType() const
How is Index applied to BasePtr when computing addresses.
const SDValue & getVectorLength() const
const SDValue & getIndex() const
const SDValue & getBasePtr() const
const SDValue & getMask() const
This class is used to represent a VP_LOAD node.
const SDValue & getValue() const
This class is used to represent a VP_STORE node.
This class is used to represent an EXPERIMENTAL_VP_STRIDED_LOAD node.
const SDValue & getMask() const
ISD::LoadExtType getExtensionType() const
const SDValue & getStride() const
const SDValue & getOffset() const
const SDValue & getVectorLength() const
const SDValue & getBasePtr() const
This class is used to represent an EXPERIMENTAL_VP_STRIDED_STORE node.
const SDValue & getBasePtr() const
const SDValue & getMask() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if this is a truncating store.
const SDValue & getOffset() const
const SDValue & getVectorLength() const
const SDValue & getStride() const
bool isCompressingStore() const
Returns true if the op does a compression to the vector before storing.
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
Definition TypeSize.h:181
constexpr bool hasKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns true if there exists a value X where RHS*X will result in a value whose quantity matches our ...
Definition TypeSize.h:266
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:201
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:231
constexpr bool isNonZero() const
Definition TypeSize.h:156
constexpr ScalarTy getKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns a value X where RHS*X will result in a value whose quantity matches our own.
Definition TypeSize.h:274
static constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:217
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:169
constexpr bool isKnownEven() const
A return value of true indicates we know at compile time that the number of elements (vscale * Min) i...
Definition TypeSize.h:177
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
constexpr bool isZero() const
Definition TypeSize.h:154
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:224
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
Definition TypeSize.h:253
static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:238
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
Definition ISDOpcodes.h:43
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:851
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:263
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
Definition ISDOpcodes.h:516
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:238
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ ATOMIC_LOAD_FMINIMUMNUM
@ LOOP_DEPENDENCE_RAW_MASK
@ MASK_BEFOREFIRST
Has one mask vector operand.
@ VECREDUCE_SEQ_FADD
Generic reduction nodes.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ VECREDUCE_FMINIMUMNUM
@ AVGSUBFLOORS
AVGSUBFLOORS/AVGSUBFLOORU - Averaging subtract - Subtract two integers using an integer of type i[N+1...
Definition ISDOpcodes.h:739
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:605
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:811
@ SMULFIX
RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same...
Definition ISDOpcodes.h:397
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SMULFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:403
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:885
@ CTTZ_ELTS
Returns the number of number of trailing (least significant) zero elements in a vector.
@ ATOMIC_LOAD_USUB_COND
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:523
@ VECTOR_FIND_LAST_ACTIVE
Finds the index of the last active mask element Operands: Mask.
@ FMODF
FMODF - Decomposes the operand into integral and fractional parts, each having the same type and sign...
@ FATAN2
FATAN2 - atan2, inspired by libm.
@ FSINCOSPI
FSINCOSPI - Compute both the sine and cosine times pi more accurately than FSINCOS(pi*x),...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:912
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:589
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:420
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ VECTOR_SHUFFLE_VAR
VECTOR_SHUFFLE_VAR(VEC, MASK) - Returns VEC permuted by MASK, an integer vector with the same number ...
Definition ISDOpcodes.h:665
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:771
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
Definition ISDOpcodes.h:942
@ FPTRUNC_ROUND
FPTRUNC_ROUND - This corresponds to the fptrunc_round intrinsic.
Definition ISDOpcodes.h:520
@ FAKE_USE
FAKE_USE represents a use of the operand but does not do anything.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ CLMUL
Carry-less multiplication operations.
Definition ISDOpcodes.h:802
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ SDIVFIX
RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on 2 integers with the same width...
Definition ISDOpcodes.h:410
@ CONVERT_FROM_ARBITRARY_FP
CONVERT_FROM_ARBITRARY_FP - This operator converts from an arbitrary floating-point represented as an...
@ ATOMIC_LOAD_USUB_SAT
@ CTLZ_ZERO_POISON
Definition ISDOpcodes.h:820
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:876
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
Definition ISDOpcodes.h:731
@ STRICT_UINT_TO_FP
Definition ISDOpcodes.h:490
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:681
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ PARTIAL_REDUCE_FMLA
@ VECREDUCE_FMAXIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM nodes do not propagate NaNs and order signed zeroes using the llvm....
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SSUBO
Same for subtraction.
Definition ISDOpcodes.h:355
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor to...
Definition ISDOpcodes.h:640
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
Definition ISDOpcodes.h:707
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
Definition ISDOpcodes.h:546
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
Definition ISDOpcodes.h:553
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:377
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:828
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:235
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:688
@ GET_ACTIVE_LANE_MASK
GET_ACTIVE_LANE_MASK - this corrosponds to the llvm.get.active.lane.mask intrinsic.
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition ISDOpcodes.h:351
@ ARITH_FENCE
ARITH_FENCE - This corresponds to a arithmetic fence intrinsic.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:720
@ ATOMIC_LOAD_FMAXIMUM
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:793
@ AssertNoFPClass
AssertNoFPClass - These nodes record if a register contains a float value that is known to be not som...
Definition ISDOpcodes.h:80
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:659
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:619
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Same as FMINNUM/FMAXNUM, except that a signaling NaN operand deterministi...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:581
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:882
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:843
@ FMINNUM
FMINNUM/FMAXNUM - Same semantics as the llvm.minnum/maxnum intrinsics.
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
Definition ISDOpcodes.h:389
@ SMULO
Same for multiplication.
Definition ISDOpcodes.h:359
@ ATOMIC_LOAD_FMINIMUM
@ VECTOR_SPLICE_LEFT
VECTOR_SPLICE_LEFT(VEC1, VEC2, OFFSET) - Shifts CONCAT_VECTORS(VEC1, VEC2) left by OFFSET elements an...
Definition ISDOpcodes.h:669
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
Definition ISDOpcodes.h:931
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:920
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:751
@ MASKED_UDIV
Masked vector arithmetic that returns poison on disabled lanes.
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
Definition ISDOpcodes.h:650
@ SDIVFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
Definition ISDOpcodes.h:416
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:837
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
Definition ISDOpcodes.h:489
@ MGATHER
Masked gather and scatter - load and store operations for a vector of random addresses with additiona...
@ ATOMIC_LOAD_FMAXIMUMNUM
@ ATOMIC_LOAD_UDEC_WRAP
@ STRICT_FP_TO_UINT
Definition ISDOpcodes.h:483
@ PEXT
Parallel bit extract (compress) and parallel bit deposit (expand).
Definition ISDOpcodes.h:807
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
Definition ISDOpcodes.h:505
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:482
@ FMINIMUM
FMINIMUM/FMAXIMUM - Same semantics as the llvm.minimum/maximum intrinsics.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:958
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:510
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:763
@ SCMP
[US]CMP - 3-way comparison of signed or unsigned integers.
Definition ISDOpcodes.h:759
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
Definition ISDOpcodes.h:726
@ VECTOR_MATCH
VECTOR_MATCH - this corresponds to the llvm.experimental.vector.match intrinsic.
@ VECTOR_SPLICE_RIGHT
VECTOR_SPLICE_RIGHT(VEC1, VEC2, OFFSET) - Shifts CONCAT_VECTORS(VEC1,VEC2) right by OFFSET elements a...
Definition ISDOpcodes.h:673
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
Definition ISDOpcodes.h:243
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:570
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:55
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
Definition ISDOpcodes.h:819
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:991
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
Definition ISDOpcodes.h:715
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
Definition ISDOpcodes.h:953
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ EXPERIMENTAL_VECTOR_HISTOGRAM
Experimental vector histogram intrinsic Operands: Input Chain, Inc, Mask, Base, Index,...
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
Definition ISDOpcodes.h:977
@ VECREDUCE_FMINIMUM
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:888
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ VECREDUCE_SEQ_FMUL
@ CONVERT_TO_ARBITRARY_FP
CONVERT_TO_ARBITRARY_FP - Converts a native FP value to an arbitrary floating-point format,...
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:64
@ ATOMIC_LOAD_UINC_WRAP
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:539
@ PARTIAL_REDUCE_SUMLA
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:368
@ VECTOR_REPEAT
VECTOR_REPEAT(FIXED_LENGTH_VECTOR) Repeatedly copies the elements of the source fixed-length vector t...
Definition ISDOpcodes.h:645
@ VECTOR_DEINTERLEAVE
VECTOR_DEINTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor ...
Definition ISDOpcodes.h:629
@ CTTZ_ELTS_ZERO_POISON
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - Same semantics as the llvm.minimumnum/maximumnum intrinsics.
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
Definition ISDOpcodes.h:746
@ ABS_MIN_POISON
ABS with a poison result for INT_MIN.
Definition ISDOpcodes.h:775
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:561
@ LOOP_DEPENDENCE_WAR_MASK
The llvm.loop.dependence.
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
LLVM_ABI NodeType getUnmaskedBinOpOpcode(unsigned MaskedOpc)
Given a MaskedOpc of ISD::MASKED_(U|S)(DIV|REM), returns the unmasked ISD::(U|S)(DIV|REM).
bool isUNINDEXEDLoad(const SDNode *N)
Returns true if the specified node is an unindexed load.
LLVM_ABI std::optional< unsigned > getVPForBaseOpcode(unsigned Opcode)
Translate this non-VP Opcode to its corresponding VP Opcode.
MemIndexType
MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's index parameter when calcula...
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
LLVM_ABI LegalityPredicate isVector(unsigned TypeIdx)
True iff the specified type index is a vector.
constexpr double e
Type * getValueType(Value *V, bool ReVec, bool LookThroughCmp)
Returns the "element type" of the given value/instruction V.
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1781
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:173
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr int PoisonMaskElem
@ Mul
Product of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1901
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:206
LLVM_ABI void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
@ Increment
Incrementally increasing token ID.
Definition AllocToken.h:26
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:881
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Extended Value Type.
Definition ValueTypes.h:35
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Definition ValueTypes.h:90
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
Definition ValueTypes.h:433
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
Definition ValueTypes.h:70
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
Definition ValueTypes.h:144
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
Definition ValueTypes.h:322
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:170
ElementCount getVectorElementCount() const
Definition ValueTypes.h:388
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:509
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:411
bool isByteSized() const
Return true if the bit size is a multiple of 8.
Definition ValueTypes.h:281
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition ValueTypes.h:397
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:423
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition ValueTypes.h:516
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
Definition ValueTypes.h:98
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition ValueTypes.h:61
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
Definition ValueTypes.h:419
EVT widenIntegerVectorElementType(LLVMContext &Context) const
Return a VT for an integer vector type with the size of the elements doubled.
Definition ValueTypes.h:490
EVT changeVectorElementCount(LLVMContext &Context, ElementCount EC) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element coun...
Definition ValueTypes.h:109
bool isFixedLengthVector() const
Definition ValueTypes.h:214
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
Definition ValueTypes.h:55
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
Definition ValueTypes.h:457
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:191
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:361
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
Definition ValueTypes.h:294
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition ValueTypes.h:202
bool knownBitsGE(EVT VT) const
Return true if we know at compile time this has more than or the same bits as VT.
Definition ValueTypes.h:306
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:366
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
Definition ValueTypes.h:136
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:374
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:499
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition ValueTypes.h:175
This class contains a discriminated union of information about pointers in memory operands,...
LLVM_ABI unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.